PluginProbe
BeyondWords – AI audio for publishers / 6.0.3
BeyondWords – AI audio for publishers v6.0.3
7.1.0 trunk 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.0.5 4.0.6 4.1.0 4.1.1 4.1.2 4.2.0 4.2.1 4.2.2 4.2.3 4.2.4 4.3.0 4.4.0 4.5.0 4.5.1 4.6.0 4.6.1 4.6.2 4.7.0 All 43 releases
speechkit / src / Component / Posts / BulkEdit / BulkEdit.php

BulkEdit.php in BeyondWords – AI audio for publishers 6.0.3, at src/Component/Posts/BulkEdit/BulkEdit.php

298 lines 8.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 declare(strict_types=1);
4
5 /**
6 * BeyondWords Bulk Edit.
7 *
8 * Text Domain: beyondwords
9 *
10 * @package Beyondwords\Wordpress
11 * @author Stuart McAlpine <stu@beyondwords.io>
12 * @since 3.0.0
13 */
14
15 namespace Beyondwords\Wordpress\Component\Posts\BulkEdit;
16
17 use Beyondwords\Wordpress\Core\Core;
18 use Beyondwords\Wordpress\Core\CoreUtils;
19 use Beyondwords\Wordpress\Component\Settings\SettingsUtils;
20 use Beyondwords\Wordpress\Plugin;
21
22 /**
23 * BulkEdit
24 *
25 * @since 3.0.0
26 */
27 class BulkEdit
28 {
29 /**
30 * Init.
31 *
32 * @since 4.0.0
33 * @since 6.0.0 Make static.
34 */
35 public static function init()
36 {
37 add_action('bulk_edit_custom_box', [self::class, 'bulkEditCustomBox'], 10, 2);
38 add_action('wp_ajax_save_bulk_edit_beyondwords', [self::class, 'saveBulkEdit']);
39
40 add_action('wp_loaded', function (): void {
41 $postTypes = SettingsUtils::getCompatiblePostTypes();
42
43 if (is_array($postTypes)) {
44 foreach ($postTypes as $postType) {
45 add_filter("bulk_actions-edit-{$postType}", [self::class, 'bulkActionsEdit'], 10, 1);
46 add_filter("handle_bulk_actions-edit-{$postType}", [self::class, 'handleBulkDeleteAction'], 10, 3); // phpcs:ignore Generic.Files.LineLength.TooLong
47 add_filter("handle_bulk_actions-edit-{$postType}", [self::class, 'handleBulkGenerateAction'], 10, 3); // phpcs:ignore Generic.Files.LineLength.TooLong
48 }
49 }
50 });
51 }
52
53 /**
54 * Adds the meta box container.
55 *
56 * @since 6.0.0 Make static.
57 */
58 public static function bulkEditCustomBox($columnName, $postType)
59 {
60 if ($columnName !== 'beyondwords') {
61 return;
62 }
63
64 $postTypes = SettingsUtils::getCompatiblePostTypes();
65
66 if (! in_array($postType, $postTypes)) {
67 return;
68 }
69
70 wp_nonce_field('beyondwords_bulk_edit_nonce', 'beyondwords_bulk_edit');
71
72 ?>
73 <fieldset class="inline-edit-col-right">
74 <div class="inline-edit-col">
75 <div class="inline-edit-group wp-clearfix">
76 <label class="alignleft">
77 <span class="title"><?php esc_html_e('BeyondWords', 'speechkit'); ?></span>
78 <select name="beyondwords_generate_audio">
79 <option value="-1"><?php esc_html_e('— No change —', 'speechkit'); ?></option>
80 <option value="generate"><?php esc_html_e('Generate audio', 'speechkit'); ?></option>
81 <option value="delete"><?php esc_html_e('Delete audio', 'speechkit'); ?></option>
82 </select>
83 </label>
84 </div>
85 </div>
86 </fieldset>
87 <?php
88 }
89
90 /**
91 * Save Bulk Edit updates.
92 *
93 * @link https://rudrastyh.com/wordpress/bulk-edit.html
94 *
95 * @since 6.0.0 Make static.
96 */
97 public static function saveBulkEdit()
98 {
99 /*
100 * We need to verify this came from the our screen and with proper authorization,
101 * because save_post can be triggered at other times.
102 */
103 if (
104 ! isset($_POST['beyondwords_bulk_edit_nonce']) ||
105 ! wp_verify_nonce(sanitize_key($_POST['beyondwords_bulk_edit_nonce']), 'beyondwords_bulk_edit')
106 ) {
107 wp_nonce_ays('');
108 }
109
110 if (! isset($_POST['beyondwords_bulk_edit']) || ! isset($_POST['post_ids'])) {
111 return [];
112 }
113
114 if (is_array($_POST['post_ids']) && count($_POST['post_ids'])) {
115 $postIds = array_map('intval', $_POST['post_ids']);
116 $postIds = array_filter($postIds);
117
118 switch ($_POST['beyondwords_bulk_edit']) {
119 case 'generate':
120 return self::generateAudioForPosts($postIds);
121 case 'delete':
122 return self::deleteAudioForPosts($postIds);
123 }
124 }
125
126 return [];
127 }
128
129 /**
130 * Generate audio for posts.
131 *
132 * @since 6.0.0 Make static.
133 */
134 public static function generateAudioForPosts(array|null $postIds): array
135 {
136 if (! is_array($postIds)) {
137 return [];
138 }
139
140 $updatedPostIds = [];
141
142 foreach ($postIds as $postId) {
143 if (! get_post_meta($postId, 'beyondwords_content_id', true)) {
144 update_post_meta($postId, 'beyondwords_generate_audio', '1');
145 }
146 $updatedPostIds[] = $postId;
147 }
148
149 return $updatedPostIds;
150 }
151
152 /**
153 * Delete audio for posts.
154 *
155 * @since 6.0.0 Make static.
156 */
157 public static function deleteAudioForPosts(array|null $postIds): array
158 {
159 if (! is_array($postIds)) {
160 return [];
161 }
162
163 $updatedPostIds = [];
164
165 $response = Core::batchDeleteAudioForPosts($postIds);
166
167 if (! $response) {
168 throw new \Exception(esc_html__('Error while bulk deleting audio. Please contact support with reference BULK-NO-RESPONSE.', 'speechkit')); // phpcs:ignore Generic.Files.LineLength.TooLong
169 }
170
171 // Now process all posts
172 $keys = CoreUtils::getPostMetaKeys('all');
173
174 foreach ($response as $postId) {
175 foreach ($keys as $key) {
176 delete_post_meta($postId, $key);
177 }
178 $updatedPostIds[] = $postId;
179 }
180
181 return $updatedPostIds;
182 }
183
184 /**
185 * Add custom bulk actions to the posts list table.
186 *
187 * @since 6.0.0 Make static.
188 */
189 public static function bulkActionsEdit($bulk_array)
190 {
191 $bulk_array['beyondwords_generate_audio'] = __('Generate audio', 'speechkit');
192 $bulk_array['beyondwords_delete_audio'] = __('Delete audio', 'speechkit');
193
194 return $bulk_array;
195 }
196
197 /**
198 * Handle the "Generate audio" bulk action.
199 *
200 * @since 6.0.0 Make static.
201 */
202 public static function handleBulkGenerateAction($redirect, $doaction, $objectIds)
203 {
204 if ($doaction !== 'beyondwords_generate_audio') {
205 return $redirect;
206 }
207
208 // Remove query args
209 $args = [
210 'beyondwords_bulk_generated',
211 'beyondwords_bulk_deleted',
212 'beyondwords_bulk_failed',
213 'beyondwords_bulk_error',
214 ];
215
216 $redirect = remove_query_arg($args, $redirect);
217
218 // Order batch by Post ID asc
219 sort($objectIds);
220
221 $generated = 0;
222 $failed = 0;
223
224 try {
225 // Update all custom fields before attempting any processing
226 foreach ($objectIds as $postId) {
227 update_post_meta($postId, 'beyondwords_generate_audio', '1');
228 }
229
230 // Now process all posts
231 foreach ($objectIds as $postId) {
232 $response = Core::generateAudioForPost($postId);
233
234 if ($response) {
235 $generated++;
236 } else {
237 $failed++;
238 }
239 }
240 } catch (\Exception $e) {
241 $redirect = add_query_arg('beyondwords_bulk_error', $e->getMessage(), $redirect);
242 }
243
244 // Add $generated & $failed query args into redirect
245 $redirect = add_query_arg('beyondwords_bulk_generated', $generated, $redirect);
246 $redirect = add_query_arg('beyondwords_bulk_failed', $failed, $redirect);
247
248 // Add nonce to redirect url
249 $nonce = wp_create_nonce('beyondwords_bulk_edit_result');
250
251 return add_query_arg('beyondwords_bulk_edit_result_nonce', $nonce, $redirect);
252 }
253
254 /**
255 * Handle the "Delete audio" bulk action.
256 *
257 * @since 6.0.0 Make static.
258 */
259 public static function handleBulkDeleteAction($redirect, $doaction, $objectIds)
260 {
261 if ($doaction !== 'beyondwords_delete_audio') {
262 return $redirect;
263 }
264
265 // Remove query args
266 $args = [
267 'beyondwords_bulk_generated',
268 'beyondwords_bulk_deleted',
269 'beyondwords_bulk_failed',
270 'beyondwords_bulk_error',
271 ];
272
273 $redirect = remove_query_arg($args, $redirect);
274
275 // Order batch by Post ID asc
276 sort($objectIds);
277
278 $deleted = 0;
279
280 // Handle "Delete audio" bulk action
281 try {
282 $result = self::deleteAudioForPosts($objectIds);
283
284 $deleted = count($result);
285
286 // Add $deleted query arg into redirect
287 $redirect = add_query_arg('beyondwords_bulk_deleted', $deleted, $redirect);
288 } catch (\Exception $e) {
289 $redirect = add_query_arg('beyondwords_bulk_error', $e->getMessage(), $redirect);
290 }
291
292 // Add $nonce query arg into redirect
293 $nonce = wp_create_nonce('beyondwords_bulk_edit_result');
294
295 return add_query_arg('beyondwords_bulk_edit_result_nonce', $nonce, $redirect);
296 }
297 }
298