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