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