PluginProbe
BeyondWords – AI audio for publishers / 6.3.0
BeyondWords – AI audio for publishers v6.3.0
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.3.0, at src/Component/Posts/BulkEdit/BulkEdit.php

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