Last active
January 25, 2017 08:59
-
-
Save subhashdasyam/4c3f95de476072573d373e7471c7eb75 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class LittleUtils{ | |
private static $systemRequirementsJsonFilePath; | |
/** | |
* Checks if system meets requirements | |
* @return string If all the requirements are satisfied then it return "Success" else "Error message" | |
*/ | |
private function __checkSystemRequirements(){ | |
$result = array(); | |
//Get disabled php functions and check if "exec" command is disabled or not. | |
$disabled = array_map('trim', explode(',', ini_get('disable_functions'))); | |
if(in_array('exec', $disabled)){ | |
$result['exec'] = array("success"=>false,"msg"=>"CW Image Optimizer requires exec(). Your system administrator has disabled this function."); | |
} | |
else{ | |
$result['exec'] = array("success"=>true,"msg"=>""); | |
} | |
//Check if required executable libraries are installed | |
$missingLibraries = array(); | |
$requiredLibraries = array( | |
'PNG' => 'opt-png', | |
'JPG' => 'opt-jpg', | |
'GIF' => 'opt-gif', | |
); | |
foreach($requiredLibraries as $imageType => $requiredLibrary){ | |
$res = trim(exec('which ' . $requiredLibrary)); | |
if(empty($res)){ | |
$missingLibraries[] = $requiredLibrary; | |
} | |
} | |
$missingLibrariesString = implode(', ', $missingLibraries); | |
if(!empty($missingLibrariesString)){ | |
$result['missing'] = array("success"=>false, "msg"=>"CW Image Optimizer requires http://sourceforge.net/projects/littleutils. You are missing: $missingLibrariesString."); | |
} | |
else{ | |
$result['missing'] = array("success"=>true,"msg"=>"All required libraries found"); | |
} | |
if ( FALSE === is_writable(dirname(self::$systemRequirementsJsonFilePath)) ) { | |
$result['file_write_perm'] = array("success"=> false, msg="Unable to write the requirements file ".self::$systemRequirementsJsonFilePath.". Please make sure the path is writable"); | |
//Utils::ErrorReportAndQuit(__LINE__, __FILE__, "Unable to write the requirements file ".self::$systemRequirementsJsonFilePath.". Please make sure the path is writable"); | |
} | |
else{ | |
$result['file_write_perm'] = array("success"=> true, msg=""); | |
} | |
$fHandle = file_put_contents(self::$systemRequirementsJsonFilePath,json_encode($result)); | |
if($fHandle) | |
$result['file_write'] = array("success"=> true, msg=""); | |
else | |
$result['file_write'] = array("success"=> false, msg="Unable to Write contents to ".self::$systemRequirementsJsonFilePath.". Please make sure the path is writable"); | |
foreach($result as $key=>$value){ | |
if(!$value['success']){ | |
return $value['msg']; | |
} | |
} | |
return "Success"; | |
} | |
/** | |
* Checks if file already exists and if system requirements were already met or we should do a check | |
*/ | |
private function checkSystemRequirements(){ | |
// If requirements file doesn't exists check the requirements and write to file | |
if ( FALSE === file_exists(self::$systemRequirementsJsonFilePath) || FALSE === is_file(self::$systemRequirementsJsonFilePath)) { | |
return $this->__checkSystemRequirements() === "Success"?true:false; // Check the System Requirements and | |
} | |
// File Exists | |
//Read the file | |
$content = json_decode(file_get_contents(self::$systemRequirementsJsonFilePath),true); | |
// if the requirement file exists but if doesn't have required info check requirements again and rewrite the fresh file | |
if(!isset($content['exec']) || !isset($content['missing'])){ | |
return $this->__checkSystemRequirements() === "Success"?true:false; | |
} | |
// if the requirements file exists and if the requirements are false check again. | |
if($content['exec']['success'] === false || $content['missing']['success'] === false){ | |
//echo $content['exec']['msg']."<br/>".$content['missing']['msg']; | |
//***********TODO: this function is not well coded. What happens if the code reaches this point? ******** | |
// There is no additional check done. If the check fails again, the code will continue running. | |
// here is the content is false that means the Little utils or php doesn't have required functions to continue, | |
// so recursive checks are not needed, install the functions and packages then run the code again that should fix this | |
return $this->__checkSystemRequirements() === "Success"?true:false; | |
} | |
// Passed all hurdles then it seems everything is passed, continue. | |
return true; | |
} | |
public static function verifyFileNameElseQuit($fileName){ | |
// Changed to if not << if file name has a-z and 1-2 it matches so this function always throws error for valid | |
// file names, so changed to if not | |
if(!preg_match('/[^a-zA-Z0-9\-]+/',$fileName,$matches)){ | |
Utils::ErrorReportAndQuit(__LINE__, __FILE__, "Filename to save images contains invalid characters. Only alpha-numeric and dash are allowed: ". $fileName); | |
} | |
} | |
/** | |
* Optimizes an image given filepath. Works for gif, jpeg, and png | |
* @param string $fileName | |
* @return array | |
*/ | |
public function optimize($fileName){ | |
//Verify if filename doesn't have invalid characters, else quit | |
$this->verifyFileNameElseQuit($fileName); | |
$thisFolder = dirname(__FILE__).DIRECTORY_SEPARATOR; | |
self::$systemRequirementsJsonFilePath = $thisFolder.'check.json'; | |
if(!self::checkSystemRequirements()) | |
return false; | |
//Force file path to be inside the cache folder | |
$filePath = $thisFolder. "cache". DIRECTORY_SEPARATOR. $fileName; | |
//Check if File Exists | |
if ( FALSE === file_exists($filePath) || FALSE === is_file($filePath) ) { | |
$msg = sprintf("Could not find %s", $filePath); | |
return array("success"=>false, "message"=> $msg, "savings"=> NULL); | |
} | |
//Check that the file is writable | |
if ( FALSE === is_writable($filePath) ) { | |
$msg = sprintf("%s is not writable", $filePath); | |
return array("success"=>false, "message"=> $msg, "savings"=> NULL); | |
} | |
if(function_exists('getimagesize')){ | |
$type = getimagesize($filePath); | |
if(false !== $type){ | |
$type = $type['mime']; | |
} | |
}elseif(function_exists('mime_content_type')){ | |
$type = mime_content_type($filePath); | |
}else{ | |
return array("success"=>false, "message"=> 'Missing getimagesize() and mime_content_type() PHP functions', "savings"=> NULL); | |
} | |
switch($type){ | |
case 'image/jpeg': | |
$command = 'opt-jpg'; | |
break; | |
case 'image/png': | |
$command = 'opt-png'; | |
break; | |
case 'image/gif': | |
$command = 'opt-gif'; | |
break; | |
default: | |
return array("success"=>false, "message"=> 'Unknown type: ' . $type, "savings"=> NULL); | |
} | |
$result = exec($command . ' ' . escapeshellarg($filePath)); | |
$result = str_replace($filePath . ': ', '', $result); | |
if($result == 'unchanged') { | |
return array("success"=>true, "message"=> 'No savings', "savings"=>0); | |
} | |
if(strpos($result, ' vs. ') !== false) { | |
$s = explode(' vs. ', $result); | |
$savings = intval($s[0]) - intval($s[1]); | |
$savingsString = $this->getBytesInHumanFriendlyFormat($savings, 1); | |
$savingsString = str_replace(' ', ' ', $savingsString); | |
$percent = 100 - (100 * ($s[1] / $s[0])); | |
$resultMessage = sprintf("Reduced by %01.1f%% (%s)",$percent,$savingsString); | |
return array("success"=>true, "message"=> $resultMessage, "savings"=>$percent); | |
} | |
return array("success"=>false, "message"=> 'Bad response from optimizer', "savings"=> NULL); | |
} | |
/** | |
* Returns a string with a human friendly reading of bytes | |
* @param int $bytes | |
* @param int $precision | |
* @return string | |
*/ | |
private function getBytesInHumanFriendlyFormat($bytes, $precision = 2) { | |
$units = array('B', 'KB', 'MB', 'GB', 'TB'); | |
$bytes = max($bytes, 0); | |
$pow = floor(($bytes ? log($bytes) : 0) / log(1024)); | |
$pow = min($pow, count($units) - 1); | |
$bytes /= pow(1024, $pow); | |
return round($bytes, $precision) . ' ' . $units[$pow]; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
#Copy the above file
usage
$lu = new LittleUtils();
print_r($lu->optimize('a.gif'));
a.gif will be image path