Skip to content

Commit dae6939

Browse files
authored
Merge pull request #23557 from Yoast/1396-woo-seo---create-bulk-editor-integration-that-supplies-the-bulk-editor-with-woo-specifics
feat(bulk-editor): supply post images through a filter
2 parents 0788e50 + a289cc4 commit dae6939

9 files changed

Lines changed: 380 additions & 30 deletions

File tree

src/bulk-editor/domain/posts/post.php

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,13 @@ class Post {
7878
*/
7979
private $editable;
8080

81+
/**
82+
* The images and their variations for this post.
83+
*
84+
* @var array<string, int|string>
85+
*/
86+
private $images;
87+
8188
/**
8289
* Whether each field needs improvement, keyed by field param (e.g. `seo_title`). Empty for a post whose
8390
* fields are not editable.
@@ -117,21 +124,22 @@ class Post {
117124
/**
118125
* The constructor.
119126
*
120-
* @param int $id The post ID.
121-
* @param string $title The post title.
122-
* @param string $status The post status.
123-
* @param string $edit_link The URL to edit the post.
124-
* @param string $focus_keyphrase The focus keyphrase.
125-
* @param string $seo_title The raw stored SEO title.
126-
* @param string $meta_description The raw stored meta description.
127-
* @param string $social_title The raw stored social title.
128-
* @param string $social_description The raw stored social description.
129-
* @param bool $editable Whether the current user may edit this post.
130-
* @param array<string, bool> $needs_improvement Whether each field needs improvement, keyed by field param.
131-
* @param string $seo_title_fallback The post type's SEO title template (empty when stored value is set).
132-
* @param string $meta_description_fallback The post type's meta description template (empty when stored value is set).
133-
* @param string $social_title_fallback The post type's social title template (empty when stored value is set).
134-
* @param string $social_description_fallback The post type's social description template (empty when stored value is set).
127+
* @param int $id The post ID.
128+
* @param string $title The post title.
129+
* @param string $status The post status.
130+
* @param string $edit_link The URL to edit the post.
131+
* @param string $focus_keyphrase The focus keyphrase.
132+
* @param string $seo_title The raw stored SEO title.
133+
* @param string $meta_description The raw stored meta description.
134+
* @param string $social_title The raw stored social title.
135+
* @param string $social_description The raw stored social description.
136+
* @param bool $editable Whether the current user may edit this post.
137+
* @param array<string, bool> $needs_improvement Whether each field needs improvement, keyed by field param.
138+
* @param string $seo_title_fallback The post type's SEO title template (empty when stored value is set).
139+
* @param string $meta_description_fallback The post type's meta description template (empty when stored value is set).
140+
* @param string $social_title_fallback The post type's social title template (empty when stored value is set).
141+
* @param string $social_description_fallback The post type's social description template (empty when stored value is set).
142+
* @param array<string, int|string> $images The images and their variations for this post.
135143
*/
136144
public function __construct(
137145
int $id,
@@ -148,7 +156,8 @@ public function __construct(
148156
string $seo_title_fallback = '',
149157
string $meta_description_fallback = '',
150158
string $social_title_fallback = '',
151-
string $social_description_fallback = ''
159+
string $social_description_fallback = '',
160+
array $images = []
152161
) {
153162
$this->id = $id;
154163
$this->title = $title;
@@ -165,6 +174,7 @@ public function __construct(
165174
$this->meta_description_fallback = $meta_description_fallback;
166175
$this->social_title_fallback = $social_title_fallback;
167176
$this->social_description_fallback = $social_description_fallback;
177+
$this->images = $images;
168178
}
169179

170180
/**
@@ -197,6 +207,7 @@ public function to_array(): array {
197207
],
198208
$this->needs_improvement,
199209
),
210+
'images' => $this->images,
200211
];
201212
}
202213
}

src/bulk-editor/infrastructure/posts/indexable-posts-collector.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
*/
2020
class Indexable_Posts_Collector implements Posts_Collector_Interface {
2121

22+
use Post_Images_Trait;
2223
use Post_Title_Trait;
2324
use Searchable_Fields_Trait;
2425

@@ -285,9 +286,10 @@ private function apply_search( ORM $builder, string $search ): void {
285286
private function build_post( Indexable $indexable, bool $editable, bool $scores_enabled ): Post {
286287
$object_id = (int) $indexable->object_id;
287288
$title = $this->get_normalized_title( $object_id );
289+
$images = $this->get_post_images( $object_id, (string) $indexable->object_sub_type );
288290

289291
if ( ! $editable ) {
290-
return new Post( $object_id, $title, (string) $indexable->post_status, '', '', '', '', '', '', false );
292+
return new Post( $object_id, $title, (string) $indexable->post_status, '', '', '', '', '', '', false, [], '', '', '', '', $images );
291293
}
292294

293295
$post_type = (string) $indexable->object_sub_type;
@@ -321,6 +323,7 @@ private function build_post( Indexable $indexable, bool $editable, bool $scores_
321323
( $raw_meta_description === '' ) ? $resolved_values['meta_description'] : '',
322324
( $raw_social_title === '' ) ? $resolved_values['social_title'] : '',
323325
( $raw_social_description === '' ) ? $resolved_values['social_description'] : '',
326+
$images,
324327
);
325328
}
326329

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
// phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure.
4+
namespace Yoast\WP\SEO\Bulk_Editor\Infrastructure\Posts;
5+
6+
/**
7+
* Collects the images shown for a post, shared by both post collectors.
8+
*/
9+
trait Post_Images_Trait {
10+
11+
/**
12+
* Returns the images to show for a post in the bulk editor.
13+
*
14+
* Yoast SEO itself has no images to show, so the list is empty unless an add-on supplies one.
15+
*
16+
* @param int $post_id The post ID.
17+
* @param string $content_type The post type.
18+
*
19+
* @return array<string, int|string> The images.
20+
*/
21+
protected function get_post_images( int $post_id, string $content_type ): array {
22+
/**
23+
* Filter: 'wpseo_bulk_editor_post_images' - Allows add-ons to supply the images shown for a post.
24+
*
25+
* @internal
26+
*
27+
* @param array<string, int|string> $images The images, empty by default.
28+
* @param int $post_id The post ID.
29+
* @param string $content_type The post type.
30+
*/
31+
$images = \apply_filters( 'wpseo_bulk_editor_post_images', [], $post_id, $content_type );
32+
33+
return \is_array( $images ) ? $images : [];
34+
}
35+
}

src/bulk-editor/infrastructure/posts/post-meta-posts-collector.php

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
*/
1818
class Post_Meta_Posts_Collector implements Posts_Collector_Interface {
1919

20+
use Post_Images_Trait;
2021
use Post_Title_Trait;
2122
use Searchable_Fields_Trait;
2223

@@ -114,7 +115,7 @@ public function get_posts( Posts_Query $query ): Posts_Page {
114115

115116
$posts_list = new Posts_List();
116117
foreach ( $post_ids as $post_id ) {
117-
$posts_list->add( $this->build_post( $post_id, ( $editability[ $post_id ] ?? false ), $query->are_scores_enabled() ) );
118+
$posts_list->add( $this->build_post( $post_id, ( $editability[ $post_id ] ?? false ), $query->are_scores_enabled(), $query->get_content_type() ) );
118119
}
119120

120121
return new Posts_Page( $posts_list, (int) $wp_query->found_posts, $query->get_page(), $query->get_per_page() );
@@ -214,20 +215,22 @@ public function filter_posts_where( $where, $wp_query ): string {
214215
* The SEO data and edit link of a post the current user cannot edit are withheld, so the post is
215216
* shown in the list but stays locked and does not expose its metadata.
216217
*
217-
* @param int $post_id The post ID.
218-
* @param bool $editable Whether the current user may edit the post.
219-
* @param bool $scores_enabled Whether the per-field scores may back the needs-improvement verdict.
218+
* @param int $post_id The post ID.
219+
* @param bool $editable Whether the current user may edit the post.
220+
* @param bool $scores_enabled Whether the per-field scores may back the needs-improvement verdict.
221+
* @param string $content_type The post type of the collected page.
220222
*
221223
* @return Post The post.
222224
*/
223-
private function build_post( int $post_id, bool $editable, bool $scores_enabled ): Post {
225+
private function build_post( int $post_id, bool $editable, bool $scores_enabled, string $content_type ): Post {
224226
$post = \get_post( $post_id );
225227
$status = ( $post !== null ) ? (string) $post->post_status : '';
226228
$post_type = ( $post !== null ) ? (string) $post->post_type : '';
227229
$title = $this->get_normalized_title( $post_id );
230+
$images = $this->get_post_images( $post_id, $content_type );
228231

229232
if ( ! $editable ) {
230-
return new Post( $post_id, $title, $status, '', '', '', '', '', '', false );
233+
return new Post( $post_id, $title, $status, '', '', '', '', '', '', false, [], '', '', '', '', $images );
231234
}
232235

233236
// Read each field's value once from its meta suffix, keyed by field param, so the values can be reused for
@@ -264,6 +267,7 @@ private function build_post( int $post_id, bool $editable, bool $scores_enabled
264267
( $raw_meta_description === '' ) ? $fields['meta_description'] : '',
265268
( $raw_social_title === '' ) ? $fields['social_title'] : '',
266269
( $raw_social_description === '' ) ? $fields['social_description'] : '',
270+
$images,
267271
);
268272
}
269273

tests/Unit/Bulk_Editor/Domain/Posts/Post_Test.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,50 @@ public function test_to_array() {
6767
'social_title' => false,
6868
'social_description' => true,
6969
],
70+
'images' => [],
7071
],
7172
$instance->to_array(),
7273
);
7374
}
7475

76+
/**
77+
* Tests that the images passed to the post are exposed as they were given.
78+
*
79+
* @return void
80+
*/
81+
public function test_to_array_with_images() {
82+
$images = [
83+
'thumbnail' => 'https://example.com/product.jpg',
84+
'count' => 3,
85+
];
86+
87+
$instance = new Post(
88+
7,
89+
'Hello world',
90+
'draft',
91+
'',
92+
'',
93+
'',
94+
'',
95+
'',
96+
'',
97+
true,
98+
[
99+
'seo_title' => false,
100+
'meta_description' => true,
101+
'social_title' => false,
102+
'social_description' => true,
103+
],
104+
'',
105+
'',
106+
'',
107+
'',
108+
$images,
109+
);
110+
111+
$this->assertSame( $images, $instance->to_array()['images'] );
112+
}
113+
75114
/**
76115
* Tests that a locked post reports itself as not editable.
77116
*
@@ -102,6 +141,7 @@ public function test_to_array_not_editable() {
102141
'social_title' => false,
103142
'social_description' => false,
104143
],
144+
'images' => [],
105145
],
106146
$instance->to_array(),
107147
);

tests/Unit/Bulk_Editor/Domain/Posts/Posts_Page_Test.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ public function test_to_array() {
5353
'social_title' => false,
5454
'social_description' => false,
5555
],
56+
'images' => [],
5657
],
5758
],
5859
'total' => 45,

0 commit comments

Comments
 (0)