root/trunk/lib/SGL/Image.php

Revision 3122, 30.6 kB (checked in by demian, 3 weeks ago)

bugfix to trunk merge

Line 
1 <?php
2 /* Reminder: always indent with 4 spaces (no tabs). */
3 // +---------------------------------------------------------------------------+
4 // | Copyright (c) 2006, Demian Turner                                         |
5 // | All rights reserved.                                                      |
6 // |                                                                           |
7 // | Redistribution and use in source and binary forms, with or without        |
8 // | modification, are permitted provided that the following conditions        |
9 // | are met:                                                                  |
10 // |                                                                           |
11 // | o Redistributions of source code must retain the above copyright          |
12 // |   notice, this list of conditions and the following disclaimer.           |
13 // | o Redistributions in binary form must reproduce the above copyright       |
14 // |   notice, this list of conditions and the following disclaimer in the     |
15 // |   documentation and/or other materials provided with the distribution.    |
16 // | o The names of the authors may not be used to endorse or promote          |
17 // |   products derived from this software without specific prior written      |
18 // |   permission.                                                             |
19 // |                                                                           |
20 // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS       |
21 // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT         |
22 // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR     |
23 // | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT      |
24 // | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,     |
25 // | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT          |
26 // | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,     |
27 // | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY     |
28 // | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT       |
29 // | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE     |
30 // | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.      |
31 // |                                                                           |
32 // +---------------------------------------------------------------------------+
33 // | Seagull 0.6                                                               |
34 // +---------------------------------------------------------------------------+
35 // | Image.php                                                                 |
36 // +---------------------------------------------------------------------------+
37 // | Author: Dmitri Lakachauskis <dmitri@telenet.lv>                           |
38 // +---------------------------------------------------------------------------+
39
40 define('SGL_IMAGE_DEFAULT_SECTION', 'default');
41
42 /**
43  * Base image class.
44  *
45  * @package    SGL
46  * @subpackage image
47  * @author     Dmitri Lakachauskis <dmitri@telenet.lv>
48  */
49 class SGL_Image
50 {
51     /**
52      * Image file name e.g. my-image-name.jpg.
53      *
54      * @var string
55      */
56     var $fileName;
57
58     /**
59      * Name of module, which uses this class.
60      *
61      * @var string
62      */
63     var $moduleName;
64
65     /**
66      * Used for image modification.
67      *
68      * @var array
69      */
70     var $_aParams = array();
71
72     /**
73      * Thumbnails params are stored here.
74      *
75      * @var array
76      */
77     var $_aThumbnails = array();
78
79     /**
80      * Loaded strategies.
81      *
82      * @var array
83      */
84     var $_aStrats = array();
85
86     /**
87      * Constructor.
88      *
89      * @access public
90      *
91      * @param string $fileName
92      * @param string $moduleName
93      */
94     function SGL_Image($fileName = null, $moduleName = '')
95     {
96         SGL::logMessage(null, PEAR_LOG_DEBUG);
97
98         if (is_null($fileName)) {
99             $fileName = $this->generateUniqueFileName();
100         }
101
102         $this->fileName   = $fileName;
103         $this->moduleName = $moduleName;
104     }
105
106     /**
107      * Get filename.
108      *
109      * @return string
110      */
111     function getFileName()
112     {
113         return $this->fileName;
114     }
115
116     /**
117      * Initialize SGL_Image instance. Can parse the specified ini file passed
118      * as $params or use the prepeared array directly.
119      * Load strategies taking into account extracted params.
120      *
121      * @access public
122      *
123      * @param mixed  $params
124      * @param string $container
125      *
126      * @return boolean
127      */
128     function init($params, $container = SGL_IMAGE_DEFAULT_SECTION)
129     {
130         // filename is specified
131         if (is_string($params)) {
132             if (file_exists($params)) {
133                 $params = SGL_ImageConfig::getParamsFromFile($params);
134                 if (PEAR::isError($params)) {
135                     return $params;
136                 }
137                 $params = $params[$container];
138             } else {
139                 return SGL::raiseError("SGL_Image: file '$params' not found");
140             }
141         } elseif (!is_array($params)) { // wrong parameters' type
142             return SGL::raiseError("SGL_Image: you should specify an array
143                 or path to configuration file");
144         }
145         $ok = $this->_setParams($params);
146         if (PEAR::isError($ok)) {
147             return $ok;
148         }
149         $ok = $this->_loadStrategies();
150         if (PEAR::isError($ok)) {
151             return $ok;
152         }
153         return true;
154     }
155
156     /**
157      * Generate filename.
158      *
159      * @access public
160      *
161      * @return string
162      */
163     function generateUniqueFileName()
164     {
165         return md5(uniqid(rand(), true));
166     }
167
168     /**
169      * Get path to image folder. Can be called statically or as instance call.
170      *
171      * @access public
172      *
173      * @param string $moduleName
174      *
175      * @return string
176      *
177      * @see _getImagePath()
178      */
179     function getPath()
180     {
181         $args = func_get_args();
182         $args = array_merge(array('path'), $args);
183         $callback = SGL_Image::_isStaticMethod()
184             ? array('SGL_Image', '_getImagePath')
185             : array($this, '_getImagePath');
186         return call_user_func_array($callback, $args);
187     }
188
189     /**
190      * Get URL to image folder. Can be called statically or as instance call.
191      * It is only possible to get an URL to a folder if we place files at
192      * SGL_MOD_DIR/$moduleName/www/images. To achieve this we must specify a
193      * module name during image instantiation or as an argument here.
194      *
195      * @access public
196      *
197      * @param string $moduleName
198      *
199      * @return string
200      *
201      * @see _getImagePath()
202      */
203     function getUrl()
204     {
205         $args = func_get_args();
206         $args = array_merge(array('url'), $args);
207         $callback = SGL_Image::_isStaticMethod()
208             ? array('SGL_Image', '_getImagePath')
209             : array($this, '_getImagePath');
210         return call_user_func_array($callback, $args);
211     }
212
213     /**
214      * Upload image and create thumbnails.
215      *
216      * @access public
217      *
218      * @param string  $srcLocation  image temporary location
219      * @param string  $callback     which method to use to create new image
220      * @param boolean $replace      replace existing image
221      *
222      * @return boolean
223      */
224     function create($srcLocation, $callback = 'move_uploaded_file', $replace = false)
225     {
226         if (!function_exists($callback)) {
227             return SGL::raiseError("SGL_Image: function '$callback'
228                 does not exist");
229         }
230         $destPath = $this->getPath();
231         $ok = SGL_Image::_ensureDirIsWritable($destPath);
232         if (PEAR::isError($ok)) {
233             return $ok;
234         }
235         $destLocation = $destPath . '/' . $this->fileName;
236         if ($replace && file_exists($destLocation)) {
237             unlink($destLocation);
238         } elseif (file_exists($destLocation)) { // purely for testing
239             return SGL::raiseError("SGL_Image: file '$destLocation' exists");
240         }
241         if (!$callback($srcLocation, $destLocation)) {
242             return SGL::raiseError("SGL_Image: function '$callback' failed");
243         }
244         $ok = $this->_toThumbnails();
245         if (PEAR::isError($ok)) {
246             return $ok;
247         }
248         $ok = $this->transform();
249         if (PEAR::isError($ok)) {
250             return $ok;
251         }
252         return true;
253     }
254
255     /**
256      * Alias for SGL_Image#create($srcLocation, $callback, $replace = true).
257      *
258      * @access public
259      *
260      * @param string $srcLocation
261      * @param string $callback
262      *
263      * @return boolean
264      *
265      * @see create()
266      */
267     function replace($srcLocation, $callback = 'move_uploaded_file')
268     {
269         return $this->create($srcLocation, $callback, true);
270     }
271
272     /**
273      * Delete image and it's thumbnails.
274      *
275      * @access public
276      *
277      * @param mixed $fileName
278      *
279      * @return boolean
280      */
281     function delete($fileName = null)
282     {
283         if (is_null($fileName)) {
284             if (is_null($this->fileName)) {
285                 return SGL::raiseError('SGL_Image: file name is not specified');
286             }
287             $fileName = $this->getPath() . '/' . $this->fileName;
288         }
289         $ok = SGL_Image::_ensureDirIsWritable(dirname($fileName));
290         if (PEAR::isError($ok)) {
291             return $ok;
292         }
293         if (!file_exists($fileName)) {
294             return SGL::raiseError('SGL_Image: file not found', SGL_ERROR_NOFILE);
295         }
296         unlink($fileName);
297         $ok = $this->_toThumbnails('unlink'); // delete thumbnails
298         if (PEAR::isError($ok)) {
299             return $ok;
300         }
301         return true;
302     }
303
304     /**
305      * Transform image.
306      *
307      * @access public
308      *
309      * @param mixed $section
310      *
311      * @return boolean
312      */
313     function transform($section = null)
314     {
315         // do nothing if no strats were loaded or there is no strategy for
316         // specified section (thumbnail)
317         if (empty($this->_aStrats) || (!is_null($section)
318                 && !isset($this->_aStrats[$section]))) {
319             return true;
320         }
321         reset($this->_aStrats);
322         if (is_null($section)) {
323             $section = key($this->_aStrats);
324             // no strategy loaded for parent section
325             if (!is_numeric($section)) {
326                 return true;
327             }
328             $fileName = $this->getPath() . '/' . $this->fileName;
329             $params   = &$this->_aParams;
330         } else {
331             $thumbDir = !empty($this->_aParams['thumbDir'])
332                 ? '/' . $this->_aParams['thumbDir']
333                 : '';
334             $fileName = $this->getPath() . $thumbDir . '/' .
335                 $section . '_' . $this->fileName;
336             $params = &$this->_aThumbnails[$section];
337         }
338         foreach ($this->_aStrats[$section] as $stratName => $stratObj) {
339             $configString = $params[$stratName];
340             if (is_object($configString)) {
341                 $configString = '';
342             }
343             $ok = $stratObj->init($fileName, $configString);
344             if (PEAR::isError($ok)) {
345                 return $ok;
346             }
347             $ok = $stratObj->transform();
348             if (PEAR::isError($ok)) {
349                 return $ok;
350             }
351             $ok = $stratObj->save($params['saveQuality']);
352             if (PEAR::isError($ok)) {
353                 return $ok;
354             }
355         }
356         return true;
357     }
358
359     /**
360      * Transform main image and all it's thumbnails by loaded strategies.
361      *
362      * @access public
363      *
364      * @return boolean
365      *
366      * @see transform()
367      */
368     function transformAll()
369     {
370         $parentSection = array(null);
371         $aSections = array_merge($parentSection, $this->getThumbnailNames());
372         foreach ($aSections as $sectionName) {
373             $ok = $this->transform($sectionName);
374             if (PEAR::isError($ok)) {
375                 return $ok;
376             }
377         }
378         return true;
379     }
380
381     /**
382      * @access public
383      *
384      * @return array
385      */
386     function getThumbnailNames()
387     {
388         return array_keys($this->_aThumbnails);
389     }
390
391     /**
392      * Set modification params.
393      *
394      * @access private
395      *
396      * @param array  $aParams
397      *
398      * @return boolean
399      */
400     function _setParams($aParams)
401     {
402         $ok = SGL_ImageConfig::paramsCheck($aParams);
403         if (PEAR::isError($ok)) {
404             return $ok;
405         }
406         SGL_ImageConfig::cleanup($aParams);
407         if (isset($aParams['thumbnails'])) {
408             foreach ($aParams['thumbnails'] as $thumbName => $thumbParams) {
409                 $ok = SGL_ImageConfig::paramsCheck($thumbParams, $thumbName);
410                 if (PEAR::isError($ok)) {
411                     return $ok;
412                 }
413             }
414             SGL_ImageConfig::cleanup($aParams['thumbnails']);
415             $this->_aThumbnails = $aParams['thumbnails'];
416             unset($aParams['thumbnails']);
417         }
418         $this->_aParams = $aParams;
419         return true;
420     }
421
422     /**
423      * @access private
424      *
425      * @param string $callType
426      * @param string $moduleName
427      *
428      * @return string
429      */
430     function _getImagePath()
431     {
432         $args = func_get_args();
433         if (empty($args)) { // at least $callType must be specified
434             return SGL::raiseError('SGL_Image: call type is not specified');
435         }
436
437         $callType   = array_shift($args); // 'url' or 'path'
438         $moduleName = false;
439         $path       = '';
440
441         // get module
442         if (SGL_Image::_isInstanceMethod()) {
443             if (count($args)) {
444                 $moduleName = array_shift($args);
445             } else { // we know module's name if we have an instance
446                 $moduleName = $this->moduleName;
447             }
448         } elseif (count($args)) {
449             $moduleName = array_shift($args);
450         }
451
452         if ('url' == $callType) {
453             // if we try to get an URL, module name must be specified,
454             // otherwise it is not possible to have access to image via HTTP
455             if (empty($moduleName)) {
456                 return SGL::raiseError('SGL_Image: module is not specified');
457             }
458             $path = SGL_BASE_URL . '/' . $moduleName . '/images';
459         } else {
460             if (!empty($moduleName)) {
461                 $path = SGL_MOD_DIR . '/' . $moduleName . '/www/images';
462             } else {
463                 $path = SGL_UPLOAD_DIR;
464             }
465         }
466         return $path;
467     }
468
469     /**
470      * Copy, move or delete thumbnails, using original image.
471      *
472      * @access private
473      *
474      * @param string $callback  operation to perform on original image
475      *
476      * @return boolean
477      */
478     function _toThumbnails($callback = 'copy')
479     {
480         if (empty($this->_aThumbnails)) {
481             return true;
482         }
483         if (!function_exists($callback)) {
484             return SGL::raiseError("SGL_Image: function '$callback'
485                 does not exist");
486         }
487         $aThumbs  = array_keys($this->_aThumbnails); // available thumbnails
488         $origFile = $this->getPath() . '/' . $this->fileName;
489         $thumbDir = empty($this->_aParams['thumbDir'])
490             ? '' : '/' . $this->_aParams['thumbDir'];
491         foreach ($aThumbs as $thumbName) {
492             $destLocation = $this->getPath() . $thumbDir . '/' . $thumbName
493                 . '_' . $this->fileName;
494             $ok = SGL_Image::_ensureDirIsWritable(dirname($destLocation));
495             if (PEAR::isError($ok)) {
496                 return $ok;
497             }
498             if (file_exists($destLocation)) {
499                 unlink($destLocation);
500             }
501             if ($callback != 'unlink') {
502                 if (!$callback($origFile, $destLocation)) {
503                     return SGL::raiseError("SGL_Image: function
504                         '$callback' failed");
505                 }
506                 $ok = $this->transform($thumbName);
507                 if (PEAR::isError($ok)) {
508                     return $ok;
509                 }
510             }
511         }
512         return true;
513     }
514
515     /**
516      * @access private
517      * @static
518      *
519      * @param string $dirName
520      *
521      * @return boolean
522      */
523     function _ensureDirIsWritable($dirName)
524     {
525         if (!is_writable($dirName)) {
526             require_once 'System.php';
527             $ok = System::mkDir(array('-p', $dirName));
528             if (PEAR::isError($ok)) {
529                 return $ok;
530             }
531             if (!$ok) {
532                 return SGL::raiseError("SGL_Image: can not make directory
533                     '$dirName' writable");
534             }
535             $mask = umask(0);
536             $ok   = @chmod($dirName, 0777);
537             if (!$ok) {
538                 return SGL::raiseError("SGL_Image: can not perform chmod on
539                     directory '$dirName'");
540             }
541             umask($mask);
542         }
543         return true;
544     }
545
546     /**
547      * @access private
548      *
549      * @return boolean
550      */
551     function _loadStrategies()
552     {
553         // transformation: main container + thumbnails
554         $aConfiguration = array_merge(array($this->_aParams), $this->_aThumbnails);
555         $aAvailParams = SGL_ImageConfig::getAvailableParams();
556         $aDrivers     = array();
557         foreach ($aConfiguration as $container => $aParams) {
558
559             // available strategies for current container
560             $aStrats = array_diff(array_keys($aParams), $aAvailParams);
561
562             // while testing mock object can be passed as a driver
563             if (!is_object($aParams['driver'])) {
564                 // load driver
565                 $driverSignature = md5($aParams['driver']);
566                 if (!isset($aDrivers[$driverSignature])) {
567                     require_once 'Image/Transform.php';
568                     $oDriver = &Image_Transform::factory($aParams['driver']);
569                     if (PEAR::isError($oDriver)) {
570                         return $oDriver;
571                     }
572                     $aDrivers[$driverSignature] = &$oDriver;
573                 }
574             }
575
576             // load strategies
577             foreach ($aStrats as $strategyName) {
578                 // skip strategy without params or switched off strategies
579                 if (empty($aParams[$strategyName])) {
580                     continue;
581                 }
582
583                 // while testing a mock obejct can be passed
584                 if (is_object($aParams[$strategyName])) {
585                     $this->_aStrats[$container][$strategyName] = &$aParams[$strategyName];
586                     continue;
587                 }
588
589                 $stratName = ucfirst($strategyName) . 'Strategy';
590                 $stratFile = SGL_CORE_DIR . "/ImageTransform/$stratName.php";
591                 if (!file_exists($stratFile)) {
592                     return SGL::raiseError("SGL_Image: file '$stratFile' does not exist");
593                 }
594                 include_once $stratFile;
595                 $stratClass = 'SGL_ImageTransform_' . $stratName;
596                 if (!class_exists($stratClass)) {
597                     return SGL::raiseError("SGL_Image: class '$stratClass' does not exist");
598                 }
599                 $this->_aStrats[$container][$strategyName] = & new $stratClass(
600                     $aDrivers[$driverSignature]);
601             }
602         }
603         return true;
604     }
605
606     /**
607      * Check if method is called statically.
608      *
609      * @access private
610      * @static
611      *
612      * @return boolean
613      *
614      * @see _isInstanceMethod()
615      */
616     function _isStaticMethod()
617     {
618         return !SGL_Image::_isInstanceMethod();
619     }
620
621     /**
622      * Check if SGL_Image instance is initialized.
623      *
624      * @access private
625      * @static
626      *
627      * @return boolean
628      *
629      * @see _isStaticMethod()
630      */
631     function _isInstanceMethod()
632     {
633         return isset($this) && is_a($this, 'SGL_Image');
634     }
635 }
636
637 /**
638  * @staticvar array
639  *
640  * @see SGL_ImageConfig::getProperty()
641  */
642 $GLOBALS['_SGL']['ImageConfig']['aProps']['_aMainParams'] =
643     array('driver', 'saveQuality', 'thumbDir');
644
645 /**
646  * @staticvar array
647  *
648  * @see SGL_ImageConfig::getProperty()
649  */
650 $GLOBALS['_SGL']['ImageConfig']['aProps']['_aAdditionalParams'] =
651     array('inherit', 'thumbnails', 'inheritThumbnails');
652
653 /**
654  * Manipulate with SGL_Image configuration.
655  *
656  * @package    seagull
657  * @subpackage image
658  * @author     Dmitri Lakachauskis <dmitri@telenet.lv>
659  */
660 class SGL_ImageConfig
661 {
662     /**
663      * Remove processed params from config array to keep it clean.
664      *
665      * @access public
666      * @static
667      *
668      * @param array $aParams
669      */
670     function cleanup(&$aParams)
671     {
672         if (empty($aParams)) {
673             return;
674         }
675         reset($aParams);
676         $firstkey = key($aParams);
677         if (is_array($aParams[$firstkey])) {
678             foreach ($aParams as $key => $value) {
679                 SGL_ImageConfig::cleanup($aParams[$key]);
680             }
681             return;
682         }
683         reset($aParams);
684         $aAddParams = &SGL_ImageConfig::getProperty('_aAdditionalParams');
685         foreach ($aAddParams as $param) {
686             if (isset($aParams[$param]) && is_scalar($aParams[$param])) {
687                 unset($aParams[$param]);
688             }
689         }
690     }
691
692     /**
693      * Check if all params needed for SGL_Image initialization are specified.
694      *
695      * @access public
696      * @static
697      *
698      * @param array  $aParams
699      * @param string $sectionName
700      *
701      * @return boolean
702      */
703     function paramsCheck($aParams, $sectionName = '')
704     {
705         $aMainParams = &SGL_ImageConfig::getProperty('_aMainParams');
706         $aRet = array_diff($aMainParams, array_keys($aParams));
707         if (!empty($aRet)) {
708             $error = "SGL_ImageConfig: missing parameters";
709             if (!empty($sectionName)) {
710                 $error .= ' for [' . $sectionName . ']';
711             }
712             $error .= ': ' . implode(', ', $aRet);
713             return SGL::raiseError($error);
714         }
715         return true;
716     }
717
718     /**
719      * Get all available config params. This does not include strategies.
720      *
721      * @access public
722      * @static
723      *
724      * @return array
725      */
726     function getAvailableParams()
727     {
728         $aAddParams  = &SGL_ImageConfig::getProperty('_aAdditionalParams');
729         $aMainParams = &SGL_ImageConfig::getProperty('_aMainParams');
730         return array_merge($aAddParams, $aMainParams);
731     }
732
733     /**
734      * Extract params from file. While extracting we take into account
735      * config sections' inheritance.
736      *
737      * @access public
738      * @static
739      *
740      * @param string $fileName
741      *
742      * @return array
743      */
744     function getParamsFromFile($fileName)
745     {
746         if (!is_readable($fileName)) {
747             return SGL::raiseError("SGL_ImageConfig: '$fileName' is not readable");
748         }
749         $aRet = parse_ini_file($fileName, true);
750         if (!isset($aRet[SGL_IMAGE_DEFAULT_SECTION])) {
751             return SGL::raiseError('SGL_ImageConfig: default container not found');
752         }
753         $aSections = SGL_ImageConfig::getUniqueSectionNames($aRet);
754
755         ksort($aRet);
756         $aResult = array();
757         $default = array();
758         foreach ($aSections as $sectionName) {
759             $ret = SGL_ImageConfig::_getSectionData($aRet, $sectionName, $default);
760             if (PEAR::isError($ret)) {
761                 return $ret;
762             }
763             if ($sectionName == SGL_IMAGE_DEFAULT_SECTION) {
764                 $default = $ret;
765             } else {
766                 $aResult[$sectionName] = $ret;
767             }
768         }
769
770         $aDefault = array(SGL_IMAGE_DEFAULT_SECTION => $default);
771         return array_merge($aDefault, $aResult);
772     }
773
774     /**
775      * Extract params from config string.
776      *
777      * @access public
778      * @static
779      *
780      * @param string $configString
781      *
782      * @return array
783      */
784     function getParamsFromString($configString)
785     {
786         $aRet = array();
787         if (empty($configString)) {
788             return $aRet;
789         }
790         $aParams = array_map('trim', explode(',', $configString));
791         foreach ($aParams as $param) {
792             if (false !== strpos($param, ':')) {
793                 $arr = explode(':', $param);
794                 $aRet[$arr[0]] = $arr[1];
795             } else {
796                 $aRet[] = $param; // when only one parameter exists
797             }
798         }
799         return $aRet;
800     }
801
802     /**
803      * Helper method for SGL_ImageConfig::getParamsFromFile().
804      *
805      * @access public
806      * @static
807      *
808      * @param array $aSections
809      *
810      * @return array
811      *
812      * @see getParamsFromFile()
813      */
814     function getUniqueSectionNames($aSections)
815     {
816         $aResult   = array();
817         $aSections = array_keys($aSections);
818         sort($aSections);
819         foreach ($aSections as $sectionName) {
820             $aNameParts = explode('_', $sectionName);
821             if (in_array($aNameParts[0], $aResult)) {
822                 continue;
823             }
824             $aResult[] = $sectionName;
825         }
826         // place default section at beginning
827         $index = array_search(SGL_IMAGE_DEFAULT_SECTION, $aResult);
828         unset($aResult[$index]);
829         array_unshift($aResult, SGL_IMAGE_DEFAULT_SECTION);
830         return $aResult;
831     }
832
833     /**
834      * Helper method for SGL_ImageConfig::getParamsFromFile(), which does
835      * all the dirty work i.e. merging sections' options.
836      *
837      * @access private
838      * @static
839      *
840      * @param array  $aData
841      * @param string $sectionName
842      * @param array  $override
843      *
844      * @return array
845      *
846      * @see getParamsFromFile()
847      */
848     function _getSectionData($aData, $sectionName, $override)
849     {
850         if (!empty($override['thumbnails'])) {
851             $overrideThumbs = $override['thumbnails'];
852             unset($override['thumbnails']);
853         }
854
855         // save parent section's data
856         $aResult = !empty($aData[$sectionName]['inherit'])
857             ? array_merge($override, $aData[$sectionName]) // inherit from default
858             : $aData[$sectionName];
859
860         // process thumbnails
861         if (!empty($aResult['thumbnails']) || !empty($aResult['inheritThumbnails'])) {
862             $aTotalThumbs = array();
863             if (!empty($aResult['inheritThumbnails'])
864                     && isset($overrideThumbs)
865                     && is_array($overrideThumbs)) {
866                 $aTotalThumbs = array_keys($overrideThumbs);
867             }
868             if (!empty($aResult['thumbnails'])) {
869                 $aThumbs = explode(',', $aResult['thumbnails']);
870                 $aTotalThumbs = array_merge($aTotalThumbs, $aThumbs);
871             }
872
873             $aThumbs = array();
874             foreach ($aTotalThumbs as $thumbName) {
875                 // e.g. media_small
876                 $thumbSectionName = $sectionName . '_' . $thumbName;
877                 if (isset($aData[$thumbSectionName])) {
878                     $aThumbs[$thumbName] = (isset($aData[$thumbSectionName]['inherit'])
879                             && !$aData[$thumbSectionName]['inherit'])
880                         // do inherit parent container
881                         ? $aData[$thumbSectionName]
882                         // do inherit by default
883                         : array_merge($aResult, $aData[$thumbSectionName]);
884
885                     // default thumbnail exists
886                 } elseif (isset($overrideThumbs[$thumbName])
887                         // and it can be inherited
888                         && !empty($aResult['inheritThumbnails'])) {
889                     $defaultThumbSectionName = SGL_IMAGE_DEFAULT_SECTION .
890                         '_' . $thumbName;
891                     if (isset($aData[$defaultThumbSectionName]['inherit'])
892                             && !$aData[$defaultThumbSectionName]['inherit']) {
893                         // do not inherit parent section's data
894                         $aThumbs[$thumbName] = $overrideThumbs[$thumbName];
895                     } else {
896                         // inherit parent section's data
897                         $aThumbs[$thumbName] = array_merge($aResult,
898                             $overrideThumbs[$thumbName]);
899                     }
900                 }
901             }
902             if (!empty($aThumbs)) {
903                 $aResult['thumbnails'] = $aThumbs;
904             }
905         }
906         return $aResult;
907     }
908
909     /**
910      * Replacement for PEAR::getStaticProperty(). Vars are initialized
911      * by putting values directly in $GLOBALS array. In that case we can
912      * ignore annoying error for PHP 5.1.6.
913      *
914      * @access public
915      * @static
916      *
917      * @param string $name
918      *
919      * @return mixed
920      */
921     function &getProperty($name)
922     {
923         $aProps = &$GLOBALS['_SGL']['ImageConfig']['aProps'];
924         if (!isset($aProps[$name])) {
925             $aProps[$name] = null;
926         }
927         return $aProps[$name];
928     }
929 }
930
931 /**
932  * Base image transformation strategy.
933  *
934  * @package    seagull
935  * @subpackage image
936  * @author     Dmitri Lakachauskis <dmitri@telenet.lv>
937  *
938  * @abstract
939  */
940 class SGL_ImageTransformStrategy
941 {
942     /**
943      * PEAR Image_Transfrom.
944      *
945      * @var object
946      */
947     var $driver;
948
949     /**
950      * Full image path.
951      *
952      * @var string
953      */
954     var $fileName;
955
956     /**
957      * Constructor.
958      *
959      * @access public
960      *
961      * @param PEAR Image_Transfrom $driver
962      */
963     function SGL_ImageTransformStrategy(&$driver)
964     {
965         $this->driver = &$driver;
966     }
967
968     /**
969      * Init strategy i.e. load image file and parse params.
970      *
971      * @access public
972      *
973      * @param string $fileName
974      * @param string $configString
975      *
976      * @return boolean
977      */
978     function init($fileName, $configString = '')
979     {
980         $ok = $this->load($fileName);
981         if (PEAR::isError($ok)) {
982             return $ok;
983         }
984         if (!empty($configString)) {
985             $aParsedParams = SGL_ImageConfig::getParamsFromString($configString);
986             $this->setParams($aParsedParams);
987         }
988         return true;
989     }
990
991     /**
992      * @access public
993      *
994      * @param array $aParams
995      */
996     function setParams($aParams)
997     {
998         $this->aParams = $aParams;
999     }
1000
1001     /**
1002      * Load file.
1003      *
1004      * @access public
1005      *
1006      * @param string $fileName
1007      *
1008      * @return boolean
1009      */
1010     function load($fileName)
1011     {
1012         if (!is_readable($fileName)) {
1013             return SGL::raiseError("SGL_Image: file '$fileName' is not readable");
1014         }
1015         $this->fileName = $fileName;
1016         return $this->driver->load($fileName);
1017     }
1018
1019     /**
1020      * Save file, free memory.
1021      *
1022      * @access public
1023      *
1024      * @param $saveQuality
1025      * @param $saveFormat   jpg, gif or png (not support by SGL_Image yet)
1026      *
1027      * @return boolean
1028      */
1029     function save($saveQuality, $saveFormat = '')
1030     {
1031         $ok = $this->driver->save($this->fileName, $saveFormat, $saveQuality);
1032         if (PEAR::isError($ok)) {
1033             return $ok;
1034         }
1035         return $this->driver->free();
1036     }
1037
1038     /**
1039      * Tranform image.
1040      *
1041      * @access   public
1042      * @abstract
1043      */
1044     function transform()
1045     {
1046     }
1047 }
1048
1049 ?>
Note: See TracBrowser for help on using the browser.