source: trunk/lib/ImageThumb.inc.php @ 136

Last change on this file since 136 was 136, checked in by scdev, 18 years ago

Q - Merged branches/2.0singleton into trunk. Completed updating classes to use singleton methods. Implemented tests. Fixed some bugs. Changed some interfaces.

File size: 29.6 KB
Line 
1<?php
2/**
3 * ImageThumb.inc.php
4 * code by strangecode :: www.strangecode.com :: this document contains copyrighted information
5 *
6 * @author   Quinn Comendant <quinn@strangecode.com>
7 * @requires Netpbm <http://sourceforge.net/projects/netpbm/> and libjpeg or GD.
8 * @version  2.0
9 */
10
11// Image resize options.
12define('IMAGETHUMB_FIT_WIDTH', 1);
13define('IMAGETHUMB_FIT_HEIGHT', 2);
14define('IMAGETHUMB_FIT_LARGER', 3);
15define('IMAGETHUMB_STRETCH', 4);
16define('IMAGETHUMB_NO_SCALE', 5);
17define('IMAGETHUMB_METHOD_NETPBM', 6);
18define('IMAGETHUMB_METHOD_GD', 7);
19
20class ImageThumb {
21   
22    // General object parameters.
23    var $_params = array(
24        // The location for images to create thumbnails from.
25        'source_dir' => null,
26
27        // Existing files will be overwritten when there is a name conflict?
28        'allow_overwriting' => false,
29
30        // The file permissions of the uploaded files. Remember, files will be owned by the web server user.
31        'dest_file_perms' => 0600,
32
33        // Permissions of autocreated directories. Must be at least 0700 with owner=apache.
34        'dest_dir_perms' => 0777,
35
36        // Require file to have one of the following file name extentions.
37        'valid_file_extensions' => array('jpg', 'jpeg', 'gif', 'png'),
38       
39        // Method to use for resizing. (IMAGETHUMB_METHOD_NETPBM or IMAGETHUMB_METHOD_GD)
40        'resize_method' => IMAGETHUMB_METHOD_NETPBM,
41
42        // Netpbm and libjpeg binary locations.
43        'anytopnm_binary' => '/usr/bin/anytopnm',
44        'pnmscale_binary' => '/usr/bin/pnmscale',
45        'cjpeg_binary' => '/usr/bin/cjpeg',
46
47        // Which messages do we pass to raiseMsg? Use one of the MSG_* constants or false to disable.
48        'display_messages' => MSG_ALL,
49    );
50   
51    // Default image size specs.
52    var $default_image_specs = array(
53        // The destination for an image thumbnail size. Path relative to source_dir (eg: ../thumbs).
54        'dest_dir' => null,
55       
56        // Destination file types. (IMG_JPG, IMG_PNG, IMG_GIF, IMG_WBMP)
57        'dest_file_type' => IMG_JPG,
58
59        // Destination file types. ('jpg', 'png', 'gif', 'wbmp')
60        'dest_file_extention' => 'jpg',
61       
62        // Type of scaling to perform, and sizes used to calculate max dimentions.
63        'scaling_type' => IMAGETHUMB_FIT_LARGER,
64        'width' => null,
65        'height' => null,
66
67        // Percentage quality of image compression output 0-100.
68        'quality' => 65,
69
70        // Create progressive jpegs?
71        'progressive' => false,
72
73        // If using GD method, apply sharpen filter. Requires PHP > 5.1.
74        'sharpen' => true,
75       
76        // Integers between 1-100, useful values are 65-85.
77        'sharpen_value' => 75,
78
79        // If source image is smaller than thumbnail, allow upscaling?
80        'allow_upscaling' => false,
81
82        // If thumb exists and filesize is smaller than this, do not overwrite the thumb.
83        'keep_filesize' => null,
84    );
85
86    // Final specifications for image sizes, set with setSpec().
87    var $image_specs = array();
88
89    /**
90     * Set (or overwrite existing) parameters by passing an array of new parameters.
91     *
92     * @access public
93     * @param  array    $params     Array of parameters (key => val pairs).
94     */
95    function setParam($params)
96    {
97        $app =& App::getInstance();
98
99        if (isset($params) && is_array($params)) {
100
101            // Enforce valid upload_path parameter.
102            if (isset($params['source_dir'])) {
103                $params['source_dir'] = realpath($params['source_dir']);
104                // Must be directory.
105                if (!is_dir($params['source_dir'])) {
106                    $app->logMsg(sprintf('Source directory invalid: %s', $params['source_dir']), LOG_ERR, __FILE__, __LINE__);
107                    trigger_error(sprintf('Source directory invalid: %s', $params['source_dir']), E_USER_ERROR);
108                }
109                // Must be readable.
110                if (!is_readable($params['source_dir'])) {
111                    $app->logMsg(sprintf('Source directory not readable: %s', $params['source_dir']), LOG_ERR, __FILE__, __LINE__);
112                    trigger_error(sprintf('Source directory not readable: %s', $params['source_dir']), E_USER_ERROR);
113                }
114            }
115
116            // Merge new parameters with old overriding only those passed.
117            $this->_params = array_merge($this->_params, $params);
118        } else {
119            $app->logMsg(sprintf('Parameters are not an array: %s', $params), LOG_ERR, __FILE__, __LINE__);
120        }
121    }
122
123    /**
124     * Return the value of a parameter, if it exists.
125     *
126     * @access public
127     * @param string $param        Which parameter to return.
128     * @return mixed               Configured parameter value.
129     */
130    function getParam($param)
131    {
132        $app =& App::getInstance();
133   
134        if (isset($this->_params[$param])) {
135            return $this->_params[$param];
136        } else {
137            $app->logMsg(sprintf('Parameter is not set: %s', $param), LOG_NOTICE, __FILE__, __LINE__);
138            return null;
139        }
140    }
141
142    /**
143     * Set the specification of thumbnails.
144     *
145     * @access  public
146     * @param   array $spec The specifications for a size of output image.
147     */
148    function setSpec($spec, $index=null)
149    {
150        $app =& App::getInstance();
151
152        // A little sanity checking.
153        if (!isset($spec['dest_dir']) || '' == $spec['dest_dir']) {
154            $app->logMsg('setSpec error: dest_dir not specified.', LOG_ERR, __FILE__, __LINE__);
155        }
156        if (isset($spec['dest_file_type'])) {
157            switch ($spec['dest_file_type']) {
158            case IMG_JPG :
159                if (imagetypes() & IMG_JPG == 0) {
160                    $app->logMsg(sprintf('IMG_JPG is not supported by this version of PHP GD.', null), LOG_ERR, __FILE__, __LINE__);
161                }
162                $spec['dest_file_extention'] = 'jpg';
163                break;
164            case IMG_PNG :
165                if (imagetypes() & IMG_PNG == 0) {
166                    $app->logMsg(sprintf('IMG_PNG is not supported by this version of PHP GD.', null), LOG_ERR, __FILE__, __LINE__);
167                }
168                $spec['dest_file_extention'] = 'png';
169                break;
170            case IMG_GIF :
171                if (imagetypes() & IMG_GIF == 0) {
172                    $app->logMsg(sprintf('IMG_GIF is not supported by this version of PHP GD.', null), LOG_ERR, __FILE__, __LINE__);
173                }
174                $spec['dest_file_extention'] = 'gif';
175                break;
176            case IMG_WBMP :
177                if (imagetypes() & IMG_WBMP == 0) {
178                    $app->logMsg(sprintf('IMG_WBMP is not supported by this version of PHP GD.', null), LOG_ERR, __FILE__, __LINE__);
179                }
180                $spec['dest_file_extention'] = 'wbmp';
181                break;
182            default :
183                $app->logMsg(sprintf('Invalid dest_file_type: %s', $spec['dest_file_type']), LOG_ERR, __FILE__, __LINE__);
184                break;
185            }
186        }
187        if (!isset($spec['width']) || !is_int($spec['width'])) {
188            $app->logMsg('setSpec error: width not specified.', LOG_ERR, __FILE__, __LINE__);
189        }
190        if (!isset($spec['height']) || !is_int($spec['height'])) {
191            $app->logMsg('setSpec error: height not specified.', LOG_ERR, __FILE__, __LINE__);
192        }
193        if (isset($spec['quality']) && IMG_JPG != $spec['dest_file_type']) {
194            $app->logMsg('The "quality" specification is not used unless IMG_JPG is the dest_file_type.', LOG_INFO, __FILE__, __LINE__);
195        }
196        if (isset($spec['progressive']) && IMG_JPG != $spec['dest_file_type']) {
197            $app->logMsg('The "progressive" specification is not used unless IMG_JPG is the dest_file_type.', LOG_INFO, __FILE__, __LINE__);
198        }
199       
200        if (isset($index) && isset($this->image_specs[$index])) {
201            // Merge with previous.
202            $final_spec = array_merge($this->image_specs[$index], $spec);
203            $this->image_specs[$index] = $final_spec;
204        } else {
205            // Merge with defaults.
206            $final_spec = array_merge($this->default_image_specs, $spec);           
207            $this->image_specs[] = $final_spec;
208        }
209       
210        return $final_spec;
211    }
212
213    /**
214     * Process an entire directory of images.
215     *
216     * @access  public
217     * @return  bool true on success, false on failure.
218     */
219    function processAll($runtime_specs=null)
220    {
221        $app =& App::getInstance();
222
223        // Ensure we have a source.
224        if ('' == $this->getParam('source_dir')) {
225            $app->logMsg(sprintf('Source directory not set before processing.'), LOG_ERR, __FILE__, __LINE__);
226            return false;
227        }
228
229        // Get all files in source directory.
230        $dir_handle = opendir($this->getParam('source_dir'));
231        while ($dir_handle && ($file = readdir($dir_handle)) !== false) {
232            // If the file name does not start with a dot (. or .. or .htaccess).
233            if (!preg_match('/^\./', $file) && in_array(strtolower(substr($file, strrpos($file, '.') + 1)), $this->getParam('valid_file_extensions'))) {
234                $files[] = $file;
235            }
236        }
237
238        // Process each found file.
239        if (is_array($files) && !empty($files)) {
240            $return_val = 0;
241            foreach ($files as $file_name) {
242                $return_val += $this->processFile($file_name, $runtime_specs);
243            }
244            $this->_raiseMsg(sprintf(_("Resized %s images."), sizeof($files)), MSG_SUCCESS, __FILE__, __LINE__);
245            return 0 === $return_val;
246        } else {
247            $app->logMsg(sprintf('No images found to thumbnail in directory %s.', $this->getParam('source_dir')), LOG_NOTICE, __FILE__, __LINE__);
248            return false;
249        }
250    }
251
252    /**
253     * Generate thumbnails for the specified file.
254     *
255     * @access  public
256     * @param   string $file_name Name of file with extention.
257     * @param   array $runtime_specs Array of specifications that will override all configured specifications.
258     * @return  bool true on success, false on failure.
259     */
260    function processFile($file_name, $runtime_specs=null)
261    {
262        $app =& App::getInstance();
263
264        // Source file determinted by provided file_name.
265        $source_file = realpath(sprintf('%s/%s', $this->getParam('source_dir'), $file_name));
266       
267        // Ensure we have a source.
268        if (sizeof($this->image_specs) < 1) {
269            if (is_array($runtime_specs)) {
270                $this->setSpec($runtime_specs, 0);
271            } else {
272                $app->logMsg(sprintf('Image specifications not set before processing.'), LOG_ERR, __FILE__, __LINE__);
273                return false;               
274            }
275        }
276
277        // Ensure we have a source.
278        if ('' == $this->getParam('source_dir')) {
279            $app->logMsg(sprintf('Source directory not set before processing.'), LOG_ERR, __FILE__, __LINE__);
280            return false;
281        }
282
283        // Confirm source image exists.
284        if (!file_exists($source_file)) {
285            $this->_raiseMsg(sprintf(_("Image resizing failed: source image %s was not found."), $file_name), MSG_ERR, __FILE__, __LINE__);
286            $app->logMsg(sprintf('Source image not found: %s', $source_file), LOG_ALERT, __FILE__, __LINE__);
287            return false;
288        }
289
290        // Confirm source image is readable.
291        if (!is_readable($source_file)) {
292            $this->_raiseMsg(sprintf(_("Image resizing failed: source image %s is not readable."), $file_name), MSG_ERR, __FILE__, __LINE__);
293            $app->logMsg(sprintf('Source image not readable: %s', $source_file), LOG_ALERT, __FILE__, __LINE__);
294            return false;
295        }
296
297        // Confirm source image contains data.
298        if (filesize($source_file) <= 0) {
299            $this->_raiseMsg(sprintf(_("Image resizing failed: source image %s is zero bytes."), $file_name), MSG_ERR, __FILE__, __LINE__);
300            $app->logMsg(sprintf('Source image is zero bytes: %s', $source_file), LOG_ALERT, __FILE__, __LINE__);
301            return false;
302        }
303
304        // Confirm source image has a valid file extension.
305        if (!$this->_validFileExtension($file_name)) {
306            $this->_raiseMsg(sprintf(_("Image resizing failed: source image %s not a valid type. It must have one of the following file name extensions: %s"), $file_name, join(', ', $this->getParam('valid_file_extensions'))), MSG_ERR, __FILE__, __LINE__);
307            $app->logMsg(sprintf('Image resizing failed: source image not of valid type: %s', $source_file), LOG_ERR, __FILE__, __LINE__);
308            return false;
309        }
310
311        // Ensure destination directories are created. This will only be called once per page load.
312        $this->_createDestDirs();
313       
314        // To keep this script running even if user tries to stop browser.
315        ignore_user_abort(true);
316        ini_set('max_execution_time', 300);
317        ini_set('max_input_time', 300);
318
319        // This remains zero until something goes wrong.
320        $return_val = 0;
321
322        foreach ($this->image_specs as $index => $spec) {
323           
324            if (is_array($runtime_specs)) {
325                // Override with runtime specs.
326                $spec = $this->setSpec($runtime_specs, $index);
327            }
328           
329            // Destination filename uses the extention defined by dest_file_extention.
330            $dest_file = realpath(sprintf('%s/%s/%s.%s', $this->getParam('source_dir'), $spec['dest_dir'], substr($file_name, 0, strrpos($file_name, '.')), $spec['dest_file_extention']));
331
332            // Skip existing thumbnails with file size below $spec['keep_filesize'].
333            if (isset($spec['keep_filesize']) && file_exists($dest_file)) {
334                $file_size = filesize($dest_file);
335                if (false !== $file_size && $file_size < $spec['keep_filesize']) {
336                    $app->logMsg(sprintf('Skipping thumbnail %s. File already exists and file size is less than %s bytes.', $spec['dest_dir'] . '/' . $file_name, $spec['keep_filesize']), LOG_DEBUG, __FILE__, __LINE__);
337                    continue;
338                }
339            }
340
341            // Determine if original file size is smaller than specified thumbnail size. Do not scale-up if $spec['allow_upscaling'] config is set to false.
342            $image_size = getimagesize($source_file);
343            if ($image_size['0'] <= $spec['width'] && $image_size['1'] <= $spec['height'] && !$spec['allow_upscaling']) {
344                $spec['scaling_type'] = IMAGETHUMB_NO_SCALE;
345                $app->logMsg(sprintf('Image %s smaller than specified %s thumbnail size. Keeping original size.', $file_name, $spec['dest_dir']), LOG_DEBUG, __FILE__, __LINE__);
346            }
347
348            // DO IT! Based on available method.
349            if (IMAGETHUMB_METHOD_NETPBM === $this->getParam('resize_method') && file_exists($this->getParam('anytopnm_binary')) && file_exists($this->getParam('pnmscale_binary')) && file_exists($this->getParam('cjpeg_binary'))) {
350                // Resize using Netpbm binaries.
351                $app->logMsg(sprintf('Resizing with Netpbm...', null), LOG_DEBUG, __FILE__, __LINE__);
352                $return_val += $this->_resizeWithNetpbm($source_file, $dest_file, $spec);
353            } else if (IMAGETHUMB_METHOD_GD === $this->getParam('resize_method') && extension_loaded('gd')) {
354                // Resize with GD.
355                $app->logMsg(sprintf('Resizing with GD...', null), LOG_DEBUG, __FILE__, __LINE__);
356                $return_val += $this->_resizeWithGD($source_file, $dest_file, $spec);
357            } else {
358                $app->logMsg(sprintf('Image thumbnailing failed. Neither Netpbm or GD is available.', null), LOG_DEBUG, __FILE__, __LINE__);
359                return false;
360            }
361        }
362
363        // If > 0, there was a problem thumb-nailing.
364        return 0 === $return_val;
365    }
366   
367    /*
368    * Use the Netpbm and libjpg cjpeg tools to generate a rescaled compressed image.
369    * This is the preferred method over GD which has (supposedly) less quality.
370    *
371    * @access   private
372    * @param    string  $source_file    Full path to source image file.
373    * @param    string  $dest_file      Full path to destination image file.
374    * @param    array   $spec           Array of image size specifications.
375    * @return   int                     0 if no error, n > 0 if errors.
376    * @author   Quinn Comendant <quinn@strangecode.com>
377    * @version  1.0
378    * @since    19 May 2006 13:55:46
379    */
380    function _resizeWithNetpbm($source_file, $dest_file, $spec)
381    {
382        $app =& App::getInstance();
383
384        // Define pnmscale arguments.
385        switch ($spec['scaling_type']) {
386        case IMAGETHUMB_FIT_WIDTH :
387            $pnmscale_args = sprintf(' -width %s ', escapeshellarg($spec['width']));
388            break;
389        case IMAGETHUMB_FIT_HEIGHT :
390            $pnmscale_args = sprintf(' -height %s ', escapeshellarg($spec['height']));
391            break;
392        case IMAGETHUMB_FIT_LARGER :
393            $pnmscale_args = sprintf(' -xysize %s %s ', escapeshellarg($spec['width']), escapeshellarg($spec['height']));
394            break;
395        case IMAGETHUMB_STRETCH :
396            $pnmscale_args = sprintf(' -width %s -height %s ', escapeshellarg($spec['width']), escapeshellarg($spec['height']));
397            break;
398        case IMAGETHUMB_NO_SCALE :
399        default :
400            $pnmscale_args = ' 1 ';
401            break;
402        }
403
404        // Define cjpeg arguments.
405        $cjpeg_args = sprintf(' -optimize -quality %s ', escapeshellarg($spec['quality']));
406        $cjpeg_args .= (true === $spec['progressive']) ? ' -progressive ' : '';
407
408        // Format the command that creates the thumbnail.
409        $command = sprintf('%s %s | %s %s | %s %s > %s/%s',
410            escapeshellcmd($this->getParam('anytopnm_binary')),
411            escapeshellcmd($source_file),
412            escapeshellcmd($this->getParam('pnmscale_binary')),
413            escapeshellcmd($pnmscale_args),
414            escapeshellcmd($this->getParam('cjpeg_binary')),
415            escapeshellcmd($cjpeg_args),
416            escapeshellcmd($dest_file),
417            escapeshellcmd($file_name)
418        );
419        $app->logMsg(sprintf('ImageThumb Netpbm command: %s', $command), LOG_DEBUG, __FILE__, __LINE__);
420       
421        // Execute!
422        exec($command, $output, $return_val);
423
424        if (0 === $return_val) {
425            // Success!
426            // Make the thumbnail writable so the user can delete it over ftp without being 'apache'.
427            chmod($dest_file, $this->getParam('dest_file_perms'));
428            $app->logMsg(sprintf('Successfully resized image %s', $spec['dest_dir'] . '/' . basename($dest_file), $return_val), LOG_DEBUG, __FILE__, __LINE__);
429        } else {
430            // An error occurred.
431            $app->logMsg(sprintf('Image %s failed resizing with return value: %s%s', $spec['dest_dir'] . '/' . basename($dest_file), $return_val, empty($output) ? '' : ' (' . getDump($output) . ')'), LOG_ERR, __FILE__, __LINE__);
432        }
433
434        // Return from the command will be > 0 if there was an error.
435        return $return_val;
436    }
437
438    /*
439    * Use PHP's built-in GD tools to generate a rescaled compressed image.
440    *
441    * @access   private
442    * @param    string  $source_file    Full path to source image file.
443    * @param    string  $dest_file      Full path to destination image file.
444    * @param    array   $spec           Array of image size specifications.
445    * @return   int                     0 if no error, n > 0 if errors.
446    * @author   Quinn Comendant <quinn@strangecode.com>
447    * @version  1.0
448    * @since    19 May 2006 15:46:02
449    */
450    function _resizeWithGD($source_file, $dest_file, $spec)
451    {
452        $app =& App::getInstance();
453
454        // Get original file dimensions and type.
455        list($source_image_width, $source_image_height, $source_image_type) = getimagesize($source_file);
456
457        // Define destination image dimentions.
458        switch ($spec['scaling_type']) {
459        case IMAGETHUMB_FIT_WIDTH :
460            $dest_image_width = $spec['width'];
461            $dest_image_height = $source_image_height * ($spec['width'] / $source_image_width);
462            break;
463        case IMAGETHUMB_FIT_HEIGHT :
464            $dest_image_height = $spec['height'];
465            $dest_image_width = $source_image_width * ($spec['height'] / $source_image_height);
466            break;
467        case IMAGETHUMB_FIT_LARGER :
468            if (($source_image_width * ($spec['height'] / $source_image_height)) <= $spec['width']) {
469                // Height is larger.
470                $dest_image_height = $spec['height'];
471                $dest_image_width = $source_image_width * ($spec['height'] / $source_image_height);
472            } else {
473                // Width is larger.
474                $dest_image_width = $spec['width'];
475                $dest_image_height = $source_image_height * ($spec['width'] / $source_image_width);
476            }
477            break;
478        case IMAGETHUMB_STRETCH :
479            $dest_image_width = $spec['width'];
480            $dest_image_height = $spec['height'];
481            break;
482        case IMAGETHUMB_NO_SCALE :
483        default :
484            $dest_image_width = $source_image_width;
485            $dest_image_height = $source_image_height;
486            break;
487        }
488
489        // Create source image data in memory.
490        switch ($source_image_type) {
491        case IMAGETYPE_JPEG :
492            $source_image_resource = imagecreatefromjpeg($source_file);
493            break;
494        case IMAGETYPE_PNG :
495            $source_image_resource = imagecreatefrompng($source_file);
496            break;
497        case IMAGETYPE_GIF :
498            $source_image_resource = imagecreatefromgif($source_file);
499            break;
500        case IMAGETYPE_WBMP :
501            $source_image_resource = imagecreatefromwbmp($source_file);
502        default :
503            $app->logMsg(sprintf('Source image type %s not supported.', $source_image_type), LOG_WARNING, __FILE__, __LINE__);
504            return 1;
505            break;
506        }
507        if (!$source_image_resource) {
508            $app->logMsg(sprintf('Error creating %s image in memory from %s', $source_image_type, $source_file), LOG_WARNING, __FILE__, __LINE__);
509            return 1;
510        }
511       
512        // Create destination image data in memory.
513        $dest_image_resource = imagecreatetruecolor($dest_image_width, $dest_image_height);
514
515        // Resample!
516        if (!imagecopyresampled($dest_image_resource, $source_image_resource, 0, 0, 0, 0, $dest_image_width, $dest_image_height, $source_image_width, $source_image_height)) {
517            $app->logMsg(sprintf('Error resampling image %s', $source_file), LOG_WARNING, __FILE__, __LINE__);
518            return 1;
519        }
520       
521        // Sharpen image using a custom filter matrix.
522        if (phpversion() > '5.1' && true === $spec['sharpen'] && $spec['sharpen_value'] > 0) {
523            $sharpen_value = round((((48 - 10) / (100 - 1)) * (100 - $spec['sharpen_value'])) + 10);
524            imageconvolution($dest_image_resource, array(array(-1,-1,-1),array(-1,$sharpen_value,-1),array(-1,-1,-1)), ($sharpen_value - 8), 0);
525        }
526
527        // Save image.
528        $return_val = true;
529        switch ($spec['dest_file_type']) {
530        case IMG_JPG :
531            imageinterlace($dest_image_resource, (true == $spec['progressive'] ? 1 : 0));
532            $return_val = imagejpeg($dest_image_resource, $dest_file, $spec['quality']);
533            break;
534        case IMG_PNG :
535            $return_val = imagepng($dest_image_resource, $dest_file);
536            break;
537        case IMG_GIF :
538            $return_val = imagegif($dest_image_resource, $dest_file);
539            break;
540        case IMG_WBMP :
541            $return_val = imagewbmp($dest_image_resource, $dest_file);
542            break;
543        default :
544            $app->logMsg(sprintf('Destination image type %s not supported for image %s.', $spec['dest_file_type'], $dest_file), LOG_WARNING, __FILE__, __LINE__);
545            return 1;
546            break;
547        }
548
549        if ($return_val) {
550            // Success!
551            // Make the thumbnail writable so the user can delete it over ftp without being 'apache'.
552            chmod($dest_file, $this->getParam('dest_file_perms'));
553            $app->logMsg(sprintf('Successfully resized image %s', $dest_file), LOG_DEBUG, __FILE__, __LINE__);
554            return 0;
555        } else {
556            // An error occurred.
557            $app->logMsg(sprintf('Image %s failed resizing.', $dest_file), LOG_ERR, __FILE__, __LINE__);
558            return 1;
559        }
560    }
561
562    /**
563     * Delete the thumbnails for the specified file name.
564     *
565     * @access  public
566     * @param   string $file_name The file name to delete, with extention.
567     * @return  bool true on success, false on failure.
568     */
569    function deleteThumbs($file_name)
570    {
571        $app =& App::getInstance();
572
573        // Ensure we have a source.
574        if ('' == $this->getParam('source_dir')) {
575            $app->logMsg(sprintf('Source directory not set before processing.'), LOG_ERR, __FILE__, __LINE__);
576            return false;
577        }
578
579        $return_val = 0;
580        foreach ($this->image_specs as $spec) {
581            $dest_file = realpath(sprintf('%s/%s/%s.%s', $this->getParam('source_dir'), $spec['dest_dir'], substr($file_name, 0, strrpos($file_name, '.')), $spec['dest_file_extention']));
582            if (file_exists($dest_file)) {
583                if (!unlink($dest_file)) {
584                    $return_val++;
585                    $app->logMsg(sprintf(_("Delete thumbs failed: %s"), $dest_file), LOG_WARNING, __FILE__, __LINE__);
586                }
587            }
588        }
589        $this->_raiseMsg(sprintf(_("The thumbnails for file %s have been deleted."), $file_name), MSG_SUCCESS, __FILE__, __LINE__);
590        return 0 === $return_val;
591    }
592
593    /**
594     * Delete the source image with the specified file name.
595     *
596     * @access  public
597     * @param   string $file_name The file name to delete, with extention.
598     * @return  bool true on success, false on failure.
599     */
600    function deleteOriginal($file_name)
601    {
602        $app =& App::getInstance();
603
604        // Ensure we have a source.
605        if ('' == $this->getParam('source_dir')) {
606            $app->logMsg(sprintf('Source directory not set before processing.'), LOG_ERR, __FILE__, __LINE__);
607            return false;
608        }
609
610        $source_file = realpath(sprintf('%s/%s', $this->getParam('source_dir'), $file_name));
611        if (!unlink($source_file)) {
612            $app->logMsg(sprintf(_("Delete original failed: %s"), $source_file), LOG_WARNING, __FILE__, __LINE__);
613            return false;
614        }
615        $this->_raiseMsg(sprintf(_("The original file %s has been deleted."), $file_name), MSG_SUCCESS, __FILE__, __LINE__);
616        return true;
617    }
618
619    /**
620     * Returns true if file exists.
621     *
622     * @access  public
623     * @param   string $file_name The file name to test, with extention.
624     * @return  bool true on success, false on failure.
625     */
626    function exists($file_name)
627    {
628        $app =& App::getInstance();
629
630        // Ensure we have a source.
631        if ('' == $this->getParam('source_dir')) {
632            $app->logMsg(sprintf('Source directory not set before processing.'), LOG_ERR, __FILE__, __LINE__);
633            return false;
634        }
635
636        $source_file = realpath(sprintf('%s/%s', $this->getParam('source_dir'), $file_name));
637        return file_exists($source_file);
638    }
639
640    /**
641     * Tests if extention of $file_name is in the array valid_file_extensions.
642     *
643     * @access  public
644     * @param   string  $file_name  A file name.
645     * @return  bool    True on success, false on failure.
646     */
647    function _validFileExtension($file_name)
648    {
649        preg_match('/.*?\.(\w+)$/i', $file_name, $ext);
650        return !empty($ext) && in_array(strtolower($ext[1]), $this->getParam('valid_file_extensions'));       
651    }
652
653    /**
654     * Make directory for each specified thumbnail size, if it doesn't exist.
655     *
656     * @access  public
657     * @return  bool true on success, false on failure.
658     */
659    function _createDestDirs()
660    {
661        $app =& App::getInstance();
662
663        static $already_checked = false;
664
665        if (!$already_checked) {
666            // Ensure we have a source.
667            if ('' == $this->getParam('source_dir')) {
668                $app->logMsg(sprintf('Source directory not set before creating destination directories.'), LOG_ERR, __FILE__, __LINE__);
669                return false;
670            }
671       
672            // Loop through specs and ensure all dirs are created.
673            $return_val = 0;
674            foreach ($this->image_specs as $spec) {
675                if (!file_exists($this->getParam('source_dir') . '/' . $spec['dest_dir'])) {
676                    if (!mkdir($this->getParam('source_dir') . '/' . $spec['dest_dir'], $this->getParam('dest_dir_perms'))) {
677                        $return_val++;
678                        $app->logMsg(sprintf('mkdir failure: %s', $this->getParam('source_dir') . '/' . $spec['dest_dir']), LOG_ERR, __FILE__, __LINE__);
679                    }
680                }
681            }
682
683            // If > 0, there was a problem creating dest dirs.
684            return 0 === $return_val;
685        }
686
687        $already_checked = true;
688    }
689
690    /**
691     * An alias for $app->raiseMsg that only sends messages configured by display_messages.
692     *
693     * @access public
694     *
695     * @param string $message The text description of the message.
696     * @param int    $type    The type of message: MSG_NOTICE,
697     *                        MSG_SUCCESS, MSG_WARNING, or MSG_ERR.
698     * @param string $file    __FILE__.
699     * @param string $line    __LINE__.
700     */
701    function _raiseMsg($message, $type, $file, $line)
702    {
703        $app =& App::getInstance();
704
705        if ($this->getParam('display_messages') === true || (is_int($this->getParam('display_messages')) && $this->getParam('display_messages') & $type > 0)) {
706            $app->raiseMsg($message, $type, $file, $line);
707        }
708    }
709
710} // End of class.
711?>
Note: See TracBrowser for help on using the repository browser.