From 00de278dc790e7714ff4c021d1c1b0ff998959e9 Mon Sep 17 00:00:00 2001 From: Ryan Cramer Date: Fri, 10 Apr 2020 12:48:28 -0400 Subject: [PATCH] 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. --- wire/core/Pageimage.php | 107 ++++++++--- wire/modules/Fieldtype/FieldtypeImage.module | 180 ++++++++++++++++-- .../ProcessPageEditImageSelect.js | 2 +- .../ProcessPageEditImageSelect.min.js | 2 +- .../ProcessPageEditImageSelect.module | 22 ++- 5 files changed, 263 insertions(+), 50 deletions(-) diff --git a/wire/core/Pageimage.php b/wire/core/Pageimage.php index 068e878e..3c99d507 100644 --- a/wire/core/Pageimage.php +++ b/wire/core/Pageimage.php @@ -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 diff --git a/wire/modules/Fieldtype/FieldtypeImage.module b/wire/modules/Fieldtype/FieldtypeImage.module index c9c843e8..68b5e364 100644 --- a/wire/modules/Fieldtype/FieldtypeImage.module +++ b/wire/modules/Fieldtype/FieldtypeImage.module @@ -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; + } + */ + } diff --git a/wire/modules/Process/ProcessPageEditImageSelect/ProcessPageEditImageSelect.js b/wire/modules/Process/ProcessPageEditImageSelect/ProcessPageEditImageSelect.js index 73fb81ad..3d2a4e3a 100644 --- a/wire/modules/Process/ProcessPageEditImageSelect/ProcessPageEditImageSelect.js +++ b/wire/modules/Process/ProcessPageEditImageSelect/ProcessPageEditImageSelect.js @@ -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() { diff --git a/wire/modules/Process/ProcessPageEditImageSelect/ProcessPageEditImageSelect.min.js b/wire/modules/Process/ProcessPageEditImageSelect/ProcessPageEditImageSelect.min.js index 64580005..3389a64c 100644 --- a/wire/modules/Process/ProcessPageEditImageSelect/ProcessPageEditImageSelect.min.js +++ b/wire/modules/Process/ProcessPageEditImageSelect/ProcessPageEditImageSelect.min.js @@ -1 +1 @@ -function enablePWImageDialogButtons(){var $buttonPane=parent.jQuery(".ui-dialog-buttonpane");$buttonPane.find("button").button("enable");return}function disablePWImageDialogButtons(){var $buttonPane=parent.jQuery(".ui-dialog-buttonpane");$buttonPane.find("button").button("disable");return}function closePWImageDialog(){parent.jQuery("iframe.ui-dialog-content").dialog("close")}function setupProcessSaveReloaded(fileID,isNew){if(isNew){var offsetTop=parent.jQuery("#"+fileID).offset().top-20;parent.jQuery("html, body").animate({scrollTop:offsetTop},1e3,"swing");parent.jQuery("#"+fileID).hide();setTimeout(function(){parent.jQuery("#"+fileID).slideDown()},900)}else{parent.jQuery("#"+fileID).find("img").hide();setTimeout(function(){parent.jQuery("#"+fileID).find("img").fadeIn("normal",function(){parent.jQuery("#"+fileID).find(".gridImage__edit").click()})},500)}closePWImageDialog()}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.trigger("reload");parent.jQuery(".Inputfield").on("reloaded",function(){if(finished)return;finished=true;if(fileID.length>0){setTimeout(function(){setupProcessSaveReloaded(fileID,isNew)},250)}})}function refreshPageEditField(fieldName){parent.jQuery("#wrap_Inputfield_"+fieldName).trigger("reload")}function setupExecuteVariations(){$(document).on("click","input#delete_all",function(event){if($(this).is(":checked")){$("input.delete").attr("checked","checked")}else{$("input.delete").removeAttr("checked")}event.stopPropagation()});var magnificOptions={type:"image",closeOnContentClick:true,closeBtnInside:true};$("a.preview").magnificPopup(magnificOptions);var $varcnt=$("#varcnt_id");var varcntID=$varcnt.val();var varcnt=$varcnt.attr("data-cnt");window.parent.jQuery("#"+varcntID).text(varcnt)}function setupSelectedImage(){var croppingActive=false;var inputPixelsActive=false;var $form=$("#selected_image_settings");var $container=$("#selected_image_container");var $img=$("#selected_image");var $hidpi=$("#selected_image_hidpi");var fullWidth;var minWidth=0;var minHeight=0;function setupImage($img){var originalWidth=$img.width();var maxWidth=9999;var maxHeight=9999;function updateHidpiCheckbox(w){if(w=maxHeight||w>=maxWidth)&&$form.hasClass("croppable")){w=maxWidth;h=maxHeight;$("#selected_image_link").removeAttr("checked");$link.hide()}else{if(!$link.is(":visible")){$link.fadeIn();if($link.attr("data-was-checked")==1){$link.attr("checked","checked")}}}$("#input_width").val(w);$("#input_height").val(h);$img.attr("width",w);$img.attr("height",h);updateHidpiCheckbox(w);var $latin=$("#latin");if($latin.is(":visible"))$latin.height(h);if(!$form.hasClass("rte")){var $useResize=$("#selected_image_resize");if(originalWidth<=w){$useResize.hide()}else{if(!$useResize.is(":visible"))$useResize.fadeIn()}}}function setupImageResizable(){$img.resizable({aspectRatio:true,handles:"n, ne, e, se, s, sw, w",alsoResize:"#selected_image_container",maxWidth:maxWidth,maxHeight:maxHeight,minWidth:10,minHeight:10,start:function(){$form.addClass("resizing_active")},stop:function(){$img.attr("width",$img.width()).attr("height",$img.height());if(originalWidth!=$img.width()){$img.addClass("resized");if(!$form.hasClass("rte")){var $resizeYes=$("#selected_image_resize_yes");if(!$resizeYes.is(":checked")){$resizeYes.attr("checked","checked");$("#selected_image_resize_no").removeAttr("checked")}}}$form.removeClass("resizing_active");if($("#resize_action").hasClass("on"))$("#resize_action").click().mouseout()},resize:populateResizeDimensions});$img.addClass("resizable_setup")}var cropData=null;function setupImageCroppable(){var cropButtons=[{html:$("#button_crop").html(),click:function(){$("#button_crop").click()}},{html:$("#button_cancel_crop").html(),click:function(){$("#button_cancel_crop").click()},class:"ui-priority-secondary"}];$(".show_when_crop").hide();$("#crop_action, .crop_trigger").click(function(e){var recrop=$(this).attr("data-recrop");if(recrop&&recrop.length>0){window.location.assign(recrop);return true}if(!$form.hasClass("croppable"))return;if(croppingActive)return false;croppingActive=true;$("#selected_image_settings").addClass("cropping_active");$(".hide_when_crop").hide();$(".show_when_crop").show();if($img.hasClass("resizable_setup"))$img.resizable("destroy");var cropSettings={autoCrop:true,autoCropArea:.35,zoomable:false,rotatable:false,maxWidth:$img.attr("data-origwidth"),maxHeight:$img.attr("data-origheight"),minCropBoxWidth:minWidth<2?0:minWidth,minCropBoxHeight:minHeight<2?0:minHeight,minWidth:minWidth<2?0:minWidth,minHeight:minHeight<2?0:minHeight,done:function(data){$("#crop_x").val(Math.floor(data.x));$("#crop_y").val(Math.floor(data.y));$("#crop_w").val(Math.floor(data.width));$("#crop_h").val(Math.floor(data.height));cropData=data}};var crop=$img.attr("data-crop");if(crop&&crop.length>0){crop=crop.split(",");cropSettings.data={x:crop[0],y:crop[1],width:crop[2],height:crop[3]};setTimeout(function(){disablePWImageDialogButtons(cropButtons)},1e3)}else{disablePWImageDialogButtons(cropButtons)}$img.cropper(cropSettings);setTimeout(function(){$(".cropper-canvas").width($(".cropper-container").width()).height($(".cropper-container").height())},500);var cropCoordinatesChange=function(){var data={x:parseInt($("#crop_x").val()),y:parseInt($("#crop_y").val()),width:parseInt($("#crop_w").val()),height:parseInt($("#crop_h").val()),rotate:0};$img.cropper("setData",data)};$("#crop_coordinates input").change(cropCoordinatesChange)});function stopCrop(){$img.cropper("destroy");$(".show_when_crop").hide();$(".hide_when_crop").show();croppingActive=false;$("#selected_image_settings").removeClass("cropping_active");setupImageResizable();enablePWImageDialogButtons()}$("#button_cancel_crop").click(function(){stopCrop()});$("#button_crop").click(function(){if($form.hasClass("processing"))return false;$form.addClass("processing");return true});if($img.attr("data-crop")){$("#crop_action").click()}}function inputPixelsChange(event){if(inputPixelsActive)return;if($(this).parents("#crop_coordinates").length)return;inputPixelsActive=true;var w,h,abort=false,noChange=false,oldWidth=$img.attr("width"),oldHeight=$img.attr("height"),origWidth=parseInt($img.attr("data-origwidth")),origHeight=parseInt($img.attr("data-origheight"));oldWidth=typeof oldWidth=="undefined"?$img.width():parseInt(oldWidth);oldHeight=typeof oldHeight=="undefined"?$img.height():parseInt(oldHeight);if($(this).attr("id")=="input_width"){w=parseInt($(this).val());h=origHeight/(origWidth/w);if(w==oldWidth)noChange=true}else{h=parseInt($(this).val());w=Math.round(h/oldHeight*oldWidth);w=origWidth/(origHeight/h);if(h==oldHeight)noChange=true}if(w<1||h<1||noChange){abort=1}else if(maxWidth>0&&w>maxWidth){abort=2}else if(minWidth>1&&w1&&hmaxWidth)origWidth=maxWidth;if(origWidth>$(window).width()){$("#content").css("overflow-x","auto")}$("#input_width").val(origWidth).change()});$("#min_action").click(function(){var imgWidth=$img.width();var imgHeight=$img.height();var windowWidth=$(window).width()-30;var windowHeight=$(window).height()-$("#wrap_info").height()-60;var updated=false;if(imgHeight>windowHeight){$("#input_height").val(windowHeight).change();updated=true}if(imgWidth>windowWidth){$("#input_width").val(windowWidth).change();updated=true}if(!updated){$("#input_width").val(Math.ceil(imgWidth/2)).change()}});$("#align_left_action, #align_center_action, #align_right_action").click(function(){var $select=$("#selected_image_class");var labelKey=$(this).attr("data-label");if($(this).hasClass("on")){$select.children("option").removeAttr("selected");$(this).removeClass("on")}else{$(this).siblings(".on").removeClass("on");$select.children("option").removeAttr("selected");$select.find("option[data-label="+labelKey+"]").attr("selected","selected");$(this).addClass("on")}$select.change()});var labelKey=$("#selected_image_class").find("option[selected=selected]").attr("data-label");if(labelKey)$("#action_icons").find("span[data-label="+labelKey+"]").addClass("on");$("#resize_action").hover(function(){if($(this).hasClass("on"))return;$("#resize_tips").show();$("#input_width, #input_height").addClass("ui-state-highlight")},function(){if($(this).hasClass("on"))return;$("#resize_tips").hide();$("#input_width, #input_height").removeClass("ui-state-highlight")}).click(function(){if($(this).hasClass("on")){$(this).removeClass("on");$("#input_width, #input_height").removeClass("ui-state-highlight")}else{$(this).addClass("on");$("#input_width, #input_height").addClass("ui-state-highlight")}});$("#description_action").click(function(){if($(this).hasClass("on")){$(this).removeClass("on");$("#wrap_description").slideUp("fast")}else{$(this).addClass("on");$("#wrap_description").slideDown("fast")}})}function setupImageCaption(){$("#selected_image_caption").change(function(){if($form.hasClass("cropping_active"))return;var $caption=$("#caption_preview");if($(this).is(":checked")){$caption.fadeIn()}else if($caption.is(":visible")){$caption.fadeOut()}}).change()}function fitImageToWindow(){var winwidth=$(window).width()-30;var winheight=$(window).height()-($("#wrap_info").height()+60);if($img.width()>winwidth){$img.width(winwidth).css("height","auto").removeAttr("height");$img.removeAttr("height")}if($img.height()>winheight){$img.removeAttr("width").css("width","auto").height(winheight)}$container.width($img.width()).height($img.height())}$("#loading_button").hide();if($img.attr("data-fit")){fitImageToWindow()}else{$container.width($img.width()).height($img.height())}$("#selected_image_settings .input_pixels").change(inputPixelsChange);$("#selected_image_class").change(alignClassChange).change();fullWidth=$img.attr("data-origwidth");populateResizeDimensions();setupImageCroppable();setupImageActions();setupImageCaption();$("button.submit_save_copy, button.submit_save_replace").click(function(){$form.addClass("processing");disablePWImageDialogButtons()})}if($img.length>0){$img=$img.first();if($img.width()>0&&$img.height()>0){setupImage($img)}else{$img.load(function(){$img=$(this);setupImage($img)})}}}$(document).ready(function(){var $page_id=$("#page_id");if($page_id.length>0){var page_id=$page_id.val();$page_id.bind("pageSelected",function(event,data){if(data.id==page_id)return;window.location="./?id="+data.id+"&modal=1"})}if($("#selected_image").length>0){setTimeout(function(){setupSelectedImage()},250)}else if($("#ImageVariations").length>0){setupExecuteVariations()}enablePWImageDialogButtons();$(window).keydown(function(event){if(event.keyCode==13){event.preventDefault();return false}})}); \ No newline at end of file +function enablePWImageDialogButtons(){var $buttonPane=parent.jQuery(".ui-dialog-buttonpane");$buttonPane.find("button").button("enable");return}function disablePWImageDialogButtons(){var $buttonPane=parent.jQuery(".ui-dialog-buttonpane");$buttonPane.find("button").button("disable");return}function closePWImageDialog(){parent.jQuery("iframe.ui-dialog-content").dialog("close")}function setupProcessSaveReloaded(fileID,isNew){if(isNew){var offsetTop=parent.jQuery("#"+fileID).offset().top-20;parent.jQuery("html, body").animate({scrollTop:offsetTop},1e3,"swing");parent.jQuery("#"+fileID).hide();setTimeout(function(){parent.jQuery("#"+fileID).slideDown()},900)}else{parent.jQuery("#"+fileID).find("img").hide();setTimeout(function(){parent.jQuery("#"+fileID).find("img").fadeIn("normal",function(){parent.jQuery("#"+fileID).find(".gridImage__edit").click()})},500)}closePWImageDialog()}function setupProcessSave(fieldName,fileID,isNew){var finished=false;var $inputfield=parent.jQuery("#wrap_Inputfield_"+fieldName);if(!$inputfield.length){$inputfield=parent.jQuery("#"+fileID).closest(".InputfieldImage")}$inputfield.trigger("reload");parent.jQuery(".Inputfield").on("reloaded",function(){if(finished)return;finished=true;if(fileID.length>0){setTimeout(function(){setupProcessSaveReloaded(fileID,isNew)},250)}})}function refreshPageEditField(fieldName){parent.jQuery("#wrap_Inputfield_"+fieldName).trigger("reload")}function setupExecuteVariations(){$(document).on("click","input#delete_all",function(event){if($(this).is(":checked")){$("input.delete").attr("checked","checked")}else{$("input.delete").removeAttr("checked")}event.stopPropagation()});var magnificOptions={type:"image",closeOnContentClick:true,closeBtnInside:true};$("a.preview").magnificPopup(magnificOptions);var $varcnt=$("#varcnt_id");var varcntID=$varcnt.val();var varcnt=$varcnt.attr("data-cnt");window.parent.jQuery("#"+varcntID).text(varcnt)}function setupSelectedImage(){var croppingActive=false;var inputPixelsActive=false;var $form=$("#selected_image_settings");var $container=$("#selected_image_container");var $img=$("#selected_image");var $hidpi=$("#selected_image_hidpi");var fullWidth;var minWidth=0;var minHeight=0;function setupImage($img){var originalWidth=$img.width();var maxWidth=9999;var maxHeight=9999;function updateHidpiCheckbox(w){if(w=maxHeight||w>=maxWidth)&&$form.hasClass("croppable")){w=maxWidth;h=maxHeight;$("#selected_image_link").removeAttr("checked");$link.hide()}else{if(!$link.is(":visible")){$link.fadeIn();if($link.attr("data-was-checked")==1){$link.attr("checked","checked")}}}$("#input_width").val(w);$("#input_height").val(h);$img.attr("width",w);$img.attr("height",h);updateHidpiCheckbox(w);var $latin=$("#latin");if($latin.is(":visible"))$latin.height(h);if(!$form.hasClass("rte")){var $useResize=$("#selected_image_resize");if(originalWidth<=w){$useResize.hide()}else{if(!$useResize.is(":visible"))$useResize.fadeIn()}}}function setupImageResizable(){$img.resizable({aspectRatio:true,handles:"n, ne, e, se, s, sw, w",alsoResize:"#selected_image_container",maxWidth:maxWidth,maxHeight:maxHeight,minWidth:10,minHeight:10,start:function(){$form.addClass("resizing_active")},stop:function(){$img.attr("width",$img.width()).attr("height",$img.height());if(originalWidth!=$img.width()){$img.addClass("resized");if(!$form.hasClass("rte")){var $resizeYes=$("#selected_image_resize_yes");if(!$resizeYes.is(":checked")){$resizeYes.attr("checked","checked");$("#selected_image_resize_no").removeAttr("checked")}}}$form.removeClass("resizing_active");if($("#resize_action").hasClass("on"))$("#resize_action").click().mouseout()},resize:populateResizeDimensions});$img.addClass("resizable_setup")}var cropData=null;function setupImageCroppable(){var cropButtons=[{html:$("#button_crop").html(),click:function(){$("#button_crop").click()}},{html:$("#button_cancel_crop").html(),click:function(){$("#button_cancel_crop").click()},class:"ui-priority-secondary"}];$(".show_when_crop").hide();$("#crop_action, .crop_trigger").click(function(e){var recrop=$(this).attr("data-recrop");if(recrop&&recrop.length>0){window.location.assign(recrop);return true}if(!$form.hasClass("croppable"))return;if(croppingActive)return false;croppingActive=true;$("#selected_image_settings").addClass("cropping_active");$(".hide_when_crop").hide();$(".show_when_crop").show();if($img.hasClass("resizable_setup"))$img.resizable("destroy");var cropSettings={autoCrop:true,autoCropArea:.35,zoomable:false,rotatable:false,maxWidth:$img.attr("data-origwidth"),maxHeight:$img.attr("data-origheight"),minCropBoxWidth:minWidth<2?0:minWidth,minCropBoxHeight:minHeight<2?0:minHeight,minWidth:minWidth<2?0:minWidth,minHeight:minHeight<2?0:minHeight,done:function(data){$("#crop_x").val(Math.floor(data.x));$("#crop_y").val(Math.floor(data.y));$("#crop_w").val(Math.floor(data.width));$("#crop_h").val(Math.floor(data.height));cropData=data}};var crop=$img.attr("data-crop");if(crop&&crop.length>0){crop=crop.split(",");cropSettings.data={x:crop[0],y:crop[1],width:crop[2],height:crop[3]};setTimeout(function(){disablePWImageDialogButtons(cropButtons)},1e3)}else{disablePWImageDialogButtons(cropButtons)}$img.cropper(cropSettings);setTimeout(function(){$(".cropper-canvas").width($(".cropper-container").width()).height($(".cropper-container").height())},500);var cropCoordinatesChange=function(){var data={x:parseInt($("#crop_x").val()),y:parseInt($("#crop_y").val()),width:parseInt($("#crop_w").val()),height:parseInt($("#crop_h").val()),rotate:0};$img.cropper("setData",data)};$("#crop_coordinates input").change(cropCoordinatesChange)});function stopCrop(){$img.cropper("destroy");$(".show_when_crop").hide();$(".hide_when_crop").show();croppingActive=false;$("#selected_image_settings").removeClass("cropping_active");setupImageResizable();enablePWImageDialogButtons()}$("#button_cancel_crop").click(function(){stopCrop()});$("#button_crop").click(function(){if($form.hasClass("processing"))return false;$form.addClass("processing");return true});if($img.attr("data-crop")){$("#crop_action").click()}}function inputPixelsChange(event){if(inputPixelsActive)return;if($(this).parents("#crop_coordinates").length)return;inputPixelsActive=true;var w,h,abort=false,noChange=false,oldWidth=$img.attr("width"),oldHeight=$img.attr("height"),origWidth=parseInt($img.attr("data-origwidth")),origHeight=parseInt($img.attr("data-origheight"));oldWidth=typeof oldWidth=="undefined"?$img.width():parseInt(oldWidth);oldHeight=typeof oldHeight=="undefined"?$img.height():parseInt(oldHeight);if($(this).attr("id")=="input_width"){w=parseInt($(this).val());h=origHeight/(origWidth/w);if(w==oldWidth)noChange=true}else{h=parseInt($(this).val());w=Math.round(h/oldHeight*oldWidth);w=origWidth/(origHeight/h);if(h==oldHeight)noChange=true}if(w<1||h<1||noChange){abort=1}else if(maxWidth>0&&w>maxWidth){abort=2}else if(minWidth>1&&w1&&hmaxWidth)origWidth=maxWidth;if(origWidth>$(window).width()){$("#content").css("overflow-x","auto")}$("#input_width").val(origWidth).change()});$("#min_action").click(function(){var imgWidth=$img.width();var imgHeight=$img.height();var windowWidth=$(window).width()-30;var windowHeight=$(window).height()-$("#wrap_info").height()-60;var updated=false;if(imgHeight>windowHeight){$("#input_height").val(windowHeight).change();updated=true}if(imgWidth>windowWidth){$("#input_width").val(windowWidth).change();updated=true}if(!updated){$("#input_width").val(Math.ceil(imgWidth/2)).change()}});$("#align_left_action, #align_center_action, #align_right_action").click(function(){var $select=$("#selected_image_class");var labelKey=$(this).attr("data-label");if($(this).hasClass("on")){$select.children("option").removeAttr("selected");$(this).removeClass("on")}else{$(this).siblings(".on").removeClass("on");$select.children("option").removeAttr("selected");$select.find("option[data-label="+labelKey+"]").attr("selected","selected");$(this).addClass("on")}$select.change()});var labelKey=$("#selected_image_class").find("option[selected=selected]").attr("data-label");if(labelKey)$("#action_icons").find("span[data-label="+labelKey+"]").addClass("on");$("#resize_action").hover(function(){if($(this).hasClass("on"))return;$("#resize_tips").show();$("#input_width, #input_height").addClass("ui-state-highlight")},function(){if($(this).hasClass("on"))return;$("#resize_tips").hide();$("#input_width, #input_height").removeClass("ui-state-highlight")}).click(function(){if($(this).hasClass("on")){$(this).removeClass("on");$("#input_width, #input_height").removeClass("ui-state-highlight")}else{$(this).addClass("on");$("#input_width, #input_height").addClass("ui-state-highlight")}});$("#description_action").click(function(){if($(this).hasClass("on")){$(this).removeClass("on");$("#wrap_description").slideUp("fast")}else{$(this).addClass("on");$("#wrap_description").slideDown("fast")}})}function setupImageCaption(){$("#selected_image_caption").change(function(){if($form.hasClass("cropping_active"))return;var $caption=$("#caption_preview");if($(this).is(":checked")){$caption.fadeIn()}else if($caption.is(":visible")){$caption.fadeOut()}}).change()}function fitImageToWindow(){var winwidth=$(window).width()-30;var winheight=$(window).height()-($("#wrap_info").height()+60);if($img.width()>winwidth){$img.width(winwidth).css("height","auto").removeAttr("height");$img.removeAttr("height")}if($img.height()>winheight){$img.removeAttr("width").css("width","auto").height(winheight)}$container.width($img.width()).height($img.height())}$("#loading_button").hide();if($img.attr("data-fit")){fitImageToWindow()}else{$container.width($img.width()).height($img.height())}$("#selected_image_settings .input_pixels").change(inputPixelsChange);$("#selected_image_class").change(alignClassChange).change();fullWidth=$img.attr("data-origwidth");populateResizeDimensions();setupImageCroppable();setupImageActions();setupImageCaption();$("button.submit_save_copy, button.submit_save_replace").click(function(){$form.addClass("processing");disablePWImageDialogButtons()})}if($img.length>0){$img=$img.first();if($img.width()>0&&$img.height()>0){setupImage($img)}else{$img.load(function(){$img=$(this);setupImage($img)})}}}$(document).ready(function(){var $page_id=$("#page_id");if($page_id.length>0){var page_id=$page_id.val();$page_id.bind("pageSelected",function(event,data){if(data.id==page_id)return;window.location="./?id="+data.id+"&modal=1"})}if($("#selected_image").length>0){setTimeout(function(){setupSelectedImage()},250)}else if($("#ImageVariations").length>0){setupExecuteVariations()}enablePWImageDialogButtons();$(window).keydown(function(event){if(event.keyCode==13){event.preventDefault();return false}})}); \ No newline at end of file diff --git a/wire/modules/Process/ProcessPageEditImageSelect/ProcessPageEditImageSelect.module b/wire/modules/Process/ProcessPageEditImageSelect/ProcessPageEditImageSelect.module index 26bcb787..8fd47b65 100644 --- a/wire/modules/Process/ProcessPageEditImageSelect/ProcessPageEditImageSelect.module +++ b/wire/modules/Process/ProcessPageEditImageSelect/ProcessPageEditImageSelect.module @@ -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 */