Skip to content

Commit

Permalink
Merge pull request #154 from 10up/fix/75-slow-load-times-due-to-svgdi…
Browse files Browse the repository at this point in the history
…mensions

Fix | Slow load times due to svg_dimensions
  • Loading branch information
jeffpaul committed Dec 12, 2023
2 parents 250b00f + d0b5b8a commit fbcee2f
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 13 deletions.
16 changes: 15 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@
"@wordpress/env": "^5.14.0",
"@wordpress/icons": "^9.20.0",
"@wordpress/scripts": "^26.0.0",
"cypress": "^13.3.0"
"cypress": "^13.3.0",
"mochawesome-json-to-md": "^0.7.2"
},
"dependencies": {
"cypress-mochawesome-reporter": "^3.4.0",
Expand Down
56 changes: 45 additions & 11 deletions safe-svg.php
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ protected function is_gzipped( $contents ) {
public function fix_admin_preview( $response, $attachment, $meta ) {

if ( 'image/svg+xml' === $response['mime'] ) {
$dimensions = $this->svg_dimensions( get_attached_file( $attachment->ID ) );
$dimensions = $this->svg_dimensions( $attachment->ID );

if ( $dimensions ) {
$response = array_merge( $response, $dimensions );
Expand Down Expand Up @@ -384,7 +384,7 @@ public function fix_admin_preview( $response, $attachment, $meta ) {
*/
public function one_pixel_fix( $image, $attachment_id, $size, $icon ) {
if ( get_post_mime_type( $attachment_id ) === 'image/svg+xml' ) {
$dimensions = $this->svg_dimensions( get_attached_file( $attachment_id ) );
$dimensions = $this->svg_dimensions( $attachment_id );

if ( $dimensions ) {
$image[1] = $dimensions['width'];
Expand Down Expand Up @@ -445,7 +445,7 @@ public function get_image_tag_override( $html, $id, $alt, $title, $align, $size
$width = $size[0];
$height = $size[1];
// phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition.Found, Squiz.PHP.DisallowMultipleAssignments.FoundInControlStructure
} elseif ( 'full' === $size && $dimensions = $this->svg_dimensions( get_attached_file( $id ) ) ) {
} elseif ( 'full' === $size && $dimensions = $this->svg_dimensions( $id ) ) {
$width = $dimensions['width'];
$height = $dimensions['height'];
} else {
Expand Down Expand Up @@ -485,7 +485,7 @@ public function skip_svg_regeneration( $metadata, $attachment_id ) {
$relative_path = str_replace( trailingslashit( $upload_dir['basedir'] ), '', $svg_path );
$filename = basename( $svg_path );

$dimensions = $this->svg_dimensions( $svg_path );
$dimensions = $this->svg_dimensions( $attachment_id );

if ( ! $dimensions ) {
return $metadata;
Expand Down Expand Up @@ -560,19 +560,43 @@ public function metadata_error_fix( $data, $post_id ) {
/**
* Get SVG size from the width/height or viewport.
*
* @param string|false $svg The file path to where the SVG file should be, false otherwise.
* @param integer $attachment_id The attachment ID of the SVG being processed.
*
* @return array|bool
*/
protected function svg_dimensions( $svg ) {
protected function svg_dimensions( $attachment_id ) {
/**
* Calculate SVG dimensions and orientation.
*
* This filter allows you to implement your own sizing. By returning a non-false
* value, it will short-circuit this function and return your set value.
*
* @param boolean Default value of the filter.
* @param integer $attachment_id The attachment ID of the SVG being processed.
*
* @return array|false An array of SVG dimensions and orientation or false.
*/
$short_circuit = apply_filters( 'safe_svg_pre_dimensions', false, $attachment_id );

if ( false !== $short_circuit ) {
return $short_circuit;
}

if ( ! function_exists( 'simplexml_load_file' ) ) {
return false;
}

$svg = @simplexml_load_file( $svg ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
$width = 0;
$height = 0;
if ( $svg ) {
$svg = get_attached_file( $attachment_id );
$metadata = wp_get_attachment_metadata( $attachment_id );
$width = 0;
$height = 0;

if ( $svg && ! empty( $metadata['width'] ) && empty( $metadata['height'] ) ) {
$width = floatval( $metadata['width'] );
$height = floatval( $metadata['height'] );
} elseif ( $svg ) {
$svg = @simplexml_load_file( $svg ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged

$attributes = $svg->attributes();

if ( isset( $attributes->viewBox ) ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
Expand Down Expand Up @@ -627,11 +651,21 @@ protected function svg_dimensions( $svg ) {
}
}

return array(
$dimensions = array(
'width' => $width,
'height' => $height,
'orientation' => ( $width > $height ) ? 'landscape' : 'portrait',
);

/**
* Calculate SVG dimensions and orientation.
*
* @param array $dimensions An array containing width, height, and orientation.
* @param string $svg The file path to the SVG.
*
* @return array An array of SVG dimensions and orientation.
*/
return apply_filters( 'safe_svg_dimensions', $dimensions, $svg );
}

/**
Expand Down
58 changes: 58 additions & 0 deletions tests/unit/test-safe-svg.php
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,64 @@ public function test_one_pixel_fix() {
)
);

\WP_Mock::userFunction(
'wp_get_attachment_metadata',
array(
'args' => 1,
'return_in_order' => array(
array(
'width' => 600,
'height' => 600,
'file' => __DIR__ . '/files/svgCleanOne.svg',
'sizes' => array(
'thumbnail' => array(
'width' => 150,
'height' => 150,
'crop' => 1,
'file' => 'svgCleanOne.svg',
'mime-type' => 'image/svg+xml',
),
'medium' => array(
'width' => 300,
'height' => 300,
'crop' => 0, // Set to 0 if you don't want to crop
'file' => 'svgCleanOne.svg',
'mime-type' => 'image/svg+xml',
),
'medium_large' => array(
'width' => 768,
'height' => 0,
'crop' => 0,
'file' => 'svgCleanOne.svg',
'mime-type' => 'image/svg+xml',
),
'large' => array(
'width' => 1024,
'height' => 1024,
'crop' => 0,
'file' => 'svgCleanOne.svg',
'mime-type' => 'image/svg+xml',
),
'1536x1536' => array(
'width' => 1536,
'height' => 1536,
'crop' => 0,
'file' => 'svgCleanOne.svg',
'mime-type' => 'image/svg+xml',
),
'2048x2048' => array(
'width' => 2048,
'height' => 2048,
'crop' => 0,
'file' => 'svgCleanOne.svg',
'mime-type' => 'image/svg+xml',
),
),
),
),
)
);

// Test SVG Dimensions
$image_sizes = $this->instance->one_pixel_fix( array(), 1, 'thumbnail', false );
if ( ! empty( $image_sizes ) ) {
Expand Down

0 comments on commit fbcee2f

Please sign in to comment.