mirror of
https://github.com/processwire/processwire.git
synced 2025-08-13 10:15:28 +02:00
Update FieldtypeImage and Pageimage to support new searchable width, height and ratio properties in the DB schema. These will become more useful over time as files are uploaded/saved and new info populates.
This commit is contained in:
@@ -41,6 +41,7 @@
|
||||
* @property-read string $alt Convenient alias for the 'description' property, unless overridden (since 3.0.125).
|
||||
* @property-read string $src Convenient alias for the 'url' property, unless overridden (since 3.0.125).
|
||||
* @property-read PagefileExtra $webp Access webp version of image (since 3.0.132)
|
||||
* @property-read float $ratio Image ratio where 1.0 is square, >1 is wider than tall, >2 is twice as wide as well, <1 is taller than wide, etc. (since 3.0.154+)
|
||||
*
|
||||
* Properties inherited from Pagefile
|
||||
* ==================================
|
||||
@@ -444,12 +445,30 @@ class Pageimage extends Pagefile {
|
||||
case 'sizeOptions':
|
||||
$value = $this->sizeOptions;
|
||||
break;
|
||||
case 'ratio':
|
||||
$value = $this->ratio();
|
||||
break;
|
||||
default:
|
||||
$value = parent::get($key);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set image info (internal use)
|
||||
*
|
||||
* #pw-internal
|
||||
*
|
||||
* @param array $info
|
||||
*
|
||||
*/
|
||||
public function setImageInfo(array $info) {
|
||||
// width and height less than 0 indicate percentage rather than pixels
|
||||
if(isset($info['width']) && $info['width'] < 0) $info['width'] = abs($info['width']) . '%';
|
||||
if(isset($info['height']) && $info['height'] < 0) $info['height'] = abs($info['height']) . '%';
|
||||
$this->imageInfo = array_merge($this->imageInfo, $info);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the image information with PHP’s getimagesize function and caches the result
|
||||
*
|
||||
@@ -462,36 +481,33 @@ class Pageimage extends Pagefile {
|
||||
*/
|
||||
public function getImageInfo($reset = false) {
|
||||
|
||||
if($reset) $checkImage = true;
|
||||
else if($this->imageInfo['width']) $checkImage = false;
|
||||
else $checkImage = true;
|
||||
|
||||
$imageInfo = $this->imageInfo;
|
||||
$filename = is_string($reset) && file_exists($reset) ? $reset : '';
|
||||
|
||||
if($checkImage || $filename) {
|
||||
if($this->ext == 'svg') {
|
||||
$info = $this->getImageInfoSVG($filename);
|
||||
$imageInfo['width'] = $info['width'];
|
||||
$imageInfo['height'] = $info['height'];
|
||||
} else {
|
||||
if($filename) {
|
||||
$info = @getimagesize($filename);
|
||||
} else {
|
||||
$info = @getimagesize($this->filename);
|
||||
}
|
||||
if((!$info || empty($info[0])) && !empty($this->sizeOptions['_width'])) {
|
||||
// on fail, fallback to size options that were requested for the image (if available)
|
||||
$imageInfo['width'] = $this->sizeOptions['_width'];
|
||||
$imageInfo['height'] = $this->sizeOptions['_height'];
|
||||
} else if($info) {
|
||||
$imageInfo['width'] = $info[0];
|
||||
$imageInfo['height'] = $info[1];
|
||||
}
|
||||
}
|
||||
if(!$filename) $this->imageInfo = $imageInfo;
|
||||
|
||||
if(!$reset && $imageInfo['width'] && !$filename) {
|
||||
return $imageInfo;
|
||||
}
|
||||
|
||||
if($this->ext == 'svg') {
|
||||
$imageInfo = array_merge($imageInfo, $this->getImageInfoSVG($filename));
|
||||
} else {
|
||||
if($filename) {
|
||||
$info = @getimagesize($filename);
|
||||
} else {
|
||||
$info = @getimagesize($this->filename);
|
||||
}
|
||||
if((!$info || empty($info[0])) && !empty($this->sizeOptions['_width'])) {
|
||||
// on fail, fallback to size options that were requested for the image (if available)
|
||||
$imageInfo['width'] = $this->sizeOptions['_width'];
|
||||
$imageInfo['height'] = $this->sizeOptions['_height'];
|
||||
} else if($info) {
|
||||
$imageInfo['width'] = $info[0];
|
||||
$imageInfo['height'] = $info[1];
|
||||
}
|
||||
}
|
||||
|
||||
if(!$filename) $this->imageInfo = $imageInfo;
|
||||
|
||||
return $imageInfo;
|
||||
}
|
||||
|
||||
@@ -1259,6 +1275,24 @@ class Pageimage extends Pagefile {
|
||||
return $this->size($adjustedWidth, $adjustedHeight, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ratio of width divided by height
|
||||
*
|
||||
* @return float
|
||||
* @since 3.0.154
|
||||
*
|
||||
*/
|
||||
public function ratio() {
|
||||
$width = $this->width();
|
||||
$height = $this->height();
|
||||
if($width === $height) return 1.0;
|
||||
$ratio = $width / $height;
|
||||
$ratio = round($ratio, 2);
|
||||
if($ratio > 99.99) $ratio = 99.99; // max allowed width>height ratio
|
||||
if($ratio < 0.01) $ratio = 0.01; // min allowed height>width ratio
|
||||
return $ratio;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PageimageVariations helper instancd
|
||||
*
|
||||
@@ -1686,6 +1720,27 @@ class Pageimage extends Pagefile {
|
||||
$extras['webp'] = $this->webp();
|
||||
return $extras;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace file with another
|
||||
*
|
||||
* Should be followed up with a save() to ensure related properties are also committed to DB.
|
||||
*
|
||||
* #pw-internal
|
||||
*
|
||||
* @param string $filename File to replace current one with
|
||||
* @param bool $move Move given $filename rather than copy? (default=true)
|
||||
* @return bool
|
||||
* @throws WireException
|
||||
* @since 3.0.154
|
||||
*
|
||||
*/
|
||||
public function replaceFile($filename, $move = true) {
|
||||
if(!parent::replaceFile($filename, $move)) return false;
|
||||
$this->getImageInfo(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Basic debug info
|
||||
|
@@ -9,23 +9,43 @@
|
||||
* /wire/core/Fieldtype.php
|
||||
* /wire/core/FieldtypeMulti.php
|
||||
*
|
||||
* ProcessWire 3.x, Copyright 2016 by Ryan Cramer
|
||||
* 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' => 101,
|
||||
'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);
|
||||
@@ -33,28 +53,130 @@ class FieldtypeImage extends FieldtypeFile {
|
||||
return $pageimages;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Pagefiles $pagefiles
|
||||
* @param string $filename
|
||||
* @return Pageimage|Pagefile
|
||||
*
|
||||
*/
|
||||
protected function getBlankPagefile(Pagefiles $pagefiles, $filename) {
|
||||
return $this->wire(new Pageimage($pagefiles, $filename));
|
||||
}
|
||||
|
||||
/*
|
||||
public function getInputfield(Page $page, Field $field) {
|
||||
|
||||
// even though we don't want this input field, call it anyway
|
||||
parent::getInputfield($page, $field);
|
||||
|
||||
$inputfield = $this->modules->get("InputfieldImage");
|
||||
$inputfield->class = $this->className();
|
||||
|
||||
$this->setupHooks($page, $field, $inputfield);
|
||||
|
||||
return $inputfield;
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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;
|
||||
$columns = array('width', 'height', 'ratio');
|
||||
foreach($columns as $column) {
|
||||
if(!$this->addColumn($field, $column, $schema)) $numErrors++;
|
||||
if($numErrors) break;
|
||||
}
|
||||
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'] = $pagefile->ratio;
|
||||
}
|
||||
|
||||
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 DB
|
||||
list($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
|
||||
@@ -102,6 +224,13 @@ class FieldtypeImage extends FieldtypeFile {
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Inputfields to configure fields using this Fieldtype
|
||||
*
|
||||
* @param Field $field
|
||||
* @return InputfieldWrapper
|
||||
*
|
||||
*/
|
||||
public function ___getConfigInputfields(Field $field) {
|
||||
|
||||
$inputfields = parent::___getConfigInputfields($field);
|
||||
@@ -112,6 +241,21 @@ class FieldtypeImage extends FieldtypeFile {
|
||||
return $inputfields;
|
||||
}
|
||||
|
||||
/*
|
||||
public function getInputfield(Page $page, Field $field) {
|
||||
|
||||
// even though we don't want this input field, call it anyway
|
||||
parent::getInputfield($page, $field);
|
||||
|
||||
$inputfield = $this->modules->get("InputfieldImage");
|
||||
$inputfield->class = $this->className();
|
||||
|
||||
$this->setupHooks($page, $field, $inputfield);
|
||||
|
||||
return $inputfield;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@@ -37,7 +37,7 @@ function setupProcessSave(fieldName, fileID, isNew) {
|
||||
var finished = false;
|
||||
var $inputfield = parent.jQuery('#wrap_Inputfield_' + fieldName);
|
||||
if(!$inputfield.length) {
|
||||
$inputfield = parent.jQuery('#' + fileID).closest('.Inputfield');
|
||||
$inputfield = parent.jQuery('#' + fileID).closest('.InputfieldImage');
|
||||
}
|
||||
$inputfield.trigger('reload');
|
||||
parent.jQuery('.Inputfield').on('reloaded', function() {
|
||||
|
File diff suppressed because one or more lines are too long
@@ -1159,6 +1159,8 @@ class ProcessPageEditImageSelect extends Process implements ConfigurableModule {
|
||||
// replace original image
|
||||
|
||||
if($this->original && $this->original != $image2->basename() && $original = $image->pagefiles->get($this->original)) {
|
||||
/** @var Pageimage $original */
|
||||
|
||||
$fileID = 'file_' . $original->hash;
|
||||
|
||||
if($rebuildVariations && $this->field->get('adminThumbs')) {
|
||||
@@ -1174,12 +1176,24 @@ class ProcessPageEditImageSelect extends Process implements ConfigurableModule {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// replace original image
|
||||
$target = $path . $this->original;
|
||||
$this->wire('files')->unlink($target);
|
||||
$this->wire('files')->rename($image2->filename(), $target);
|
||||
|
||||
if($original->replaceFile($image2->filename())) {
|
||||
$original->modified = time();
|
||||
$original->modifiedUser = $this->wire('user');
|
||||
/** @var FieldtypeFile $fieldtype */
|
||||
$fieldtype = $this->field->type;
|
||||
$fieldtype->saveFileCols($this->page, $this->field, $original, array(
|
||||
'filesize' => $original->filesize(),
|
||||
'modified' => $original->modified,
|
||||
'modified_users_id' => $original->modified_users_id,
|
||||
'width' => $original->width(),
|
||||
'height' => $original->height(),
|
||||
'ratio' => $original->ratio(),
|
||||
));
|
||||
}
|
||||
|
||||
$this->wire('pages')->uncacheAll();
|
||||
$page = $this->wire('pages')->get($this->page->id);
|
||||
/** @var Pageimages $value */
|
||||
|
Reference in New Issue
Block a user