PluginProbe ʕ •ᴥ•ʔ
Permalink Manager Lite / 2.4.4.3
Permalink Manager Lite v2.4.4.3
2.5.4 2.5.3.4 2.2.18 2.2.19.2 2.2.19.3 2.2.19.3.1 2.2.2 2.2.20 2.2.20.1 2.2.20.3 2.2.4 2.2.5 2.2.6 2.2.7.2 2.2.7.3 2.2.7.5 2.2.7.6 2.2.8.4 2.2.8.5 2.2.8.6 2.2.8.7 2.2.8.9 2.2.9.1 2.2.9.2 2.2.9.2.1 2.2.9.3 2.2.9.4 2.2.9.6 2.2.9.7 2.2.9.9 2.3.0 2.3.1.1 2.4.0 2.4.1 2.4.1.2 2.4.1.3 2.4.1.4 2.4.1.5 2.4.1.6 2.4.2 2.4.2.1 2.4.3 2.4.3.1 2.4.3.2 2.4.3.3 2.4.3.4 2.4.4 2.4.4.1 2.4.4.2 2.4.4.3 2.5.0 2.5.1 2.5.1.1 2.5.1.2 2.5.1.3 2.5.1.4 2.5.2 2.5.2.1 2.5.2.2 2.5.2.3 2.5.2.4 2.5.3 2.5.3.1 2.5.3.2 2.5.3.3 trunk 0.2 0.3 0.3.1 0.3.2 0.3.3 0.3.4 0.4 0.4.1 0.4.2 0.4.3 0.4.4 0.4.6 0.4.7 0.4.8 0.4.9 0.5.3 0.5.4 1.0.0 1.0.1 1.0.4 1.1.0 1.1.1 1.1.2 1.11.6.3 2.0.0 2.0.3 2.0.4 2.0.4.3 2.0.5.1 2.0.5.2 2.0.5.3 2.0.5.3.1 2.0.5.4 2.0.5.4a 2.0.5.5 2.0.5.6 2.0.5.6.1 2.0.5.7 2.0.5.9a 2.0.6.2.1 2.0.6.2a 2.0.6.3 2.1.0 2.1.1 2.1.2.4 2.2.0 2.2.1.1 2.2.1.2 2.2.11 2.2.12 2.2.13.1 2.2.14 2.2.15.1 2.2.16 2.2.17
permalink-manager / includes / core / permalink-manager-actions.php
permalink-manager / includes / core Last commit date
permalink-manager-actions.php 1 year ago permalink-manager-admin-functions.php 1 year ago permalink-manager-core-functions.php 1 year ago permalink-manager-debug.php 1 year ago permalink-manager-gutenberg.php 1 year ago permalink-manager-helper-functions.php 1 year ago permalink-manager-uri-functions-post.php 1 year ago permalink-manager-uri-functions.php 1 year ago
permalink-manager-actions.php
732 lines
1 <?php
2
3 /**
4 * Additional hooks for "Permalink Manager Pro"
5 */
6 class Permalink_Manager_Actions {
7
8 public function __construct() {
9 add_action( 'admin_init', array( $this, 'trigger_action' ), 9 );
10 add_action( 'admin_init', array( $this, 'extra_actions' ) );
11
12 // Ajax-based functions
13 if ( is_admin() ) {
14 add_action( 'wp_ajax_pm_bulk_tools', array( $this, 'ajax_bulk_tools' ) );
15 add_action( 'wp_ajax_pm_save_permalink', array( $this, 'ajax_save_permalink' ) );
16 add_action( 'wp_ajax_pm_detect_duplicates', array( $this, 'ajax_detect_duplicates' ) );
17 add_action( 'wp_ajax_pm_dismissed_notice_handler', array( $this, 'ajax_hide_global_notice' ) );
18 }
19 }
20
21 /**
22 * Route the requests to functions that save datasets with associated callbacks
23 */
24 public function trigger_action() {
25 global $permalink_manager_after_sections_html;
26
27 // 1. Check if the form was submitted
28 if ( empty( $_POST ) ) {
29 return;
30 }
31
32 // 2. Do nothing if search query is not empty
33 if ( isset( $_REQUEST['search-submit'] ) || isset( $_REQUEST['months-filter-button'] ) ) {
34 return;
35 }
36
37 $actions_map = array(
38 'uri_editor' => array( 'function' => 'update_all_permalinks', 'display_uri_table' => true ),
39 'permalink_manager_options' => array( 'function' => 'save_settings' ),
40 'permalink_manager_permastructs' => array( 'function' => 'save_permastructures' ),
41 'import' => array( 'function' => 'import_custom_permalinks_uris' ),
42 );
43
44 // 3. Find the action
45 foreach ( $actions_map as $action => $map ) {
46 if ( isset( $_POST[ $action ] ) && wp_verify_nonce( $_POST[ $action ], 'permalink-manager' ) ) {
47 // Execute the function
48 $output = call_user_func( array( $this, $map['function'] ) );
49
50 // Get list of updated URIs
51 if ( ! empty( $map['display_uri_table'] ) ) {
52 $updated_slugs_count = ( isset( $output['updated_count'] ) && $output['updated_count'] > 0 ) ? $output['updated_count'] : false;
53 $updated_slugs_array = ( $updated_slugs_count ) ? $output['updated'] : '';
54 }
55
56 // Trigger only one function
57 break;
58 }
59 }
60
61 // 4. Display the slugs table (and append the globals)
62 if ( isset( $updated_slugs_count ) && isset( $updated_slugs_array ) ) {
63 $permalink_manager_after_sections_html .= Permalink_Manager_UI_Elements::display_updated_slugs( $updated_slugs_array );
64 }
65 }
66
67 /**
68 * Route the requests to the additional tools-related functions with the relevant callbacks
69 */
70 public static function extra_actions() {
71 global $permalink_manager_before_sections_html;
72
73 if ( current_user_can( 'manage_options' ) && ! empty( $_GET['permalink-manager-nonce'] ) ) {
74 // Check if the nonce field is correct
75 $nonce = sanitize_key( $_GET['permalink-manager-nonce'] );
76
77 if ( ! wp_verify_nonce( $nonce, 'permalink-manager' ) ) {
78 $permalink_manager_before_sections_html = Permalink_Manager_UI_Elements::get_alert_message( __( 'You are not allowed to remove Permalink Manager data!', 'permalink-manager' ), 'error updated_slugs' );
79
80 return;
81 }
82
83 if ( isset( $_GET['clear-permalink-manager-uris'] ) ) {
84 self::clear_all_uris();
85 } else if ( isset( $_GET['remove-permalink-manager-settings'] ) ) {
86 $option_name = sanitize_text_field( $_GET['remove-permalink-manager-settings'] );
87 self::remove_plugin_data( $option_name );
88 } else if ( ! empty( $_REQUEST['remove-uri'] ) ) {
89 $uri_key = sanitize_text_field( $_REQUEST['remove-uri'] );
90 self::force_clear_single_element_uris_and_redirects( $uri_key );
91 } else if ( ! empty( $_REQUEST['remove-redirect'] ) ) {
92 $redirect_key = sanitize_text_field( $_REQUEST['remove-redirect'] );
93 self::force_clear_single_redirect( $redirect_key );
94 }
95 } else if ( ! empty( $_POST['screen-options-apply'] ) ) {
96 self::save_screen_options();
97 }
98 }
99
100 /**
101 * Bulk remove obsolete custom permalinks and redirects
102 */
103 public static function clear_all_uris() {
104 global $permalink_manager_redirects, $permalink_manager_before_sections_html;
105
106 // Get all custom permalinks & redirects
107 $custom_permalinks = Permalink_Manager_URI_Functions::get_all_uris();
108 $custom_redirects = (array) $permalink_manager_redirects;
109
110 // Check if array with custom URIs exists
111 if ( empty( $custom_permalinks ) ) {
112 return;
113 }
114
115 // Count removed URIs & redirects
116 $removed_uris = 0;
117 $removed_redirects = 0;
118
119 // Get all element IDs
120 $element_ids = array_merge( array_keys( $custom_permalinks ), array_keys( $custom_redirects ) );
121
122 // 1. Remove unused custom URI & redirects for deleted post or term
123 foreach ( $element_ids as $element_id ) {
124 $count = self::clear_single_element_uris_and_redirects( $element_id, true );
125
126 $removed_uris = ( ! empty( $count[0] ) ) ? $count[0] + $removed_uris : $removed_uris;
127 $removed_redirects = ( ! empty( $count[1] ) ) ? $count[1] + $removed_redirects : $removed_redirects;
128 }
129
130 // 2. Keep only a single redirect
131 $removed_redirects += self::clear_redirects_array();
132
133 // 3. Save cleared URIs & Redirects
134 if ( $removed_uris > 0 || $removed_redirects > 0 ) {
135 Permalink_Manager_URI_Functions::save_all_uris();
136 update_option( 'permalink-manager-redirects', array_filter( $permalink_manager_redirects ), true );
137
138 // Translators: 1: Number of custom URIs, 2: Number of custom redirects.
139 $permalink_manager_before_sections_html .= Permalink_Manager_UI_Elements::get_alert_message( sprintf( __( '%1$d Custom URIs and %2$d Custom Redirects were removed!', 'permalink-manager' ), $removed_uris, $removed_redirects ), 'updated updated_slugs' );
140 } else {
141 $permalink_manager_before_sections_html .= Permalink_Manager_UI_Elements::get_alert_message( __( 'No Custom URIs or Custom Redirects were removed!', 'permalink-manager' ), 'error updated_slugs' );
142 }
143 }
144
145 /**
146 * Remove obsolete custom permalink & redirects for specific post or term
147 *
148 * @param string|int $element_id
149 * @param bool $count_removed
150 *
151 * @return array
152 */
153 public static function clear_single_element_uris_and_redirects( $element_id, $count_removed = false ) {
154 global $wpdb, $permalink_manager_redirects, $permalink_manager_options;
155
156 // Count removed URIs & redirects
157 $removed_uris = 0;
158 $removed_redirects = 0;
159
160 // Only admin users can remove the broken URIs for removed post types & taxonomies
161 $check_if_admin = is_admin();
162
163 // Check if the advanced mode is turned on
164 $advanced_mode = Permalink_Manager_Helper_Functions::is_advanced_mode_on();
165
166 // If "Disable URI Editor to disallow Permalink changes" is set globally, the pages that follow the global settings should also be removed
167 if ( $advanced_mode && ! empty( $permalink_manager_options["general"]["auto_update_uris"] ) && $permalink_manager_options["general"]["auto_update_uris"] == 2 ) {
168 $strict_mode = true;
169 } else {
170 $strict_mode = false;
171 }
172
173 // 1. Check if element exists
174 if ( strpos( $element_id, 'tax-' ) !== false ) {
175 $term_id = preg_replace( "/[^0-9]/", "", $element_id );
176 $term_info = $wpdb->get_row( $wpdb->prepare( "SELECT taxonomy, meta_value FROM {$wpdb->term_taxonomy} AS t LEFT JOIN {$wpdb->termmeta} AS tm ON tm.term_id = t.term_id AND tm.meta_key = 'auto_update_uri' WHERE t.term_id = %d", $term_id ) );
177
178 // Custom URIs for disabled taxonomies may only be deleted via the admin dashboard, although they will always be removed if the term no longer exists in the database
179 $remove = ( ! empty( $term_info->taxonomy ) ) ? Permalink_Manager_Helper_Functions::is_taxonomy_disabled( $term_info->taxonomy, $check_if_admin ) : true;
180
181 // Remove custom URIs for URIs disabled in URI Editor
182 if ( $strict_mode ) {
183 $remove = ( empty( $term_info->meta_value ) || $term_info->meta_value == 2 ) ? true : $remove;
184 } else {
185 $remove = ( ! empty( $term_info->meta_value ) && $term_info->meta_value == 2 ) ? true : $remove;
186 }
187 } else if ( is_numeric( $element_id ) ) {
188 $post_info = $wpdb->get_row( $wpdb->prepare( "SELECT post_type, meta_value FROM {$wpdb->posts} AS p LEFT JOIN {$wpdb->postmeta} AS pm ON pm.post_ID = p.ID AND pm.meta_key = 'auto_update_uri' WHERE ID = %d AND post_status NOT IN ('auto-draft', 'trash') AND post_type != 'nav_menu_item'", $element_id ) );
189
190 // Custom URIs for disabled post types may only be deleted via the admin dashboard, although they will always be removed if the post no longer exists in the database
191 $remove = ( ! empty( $post_info->post_type ) ) ? Permalink_Manager_Helper_Functions::is_post_type_disabled( $post_info->post_type, $check_if_admin ) : true;
192
193 // Remove custom URIs for URIs disabled in URI Editor
194 if ( $strict_mode ) {
195 $remove = ( empty( $post_info->meta_value ) || $post_info->meta_value == 2 ) ? true : $remove;
196 } else {
197 $remove = ( ! empty( $post_info->meta_value ) && $post_info->meta_value == 2 ) ? true : $remove;
198 }
199
200 // Remove custom URIs for attachments redirected with Yoast's SEO Premium
201 $yoast_permalink_options = ( class_exists( 'WPSEO_Premium' ) ) ? get_option( 'wpseo_permalinks' ) : array();
202
203 if ( ! empty( $yoast_permalink_options['redirectattachment'] ) && $post_info->post_type == 'attachment' ) {
204 $attachment_parent = $wpdb->get_var( "SELECT post_parent FROM {$wpdb->prefix}posts WHERE ID = {$element_id} AND post_type = 'attachment'" );
205 if ( ! empty( $attachment_parent ) ) {
206 $remove = true;
207 }
208 }
209 }
210
211 // 2A. Remove ALL unused custom permalinks & redirects
212 if ( ! empty( $remove ) ) {
213 $current_uri = Permalink_Manager_URI_Functions::get_single_uri( $element_id, false, true, null );
214
215 // Remove URI
216 if ( ! empty( $current_uri ) ) {
217 $removed_uris = 1;
218 Permalink_Manager_URI_Functions::remove_single_uri( $element_id, null, false );
219 }
220
221 // Remove all custom redirects
222 if ( ! empty( $permalink_manager_redirects[ $element_id ] ) && is_array( $permalink_manager_redirects[ $element_id ] ) ) {
223 $removed_redirects = count( $permalink_manager_redirects[ $element_id ] );
224 unset( $permalink_manager_redirects[ $element_id ] );
225 }
226 } // 2B. Check if the post/term uses the same URI for both permalink & custom redirects
227 else {
228 $removed_redirect = self::clear_single_element_duplicated_redirect( $element_id, false );
229 $removed_redirects = ( ! empty( $removed_redirect ) ) ? 1 : 0;
230 }
231
232 // Check if function should only return the counts or update
233 if ( $count_removed ) {
234 return array( $removed_uris, $removed_redirects );
235 } else if ( ! empty( $removed_uris ) || ! empty( $removed_redirects ) ) {
236 Permalink_Manager_URI_Functions::save_all_uris();
237 update_option( 'permalink-manager-redirects', array_filter( $permalink_manager_redirects ), true );
238 }
239
240 return array();
241 }
242
243 /**
244 * Remove the duplicated custom redirect if the post/term has the same URI for both custom permalink and custom redirect
245 *
246 * @param string|int $element_id
247 * @param bool $save_redirects
248 * @param string $uri
249 *
250 * @return int
251 */
252 public static function clear_single_element_duplicated_redirect( $element_id, $save_redirects = true, $uri = null ) {
253 global $permalink_manager_redirects;
254
255 // If the custom permalink is not changed ($uri) use the one that is currently used
256 if( ! empty( $uri ) ) {
257 $current_uri = $uri;
258 } else {
259 $current_uri = Permalink_Manager_URI_Functions::get_single_uri( $element_id, false, true, null );
260 }
261
262 if ( ! empty( $current_uri ) && ! empty( $permalink_manager_redirects[ $element_id ] ) && in_array( $current_uri, $permalink_manager_redirects[ $element_id ] ) ) {
263 $duplicated_redirect_id = array_search( $current_uri, $permalink_manager_redirects[ $element_id ] );
264 unset( $permalink_manager_redirects[ $element_id ][ $duplicated_redirect_id ] );
265 }
266
267 // Update the redirects array in the database if the duplicated redirect was unset
268 if ( isset( $duplicated_redirect_id ) && $save_redirects ) {
269 update_option( 'permalink-manager-redirects', array_filter( $permalink_manager_redirects ) );
270 }
271
272 return ( isset( $duplicated_redirect_id ) ) ? 1 : 0;
273 }
274
275 /**
276 * Remove the duplicated if the same URI is used for multiple custom redirects and return the removed redirects count
277 *
278 * @param bool $save_redirects
279 *
280 * @return int
281 */
282 public static function clear_redirects_array( $save_redirects = false ) {
283 global $permalink_manager_redirects;
284
285 $removed_redirects = 0;
286
287 $all_redirect_duplicates = Permalink_Manager_Admin_Functions::get_all_duplicates();
288
289 foreach ( $all_redirect_duplicates as $single_redirect_duplicate ) {
290 $last_element = reset( $single_redirect_duplicate );
291
292 foreach ( $single_redirect_duplicate as $redirect_key ) {
293 // Keep a single redirect
294 if ( $last_element == $redirect_key ) {
295 continue;
296 }
297 preg_match( "/redirect-(\d+)_(tax-\d+|\d+)/", $redirect_key, $ids );
298
299 if ( ! empty( $ids[2] ) && ! empty( $permalink_manager_redirects[ $ids[2] ][ $ids[1] ] ) ) {
300 $removed_redirects ++;
301 unset( $permalink_manager_redirects[ $ids[2] ][ $ids[1] ] );
302 }
303 }
304 }
305
306 // Update the redirects array in the database if the duplicated redirect was unset
307 if ( isset( $duplicated_redirect_id ) && $save_redirects ) {
308 update_option( 'permalink-manager-redirects', array_filter( $permalink_manager_redirects ) );
309 }
310
311 return $removed_redirects;
312 }
313
314 /**
315 * Remove custom permalinks & custom redirects for requested post or term
316 *
317 * @param $uri_key
318 *
319 * @return bool
320 */
321 public static function force_clear_single_element_uris_and_redirects( $uri_key ) {
322 global $permalink_manager_redirects, $permalink_manager_before_sections_html;
323
324 $custom_uri = Permalink_Manager_URI_Functions::get_single_uri( $uri_key, false, true, null );
325
326 // Check if custom URI is set
327 if ( ! empty( $custom_uri ) ) {
328 Permalink_Manager_URI_Functions::remove_single_uri( $uri_key, null, true );
329 // translators: %s is the custom URI that was removed.
330 $updated = Permalink_Manager_UI_Elements::get_alert_message( sprintf( __( 'URI "%s" was removed successfully!', 'permalink-manager' ), $custom_uri ), 'updated' );
331 }
332
333 // Check if custom redirects are set
334 if ( isset( $permalink_manager_redirects[ $uri_key ] ) ) {
335 unset( $permalink_manager_redirects[ $uri_key ] );
336 update_option( 'permalink-manager-redirects', $permalink_manager_redirects, true );
337 }
338
339 if ( empty( $updated ) ) {
340 $permalink_manager_before_sections_html .= Permalink_Manager_UI_Elements::get_alert_message( __( 'URI and/or custom redirects does not exist or were already removed!', 'permalink-manager' ), 'error' );
341 } else {
342 // Display the alert in admin panel
343 if ( isset( $permalink_manager_before_sections_html ) && is_admin() ) {
344 $permalink_manager_before_sections_html .= $updated;
345 }
346 }
347
348 return true;
349 }
350
351 /**
352 * Remove only custom redirects for requested post or term
353 *
354 * @param string $redirect_key
355 */
356 public static function force_clear_single_redirect( $redirect_key ) {
357 global $permalink_manager_redirects, $permalink_manager_before_sections_html;
358
359 preg_match( "/redirect-(\d+)_(tax-\d+|\d+)/", $redirect_key, $ids );
360
361 if ( ! empty( $permalink_manager_redirects[ $ids[2] ][ $ids[1] ] ) ) {
362 unset( $permalink_manager_redirects[ $ids[2] ][ $ids[1] ] );
363
364 update_option( 'permalink-manager-redirects', array_filter( $permalink_manager_redirects ) );
365
366 $permalink_manager_before_sections_html = Permalink_Manager_UI_Elements::get_alert_message( __( 'The redirect was removed successfully!', 'permalink-manager' ), 'updated' );
367 }
368 }
369
370 /**
371 * Save "Screen Options"
372 */
373 public static function save_screen_options() {
374 check_admin_referer( 'screen-options-nonce', 'screenoptionnonce' );
375
376 // The values will be sanitized inside the function
377 self::save_settings( 'screen-options', $_POST['screen-options'] );
378 }
379
380 /**
381 * Save the plugin settings
382 *
383 * @param bool $field
384 * @param bool $value
385 * @param bool $display_alert
386 */
387 public static function save_settings( $field = false, $value = false, $display_alert = true ) {
388 global $permalink_manager_options, $permalink_manager_before_sections_html;
389
390 // Info: The settings array is used also by "Screen Options"
391 $new_options = $permalink_manager_options;
392 //$new_options = array();
393
394 // Save only selected field/sections
395 if ( $field && $value ) {
396 $new_options[ $field ] = $value;
397 } else {
398 $post_fields = $_POST;
399
400 foreach ( $post_fields as $option_name => $option_value ) {
401 $new_options[ $option_name ] = $option_value;
402 }
403 }
404
405 // Allow only white-listed option groups
406 foreach ( $new_options as $group => $group_options ) {
407 if ( ! in_array( $group, array( 'licence', 'screen-options', 'general', 'permastructure-settings', 'stop-words' ) ) ) {
408 unset( $new_options[ $group ] );
409 }
410 }
411
412 // Sanitize & override the global with new settings
413 $new_options = Permalink_Manager_Helper_Functions::sanitize_array( $new_options );
414 $permalink_manager_options = $new_options = array_filter( $new_options );
415
416 // Save the settings in database
417 update_option( 'permalink-manager', $new_options );
418
419 // Display the message
420 $permalink_manager_before_sections_html .= ( $display_alert ) ? Permalink_Manager_UI_Elements::get_alert_message( __( 'The settings are saved!', 'permalink-manager' ), 'updated' ) : "";
421 }
422
423 /**
424 * Save the permastructures
425 */
426 public static function save_permastructures() {
427 global $permalink_manager_permastructs;
428
429 $permastructure_options = $permastructures = array();
430 $permastructure_types = array( 'post_types', 'taxonomies' );
431
432 // Split permastructures & sanitize them
433 foreach ( $permastructure_types as $type ) {
434 if ( empty( $_POST[ $type ] ) || ! is_array( $_POST[ $type ] ) ) {
435 continue;
436 }
437
438 $permastructures[ $type ] = $_POST[ $type ];
439
440 foreach ( $permastructures[ $type ] as &$single_permastructure ) {
441 $single_permastructure = Permalink_Manager_Helper_Functions::sanitize_title( $single_permastructure, true, false, false );
442 $single_permastructure = trim( $single_permastructure, '\/ ' );
443 }
444 }
445
446 if ( ! empty( $_POST['permastructure-settings'] ) ) {
447 $permastructure_options = $_POST['permastructure-settings'];
448 }
449
450 // A. Permastructures
451 if ( ! empty( $permastructures['post_types'] ) || ! empty( $permastructures['taxonomies'] ) ) {
452 // Override the global with settings
453 $permalink_manager_permastructs = $permastructures;
454
455 // Save the settings in database
456 update_option( 'permalink-manager-permastructs', $permastructures );
457 }
458
459 // B. Permastructure settings
460 if ( ! empty( $permastructure_options ) ) {
461 self::save_settings( 'permastructure-settings', $permastructure_options );
462 }
463 }
464
465 /**
466 * Update all permalinks in "Bulk URI Editor"
467 */
468 function update_all_permalinks() {
469 // Check if posts or terms should be updated
470 if ( ! empty( $_POST['content_type'] ) && $_POST['content_type'] == 'taxonomies' ) {
471 return Permalink_Manager_URI_Functions_Tax::update_all_permalinks();
472 } else {
473 return Permalink_Manager_URI_Functions_Post::update_all_permalinks();
474 }
475 }
476
477 /**
478 * Remove a specific section of the plugin data stored in the database
479 *
480 * @param $field_name
481 */
482 public static function remove_plugin_data( $field_name ) {
483 global $permalink_manager, $permalink_manager_before_sections_html;
484
485 // Make sure that the user is allowed to remove the plugin data
486 if ( ! current_user_can( 'manage_options' ) ) {
487 $permalink_manager_before_sections_html .= Permalink_Manager_UI_Elements::get_alert_message( __( 'You are not allowed to remove Permalink Manager data!', 'permalink-manager' ), 'error updated_slugs' );
488 }
489
490 switch ( $field_name ) {
491 case 'uris' :
492 $option_name = 'permalink-manager-uris';
493 $alert = __( 'Custom permalinks', 'permalink-manager' );
494 break;
495 case 'redirects' :
496 $option_name = 'permalink-manager-redirects';
497 $alert = __( 'Custom redirects', 'permalink-manager' );
498 break;
499 case 'external-redirects' :
500 $option_name = 'permalink-manager-external-redirects';
501 $alert = __( 'External redirects', 'permalink-manager' );
502 break;
503 case 'permastructs' :
504 $option_name = 'permalink-manager-permastructs';
505 $alert = __( 'Permastructure settings', 'permalink-manager' );
506 break;
507 case 'settings' :
508 $option_name = 'permalink-manager';
509 $alert = __( 'Permastructure settings', 'permalink-manager' );
510 break;
511 default :
512 $alert = '';
513 }
514
515 if ( ! empty( $option_name ) ) {
516 // Remove the option from DB
517 delete_option( $option_name );
518
519 // Reload globals
520 $permalink_manager->get_options_and_globals();
521
522 // Translators: %s is the name of the data field that was removed
523 $alert_message = sprintf( __( '%s were removed!', 'permalink-manager' ), $alert );
524 $permalink_manager_before_sections_html .= Permalink_Manager_UI_Elements::get_alert_message( $alert_message, 'updated updated_slugs' );
525 }
526 }
527
528 /**
529 * Trigger bulk tools ("Regenerate & reset", "Find & replace") via AJAX
530 */
531 function ajax_bulk_tools() {
532 global $sitepress, $wpdb;
533
534 // Define variables
535 $return = array( 'alert' => Permalink_Manager_UI_Elements::get_alert_message( __( '<strong>No slugs</strong> were updated!', 'permalink-manager' ), 'error updated_slugs' ) );
536
537 // Get the name of the function
538 if ( isset( $_POST['regenerate'] ) && wp_verify_nonce( $_POST['regenerate'], 'permalink-manager' ) ) {
539 $operation = 'regenerate';
540 } else if ( isset( $_POST['find_and_replace'] ) && wp_verify_nonce( $_POST['find_and_replace'], 'permalink-manager' ) && ! empty( $_POST['old_string'] ) && ! empty( $_POST['new_string'] ) ) {
541 $operation = 'find_and_replace';
542 }
543
544 // Get the session ID
545 $uniq_id = ( ! empty( $_POST['pm_session_id'] ) ) ? $_POST['pm_session_id'] : '';
546
547 // Get content type & post statuses
548 if ( ! empty( $_POST['content_type'] ) && $_POST['content_type'] == 'taxonomies' ) {
549 $content_type = 'taxonomies';
550
551 if ( empty( $_POST['taxonomies'] ) ) {
552 $error = true;
553 $return = array( 'alert' => Permalink_Manager_UI_Elements::get_alert_message( __( '<strong>No taxonomy</strong> selected!', 'permalink-manager' ), 'error updated_slugs' ) );
554 }
555 } else {
556 $content_type = 'post_types';
557
558 // Check if any post type was selected
559 if ( empty( $_POST['post_types'] ) ) {
560 $error = true;
561 $return = array( 'alert' => Permalink_Manager_UI_Elements::get_alert_message( __( '<strong>No post type</strong> selected!', 'permalink-manager' ), 'error updated_slugs' ) );
562 }
563
564 // Check post status
565 if ( empty( $_POST['post_statuses'] ) ) {
566 $error = true;
567 $return = array( 'alert' => Permalink_Manager_UI_Elements::get_alert_message( __( '<strong>No post status</strong> selected!', 'permalink-manager' ), 'error updated_slugs' ) );
568 }
569 }
570
571 if ( ! empty( $operation ) && empty( $error ) ) {
572 // Hotfix for WPML (start)
573 if ( $sitepress ) {
574 remove_filter( 'get_terms_args', array( $sitepress, 'get_terms_args_filter' ), 10 );
575 remove_filter( 'get_term', array( $sitepress, 'get_term_adjust_id' ), 1 );
576 remove_filter( 'terms_clauses', array( $sitepress, 'terms_clauses' ), 10 );
577 remove_filter( 'get_pages', array( $sitepress, 'get_pages_adjust_ids' ), 1 );
578 }
579
580 // Get the mode
581 $mode = ( isset( $_POST['mode'] ) ) ? $_POST['mode'] : 'custom_uris';
582 $preview_mode = ( ! empty( $_POST['preview_mode'] ) ) ? true : false;
583
584 // Get items (try to get them from transient)
585 $items = get_transient( "pm_{$uniq_id}" );
586
587 // Get the iteration count and chunk size
588 $iteration = isset( $_POST['iteration'] ) ? intval( $_POST['iteration'] ) : 1;
589 $chunk_size = apply_filters( 'permalink_manager_chunk_size', 50 );
590
591 if ( empty( $items ) && ! empty ( $chunk_size ) ) {
592 if ( $content_type == 'taxonomies' ) {
593 $items = Permalink_Manager_URI_Functions_Tax::get_items();
594 } else {
595 $items = Permalink_Manager_URI_Functions_Post::get_items();
596 }
597
598 if ( ! empty( $items ) ) {
599 // Count how many items need to be processed
600 $total = count( $items );
601
602 // Split items array into chunks and save them to transient
603 $items = array_chunk( $items, $chunk_size );
604
605 set_transient( "pm_{$uniq_id}", $items, 600 );
606
607 // Check for MySQL errors
608 if ( ! empty( $wpdb->last_error ) ) {
609 printf( '%s (%sMB)', esc_html( $wpdb->last_error ), esc_html( number_format( strlen( serialize( $items ) ) / 1000000, 2 ) ) );
610 http_response_code( 500 );
611 die();
612 }
613 }
614 }
615
616 // Get homepage URL and ensure that it ends with slash
617 $home_url = Permalink_Manager_Helper_Functions::get_permalink_base() . "/";
618
619 // Process the variables from $_POST object
620 $old_string = ( ! empty( $_POST['old_string'] ) ) ? str_replace( $home_url, '', esc_sql( $_POST['old_string'] ) ) : '';
621 $new_string = ( ! empty( $_POST['new_string'] ) ) ? str_replace( $home_url, '', esc_sql( $_POST['new_string'] ) ) : '';
622
623 // Process only one subarray
624 if ( ! empty( $items[ $iteration - 1 ] ) ) {
625 $chunk = $items[ $iteration - 1 ];
626
627 // Check how many iterations are needed
628 $total_iterations = count( $items );
629
630 if ( $content_type == 'taxonomies' ) {
631 $output = Permalink_Manager_URI_Functions_Tax::bulk_process_items( $chunk, $mode, $operation, $old_string, $new_string, $preview_mode );
632 } else {
633 $output = Permalink_Manager_URI_Functions_Post::bulk_process_items( $chunk, $mode, $operation, $old_string, $new_string, $preview_mode );
634 }
635
636 if ( ! empty( $output['updated_count'] ) ) {
637 $return = array_merge( $return, (array) Permalink_Manager_UI_Elements::display_updated_slugs( $output['updated'], true, true, $preview_mode ) );
638 $return['updated_count'] = $output['updated_count'];
639 }
640
641 // Send total number of processed items with a first chunk
642 if ( ! empty( $total ) && ! empty( $total_iterations ) && $iteration == 1 ) {
643 $return['total'] = $total;
644 $return['items'] = $items;
645 }
646
647 $return['iteration'] = $iteration;
648 $return['total_iterations'] = $total_iterations;
649 $return['progress'] = $chunk_size * $iteration;
650 $return['chunk'] = $chunk;
651
652 // After all chunks are processed remove the transient
653 if ( $iteration == $total_iterations ) {
654 delete_transient( "pm_{$uniq_id}" );
655 }
656 }
657
658 // Hotfix for WPML (end)
659 if ( $sitepress ) {
660 add_filter( 'terms_clauses', array( $sitepress, 'terms_clauses' ), 10, 4 );
661 add_filter( 'get_term', array( $sitepress, 'get_term_adjust_id' ), 1, 1 );
662 add_filter( 'get_terms_args', array( $sitepress, 'get_terms_args_filter' ), 10, 2 );
663 add_filter( 'get_pages', array( $sitepress, 'get_pages_adjust_ids' ), 1, 2 );
664 }
665 }
666
667 wp_send_json( $return );
668 die();
669 }
670
671 /**
672 * Save permalink via AJAX
673 */
674 public function ajax_save_permalink() {
675 $element_id = ( ! empty( $_POST['permalink-manager-edit-uri-element-id'] ) ) ? sanitize_text_field( $_POST['permalink-manager-edit-uri-element-id'] ) : '';
676
677 if ( ! empty( $element_id ) && is_numeric( $element_id ) && current_user_can( 'edit_post', $element_id ) ) {
678 Permalink_Manager_URI_Functions_Post::update_post_hook( $element_id );
679
680 // Reload URI Editor & clean post cache
681 clean_post_cache( $element_id );
682 die();
683 }
684 }
685
686 /**
687 * Check if URI was used before
688 */
689 function ajax_detect_duplicates() {
690 $duplicate_alert = __( "Permalink is already in use, please select another one!", "permalink-manager" );
691 $duplicates_data = array();
692
693 if ( ! empty( $_REQUEST['custom_uris'] ) ) {
694 $custom_uris = Permalink_Manager_Helper_Functions::sanitize_array( $_REQUEST['custom_uris'] );
695
696 // Check each URI
697 foreach ( $custom_uris as $raw_element_id => $element_uri ) {
698 $element_id = sanitize_key( $raw_element_id );
699 $duplicates_data[ $element_id ] = Permalink_Manager_URI_Functions::is_uri_duplicated( $element_uri, $element_id ) ? $duplicate_alert : 0;
700 }
701 } else if ( ! empty( $_REQUEST['custom_uri'] ) && ! empty( $_REQUEST['element_id'] ) ) {
702 $duplicates_data = Permalink_Manager_URI_Functions::is_uri_duplicated( $_REQUEST['custom_uri'], sanitize_key( $_REQUEST['element_id'] ) );
703 }
704
705 wp_send_json( $duplicates_data );
706 }
707
708 /**
709 * Hide global notices (AJAX)
710 */
711 function ajax_hide_global_notice() {
712 global $permalink_manager_alerts;
713
714 // Get the ID of the alert
715 $alert_id = ( ! empty( $_REQUEST['alert_id'] ) ) ? sanitize_title( $_REQUEST['alert_id'] ) : "";
716 if ( ! empty( $permalink_manager_alerts[ $alert_id ] ) ) {
717 $dismissed_transient_name = sprintf( 'permalink-manager-notice_%s', $alert_id );
718 $dismissed_time = ( ! empty( $permalink_manager_alerts[ $alert_id ]['dismissed_time'] ) ) ? (int) $permalink_manager_alerts[ $alert_id ]['dismissed_time'] : DAY_IN_SECONDS;
719
720 set_transient( $dismissed_transient_name, 1, $dismissed_time );
721 }
722 }
723
724 /**
725 * Import old URIs from "Custom Permalinks" (Pro)
726 */
727 function import_custom_permalinks_uris() {
728 Permalink_Manager_Third_Parties::import_custom_permalinks_uris();
729 }
730
731 }
732