Open-Source PHP Framework - Designed for rapid development of performance-oriented scalable applications

/mvc/components/file

[return to app]
1
<?php
/**
 * Tools for file management and image modification
 */
class fileComponent {
    /**
     * Cache of files as they are processed
     * @var array
     */
    public $files = array(), $resizedFiles = array();

    /**
     * Get the dimensions of an image file, results are cached in the $this->files array and are indexed by $src
     *
     * @param string $src Location of the image file
     * @return mixed Array on success, boolean false on failure
     */
    public function getImageSize($src) {
        //error-suppression is needed to avoid error warnings from invalid images
        $imageSize = @getimagesize($src);
        if ($imageSize) {
            list($this->files[$src]['width'], $this->files[$src]['height'], $this->files[$src]['type']) =
 
$imageSize; } return $imageSize; } /** * Get the format (gif, jpeg, etc.) of an image file * * @param string $src * @return mixed String for standard image types, int for non-standard, boolean false on failure */ public function getImageFormat($src) { if (!isset($this->files[$src])) { if (function_exists('exif_imagetype')) { return exif_imagetype($src); } else if (!$this->getImageSize($src)) { return false; } } //matches the PHP IMAGETYPE constants relevant to standard images (the two TIFF types are 7 & 8) $formats = array(1 => 'gif', 'jpg', 'png', 'swf', 'psd', 'bmp', 'tif', 'tif', 15 => 'bmp'); return (isset($formats[$this->files[$src]['type']]) ? $formats[$this->files[$src]['type']] : $this->files[$src]['type']); } /** * Validates a file uploaded from a form * * @param string $id * @param boolean or int $imagesOnly, a value of -1 will populate $this->files via getImageSize() but won't
 
throw an * error for non-images * @return boolean */ public function validateUploadedFile($id, $imagesOnly = false) { if (substr($_FILES[$id]['name'], 0, 1) == '.') { $error = 'File names must not begin with a dot'; } else if (!isset($_FILES[$id]['error'])) { $error = 'File upload failed, please try again'; } else { switch ($_FILES[$id]['error']) { case '0': if ($imagesOnly) { $imageSpecs = $this->getImageSize($_FILES[$id]['tmp_name']); if (isset($this->files[$_FILES[$id]['tmp_name']])) { $this->files[$_FILES[$id]['tmp_name']]['name'] = $_FILES[$id]['name']; } if ($imagesOnly > 0) { if (!$imageSpecs) { $error = 'Upload failed or file is not an image'; } else if (!in_array($this->files[$_FILES[$id]['tmp_name']]['type'], range(1, 3))) { $error = 'Image type is not supported. Please upload a jpg, gif or png file.'; } } } break; case '1': case '2': $error = 'The file exceeds the maximum permitted filesize'; break; case '3': $error = 'The file was only partially uploaded, please try again'; break; case '4': $error = 'Please select a file before pressing the upload button'; break; default: $error = 'There was a system error and your file could not be saved, please try again'; break; } } if (isset($error)) { $_POST['errors'][$id] = $error; return false; } return true; } /** * Validates and moves a file uploaded from a form * * @param string $id * @param string $destination * @param boolean $imagesOnly * @return boolean */ public function moveUploadFile($id, $destination, $imagesOnly = false) { $return = false; if ($this->validateUploadedFile($id, $imagesOnly)) { if (is_dir($destination)) { $destinationLast = substr($destination, -1); if ($destinationLast != '/' && $destinationLast != '\\') { $destination .= '/'; } $destination .= $_FILES[$id]['name']; } if (move_uploaded_file($_FILES[$id]['tmp_name'], $destination)) { chmod($destination, 0777); $return = true; } else { $_POST['errors'][$id] = 'Could not move the uploaded file'; } } return $return; } /** * Resizes an image or generates a set of resized images, optionally adding a watermark to any of them. * * To resize/watermark/process a file immediately after being uploaded: * * $id = 'example'; //name of form's upload field * $args = array('outputFolder' => 'exampleDestination'); //add args as desired * $fileComponent = get::component('fileComponent'); * $fileComponent->validateUploadedFile($id); * $fileComponent->resizeImage($args); * * Requires the PHP GD extension to be enabled. * * $specs array keys: * width - default is original width, if constrain is true then this becomes the maximum width * height - default is original height, if constrain is true then this becomes the maximum height * constrain - Boolean, default is true - resize the image proportionally, if false the end image may be
 
stretched * onlyReduce - Boolean, default is true - if true the end image can only be reduced, never be enlarged
 
(which * usually degrades quality) * outputFolder - folder where to output the file, if omitted the system default will be used * outputFile - filename, if omitted the source filename will be used * stdout - return the image bitstream to stdout (echo the image out), overrides outputFolder & outputFile
 
options * watermark - string containing src or an array with keys: * src - required, the path to the watermark image file * opacity - Optional, default if omitted is 14 * * You can specify generation of multiple output files by setting specs to an array of $specs, eg.: * $specs[] = array('width' => 200, 'height' => 100, 'outputFile' => 'thumbnail.jpg'); * $specs[] = array('width' => 500, 'height' => 300, 'outputFile' => 'bigfile.jpg'); * * @param array $specs * @param string $src Optional, if omitted the last file $this->files will be used which is populated
 
automatically * with the uploaded-file when you call validateUploadedFile() or uploadFile(). * The array is also populated manually from $src when you call getImageSize($src) * if $this->files is empty then the method will exit * @return boolean */ public function resizeImage(array $specs, $src = null) { if (!$src && $this->files) { end($this->files); $src = key($this->files); } if (!isset($this->files[$src]) && !$this->getImageSize($src)){ return false; } $types = array(1 => 'gif', 'jpeg', 'png'); $createImageFunction = 'imagecreatefrom' . $types[$this->files[$src]['type']]; $sourceImage = $createImageFunction($src); if (!is_array(current($specs))) { $specs = array($specs); } foreach ($specs as $image) { $width = $image['width']; $height = $image['height']; if (!isset($image['constrain']) || $image['constrain']) { $proportion = ($width / $this->files[$src]['width']); $proposedHeight = round($this->files[$src]['height'] * $proportion); if ($proposedHeight <= $height) { $height = $proposedHeight; } else { $proportion = ($height / $this->files[$src]['height']); $width = round($this->files[$src]['width'] * $proportion); } //need to check both height && width as due to rounding it is possible for //one dimension to be equal and the other to be 1px larger than original if ((!isset($image['onlyReduce']) || $image['onlyReduce']) && ($width > $this->files[$src]['width'] || $height > $this->files[$src]['height'])) { $width = $this->files[$src]['width']; $height = $this->files[$src]['height']; } } if ($this->files[$src]['type']== 2) { $finalImage = imagecreatetruecolor($width, $height); } else { $finalImage = imagecreate($width, $height); imagecolortransparent($finalImage, imagecolorallocate($finalImage, 0, 0, 0)); } imagecopyresampled($finalImage, $sourceImage, 0, 0, 0, 0, $width, $height, $this->files[$src]['width'], $this->files[$src]['height']); if (isset($image['watermark']) && !is_array($image['watermark'])) { $image['watermark'] = array('src' => $image['watermark']); } if (isset($image['watermark']) && isset($image['watermark']['src'])) { $watermarkSrc = $image['watermark']['src']; if (!isset($this->files[$watermarkSrc]) && !$this->getImageSize($watermarkSrc)) { if (DEBUG_MODE) { trigger_error('Watermark file' . $watermarkSrc . ' is invalid', E_USER_NOTICE); } } if (isset($this->files[$watermarkSrc])) { $watermark = $this->files[$watermarkSrc]; $watermarkOffsetX = max(round(($width - $watermark['width']) / 2), 0); $watermarkOffsetY = max(round(($height - $watermark['height']) / 2), 0); if ($width > $watermark['width'] && $height > $watermark['height']) { if (!isset($this->files[$watermarkSrc]['image'])) { $this->files[$watermarkSrc]['image'] = imagecreatefrompng($watermarkSrc); if ($this->files[$src]['type'] != 2) { $endOfWatermarkX = ($watermarkOffsetX + $watermark['width']); $endOfWatermarkY = ($watermarkOffsetY + $watermark['height']); $transparency = imagecolorat($this->files[$watermarkSrc]['image'], 1, 1); for ($x = $watermarkOffsetX; $x <= $endOfWatermarkX; $x++) { for ($y = $endOfWatermarkY; $y <= $endOfWatermarkY; $y++) { $rbg = imagecolorsforindex($finalImage, imagecolorat($finalImage, $x,
 
$y)); if ($rbg['alpha'] == 127) { imagesetpixel($this->files[$watermarkSrc]['image'], ($x - $watermarkOffsetX), ($y - $watermarkOffsetY), $transparency); } } } } } $opacity = (isset($image['watermark']['opacity']) ? $image['watermark']['opacity'] : 14); imagecopymerge($finalImage, $this->files[$watermarkSrc]['image'], $watermarkOffsetX, $watermarkOffsetY, 0, 0, $watermark['width'], $watermark['height'],
 
$opacity); } } } if (isset($image['stdout']) && $image['stdout']) { $outputPath = null; //send to stdout } else if (!isset($image['outputFolder']) && !isset($image['outputFile'])) { $outputPath = $src; //overwrite original upload } else { $outputPath = (isset($image['outputFolder']) ? $image['outputFolder'] : ''); $outputPathLast = substr($outputPath, -1); if ($outputPath && $outputPathLast != '/' && $outputPathLast != '\\') { $outputPath .= '/'; } if (!isset($image['outputFile'])) { if (isset($this->files[$src]['name'])) { $image['outputFile'] = $this->files[$src]['name']; } else { $srcParts = explode('/', str_replace('\\', '/', $src)); $image['outputFile'] = end($srcParts); } } $outputPath .= $image['outputFile']; } $this->resizedFiles[$outputPath]['width'] = $width; $this->resizedFiles[$outputPath]['height'] = $height; $quality = ($this->files[$src]['type'] == 2 ? 75 : null); $generateImageFunction = 'image' . $types[$this->files[$src]['type']]; $generateImageFunction($finalImage, $outputPath, $quality); imagedestroy($finalImage); } imagedestroy($sourceImage); return true; } }