Blame | Last modification | View Log | Download
<?php namespace ProcessWire;/*** ProcessWire Image Fieldtype** Field that stores one or more image files.** For documentation about the fields used in this class, please see:* /wire/core/Fieldtype.php* /wire/core/FieldtypeMulti.php** ProcessWire 3.x, Copyright 2020 by Ryan Cramer* https://processwire.com***/class FieldtypeImage extends FieldtypeFile {/*** File schema is configured to store dimensions for image files 'width', 'height', 'ratio' (flag)**/const fileSchemaDimensions = 256;/*** Get module info** @return array**/public static function getModuleInfo() {return array('title' => 'Images','version' => 102,'summary' => 'Field that stores one or more GIF, JPG, or PNG images','permanent' => true,);}/*** Get blank value** @param Page $page* @param Field $field* @return Pageimages|Pagefiles**/public function getBlankValue(Page $page, Field $field) {$pageimages = $this->wire(new Pageimages($page));$pageimages->setField($field);$pageimages->setTrackChanges(true);return $pageimages;}/*** @param Pagefiles $pagefiles* @param string $filename* @return Pageimage|Pagefile**/protected function getBlankPagefile(Pagefiles $pagefiles, $filename) {return $this->wire(new Pageimage($pagefiles, $filename));}/*** Get default file extensions* @return string**/protected function getDefaultFileExtensions() {return "gif jpg jpeg png";}/*** Check and update database schema according to current version and features** @param Field $field* @param array $schema Updated directly* @param int $fileSchema The fileSchema version flags integer* @return int Updated fileSchema flags integer* @since 3.0.154**/protected function updateDatabaseSchema(Field $field, array &$schema, $fileSchema) {$fileSchema = parent::updateDatabaseSchema($field, $schema, $fileSchema);$hasDimensions = $fileSchema & self::fileSchemaDimensions;$schema['width'] = 'int';$schema['height'] = 'int';$schema['ratio'] = 'decimal(4,2)';$schema['keys']['width'] = 'index (width)';$schema['keys']['height'] = 'index (height)';$schema['keys']['ratio'] = 'index (ratio)';if(!$hasDimensions) {$numErrors = 0;if($this->wire('database')->tableExists($field->getTable())) {$columns = array('width', 'height', 'ratio');foreach($columns as $column) {if(!$this->addColumn($field, $column, $schema)) $numErrors++;if($numErrors) break;}} else {// new field being created that is getting initial schema to create table}if(!$numErrors) {$fileSchema = $fileSchema | self::fileSchemaDimensions;}}return $fileSchema;}/*** Convert individual Pagefile to array for storage in DB** @param Page $page* @param Field $field* @param Pagefile|Pageimage $pagefile* @return array**/protected function sleepFile(Page $page, Field $field, Pagefile $pagefile) {$item = parent::sleepFile($page, $field, $pagefile);$fileSchema = (int) $field->get('fileSchema');if($fileSchema & self::fileSchemaDimensions) {$info = $pagefile->getImageInfo(true);if(strpos($info['width'], '%')) $info['width'] = (-1 * (int) rtrim($info['width'], '%'));if(strpos($info['height'], '%')) $info['height'] = (-1 * (int) rtrim($info['height'], '%'));$item['width'] = (int) $info['width'];$item['height'] = (int) $info['height'];$item['ratio'] = number_format($pagefile->ratio, 2, '.', '');}return $item;}/*** Wakeup individual file converting array of data to Pagefile and adding it to Pagefiles** @param Page $page* @param Field $field* @param Pagefiles $pagefiles* @param array $a Data from DB* @return Pagefile**/protected function wakeupFile(Page $page, Field $field, Pagefiles $pagefiles, array $a) {/** @var Pageimage $pagefile */$pagefile = parent::wakeupFile($page, $field, $pagefiles, $a);if(!empty($a['width'])) {// dimension info already present in DB: populate to Pageimage object/*if($a['width'] < 0) $a['width'] = abs($a['width']) . '%';if($a['height'] < 0) $a['height'] = abs($a['height']) . '%';$pagefile->setImageInfo(array('width' => $a['width'], 'height' => $a['height']));*/} else if(self::autoUpdateOnWakeup && (((int) $field->get('fileSchema')) & self::fileSchemaDimensions) && $pagefile->width()) {// dimension info not yet in DB: detect and populate in DBlist($width, $height, $ratio) = array($pagefile->width(), $pagefile->height(), $pagefile->ratio);if(strpos($width, '%')) $width = (-1 * (int) rtrim($width, '%'));if(strpos($height, '%')) $height = (-1 * (int) rtrim($height, '%'));$this->saveFileCols($page, $field, $pagefile, array('width' => $width,'height' => $height,'ratio' => $ratio,));}return $pagefile;}/*** Export a Pageimages value to a portable PHP array** @param Page $page* @param Field $field* @param array|float|int|null|object|string $value* @param array $options* @return array**/public function ___exportValue(Page $page, Field $field, $value, array $options = array()) {/** @var Pageimages $pagefiles */$pagefiles = $value;$value = parent::___exportValue($page, $field, $value, $options);if(empty($options['system'])) {foreach($value as $k => $v) {$img = $pagefiles->get($v['name']);$value[$k]['width'] = $img->width();$value[$k]['height'] = $img->height();}}if(!empty($options['FieldtypeImage'])) {$o = $options['FieldtypeImage'];if(!empty($o['variations'])) {// include URLs to image variationsforeach($value as $k => $v) {if(empty($options['system'])) {$img = $pagefiles->get($v['name']);} else {$img = $pagefiles->get($k);}$variations = array();foreach($img->getVariations() as $variation) {/** @var Pageimage $variation */$variations[$variation->name] = $variation->httpUrl();}$value[$k]['variations'] = $variations;}}}return $value;}/*** Get Inputfields to configure fields using this Fieldtype** @param Field $field* @return InputfieldWrapper**/public function ___getConfigInputfields(Field $field) {$inputfields = parent::___getConfigInputfields($field);$f = $inputfields->get('outputString');$f->attr('placeholder', "i.e. <img src='{url}' alt='{description}' />");$f->notes .= ", {width}, {height}";return $inputfields;}/*public function getInputfield(Page $page, Field $field) {// even though we don't want this input field, call it anywayparent::getInputfield($page, $field);$inputfield = $this->modules->get("InputfieldImage");$inputfield->class = $this->className();$this->setupHooks($page, $field, $inputfield);return $inputfield;}*/}