Source for file ImageManager.php

Documentation is available at ImageManager.php

  1. <?php
  2. /**
  3.  * ImageManager, list images, directories, and thumbnails.
  4.  * @author $Author$
  5.  * @version $Id$
  6.  * @package ImageManager
  7.  */
  8.  
  9. require_once('Files.php');
  10.  
  11. /**
  12.  * ImageManager Class.
  13.  * @author $Author$
  14.  * @version $Id$
  15.  */
  16. class ImageManager 
  17. {
  18.     /**
  19.      * Configuration array.
  20.      */
  21.     var $config;
  22.  
  23.     /**
  24.      * Array of directory information.
  25.      */
  26.     var $dirs;
  27.  
  28.     /**
  29.      * Constructor. Create a new Image Manager instance.
  30.      * @param array $config configuration array, see config.inc.php
  31.      */
  32.     function ImageManager($config
  33.     {
  34.         $this->config = $config;
  35.     }
  36.  
  37.     /**
  38.      * Get the base directory.
  39.      * @return string base dir, see config.inc.php
  40.      */
  41.     function getBaseDir(
  42.     {
  43.         Return $this->config['base_dir'];
  44.     }
  45.  
  46.     /**
  47.      * Get the base URL.
  48.      * @return string base url, see config.inc.php
  49.      */
  50.     function getBaseURL(
  51.     {
  52.         Return $this->config['base_url'];
  53.     }
  54.  
  55.     function isValidBase()
  56.     {
  57.         return is_dir($this->getBaseDir());
  58.     }
  59.  
  60.     /**
  61.      * Get the tmp file prefix.
  62.      * @return string tmp file prefix.
  63.      */
  64.     function getTmpPrefix(
  65.     {
  66.         Return $this->config['tmp_prefix'];
  67.     }
  68.  
  69.     /**
  70.      * Get the sub directories in the base dir.
  71.      * Each array element contain
  72.      * the relative path (relative to the base dir) as key and the
  73.      * full path as value.
  74.      * @return array of sub directries
  75.      *  <code>array('path name' => 'full directory path', ...)</code>
  76.      */
  77.     function getDirs(
  78.     {
  79.         if(is_null($this->dirs))
  80.         {
  81.             $dirs $this->_dirs($this->getBaseDir(),'/');
  82.             ksort($dirs);
  83.             $this->dirs = $dirs;
  84.         }
  85.         return $this->dirs;
  86.     }
  87.  
  88.     /**
  89.      * Recursively travese the directories to get a list
  90.      * of accessable directories.
  91.      * @param string $base the full path to the current directory
  92.      * @param string $path the relative path name
  93.      * @return array of accessiable sub-directories
  94.      *  <code>array('path name' => 'full directory path', ...)</code>
  95.      */
  96.     function _dirs($base$path
  97.     {
  98.         $base Files::fixPath($base);
  99.         $dirs array();
  100.  
  101.         if($this->isValidBase(== false)
  102.             return $dirs;
  103.  
  104.         $d @dir($base);
  105.         
  106.         while (false !== ($entry $d->read())) 
  107.         {
  108.             //If it is a directory, and it doesn't start with
  109.             // a dot, and if is it not the thumbnail directory
  110.             if(is_dir($base.$entry
  111.                 && substr($entry,0,1!= '.'
  112.                 && $this->isThumbDir($entry== false
  113.             {
  114.                 $relative Files::fixPath($path.$entry);
  115.                 $fullpath Files::fixPath($base.$entry);
  116.                 $dirs[$relative$fullpath;
  117.                 $dirs array_merge($dirs$this->_dirs($fullpath$relative));
  118.             }
  119.         }
  120.         $d->close();
  121.  
  122.         Return $dirs;
  123.     }
  124.  
  125.     /**
  126.      * Get all the files and directories of a relative path.
  127.      * @param string $path relative path to be base path.
  128.      * @return array of file and path information.
  129.      *  <code>array(0=>array('relative'=>'fullpath',...), 1=>array('filename'=>fileinfo array(),...)</code>
  130.      *  fileinfo array: <code>array('url'=>'full url',
  131.      *                        'relative'=>'relative to base',
  132.      *                         'fullpath'=>'full file path',
  133.      *                         'image'=>imageInfo array() false if not image,
  134.      *                         'stat' => filestat)</code>
  135.      */
  136.     function getFiles($path
  137.     {
  138.         $files array();
  139.         $dirs array();
  140.  
  141.         if($this->isValidBase(== false)
  142.             return array($files,$dirs);
  143.  
  144.         $path Files::fixPath($path);
  145.         $base Files::fixPath($this->getBaseDir());
  146.         $fullpath Files::makePath($base,$path);
  147.  
  148.  
  149.         $d @dir($fullpath);
  150.         
  151.         while (false !== ($entry $d->read())) 
  152.         {
  153.             //not a dot file or directory
  154.             if(substr($entry,0,1!= '.')
  155.             {
  156.                 if(is_dir($fullpath.$entry)
  157.                     && $this->isThumbDir($entry== false)
  158.                 {
  159.                     $relative Files::fixPath($path.$entry);
  160.                     $full Files::fixPath($fullpath.$entry);
  161.                     $count $this->countFiles($full);
  162.                     $dirs[$relativearray('fullpath'=>$full,'entry'=>$entry,'count'=>$count);
  163.                 }
  164.                 else if(is_file($fullpath.$entry&& $this->isThumb($entry)==false && $this->isTmpFile($entry== false
  165.                 {
  166.                     $img $this->getImageInfo($fullpath.$entry);
  167.  
  168.                     if(!(!is_array($img)&&$this->config['validate_images']))
  169.                     {
  170.                         $file['url'Files::makePath($this->config['base_url'],$path).$entry;
  171.                         $file['relative'$path.$entry;
  172.                         $file['fullpath'$fullpath.$entry;
  173.                         $file['image'$img;
  174.                         $file['stat'stat($fullpath.$entry);
  175.                         $files[$entry$file;
  176.                     }
  177.                 }
  178.             }
  179.         }
  180.         $d->close();
  181.         ksort($dirs);
  182.         ksort($files);
  183.         
  184.         Return array($dirs$files);
  185.     }    
  186.  
  187.     /**
  188.      * Count the number of files and directories in a given folder
  189.      * minus the thumbnail folders and thumbnails.
  190.      */
  191.     function countFiles($path
  192.     {
  193.         $total 0;
  194.  
  195.         if(is_dir($path)) 
  196.         {
  197.             $d @dir($path);
  198.  
  199.             while (false !== ($entry $d->read())) 
  200.             {
  201.                 //echo $entry."<br>";
  202.                 if(substr($entry,0,1!= '.'
  203.                     && $this->isThumbDir($entry== false
  204.                     && $this->isTmpFile($entry== false
  205.                     && $this->isThumb($entry== false
  206.                 {
  207.                     $total++;
  208.                 }
  209.             }
  210.             $d->close();
  211.         }
  212.         return $total;
  213.     }
  214.  
  215.     /**
  216.      * Get image size information.
  217.      * @param string $file the image file
  218.      * @return array of getImageSize information,
  219.      *   false if the file is not an image.
  220.      */
  221.     function getImageInfo($file
  222.     {
  223.         Return @getImageSize($file);
  224.     }
  225.  
  226.     /**
  227.      * Check if the file contains the thumbnail prefix.
  228.      * @param string $file filename to be checked
  229.      * @return true if the file contains the thumbnail prefix, false otherwise.
  230.      */
  231.     function isThumb($file
  232.     {
  233.         $len strlen($this->config['thumbnail_prefix']);
  234.         if(substr($file,0,$len)==$this->config['thumbnail_prefix'])
  235.             Return true;
  236.         else
  237.             Return false;
  238.     }
  239.  
  240.     /**
  241.      * Check if the given directory is a thumbnail directory.
  242.      * @param string $entry directory name
  243.      * @return true if it is a thumbnail directory, false otherwise
  244.      */
  245.     function isThumbDir($entry
  246.     {
  247.         if($this->config['thumbnail_dir'== false
  248.             || strlen(trim($this->config['thumbnail_dir'])) == 0)
  249.             Return false;        
  250.         else
  251.             Return ($entry == $this->config['thumbnail_dir']);
  252.     }
  253.  
  254.     /**
  255.      * Check if the given file is a tmp file.
  256.      * @param string $file file name
  257.      * @return boolean true if it is a tmp file, false otherwise
  258.      */
  259.     function isTmpFile($file
  260.     {
  261.         $len strlen($this->config['tmp_prefix']);
  262.         if(substr($file,0,$len)==$this->config['tmp_prefix'])
  263.             Return true;
  264.         else
  265.             Return false;         
  266.     }
  267.  
  268.     /**
  269.      * For a given image file, get the respective thumbnail filename
  270.      * no file existence check is done.
  271.      * @param string $fullpathfile the full path to the image file
  272.      * @return string of the thumbnail file
  273.      */
  274.     function getThumbName($fullpathfile
  275.     {
  276.         $path_parts pathinfo($fullpathfile);
  277.         
  278.         $thumbnail $this->config['thumbnail_prefix'].$path_parts['basename'];
  279.  
  280.         if($this->config['safe_mode'== true
  281.             || strlen(trim($this->config['thumbnail_dir'])) == 0)
  282.         {
  283.             Return Files::makeFile($path_parts['dirname'],$thumbnail);
  284.         }
  285.         else
  286.         {
  287.             if(strlen(trim($this->config['thumbnail_dir'])) 0)
  288.             {
  289.                 $path Files::makePath($path_parts['dirname'],$this->config['thumbnail_dir']);
  290.                 if(!is_dir($path))
  291.                     Files::createFolder($path);
  292.                 Return Files::makeFile($path,$thumbnail);
  293.             }
  294.             else //should this ever happen?
  295.             {
  296.                 //error_log('ImageManager: Error in creating thumbnail name');
  297.             }
  298.         }
  299.     }
  300.     
  301.     /**
  302.      * Similar to getThumbName, but returns the URL, base on the
  303.      * given base_url in config.inc.php
  304.      * @param string $relative the relative image file name,
  305.      *  relative to the base_dir path
  306.      * @return string the url of the thumbnail
  307.      */
  308.     function getThumbURL($relative
  309.     {
  310.         $path_parts pathinfo($relative);
  311.         $thumbnail $this->config['thumbnail_prefix'].$path_parts['basename'];
  312.         if($path_parts['dirname']=='\\'$path_parts['dirname']='/';
  313.  
  314.         if($this->config['safe_mode'== true
  315.             || strlen(trim($this->config['thumbnail_dir'])) == 0)
  316.         {
  317.             Return Files::makeFile($this->getBaseURL(),$thumbnail);
  318.         }
  319.         else
  320.         {
  321.             if(strlen(trim($this->config['thumbnail_dir'])) 0)
  322.             {
  323.                 $path Files::makePath($path_parts['dirname'],$this->config['thumbnail_dir']);
  324.                 $url_path Files::makePath($this->getBaseURL()$path);
  325.                 Return Files::makeFile($url_path,$thumbnail);
  326.             }
  327.             else //should this ever happen?
  328.             {
  329.                 //error_log('ImageManager: Error in creating thumbnail url');
  330.             }
  331.  
  332.         }
  333.     }
  334.  
  335.     /**
  336.      * Check if the given path is part of the subdirectories
  337.      * under the base_dir.
  338.      * @param string $path the relative path to be checked
  339.      * @return boolean true if the path exists, false otherwise
  340.      */
  341.     function validRelativePath($path
  342.     {
  343.         $dirs $this->getDirs();
  344.         if($path == '/')
  345.             Return true;
  346.         //check the path given in the url against the 
  347.         //list of paths in the system.
  348.         for($i 0$i count($dirs)$i++)
  349.         {
  350.             $key key($dirs);
  351.             //we found the path
  352.             if($key == $path)
  353.                 Return true;
  354.         
  355.             next($dirs);
  356.         }        
  357.         Return false;
  358.     }
  359.  
  360.     /**
  361.      * Process uploaded files, assumes the file is in
  362.      * $_FILES['upload'] and $_POST['dir'] is set.
  363.      * The dir must be relative to the base_dir and exists.
  364.      * If 'validate_images' is set to true, only file with
  365.      * image dimensions will be accepted.
  366.      * @return null 
  367.      */
  368.     function processUploads(
  369.     {
  370.         if($this->isValidBase(== false)
  371.             return;
  372.  
  373.         $relative null;
  374.  
  375.         if(isset($_POST['dir'])) 
  376.             $relative rawurldecode($_POST['dir']);
  377.         else
  378.             return;
  379.  
  380.         //check for the file, and must have valid relative path
  381.         if(isset($_FILES['upload']&& $this->validRelativePath($relative))
  382.         {
  383.             $this->_processFiles($relative$_FILES['upload']);
  384.         }
  385.     }
  386.  
  387.     /**
  388.      * Process upload files. The file must be an
  389.      * uploaded file. If 'validate_images' is set to
  390.      * true, only images will be processed. Any duplicate
  391.      * file will be renamed. See Files::copyFile for details
  392.      * on renaming.
  393.      * @param string $relative the relative path where the file
  394.      *  should be copied to.
  395.      * @param array $file the uploaded file from $_FILES
  396.      * @return boolean true if the file was processed successfully,
  397.      *  false otherwise
  398.      */
  399.     function _processFiles($relative$file)
  400.     {
  401.         
  402.         if($file['error']!=0)
  403.         {
  404.             Return false;
  405.         }
  406.  
  407.         if(!is_file($file['tmp_name']))
  408.         {
  409.             Return false;
  410.         }
  411.  
  412.         if(!is_uploaded_file($file['tmp_name']))
  413.         {
  414.             Files::delFile($file['tmp_name']);
  415.             Return false;
  416.         }
  417.         
  418.  
  419.         if($this->config['validate_images'== true)
  420.         {
  421.             $imgInfo @getImageSize($file['tmp_name']);
  422.             if(!is_array($imgInfo))
  423.             {
  424.                 Files::delFile($file['tmp_name']);
  425.                 Return false;
  426.             }
  427.         }
  428.  
  429.         //now copy the file
  430.         $path Files::makePath($this->getBaseDir(),$relative);
  431.         $result Files::copyFile($file['tmp_name']$path$file['name']);
  432.  
  433.         //no copy error
  434.         if(!is_int($result))
  435.         {
  436.             Files::delFile($file['tmp_name']);
  437.             Return true;
  438.         }
  439.  
  440.         //delete tmp files.
  441.         Files::delFile($file['tmp_name']);
  442.         Return false;
  443.     }
  444.  
  445.     /**
  446.      * Get the URL of the relative file.
  447.      * basically appends the relative file to the
  448.      * base_url given in config.inc.php
  449.      * @param string $relative a file the relative to the base_dir
  450.      * @return string the URL of the relative file.
  451.      */
  452.     function getFileURL($relative
  453.     {
  454.         Return Files::makeFile($this->getBaseURL(),$relative);
  455.     }
  456.  
  457.     /**
  458.      * Get the fullpath to a relative file.
  459.      * @param string $relative the relative file.
  460.      * @return string the full path, .ie. the base_dir + relative.
  461.      */
  462.     function getFullPath($relative
  463.     {
  464.         Return Files::makeFile($this->getBaseDir(),$relative);;
  465.     }
  466.  
  467.     /**
  468.      * Get the default thumbnail.
  469.      * @return string default thumbnail, empty string if
  470.      *  the thumbnail doesn't exist.
  471.      */
  472.     function getDefaultThumb(
  473.     {
  474.         if(is_file($this->config['default_thumbnail']))
  475.             Return $this->config['default_thumbnail'];
  476.         else 
  477.             Return '';
  478.     }
  479.  
  480.  
  481.     /**
  482.      * Get the thumbnail url to be displayed.
  483.      * If the thumbnail exists, and it is up-to-date
  484.      * the thumbnail url will be returns. If the
  485.      * file is not an image, a default image will be returned.
  486.      * If it is an image file, and no thumbnail exists or
  487.      * the thumbnail is out-of-date (i.e. the thumbnail
  488.      * modified time is less than the original file)
  489.      * then a thumbs.php?img=filename.jpg is returned.
  490.      * The thumbs.php url will generate a new thumbnail
  491.      * on the fly. If the image is less than the dimensions
  492.      * of the thumbnails, the image will be display instead.
  493.      * @param string $relative the relative image file.
  494.      * @return string the url of the thumbnail, be it
  495.      *  actually thumbnail or a script to generate the
  496.      *  thumbnail on the fly.
  497.      */
  498.     function getThumbnail($relative
  499.     {
  500.         $fullpath Files::makeFile($this->getBaseDir(),$relative);
  501.  
  502.         //not a file???
  503.         if(!is_file($fullpath))
  504.             Return $this->getDefaultThumb();
  505.  
  506.         $imgInfo @getImageSize($fullpath);
  507.         
  508.         //not an image
  509.         if(!is_array($imgInfo))
  510.             Return $this->getDefaultThumb();
  511.  
  512.         //the original image is smaller than thumbnails,
  513.         //so just return the url to the original image.
  514.         if ($imgInfo[0<= $this->config['thumbnail_width']
  515.          && $imgInfo[1<= $this->config['thumbnail_height'])
  516.             Return $this->getFileURL($relative);
  517.  
  518.         $thumbnail $this->getThumbName($fullpath);
  519.         
  520.         //check for thumbnails, if exists and
  521.         // it is up-to-date, return the thumbnail url
  522.         if(is_file($thumbnail))
  523.         {
  524.             if(filemtime($thumbnail>= filemtime($fullpath))
  525.                 Return $this->getThumbURL($relative);
  526.         }
  527.  
  528.         //well, no thumbnail was found, so ask the thumbs.php
  529.         //to generate the thumbnail on the fly.
  530.         Return 'thumbs.php?img='.rawurlencode($relative);
  531.     }
  532.  
  533.     /**
  534.      * Delete and specified files.
  535.      * @return boolean true if delete, false otherwise
  536.      */
  537.     function deleteFiles(
  538.     {
  539.         if(isset($_GET['delf']))
  540.             $this->_delFile(rawurldecode($_GET['delf']));
  541.     }
  542.  
  543.     /**
  544.      * Delete and specified directories.
  545.      * @return boolean true if delete, false otherwise
  546.      */
  547.     function deleteDirs(
  548.     {
  549.          if(isset($_GET['deld']))
  550.             return $this->_delDir(rawurldecode($_GET['deld']));        
  551.          else
  552.              Return false;
  553.     }
  554.  
  555.     /**
  556.      * Delete the relative file, and any thumbnails.
  557.      * @param string $relative the relative file.
  558.      * @return boolean true if deleted, false otherwise.
  559.      */
  560.     function _delFile($relative
  561.     {
  562.         $fullpath Files::makeFile($this->getBaseDir(),$relative);
  563.         
  564.         //check that the file is an image
  565.         if($this->config['validate_images'== true)
  566.         {
  567.             if(!is_array($this->getImageInfo($fullpath)))
  568.                 return false//hmmm not an Image!!???
  569.         }
  570.  
  571.         $thumbnail $this->getThumbName($fullpath);
  572.  
  573.         if(Files::delFile($fullpath))
  574.             Return Files::delFile($thumbnail);
  575.         else
  576.             Return false;
  577.     }
  578.  
  579.     /**
  580.      * Delete directories recursively.
  581.      * @param string $relative the relative path to be deleted.
  582.      * @return boolean true if deleted, false otherwise.
  583.      */
  584.     function _delDir($relative
  585.     {
  586.         $fullpath Files::makePath($this->getBaseDir(),$relative);
  587.         if($this->countFiles($fullpath<= 0)
  588.             return Files::delFolder($fullpath,true)//delete recursively.
  589.         else
  590.             Return false;
  591.     }
  592.  
  593.     /**
  594.      * Create new directories.
  595.      * If in safe_mode, nothing happens.
  596.      * @return boolean true if created, false otherwise.
  597.      */
  598.     function processNewDir(
  599.     {
  600.         if($this->config['safe_mode'== true)
  601.             Return false;
  602.  
  603.         if(isset($_GET['newDir']&& isset($_GET['dir']))
  604.         {
  605.             $newDir rawurldecode($_GET['newDir']);
  606.             $dir rawurldecode($_GET['dir']);
  607.             $path Files::makePath($this->getBaseDir(),$dir);
  608.             $fullpath Files::makePath($pathFiles::escape($newDir));
  609.             if(is_dir($fullpath))
  610.                 Return false;
  611.  
  612.             Return Files::createFolder($fullpath);
  613.         }
  614.     }
  615.  
  616.     /**
  617.      * Do some graphic library method checkings
  618.      * @param string $library the graphics library, GD, NetPBM, or IM.
  619.      * @param string $method the method to check.
  620.      * @return boolean true if able, false otherwise.
  621.      */
  622.     function validGraphicMethods($library,$method)
  623.     {
  624.         switch ($library)
  625.         {
  626.             case 'GD':
  627.                 return $this->_checkGDLibrary($method);
  628.                 break;
  629.             case 'NetPBM':
  630.                 return $this->_checkNetPBMLibrary($method);
  631.                 break;
  632.             case 'IM':
  633.                 return $this->_checkIMLibrary($method);
  634.         }
  635.         return false;
  636.     }
  637.  
  638.     function _checkIMLibrary($method)
  639.     {
  640.         //ImageMagick goes throught 1 single executable
  641.         if(is_file(Files::fixPath(IMAGE_TRANSFORM_LIB_PATH).'convert'))
  642.             return true;
  643.         else
  644.             return false;
  645.     }
  646.  
  647.     /**
  648.      * Check the GD library functionality.
  649.      * @param string $library the graphics library, GD, NetPBM, or IM.
  650.      * @return boolean true if able, false otherwise.
  651.      */
  652.     function _checkGDLibrary($method)
  653.     {
  654.         $errors array();
  655.         switch($method)
  656.         {
  657.             case 'create':
  658.                 $errors['createjpeg'function_exists('imagecreatefromjpeg');
  659.                 $errors['creategif'function_exists('imagecreatefromgif');
  660.                 $errors['createpng'function_exists('imagecreatefrompng');
  661.                 break;
  662.             case 'modify':
  663.                 $errors['create'function_exists('ImageCreateTrueColor'|| function_exists('ImageCreate');
  664.                 $errors['copy'function_exists('ImageCopyResampled'|| function_exists('ImageCopyResized');
  665.                 break;
  666.             case 'save':
  667.                 $errors['savejpeg'function_exists('imagejpeg');
  668.                 $errors['savegif'function_exists('imagegif');
  669.                 $errors['savepng'function_exists('imagepng');
  670.                 break;
  671.         }
  672.  
  673.         return $errors;
  674.     }
  675. }
  676.  
  677. ?>

Documentation generated on Mon, 05 May 2008 16:20:24 +0400 by phpDocumentor 1.4.0