PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 28.5
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v28.5
28.5 28.4 28.3 28.2 28.1 28.0 27.9 27.8 27.7 27.6 27.5 trunk 18.0 18.1 18.2 18.3 18.4 18.4.1 18.5 18.5.1 18.6 18.7 18.8 18.9 19.0 All 129 releases
← All changes | src/helpers/image-helper.php +72 -23 18.228.5 View file →
@@ -2,9 +2,11 @@
2 2
3 3 namespace Yoast\WP\SEO\Helpers;
4 4
5 5 use WPSEO_Image_Utils;
6 +use Yoast\WP\SEO\Models\SEO_Links;
6 7 use Yoast\WP\SEO\Repositories\Indexable_Repository;
8 +use Yoast\WP\SEO\Repositories\SEO_Links_Repository;
7 9
8 10 /**
9 11 * A helper object for images.
10 12 */
@@ -14,9 +16,9 @@
14 16 * Image types that are supported by Open Graph.
15 17 *
16 18 * @var array
17 19 */
18 - protected static $valid_image_types = [ 'image/jpeg', 'image/gif', 'image/png' ];
20 + protected static $valid_image_types = [ 'image/jpeg', 'image/gif', 'image/png', 'image/webp' ];
19 21
20 22 /**
21 23 * Image extensions that are supported by Open Graph.
22 24 *
@@ -21,9 +23,9 @@
21 23 * Image extensions that are supported by Open Graph.
22 24 *
23 25 * @var array
24 26 */
25 - protected static $valid_image_extensions = [ 'jpeg', 'jpg', 'gif', 'png' ];
27 + protected static $valid_image_extensions = [ 'jpeg', 'jpg', 'gif', 'png', 'webp' ];
26 28
27 29 /**
28 30 * Represents the indexables repository.
29 31 *
@@ -31,23 +33,46 @@
31 33 */
32 34 protected $indexable_repository;
33 35
34 36 /**
37 + * Represents the SEO Links repository.
38 + *
39 + * @var SEO_Links_Repository
40 + */
41 + protected $seo_links_repository;
42 +
43 + /**
35 44 * The options helper.
36 45 *
37 46 * @var Options_Helper
38 47 */
39 - private $options;
48 + private $options_helper;
40 49
41 50 /**
51 + * The URL helper.
52 + *
53 + * @var Url_Helper
54 + */
55 + private $url_helper;
56 +
57 + /**
42 58 * Image_Helper constructor.
43 59 *
44 60 * @param Indexable_Repository $indexable_repository The indexable repository.
61 + * @param SEO_Links_Repository $seo_links_repository The SEO Links repository.
45 62 * @param Options_Helper $options The options helper.
63 + * @param Url_Helper $url_helper The URL helper.
46 64 */
47 - public function __construct( Indexable_Repository $indexable_repository, Options_Helper $options ) {
65 + public function __construct(
66 + Indexable_Repository $indexable_repository,
67 + SEO_Links_Repository $seo_links_repository,
68 + Options_Helper $options,
69 + Url_Helper $url_helper
70 + ) {
48 71 $this->indexable_repository = $indexable_repository;
49 - $this->options = $options;
72 + $this->seo_links_repository = $seo_links_repository;
73 + $this->options_helper = $options;
74 + $this->url_helper = $url_helper;
50 75 }
51 76
52 77 /**
53 78 * Determines whether or not the wanted attachment is considered valid.
@@ -271,35 +296,58 @@
271 296
272 297 /**
273 298 * Find an attachment ID for a given URL.
274 299 *
275 - * @param string $url The URL to find the attachment for.
300 + * @param string $url The URL to find the attachment for.
301 + * @param bool $use_link_table Whether the SEO Links table will be used to retrieve the id.
276 302 *
277 303 * @return int The found attachment ID, or 0 if none was found.
278 304 */
279 - public function get_attachment_by_url( $url ) {
280 - // Strip out the size part of an image URL.
281 - $url = \preg_replace( '/(.*)-\d+x\d+\.(jpeg|jpg|png|gif)$/', '$1.$2', $url );
282 -
305 + public function get_attachment_by_url( $url, $use_link_table = true ) {
283 306 // Don't try to do this for external URLs.
284 - if ( \strpos( $url, \get_site_url() ) !== 0 ) {
307 + $parsed_url = \wp_parse_url( $url );
308 + if ( $this->url_helper->get_link_type( $parsed_url ) === SEO_Links::TYPE_EXTERNAL ) {
285 309 return 0;
286 310 }
287 311
288 - $indexable = $this->indexable_repository->find_by_permalink( $url );
312 + /** The `wpseo_force_creating_and_using_attachment_indexables` filter is documented in indexable-link-builder.php */
313 + if ( ! $this->options_helper->get( 'disable-attachment' ) || \apply_filters( 'wpseo_force_creating_and_using_attachment_indexables', false ) ) {
314 + // Strip out the size part of an image URL.
315 + $url = \preg_replace( '/(.*)-\d+x\d+\.(jpeg|jpg|png|gif)$/', '$1.$2', $url );
289 316
290 - if ( $indexable && $indexable->object_type === 'post' && $indexable->object_sub_type === 'attachment' ) {
291 - return $indexable->object_id;
317 + $indexable = $this->indexable_repository->find_by_permalink( $url );
318 +
319 + if ( $indexable && $indexable->object_type === 'post' && $indexable->object_sub_type === 'attachment' ) {
320 + return $indexable->object_id;
321 + }
322 +
323 + $post_id = WPSEO_Image_Utils::get_attachment_by_url( $url );
324 +
325 + if ( $post_id !== 0 ) {
326 + // Find the indexable, this triggers creating it so it can be found next time.
327 + $this->indexable_repository->find_by_id_and_type( $post_id, 'post' );
328 + }
329 +
330 + return $post_id;
292 331 }
293 332
294 - $post_id = WPSEO_Image_Utils::get_attachment_by_url( $url );
333 + if ( ! $use_link_table ) {
334 + return WPSEO_Image_Utils::get_attachment_by_url( $url );
335 + }
336 + $cache_key = 'attachment_seo_link_object_' . \md5( $url );
295 337
296 - if ( $post_id !== 0 ) {
297 - // Find the indexable, this triggers creating it so it can be found next time.
298 - $this->indexable_repository->find_by_id_and_type( $post_id, 'post' );
338 + $found = false;
339 + $link = \wp_cache_get( $cache_key, 'yoast-seo-attachment-link', false, $found );
340 +
341 + if ( $found === false ) {
342 + $link = $this->seo_links_repository->find_one_by_url( $url );
343 + \wp_cache_set( $cache_key, $link, 'yoast-seo-attachment-link', \MINUTE_IN_SECONDS );
299 344 }
345 + if ( ! \is_a( $link, SEO_Links::class ) ) {
346 + return WPSEO_Image_Utils::get_attachment_by_url( $url );
347 + }
300 348
301 - return $post_id;
349 + return $link->target_post_id;
302 350 }
303 351
304 352 /**
305 353 * Retrieves an attachment ID for an image uploaded in the settings.
@@ -317,9 +365,10 @@
317 365 return WPSEO_Image_Utils::get_attachment_id_from_settings( $setting );
318 366 }
319 367
320 368 /**
321 - * Based on and image ID return array with the best variation of that image. If it's not saved to the DB, save it to an option.
369 + * Based on and image ID return array with the best variation of that image. If it's not saved to the DB, save it
370 + * to an option.
322 371 *
323 372 * @param string $setting The setting name. Should be company or person.
324 373 *
325 374 * @return array|bool Array with image details when the image is found, boolean when it's not found.
@@ -324,17 +373,17 @@
324 373 *
325 374 * @return array|bool Array with image details when the image is found, boolean when it's not found.
326 375 */
327 376 public function get_attachment_meta_from_settings( $setting ) {
328 - $image_meta = $this->options->get( $setting . '_meta', false );
377 + $image_meta = $this->options_helper->get( $setting . '_meta', false );
329 378 if ( ! $image_meta ) {
330 - $image_id = $this->options->get( $setting . '_id', false );
379 + $image_id = $this->options_helper->get( $setting . '_id', false );
331 380 if ( $image_id ) {
332 381 // There is not an option to put a URL in an image field in the settings anymore, only to upload it through the media manager.
333 382 // This means an attachment always exists, so doing this is only needed once.
334 383 $image_meta = $this->get_best_attachment_variation( $image_id );
335 384 if ( $image_meta ) {
336 - $this->options->set( $setting . '_meta', $image_meta );
385 + $this->options_helper->set( $setting . '_meta', $image_meta );
337 386 }
338 387 }
339 388 }
340 389