Webylon 3.2 API Docs
  • Package
  • Class
  • Tree
  • Deprecated
  • Download
Version: current
  • 3.2
  • 3.1

Packages

  • 1c
    • exchange
      • catalog
  • auth
  • Booking
  • building
    • company
  • cart
    • shipping
    • steppedcheckout
  • Catalog
    • monument
  • cms
    • assets
    • batchaction
    • batchactions
    • bulkloading
    • comments
    • content
    • core
    • export
    • newsletter
    • publishers
    • reports
    • security
    • tasks
  • Dashboard
  • DataObjectManager
  • event
  • faq
  • forms
    • actions
    • core
    • fields-basic
    • fields-dataless
    • fields-datetime
    • fields-files
    • fields-formatted
    • fields-formattedinput
    • fields-relational
    • fields-structural
    • transformations
    • validators
  • googlesitemaps
  • guestbook
  • installer
  • newsletter
  • None
  • photo
    • gallery
  • PHP
  • polls
  • recaptcha
  • sapphire
    • api
    • bulkloading
    • control
    • core
    • cron
    • dev
    • email
    • fields-formattedinput
    • filesystem
    • formatters
    • forms
    • i18n
    • integration
    • misc
    • model
    • parsers
    • search
    • security
    • tasks
    • testing
    • tools
    • validation
    • view
    • widgets
  • seo
    • open
      • graph
  • sfDateTimePlugin
  • spamprotection
  • stealth
    • captha
  • subsites
  • userform
    • pagetypes
  • userforms
  • webylon
  • widgets

Classes

  • Archive
  • File
  • Filesystem
  • FlushGeneratedImagesTask
  • FLV
  • Folder
  • Folder_UnusedAssetsField
  • GD
  • Image
  • Image_Cached
  • MediawebPage_Image
  • MP3
  • SaveFileSizeTask
  • TarballArchive
  • Upload
  • Upload_Validator
  • VideoFile
  1 <?php
  2 /**
  3  * Represents an image attached to a page.
  4  * @package sapphire
  5  * @subpackage filesystem
  6  */
  7 class Image extends File {
  8     
  9     const ORIENTATION_SQUARE = 0;
 10     const ORIENTATION_PORTRAIT = 1;
 11     const ORIENTATION_LANDSCAPE = 2;
 12     
 13     static $casting = array(
 14         'Tag' => 'HTMLText',
 15     );
 16 
 17     // форматы преобразования для которых при равенстве размеров картинки совпадают
 18     static $safeGenerateFormats = array('SetRatioSize', 'SetSize', 'SetWidth', 'SetHeight');
 19 
 20     /**
 21      * The width of an image thumbnail in a strip.
 22      * @var int
 23      */
 24     public static $strip_thumbnail_width = 50;
 25     
 26     /**
 27      * The height of an image thumbnail in a strip.
 28      * @var int
 29      */
 30     public static $strip_thumbnail_height = 50;
 31     
 32     /**
 33      * The width of an image thumbnail in the CMS.
 34      * @var int
 35      */
 36     public static $cms_thumbnail_width = 100;
 37     
 38     /**
 39      * The height of an image thumbnail in the CMS.
 40      */
 41     public static $cms_thumbnail_height = 100;
 42     
 43     /**
 44      * The width of an image thumbnail in the Asset section.
 45      */
 46     public static $asset_thumbnail_width = 100;
 47     
 48     /**
 49      * The height of an image thumbnail in the Asset section.
 50      */
 51     public static $asset_thumbnail_height = 100;
 52     
 53     /**
 54      * The width of an image preview in the Asset section.
 55      */
 56     public static $asset_preview_width = 400;
 57     
 58     /**
 59      * The height of an image preview in the Asset section.
 60      */
 61     public static $asset_preview_height = 200;
 62     
 63     /** 
 64      * Height and width of an asset in a popup 
 65      */ 
 66     public static $asset_popup_size = 800; 
 67                  
 68     /**
 69      * Set up template methods to access the transformations generated by 'generate' methods.
 70      */
 71     public function defineMethods() {
 72         $methodNames = $this->allMethodNames();
 73         foreach($methodNames as $methodName) {
 74             if(substr($methodName,0,8) == 'generate') {
 75                 $this->addWrapperMethod(substr($methodName,8), 'getFormattedImage');
 76             }
 77         }
 78         
 79         parent::defineMethods();
 80     }
 81     
 82     /**
 83      * An image exists if it has a filename.
 84      * @return boolean
 85      */
 86     public function exists() {
 87         if(isset($this->record["Filename"])) {
 88             return true;
 89         }       
 90     }
 91 
 92     /**
 93      * Get the relative URL for this Image.
 94      * Overwrites File->URL() which returns an absolute URL.
 95      * 
 96      * @todo Refactor to return absolute URL like {@link File}
 97      * @uses Director::baseURL()
 98      * @return string
 99      */
100 /* !!! absent in 2.4.0
101     function getURL() {
102         return $this->Filename;//Director::baseURL() . $this->Filename;
103     }
104 */  
105     /**
106      * Return an XHTML img tag for this Image.
107      * @return string
108      */
109     function getTag() {
110         if(file_exists(Director::baseFolder() . '/' . $this->Filename)) {
111             $url = $this->getURL(); // !!! absolute url
112             $title = ($this->Title) ? $this->Title : $this->Filename;
113             if($this->Title) {
114                 $title = Convert::raw2att($this->Title);
115             } else {
116                 if(preg_match("/([^\/]*)\.[a-zA-Z0-9]{1,6}$/", $title, $matches)) $title = Convert::raw2att($matches[1]);
117             }
118             return "<img src=\"$url\" alt=\"$title\" />";
119         }
120     }
121     
122     /**
123      * Return an XHTML img tag for this Image.
124      * @return string
125      */
126     function forTemplate() {
127         return $this->getTag();
128     }
129 
130     function loadUploadedImage($tmpFile) {
131         if(!is_array($tmpFile)) {
132             user_error("Image::loadUploadedImage() Not passed an array.  Most likely, the form hasn't got the right enctype", E_USER_ERROR);
133         }
134         
135         if(!$tmpFile['size']) {
136             return;
137         }
138         
139         $class = $this->class;
140 
141         // Create a folder      
142         if(!file_exists(ASSETS_PATH)) {
143             mkdir(ASSETS_PATH, Filesystem::$folder_create_mask);
144         }
145         
146         if(!file_exists(ASSETS_PATH . "/$class")) {
147             mkdir(ASSETS_PATH . "/$class", Filesystem::$folder_create_mask);
148         }
149 
150         // Generate default filename
151         $file = Convert::rus2lat($tmpFile['name']);
152         $file = str_replace(' ', '-',$file);
153         $file = ereg_replace('[^A-Za-z0-9+.-]+','',$file);
154         $file = ereg_replace('-+', '-',$file);
155         if(!$file) {
156             $file = "file.jpg";
157         }
158         
159         $file = ASSETS_PATH . "/$class/$file";
160         
161         while(file_exists(BASE_PATH . "/$file")) {
162             $i = $i ? ($i+1) : 2;
163             $oldFile = $file;
164             $file = ereg_replace('[0-9]*(\.[^.]+$)',$i . '\\1', $file);
165             if($oldFile == $file && $i > 2) user_error("Couldn't fix $file with $i", E_USER_ERROR);
166         }
167         
168         if(file_exists($tmpFile['tmp_name']) && copy($tmpFile['tmp_name'], BASE_PATH . "/$file")) {
169             // Remove the old images
170 
171             $this->deleteFormattedImages();
172             return true;
173         }
174     }
175     
176     public function SetWidth($width) {
177         return $this->getFormattedImage('SetWidth', $width);
178     }
179     
180     public function SetHeight($height) {
181         return $this->getFormattedImage('SetHeight', $height);
182     }
183     
184     public function SetSize($width, $height) {
185         return $this->getFormattedImage('SetSize', $width, $height);
186     }
187     
188     public function SetRatioSize($width, $height) {
189         return $this->getFormattedImage('SetRatioSize', $width, $height);
190     }
191     
192     public function generateSetRatioSize(GD $gd, $width, $height) {
193         return $gd->resizeRatio($width, $height);
194     }
195     
196     /**
197      * Resize this Image by width, keeping aspect ratio. Use in templates with $SetWidth.
198      * @return GD
199      */
200     public function generateSetWidth(GD $gd, $width) {
201         return $gd->resizeByWidth($width);
202     }
203     
204     /**
205      * Resize this Image by height, keeping aspect ratio. Use in templates with $SetHeight.
206      * @return GD
207      */
208     public function generateSetHeight(GD $gd, $height){
209         return $gd->resizeByHeight($height);
210     }
211     
212     /**
213      * Resize this Image by both width and height, using padded resize. Use in templates with $SetSize.
214      * @return GD
215      */
216     public function generateSetSize(GD $gd, $width, $height) {
217         return $gd->paddedResize($width, $height);
218     }
219     
220     public function CMSThumbnail() {
221         return $this->getFormattedImage('CMSThumbnail');
222     }
223     
224     /**
225      * Resize this image for the CMS. Use in templates with $CMSThumbnail.
226      * @return GD
227      */
228     function generateCMSThumbnail(GD $gd) {
229         return $gd->paddedResize($this->stat('cms_thumbnail_width'),$this->stat('cms_thumbnail_height'));
230     }
231     
232     /**
233      * Resize this image for preview in the Asset section. Use in templates with $AssetLibraryPreview.
234      * @return GD
235      */
236     function generateAssetLibraryPreview(GD $gd) {
237         return $gd->paddedResize($this->stat('asset_preview_width'),$this->stat('asset_preview_height'));
238     }
239     
240     /**
241      * Resize this image for thumbnail in the Asset section. Use in templates with $AssetLibraryThumbnail.
242      * @return GD
243      */
244     function generateAssetLibraryThumbnail(GD $gd) {
245         return $gd->paddedResize($this->stat('asset_thumbnail_width'),$this->stat('asset_thumbnail_height'));
246     }
247     
248     /**
249      * Resize this image for use as a thumbnail in a strip. Use in templates with $StripThumbnail.
250      * @return GD
251      */
252     function generateStripThumbnail(GD $gd) {
253         return $gd->croppedResize($this->stat('strip_thumbnail_width'),$this->stat('strip_thumbnail_height'));
254     }
255     
256     function generatePaddedImage(GD $gd, $width, $height) {
257         return $gd->paddedResize($width, $height);
258     }
259 
260     /**
261      * Return an image object representing the image in the given format.
262      * This image will be generated using generateFormattedImage().
263      * The generated image is cached, to flush the cache append ?flush=1 to your URL.
264      * @param string $format The name of the format.
265      * @param string $arg1 An argument to pass to the generate function.
266      * @param string $arg2 A second argument to pass to the generate function.
267      * @return Image_Cached
268      */
269     function getFormattedImage($format, $arg1 = null, $arg2 = null) {
270         if($this->ID && $this->Filename && Director::fileExists($this->Filename)) {
271             $cacheFile = $this->cacheFilename($format, $arg1, $arg2);
272 
273             if(!file_exists(Director::baseFolder().'/'.$cacheFile) || isset($_GET['flush'])) {
274                 $this->generateFormattedImage($format, $arg1, $arg2);
275             }
276             
277             $cached = new Image_Cached($cacheFile);
278             // Pass through the title so the templates can use it
279             $cached->Title = $this->Title;
280             return $cached;
281         }
282     }
283     
284     /**
285      * Return the filename for the cached image, given it's format name and arguments.
286      * @param string $format The format name.
287      * @param string $arg1 The first argument passed to the generate function.
288      * @param string $arg2 The second argument passed to the generate function.
289      * @return string
290      */
291     function cacheFilename($format, $arg1 = null, $arg2 = null) {
292         $folder = $this->ParentID ? $this->Parent()->Filename : ASSETS_DIR . "/";
293         
294         $format = $format.$arg1.$arg2;
295         
296         return $folder . "_resampled/$format-" . $this->Name;
297     }
298     
299     /**
300      * Generate an image on the specified format. It will save the image
301      * at the location specified by cacheFilename(). The image will be generated
302      * using the specific 'generate' method for the specified format.
303      * @param string $format Name of the format to generate.
304      * @param string $arg1 Argument to pass to the generate method.
305      * @param string $arg2 A second argument to pass to the generate method.
306      */
307     function generateFormattedImage($format, $arg1 = null, $arg2 = null) {
308         $cacheFile = $this->cacheFilename($format, $arg1, $arg2);
309     
310         $gd = new GD(Director::baseFolder().'/' . $this->Filename);
311         
312         if($gd->hasGD()){
313             $generateFunc = "generate$format";      
314             if($this->hasMethod($generateFunc)){
315                 $gd2 = $this->$generateFunc($gd, $arg1, $arg2);
316                 if($gd2){
317                     // если картинки совпадают - просто копируем (на unix-like можно делать symlink)
318                     if (array_search($format, Image::$safeGenerateFormats) !== false
319                         && $gd->getWidth() == $gd2->getWidth() && $gd->getHeight() == $gd2->getHeight()
320                         ) {
321                         $gd2->makeDir(dirname(Director::baseFolder().'/' . $cacheFile));
322                         copy(Director::baseFolder().'/' . $this->Filename, Director::baseFolder().'/' . $cacheFile);
323                         @chmod(Director::baseFolder().'/' . $cacheFile, 0664);
324                     }
325                     else {
326                         $gd2->writeTo(Director::baseFolder().'/' . $cacheFile);
327                     }
328                 }
329     
330             } else {
331                 USER_ERROR("Image::generateFormattedImage - Image $format function not found.",E_USER_WARNING);
332             }
333         }
334     }
335     
336     /**
337      * Generate a resized copy of this image with the given width & height.
338      * Use in templates with $ResizedImage.
339      */
340     function generateResizedImage($gd, $width, $height) {
341         if(is_numeric($gd) || !$gd){
342             USER_ERROR("Image::generateFormattedImage - generateResizedImage is being called by legacy code or gd is not set.",E_USER_WARNING);
343         }else{
344             return $gd->resize($width, $height);
345         }
346     }
347 
348     /**
349      * Generate a resized copy of this image with the given width & height, cropping to maintain aspect ratio.
350      * Use in templates with $CroppedImage
351      */
352     function generateCroppedImage($gd, $width, $height) {
353         return $gd->croppedResize($width, $height);
354     }
355     
356     /**
357      * Generate a rotateв Clockwise image
358      * Use in templates with $RotateClockwise
359      */
360     public function generateRotateClockwise(GD $gd) {
361         return $gd->rotate(90);
362     }
363 
364     /**
365      * Generate a rotateв CounterClockwise image
366      * Use in templates with $RotateCounterClockwise
367      */
368     public function generateRotateCounterClockwise(GD $gd) {
369         return $gd->rotate(270);
370     }
371 
372     /**
373      * Remove all of the formatted cached images for this image.
374      * @return int The number of formatted images deleted
375      */
376     public function deleteFormattedImages() {
377             
378         if(!$this->Filename) return 0;
379         $numDeleted = 0;
380         $folder = $this->ParentID ? $this->Parent()->Filename : ASSETS_DIR . '/';
381         $name = $this->Name;
382         
383         if ($this->isChanged('ParentID')) {
384             $folder = dirname($this->getField('Filename')) . '/';
385             $name = basename($this->getField('Filename'));
386         }
387         
388         $cacheDir = Director::getAbsFile($folder . '_resampled/');
389         if(!is_dir($cacheDir)) return 0;
390 
391         $this->extend('deleteFormattedImages', $numDeleted);        
392         
393         $cachedFiles = array();
394         if($handle = opendir($cacheDir)) {
395             while(($file = readdir($handle)) !== false) {
396                 // save files not starting with a dot && ending with $this->Name
397                 if(substr($file, 0, 1) != '.' 
398                     && substr_compare($file, $name, -strlen($name), strlen($name)) == 0
399                     && is_file($cacheDir . $file)
400                 ) {
401                     $cachedFiles[] = $file;
402                 }
403             }
404             closedir($handle);
405         }
406         if (count($cachedFiles) == 0) return 0;
407 
408         $methodNames = $this->allMethodNames();
409         $generateFuncs = array();
410         foreach($methodNames as $methodName) {
411             if(substr($methodName, 0, 8) == 'generate') {
412                 $format = substr($methodName, 8);
413                 $generateFuncs[] = $format;
414             }
415         }
416         // All generate functions may appear any number of times in the image cache name.
417         $generateFuncs = implode('|', $generateFuncs);
418         $pattern = "/^(({$generateFuncs})(\d+)?-)+".preg_quote($name)."$/i";
419 
420         foreach(preg_grep($pattern, $cachedFiles) as $cfile) {
421             if(file_exists($cacheDir . $cfile)) {
422                 unlink($cacheDir . $cfile);
423                 $numDeleted++;
424             }
425         }       
426         return $numDeleted;
427     }
428      
429     /**
430      * Get the dimensions of this Image.
431      * @param string $dim If this is equal to "string", return the dimensions in string form,
432      * if it is 0 return the height, if it is 1 return the width.
433      * @return string|int
434      */
435     function getDimensions($dim = "string") {
436         if($this->getField('Filename')) {
437             $imagefile = Director::baseFolder() . '/' . $this->getField('Filename');
438             if(file_exists($imagefile)) {
439                 $size = getimagesize($imagefile);
440                 return ($dim === "string") ? "$size[0]x$size[1]" : $size[$dim];
441             } else {
442                 return ($dim === "string") ? "file '$imagefile' not found" : null;
443             }
444         }
445     }
446 
447     /**
448      * Get the width of this image.
449      * @return int
450      */
451     function getWidth() {
452         return $this->getDimensions(0);
453     }
454     
455     /**
456      * Get the height of this image.
457      * @return int
458      */
459     function getHeight() {
460         return $this->getDimensions(1);
461     }
462     
463     /**
464      * Get the orientation of this image.
465      * @return ORIENTATION_SQUARE | ORIENTATION_PORTRAIT | ORIENTATION_LANDSCAPE
466      */
467     function getOrientation() {
468         $width = $this->getWidth();
469         $height = $this->getHeight();
470         if($width > $height) {
471             return self::ORIENTATION_LANDSCAPE;
472         } elseif($height > $width) {
473             return self::ORIENTATION_PORTRAIT;
474         } else {
475             return self::ORIENTATION_SQUARE;
476         }
477     }
478 
479     /**
480      * Возвращает содержимое файла
481      * Требуется для SVG-формата
482      * 
483      * @return string
484      */ 
485     function getSVGContent() {
486         if (strtoupper($this->getExtension()) == 'SVG') {
487             if(file_exists($this->getFullPath())) {
488                 return file_get_contents($this->getFullPath());             
489             }
490         }
491         return false;
492     }
493     
494     protected function onBeforeDelete() { 
495         parent::onBeforeDelete(); 
496         $this->deleteFormattedImages();
497     }
498     
499     //При перемещении Image удаляем его Formatted Images
500     protected function resetFilename($renamePhysicalFile = true) {
501         $this->deleteFormattedImages();     
502         parent::resetFilename($renamePhysicalFile);
503     }
504 }
505 
506 /**
507  * A resized / processed {@link Image} object.
508  * When Image object are processed or resized, a suitable Image_Cached object is returned, pointing to the
509  * cached copy of the processed image.
510  * @package sapphire
511  * @subpackage filesystem
512  */
513 class Image_Cached extends Image {
514     /**
515      * Create a new cached image.
516      * @param string $filename The filename of the image.
517      * @param boolean $isSingleton This this to true if this is a singleton() object, a stub for calling methods.  Singletons
518      * don't have their defaults set.
519      */
520     public function __construct($filename = null, $isSingleton = false) {
521         parent::__construct(array(), $isSingleton);
522         $this->Filename = $filename;
523     }
524     
525     public function getRelativePath() {
526         return $this->getField('Filename');
527     }
528     
529     // Prevent this from doing anything
530     public function requireTable() {
531         
532     }
533     
534     public function debug() {
535         return "Image_Cached object for $this->Filename";
536     }
537 }
538 
539 
[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the Silverstripe Forums to ask development related questions. -
Webylon 3.2 API Docs API documentation generated by ApiGen 2.8.0