mirror of
https://github.com/processwire/processwire.git
synced 2025-08-13 18:24:57 +02:00
Minor refactoring in ProcessPageEditImageSelect, plus update the executeVariations() method to also show webp extras when applicable.
This commit is contained in:
@@ -101,9 +101,11 @@ class Pageimage extends Pagefile {
|
||||
protected $original = null;
|
||||
|
||||
/**
|
||||
* Cached result of the getVariations() method
|
||||
* Cached result of the variations() method
|
||||
*
|
||||
* Don't reference this directly, because it won't be loaded unless requested, instead use the getVariations() method
|
||||
* Don't reference this directly, because it won't be loaded unless requested, instead use the variations() method
|
||||
*
|
||||
* @var PageimageVariations
|
||||
*
|
||||
*/
|
||||
private $variations = null;
|
||||
@@ -1188,6 +1190,19 @@ class Pageimage extends Pagefile {
|
||||
return $this->size($adjustedWidth, $adjustedHeight, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PageimageVariations helper instancd
|
||||
*
|
||||
* #pw-internal
|
||||
*
|
||||
* @return PageimageVariations
|
||||
*
|
||||
*/
|
||||
public function variations() {
|
||||
if($this->variations === null) $this->variations = new PageimageVariations($this);
|
||||
return $this->variations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all size variations of this image
|
||||
*
|
||||
@@ -1198,9 +1213,11 @@ class Pageimage extends Pagefile {
|
||||
*
|
||||
* @param array $options Optional, one or more options in an associative array of the following:
|
||||
* - `info` (bool): when true, method returns variation info arrays rather than Pageimage objects (default=false).
|
||||
* - `verbose` (bool): Return verbose array of info. If false, returns only filenames (default=true).
|
||||
* - `verbose` (bool|int): Return verbose array of info. If false, returns only filenames (default=true).
|
||||
* This option does nothing unless the `info` option is true. Also note that if verbose is false, then all options
|
||||
* following this one no longer apply (since it is no longer returning width/height info).
|
||||
* following this one no longer apply (since it is no longer returning width/height info).
|
||||
* When integer 1, returned info array also includes Pageimage variation options in 'pageimage' index of
|
||||
* returned arrays (since 3.0.137).
|
||||
* - `width` (int): only variations with given width will be returned
|
||||
* - `height` (int): only variations with given height will be returned
|
||||
* - `width>=` (int): only variations with width greater than or equal to given will be returned
|
||||
@@ -1219,97 +1236,7 @@ class Pageimage extends Pagefile {
|
||||
*
|
||||
*/
|
||||
public function getVariations(array $options = array()) {
|
||||
|
||||
if(!is_null($this->variations) && empty($options)) return $this->variations;
|
||||
|
||||
$defaults = array(
|
||||
'info' => false,
|
||||
'verbose' => true,
|
||||
);
|
||||
|
||||
$options = array_merge($defaults, $options);
|
||||
if(!$options['verbose'] && !$options['info']) $options['verbose'] = true; // non-verbose only allowed if info==true
|
||||
$variations = $options['info'] ? null : $this->wire(new Pageimages($this->pagefiles->page));
|
||||
$dir = new \DirectoryIterator($this->pagefiles->path);
|
||||
$infos = array();
|
||||
|
||||
// if suffix or noSuffix option contains space, convert it to suffixes or noSuffixes array option
|
||||
foreach(array('suffix', 'noSuffix') as $key) {
|
||||
if(!isset($options[$key])) continue;
|
||||
if(strpos(trim($options['suffix']), ' ') === false) continue;
|
||||
$keyPlural = $key . 'es';
|
||||
$value = isset($options[$keyPlural]) ? $options[$keyPlural] : array();
|
||||
$options[$keyPlural] = array_merge($value, explode(' ', trim($options[$key])));
|
||||
unset($options[$key]);
|
||||
}
|
||||
|
||||
foreach($dir as $file) {
|
||||
|
||||
if($file->isDir() || $file->isDot()) continue;
|
||||
|
||||
$info = $this->isVariation($file->getFilename(), array('verbose' => $options['verbose']));
|
||||
if(!$info) continue;
|
||||
|
||||
if($options['info'] && !$options['verbose']) {
|
||||
$infos[] = $info;
|
||||
continue;
|
||||
}
|
||||
|
||||
$allow = true;
|
||||
|
||||
foreach($options as $option => $value) {
|
||||
switch($option) {
|
||||
case 'width': $allow = $info['width'] == $value; break;
|
||||
case 'width>=': $allow = $info['width'] >= $value; break;
|
||||
case 'width<=': $allow = $info['width'] <= $value; break;
|
||||
case 'height': $allow = $info['height'] == $value; break;
|
||||
case 'height>=': $allow = $info['height'] >= $value; break;
|
||||
case 'height<=': $allow = $info['height'] <= $value; break;
|
||||
case 'name': $allow = stripos($file->getBasename(), $value) !== false; break;
|
||||
case 'noName': $allow = stripos($file->getBasename(), $value) === false; break;
|
||||
case 'regexName': $allow = preg_match($value, $file->getBasename()); break;
|
||||
case 'suffix': $allow = in_array($value, $info['suffix']); break;
|
||||
case 'noSuffix': $allow = !in_array($value, $info['suffix']); break;
|
||||
case 'suffixes':
|
||||
// any one of given suffixes will allow the variation
|
||||
$allow = false;
|
||||
foreach($value as $suffix) {
|
||||
$allow = in_array($suffix, $info['suffix']);
|
||||
if($allow) break;
|
||||
}
|
||||
break;
|
||||
case 'noSuffixes':
|
||||
// any one of the given suffixes will disallow the variation
|
||||
$allow = true;
|
||||
foreach($value as $noSuffix) {
|
||||
if(!in_array($noSuffix, $info['suffix'])) continue;
|
||||
$allow = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(!$allow) break;
|
||||
}
|
||||
|
||||
if(!$allow) continue;
|
||||
|
||||
if(!empty($options['info'])) {
|
||||
$infos[$file->getBasename()] = $info;
|
||||
} else {
|
||||
$pageimage = clone $this;
|
||||
$pathname = $file->getPathname();
|
||||
if(DIRECTORY_SEPARATOR != '/') $pathname = str_replace(DIRECTORY_SEPARATOR, '/', $pathname);
|
||||
$pageimage->setFilename($pathname);
|
||||
$pageimage->setOriginal($this);
|
||||
$variations->add($pageimage);
|
||||
}
|
||||
}
|
||||
|
||||
if(!empty($options['info'])) return $infos;
|
||||
|
||||
if(empty($options)) $this->variations = $variations;
|
||||
|
||||
return $variations;
|
||||
return $this->variations()->find($options);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1343,118 +1270,7 @@ class Pageimage extends Pagefile {
|
||||
*
|
||||
*/
|
||||
public function ___rebuildVariations($mode = 0, array $suffix = array(), array $options = array()) {
|
||||
|
||||
$skipped = array();
|
||||
$rebuilt = array();
|
||||
$errors = array();
|
||||
$reasons = array();
|
||||
$options['forceNew'] = true;
|
||||
|
||||
foreach($this->getVariations(array('info' => true)) as $info) {
|
||||
|
||||
$o = $options;
|
||||
unset($o['cropping']);
|
||||
$skip = false;
|
||||
$name = $info['name'];
|
||||
|
||||
if($info['crop'] && !$mode) {
|
||||
// skip crops when mode is 0
|
||||
$reasons[$name] = "$name: Crop is $info[crop] and mode is 0";
|
||||
$skip = true;
|
||||
|
||||
} else if(count($info['suffix'])) {
|
||||
// check suffixes
|
||||
foreach($info['suffix'] as $k => $s) {
|
||||
if($s === 'hidpi') {
|
||||
// allow hidpi to passthru
|
||||
$o['hidpi'] = true;
|
||||
} else if($s == 'is') {
|
||||
// this is a known core suffix that we allow
|
||||
} else if(strpos($s, 'cropx') === 0) {
|
||||
// skip cropx suffix (already known from $info[crop])
|
||||
unset($info['suffix'][$k]);
|
||||
continue;
|
||||
} else if(strpos($s, 'pid') === 0 && preg_match('/^pid\d+$/', $s)) {
|
||||
// allow pid123 to pass through
|
||||
} else if(in_array($s, $suffix)) {
|
||||
// suffix is one provided in $suffix argument
|
||||
if($mode == 2) {
|
||||
// mode 2 where $suffix is an exclusion list
|
||||
$skip = true;
|
||||
$reasons[$name] = "$name: Suffix '$s' is one provided in exclusion list (mode==true)";
|
||||
} else {
|
||||
// allowed suffix
|
||||
}
|
||||
} else {
|
||||
// image has suffix not specified in $suffix argument
|
||||
if($mode == 0 || $mode == 1 || $mode == 3) {
|
||||
$skip = true;
|
||||
$reasons[$name] = "$name: Image has suffix '$s' not provided in allowed list: " . implode(', ', $suffix);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($mode == 4 && ($info['width'] == 0 || $info['height'] == 0)) {
|
||||
// skip images that don't specify both width and height
|
||||
$skip = true;
|
||||
}
|
||||
|
||||
if($skip) {
|
||||
$skipped[] = $name;
|
||||
continue;
|
||||
}
|
||||
|
||||
// rebuild the variation
|
||||
$o['forceNew'] = true;
|
||||
$o['suffix'] = $info['suffix'];
|
||||
if(is_file($info['path'])) $this->wire('files')->unlink($info['path'], true);
|
||||
|
||||
/*
|
||||
if(!$info['width'] && $info['actualWidth']) {
|
||||
$info['width'] = $info['actualWidth'];
|
||||
$options['nameWidth'] = 0;
|
||||
}
|
||||
if(!$info['height'] && $info['actualHeight']) {
|
||||
$info['height'] = $info['actualHeight'];
|
||||
$options['nameHeight'] = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
if($info['crop'] && preg_match('/^x(\d+)y(\d+)$/', $info['crop'], $matches)) {
|
||||
// dimensional cropping info contained in filename
|
||||
$cropX = (int) $matches[1];
|
||||
$cropY = (int) $matches[2];
|
||||
$variation = $this->crop($cropX, $cropY, $info['width'], $info['height'], $options);
|
||||
|
||||
} else if($info['crop']) {
|
||||
// direct cropping info contained in filename
|
||||
$options['cropping'] = $info['crop'];
|
||||
$variation = $this->size($info['width'], $info['height'], $options);
|
||||
|
||||
} else if($this->hasFocus) {
|
||||
// crop to focus area, which the size() method will determine on its own
|
||||
$variation = $this->size($info['width'], $info['height'], $options);
|
||||
|
||||
} else {
|
||||
// no crop, no focus, just resize
|
||||
$variation = $this->size($info['width'], $info['height'], $options);
|
||||
}
|
||||
|
||||
if($variation) {
|
||||
if($variation->name != $name) rename($variation->filename(), $info['path']);
|
||||
$rebuilt[] = $name;
|
||||
} else {
|
||||
$errors[] = $name;
|
||||
}
|
||||
}
|
||||
|
||||
return array(
|
||||
'rebuilt' => $rebuilt,
|
||||
'skipped' => $skipped,
|
||||
'reasons' => $reasons,
|
||||
'errors' => $errors
|
||||
);
|
||||
return $this->variations()->rebuild($mode, $suffix, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1488,153 +1304,7 @@ class Pageimage extends Pagefile {
|
||||
*
|
||||
*/
|
||||
public function ___isVariation($basename, $options = array()) {
|
||||
|
||||
$defaults = array(
|
||||
'allowSelf' => false,
|
||||
'verbose' => true,
|
||||
);
|
||||
|
||||
if(!is_array($options)) $options = array('allowSelf' => (bool) $options);
|
||||
$options = array_merge($defaults, $options);
|
||||
|
||||
static $level = 0;
|
||||
$variationName = basename($basename);
|
||||
$originalName = $this->basename;
|
||||
$info = array();
|
||||
|
||||
// that that everything from the beginning up to the first period is exactly the same
|
||||
// otherwise, they are different source files
|
||||
$test1 = substr($variationName, 0, strpos($variationName, '.'));
|
||||
$test2 = substr($originalName, 0, strpos($originalName, '.'));
|
||||
if($test1 !== $test2) return false;
|
||||
|
||||
// remove extension from originalName
|
||||
$originalName = basename($originalName, "." . $this->ext());
|
||||
|
||||
// if originalName is already a variation filename, remove the variation info from it.
|
||||
// reduce to original name, i.e. all info after (and including) a period
|
||||
if(strpos($originalName, '.') && preg_match('/^([^.]+)\.(?:\d+x\d+|-[_a-z0-9]+)/', $originalName, $matches)) {
|
||||
$originalName = $matches[1];
|
||||
}
|
||||
|
||||
// if file is the same as the original, then it's not a variation
|
||||
if(!$options['allowSelf'] && $variationName == $this->basename) return false;
|
||||
|
||||
// if file doesn't start with the original name then it's not a variation
|
||||
if(strpos($variationName, $originalName) !== 0) return false;
|
||||
|
||||
// get down to the meat and the base
|
||||
// meat is the part of the filename containing variation info like dimensions, crop, suffix, etc.
|
||||
// base is the part before that, which may include parent meat
|
||||
$pos = strrpos($variationName, '.'); // get extension
|
||||
$ext = substr($variationName, $pos);
|
||||
$base = substr($variationName, 0, $pos); // get without extension
|
||||
$rpos = strrpos($base, '.'); // get last data chunk after dot
|
||||
if($rpos !== false) {
|
||||
$meat = substr($base, $rpos+1) . $ext; // the part of the filename we're interested in
|
||||
$base = substr($base, 0, $rpos); // the rest of the filename
|
||||
$parent = "$base." . $this->ext();
|
||||
} else {
|
||||
$meat = $variationName;
|
||||
$parent = null;
|
||||
}
|
||||
|
||||
// identify parent and any parent suffixes
|
||||
$suffixAll = array();
|
||||
if($options['verbose']) {
|
||||
while(($pos = strrpos($base, '.')) !== false) {
|
||||
$part = substr($base, $pos + 1);
|
||||
$base = substr($base, 0, $pos);
|
||||
while(($rpos = strrpos($part, '-')) !== false) {
|
||||
$suffixAll[] = substr($part, $rpos + 1);
|
||||
$part = substr($part, 0, $rpos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// variation name with size dimensions and optionally suffix
|
||||
$re1 = '/^' .
|
||||
'(\d+)x(\d+)' . // 50x50
|
||||
'([pd]\d+x\d+|[a-z]{1,2})?' . // nw or p30x40 or d30x40
|
||||
'(?:-([-_a-z0-9]+))?' . // -suffix1 or -suffix1-suffix2, etc.
|
||||
'\.' . $this->ext() . // .jpg
|
||||
'$/';
|
||||
|
||||
// variation name with suffix only
|
||||
$re2 = '/^' .
|
||||
'-([-_a-z0-9]+)' . // suffix1 or suffix1-suffix2, etc.
|
||||
'(?:\.' . // optional extras for dimensions/crop, starts with period
|
||||
'(\d+)x(\d+)' . // optional 50x50
|
||||
'([pd]\d+x\d+|[a-z]{1,2})?' . // nw or p30x40 or d30x40
|
||||
')?' .
|
||||
'\.' . $this->ext() . // .jpg
|
||||
'$/';
|
||||
|
||||
// if regex does not match, return false
|
||||
if(preg_match($re1, $meat, $matches)) {
|
||||
// this is a variation with dimensions, return array of info
|
||||
if($options['verbose']) $info = array(
|
||||
'name' => $basename,
|
||||
'url' => $this->pagefiles->url . $basename,
|
||||
'path' => $this->pagefiles->path . $basename,
|
||||
'original' => $originalName . '.' . $this->ext(),
|
||||
'width' => (int) $matches[1],
|
||||
'height' => (int) $matches[2],
|
||||
'crop' => (isset($matches[3]) ? $matches[3] : ''),
|
||||
'suffix' => (isset($matches[4]) ? explode('-', $matches[4]) : array()),
|
||||
);
|
||||
|
||||
} else if(preg_match($re2, $meat, $matches)) {
|
||||
|
||||
// this is a variation only with suffix
|
||||
if($options['verbose']) $info = array(
|
||||
'name' => $basename,
|
||||
'url' => $this->pagefiles->url . $basename,
|
||||
'path' => $this->pagefiles->path . $basename,
|
||||
'original' => $originalName . '.' . $this->ext(),
|
||||
'width' => (isset($matches[2]) ? (int) $matches[2] : 0),
|
||||
'height' => (isset($matches[3]) ? (int) $matches[3] : 0),
|
||||
'crop' => (isset($matches[4]) ? $matches[4] : ''),
|
||||
'suffix' => explode('-', $matches[1]),
|
||||
);
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
// if not in verbose mode, just return variation basename
|
||||
if(!$options['verbose']) return $variationName;
|
||||
|
||||
$actualInfo = $this->getImageInfo($info['path']);
|
||||
$info['actualWidth'] = $actualInfo['width'];
|
||||
$info['actualHeight'] = $actualInfo['height'];
|
||||
$info['hidpiWidth'] = $this->hidpiWidth(0, $info['actualWidth']);
|
||||
$info['hidpiHeight'] = $this->hidpiWidth(0, $info['actualHeight']);
|
||||
|
||||
if(empty($info['crop'])) {
|
||||
// attempt to extract crop info from suffix
|
||||
foreach($info['suffix'] as $key => $suffix) {
|
||||
if(strpos($suffix, 'cropx') === 0) {
|
||||
$info['crop'] = ltrim($suffix, 'crop'); // i.e. x123y456
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($parent) {
|
||||
// suffixAll includes all parent suffix in addition to current suffix
|
||||
if(!$level) $info['suffixAll'] = array_unique(array_merge($info['suffix'], $suffixAll));
|
||||
// parent property is set with more variation info, when available
|
||||
$level++;
|
||||
$info['parentName'] = $parent;
|
||||
$info['parent'] = $this->isVariation($parent);
|
||||
$level--;
|
||||
}
|
||||
|
||||
if(!$this->original) {
|
||||
$this->original = $this->pagefiles->get($info['original']);
|
||||
}
|
||||
|
||||
return $info;
|
||||
return $this->variations()->getInfo($basename, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1649,42 +1319,7 @@ class Pageimage extends Pagefile {
|
||||
*
|
||||
*/
|
||||
public function removeVariations(array $options = array()) {
|
||||
|
||||
$defaults = array(
|
||||
'dryRun' => false,
|
||||
'getFiles' => false
|
||||
);
|
||||
|
||||
$variations = $this->getVariations($options);
|
||||
if(!empty($options['dryrun'])) $defaults['dryRun'] = $options['dryrun']; // case insurance
|
||||
$options = array_merge($defaults, $options); // placement after getVariations() intended
|
||||
$deletedFiles = array();
|
||||
|
||||
/** @var WireFileTools $files */
|
||||
$files = $this->wire('files');
|
||||
|
||||
foreach($variations as $variation) {
|
||||
$filename = $variation->filename;
|
||||
if(!is_file($filename)) continue;
|
||||
if($options['dryRun']) {
|
||||
$success = true;
|
||||
} else {
|
||||
$success = $files->unlink($filename, true);
|
||||
}
|
||||
if($success) $deletedFiles[] = $filename;
|
||||
|
||||
foreach($this->extras() as $extra) {
|
||||
if($options['dryRun']) {
|
||||
$deletedFiles[] = $extra->filename();
|
||||
} else if($extra->unlink()) {
|
||||
$deletedFiles[] = $extra->filename();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!$options['dryRun']) $this->variations = null;
|
||||
|
||||
return ($options['dryRun'] || $options['getFiles'] ? $deletedFiles : $this);
|
||||
return $this->variations()->remove($options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
621
wire/core/PageimageVariations.php
Normal file
621
wire/core/PageimageVariations.php
Normal file
@@ -0,0 +1,621 @@
|
||||
<?php namespace ProcessWire;
|
||||
|
||||
/**
|
||||
* ProcessWire PageimageVariations
|
||||
*
|
||||
* Helper class for Pageimage that handles variation collection methods
|
||||
*
|
||||
* ProcessWire 3.x, Copyright 2019 by Ryan Cramer
|
||||
* https://processwire.com
|
||||
*
|
||||
* @since 3.0.137
|
||||
*
|
||||
*/
|
||||
|
||||
class PageimageVariations extends Wire implements \IteratorAggregate, \Countable {
|
||||
|
||||
/**
|
||||
* @var Pageimage
|
||||
*
|
||||
*/
|
||||
protected $pageimage;
|
||||
|
||||
/**
|
||||
* @var Pagefiles|Pageimages
|
||||
*
|
||||
*/
|
||||
protected $pagefiles;
|
||||
|
||||
/**
|
||||
* @var Pageimages|null
|
||||
*
|
||||
*/
|
||||
protected $variations = null;
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param Pageimage $pageimage
|
||||
*
|
||||
*/
|
||||
public function __construct(Pageimage $pageimage) {
|
||||
$this->pageimage = $pageimage;
|
||||
$this->pagefiles = $pageimage->pagefiles;
|
||||
$pageimage->wire($this);
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function getIterator() {
|
||||
return $this->find();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a total or filtered count of variations
|
||||
*
|
||||
* This method is also here to implement the Countable interface.
|
||||
*
|
||||
* @param array $options See options for find() emthod
|
||||
* @return int
|
||||
*
|
||||
*/
|
||||
public function count($options = array()) {
|
||||
if($this->variations) {
|
||||
$count = $this->variations->count();
|
||||
} else {
|
||||
$options['count'] = true;
|
||||
$count = $this->find($options);
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a file name (basename), return array of info if this is a variation for this instance’s file, or false if not.
|
||||
*
|
||||
* Returned array includes the following indexes:
|
||||
*
|
||||
* - `original` (string): Original basename
|
||||
* - `url` (string): URL to image
|
||||
* - `path` (string): Full path + filename to image
|
||||
* - `width` (int): Specified width in filename
|
||||
* - `height` (int): Specified height in filename
|
||||
* - `actualWidth` (int): Actual width when checked manually
|
||||
* - `actualHeight` (int): Acual height when checked manually
|
||||
* - `crop` (string): Cropping info string or blank if none
|
||||
* - `suffix` (array): Array of suffixes
|
||||
*
|
||||
* The following are only present if variation is based on another variation, and thus has a parent variation
|
||||
* image between it and the original:
|
||||
*
|
||||
* - `suffixAll` (array): Contains all suffixes including among parent variations
|
||||
* - `parent` (array): Variation info array of direct parent variation file
|
||||
*
|
||||
* @param string $basename Filename to check (basename, which excludes path)
|
||||
* @param array|bool $options Array of options to modify behavior, or boolean to only specify `allowSelf` option.
|
||||
* - `allowSelf` (bool): When true, it will return variation info even if same as current Pageimage. (default=false)
|
||||
* - `verbose` (bool): Return verbose array of info? If false, just returns basename (string) or false. (default=true)
|
||||
* @return bool|string|array Returns false if not a variation, or array (verbose) or string (non-verbose) of info if it is.
|
||||
*
|
||||
*/
|
||||
public function getInfo($basename, $options = array()) {
|
||||
|
||||
$defaults = array(
|
||||
'allowSelf' => false,
|
||||
'verbose' => true,
|
||||
);
|
||||
|
||||
if(!is_array($options)) $options = array('allowSelf' => (bool) $options);
|
||||
$options = array_merge($defaults, $options);
|
||||
|
||||
static $level = 0;
|
||||
$variationName = basename($basename);
|
||||
$originalName = $this->pageimage->basename;
|
||||
|
||||
// that that everything from the beginning up to the first period is exactly the same
|
||||
// otherwise, they are different source files
|
||||
$test1 = substr($variationName, 0, strpos($variationName, '.'));
|
||||
$test2 = substr($originalName, 0, strpos($originalName, '.'));
|
||||
if($test1 !== $test2) return false;
|
||||
|
||||
// remove extension from originalName
|
||||
$originalName = basename($originalName, "." . $this->pageimage->ext());
|
||||
|
||||
// if originalName is already a variation filename, remove the variation info from it.
|
||||
// reduce to original name, i.e. all info after (and including) a period
|
||||
if(strpos($originalName, '.') && preg_match('/^([^.]+)\.(?:\d+x\d+|-[_a-z0-9]+)/', $originalName, $matches)) {
|
||||
$originalName = $matches[1];
|
||||
}
|
||||
|
||||
// if file is the same as the original, then it's not a variation
|
||||
if(!$options['allowSelf'] && $variationName == $this->pageimage->basename) return false;
|
||||
|
||||
// if file doesn't start with the original name then it's not a variation
|
||||
if(strpos($variationName, $originalName) !== 0) return false;
|
||||
|
||||
// get down to the meat and the base
|
||||
// meat is the part of the filename containing variation info like dimensions, crop, suffix, etc.
|
||||
// base is the part before that, which may include parent meat
|
||||
$pos = strrpos($variationName, '.'); // get extension
|
||||
$ext = substr($variationName, $pos);
|
||||
$base = substr($variationName, 0, $pos); // get without extension
|
||||
$rpos = strrpos($base, '.'); // get last data chunk after dot
|
||||
|
||||
if($rpos !== false) {
|
||||
$meat = substr($base, $rpos+1) . $ext; // the part of the filename we're interested in
|
||||
$base = substr($base, 0, $rpos); // the rest of the filename
|
||||
$parent = "$base." . $this->pageimage->ext();
|
||||
} else {
|
||||
$meat = $variationName;
|
||||
$parent = null;
|
||||
}
|
||||
|
||||
// identify parent and any parent suffixes
|
||||
$suffixAll = array();
|
||||
if($options['verbose']) {
|
||||
while(($pos = strrpos($base, '.')) !== false) {
|
||||
$part = substr($base, $pos + 1);
|
||||
$base = substr($base, 0, $pos);
|
||||
while(($rpos = strrpos($part, '-')) !== false) {
|
||||
$suffixAll[] = substr($part, $rpos + 1);
|
||||
$part = substr($part, 0, $rpos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// variation name with size dimensions and optionally suffix
|
||||
$re1 = '/^' .
|
||||
'(\d+)x(\d+)' . // 50x50
|
||||
'([pd]\d+x\d+|[a-z]{1,2})?' . // nw or p30x40 or d30x40
|
||||
'(?:-([-_a-z0-9]+))?' . // -suffix1 or -suffix1-suffix2, etc.
|
||||
'\.' . $this->pageimage->ext() .
|
||||
'$/';
|
||||
|
||||
// variation name with suffix only
|
||||
$re2 = '/^' .
|
||||
'-([-_a-z0-9]+)' . // suffix1 or suffix1-suffix2, etc.
|
||||
'(?:\.' . // optional extras for dimensions/crop, starts with period
|
||||
'(\d+)x(\d+)' . // optional 50x50
|
||||
'([pd]\d+x\d+|[a-z]{1,2})?' . // nw or p30x40 or d30x40
|
||||
')?' .
|
||||
'\.' . $this->pageimage->ext() .
|
||||
'$/';
|
||||
|
||||
// if regex does not match, return false
|
||||
if(preg_match($re1, $meat, $matches)) {
|
||||
|
||||
// this is a variation with dimensions, return array of info
|
||||
$width = (int) $matches[1];
|
||||
$height = (int) $matches[2];
|
||||
$crop = isset($matches[3]) ? $matches[3] : '';
|
||||
$suffix = isset($matches[4]) ? explode('-', $matches[4]) : array();
|
||||
|
||||
} else if(preg_match($re2, $meat, $matches)) {
|
||||
|
||||
// this is a variation only with suffix
|
||||
$width = isset($matches[2]) ? (int) $matches[2] : 0;
|
||||
$height = isset($matches[3]) ? (int) $matches[3] : 0;
|
||||
$crop = isset($matches[4]) ? $matches[4] : '';
|
||||
$suffix = explode('-', $matches[1]);
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
// if not in verbose mode, just return variation basename
|
||||
if(!$options['verbose']) return $variationName;
|
||||
|
||||
$path = $this->pagefiles->path . $basename;
|
||||
$actualInfo = $this->pageimage->getImageInfo($path);
|
||||
|
||||
$info = array(
|
||||
'name' => $basename,
|
||||
'url' => $this->pagefiles->url . $basename,
|
||||
'path' => $path,
|
||||
'original' => $originalName . '.' . $this->pageimage->ext(),
|
||||
'width' => $width,
|
||||
'height' => $height,
|
||||
'crop' => $crop,
|
||||
'suffix' => $suffix,
|
||||
'suffixAll' => array(), // present only when image has a parent variation
|
||||
'actualWidth' => $actualInfo['width'],
|
||||
'actualHeight' => $actualInfo['height'],
|
||||
'hidpiWidth' => $this->pageimage->hidpiWidth(0, $actualInfo['width']),
|
||||
'hidpiHeight' => $this->pageimage->hidpiWidth(0, $actualInfo['height']),
|
||||
'parentName' => '', // present only when image has a parent variation
|
||||
'parent' => null, // present only when image has a parent variation
|
||||
'webpUrl' => '',
|
||||
'webpPath' => '',
|
||||
);
|
||||
|
||||
foreach($this->pageimage->extras() as $name => $extra) {
|
||||
if(!$extra->exists()) continue;
|
||||
$info["{$name}Url"] = $extra->url(false);
|
||||
$info["{$name}Path"] = $extra->filename();
|
||||
}
|
||||
|
||||
if(empty($info['crop'])) {
|
||||
// attempt to extract crop info from suffix
|
||||
foreach($info['suffix'] as $key => $suffix) {
|
||||
if(strpos($suffix, 'cropx') === 0) {
|
||||
$info['crop'] = ltrim($suffix, 'crop'); // i.e. x123y456
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($parent) {
|
||||
// suffixAll includes all parent suffix in addition to current suffix
|
||||
if(!$level) $info['suffixAll'] = array_unique(array_merge($info['suffix'], $suffixAll));
|
||||
// parent property is set with more variation info, when available
|
||||
$level++;
|
||||
$info['parentName'] = $parent;
|
||||
$info['parent'] = $this->getInfo($parent);
|
||||
$level--;
|
||||
} else {
|
||||
unset($info['parent'], $info['parentName'], $info['suffixAll']);
|
||||
}
|
||||
|
||||
if(!$this->pageimage->original) {
|
||||
$this->pageimage->setOriginal($this->pagefiles->get($info['original']));
|
||||
}
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all size variations of this image
|
||||
*
|
||||
* This is useful after a delete of an image (for example). This method can be used to track down all the
|
||||
* child files that also need to be deleted.
|
||||
*
|
||||
* @param array $options Optional, one or more options in an associative array of the following:
|
||||
* - `info` (bool): when true, method returns variation info arrays rather than Pageimage objects (default=false).
|
||||
* - `count` (bool): when true, only a count of variations is returned (default=false).
|
||||
* - `verbose` (bool|int): Return verbose array of info. If false, returns only filenames (default=true).
|
||||
* This option does nothing unless the `info` option is true. Also note that if verbose is false, then all options
|
||||
* following this one no longer apply (since it is no longer returning width/height info).
|
||||
* When integer 1, returned info array also includes Pageimage variation options in 'pageimage' index of
|
||||
* returned arrays (since 3.0.137).
|
||||
* - `width` (int): only variations with given width will be returned
|
||||
* - `height` (int): only variations with given height will be returned
|
||||
* - `width>=` (int): only variations with width greater than or equal to given will be returned
|
||||
* - `height>=` (int): only variations with height greater than or equal to given will be returned
|
||||
* - `width<=` (int): only variations with width less than or equal to given will be returned
|
||||
* - `height<=` (int): only variations with height less than or equal to given will be returned
|
||||
* - `suffix` (string): only variations having the given suffix will be returned
|
||||
* - `suffixes` (array): only variations having one of the given suffixes will be returned
|
||||
* - `noSuffix` (string): exclude variations having this suffix
|
||||
* - `noSuffixes` (array): exclude variations having any of these suffixes
|
||||
* - `name` (string): only variations containing this text in filename will be returned (case insensitive)
|
||||
* - `noName` (string): only variations NOT containing this text in filename will be returned (case insensitive)
|
||||
* - `regexName` (string): only variations that match this PCRE regex will be returned
|
||||
* @return Pageimages|array|int Returns Pageimages array of Pageimage instances.
|
||||
* Only returns regular array if provided `$options['info']` is true.
|
||||
* Returns integer if count option is specified.
|
||||
*
|
||||
*/
|
||||
public function find(array $options = array()) {
|
||||
|
||||
if(!is_null($this->variations) && empty($options)) return $this->variations;
|
||||
|
||||
$defaults = array(
|
||||
'info' => false,
|
||||
'verbose' => true,
|
||||
'count' => false,
|
||||
);
|
||||
|
||||
$options = array_merge($defaults, $options);
|
||||
if($options['count']) {
|
||||
$options['verbose'] = false;
|
||||
$options['info'] = false;
|
||||
} else if(!$options['verbose'] && !$options['info']) {
|
||||
$options['verbose'] = true; // non-verbose only allowed if info==true
|
||||
}
|
||||
|
||||
$variations = null;
|
||||
$dir = new \DirectoryIterator($this->pagefiles->path);
|
||||
$infos = array();
|
||||
$count = 0;
|
||||
|
||||
if(!$options['info'] && $options['count']) {
|
||||
$variations = $this->wire(new Pageimages($this->pagefiles->page));
|
||||
}
|
||||
|
||||
// if suffix or noSuffix option contains space, convert it to suffixes or noSuffixes array option
|
||||
foreach(array('suffix', 'noSuffix') as $key) {
|
||||
if(!isset($options[$key])) continue;
|
||||
if(strpos(trim($options['suffix']), ' ') === false) continue;
|
||||
$keyPlural = $key . 'es';
|
||||
$value = isset($options[$keyPlural]) ? $options[$keyPlural] : array();
|
||||
$options[$keyPlural] = array_merge($value, explode(' ', trim($options[$key])));
|
||||
unset($options[$key]);
|
||||
}
|
||||
|
||||
foreach($dir as $file) {
|
||||
|
||||
if($file->isDir() || $file->isDot()) continue;
|
||||
|
||||
$info = $this->getInfo($file->getFilename(), array('verbose' => $options['verbose']));
|
||||
if(!$info) continue;
|
||||
|
||||
if($options['info'] && !$options['verbose']) {
|
||||
$infos[] = $info;
|
||||
continue;
|
||||
}
|
||||
|
||||
$allow = true;
|
||||
|
||||
foreach($options as $option => $value) {
|
||||
switch($option) {
|
||||
case 'width': $allow = $info['width'] == $value; break;
|
||||
case 'width>=': $allow = $info['width'] >= $value; break;
|
||||
case 'width<=': $allow = $info['width'] <= $value; break;
|
||||
case 'height': $allow = $info['height'] == $value; break;
|
||||
case 'height>=': $allow = $info['height'] >= $value; break;
|
||||
case 'height<=': $allow = $info['height'] <= $value; break;
|
||||
case 'name': $allow = stripos($file->getBasename(), $value) !== false; break;
|
||||
case 'noName': $allow = stripos($file->getBasename(), $value) === false; break;
|
||||
case 'regexName': $allow = preg_match($value, $file->getBasename()); break;
|
||||
case 'suffix': $allow = in_array($value, $info['suffix']); break;
|
||||
case 'noSuffix': $allow = !in_array($value, $info['suffix']); break;
|
||||
case 'suffixes':
|
||||
// any one of given suffixes will allow the variation
|
||||
$allow = false;
|
||||
foreach($value as $suffix) {
|
||||
$allow = in_array($suffix, $info['suffix']);
|
||||
if($allow) break;
|
||||
}
|
||||
break;
|
||||
case 'noSuffixes':
|
||||
// any one of the given suffixes will disallow the variation
|
||||
$allow = true;
|
||||
foreach($value as $noSuffix) {
|
||||
if(!in_array($noSuffix, $info['suffix'])) continue;
|
||||
$allow = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(!$allow) break;
|
||||
}
|
||||
|
||||
if(!$allow) continue;
|
||||
|
||||
$basename = $file->getBasename();
|
||||
|
||||
if($options['count']) {
|
||||
$count++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(empty($options['info']) || $options['verbose'] === 1) {
|
||||
$pageimage = clone $this->pageimage;
|
||||
$pathname = $file->getPathname();
|
||||
if(DIRECTORY_SEPARATOR != '/') $pathname = str_replace(DIRECTORY_SEPARATOR, '/', $pathname);
|
||||
$pageimage->setFilename($pathname);
|
||||
$pageimage->setOriginal($this->pageimage);
|
||||
if($options['verbose'] === 1) {
|
||||
$info['pageimage'] = $pageimage;
|
||||
} else {
|
||||
$variations->add($pageimage);
|
||||
}
|
||||
}
|
||||
if(!empty($options['info'])) {
|
||||
$infos[$basename] = $info;
|
||||
}
|
||||
}
|
||||
|
||||
if($options['count']) return $count;
|
||||
if(!empty($options['info'])) return $infos;
|
||||
if(empty($options)) $this->variations = $variations;
|
||||
|
||||
return $variations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rebuilds variations of this image
|
||||
*
|
||||
* By default, this excludes crops and images with suffixes, but can be overridden with the `$mode` and `$suffix` arguments.
|
||||
*
|
||||
* **Options for $mode argument**
|
||||
*
|
||||
* - `0` (int): Rebuild only non-suffix, non-crop variations, and those w/suffix specified in $suffix argument. ($suffix is INCLUSION list)
|
||||
* - `1` (int): Rebuild all non-suffix variations, and those w/suffix specifed in $suffix argument. ($suffix is INCLUSION list)
|
||||
* - `2` (int): Rebuild all variations, except those with suffix specified in $suffix argument. ($suffix is EXCLUSION list)
|
||||
* - `3` (int): Rebuild only variations specified in the $suffix argument. ($suffix is ONLY-INCLUSION list)
|
||||
* - `4` (int): Rebuild only non-proportional, non-crop variations (variations that specify both width and height)
|
||||
*
|
||||
* Mode 0 is the only truly safe mode, as in any other mode there are possibilities that the resulting
|
||||
* rebuild of the variation may not be exactly what was intended. The issues with other modes primarily
|
||||
* arise when the suffix means something about the technical details of the produced image, or when
|
||||
* rebuilding variations that include crops from an original image that has since changed dimensions or crops.
|
||||
*
|
||||
* @param int $mode See the options for $mode argument above (default=0).
|
||||
* @param array $suffix Optional argument to specify suffixes to include or exclude (according to $mode).
|
||||
* @param array $options See $options for `Pageimage::size()` for details.
|
||||
* @return array Returns an associative array with with the following indexes:
|
||||
* - `rebuilt` (array): Names of files that were rebuilt.
|
||||
* - `skipped` (array): Names of files that were skipped.
|
||||
* - `errors` (array): Names of files that had errors.
|
||||
* - `reasons` (array): Reasons why files were skipped or had errors, associative array indexed by file name.
|
||||
*
|
||||
*/
|
||||
public function rebuild($mode = 0, array $suffix = array(), array $options = array()) {
|
||||
|
||||
$skipped = array();
|
||||
$rebuilt = array();
|
||||
$errors = array();
|
||||
$reasons = array();
|
||||
$options['forceNew'] = true;
|
||||
|
||||
foreach($this->find(array('info' => true)) as $info) {
|
||||
|
||||
$o = $options;
|
||||
unset($o['cropping']);
|
||||
$skip = false;
|
||||
$name = $info['name'];
|
||||
$hadWebp = false;
|
||||
|
||||
if($info['crop'] && !$mode) {
|
||||
// skip crops when mode is 0
|
||||
$reasons[$name] = "$name: Crop is $info[crop] and mode is 0";
|
||||
$skip = true;
|
||||
|
||||
} else if(count($info['suffix'])) {
|
||||
// check suffixes
|
||||
foreach($info['suffix'] as $k => $s) {
|
||||
if($s === 'hidpi') {
|
||||
// allow hidpi to passthru
|
||||
$o['hidpi'] = true;
|
||||
} else if($s == 'is') {
|
||||
// this is a known core suffix that we allow
|
||||
} else if(strpos($s, 'cropx') === 0) {
|
||||
// skip cropx suffix (already known from $info[crop])
|
||||
unset($info['suffix'][$k]);
|
||||
continue;
|
||||
} else if(strpos($s, 'pid') === 0 && preg_match('/^pid\d+$/', $s)) {
|
||||
// allow pid123 to pass through
|
||||
} else if(in_array($s, $suffix)) {
|
||||
// suffix is one provided in $suffix argument
|
||||
if($mode == 2) {
|
||||
// mode 2 where $suffix is an exclusion list
|
||||
$skip = true;
|
||||
$reasons[$name] = "$name: Suffix '$s' is one provided in exclusion list (mode==true)";
|
||||
} else {
|
||||
// allowed suffix
|
||||
}
|
||||
} else {
|
||||
// image has suffix not specified in $suffix argument
|
||||
if($mode == 0 || $mode == 1 || $mode == 3) {
|
||||
$skip = true;
|
||||
$reasons[$name] = "$name: Image has suffix '$s' not provided in allowed list: " . implode(', ', $suffix);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($mode == 4 && ($info['width'] == 0 || $info['height'] == 0)) {
|
||||
// skip images that don't specify both width and height
|
||||
$skip = true;
|
||||
}
|
||||
|
||||
if($skip) {
|
||||
$skipped[] = $name;
|
||||
continue;
|
||||
}
|
||||
|
||||
// rebuild the variation
|
||||
$o['forceNew'] = true;
|
||||
$o['suffix'] = $info['suffix'];
|
||||
|
||||
if(is_file($info['path'])) {
|
||||
$this->wire('files')->unlink($info['path'], true);
|
||||
if(!empty($info['webpPath']) && is_file($info['webpPath'])) {
|
||||
$this->wire('files')->unlink($info['webpPath'], true);
|
||||
$hadWebp = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if(!$info['width'] && $info['actualWidth']) {
|
||||
$info['width'] = $info['actualWidth'];
|
||||
$options['nameWidth'] = 0;
|
||||
}
|
||||
if(!$info['height'] && $info['actualHeight']) {
|
||||
$info['height'] = $info['actualHeight'];
|
||||
$options['nameHeight'] = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
if($info['crop'] && preg_match('/^x(\d+)y(\d+)$/', $info['crop'], $matches)) {
|
||||
// dimensional cropping info contained in filename
|
||||
$cropX = (int) $matches[1];
|
||||
$cropY = (int) $matches[2];
|
||||
$variation = $this->pageimage->crop($cropX, $cropY, $info['width'], $info['height'], $options);
|
||||
|
||||
} else if($info['crop']) {
|
||||
// direct cropping info contained in filename
|
||||
$options['cropping'] = $info['crop'];
|
||||
$variation = $this->pageimage->size($info['width'], $info['height'], $options);
|
||||
|
||||
} else if($this->pageimage->hasFocus) {
|
||||
// crop to focus area, which the size() method will determine on its own
|
||||
$variation = $this->pageimage->size($info['width'], $info['height'], $options);
|
||||
|
||||
} else {
|
||||
// no crop, no focus, just resize
|
||||
$variation = $this->pageimage->size($info['width'], $info['height'], $options);
|
||||
}
|
||||
|
||||
if($variation) {
|
||||
if($variation->name != $name) {
|
||||
rename($variation->filename(), $info['path']);
|
||||
$variation->data('basename', $name);
|
||||
}
|
||||
$rebuilt[] = $name;
|
||||
if($hadWebp) {
|
||||
// forces create of webp version
|
||||
$webpName = basename($variation->webp()->url());
|
||||
if($webpName) $rebuilt[] = $webpName;
|
||||
}
|
||||
} else {
|
||||
$errors[] = $name;
|
||||
}
|
||||
}
|
||||
|
||||
return array(
|
||||
'rebuilt' => $rebuilt,
|
||||
'skipped' => $skipped,
|
||||
'reasons' => $reasons,
|
||||
'errors' => $errors
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all the alternate sizes associated with this Pageimage
|
||||
*
|
||||
* @param array $options See options for getVariations() method to limit what variations are removed, plus these:
|
||||
* - `dryRun` (bool): Do not remove now and instead only return the filenames of variations that would be deleted (default=false).
|
||||
* - `getFiles` (bool): Return deleted filenames? Also assumed if the test option is used (default=false).
|
||||
* @return $this|array Returns $this by default, or array of deleted filenames if the `getFiles` option is specified
|
||||
*
|
||||
*/
|
||||
public function remove(array $options = array()) {
|
||||
|
||||
$defaults = array(
|
||||
'dryRun' => false,
|
||||
'getFiles' => false
|
||||
);
|
||||
|
||||
$variations = $this->find($options);
|
||||
if(!empty($options['dryrun'])) $defaults['dryRun'] = $options['dryrun']; // case insurance
|
||||
$options = array_merge($defaults, $options); // placement after getVariations() intended
|
||||
$deletedFiles = array();
|
||||
|
||||
/** @var WireFileTools $files */
|
||||
$files = $this->wire('files');
|
||||
|
||||
foreach($variations as $variation) {
|
||||
$filename = $variation->filename;
|
||||
if(!is_file($filename)) continue;
|
||||
if($options['dryRun']) {
|
||||
$success = true;
|
||||
} else {
|
||||
$success = $files->unlink($filename, true);
|
||||
}
|
||||
if($success) $deletedFiles[] = $filename;
|
||||
|
||||
foreach($this->pageimage->extras() as $extra) {
|
||||
if(!$extra->exists()) continue;
|
||||
if($options['dryRun']) {
|
||||
$deletedFiles[] = $extra->filename();
|
||||
} else if($extra->unlink()) {
|
||||
$deletedFiles[] = $extra->filename();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!$options['dryRun']) $this->variations = null;
|
||||
|
||||
return ($options['dryRun'] || $options['getFiles'] ? $deletedFiles : $this);
|
||||
}
|
||||
}
|
@@ -923,10 +923,13 @@ class Sanitizer extends Wire {
|
||||
$value = "$basename.$pathinfo[extension]";
|
||||
}
|
||||
|
||||
return $this->name($value, $beautify, $maxLength, '_', array(
|
||||
$value = $this->name($value, $beautify, $maxLength, '_', array(
|
||||
'allowAdjacentExtras' => true, // language translation filenames require doubled "--" chars, others may too
|
||||
)
|
||||
);
|
||||
));
|
||||
|
||||
while(strpos($value, '..') !== false) $value = str_replace('..', '', $value);
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
|
File diff suppressed because one or more lines are too long
@@ -212,35 +212,45 @@ class ProcessPageEditImageSelect extends Process implements ConfigurableModule {
|
||||
*
|
||||
*/
|
||||
public function init() {
|
||||
|
||||
/** @var Config $config */
|
||||
$config = $this->wire('config');
|
||||
/** @var WireInput $input */
|
||||
$input = $this->wire('input');
|
||||
/** @var Session $session */
|
||||
$session = $this->wire('session');
|
||||
/** @var Sanitizer $sanitizer */
|
||||
$sanitizer = $this->wire('sanitizer');
|
||||
|
||||
|
||||
// throw new WireException($this->labels['demoMode']);
|
||||
if($this->config->demo) {
|
||||
if($this->wire('input')->urlSegmentStr != 'variations') {
|
||||
if($config->demo) {
|
||||
if($input->urlSegmentStr != 'variations') {
|
||||
throw new WireException($this->labels['demoMode']);
|
||||
}
|
||||
}
|
||||
|
||||
$this->modules->get("ProcessPageList");
|
||||
|
||||
$this->rte = $this->input->get('rte') !== null && $this->input->get('rte') == "0" ? false : true;
|
||||
$id = (int) $this->input->get->id;
|
||||
$editID = (int) $this->input->get->edit_page_id;
|
||||
$this->rte = $input->get('rte') !== null && $input->get('rte') == "0" ? false : true;
|
||||
$id = (int) $input->get('id');
|
||||
$editID = (int) $input->get('edit_page_id');
|
||||
|
||||
if($editID) {
|
||||
$this->wire('session')->set($this, 'edit_page_id', $editID);
|
||||
$session->set($this, 'edit_page_id', $editID);
|
||||
} else {
|
||||
$editID = (int) $this->wire('session')->get($this, 'edit_page_id');
|
||||
$editID = (int) $session->get($this, 'edit_page_id');
|
||||
}
|
||||
|
||||
if($editID) {
|
||||
$this->editorPage = $this->wire('pages')->get($editID);
|
||||
if(!$this->editorPage->editable()) {
|
||||
$this->editorPage = null;
|
||||
$this->wire('session')->remove($this, 'edit_page_id');
|
||||
$session->remove($this, 'edit_page_id');
|
||||
}
|
||||
}
|
||||
|
||||
$fieldName = $this->wire('sanitizer')->fieldName($this->wire('input')->get('field'));
|
||||
$fieldName = $sanitizer->fieldName($input->get('field'));
|
||||
if($fieldName) {
|
||||
$this->fieldName = $fieldName; // original
|
||||
if(strpos($fieldName, '_repeater') && preg_match('/_repeater\d+$/', $fieldName, $matches)) {
|
||||
@@ -255,20 +265,21 @@ class ProcessPageEditImageSelect extends Process implements ConfigurableModule {
|
||||
}
|
||||
|
||||
// if no ID was specified, then retrieive ID from filename path, if it's there
|
||||
if($this->input->get->file && preg_match('{[/,]}', $this->input->get->file)) {
|
||||
$file = $input->get('file');
|
||||
if($file && preg_match('{[/,]}', $file)) {
|
||||
|
||||
if(preg_match('{(\d+)[/,][^/,]+\.(' . $this->extensions . ')$}iD', $this->input->get->file, $matches)) {
|
||||
if(preg_match('{(\d+)[/,][^/,]+\.(' . $this->extensions . ')$}iD', $file, $matches)) {
|
||||
// ..........ID.../,filename.ext
|
||||
// format: 123/filename.jpg OR 123,filename.jpg
|
||||
// also covers new pagefileSecure URLs
|
||||
$id = (int) $matches[1];
|
||||
|
||||
} else if(preg_match('{(/[\d/]+)/([-_.a-z0-9]+)\.(' . $this->extensions . ')$}iD', $this->input->get->file, $matches)) {
|
||||
} else if(preg_match('{(/[\d/]+)/([-_.a-z0-9]+)\.(' . $this->extensions . ')$}iD', $file, $matches)) {
|
||||
// .................ID........filename........ext
|
||||
// extended asset path format: 1/2/3/filename.jpg
|
||||
$id = PagefilesManager::dirToPageID($matches[1]);
|
||||
|
||||
} else if(preg_match('{^' . $this->wire('config')->urls->root . '([-_./a-zA-Z0-9]*/)' . $this->wire('config')->pagefileUrlPrefix . '[^/]+\.(' . $this->extensions . ')$}iD', $this->input->get->file, $matches)) {
|
||||
} else if(preg_match('{^' . $config->urls->root . '([-_./a-zA-Z0-9]*/)' . $config->pagefileUrlPrefix . '[^/]+\.(' . $this->extensions . ')$}iD', $file, $matches)) {
|
||||
// .............................../....................path/to/page.........................-?....................filename..........ext
|
||||
// legacy pagefileSecure URL format: /path/to/page/filename.jpg
|
||||
// @todo: does this still need to be here or can it be dropped?
|
||||
@@ -310,21 +321,20 @@ class ProcessPageEditImageSelect extends Process implements ConfigurableModule {
|
||||
}
|
||||
}
|
||||
|
||||
if($this->input->get->winwidth) $this->maxImageWidth = ((int) $this->input->get->winwidth) - 70;
|
||||
if($this->maxImageWidth < 400) $this->maxImageWidth = 400;
|
||||
|
||||
$this->hidpi = ((int) $this->wire('input')->get('hidpi')) ? true : false;
|
||||
$hidpi = $this->wire('input')->get('hidpi');
|
||||
if($input->get('winwidth')) $this->maxImageWidth = ((int) $input->get('winwidth')) - 70;
|
||||
if($this->maxImageWidth < 400) $this->maxImageWidth = 400;
|
||||
|
||||
$hidpi = $input->get('hidpi');
|
||||
if($hidpi === null && $this->hidpiDefault) $hidpi = true;
|
||||
if(!$this->rte) $hidpi = false; // hidpi not applicable outside of RTE mode
|
||||
$this->hidpi = $hidpi ? true : false;
|
||||
|
||||
if($this->rte) $this->caption = $this->wire('input')->get('caption') ? true : false;
|
||||
if($this->rte) $this->caption = $input->get('caption') ? true : false;
|
||||
|
||||
// original used by InputfieldImage
|
||||
$original = $this->wire('input')->get('original');
|
||||
$original = $input->get('original');
|
||||
if($original) {
|
||||
$original = $this->wire('sanitizer')->filename($original);
|
||||
$original = $sanitizer->filename($original);
|
||||
if(is_file($this->page->filesManager()->path . $original)) {
|
||||
$this->original = $original;
|
||||
}
|
||||
@@ -344,7 +354,7 @@ class ProcessPageEditImageSelect extends Process implements ConfigurableModule {
|
||||
public function getPageimage($getVariation = false) {
|
||||
|
||||
$images = $this->getImages($this->page);
|
||||
$file = basename($this->input->get->file);
|
||||
$file = basename($this->input->get('file'));
|
||||
$variationFilename = '';
|
||||
|
||||
if(strpos($file, ',') === false) {
|
||||
@@ -501,14 +511,14 @@ class ProcessPageEditImageSelect extends Process implements ConfigurableModule {
|
||||
return "<p>$error</p>";
|
||||
}
|
||||
|
||||
if($this->input->get->file) return $this->executeEdit();
|
||||
if($this->input->get('file')) return $this->executeEdit();
|
||||
|
||||
$images = $this->getImages($this->page, $this->page->fields);
|
||||
|
||||
$out = '';
|
||||
|
||||
if(count($images)) {
|
||||
$winwidth = (int) $this->input->get->winwidth;
|
||||
$winwidth = (int) $this->input->get('winwidth');
|
||||
$in = $this->wire('modules')->get('InputfieldImage');
|
||||
$in->adminThumbs = true;
|
||||
|
||||
@@ -722,22 +732,28 @@ class ProcessPageEditImageSelect extends Process implements ConfigurableModule {
|
||||
*/
|
||||
public function ___executeEdit() {
|
||||
|
||||
|
||||
/** @var WireInput $input */
|
||||
$input = $this->wire('input');
|
||||
/** @var Config $config */
|
||||
$config = $this->wire('config');
|
||||
|
||||
$this->checkImageEditPermission();
|
||||
|
||||
if($this->wire('input')->post('submit_crop')) {
|
||||
if($input->post('submit_crop')) {
|
||||
$crop = $this->processCrop();
|
||||
$parts = $this->hidpi ? array('width' => $crop->hidpiWidth()) : array();
|
||||
$this->wire('session')->redirect($this->makeEditURL($crop->basename, $parts));
|
||||
return '';
|
||||
} else if($this->wire('input')->post('submit_save_replace')) {
|
||||
} else if($input->post('submit_save_replace')) {
|
||||
return $this->processSave(true);
|
||||
} else if($this->wire('input')->post('submit_save_copy')) {
|
||||
} else if($input->post('submit_save_copy')) {
|
||||
return $this->processSave(false);
|
||||
}
|
||||
|
||||
$path = $this->wire('config')->urls->ProcessPageEditImageSelect;
|
||||
$this->wire('config')->styles->add($path . 'cropper/cropper.min.css');
|
||||
$this->wire('config')->scripts->add($path . 'cropper/cropper.min.js');
|
||||
$path = $config->urls('ProcessPageEditImageSelect');
|
||||
$config->styles->add($path . 'cropper/cropper.min.css');
|
||||
$config->scripts->add($path . 'cropper/cropper.min.js');
|
||||
|
||||
$labels =& $this->labels;
|
||||
$formClasses = array();
|
||||
@@ -751,7 +767,7 @@ class ProcessPageEditImageSelect extends Process implements ConfigurableModule {
|
||||
foreach($icons as $key => $value) {
|
||||
$icons[$key] = "<i class='fa fa-fw fa-$value ui-priority-secondary'></i>";
|
||||
}
|
||||
|
||||
|
||||
$optionalClasses = array(
|
||||
$this->alignLeftClass => $labels['alignLeft'],
|
||||
$this->alignRightClass => $labels['alignRight'],
|
||||
@@ -762,7 +778,7 @@ class ProcessPageEditImageSelect extends Process implements ConfigurableModule {
|
||||
$cropY = null;
|
||||
$cropWidth = null;
|
||||
$cropHeight = null;
|
||||
$isCropped = preg_match_all('/\.(\d+)x(\d+).*?-crop[xy](\d+)[xy](\d+)[-.]/', $this->wire('input')->get('file'), $matches);
|
||||
$isCropped = preg_match_all('/\.(\d+)x(\d+).*?-crop[xy](\d+)[xy](\d+)[-.]/', $input->get('file'), $matches);
|
||||
|
||||
if($isCropped) { // get last coordinates present
|
||||
$cropWidth = (int) array_pop($matches[1]);
|
||||
@@ -825,25 +841,25 @@ class ProcessPageEditImageSelect extends Process implements ConfigurableModule {
|
||||
);
|
||||
|
||||
if(!$this->rte && $this->field) {
|
||||
$minWidth = $this->field->minWidth ? (int) $this->field->minWidth : 1;
|
||||
$minHeight = $this->field->minHeight ? (int) $this->field->minHeight : 1;
|
||||
$minWidth = $this->field->get('minWidth') ? (int) $this->field->get('minWidth') : 1;
|
||||
$minHeight = $this->field->get('minHeight') ? (int) $this->field->get('minHeight') : 1;
|
||||
} else {
|
||||
$minWidth = 1;
|
||||
$minHeight = 1;
|
||||
}
|
||||
|
||||
// bundle in crop information to image attributes, if specified
|
||||
if($this->wire('input')->get('crop_x')) {
|
||||
if($input->get('crop_x')) {
|
||||
$attrs['data-crop'] =
|
||||
((int) $this->wire('input')->get('crop_x')) . ',' .
|
||||
((int) $this->wire('input')->get('crop_y')) . ',' .
|
||||
((int) $this->wire('input')->get('crop_w')) . ',' .
|
||||
((int) $this->wire('input')->get('crop_h'));
|
||||
((int) $input->get('crop_x')) . ',' .
|
||||
((int) $input->get('crop_y')) . ',' .
|
||||
((int) $input->get('crop_w')) . ',' .
|
||||
((int) $input->get('crop_h'));
|
||||
}
|
||||
|
||||
// determine width/height we will display image at in editor, so that it fits
|
||||
$width = (int) $this->input->get('width');
|
||||
$height = (int) $this->input->get('height');
|
||||
$width = (int) $input->get('width');
|
||||
$height = (int) $input->get('height');
|
||||
if(!$width) $width = $this->editWidth;
|
||||
if(!$width) $width = '';
|
||||
if(!$height) $height = $this->editHeight;
|
||||
@@ -860,7 +876,7 @@ class ProcessPageEditImageSelect extends Process implements ConfigurableModule {
|
||||
// if they aren't already working with a resized image, and it's being scaled down,
|
||||
// then add the 'resized' class to ensure that our RTE 'pwimage' plugin knows to perform the resize
|
||||
// by checking for the 'resized' classname on the image
|
||||
if(basename($this->input->get->file) == $fullname && $originalWidth > $width) $attrs['class'] .= " resized";
|
||||
if(basename($input->get('file')) == $fullname && $originalWidth > $width) $attrs['class'] .= " resized";
|
||||
|
||||
// if hidpi specified keep it checed
|
||||
$hidpiChecked = $this->hidpi ? " checked='checked'" : "";
|
||||
@@ -870,7 +886,7 @@ class ProcessPageEditImageSelect extends Process implements ConfigurableModule {
|
||||
$classOptions = '';
|
||||
foreach($optionalClasses as $class => $label) {
|
||||
$labelKey = array_search($label, $labels);
|
||||
$selected = strpos($this->input->get('class'), $class) !== false ? " selected='selected'" : '';
|
||||
$selected = strpos($input->get('class'), $class) !== false ? " selected='selected'" : '';
|
||||
if($selected) $attrs['class'] .= " $class";
|
||||
$classOptions .= "<option$selected data-label='$labelKey' value='$class'>$label</option>";
|
||||
}
|
||||
@@ -883,16 +899,16 @@ class ProcessPageEditImageSelect extends Process implements ConfigurableModule {
|
||||
}
|
||||
|
||||
// prepare description (alt)
|
||||
$description = isset($_GET['description']) ? $this->input->get('description') : ''; // $image->description;
|
||||
$description = isset($_GET['description']) ? $input->get('description') : ''; // $image->description;
|
||||
if(strlen($description) > 8192) $description = substr($description, 0, 8192);
|
||||
$description = $this->wire('sanitizer')->entities($description);
|
||||
|
||||
// if dealing with a variation size or crop provide the option to link to the original (larger)
|
||||
$linkOriginalChecked = '';
|
||||
if($image->name != $original->name || $this->wire('input')->get('link')) {
|
||||
if($image->name != $original->name || $input->get('link')) {
|
||||
if($image->name != $original->name) $formClasses[] = 'not-original';
|
||||
$imgURL = str_replace($this->wire('config')->urls->root, '/', $original->url);
|
||||
$imgLinkURL = trim($this->wire('input')->get('link'));
|
||||
$imgURL = str_replace($config->urls->root, '/', $original->url);
|
||||
$imgLinkURL = trim($input->get('link'));
|
||||
if($imgLinkURL) {
|
||||
if($imgLinkURL === "1") $imgLinkURL = $imgURL; // if in toggle mode, substitute URL
|
||||
// determine if 'link to original' checkbox should be checked
|
||||
@@ -907,7 +923,7 @@ class ProcessPageEditImageSelect extends Process implements ConfigurableModule {
|
||||
$resizeYesChecked = $this->rte ? " checked='checked'" : "";
|
||||
$resizeNoChecked = !$this->rte ? " checked='checked'" : "";
|
||||
|
||||
if($this->field && $this->field->maxFiles == 1) $formClasses[] = 'maxfiles1';
|
||||
if($this->field && $this->field->get('maxFiles') == 1) $formClasses[] = 'maxfiles1';
|
||||
|
||||
// form attributes
|
||||
$formClasses[] = $isCroppable ? 'croppable' : 'not-croppable';
|
||||
@@ -1145,7 +1161,7 @@ class ProcessPageEditImageSelect extends Process implements ConfigurableModule {
|
||||
if($this->original && $this->original != $image2->basename() && $original = $image->pagefiles->get($this->original)) {
|
||||
$fileID = 'file_' . $original->hash;
|
||||
|
||||
if($rebuildVariations && $this->field->adminThumbs) {
|
||||
if($rebuildVariations && $this->field->get('adminThumbs')) {
|
||||
// remove original thumbnail
|
||||
/** @var InputfieldImage $inputfield */
|
||||
$inputfield = $this->field->getInputfield($this->page);
|
||||
@@ -1252,13 +1268,16 @@ class ProcessPageEditImageSelect extends Process implements ConfigurableModule {
|
||||
public function ___executeResize() {
|
||||
|
||||
$this->checkImageEditPermission();
|
||||
|
||||
/** @var WireInput $input */
|
||||
$input = $this->wire('input');
|
||||
|
||||
$width = (int) $this->input->get('width');
|
||||
$class = $this->sanitizer->name($this->input->get->class);
|
||||
$width = (int) $input->get('width');
|
||||
$class = $this->sanitizer->name($input->get('class'));
|
||||
$hidpi = $this->hidpi;
|
||||
$json = (int) $this->input->get('json'); // 1 or 0 (for json output mode on or off)
|
||||
$rotate = (int) $this->wire('input')->get('rotate');
|
||||
$flip = $this->wire('input')->get('flip');
|
||||
$json = (int) $input->get('json'); // 1 or 0 (for json output mode on or off)
|
||||
$rotate = (int) $input->get('rotate');
|
||||
$flip = $input->get('flip');
|
||||
if($flip != 'v' && $flip != 'h') $flip = '';
|
||||
|
||||
if(strpos($class, 'hidpi') !== false) {
|
||||
@@ -1355,12 +1374,21 @@ class ProcessPageEditImageSelect extends Process implements ConfigurableModule {
|
||||
|
||||
if(!$this->page || !$pageimage) throw new WireException("No file provided");
|
||||
if(!$this->masterPage->editable()) throw new WireException($this->labels['noAccess']);
|
||||
|
||||
$cnt = 0;
|
||||
$rows = array();
|
||||
$name = $pageimage->basename();
|
||||
$filesize = $pageimage->filesize();
|
||||
$filesizeStr = wireBytesStr($filesize);
|
||||
$mtime = filemtime($pageimage->filename);
|
||||
$modified = date('Y-m-d H:i:s', $mtime);
|
||||
$url = $pageimage->url() . "?nc=$mtime";
|
||||
$originalLabel = $this->_('Original');
|
||||
$hasEditPermission = $this->wire('user')->hasPermission('page-edit-images', $this->masterPage);
|
||||
|
||||
$variations = $pageimage->getVariations(array('info' => true));
|
||||
$cnt = count($variations);
|
||||
|
||||
$variations = $pageimage->getVariations(array('info' => true, 'verbose' => 1));
|
||||
$adminThumbOptions = $this->wire('config')->adminThumbOptions;
|
||||
$delete = $this->wire('input')->post('delete');
|
||||
|
||||
if(is_array($delete) && count($delete) && $hasEditPermission) {
|
||||
foreach($delete as $name) {
|
||||
if(!isset($variations[$name])) continue;
|
||||
@@ -1374,33 +1402,43 @@ class ProcessPageEditImageSelect extends Process implements ConfigurableModule {
|
||||
}
|
||||
}
|
||||
|
||||
$headline = sprintf(
|
||||
$this->_n('%1$d variation for image %2$s', '%1$d variations for image %2$s', $cnt),
|
||||
//$cnt, "<a class='preview' href='$pageimage->URL'>$pageimage->basename</a>"
|
||||
$cnt, $pageimage->basename
|
||||
$rows[] = array(
|
||||
'cnt' => $cnt,
|
||||
'url' => $url,
|
||||
'name' => $name,
|
||||
'notes' => array($originalLabel),
|
||||
'width' => $pageimage->width(),
|
||||
'height' => $pageimage->height(),
|
||||
'modified' => $modified,
|
||||
'filesize' => $filesize,
|
||||
'filesizeStr' => $filesizeStr,
|
||||
'deletable' => $hasEditPermission,
|
||||
);
|
||||
|
||||
foreach($pageimage->extras() as $extra) {
|
||||
if(!file_exists($extra->filename)) continue;
|
||||
$name = $extra->basename();
|
||||
$filesize = $extra->filesize();
|
||||
$filesizeStr = wireBytesStr($filesize);
|
||||
$mtime = filemtime($extra->filename);
|
||||
$modified = date('Y-m-d H:i:s', $mtime);
|
||||
$url = $extra->url() . "?nc=$mtime";
|
||||
$rows[] = array(
|
||||
'cnt' => ++$cnt,
|
||||
'url' => $url,
|
||||
'name' => $name,
|
||||
'notes' => array("$originalLabel ($extra->ext $extra->savingsPct)"),
|
||||
'width' => $pageimage->width(),
|
||||
'height' => $pageimage->height(),
|
||||
'modified' => $modified,
|
||||
'filesize' => $filesize,
|
||||
'filesizeStr' => $filesizeStr,
|
||||
'deletable' => false,
|
||||
);
|
||||
$this->headline($headline);
|
||||
|
||||
if(!$cnt) return "<h2>$headline</h2>";
|
||||
|
||||
$adminThumbOptions = $this->wire('config')->adminThumbOptions;
|
||||
|
||||
$table = $this->wire('modules')->get('MarkupAdminDataTable');
|
||||
$table->setEncodeEntities(false);
|
||||
$table->headerRow(array(
|
||||
'#',
|
||||
$this->_x('Image', 'th'),
|
||||
$this->_x('File', 'th'),
|
||||
$this->_x('Size', 'th'),
|
||||
$this->_x('Modified', 'th'),
|
||||
$this->_x('Notes', 'th'),
|
||||
($hasEditPermission ? "<label><input type='checkbox' id='delete_all' value='1' /></label>" : " ")
|
||||
));
|
||||
|
||||
$cnt = 0;
|
||||
}
|
||||
|
||||
foreach($variations as $name => $info) {
|
||||
|
||||
|
||||
$notes = array();
|
||||
if(in_array('is', $info['suffix'])) $notes[] = $this->_x('Created for placement in textarea', 'notes');
|
||||
if(in_array('hidpi', $info['suffix'])) $notes[] = $this->_x('HiDPI/Retina', 'notes');
|
||||
@@ -1432,18 +1470,87 @@ class ProcessPageEditImageSelect extends Process implements ConfigurableModule {
|
||||
$mtime = filemtime($info['path']);
|
||||
$modified = date('Y-m-d H:i:s', $mtime);
|
||||
$url = "$info[url]?nc=$mtime";
|
||||
|
||||
$rows[] = array(
|
||||
'cnt' => ++$cnt,
|
||||
'url' => $url,
|
||||
'name' => $name,
|
||||
'notes' => $notes,
|
||||
'width' => $width,
|
||||
'height' => $height,
|
||||
'modified' => $modified,
|
||||
'filesize' => $filesize,
|
||||
'filesizeStr' => $filesizeStr,
|
||||
'deletable' => $hasEditPermission,
|
||||
);
|
||||
|
||||
/** @var Pageimage $pi */
|
||||
$pi = $info['pageimage'];
|
||||
foreach($pi->extras() as $extra) {
|
||||
if(!file_exists($extra->filename)) continue;
|
||||
$name = $extra->basename();
|
||||
$filesize = $extra->filesize();
|
||||
$filesizeStr = wireBytesStr($filesize);
|
||||
$mtime = filemtime($extra->filename());
|
||||
$modified = date('Y-m-d H:i:s', $mtime);
|
||||
$url = $extra->url() . "?nc=$mtime";
|
||||
|
||||
$rows[] = array(
|
||||
'cnt' => ++$cnt,
|
||||
'url' => $url,
|
||||
'name' => $name,
|
||||
'notes' => $notes,
|
||||
'width' => $width,
|
||||
'height' => $height,
|
||||
'modified' => $modified,
|
||||
'filesize' => $filesize,
|
||||
'filesizeStr' => $filesizeStr,
|
||||
'deletable' => false,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/** @var InputfieldCheckbox $checkbox */
|
||||
$checkbox = $this->wire('modules')->get('InputfieldCheckbox');
|
||||
$checkbox->label = ' ';
|
||||
$checkbox->addClass('delete');
|
||||
$checkbox->attr('id+name', 'delete_all');
|
||||
$checkbox->val(1);
|
||||
|
||||
/** @var MarkupAdminDataTable $table */
|
||||
$table = $this->wire('modules')->get('MarkupAdminDataTable');
|
||||
$table->setEncodeEntities(false);
|
||||
$table->headerRow(array(
|
||||
'#',
|
||||
$this->_x('Image', 'th'),
|
||||
$this->_x('File', 'th'),
|
||||
$this->_x('Size', 'th'),
|
||||
$this->_x('Modified', 'th'),
|
||||
$this->_x('Notes', 'th'),
|
||||
($hasEditPermission ? $checkbox->render() : " ")
|
||||
));
|
||||
|
||||
foreach($rows as $row) {
|
||||
$checkbox->attr('name', 'delete[]');
|
||||
$checkbox->val($row['name']);
|
||||
$checkbox->attr('id', "delete_$row[cnt]");
|
||||
$table->row(array(
|
||||
++$cnt,
|
||||
"<a class='preview' href='$url'><img src='$url' alt='$name' style='max-width: 100px;' /></a>",
|
||||
"<a class='preview' href='$url'>$name</a><br /><span class='detail'>{$width}x{$height}</span>",
|
||||
"<span style='display: none;'>$filesize</span>$filesizeStr",
|
||||
$modified,
|
||||
implode('<br />', $notes),
|
||||
($hasEditPermission ? "<label><input type='checkbox' class='delete' name='delete[]' value='$name' /> </label>" : " ")
|
||||
($row['cnt'] ? $row['cnt'] : ' '),
|
||||
"<a class='preview' href='$row[url]'><img src='$row[url]' alt='$row[name]' style='max-width: 100px;' /></a>",
|
||||
"<a class='preview' href='$row[url]'>$row[name]</a><br /><span class='detail'>$row[width]x$row[height]</span>",
|
||||
"<span style='display: none;'>$row[filesize]</span>$row[filesizeStr]",
|
||||
$row['modified'],
|
||||
implode('<br />', $row['notes']),
|
||||
//($hasEditPermission ? "<label><input type='checkbox' class='delete' name='delete[]' value='$row[name]' /> </label>" : " ")
|
||||
($row['cnt'] && $row['deletable'] ? $checkbox->render() : " ")
|
||||
));
|
||||
}
|
||||
|
||||
$this->headline(sprintf(
|
||||
$this->_n('%1$d variation for image %2$s', '%1$d variations for image %2$s', $cnt),
|
||||
$cnt, $pageimage->basename
|
||||
));
|
||||
|
||||
$varcnt = $this->wire('sanitizer')->entities($this->wire('input')->get('varcnt'));
|
||||
|
||||
$form = $this->wire('modules')->get('InputfieldForm');
|
||||
|
Reference in New Issue
Block a user