PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 28.4
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v28.4
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
wordpress-seo / src / bulk-editor / user-interface / posts-overview-bulk-actions-integration.php

posts-overview-bulk-actions-integration.php in Yoast SEO – Advanced SEO with real-time guidance and built-in AI 28.4, at src/bulk-editor/user-interface/posts-overview-bulk-actions-integration.php

162 lines 5.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure.
4 namespace Yoast\WP\SEO\Bulk_Editor\User_Interface;
5
6 use Yoast\WP\SEO\Bulk_Editor\Application\Content_Types\Content_Types_Repository;
7 use Yoast\WP\SEO\Bulk_Editor\Domain\Updates\Batch_Limit;
8 use Yoast\WP\SEO\Conditionals\Admin_Conditional;
9 use Yoast\WP\SEO\Helpers\Current_Page_Helper;
10 use Yoast\WP\SEO\Integrations\Integration_Interface;
11
12 /**
13 * Adds a "Bulk edit" entry to the bulk-actions dropdown on the post overview screens,
14 * which sends the user to the bulk editor page with their selection carried over.
15 */
16 class Posts_Overview_Bulk_Actions_Integration implements Integration_Interface {
17
18 /**
19 * The value of the bulk action in the dropdown.
20 */
21 public const BULK_ACTION = 'yoast_bulk_editor';
22
23 /**
24 * Holds the Content_Types_Repository.
25 *
26 * @var Content_Types_Repository
27 */
28 private $content_types_repository;
29
30 /**
31 * Holds the Current_Page_Helper.
32 *
33 * @var Current_Page_Helper
34 */
35 private $current_page_helper;
36
37 /**
38 * Constructs the instance.
39 *
40 * @param Content_Types_Repository $content_types_repository The Content_Types_Repository.
41 * @param Current_Page_Helper $current_page_helper The Current_Page_Helper.
42 */
43 public function __construct(
44 Content_Types_Repository $content_types_repository,
45 Current_Page_Helper $current_page_helper
46 ) {
47 $this->content_types_repository = $content_types_repository;
48 $this->current_page_helper = $current_page_helper;
49 }
50
51 /**
52 * Returns the conditionals based on which this loadable should be active.
53 *
54 * @return array<string> The conditionals.
55 */
56 public static function get_conditionals() {
57 return [ Admin_Conditional::class ];
58 }
59
60 /**
61 * Initializes the integration.
62 *
63 * This is the place to register hooks and filters.
64 *
65 * @return void
66 */
67 public function register_hooks() {
68 // The supported post types are only known once post types are registered, so defer collecting them.
69 \add_action( 'admin_init', [ $this, 'register_bulk_actions' ] );
70 }
71
72 /**
73 * Registers the bulk action on the overviews of the post types the bulk editor supports.
74 *
75 * @return void
76 */
77 public function register_bulk_actions() {
78 // The same capability that gates access to the bulk editor page itself.
79 if ( ! \current_user_can( 'wpseo_manage_options' ) ) {
80 return;
81 }
82
83 foreach ( $this->content_types_repository->get_content_types() as $content_type ) {
84 \add_filter( 'bulk_actions-edit-' . $content_type['name'], [ $this, 'add_bulk_action' ] );
85 \add_filter( 'handle_bulk_actions-edit-' . $content_type['name'], [ $this, 'handle_bulk_action' ], 10, 3 );
86 }
87 }
88
89 /**
90 * Adds the bulk editor entry to the bulk-actions dropdown.
91 *
92 * @param array<string, string|array<string, string>> $actions The bulk actions.
93 *
94 * @return array<string, string|array<string, string>> The bulk actions.
95 */
96 public function add_bulk_action( $actions ) {
97 // Trashed posts are not listed in the bulk editor, so the trash view does not get the entry.
98 if ( $this->current_page_helper->is_trash_overview() ) {
99 return $actions;
100 }
101
102 // The arrow signals that this action navigates to another page instead of processing in place.
103 // VS15 (U+FE0E) forces text presentation, so wp-admin's emoji script leaves the glyph alone;
104 // RTL admins get the mirrored glyph.
105 $arrow = ( \is_rtl() ) ? "\u{2196}\u{FE0E}" : "\u{2197}\u{FE0E}";
106
107 // A nested array renders as an optgroup (since WP 5.6): the default actions stay first, followed
108 // by a visually separated "Yoast SEO" group holding the entry.
109 $actions['Yoast SEO'] = [
110 self::BULK_ACTION => \__( 'Bulk edit', 'wordpress-seo' ) . ' ' . $arrow,
111 ];
112
113 return $actions;
114 }
115
116 /**
117 * Handles the bulk action by sending the user to the bulk editor page with the selection carried over.
118 *
119 * @param string $redirect_url The URL the overview would redirect to.
120 * @param string $action The bulk action being handled.
121 * @param array<int> $post_ids The selected post IDs.
122 *
123 * @return string The URL to redirect to.
124 */
125 public function handle_bulk_action( $redirect_url, $action, $post_ids ) {
126 if ( $action !== self::BULK_ACTION ) {
127 return $redirect_url;
128 }
129
130 // The filter only fires on the overview of the post type it was registered for, so the
131 // current screen carries the content type to preselect.
132 $screen = \get_current_screen();
133 if ( $screen === null || $screen->post_type === '' ) {
134 return $redirect_url;
135 }
136
137 $args = [
138 'page' => Bulk_Editor_Integration::PAGE,
139 Bulk_Editor_Integration::CONTENT_TYPE_PARAM => $screen->post_type,
140 ];
141
142 $ids = \array_values(
143 \array_unique(
144 \array_filter(
145 \array_map( 'intval', (array) $post_ids ),
146 static function ( $id ) {
147 return $id > 0;
148 },
149 ),
150 ),
151 );
152
153 if ( $ids !== [] ) {
154 // Only the first batch can end up selected; carrying more would only risk hitting URL length limits.
155 $args[ Bulk_Editor_Integration::POST_IDS_PARAM ] = \implode( ',', \array_slice( $ids, 0, Batch_Limit::MAX_ITEMS ) );
156 $args[ Bulk_Editor_Integration::SELECTED_COUNT_PARAM ] = \count( $ids );
157 }
158
159 return \add_query_arg( $args, \admin_url( 'admin.php' ) );
160 }
161 }
162