From e93abec12e95d34a2ff0937d542f2e912056a7cb Mon Sep 17 00:00:00 2001 From: Andrew Welch Date: Fri, 28 Dec 2018 10:57:44 -0500 Subject: [PATCH 01/13] Remove internal Imgix & Thumbor transforms Signed-off-by: Andrew Welch --- src/imagetransforms/ImgixImageTransform.php | 341 ------------------ src/imagetransforms/ThumborImageTransform.php | 259 ------------- .../settings/image-transforms/imgix.twig | 31 -- .../settings/image-transforms/thumbor.twig | 22 -- 4 files changed, 653 deletions(-) delete mode 100644 src/imagetransforms/ImgixImageTransform.php delete mode 100644 src/imagetransforms/ThumborImageTransform.php delete mode 100644 src/templates/settings/image-transforms/imgix.twig delete mode 100644 src/templates/settings/image-transforms/thumbor.twig diff --git a/src/imagetransforms/ImgixImageTransform.php b/src/imagetransforms/ImgixImageTransform.php deleted file mode 100644 index b239745f..00000000 --- a/src/imagetransforms/ImgixImageTransform.php +++ /dev/null @@ -1,341 +0,0 @@ - 'w', - 'height' => 'h', - 'quality' => 'q', - 'format' => 'fm', - ]; - - const IMGIX_PURGE_ENDPOINT = 'https://api.imgix.com/v2/image/purger'; - - // Static Methods - // ========================================================================= - - /** - * @inheritdoc - */ - public static function displayName(): string - { - return Craft::t('image-optimize', 'Imgix'); - } - - // Public Properties - // ========================================================================= - - /** - * @var string - */ - public $domain; - - /** - * @var string - */ - public $apiKey; - - /** - * @var string - */ - public $securityToken; - - // Public Methods - // ========================================================================= - - /** - * @param Asset $asset - * @param AssetTransform|null $transform - * @param array $params - * - * @return string|null - * @throws \yii\base\Exception - * @throws \yii\base\InvalidConfigException - */ - public function getTransformUrl(Asset $asset, $transform, array $params = []) - { - $url = null; - $settings = ImageOptimize::$plugin->getSettings(); - - $domain = $params['domain'] ?? 'demos.imgix.net'; - $builder = new UrlBuilder($domain); - if ($asset && $builder) { - $builder->setUseHttps(true); - if ($transform) { - // Map the transform properties - foreach (self::TRANSFORM_ATTRIBUTES_MAP as $key => $value) { - if (!empty($transform[$key])) { - $params[$value] = $transform[$key]; - } - } - // Remove any 'AUTO' settings - ArrayHelper::removeValue($params, 'AUTO'); - // Handle the Imgix auto setting for compression/format - $autoParams = []; - if (empty($params['q'])) { - $autoParams[] = 'compress'; - } - if (empty($params['fm'])) { - $autoParams[] = 'format'; - } - if (!empty($autoParams)) { - $params['auto'] = implode(',', $autoParams); - } - // Handle interlaced images - if (property_exists($transform, 'interlace')) { - if (($transform->interlace != 'none') - && (!empty($params['fm'])) - && ($params['fm'] == 'jpg') - ) { - $params['fm'] = 'pjpg'; - } - } - if ($settings->autoSharpenScaledImages) { - // See if the image has been scaled >= 50% - $widthScale = $asset->getWidth() / ($transform->width ?? $asset->getWidth()); - $heightScale = $asset->getHeight() / ($transform->height ?? $asset->getHeight()); - if (($widthScale >= 2.0) || ($heightScale >= 2.0)) { - $params['usm'] = 50.0; - } - } - // Handle the mode - switch ($transform->mode) { - case 'fit': - $params['fit'] = 'clamp'; - break; - - case 'stretch': - $params['fit'] = 'scale'; - break; - - default: - // Set a sane default - if (empty($transform->position)) { - $transform->position = 'center-center'; - } - // Fit mode - $params['fit'] = 'crop'; - $cropParams = []; - // Handle the focal point - $focalPoint = $asset->getFocalPoint(); - if (!empty($focalPoint)) { - $params['fp-x'] = $focalPoint['x']; - $params['fp-y'] = $focalPoint['y']; - $cropParams[] = 'focalpoint'; - } elseif (preg_match('/(top|center|bottom)-(left|center|right)/', $transform->position)) { - // Imgix defaults to 'center' if no param is present - $filteredCropParams = explode('-', $transform->position); - $filteredCropParams = array_diff($filteredCropParams, ['center']); - $cropParams[] = $filteredCropParams; - } - // Imgix - if (!empty($cropParams) && $transform->position !== 'center-center') { - $params['crop'] = implode(',', $cropParams); - } - break; - } - } else { - // No transform was passed in; so just auto all the things - $params['auto'] = 'format,compress'; - } - // Remove the api-key param - unset($params['api-key']); - // Apply the Security Token, if set - if (!empty($this->securityToken)) { - $builder->setSignKey($this->securityToken); - } - // Finally, create the Imgix URL for this transformed image - $assetUri = $this->getAssetUri($asset); - $url = $builder->createURL($assetUri, $params); - Craft::debug( - 'Imgix transform created for: '.$assetUri.' - Params: '.print_r($params, true).' - URL: '.$url, - __METHOD__ - ); - } - - return $url; - } - - /** - * @param string $url - * @param Asset $asset - * @param AssetTransform|null $transform - * @param array $params - * - * @return string - */ - public function getWebPUrl(string $url, Asset $asset, $transform, array $params = []): string - { - $url = preg_replace('/fm=[^&]*/', 'fm=webp', $url); - - return $url; - } - - /** - * @param Asset $asset - * @param array $params - * - * @return null|string - * @throws \yii\base\InvalidConfigException - */ - public function getPurgeUrl(Asset $asset, array $params = []) - { - $url = null; - - $domain = isset($params['domain']) - ? $params['domain'] - : 'demos.imgix.net'; - $builder = new UrlBuilder($domain); - if ($asset && $builder) { - $builder->setUseHttps(true); - // Create the Imgix URL for purging this image - $assetUri = $this->getAssetUri($asset); - $url = $builder->createURL($assetUri, $params); - // Strip the query string so we just pass in the raw URL - $url = UrlHelper::stripQueryString($url); - } - - return $url; - } - - /** - * @param string $url - * @param array $params - * - * @return bool - */ - public function purgeUrl(string $url, array $params = []): bool - { - $result = false; - $apiKey = isset($params['api-key']) - ? $params['api-key'] - : ''; - // create new guzzle client - $guzzleClient = Craft::createGuzzleClient(['timeout' => 120, 'connect_timeout' => 120]); - // Submit the sitemap index to each search engine - try { - /** @var ResponseInterface $response */ - $response = $guzzleClient->post(self::IMGIX_PURGE_ENDPOINT, [ - 'auth' => [ - $apiKey, - '', - ], - 'form_params' => [ - 'url' => $url, - ], - ]); - // See if it succeeded - if (($response->getStatusCode() >= 200) - && ($response->getStatusCode() < 400) - ) { - $result = true; - } - Craft::info( - 'URL purged: '.$url.' - Response code: '.$response->getStatusCode(), - __METHOD__ - ); - } catch (\Exception $e) { - Craft::error( - 'Error purging URL: '.$url.' - '.$e->getMessage(), - __METHOD__ - ); - } - - return $result; - } - - /** - * @return array - */ - public function getTransformParams(): array - { - $params = [ - 'domain' => $this->domain, - 'api-key' => $this->apiKey, - ]; - - return $params; - } - - /** - * @param Asset $asset - * - * @return mixed - * @throws \yii\base\InvalidConfigException - */ - public function getAssetUri(Asset $asset) - { - $volume = $asset->getVolume(); - - // If this is a local volume, it implies your are using a "Web Folder" - // source in Imgix. We can then also infer that: - // - This volume has URLs - // - The "Base URL" in Imgix is set to your domain root, per the ImageOptimize docs. - // - // Therefore, we need to parse the path from the full URL, so that it - // includes the path of the volume. - if ($volume instanceof \craft\volumes\Local) { - $assetUrl = AssetsHelper::generateUrl($volume, $asset); - $assetUri = parse_url($assetUrl, PHP_URL_PATH); - - return $assetUri; - } - - return parent::getAssetUri($asset); - } - - /** - * @inheritdoc - */ - public function getSettingsHtml() - { - return Craft::$app->getView()->renderTemplate('image-optimize/settings/image-transforms/imgix.twig', [ - 'imageTransform' => $this, - ]); - } - - /** - * @inheritdoc - */ - public function rules() - { - $rules = parent::rules(); - $rules = array_merge($rules, [ - [['domain', 'apiKey', 'securityToken'], 'default', 'value' => ''], - [['domain', 'apiKey', 'securityToken'], 'string'], - ]); - - return $rules; - } -} diff --git a/src/imagetransforms/ThumborImageTransform.php b/src/imagetransforms/ThumborImageTransform.php deleted file mode 100644 index d3314be8..00000000 --- a/src/imagetransforms/ThumborImageTransform.php +++ /dev/null @@ -1,259 +0,0 @@ -getUrlBuilderForTransform($asset, $transform, $params); - } - - /** - * @param string $url - * @param Asset $asset - * @param AssetTransform|null $transform - * @param array $params - * - * @return string - * @throws \yii\base\Exception - * @throws \yii\base\InvalidConfigException - */ - public function getWebPUrl(string $url, Asset $asset, $transform, array $params = []): string - { - $builder = $this->getUrlBuilderForTransform($asset, $transform, $params) - ->addFilter('format', 'webp'); - - return (string)$builder; - } - - /** - * @param string $url - * @param array $params - * - * @return bool - */ - public function purgeUrl(string $url, array $params = []): bool - { - return false; - } - - /** - * @return array - */ - public function getTransformParams(): array - { - $params = [ - 'baseUrl' => $this->baseUrl, - 'securityKey' => $this->securityKey, - ]; - - return $params; - } - - // Private Methods - // ========================================================================= - - /** - * @param Asset $asset - * @param AssetTransform|null $transform - * @param array $params - * - * @return UrlBuilder - * @throws \yii\base\Exception - * @throws \yii\base\InvalidConfigException - */ - private function getUrlBuilderForTransform(Asset $asset, $transform, array $params = []): UrlBuilder - { - $assetUri = $this->getAssetUri($asset); - $baseUrl = $params['baseUrl']; - $securityKey = $params['securityKey'] ?: null; - $builder = UrlBuilder::construct($baseUrl, $securityKey, $assetUri); - $settings = ImageOptimize::$plugin->getSettings(); - - if ($transform->mode === 'fit') { - // https://thumbor.readthedocs.io/en/latest/usage.html#fit-in - $builder->fitIn($transform->width, $transform->height); - } elseif ($transform->mode === 'stretch') { - $builder - ->resize($transform->width, $transform->height) - ->addFilter('upscale'); - - // https://github.com/thumbor/thumbor/issues/1123 - Craft::warning('Thumbor has no equivalent to the "stretch" transform mode. The resulting image will be resized and cropped, but not stretched.', __METHOD__); - } else { - - // https://thumbor.readthedocs.io/en/latest/usage.html#image-size - $builder->resize($transform->width, $transform->height); - - if ($focalPoint = $this->getFocalPoint($asset)) { - // https://thumbor.readthedocs.io/en/latest/focal.html - $builder->addFilter('focal', $focalPoint); - } elseif (preg_match('/(top|center|bottom)-(left|center|right)/', $transform->position, $matches)) { - $v = str_replace('center', 'middle', $matches[1]); - $h = $matches[2]; - - // https://thumbor.readthedocs.io/en/latest/usage.html#horizontal-align - $builder->valign($v)->halign($h); - } - } - - // https://thumbor.readthedocs.io/en/latest/format.html - if ($format = $this->getFormat($transform)) { - $builder->addFilter('format', $format); - } - - // https://thumbor.readthedocs.io/en/latest/quality.html - if ($quality = $this->getQuality($transform)) { - $builder->addFilter('quality', $quality); - } - - if (property_exists($transform, 'interlace')) { - Craft::warning('Thumbor enables progressive JPEGs on the server-level, not as a request option. See https://thumbor.readthedocs.io/en/latest/jpegtran.html', __METHOD__); - } - - if ($settings->autoSharpenScaledImages) { - // See if the image has been scaled >= 50% - $widthScale = $asset->getWidth() / ($transform->width ?? $asset->getWidth()); - $heightScale = $asset->getHeight() / ($transform->height ?? $asset->getHeight()); - if (($widthScale >= 2.0) || ($heightScale >= 2.0)) { - // https://thumbor.readthedocs.io/en/latest/sharpen.html - $builder->addFilter('sharpen', .5, .5, 'true'); - } - } - - return $builder; - } - - /** - * @return string|null - */ - private function getFocalPoint(Asset $asset) - { - $focalPoint = $asset->getFocalPoint(); - - if (!$focalPoint) { - return null; - } - - $box = array_map('intval', [ - 'top' => $focalPoint['y'] * $asset->height - 1, - 'left' => $focalPoint['x'] * $asset->width - 1, - 'bottom' => $focalPoint['y'] * $asset->height + 1, - 'right' => $focalPoint['x'] * $asset->width + 1, - ]); - - return implode('', [ - $box['left'], - 'x', - $box['top'], - ':', - $box['right'], - 'x', - $box['bottom'], - ]); - } - - /** - * @param AssetTransform|null $transform - * - * @return string|null - */ - private function getFormat($transform) - { - $format = str_replace('jpg', 'jpeg', $transform->format); - - return $format ?: null; - } - - /** - * @param AssetTransform|null $transform - * - * @return int - */ - private function getQuality($transform) - { - return $transform->quality ?? Craft::$app->getConfig()->getGeneral()->defaultImageQuality; - } - - /** - * @inheritdoc - */ - public function getSettingsHtml() - { - return Craft::$app->getView()->renderTemplate('image-optimize/settings/image-transforms/thumbor.twig', [ - 'imageTransform' => $this, - ]); - } - - /** - * @inheritdoc - */ - public function rules() - { - $rules = parent::rules(); - $rules = array_merge($rules, [ - [['baseUrl', 'securityKey'], 'default', 'value' => ''], - [['baseUrl', 'securityKey'], 'string'], - ]); - - return $rules; - } -} diff --git a/src/templates/settings/image-transforms/imgix.twig b/src/templates/settings/image-transforms/imgix.twig deleted file mode 100644 index 6c9da829..00000000 --- a/src/templates/settings/image-transforms/imgix.twig +++ /dev/null @@ -1,31 +0,0 @@ -{% from 'image-optimize/_includes/macros' import configWarning %} - -{% import "_includes/forms" as forms %} - - -{{ forms.textField({ - label: 'Imgix Source Domain', - instructions: "The source domain to use for the Imgix transforms."|t('image-optimize'), - id: 'domain', - name: 'domain', - value: imageTransform.domain, - warning: configWarning('imageTransformTypeSettings', 'image-optimize'), -}) }} - -{{ forms.textField({ - label: 'Imgix API Key', - instructions: "The API key to use for the Imgix transforms (needed for auto-purging changed assets)."|t('image-optimize'), - id: 'apiKey', - name: 'apiKey', - value: imageTransform.apiKey, - warning: configWarning('imageTransformTypeSettings', 'image-optimize'), -}) }} - -{{ forms.textField({ - label: 'Imgix Security Token', - instructions: "The optional [security token](https://docs.imgix.com/setup/securing-images) used to sign image URLs from Imgix."|t('image-optimize'), - id: 'securityToken', - name: 'securityToken', - value: imageTransform.securityToken, - warning: configWarning('imageTransformTypeSettings', 'image-optimize'), -}) }} diff --git a/src/templates/settings/image-transforms/thumbor.twig b/src/templates/settings/image-transforms/thumbor.twig deleted file mode 100644 index 11fffd70..00000000 --- a/src/templates/settings/image-transforms/thumbor.twig +++ /dev/null @@ -1,22 +0,0 @@ -{% from 'image-optimize/_includes/macros' import configWarning %} - -{% import "_includes/forms" as forms %} - - -{{ forms.textField({ - label: 'Thumbor Base URL', - instructions: "The base URL to use for the Thumbor transforms."|t('image-optimize'), - id: 'baseUrl', - name: 'baseUrl', - value: imageTransform.baseUrl, - warning: configWarning('imageTransformTypeSettings', 'image-optimize'), -}) }} - -{{ forms.textField({ - label: 'Thumbor Security Key', - instructions: "The optional [security key](https://thumbor.readthedocs.io/en/latest/security.html) used by Thumbor to create secure image urls."|t('image-optimize'), - id: 'securityKey', - name: 'securityKey', - value: imageTransform.securityKey, - warning: configWarning('imageTransformTypeSettings', 'image-optimize'), -}) }} From a49934946dca086c8a6084c6cdd4962eca5dd471 Mon Sep 17 00:00:00 2001 From: Andrew Welch Date: Fri, 28 Dec 2018 10:58:26 -0500 Subject: [PATCH 02/13] Add getTemplatesRoot() Signed-off-by: Andrew Welch --- src/imagetransforms/ImageTransform.php | 24 +++++++++++++++++++ .../ImageTransformInterface.php | 10 +++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/imagetransforms/ImageTransform.php b/src/imagetransforms/ImageTransform.php index 360fbaf5..30288ddb 100644 --- a/src/imagetransforms/ImageTransform.php +++ b/src/imagetransforms/ImageTransform.php @@ -14,6 +14,8 @@ use craft\base\SavableComponent; use craft\elements\Asset; +use craft\helpers\FileHelper; +use craft\helpers\StringHelper; use craft\models\AssetTransform; /** @@ -28,6 +30,28 @@ abstract class ImageTransform extends SavableComponent implements ImageTransform use ImageTransformTrait; + // Static Methods + // ========================================================================= + + /** + * @return array + * @throws \ReflectionException + */ + public static function getTemplatesRoot(): array + { + $reflect = new \ReflectionClass(static::class); + $classPath = FileHelper::normalizePath( + dirname($reflect->getFileName()) + . '/../templates' + ) + . DIRECTORY_SEPARATOR; + $id = StringHelper::toKebabCase($reflect->getShortName()); + + return [ + $id, $classPath + ]; + } + // Public Methods // ========================================================================= diff --git a/src/imagetransforms/ImageTransformInterface.php b/src/imagetransforms/ImageTransformInterface.php index 7222d751..4e6ba99b 100644 --- a/src/imagetransforms/ImageTransformInterface.php +++ b/src/imagetransforms/ImageTransformInterface.php @@ -21,6 +21,15 @@ */ interface ImageTransformInterface extends SavableComponentInterface { + // Static Methods + // ========================================================================= + + /** + * @return array + * @throws \ReflectionException + */ + public static function getTemplatesRoot(): array; + // Public Methods // ========================================================================= @@ -59,7 +68,6 @@ public function getPurgeUrl(Asset $asset, array $params = []); */ public function purgeUrl(string $url, array $params = []): bool; - /** * @param Asset $asset * From 2fdbcce6c00e572f0b4933c361fe715730125f8c Mon Sep 17 00:00:00 2001 From: Andrew Welch Date: Fri, 28 Dec 2018 10:58:56 -0500 Subject: [PATCH 03/13] Use external packages for Imgix and Thumbor transforms Signed-off-by: Andrew Welch --- composer.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index ed65e598..2a79ff94 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,7 @@ "name": "nystudio107/craft-imageoptimize", "description": "Automatically create & optimize responsive image transforms, using either native Craft transforms or a service like Imgix, with zero template changes.", "type": "craft-plugin", - "version": "1.5.0", + "version": "1.5.1", "keywords": [ "craft", "cms", @@ -29,10 +29,10 @@ "prefer-stable": true, "require": { "craftcms/cms": "^3.0.0", - "imgix/imgix-php": "^2.1.0", + "nystudio107/craft-imageoptimize-imgix": "^1.0.0", + "nystudio107/craft-imageoptimize-thumbor": "^1.0.0", "ksubileau/color-thief-php": "^1.3", - "mikehaertl/php-shellcommand": "~1.2", - "99designs/phumbor": "^1.2" + "mikehaertl/php-shellcommand": "~1.2" }, "autoload": { "psr-4": { From 69ce35b9dc0301f7703cd79719cc6c9884a6f79d Mon Sep 17 00:00:00 2001 From: Andrew Welch Date: Fri, 28 Dec 2018 10:59:08 -0500 Subject: [PATCH 04/13] Remove built-in classes Signed-off-by: Andrew Welch --- src/models/Settings.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/models/Settings.php b/src/models/Settings.php index f023ad49..813d6c2e 100644 --- a/src/models/Settings.php +++ b/src/models/Settings.php @@ -110,9 +110,6 @@ class Settings extends Model * @var ImageTransformInterface[] The default Image Transform type classes */ public $defaultImageTransformTypes = [ - CraftImageTransform::class, - ImgixImageTransform::class, - ThumborImageTransform::class, ]; /** From e80f0a65143717969be30364ef409d4a7411f351 Mon Sep 17 00:00:00 2001 From: Andrew Welch Date: Fri, 28 Dec 2018 10:59:32 -0500 Subject: [PATCH 05/13] Register template roots for Image Transform components Signed-off-by: Andrew Welch --- src/ImageOptimize.php | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/ImageOptimize.php b/src/ImageOptimize.php index 59684d95..0a9a6584 100644 --- a/src/ImageOptimize.php +++ b/src/ImageOptimize.php @@ -32,6 +32,7 @@ use craft\events\GenerateTransformEvent; use craft\events\PluginEvent; use craft\events\RegisterComponentTypesEvent; +use craft\events\RegisterTemplateRootsEvent; use craft\events\RegisterUrlRulesEvent; use craft\events\ReplaceAssetEvent; use craft\events\VolumeEvent; @@ -47,6 +48,7 @@ use craft\web\twig\variables\CraftVariable; use craft\web\Controller; use craft\web\UrlManager; +use craft\web\View; use markhuot\CraftQL\CraftQL; @@ -264,6 +266,10 @@ protected function installEventHandlers() if ($request->getIsSiteRequest() && !$request->getIsConsoleRequest()) { $this->installSiteEventListeners(); } + // Install only for non-console cp requests + if ($request->getIsCpRequest() && !$request->getIsConsoleRequest()) { + $this->installCpEventListeners(); + } } /** @@ -541,6 +547,36 @@ function (RegisterUrlRulesEvent $event) { ); } + /** + * Install site event listeners for cp requests only + */ + protected function installCpEventListeners() + { + // Handler: Plugins::EVENT_AFTER_LOAD_PLUGINS + Event::on( + Plugins::class, + Plugins::EVENT_AFTER_LOAD_PLUGINS, + function () { + // Install these only after all other plugins have loaded + Event::on( + View::class, + View::EVENT_REGISTER_CP_TEMPLATE_ROOTS, + function (RegisterTemplateRootsEvent $e) { + // Register the root directodies + $allImageTransformTypes = ImageOptimize::$plugin->optimize->getAllImageTransformTypes(); + /** @var ImageTransformInterface $imageTransformType */ + foreach ($allImageTransformTypes as $imageTransformType) { + list($id, $baseDir) = $imageTransformType::getTemplatesRoot(); + if (is_dir($baseDir)) { + $e->roots[$id] = $baseDir; + } + } + } + ); + } + ); + } + /** * Return the custom frontend routes * From 4bf6e8fbe24568e03136410d56d75eb56d1d25ee Mon Sep 17 00:00:00 2001 From: Andrew Welch Date: Fri, 28 Dec 2018 10:59:56 -0500 Subject: [PATCH 06/13] Use external packages for Imgix & Thumbor Signed-off-by: Andrew Welch --- src/services/Optimize.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/Optimize.php b/src/services/Optimize.php index 4d6fcedf..2bda1023 100644 --- a/src/services/Optimize.php +++ b/src/services/Optimize.php @@ -14,8 +14,8 @@ use nystudio107\imageoptimize\imagetransforms\CraftImageTransform; use nystudio107\imageoptimize\imagetransforms\ImageTransform; use nystudio107\imageoptimize\imagetransforms\ImageTransformInterface; -use nystudio107\imageoptimize\imagetransforms\ImgixImageTransform; -use nystudio107\imageoptimize\imagetransforms\ThumborImageTransform; +use nystudio107\imageoptimizeimgix\imagetransforms\ImgixImageTransform; +use nystudio107\imageoptimizethumbor\imagetransforms\ThumborImageTransform; use Craft; use craft\base\Component; From d2d6166aa9ee36fffdbd8a3c729031165017eb0a Mon Sep 17 00:00:00 2001 From: Andrew Welch Date: Fri, 28 Dec 2018 11:00:26 -0500 Subject: [PATCH 07/13] Use component template root for template rendering Signed-off-by: Andrew Welch --- src/imagetransforms/CraftImageTransform.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/imagetransforms/CraftImageTransform.php b/src/imagetransforms/CraftImageTransform.php index d1de4887..fa951900 100644 --- a/src/imagetransforms/CraftImageTransform.php +++ b/src/imagetransforms/CraftImageTransform.php @@ -94,7 +94,7 @@ public function getSettingsHtml() { $imageProcessors = ImageOptimize::$plugin->optimize->getActiveImageProcessors(); $variantCreators = ImageOptimize::$plugin->optimize->getActiveVariantCreators(); - return Craft::$app->getView()->renderTemplate('image-optimize/settings/image-transforms/craft.twig', [ + return Craft::$app->getView()->renderTemplate('craft-image-transform/settings/image-transforms/craft.twig', [ 'imageTransform' => $this, 'imageProcessors' => $imageProcessors, 'variantCreators' => $variantCreators, From 396370ddbe4babaabb02a3a1c963956e5c90b2c9 Mon Sep 17 00:00:00 2001 From: Andrew Welch Date: Fri, 28 Dec 2018 11:01:29 -0500 Subject: [PATCH 08/13] Version 1.5.1 Signed-off-by: Andrew Welch --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42e43ecb..f9205d88 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # ImageOptimize Changelog -## 1.5.0 - 2018.12.28 +## 1.5.1 - 2018.12.28 +### Changed +* Refactored the Imgix and Thumbor Image Transforms out to external packages + +## 1.5.0 - 2018.12.27 ### Changed * Refactored out the `ImageTransform` interface to use Yii2's DI to allow them to be stand-alone components * Respond to `Assets::EVENT_GET_ASSET_THUMB_URL` for direct thumbnail generation from third party image transform services From f3a2ea38d292888e886a91d5f1ea3827ba26b2fd Mon Sep 17 00:00:00 2001 From: Andrew Welch Date: Fri, 28 Dec 2018 14:53:19 -0500 Subject: [PATCH 09/13] Fix docblocks Signed-off-by: Andrew Welch --- src/imagetransforms/ImageTransform.php | 61 +++++++++++--------------- 1 file changed, 25 insertions(+), 36 deletions(-) diff --git a/src/imagetransforms/ImageTransform.php b/src/imagetransforms/ImageTransform.php index 30288ddb..4c098ce3 100644 --- a/src/imagetransforms/ImageTransform.php +++ b/src/imagetransforms/ImageTransform.php @@ -34,8 +34,15 @@ abstract class ImageTransform extends SavableComponent implements ImageTransform // ========================================================================= /** - * @return array - * @throws \ReflectionException + * @inheritdoc + */ + public static function displayName(): string + { + return Craft::t('image-optimize', 'Generic Transform'); + } + + /** + * @inheritdoc */ public static function getTemplatesRoot(): array { @@ -56,11 +63,7 @@ public static function getTemplatesRoot(): array // ========================================================================= /** - * @param Asset $asset - * @param AssetTransform|null $transform - * @param array $params - * - * @return string|null + * @inheritdoc */ public function getTransformUrl(Asset $asset, $transform, array $params = []) { @@ -70,12 +73,7 @@ public function getTransformUrl(Asset $asset, $transform, array $params = []) } /** - * @param string $url - * @param Asset $asset - * @param AssetTransform|null $transform - * @param array $params - * - * @return string + * @inheritdoc */ public function getWebPUrl(string $url, Asset $asset, $transform, array $params = []): string { @@ -83,10 +81,7 @@ public function getWebPUrl(string $url, Asset $asset, $transform, array $params } /** - * @param Asset $asset - * @param array $params - * - * @return null|string + * @inheritdoc */ public function getPurgeUrl(Asset $asset, array $params = []) { @@ -96,10 +91,7 @@ public function getPurgeUrl(Asset $asset, array $params = []) } /** - * @param string $url - * @param array $params - * - * @return bool + * @inheritdoc */ public function purgeUrl(string $url, array $params = []): bool { @@ -107,21 +99,7 @@ public function purgeUrl(string $url, array $params = []): bool } /** - * @return array - */ - public function getTransformParams(): array - { - $params = [ - ]; - - return $params; - } - - /** - * @param Asset $asset - * - * @return mixed - * @throws \yii\base\InvalidConfigException + * @inheritdoc */ public function getAssetUri(Asset $asset) { @@ -155,6 +133,17 @@ public function prefetchRemoteFile($url) curl_close($ch); } + /** + * @inheritdoc + */ + public function getTransformParams(): array + { + $params = [ + ]; + + return $params; + } + /** * Append an extension a passed url or path * From e3c86865a0974e450656dc4f81e298ff244f92e0 Mon Sep 17 00:00:00 2001 From: Andrew Welch Date: Fri, 28 Dec 2018 14:53:30 -0500 Subject: [PATCH 10/13] Document the interface Signed-off-by: Andrew Welch --- src/imagetransforms/ImageTransformInterface.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/imagetransforms/ImageTransformInterface.php b/src/imagetransforms/ImageTransformInterface.php index 4e6ba99b..ffddba51 100644 --- a/src/imagetransforms/ImageTransformInterface.php +++ b/src/imagetransforms/ImageTransformInterface.php @@ -25,6 +25,9 @@ interface ImageTransformInterface extends SavableComponentInterface // ========================================================================= /** + * Return an array that contains the template root and corresponding file + * system directory for the Image Transform's templates + * * @return array * @throws \ReflectionException */ @@ -34,6 +37,8 @@ public static function getTemplatesRoot(): array; // ========================================================================= /** + * Return a URL to a transformed images + * * @param Asset $asset * @param AssetTransform|null $transform * @param array $params @@ -43,6 +48,8 @@ public static function getTemplatesRoot(): array; public function getTransformUrl(Asset $asset, $transform, array $params = []); /** + * Return a URL to the webp version of the transformed image + * * @param string $url * @param Asset $asset * @param AssetTransform|null $transform @@ -53,6 +60,8 @@ public function getTransformUrl(Asset $asset, $transform, array $params = []); public function getWebPUrl(string $url, Asset $asset, $transform, array $params = []): string; /** + * Return the URL that should be used to purge the Asset + * * @param Asset $asset * @param array $params * @@ -61,6 +70,8 @@ public function getWebPUrl(string $url, Asset $asset, $transform, array $params public function getPurgeUrl(Asset $asset, array $params = []); /** + * Purge the URL from the service's cache + * * @param string $url * @param array $params * @@ -69,6 +80,8 @@ public function getPurgeUrl(Asset $asset, array $params = []); public function purgeUrl(string $url, array $params = []): bool; /** + * Return the URI to the asset + * * @param Asset $asset * * @return mixed @@ -76,11 +89,15 @@ public function purgeUrl(string $url, array $params = []): bool; public function getAssetUri(Asset $asset); /** + * Prefetch the remote file to prime the cache + * * @param string $url */ public function prefetchRemoteFile($url); /** + * Get the parameters needed for this transform + * * @return array */ public function getTransformParams(): array; From 03dda3bdf6dff725d518978a8508e80b2f3836c5 Mon Sep 17 00:00:00 2001 From: Andrew Welch Date: Fri, 28 Dec 2018 14:58:48 -0500 Subject: [PATCH 11/13] Code formatting Signed-off-by: Andrew Welch --- src/imagetransforms/ImageTransform.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/imagetransforms/ImageTransform.php b/src/imagetransforms/ImageTransform.php index 4c098ce3..db5e6059 100644 --- a/src/imagetransforms/ImageTransform.php +++ b/src/imagetransforms/ImageTransform.php @@ -54,9 +54,7 @@ public static function getTemplatesRoot(): array . DIRECTORY_SEPARATOR; $id = StringHelper::toKebabCase($reflect->getShortName()); - return [ - $id, $classPath - ]; + return [$id, $classPath]; } // Public Methods From 09a65bd45a7f33dfc306c45bbfc165f53e185b10 Mon Sep 17 00:00:00 2001 From: Andrew Welch Date: Fri, 28 Dec 2018 14:59:08 -0500 Subject: [PATCH 12/13] Updated README.md Signed-off-by: Andrew Welch --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2ffd07bf..1cc59d6f 100644 --- a/README.md +++ b/README.md @@ -705,7 +705,7 @@ use vendor\package\MyImageTransform; ], ``` -No module or plugin bootstrapping code needed to get it working. +No module or plugin bootstrapping code needed to get it working. For an example of how this works, check out [craft-imageoptimize-imgix](https://github.com/nystudio107/craft-imageoptimize-imgix) & [craft-imageoptimize-thumbor](https://github.com/nystudio107/craft-imageoptimize-thumbor). If you want to wrap your `ImageTransform` into a plugin or module, simply listen for the `EVENT_REGISTER_IMAGE_TRANSFORM_TYPES` event to add your `ImageTransform` to the types that ImageOptimize knows about. @@ -727,6 +727,8 @@ Event::on(Optimize::class, Although ImageOptimize itself uses the same mechanisms internally for `ImageTranform` implementations, this allows you to update & maintain an `ImageTransform` entirely independent of ImageOptimize. +This technique is discussed in depth in the [Writing Craft Plugins with Extensible Components](https://nystudio107.com/blog/writing-craft-plugins-with-extensible-components) article. + ## ImageOptimize Roadmap Some things to do, and ideas for potential features: From 96ad0f77e111bfa848594a8a5e0456d8bd1f575d Mon Sep 17 00:00:00 2001 From: Andrew Welch Date: Fri, 28 Dec 2018 14:59:15 -0500 Subject: [PATCH 13/13] Updated translations Signed-off-by: Andrew Welch --- src/translations/en/image-optimize.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/translations/en/image-optimize.php b/src/translations/en/image-optimize.php index aa6b2e6e..ccf863a9 100644 --- a/src/translations/en/image-optimize.php +++ b/src/translations/en/image-optimize.php @@ -72,5 +72,9 @@ 'SVG' => 'SVG', 'The base URL to use for the Thumbor transforms.' => 'The base URL to use for the Thumbor transforms.', 'Module does not exist in the manifest: {moduleName}' => 'Module does not exist in the manifest: {moduleName}', - 'Thumbor' => 'Thumbor' + 'Thumbor' => 'Thumbor', + 'Optionally prefix your asset path with the bucket name. This is useful if your Thumbor configuration does not specify an explicit bucket. Only relevant for AWS S3 volumes at this time.' => 'Optionally prefix your asset path with the bucket name. This is useful if your Thumbor configuration does not specify an explicit bucket. Only relevant for AWS S3 volumes at this time.', + 'Object failed to validate' => 'Object failed to validate', + 'Is not a Model object.' => 'Is not a Model object.', + 'Generic Transform' => 'Generic Transform' ];