diff --git a/composer.json b/composer.json index e3fd95e..3357d2b 100644 --- a/composer.json +++ b/composer.json @@ -14,6 +14,10 @@ } ], "require": { - "offbeatwp/framework": "2.*" + "offbeatwp/framework": "^2" + }, + "require-dev": { + "phpstan/phpstan": "^1.11", + "szepeviktor/phpstan-wordpress": "^1.3" } } diff --git a/package.json b/package.json index 9f3885e..6e22076 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,8 @@ "lint:css": "wp-scripts lint-style", "lint:js": "wp-scripts lint-js", "packages-update": "wp-scripts packages-update", - "start": "wp-scripts start --output-path=./build/ --webpack-src-dir=src/scripts" + "start": "wp-scripts start --output-path=./build/ --webpack-src-dir=src/scripts", + "analyse": "php vendor/bin/phpstan analyse --memory-limit=3G" }, "devDependencies": { "@wordpress/i18n": "^4.2.4", diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..88b443d --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,9 @@ +# phpstan.neon +parameters: + level: 5 + phpVersion: 80200 + treatPhpDocTypesAsCertain: false + paths: + - src +includes: + - vendor/szepeviktor/phpstan-wordpress/extension.neon \ No newline at end of file diff --git a/src/.phpstorm.meta.php b/src/.phpstorm.meta.php new file mode 100644 index 0000000..6be8e94 --- /dev/null +++ b/src/.phpstorm.meta.php @@ -0,0 +1,11 @@ + OffbeatWP\Images\Repositories\ImagesRepository::class + ])); + + override(\container(), map([ + 'images' => OffbeatWP\Images\Repositories\ImagesRepository::class + ])); +} \ No newline at end of file diff --git a/src/Helpers/ImageHelper.php b/src/Helpers/ImageHelper.php index e60a693..dba884c 100644 --- a/src/Helpers/ImageHelper.php +++ b/src/Helpers/ImageHelper.php @@ -2,6 +2,8 @@ namespace OffbeatWP\Images\Helpers; +use Error; + final class ImageHelper { public const MIN_VIEWPORT_WIDTH = 320; @@ -9,28 +11,30 @@ final class ImageHelper public const MAX_VIEWPORT_WIDTH = 2000; /** - * @param int $attachment + * @param int $attachmentId * @param array{url?: string, class?: string, loading?: string, alt?: string, sizes?: string[], aspectRatio?: string, lightbox?: bool, containedMaxWidth?: string|int|float} $args * @return string */ - public function generateResponsiveImage(int $attachment, array $args = []): string + public function generateResponsiveImage($attachmentId, array $args = []): string { - $args = apply_filters('offbeat/responsiveImage/args', $args, $attachment); + $args = apply_filters('offbeat/responsiveImage/args', $args, $attachmentId); $containedMaxWidth = apply_filters('offbeat/responsiveImage/containedMaxWidth', $args['containedMaxWidth'] ?? null, $args); - $sizes = apply_filters('offbeat/responsiveImage/sizes', $args['sizes'] ?? null, $args); + /** @var array $rawSizes */ + $rawSizes = apply_filters('offbeat/responsiveImage/sizes', $args['sizes'] ?? null, $args); $aspectRatio = apply_filters('offbeat/responsiveImage/aspectRatio', $args['aspectRatio'] ?? null, $args); - if (!$sizes || !is_array($sizes)) { + $sizes = []; + if (!$rawSizes || !is_array($rawSizes)) { $sizes = [0 => '100%']; } $sizes = $this->cleanSizes($sizes); $sizes = $this->transformSizes($sizes, $containedMaxWidth); - $sources = $this->generateSources($attachment, $sizes, $aspectRatio ?? null); + $sources = $this->generateSources($attachmentId, $sizes, $aspectRatio ?? null); - return $this->generateResponsiveImageTag($attachment, $sources, $args); + return $this->generateResponsiveImageTag($attachmentId, $sources, $args); } /** @@ -53,10 +57,23 @@ protected function cleanSizes(array $sizes): array return $sizes; } + private function getViewportWidth(string $containedMaxWidth): string + { + $result = preg_replace_callback('/^(?\d+(\.\d+)?)%$/', function ($matches) { + return floor((float)$matches['percentage']) . 'vw'; + }, $containedMaxWidth); + + if ($result === null) { + throw new Error(preg_last_error_msg()); + } + + return $result; + } + /** * @param string[] $sizes * @param string|int|float $containedMaxWidth - * @return string[] + * @return string[]|float[] */ protected function transformSizes(array $sizes, $containedMaxWidth): array { @@ -70,13 +87,11 @@ protected function transformSizes(array $sizes, $containedMaxWidth): array $containedMaxWidth = '100vw'; } - // if the contained max width is percentage convert it to viewport width + // if the contained max width is percentage convert it to viewport width, otherwise convert it to an integer if (is_numeric($containedMaxWidth)) { - $containedMaxWidth = (int)$containedMaxWidth; + $convertedMaxWidth = (int)$containedMaxWidth; } else { - $containedMaxWidth = preg_replace_callback('/^(?\d+(\.\d+)?)%$/', function ($matches) { - return floor((float)$matches['percentage']) . 'vw'; - }, $containedMaxWidth); + $convertedMaxWidth = $this->getViewportWidth($containedMaxWidth); } // Remove all sizes where key is not a number @@ -97,15 +112,15 @@ protected function transformSizes(array $sizes, $containedMaxWidth): array $percentage = (float)$matches['percentage']; // Make calculation when the containedMaxWidth is based on the viewport width - if (preg_match('/^(?\d+)vw$/', $containedMaxWidth, $matches)) { + if (preg_match('/^(?\d+)vw$/', $convertedMaxWidth, $matches)) { $imageWidth = floor((int)$matches['viewportWidth'] * ($percentage / 100)) . 'vw'; - } elseif (is_numeric($containedMaxWidth)) { + } elseif (is_numeric($convertedMaxWidth)) { // if breakpoint width is smaller then the contained max width // we add a size width a relative width otherwise an absolute width - if ($breakpointWidth < $containedMaxWidth) { + if ($breakpointWidth < $convertedMaxWidth) { $imageWidth = floor($percentage) . 'vw'; } else { - $imageWidth = ceil((int)$containedMaxWidth * ($percentage / 100)) . 'px'; + $imageWidth = ceil((int)$convertedMaxWidth * ($percentage / 100)) . 'px'; } } } elseif (is_numeric($imageSize)) { @@ -123,14 +138,14 @@ protected function transformSizes(array $sizes, $containedMaxWidth): array // 2. If there is no next breakpoint, but we didn't reached the contained max width yet if ( - is_int($containedMaxWidth) && + is_int($convertedMaxWidth) && is_float($percentage) && ( - ($nextBreakpointWidth && $breakpointWidth < $containedMaxWidth && $nextBreakpointWidth > $containedMaxWidth) || - (!$nextBreakpointWidth && $breakpointWidth < $containedMaxWidth) + ($nextBreakpointWidth && $breakpointWidth < $convertedMaxWidth && $nextBreakpointWidth > $convertedMaxWidth) || + (!$nextBreakpointWidth && $breakpointWidth < $convertedMaxWidth) ) ) { - $sizesReturn[$containedMaxWidth] = ceil($containedMaxWidth * ($percentage / 100)) . 'px'; + $sizesReturn[$convertedMaxWidth] = (float)ceil($convertedMaxWidth * ($percentage / 100)) . 'px'; } } @@ -198,7 +213,7 @@ public function calculateImageWidths(array $sizes): array * @param bool $pixelDensitySrcSet * @return string[] */ - public function generateSrcSet(int $attachmentId, array $sizes, $aspectRatio = null, bool $pixelDensitySrcSet = false): array + public function generateSrcSet($attachmentId, array $sizes, $aspectRatio = null, bool $pixelDensitySrcSet = false): array { $srcSet = []; $imageModifier = $aspectRatio ? 'c' : ''; @@ -347,7 +362,7 @@ protected function generateSizesAttribute(?array $sizes): ?string /** * @param int $attachmentId * @param array{sizes: string[]|null[], media_query: string, srcset?: string[]}[] $sources - * @param array{url?: string, class?: string, loading?: string, alt?: string, sizes?: string[], aspectRatio?: string, lightbox?: bool, containedMaxWidth?: string|int|float} $args + * @param array{url?: string, class?: string, loading?: string, alt?: string, sizes?: string[], aspectRatio?: string, lightbox?: bool, containedMaxWidth?: string|int|float, caption?: string} $args * @return string */ protected function generateResponsiveImageTag(int $attachmentId, array $sources, array $args): string @@ -365,7 +380,6 @@ protected function generateResponsiveImageTag(int $attachmentId, array $sources, 'decoding' => $args['decoding'] ?? null ]; - $styles = []; $aspectRatio = $args['aspectRatio'] ?? null; $objectFit = $args['objectFit'] ?? 'cover'; @@ -454,7 +468,7 @@ public static function calculateAspectRatio($aspectRatio, $attachmentId) $originalImageSize = wp_get_attachment_image_src($attachmentId, 'full'); if (is_array($originalImageSize) && !empty($originalImageSize)) { - return intval($originalImageSize[1]) / intval($originalImageSize[2]); + return (int)$originalImageSize[1] / (int)$originalImageSize[2]; } return 3 / 2; diff --git a/src/Hooks/FocalPointInitAction.php b/src/Hooks/FocalPointInitAction.php index ec24eb0..b67ee8e 100644 --- a/src/Hooks/FocalPointInitAction.php +++ b/src/Hooks/FocalPointInitAction.php @@ -2,6 +2,7 @@ namespace OffbeatWP\Images\Hooks; +use Error; use OffbeatWP\Hooks\AbstractAction; use WP_Post; @@ -97,7 +98,7 @@ public function getImageInfoForFocalPointTriggerButton(WP_Post $post): array } public function enqueueAdminAssets() { - $entryBuildPath = dirname(__FILE__) . '/../../build'; + $entryBuildPath = __DIR__ . '/../../build'; $assetPath = $entryBuildPath . '/index.asset.php'; if ( ! file_exists( $assetPath ) ) {