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