diff --git a/CHANGELOG.md b/CHANGELOG.md
index df661887..960b9b69 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# ImageOptimize Changelog
+## 1.2.1 - 2017.09.10
+### Changed
+* Fixed an issue that could leave stale image variants around
+* Ensure that the optimized image variants are re-created if the image is edited
+* Added logging to show the savings for image variants
+* Fixed the way the Settings page is rendered
+* Updated `README.md`
+
## 1.2.0 - 2017.09.08
### Added
* Added `OptimzedImages` Field
diff --git a/composer.json b/composer.json
index 5bbb7056..3db415f4 100644
--- a/composer.json
+++ b/composer.json
@@ -2,7 +2,7 @@
"name": "nystudio107/craft3-imageoptimize",
"description": "Automatically create & optimize responsive image transforms",
"type": "craft-plugin",
- "version": "1.2.0",
+ "version": "1.2.1",
"keywords": [
"craft",
"cms",
diff --git a/src/ImageOptimize.php b/src/ImageOptimize.php
index 1a6caeb5..395c37a0 100644
--- a/src/ImageOptimize.php
+++ b/src/ImageOptimize.php
@@ -24,12 +24,14 @@
use craft\events\VolumeEvent;
use craft\models\FieldLayout;
use craft\services\AssetTransforms;
-use craft\services\Elements;
use craft\services\Fields;
use craft\services\Volumes;
+use craft\web\Controller;
use yii\base\Event;
+/** @noinspection MissingPropertyAnnotationsInspection */
+
/**
* Class ImageOptimize
*
@@ -168,6 +170,26 @@ function (GenerateTransformEvent $event) {
);
}
+ /**
+ * @inheritdoc
+ */
+ public function getSettingsResponse()
+ {
+ $view = Craft::$app->getView();
+ $namespace = $view->getNamespace();
+ $view->setNamespace('settings');
+ $settingsHtml = $this->settingsHtml();
+ $view->setNamespace($namespace);
+
+ /** @var Controller $controller */
+ $controller = Craft::$app->controller;
+
+ return $controller->renderTemplate('image-optimize/_settings', [
+ 'plugin' => $this,
+ 'settingsHtml' => $settingsHtml
+ ]);
+ }
+
/**
* @inheritdoc
*/
diff --git a/src/fields/OptimizedImages.php b/src/fields/OptimizedImages.php
index c4d338bd..9127d678 100644
--- a/src/fields/OptimizedImages.php
+++ b/src/fields/OptimizedImages.php
@@ -11,7 +11,6 @@
namespace nystudio107\imageoptimize\fields;
use craft\models\AssetTransform;
-use nystudio107\imageoptimize\ImageOptimize;
use nystudio107\imageoptimize\assetbundles\optimizedimagesfield\OptimizedImagesFieldAsset;
use nystudio107\imageoptimize\models\OptimizedImage;
@@ -24,6 +23,8 @@
use yii\db\Schema;
+/** @noinspection MissingPropertyAnnotationsInspection */
+
/**
* @author nystudio107
* @package ImageOptimize
@@ -124,10 +125,10 @@ public function beforeElementSave(ElementInterface $element, bool $isNew): bool
*/
public function afterElementSave(ElementInterface $element, bool $isNew)
{
- // If this is a new element, resave it so that it as an id for our asset transforms
- if ($isNew) {
- /** @var Asset $element */
- if ($element instanceof Asset) {
+ /** @var Asset $element */
+ if ($element instanceof Asset) {
+ // If this is a new element, resave it so that it as an id for our asset transforms
+ if ($isNew) {
// Initialize our field with defaults
$this->currentAsset = $element;
$defaultData = $this->normalizeValue(null, $element);
@@ -138,23 +139,19 @@ public function afterElementSave(ElementInterface $element, bool $isNew)
$success = Craft::$app->getElements()->saveElement($element, false);
Craft::info(
- print_r('Re-saved new asset ' . $success, true),
+ print_r('Re-saved new asset '.$success, true),
__METHOD__
);
+ } else {
+ // Otherwise create a dummy model, and populate it, to recreate any asset transforms
+ $model = new OptimizedImage();
+ $this->populateOptimizedImageModel($element, $model);
}
}
parent::afterElementSave($element, $isNew);
}
- /**
- * @inheritdoc
- */
- public function getContentColumnType(): string
- {
- return Schema::TYPE_TEXT;
- }
-
/**
* @inheritdoc
*/
@@ -173,6 +170,50 @@ public function normalizeValue($value, ElementInterface $element = null)
return $model;
}
+ /**
+ * @param Asset $element
+ * @param OptimizedImage $model
+ */
+ protected function populateOptimizedImageModel(Asset $element, OptimizedImage $model)
+ {
+ // Empty our the optimized image URLs
+ $model->optimizedImageUrls = [];
+ $model->optimizedWebPImageUrls = [];
+
+ /** @var AssetTransform $transform */
+ $transform = new AssetTransform();
+
+ foreach ($this->variants as $variant) {
+ // Create the transform based on the variant
+ $aspectRatio = $variant['aspectRatioX'] / $variant['aspectRatioY'];
+ $width = $variant['width'];
+ $transform->width = $width;
+ $transform->height = intval($width / $aspectRatio);
+ $transform->quality = $variant['quality'];
+ $transform->format = $variant['format'];
+
+ // Force generateTransformsBeforePageLoad = true to generate the images now
+ $generalConfig = Craft::$app->getConfig()->getGeneral();
+ $oldSetting = $generalConfig->generateTransformsBeforePageLoad;
+ $generalConfig->generateTransformsBeforePageLoad = true;
+ // Generate the URLs to the optimized images
+ $url = $element->getUrl($transform);
+ $generalConfig->generateTransformsBeforePageLoad = $oldSetting;
+
+ // Update the model
+ $model->optimizedImageUrls[$width] = $url;
+ $model->optimizedWebPImageUrls[$width] = $url.'.webp';
+ $model->focalPoint = $element->focalPoint;
+ $model->originalImageWidth = $element->width;
+ $model->originalImageHeight = $element->height;
+
+ Craft::info(
+ 'Created transforms for variant: '.print_r($variant, true),
+ __METHOD__
+ );
+ }
+ }
+
/**
* @inheritdoc
*/
@@ -181,6 +222,14 @@ public function serializeValue($value, ElementInterface $element = null)
return parent::serializeValue($value, $element);
}
+ /**
+ * @inheritdoc
+ */
+ public function getContentColumnType(): string
+ {
+ return Schema::TYPE_TEXT;
+ }
+
/**
* @inheritdoc
*/
@@ -192,22 +241,25 @@ public function getSettingsHtml()
$namespacedId = Craft::$app->getView()->namespaceInputId($id);
$namespacePrefix = Craft::$app->getView()->namespaceInputName($thisId);
Craft::$app->getView()->registerJs('new Craft.OptimizedImagesInput('.
- '"'. $namespacedId .'", '.
- '"'. $namespacePrefix .'"'.
+ '"'.$namespacedId.'", '.
+ '"'.$namespacePrefix.'"'.
');');
// Render the settings template
return Craft::$app->getView()->renderTemplate(
'image-optimize/_components/fields/OptimizedImages_settings',
[
- 'field' => $this,
- 'id' => $id,
- 'name' => $this->handle,
+ 'field' => $this,
+ 'id' => $id,
+ 'name' => $this->handle,
'namespace' => $namespacedId,
]
);
}
+ // Protected Methods
+ // =========================================================================
+
/**
* @inheritdoc
*/
@@ -218,77 +270,29 @@ public function getInputHtml($value, ElementInterface $element = null): string
// Get our id and namespace
$id = Craft::$app->getView()->formatInputId($this->handle);
- $namespacedId = Craft::$app->getView()->namespaceInputId($id);
+ $nameSpaceId = Craft::$app->getView()->namespaceInputId($id);
// Variables to pass down to our field JavaScript to let it namespace properly
$jsonVars = [
- 'id' => $id,
- 'name' => $this->handle,
- 'namespace' => $namespacedId,
- 'prefix' => Craft::$app->getView()->namespaceInputId(''),
+ 'id' => $id,
+ 'name' => $this->handle,
+ 'namespace' => $nameSpaceId,
+ 'prefix' => Craft::$app->getView()->namespaceInputId(''),
];
$jsonVars = Json::encode($jsonVars);
- Craft::$app->getView()->registerJs("$('#{$namespacedId}-field').ImageOptimizeOptimizedImages(" . $jsonVars . ");");
+ Craft::$app->getView()->registerJs("$('#{$nameSpaceId}-field').ImageOptimizeOptimizedImages(".$jsonVars.");");
// Render the input template
return Craft::$app->getView()->renderTemplate(
'image-optimize/_components/fields/OptimizedImages_input',
[
- 'name' => $this->handle,
- 'value' => $value,
- 'variants' => $this->variants,
- 'field' => $this,
- 'id' => $id,
- 'namespacedId' => $namespacedId,
+ 'name' => $this->handle,
+ 'value' => $value,
+ 'variants' => $this->variants,
+ 'field' => $this,
+ 'id' => $id,
+ 'nameSpaceId' => $nameSpaceId,
]
);
}
-
- // Protected Methods
- // =========================================================================
-
- /**
- * @param Asset $element
- * @param OptimizedImage $model
- */
- protected function populateOptimizedImageModel(Asset $element, OptimizedImage $model)
- {
- // Empty our the optimized image URLs
- $model->optimizedImageUrls = [];
- $model->optimizedWebPImageUrls = [];
-
- /** @var AssetTransform $transform */
- $transform = new AssetTransform();
-
- foreach ($this->variants as $variant) {
- // Create the transform based on the variant
- $aspectRatio = $variant['aspectRatioX'] / $variant['aspectRatioY'];
- $width = $variant['width'];
- $transform->width = $width;
- $transform->height = intval($width / $aspectRatio);
- $transform->quality = $variant['quality'];
- $transform->format = $variant['format'];
-
- // Force generateTransformsBeforePageLoad = true to generate the images now
- $generalConfig = Craft::$app->getConfig()->getGeneral();
- $oldSetting = $generalConfig->generateTransformsBeforePageLoad;
- $generalConfig->generateTransformsBeforePageLoad = true;
- // Generate the URLs to the optimized images
- $url = $element->getUrl($transform);
- $generalConfig->generateTransformsBeforePageLoad = $oldSetting;
-
- // Update the model
- $model->optimizedImageUrls[$width] = $url;
- $model->optimizedWebPImageUrls[$width] = $url . '.webp';
- $model->focalPoint = $element->focalPoint;
- $model->originalImageWidth = $element->width;
- $model->originalImageHeight = $element->height;
-
- Craft::info(
- 'Created transforms for variant: ' . print_r($variant, true),
- __METHOD__
- );
- }
- }
-
}
diff --git a/src/models/OptimizedImage.php b/src/models/OptimizedImage.php
index 688da866..07943ceb 100644
--- a/src/models/OptimizedImage.php
+++ b/src/models/OptimizedImage.php
@@ -12,7 +12,6 @@
use nystudio107\imageoptimize\ImageOptimize;
-use Craft;
use craft\helpers\UrlHelper;
use craft\base\Model;
use craft\validators\ArrayValidator;
diff --git a/src/services/Optimize.php b/src/services/Optimize.php
index 78f4241f..38ac12af 100644
--- a/src/services/Optimize.php
+++ b/src/services/Optimize.php
@@ -10,6 +10,7 @@
namespace nystudio107\imageoptimize\services;
+use craft\errors\VolumeException;
use nystudio107\imageoptimize\ImageOptimize;
use Craft;
@@ -25,6 +26,8 @@
use mikehaertl\shellcommand\Command as ShellCommand;
+/** @noinspection MissingPropertyAnnotationsInspection */
+
/**
* @author nystudio107
* @package ImageOptimize
@@ -61,21 +64,21 @@ public function handleGenerateTransformEvent(GenerateTransformEvent $event): str
$index = $event->transformIndex;
Craft::info(
pathinfo($index->filename, PATHINFO_FILENAME)
- . '.'
- . $index->detectedFormat
- . ' -> '
- . Craft::t('image-optimize', 'Original')
- . ': '
- . $this->humanFileSize($originalFileSize, 1)
- . ', '
- . Craft::t('image-optimize', 'Optimized')
- . ': '
- . $this->humanFileSize($optimizedFileSize, 1)
- . ' -> '
- . Craft::t('image-optimize', 'Savings')
- . ': '
- . number_format(abs((1 - ($originalFileSize / $optimizedFileSize)) * 100), 1)
- . '%',
+ .'.'
+ .$index->detectedFormat
+ .' -> '
+ .Craft::t('image-optimize', 'Original')
+ .': '
+ .$this->humanFileSize($originalFileSize, 1)
+ .', '
+ .Craft::t('image-optimize', 'Optimized')
+ .': '
+ .$this->humanFileSize($optimizedFileSize, 1)
+ .' -> '
+ .Craft::t('image-optimize', 'Savings')
+ .': '
+ .number_format(abs((1 - ($originalFileSize / $optimizedFileSize)) * 100), 1)
+ .'%',
__METHOD__
);
// Create any image variants
@@ -98,10 +101,10 @@ public function handleGenerateTransformEvent(GenerateTransformEvent $event): str
*/
public function saveTransformToTempFile(AssetTransformIndex $index, Image $image): string
{
- $tempFilename = uniqid(pathinfo($index->filename, PATHINFO_FILENAME), true) . '.' . $index->detectedFormat;
- $tempPath = Craft::$app->getPath()->getTempPath() . DIRECTORY_SEPARATOR . $tempFilename;
+ $tempFilename = uniqid(pathinfo($index->filename, PATHINFO_FILENAME), true).'.'.$index->detectedFormat;
+ $tempPath = Craft::$app->getPath()->getTempPath().DIRECTORY_SEPARATOR.$tempFilename;
$image->saveAs($tempPath);
- Craft::info('Transformed image saved to: ' . $tempPath, __METHOD__);
+ Craft::info('Transformed image saved to: '.$tempPath, __METHOD__);
return $tempPath;
}
@@ -130,127 +133,76 @@ public function optimizeImage(AssetTransformIndex $index, string $tempPath)
}
/**
- * Create any image variants for the image file
- *
- * @param AssetTransformIndex $index
- * @param Asset $asset
- * @param string $tempPath
+ * @param string $tempPath
+ * @param $thisProcessor
*/
- public function createImageVariants(AssetTransformIndex $index, Asset $asset, string $tempPath)
+ protected function executeImageProcessor($thisProcessor, string $tempPath)
{
- $settings = ImageOptimize::$plugin->getSettings();
- // Get the active image variant creators
- $activeImageVariantCreators = $settings['activeImageVariantCreators'];
- $fileFormat = $index->detectedFormat;
- if (!empty($activeImageVariantCreators[$fileFormat])) {
- // Iterate through all of the image variant creators for this format
- $imageVariantCreators = $settings['imageVariantCreators'];
- foreach ($activeImageVariantCreators[$fileFormat] as $variantCreator) {
- if (!empty($imageVariantCreators[$variantCreator])) {
- // Create the image variant in a temporary folder
- $quality = $index->transform->quality ?: Craft::$app->getConfig()->getGeneral()->defaultImageQuality;
- $outputPath = $this->executeVariantCreator(
- $imageVariantCreators[$variantCreator],
- $tempPath,
- $quality
- );
- // Copy the image variant into place
- $this->copyImageVariantToVolume(
- $imageVariantCreators[$variantCreator],
- $asset,
- $index,
- $outputPath
- );
- }
+ // Make sure the command exists
+ if (file_exists($thisProcessor['commandPath'])) {
+ // Set any options for the command
+ $commandOptions = '';
+ if (!empty($thisProcessor['commandOptions'])) {
+ $commandOptions = ' '
+ .$thisProcessor['commandOptions']
+ .' ';
}
+ // Redirect the command output if necessary for this processor
+ $outputFileFlag = '';
+ if (!empty($thisProcessor['commandOutputFileFlag'])) {
+ $outputFileFlag = ' '
+ .$thisProcessor['commandOutputFileFlag']
+ .' '
+ .escapeshellarg($tempPath)
+ .' ';
+ }
+ // Build the command to execute
+ $cmd =
+ $thisProcessor['commandPath']
+ .$commandOptions
+ .$outputFileFlag
+ .escapeshellarg($tempPath);
+ // Execute the command
+ $shellOutput = $this->executeShellCommand($cmd);
+ Craft::info($cmd."\n".$shellOutput, __METHOD__);
+ } else {
+ Craft::error(
+ $thisProcessor['commandPath']
+ .' '
+ .Craft::t('image-optimize', 'does not exist'),
+ __METHOD__
+ );
}
}
/**
- * Return an array of active image processors
+ * Execute a shell command
*
- * @return array
+ * @param string $command
+ *
+ * @return string
*/
- public function getActiveImageProcessors(): array
+ protected function executeShellCommand(string $command): string
{
- $result = [];
- $settings = ImageOptimize::$plugin->getSettings();
- // Get the active processors for the transform format
- $activeImageProcessors = $settings['activeImageProcessors'];
- foreach ($activeImageProcessors as $imageFormat => $imageProcessor) {
- // Iterate through all of the processors for this format
- $imageProcessors = $settings['imageProcessors'];
- foreach ($activeImageProcessors[$imageFormat] as $processor) {
- if (!empty($imageProcessors[$processor])) {
- $thisImageProcessor = $imageProcessors[$processor];
- $result[] = [
- 'format' => $imageFormat,
- 'creator' => $processor,
- 'command' => $thisImageProcessor['commandPath']
- . ' '
- . $thisImageProcessor['commandOptions'],
- 'installed' => file_exists($thisImageProcessor['commandPath']),
- ];
- }
- }
- }
+ // Create the shell command
+ $shellCommand = new ShellCommand();
+ $shellCommand->setCommand($command);
- return $result;
- }
+ // If we don't have proc_open, maybe we've got exec
+ if (!function_exists('proc_open') && function_exists('exec')) {
+ $shellCommand->useExec = true;
+ }
- /**
- * Return an array of active image variant creators
- *
- * @return array
- */
- public function getActiveVariantCreators(): array
- {
- $result = [];
- $settings = ImageOptimize::$plugin->getSettings();
- // Get the active image variant creators
- $activeImageVariantCreators = $settings['activeImageVariantCreators'];
- foreach ($activeImageVariantCreators as $imageFormat => $imageCreator) {
- // Iterate through all of the image variant creators for this format
- $imageVariantCreators = $settings['imageVariantCreators'];
- foreach ($activeImageVariantCreators[$imageFormat] as $variantCreator) {
- if (!empty($imageVariantCreators[$variantCreator])) {
- $thisVariantCreator = $imageVariantCreators[$variantCreator];
- $result[] = [
- 'format' => $imageFormat,
- 'creator' => $variantCreator,
- 'command' => $thisVariantCreator['commandPath']
- . ' '
- . $thisVariantCreator['commandOptions'],
- 'installed' => file_exists($thisVariantCreator['commandPath']),
- ];
- }
- }
+ // Return the result of the command's output or error
+ if ($shellCommand->execute()) {
+ $result = $shellCommand->getOutput();
+ } else {
+ $result = $shellCommand->getError();
}
return $result;
}
- /**
- * Resave all of the Asset elements in the Volume $volume
- *
- * @param Volume $volume
- */
- public function resaveVolumeAssets(Volume $volume)
- {
- $siteId = Craft::$app->getSites()->getPrimarySite()->id;
-
- Craft::$app->getQueue()->push(new ResaveElements([
- 'description' => Craft::t('image-optimize', 'Resaving Assets in {name}', ['name' => $volume->name]),
- 'elementType' => Asset::class,
- 'criteria' => [
- 'siteId' => $siteId,
- 'volumeId' => $volume->id,
- 'status' => null,
- 'enabledForSite' => false,
- ],
- ]));
- }
-
/**
* Translate bytes into something human-readable
*
@@ -264,52 +216,73 @@ public function humanFileSize($bytes, $decimals = 2): string
$sz = 'BKMGTP';
$factor = floor((strlen($bytes) - 1) / 3);
- return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . @$sz[intval($factor)];
+ return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)).@$sz[intval($factor)];
}
- // Protected Methods
- // =========================================================================
-
/**
- * @param string $tempPath
- * @param $thisProcessor
+ * Create any image variants for the image file
+ *
+ * @param AssetTransformIndex $index
+ * @param Asset $asset
+ * @param string $tempPath
*/
- protected function executeImageProcessor($thisProcessor, string $tempPath)
+ public function createImageVariants(AssetTransformIndex $index, Asset $asset, string $tempPath)
{
- // Make sure the command exists
- if (file_exists($thisProcessor['commandPath'])) {
- // Set any options for the command
- $commandOptions = '';
- if (!empty($thisProcessor['commandOptions'])) {
- $commandOptions = ' '
- . $thisProcessor['commandOptions']
- . ' ';
- }
- // Redirect the command output if necessary for this processor
- $outputFileFlag = '';
- if (!empty($thisProcessor['commandOutputFileFlag'])) {
- $outputFileFlag = ' '
- . $thisProcessor['commandOutputFileFlag']
- . ' '
- . escapeshellarg($tempPath)
- . ' ';
+ $settings = ImageOptimize::$plugin->getSettings();
+ // Get the active image variant creators
+ $activeImageVariantCreators = $settings['activeImageVariantCreators'];
+ $fileFormat = $index->detectedFormat;
+ if (!empty($activeImageVariantCreators[$fileFormat])) {
+ // Iterate through all of the image variant creators for this format
+ $imageVariantCreators = $settings['imageVariantCreators'];
+ foreach ($activeImageVariantCreators[$fileFormat] as $variantCreator) {
+ if (!empty($imageVariantCreators[$variantCreator])) {
+ // Create the image variant in a temporary folder
+ $generalConfig = Craft::$app->getConfig()->getGeneral();
+ $quality = $index->transform->quality ?: $generalConfig->defaultImageQuality;
+ $outputPath = $this->executeVariantCreator(
+ $imageVariantCreators[$variantCreator],
+ $tempPath,
+ $quality
+ );
+
+ // Get info on the original and the created variant
+ $originalFileSize = filesize($tempPath);
+ $variantFileSize = filesize($outputPath);
+
+ Craft::info(
+ pathinfo($tempPath, PATHINFO_FILENAME)
+ .'.'
+ .pathinfo($tempPath, PATHINFO_EXTENSION)
+ .' -> '
+ .pathinfo($outputPath, PATHINFO_FILENAME)
+ .'.'
+ .pathinfo($outputPath, PATHINFO_EXTENSION)
+ .' -> '
+ .Craft::t('image-optimize', 'Original')
+ .': '
+ .$this->humanFileSize($originalFileSize, 1)
+ .', '
+ .Craft::t('image-optimize', 'Variant')
+ .': '
+ .$this->humanFileSize($variantFileSize, 1)
+ .' -> '
+ .Craft::t('image-optimize', 'Savings')
+ .': '
+ .number_format(abs((1 - ($originalFileSize / $variantFileSize)) * 100), 1)
+ .'%',
+ __METHOD__
+ );
+
+ // Copy the image variant into place
+ $this->copyImageVariantToVolume(
+ $imageVariantCreators[$variantCreator],
+ $asset,
+ $index,
+ $outputPath
+ );
+ }
}
- // Build the command to execute
- $cmd =
- $thisProcessor['commandPath']
- . $commandOptions
- . $outputFileFlag
- . escapeshellarg($tempPath);
- // Execute the command
- $shellOutput = $this->executeShellCommand($cmd);
- Craft::info($cmd . "\n" . $shellOutput, __METHOD__);
- } else {
- Craft::error(
- $thisProcessor['commandPath']
- . ' '
- . Craft::t('image-optimize', 'does not exist'),
- __METHOD__
- );
}
}
@@ -322,51 +295,51 @@ protected function executeImageProcessor($thisProcessor, string $tempPath)
*/
protected function executeVariantCreator($variantCreatorCommand, string $tempPath, int $imageQuality): string
{
- $outputPath = '';
+ $outputPath = $tempPath;
// Make sure the command exists
if (file_exists($variantCreatorCommand['commandPath'])) {
// Get the output file for this image variant
- $outputPath .= '.' . $variantCreatorCommand['imageVariantExtension'];
+ $outputPath .= '.'.$variantCreatorCommand['imageVariantExtension'];
// Set any options for the command
$commandOptions = '';
if (!empty($variantCreatorCommand['commandOptions'])) {
$commandOptions = ' '
- . $variantCreatorCommand['commandOptions']
- . ' ';
+ .$variantCreatorCommand['commandOptions']
+ .' ';
}
// Redirect the command output if necessary for this variantCreator
$outputFileFlag = '';
if (!empty($variantCreatorCommand['commandOutputFileFlag'])) {
$outputFileFlag = ' '
- . $variantCreatorCommand['commandOutputFileFlag']
- . ' '
- . escapeshellarg($outputPath)
- . ' ';
+ .$variantCreatorCommand['commandOutputFileFlag']
+ .' '
+ .escapeshellarg($outputPath)
+ .' ';
}
// Get the quality setting of this transform
$commandQualityFlag = '';
if (!empty($variantCreatorCommand['commandQualityFlag'])) {
$commandQualityFlag = ' '
- . $variantCreatorCommand['commandQualityFlag']
- . ' '
- . $imageQuality
- . ' ';
+ .$variantCreatorCommand['commandQualityFlag']
+ .' '
+ .$imageQuality
+ .' ';
}
// Build the command to execute
$cmd =
$variantCreatorCommand['commandPath']
- . $commandOptions
- . $commandQualityFlag
- . $outputFileFlag
- . escapeshellarg($tempPath);
+ .$commandOptions
+ .$commandQualityFlag
+ .$outputFileFlag
+ .escapeshellarg($tempPath);
// Execute the command
$shellOutput = $this->executeShellCommand($cmd);
- Craft::info($cmd . "\n" . $shellOutput, __METHOD__);
+ Craft::info($cmd."\n".$shellOutput, __METHOD__);
} else {
Craft::error(
$variantCreatorCommand['commandPath']
- . ' '
- . Craft::t('image-optimize', 'does not exist'),
+ .' '
+ .Craft::t('image-optimize', 'does not exist'),
__METHOD__
);
}
@@ -374,6 +347,9 @@ protected function executeVariantCreator($variantCreatorCommand, string $tempPat
return $outputPath;
}
+ // Protected Methods
+ // =========================================================================
+
/**
* @param $variantCreatorCommand
* @param Asset $asset
@@ -391,19 +367,22 @@ protected function copyImageVariantToVolume(
// Figure out the resulting path for the image variant
$volume = $asset->getVolume();
$assetTransforms = Craft::$app->getAssetTransforms();
- $transformPath = $asset->getFolder()->path . $assetTransforms->getTransformSubpath($asset, $index);
- $transformPath .= '.' . $variantCreatorCommand['imageVariantExtension'];
+ $transformPath = $asset->getFolder()->path.$assetTransforms->getTransformSubpath($asset, $index);
+ $variantPath = $transformPath.'.'.$variantCreatorCommand['imageVariantExtension'];
- // No need to create the file if it already exists
- if ($volume->fileExists($transformPath)) {
- return;
+ // Delete the variant file in case it is stale
+ try {
+ $volume->deleteFile($variantPath);
+ } catch (VolumeException $e) {
+ // We're fine with that.
}
- clearstatcache(true, $outputPath);
+ clearstatcache(true, $outputPath);
$stream = fopen($outputPath, 'rb');
+ // Now create it
try {
- $volume->createFileByStream($transformPath, $stream, []);
+ $volume->createFileByStream($variantPath, $stream, []);
} catch (VolumeObjectExistsException $e) {
// We're fine with that.
}
@@ -412,40 +391,97 @@ protected function copyImageVariantToVolume(
} else {
Craft::error(
Craft::t('image-optimize', 'Failed to create image variant at: ')
- . $outputPath,
+ .$outputPath,
__METHOD__
);
}
}
/**
- * Execute a shell command
- *
- * @param string $command
+ * Return an array of active image processors
*
- * @return string
+ * @return array
*/
- protected function executeShellCommand(string $command): string
+ public function getActiveImageProcessors(): array
{
- // Create the shell command
- $shellCommand = new ShellCommand();
- $shellCommand->setCommand($command);
-
- // If we don't have proc_open, maybe we've got exec
- if (!function_exists('proc_open') && function_exists('exec')) {
- $shellCommand->useExec = true;
+ $result = [];
+ $settings = ImageOptimize::$plugin->getSettings();
+ // Get the active processors for the transform format
+ $activeImageProcessors = $settings['activeImageProcessors'];
+ foreach ($activeImageProcessors as $imageFormat => $imageProcessor) {
+ // Iterate through all of the processors for this format
+ $imageProcessors = $settings['imageProcessors'];
+ foreach ($activeImageProcessors[$imageFormat] as $processor) {
+ if (!empty($imageProcessors[$processor])) {
+ $thisImageProcessor = $imageProcessors[$processor];
+ $result[] = [
+ 'format' => $imageFormat,
+ 'creator' => $processor,
+ 'command' => $thisImageProcessor['commandPath']
+ .' '
+ .$thisImageProcessor['commandOptions'],
+ 'installed' => file_exists($thisImageProcessor['commandPath']),
+ ];
+ }
+ }
}
- // Return the result of the command's output or error
- if ($shellCommand->execute()) {
- $result = $shellCommand->getOutput();
- } else {
- $result = $shellCommand->getError();
+ return $result;
+ }
+
+ /**
+ * Return an array of active image variant creators
+ *
+ * @return array
+ */
+ public function getActiveVariantCreators(): array
+ {
+ $result = [];
+ $settings = ImageOptimize::$plugin->getSettings();
+ // Get the active image variant creators
+ $activeImageVariantCreators = $settings['activeImageVariantCreators'];
+ foreach ($activeImageVariantCreators as $imageFormat => $imageCreator) {
+ // Iterate through all of the image variant creators for this format
+ $imageVariantCreators = $settings['imageVariantCreators'];
+ foreach ($activeImageVariantCreators[$imageFormat] as $variantCreator) {
+ if (!empty($imageVariantCreators[$variantCreator])) {
+ $thisVariantCreator = $imageVariantCreators[$variantCreator];
+ $result[] = [
+ 'format' => $imageFormat,
+ 'creator' => $variantCreator,
+ 'command' => $thisVariantCreator['commandPath']
+ .' '
+ .$thisVariantCreator['commandOptions'],
+ 'installed' => file_exists($thisVariantCreator['commandPath']),
+ ];
+ }
+ }
}
return $result;
}
+ /**
+ * Resave all of the Asset elements in the Volume $volume
+ *
+ * @param Volume $volume
+ */
+ public function resaveVolumeAssets(Volume $volume)
+ {
+ $siteId = Craft::$app->getSites()->getPrimarySite()->id;
+
+ Craft::$app->getQueue()->push(new ResaveElements([
+ 'description' => Craft::t('image-optimize', 'Resaving Assets in {name}', ['name' => $volume->name]),
+ 'elementType' => Asset::class,
+ 'criteria' => [
+ 'siteId' => $siteId,
+ 'volumeId' => $volume->id,
+ 'status' => null,
+ 'enabledForSite' => false,
+ ],
+ ]));
+ }
+
/**
* @param string $path
* @param string $extension
@@ -455,9 +491,9 @@ protected function executeShellCommand(string $command): string
protected function swapPathExtension(string $path, string $extension): string
{
$pathParts = pathinfo($path);
- $newPath = $pathParts['filename'] . '.' . $extension;
+ $newPath = $pathParts['filename'].'.'.$extension;
if (!empty($pathParts['dirname']) && $pathParts['dirname'] !== '.') {
- $newPath = $pathParts['dirname'] . DIRECTORY_SEPARATOR . $newPath;
+ $newPath = $pathParts['dirname'].DIRECTORY_SEPARATOR.$newPath;
$newPath = preg_replace('#/+#', '/', $newPath);
}
diff --git a/src/templates/_components/fields/OptimizedImages_input.twig b/src/templates/_components/fields/OptimizedImages_input.twig
index 3aacc85d..8b3cdaaf 100644
--- a/src/templates/_components/fields/OptimizedImages_input.twig
+++ b/src/templates/_components/fields/OptimizedImages_input.twig
@@ -71,7 +71,7 @@
refX="0" refY="{{ markerHeight / 2 }}" orient="auto" markerUnits="strokeWidth">