PluginProbe ʕ •ᴥ•ʔ
Permalink Manager Lite / 2.2.12
Permalink Manager Lite v2.2.12
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-uri-functions-post.php
permalink-manager / includes / core Last commit date
permalink-manager-actions.php 4 years ago permalink-manager-admin-functions.php 4 years ago permalink-manager-core-functions.php 4 years ago permalink-manager-debug.php 4 years ago permalink-manager-gutenberg.php 4 years ago permalink-manager-helper-functions.php 4 years ago permalink-manager-language-plugins.php 4 years ago permalink-manager-third-parties.php 4 years ago permalink-manager-uri-functions-post.php 4 years ago permalink-manager-uri-functions.php 4 years ago
permalink-manager-uri-functions-post.php
880 lines
1 <?php
2
3 /**
4 * Additional functions used in classes and another subclasses
5 */
6 class Permalink_Manager_URI_Functions_Post extends Permalink_Manager_Class {
7
8 public function __construct() {
9 add_action( 'admin_init', array($this, 'admin_init'), 99, 3);
10
11 add_filter( '_get_page_link', array($this, 'custom_post_permalinks'), 99, 2);
12 add_filter( 'page_link', array($this, 'custom_post_permalinks'), 99, 2);
13 add_filter( 'post_link', array($this, 'custom_post_permalinks'), 99, 2);
14 add_filter( 'post_type_link', array($this, 'custom_post_permalinks'), 99, 2);
15 add_filter( 'attachment_link', array($this, 'custom_post_permalinks'), 99, 2);
16
17 add_filter( 'permalink_manager_uris', array($this, 'exclude_homepage'), 99);
18
19 // Support url_to_postid
20 add_filter( 'url_to_postid', array($this, 'url_to_postid'), 999);
21
22 /**
23 * URI Editor
24 */
25 add_filter( 'get_sample_permalink_html', array($this, 'edit_uri_box'), 10, 5 );
26
27 add_action( 'save_post', array($this, 'update_post_uri'), 99, 1);
28 add_action( 'edit_attachment', array($this, 'update_post_uri'), 99, 1 );
29 add_action( 'wp_insert_post', array($this, 'new_post_uri'), 99, 1 );
30 add_action( 'add_attachment', array($this, 'new_post_uri'), 99, 1 );
31 add_action( 'wp_trash_post', array($this, 'remove_post_uri'), 100, 1 );
32 add_action( 'delete_post', array($this, 'remove_post_uri'), 100, 1 );
33
34 add_action( 'quick_edit_custom_box', array($this, 'quick_edit_column_form'), 99, 3);
35 }
36
37 /**
38 * Init
39 */
40 function admin_init() {
41 $post_types = Permalink_Manager_Helper_Functions::get_post_types_array();
42
43 // Add "URI Editor" to "Quick Edit" for all post_types
44 foreach($post_types as $post_type => $label) {
45 add_filter( "manage_{$post_type}_posts_columns" , array($this, 'quick_edit_column') );
46 add_filter( "manage_{$post_type}_posts_custom_column" , array($this, 'quick_edit_column_content'), 10, 2 );
47 }
48 }
49
50 /**
51 * Change permalinks for posts, pages & custom post types
52 */
53 static function custom_post_permalinks($permalink, $post) {
54 global $wp_rewrite, $permalink_manager_uris, $permalink_manager_options, $permalink_manager_ignore_permalink_filters;
55
56 // Do not filter permalinks in Customizer
57 if((function_exists('is_customize_preview') && is_customize_preview()) || !empty($_REQUEST['customize_url'])) { return $permalink; }
58
59 // Do not filter in WPML String Editor
60 if(!empty($_REQUEST['icl_ajx_action']) && $_REQUEST['icl_ajx_action'] == 'icl_st_save_translation') { return $permalink; }
61
62 // WPML (prevent duplicated posts)
63 if(!empty($_REQUEST['trid']) && !empty($_REQUEST['skip_sitepress_actions'])) { return $permalink; }
64
65 // Do not run when metaboxes are loaded with Gutenberg
66 if(!empty($_REQUEST['meta-box-loader']) && empty($_POST['custom_uri'])) { return $permalink; }
67
68 // Do not filter if $permalink_manager_ignore_permalink_filters global is set
69 if(!empty($permalink_manager_ignore_permalink_filters)) { return $permalink; }
70
71 $post = (is_integer($post)) ? get_post($post) : $post;
72
73 // Do not run if post object is invalid
74 if(empty($post) || empty($post->ID) || empty($post->post_type)) { return $permalink; }
75
76 // Start with homepage URL
77 $home_url = Permalink_Manager_Helper_Functions::get_permalink_base($post);
78
79 // Check if the post is excluded
80 if(!empty($post->post_type) && Permalink_Manager_Helper_Functions::is_post_excluded($post) && $post->post_type !== 'attachment') { return $permalink; }
81
82 // 2A. Do not change permalink of frontpage
83 if(Permalink_Manager_Helper_Functions::is_front_page($post->ID)) {
84 return $permalink;
85 }
86 // 2B. Do not change permalink for drafts and future posts (+ remove trailing slash from them)
87 else if(in_array($post->post_status, array('draft', 'pending', 'auto-draft', 'future'))) {
88 return $permalink;
89 }
90
91 // 3. Save the old permalink to separate variable
92 $old_permalink = $permalink;
93
94 // 4. Filter only the posts with custom permalink assigned
95 if(isset($permalink_manager_uris[$post->ID])) {
96 // Encode URI?
97 if(!empty($permalink_manager_options['general']['decode_uris'])) {
98 $permalink = "{$home_url}/" . rawurldecode("/{$permalink_manager_uris[$post->ID]}");
99 } else {
100 $permalink = "{$home_url}/" . Permalink_Manager_Helper_Functions::encode_uri("{$permalink_manager_uris[$post->ID]}");
101 }
102 } else if($post->post_type == 'attachment' && $post->post_parent > 0 && $post->post_parent != $post->ID && !empty($permalink_manager_uris[$post->post_parent])) {
103 $permalink = "{$home_url}/{$permalink_manager_uris[$post->post_parent]}/attachment/{$post->post_name}";
104 } else if(!empty($permalink_manager_options['general']['decode_uris'])) {
105 $permalink = "{$home_url}/" . rawurldecode("/{$permalink}");
106 }
107
108 // 5. Allow to filter (do not filter in Customizer)
109 if(!(function_exists('is_customize_preview') && is_customize_preview())) {
110 return apply_filters('permalink_manager_filter_final_post_permalink', $permalink, $post, $old_permalink);
111 } else {
112 return $old_permalink;
113 }
114 }
115
116 /**
117 * Check if the provided slug is unique and then update it with SQL query.
118 */
119 static function update_slug_by_id($slug, $id) {
120 global $wpdb;
121
122 // Update slug and make it unique
123 $slug = (empty($slug)) ? get_the_title($id) : $slug;
124 $slug = sanitize_title($slug);
125
126 $new_slug = wp_unique_post_slug($slug, $id, get_post_status($id), get_post_type($id), null);
127 $wpdb->query($wpdb->prepare("UPDATE {$wpdb->posts} SET post_name = %s WHERE ID = %d", $new_slug, $id));
128
129 return $new_slug;
130 }
131
132 /**
133 * Get the active URI
134 */
135 public static function get_post_uri($post_id, $native_uri = false, $is_draft = false) {
136 global $permalink_manager_uris;
137
138 // Check if input is post object
139 $post_id = (isset($post_id->ID)) ? $post_id->ID : $post_id;
140
141 if(!empty($permalink_manager_uris[$post_id])) {
142 $final_uri = $permalink_manager_uris[$post_id];
143 } else if(!$is_draft) {
144 $final_uri = self::get_default_post_uri($post_id, $native_uri);
145 } else {
146 $final_uri = '';
147 }
148
149 return $final_uri;
150 }
151
152 /**
153 * Get the default (not overwritten by the user) or native URI (unfiltered)
154 */
155 public static function get_default_post_uri($post, $native_uri = false, $check_if_disabled = false) {
156 global $permalink_manager_options, $permalink_manager_uris, $permalink_manager_permastructs, $wp_post_types, $icl_adjust_id_url_filter_off;
157
158 // Disable WPML adjust ID filter
159 $icl_adjust_id_url_filter_off = true;
160
161 // Load all bases & post
162 $post = is_object($post) ? $post : get_post($post);
163
164 // Check if post ID is defined (and front page permalinks should be empty)
165 if(empty($post->ID) || Permalink_Manager_Helper_Functions::is_front_page($post->ID)) { return ''; }
166
167 $post_id = $post->ID;
168 $post_type = $post->post_type;
169 $post_name = (empty($post->post_name)) ? Permalink_Manager_Helper_Functions::sanitize_title($post->post_title) : $post->post_name;
170
171 // 1A. Check if post type is allowed
172 if($check_if_disabled && Permalink_Manager_Helper_Functions::is_post_type_disabled($post_type)) { return ''; }
173
174 // 1A. Get the native permastructure
175 if($post_type == 'attachment') {
176 $parent_page = ($post->post_parent > 0 && $post->post_parent != $post->ID) ? get_post($post->post_parent) : false;
177
178 if(!empty($parent_page->ID)) {
179 $parent_page_uri = (!empty($permalink_manager_uris[$parent_page->ID])) ? $permalink_manager_uris[$parent_page->ID] : get_page_uri($parent_page->ID);
180 } else {
181 $parent_page_uri = "";
182 }
183
184 $native_permastructure = ($parent_page) ? trim($parent_page_uri, "/") . "/attachment" : "";
185 } else {
186 $native_permastructure = Permalink_Manager_Helper_Functions::get_default_permastruct($post_type);
187 }
188
189 // 1B. Get the permastructure
190 if($native_uri || empty($permalink_manager_permastructs['post_types'][$post_type])) {
191 $permastructure = $native_permastructure;
192 } else {
193 $permastructure = apply_filters('permalink_manager_filter_permastructure', $permalink_manager_permastructs['post_types'][$post_type], $post);
194 }
195
196 // 1C. Set the permastructure
197 $default_base = (!empty($permastructure)) ? trim($permastructure, '/') : "";
198
199 // 2A. Get the date
200 $date = explode(" ", date('Y m d H i s', strtotime($post->post_date)));
201 $monthname = sanitize_title(date_i18n('F', strtotime($post->post_date)));
202
203 // 2B. Get the author (if needed)
204 $author = '';
205 if(strpos($default_base, '%author%') !== false) {
206 $authordata = get_userdata($post->post_author);
207 $author = $authordata->user_nicename;
208 }
209
210 // 2C. Get the post type slug
211 if(!empty($wp_post_types[$post_type])) {
212 if(!empty($wp_post_types[$post_type]->rewrite['slug'])) {
213 $post_type_slug = $wp_post_types[$post_type]->rewrite['slug'];
214 } else if(is_string($wp_post_types[$post_type]->rewrite)) {
215 $post_type_slug = $wp_post_types[$post_type]->rewrite;
216 }
217 }
218
219 $post_type_slug = (!empty($post_type_slug)) ? $post_type_slug : $post_type;
220 $post_type_slug = apply_filters('permalink_manager_filter_post_type_slug', $post_type_slug, $post, $post_type);
221 $post_type_slug = preg_replace('/(%([^%]+)%\/?)/', '', $post_type_slug);
222
223 // 3B. Get the full slug
224 $post_name = Permalink_Manager_Helper_Functions::remove_slashes($post_name);
225 $custom_slug = $full_custom_slug = Permalink_Manager_Helper_Functions::force_custom_slugs($post_name, $post);
226 $full_native_slug = $post_name;
227
228 // 3A. Fix for hierarchical CPT (start)
229 // $full_slug = (is_post_type_hierarchical($post_type)) ? get_page_uri($post) : $post_name;
230 if($post->ancestors && is_post_type_hierarchical($post_type)) {
231 foreach($post->ancestors as $parent) {
232 $parent = get_post($parent);
233 if($parent && $parent->post_name) {
234 $full_native_slug = $parent->post_name . '/' . $full_native_slug;
235 $full_custom_slug = Permalink_Manager_Helper_Functions::force_custom_slugs($parent->post_name, $parent) . '/' . $full_custom_slug;
236 }
237 }
238 }
239
240 // 3B. Allow filter the default slug (only custom permalinks)
241 if(!$native_uri) {
242 $full_slug = apply_filters('permalink_manager_filter_default_post_slug', $full_custom_slug, $post, $post_name);
243 } else {
244 $full_slug = $full_native_slug;
245 }
246
247 $post_type_tag = Permalink_Manager_Helper_Functions::get_post_tag($post_type);
248
249 // 3C. Get the standard tags and replace them with their values
250 $tags = array('%year%', '%monthnum%', '%monthname%', '%day%', '%hour%', '%minute%', '%second%', '%post_id%', '%author%', '%post_type%');
251 $tags_replacements = array($date[0], $date[1], $monthname, $date[2], $date[3], $date[4], $date[5], $post->ID, $author, $post_type_slug);
252 $default_uri = str_replace($tags, $tags_replacements, $default_base);
253
254 // 3D. Get the slug tags
255 $slug_tags = array($post_type_tag, "%postname%", "%postname_flat%", "%{$post_type}_flat%", "%native_slug%");
256 $slug_tags_replacement = array($full_slug, $full_slug, $custom_slug, $custom_slug, $full_native_slug);
257
258 // 3E. Check if any post tag is present in custom permastructure
259 $do_not_append_slug = (!empty($permalink_manager_options['permastructure-settings']['do_not_append_slug']['post_types'][$post_type])) ? true : false;
260 $do_not_append_slug = apply_filters("permalink_manager_do_not_append_slug", $do_not_append_slug, $post_type, $post);
261 if($do_not_append_slug == false) {
262 foreach($slug_tags as $tag) {
263 if(strpos($default_uri, $tag) !== false) {
264 $do_not_append_slug = true;
265 break;
266 }
267 }
268 }
269
270 // 3F. Replace the post tags with slugs or rppend the slug if no post tag is defined
271 if(!empty($do_not_append_slug)) {
272 $default_uri = str_replace($slug_tags, $slug_tags_replacement, $default_uri);
273 } else {
274 $default_uri .= "/{$full_slug}";
275 }
276
277 // 4. Replace taxonomies
278 $taxonomies = get_taxonomies();
279
280 if($taxonomies) {
281 foreach($taxonomies as $taxonomy) {
282 // 0. Check if taxonomy tag is present
283 if(strpos($default_uri, "%{$taxonomy}") === false) { continue; }
284
285 // 1. Reset $replacement variable
286 $replacement = $replacement_term = "";
287 $terms = wp_get_object_terms($post->ID, $taxonomy);
288
289 // 2. Sort the terms
290 if(!empty($terms)) {
291 $terms = wp_list_sort(
292 $terms,
293 array(
294 'parent' => 'DESC',
295 'term_id' => 'ASC',
296 )
297 );
298 }
299
300 // 3A. Try to use Yoast SEO Primary Term
301 $replacement_term = $primary_term = Permalink_Manager_Helper_Functions::get_primary_term($post->ID, $taxonomy, false);
302
303 // 3B. Get the first assigned term to this taxonomy
304 if(empty($replacement_term)) {
305 $replacement_term = (!is_wp_error($terms) && !empty($terms) && is_object($terms[0])) ? Permalink_Manager_Helper_Functions::get_lowest_element($terms[0], $terms) : '';
306 $replacement_term = apply_filters('permalink_manager_filter_post_terms', $replacement_term, $post, $terms, $taxonomy, $native_uri);
307 }
308
309 // 4A. Custom URI as term base
310 if(!empty($replacement_term->term_id) && strpos($default_uri, "%{$taxonomy}_custom_uri%") !== false && !empty($permalink_manager_uris["tax-{$replacement_term->term_id}"])) {
311 $mode = 1;
312 }
313 // 4B. Hierarhcical term base
314 else if(!empty($replacement_term->term_id) && strpos($default_uri, "%{$taxonomy}_flat%") === false && strpos($default_uri, "%{$taxonomy}_top%") === false && is_taxonomy_hierarchical($taxonomy)) {
315 $mode = 2;
316 }
317 // 4C. Force flat/non-hierarchical term base - get highest level term (if %taxonomy_top% tag is used)
318 else if(strpos($default_uri, "%{$taxonomy}_top%") !== false) {
319 $mode = 3;
320 }
321 // 4D. Force flat/non-hierarchical term base - get lowest level term (if %taxonomy_flat% tag is used)
322 else {
323 $mode = 4;
324 }
325
326 // Get the replacement slug (custom + native)
327 $replacement = Permalink_Manager_Helper_Functions::get_term_full_slug($replacement_term, $terms, $mode, $native_uri);
328 $native_replacement = Permalink_Manager_Helper_Functions::get_term_full_slug($replacement_term, $terms, $mode, true);
329
330 // Trim slashes
331 $replacement = trim($replacement, '/');
332 $native_replacement = trim($native_replacement, '/');
333
334 // Filter final category slug
335 $replacement = apply_filters('permalink_manager_filter_term_slug', $replacement, $replacement_term, $post, $terms, $taxonomy, $native_uri);
336
337 // 4. Do the replacement
338 $default_uri = (!empty($replacement)) ? str_replace(array("%{$taxonomy}%", "%{$taxonomy}_flat%", "%{$taxonomy}_custom_uri%", "%{$taxonomy}_top%"), $replacement, $default_uri) : $default_uri;
339 $default_uri = (!empty($native_replacement)) ? str_replace("%{$taxonomy}_native_slug%", $native_replacement, $default_uri) : $default_uri;
340 }
341 }
342
343 // Enable WPML adjust ID filter
344 $icl_adjust_id_url_filter_off = false;
345
346 return apply_filters('permalink_manager_filter_default_post_uri', $default_uri, $post->post_name, $post, $post_name, $native_uri);
347 }
348
349 /**
350 * The homepage should not use URI
351 */
352 function exclude_homepage($uris) {
353 // Find the homepage URI
354 $homepage_id = get_option('page_on_front');
355
356 if(is_array($uris) && !empty($uris[$homepage_id])) {
357 unset($uris[$homepage_id]);
358 }
359
360 return $uris;
361 }
362
363 /**
364 * Support url_to_postid
365 */
366 public function url_to_postid($url) {
367 global $pm_query;
368
369 // Filter only defined URLs
370 if(empty($url)) { return $url; }
371
372 // Make sure that $pm_query global is not changed
373 $old_pm_query = $pm_query;
374 $post = Permalink_Manager_Core_Functions::detect_post(null, $url, true);
375 $pm_query = $old_pm_query;
376
377 if(!empty($post->ID)) {
378 $native_url = "/?p={$post->ID}";
379 }
380
381 return (!empty($native_url)) ? $native_url : $url;
382 }
383
384 /**
385 * Bulk tools
386 */
387 public static function get_items() {
388 global $wpdb;
389
390 // Check if post types & statuses are not empty
391 if(empty($_POST['post_types']) || empty($_POST['post_statuses'])) { return false; }
392
393 $post_types_array = ($_POST['post_types']);
394 $post_statuses_array = ($_POST['post_statuses']);
395 $post_types = implode("', '", $post_types_array);
396 $post_statuses = implode("', '", $post_statuses_array);
397
398 // Filter the posts by IDs
399 $where = '';
400 if(!empty($_POST['ids'])) {
401 // Remove whitespaces and prepare array with IDs and/or ranges
402 $ids = esc_sql(preg_replace('/\s*/m', '', $_POST['ids']));
403 preg_match_all("/([\d]+(?:-?[\d]+)?)/x", $ids, $groups);
404
405 // Prepare the extra ID filters
406 $where .= "AND (";
407 foreach($groups[0] as $group) {
408 $where .= ($group == reset($groups[0])) ? "" : " OR ";
409 // A. Single number
410 if(is_numeric($group)) {
411 $where .= "(ID = {$group})";
412 }
413 // B. Range
414 else if(substr_count($group, '-')) {
415 $range_edges = explode("-", $group);
416 $where .= "(ID BETWEEN {$range_edges[0]} AND {$range_edges[1]})";
417 }
418 }
419 $where .= ")";
420 }
421
422 // Get excluded items
423 $excluded_posts_ui = $wpdb->get_col("SELECT post_ID FROM {$wpdb->postmeta} AS pm LEFT JOIN {$wpdb->posts} AS p ON (pm.post_ID = p.ID) WHERE pm.meta_key = 'auto_update_uri' AND pm.meta_value = '-2' AND post_type IN ('{$post_types}')");
424 $excluded_posts_hook = (array) apply_filters('permalink_manager_excluded_post_ids', array());
425 $excluded_posts = array_merge($excluded_posts_ui, $excluded_posts_hook);
426
427 if(!empty($excluded_posts)) {
428 $where .= sprintf(" AND ID NOT IN ('%s') ", implode("', '", $excluded_posts));
429 }
430
431 // Support for attachments
432 $attachment_support = (in_array('attachment', $post_types_array)) ? " OR (post_type = 'attachment')" : "";
433
434 // Get the rows before they are altered
435 return $wpdb->get_results("SELECT post_type, post_title, post_name, ID FROM {$wpdb->posts} WHERE ((post_status IN ('{$post_statuses}') AND post_type IN ('{$post_types}')){$attachment_support}) {$where}", ARRAY_A);
436 }
437
438 /**
439 * Find & replace (bulk action)
440 */
441 public static function find_and_replace($chunk = null, $mode = '', $old_string = '', $new_string = '') {
442 global $wpdb, $permalink_manager_uris;
443
444 // Reset variables
445 $updated_slugs_count = 0;
446 $updated_array = array();
447 $alert_type = $alert_content = $errors = '';
448
449 // Get the rows before they are altered
450 $posts_to_update = ($chunk) ? $chunk : self::get_items();
451
452 // Now if the array is not empty use IDs from each subarray as a key
453 if($posts_to_update && empty($errors)) {
454 foreach ($posts_to_update as $row) {
455 // Get default & native URL
456 $native_uri = self::get_default_post_uri($row['ID'], true);
457 $default_uri = self::get_default_post_uri($row['ID']);
458
459 $old_post_name = $old_slug = $row['post_name'];
460 $old_uri = (isset($permalink_manager_uris[$row['ID']])) ? $permalink_manager_uris[$row['ID']] : $native_uri;
461
462 // Do replacement on slugs (non-REGEX)
463 if(preg_match("/^\/.+\/[a-z]*$/i", $old_string)) {
464 $regex = stripslashes(trim(sanitize_text_field($_POST['old_string']), "/"));
465 $regex = preg_quote($regex, '~');
466 $pattern = "~{$regex}~";
467
468 $new_post_name = ($mode == 'slugs') ? preg_replace($pattern, $new_string, $old_post_name) : $old_post_name;
469 $new_uri = ($mode != 'slugs') ? preg_replace($pattern, $new_string, $old_uri) : $old_uri;
470 } else {
471 $new_post_name = ($mode == 'slugs') ? str_replace($old_string, $new_string, $old_post_name) : $old_post_name; // Post name is changed only in first mode
472 $new_uri = ($mode != 'slugs') ? str_replace($old_string, $new_string, $old_uri) : $old_uri;
473 }
474
475 // echo "{$old_uri} - {$new_uri} - {$native_uri} - {$default_uri} \n";
476
477 // Check if native slug should be changed
478 if(($mode == 'slugs') && ($old_post_name != $new_post_name)) {
479 $new_slug = self::update_slug_by_id($new_post_name, $row['ID']);
480 }
481
482 if(($old_uri != $new_uri) || ($old_post_name != $new_post_name) && !(empty($new_uri))) {
483 $permalink_manager_uris[$row['ID']] = trim($new_uri, '/');
484 $updated_array[] = array('item_title' => $row['post_title'], 'ID' => $row['ID'], 'old_uri' => $old_uri, 'new_uri' => $new_uri, 'old_slug' => $old_slug, 'new_slug' => $new_slug);
485 $updated_slugs_count++;
486 }
487
488 do_action('permalink_manager_updated_post_uri', $row['ID'], $new_uri, $old_uri, $native_uri, $default_uri);
489 }
490
491 // Filter array before saving
492 if(is_array($permalink_manager_uris)) {
493 $permalink_manager_uris = array_filter($permalink_manager_uris);
494 update_option('permalink-manager-uris', $permalink_manager_uris);
495 }
496
497 $output = array('updated' => $updated_array, 'updated_count' => $updated_slugs_count);
498 wp_reset_postdata();
499 }
500
501 return ($output) ? $output : "";
502 }
503
504 /**
505 * Regenerate slugs & bases (bulk action)
506 */
507 static function regenerate_all_permalinks($chunk = null, $mode = '') {
508 global $wpdb, $permalink_manager_uris;
509
510 // Reset variables
511 $updated_slugs_count = 0;
512 $updated_array = array();
513 $alert_type = $alert_content = $errors = '';
514
515 // Get the rows before they are altered
516 $posts_to_update = ($chunk) ? $chunk : self::get_items();
517
518 // Now if the array is not empty use IDs from each subarray as a key
519 if($posts_to_update && empty($errors)) {
520 foreach ($posts_to_update as $row) {
521 // Get default & native URL
522 $native_uri = self::get_default_post_uri($row['ID'], true);
523 $default_uri = self::get_default_post_uri($row['ID']);
524 $old_post_name = $row['post_name'];
525 $old_uri = isset($permalink_manager_uris[$row['ID']]) ? trim($permalink_manager_uris[$row['ID']], "/") : '';
526 $correct_slug = ($mode == 'slugs') ? sanitize_title($row['post_title']) : Permalink_Manager_Helper_Functions::sanitize_title($row['post_title']);
527
528 // Process URI & slug
529 $new_slug = wp_unique_post_slug($correct_slug, $row['ID'], get_post_status($row['ID']), get_post_type($row['ID']), null);
530 $new_post_name = ($mode == 'slugs') ? $new_slug : $old_post_name; // Post name is changed only in first mode
531
532 // Prepare the new URI
533 if($mode == 'slugs') {
534 $new_uri = ($old_uri) ? $old_uri : $native_uri;
535 } else if($mode == 'native') {
536 $new_uri = $native_uri;
537 } else {
538 $new_uri = $default_uri;
539 }
540
541 //print_r("{$old_uri} - {$new_uri} - {$native_uri} - {$default_uri} / - {$new_slug} - {$new_post_name} \n");
542
543 // Check if native slug should be changed
544 if(($mode == 'slugs') && ($old_post_name != $new_post_name)) {
545 self::update_slug_by_id($new_post_name, $row['ID']);
546 clean_post_cache($row['ID']);
547 }
548
549 if(($old_uri != $new_uri) || ($old_post_name != $new_post_name)) {
550 $permalink_manager_uris[$row['ID']] = $new_uri;
551 $updated_array[] = array('item_title' => $row['post_title'], 'ID' => $row['ID'], 'old_uri' => $old_uri, 'new_uri' => $new_uri, 'old_slug' => $old_post_name, 'new_slug' => $new_post_name);
552 $updated_slugs_count++;
553 }
554
555 do_action('permalink_manager_updated_post_uri', $row['ID'], $new_uri, $old_uri, $native_uri, $default_uri);
556 }
557
558 // Filter array before saving
559 if(is_array($permalink_manager_uris)) {
560 $permalink_manager_uris = array_filter($permalink_manager_uris);
561 update_option('permalink-manager-uris', $permalink_manager_uris);
562 }
563
564 $output = array('updated' => $updated_array, 'updated_count' => $updated_slugs_count);
565 wp_reset_postdata();
566 }
567
568 return (!empty($output)) ? $output : "";
569 }
570
571 /**
572 * Update all slugs & bases (bulk action)
573 */
574 static public function update_all_permalinks() {
575 global $permalink_manager_uris;
576
577 // Setup needed variables
578 $updated_slugs_count = 0;
579 $updated_array = array();
580
581 $old_uris = $permalink_manager_uris;
582 $new_uris = isset($_POST['uri']) ? $_POST['uri'] : array();
583
584 // Double check if the slugs and ids are stored in arrays
585 if (!is_array($new_uris)) $new_uris = explode(',', $new_uris);
586
587 if (!empty($new_uris)) {
588 foreach($new_uris as $id => $new_uri) {
589 // Prepare variables
590 $this_post = get_post($id);
591 $updated = '';
592
593 // Get default & native URL
594 $native_uri = self::get_default_post_uri($id, true);
595 $default_uri = self::get_default_post_uri($id);
596
597 $old_uri = isset($old_uris[$id]) ? trim($old_uris[$id], "/") : "";
598
599 // Process new values - empty entries will be treated as default values
600 $new_uri = preg_replace('/\s+/', '', $new_uri);
601 $new_uri = (!empty($new_uri)) ? trim($new_uri, "/") : $default_uri;
602 $new_slug = (strpos($new_uri, '/') !== false) ? substr($new_uri, strrpos($new_uri, '/') + 1) : $new_uri;
603
604 //print_r("{$old_uri} - {$new_uri} - {$native_uri} - {$default_uri}\n");
605
606 if($new_uri != $old_uri) {
607 $old_uris[$id] = $new_uri;
608 $updated_array[] = array('item_title' => get_the_title($id), 'ID' => $id, 'old_uri' => $old_uri, 'new_uri' => $new_uri);
609 $updated_slugs_count++;
610 }
611
612 do_action('permalink_manager_updated_post_uri', $id, $new_uri, $old_uri, $native_uri, $default_uri);
613 }
614
615 // Filter array before saving & append the global
616 if(is_array($permalink_manager_uris)) {
617 $permalink_manager_uris = array_filter($old_uris);
618 update_option('permalink-manager-uris', $permalink_manager_uris);
619 }
620
621 $output = array('updated' => $updated_array, 'updated_count' => $updated_slugs_count);
622 }
623
624 return ($output) ? $output : "";
625 }
626
627 /**
628 * Allow to edit URIs from "Edit Post" admin pages
629 */
630 function edit_uri_box($html, $id, $new_title, $new_slug, $post) {
631 global $permalink_manager_uris, $permalink_manager_options;
632
633 // Detect auto drafts
634 $autosave = (!empty($new_title) && empty($new_slug)) ? true : false;
635
636 // Check if the post is excluded
637 if(empty($post->post_type) || Permalink_Manager_Helper_Functions::is_post_excluded($post)) { return $html; }
638
639 // Ignore drafts
640 if(!empty($permalink_manager_options["general"]["ignore_drafts"]) && !empty($post->post_status) && $post->post_status == 'draft') { return $html; }
641
642 // Stop the hook (if needed)
643 $show_uri_editor = apply_filters("permalink_manager_show_uri_editor_post_{$post->post_type}", true, $post);
644 if(!$show_uri_editor) { return $html; }
645
646 $new_html = preg_replace("/^(<strong>(.*)<\/strong>)(.*)/is", "$1 ", $html);
647 $default_uri = self::get_default_post_uri($id);
648 $native_uri = self::get_default_post_uri($id, true);
649
650 // Make sure that home URL ends with slash
651 $home_url = Permalink_Manager_Helper_Functions::get_permalink_base($post);
652
653 // A. Display original permalink on front-page editor
654 if(Permalink_Manager_Helper_Functions::is_front_page($id)) {
655 preg_match('/href="([^"]+)"/mi', $html, $matches);
656 $sample_permalink = (!empty($matches[1])) ? $matches[1] : "";
657 }
658 else {
659 // B. Do not change anything if post is not saved yet (display sample permalink instead)
660 if($autosave || empty($post->post_status)) {
661 $sample_permalink_uri = $default_uri;
662 }
663 // C. Display custom URI if set
664 else {
665 $sample_permalink_uri = (!empty($permalink_manager_uris[$id])) ? $permalink_manager_uris[$id] : $native_uri;
666 }
667
668 // Decode URI & allow to filter it
669 $sample_permalink_uri = apply_filters('permalink_manager_filter_post_sample_uri', rawurldecode($sample_permalink_uri), $post);
670
671 // Prepare the sample & default permalink
672 $sample_permalink = sprintf("%s/<span class=\"editable\">%s</span>", $home_url, str_replace("//", "/", $sample_permalink_uri));
673
674 // Allow to filter the sample permalink URL
675 // $sample_permalink = apply_filters('permalink_manager_filter_post_sample_permalink', $sample_permalink, $post);
676 }
677
678 // Append new HTML output
679 $new_html .= sprintf("<span class=\"sample-permalink-span\"><a id=\"sample-permalink\" href=\"%s\">%s</a></span>&nbsp;", strip_tags($sample_permalink), $sample_permalink);
680 $new_html .= (!$autosave) ? Permalink_Manager_Admin_Functions::display_uri_box($post) : "";
681
682 // Append hidden field with native slug
683 $new_html .= (!empty($post->post_name)) ? "<span id=\"editable-post-name-full\">{$post->post_name}</span>" : "";
684
685 return $new_html;
686 }
687
688 /**
689 * "Quick Edit" form
690 */
691 function quick_edit_column($columns) {
692 global $current_screen;
693
694 // Get post type
695 $post_type = (!empty($current_screen->post_type)) ? $current_screen->post_type : false;
696
697 // Check if post type is disabled
698 if($post_type && Permalink_Manager_Helper_Functions::is_post_type_disabled($post_type)) { return $columns; }
699
700 return (is_array($columns)) ? array_merge($columns, array('permalink-manager-col' => __( 'Current URI', 'permalink-manager'))) : $columns;
701 }
702
703 function quick_edit_column_content($column_name, $post_id) {
704 global $permalink_manager_uris, $permalink_manager_options;
705
706 if($column_name == "permalink-manager-col") {
707 // Get auto-update settings
708 $auto_update_val = get_post_meta($post_id, "auto_update_uri", true);
709 $auto_update_uri = (!empty($auto_update_val)) ? $auto_update_val : $permalink_manager_options["general"]["auto_update_uris"];
710
711 $uri = (!empty($permalink_manager_uris[$post_id])) ? rawurldecode($permalink_manager_uris[$post_id]) : self::get_post_uri($post_id, true);
712 printf('<span class="permalink-manager-col-uri" data-auto_update="%s">%s</span>', intval($auto_update_uri), $uri);
713 }
714 }
715
716 function quick_edit_column_form($column_name, $post_type, $taxonomy = '') {
717 if(!$taxonomy && $column_name == 'permalink-manager-col') {
718 echo Permalink_Manager_Admin_Functions::quick_edit_column_form();
719 }
720 }
721
722 /**
723 * Update URI when new post is added
724 */
725 function new_post_uri($post_id) {
726 global $post, $permalink_manager_uris, $permalink_manager_options, $permalink_manager_before_sections_html;
727
728 // Do not trigger if post is a revision or imported via WP All Import (URI should be set after the post meta is added)
729 if(wp_is_post_revision($post_id) || (!empty($_REQUEST['page']) && $_REQUEST['page'] == 'pmxi-admin-import')) { return $post_id; }
730
731 // Prevent language mismatch in MultilingualPress plugin
732 if(is_admin() && !empty($post->ID) && $post->ID != $post_id) { return $post_id; }
733
734 // Stop when products are imported with WooCommerce importer
735 if(!empty($_REQUEST['action']) && $_REQUEST['action'] == 'woocommerce_do_ajax_product_import') { return $post_id; }
736
737 // Do not do anything if post is autosaved
738 if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return $post_id; }
739
740 // Do not do anything on in "Bulk Edit"
741 if(!empty($_REQUEST['bulk_edit'])) { return $post_id; }
742
743 // Hotfix
744 if(isset($_POST['custom_uri']) || isset($_POST['permalink-manager-quick-edit']) || isset($permalink_manager_uris[$post_id])) { return $post_id; }
745
746 $post_object = get_post($post_id);
747
748 // Check if post is allowed
749 if(empty($post_object->post_type) || Permalink_Manager_Helper_Functions::is_post_excluded($post_object)) { return $post_id; }
750
751 // Exclude drafts
752 if(!empty($permalink_manager_options["general"]["ignore_drafts"]) && !empty($post_object->post_status) && $post_object->post_status == 'draft') { return $post_id; }
753
754 // Stop the hook (if needed)
755 $allow_new_uri = apply_filters("permalink_manager_allow_new_post_uri", true, $post_object);
756 if(!$allow_new_uri) { return $post_id; }
757
758 // Ignore menu items
759 if($post_object->post_type == 'nav_menu_item') { return $post_id; }
760
761 // Ignore auto-drafts, revisions, removed posts and posts without title
762 if(in_array($post_object->post_status, array('auto-draft', 'trash')) || (strpos($post_object->post_name, 'revision-v1') !== false) || empty($post_object->post_title) || (!empty($post_object->post_name) && $post_object->post_name == 'auto-draft')) { return $post_id; }
763
764 $native_uri = self::get_default_post_uri($post_id, true);
765 $new_uri = self::get_default_post_uri($post_id);
766 $permalink_manager_uris[$post_object->ID] = $new_uri;
767
768 if(is_array($permalink_manager_uris)) {
769 update_option('permalink-manager-uris', $permalink_manager_uris);
770 }
771
772 do_action('permalink_manager_new_post_uri', $post_id, $new_uri, $native_uri);
773 }
774
775 /**
776 * Update URI from "Edit Post" admin page
777 */
778 static public function update_post_uri($post_id) {
779 global $permalink_manager_uris, $permalink_manager_options, $permalink_manager_before_sections_html;
780
781 // Verify nonce at first
782 if(!isset($_POST['permalink-manager-nonce']) || !wp_verify_nonce($_POST['permalink-manager-nonce'], 'permalink-manager-edit-uri-box')) { return $post_id; }
783
784 // Do not do anything if the field with URI or element ID are not present
785 if(!isset($_POST['custom_uri']) || empty($_POST['permalink-manager-edit-uri-element-id'])) { return $post_id; }
786
787 // Hotfix
788 if($_POST['permalink-manager-edit-uri-element-id'] != $post_id) { return $post_id; }
789
790 // Do not do anything if post is autosaved
791 if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return $post_id; }
792
793 // Do not do anything on in "Bulk Edit" or when the post is imported via WP All Import
794 if(!empty($_REQUEST['bulk_edit']) || (!empty($_REQUEST['page']) && $_REQUEST['page'] == 'pmxi-admin-import')) { return $post_id; }
795
796 // Fix for revisions
797 $is_revision = wp_is_post_revision($post_id);
798 $post_id = ($is_revision) ? $is_revision : $post_id;
799 $post = get_post($post_id);
800
801 // Check if post is allowed
802 if(empty($post->post_type) || Permalink_Manager_Helper_Functions::is_post_excluded($post)) { return $post_id; }
803
804 // Exclude drafts
805 if(!empty($permalink_manager_options["general"]["ignore_drafts"]) && !empty($post->post_status) && $post->post_status == 'draft') { return $post_id; }
806
807 // Stop the hook (if needed)
808 $allow_update_uri = apply_filters("permalink_manager_allow_update_post_uri", true, $post);
809 if(!$allow_update_uri) { return $post_id; }
810
811 // Ignore auto-drafts, removed posts and posts without title
812 if(in_array($post->post_status, array('auto-draft', 'trash')) || empty($post->post_title)) { return $post_id; }
813
814 // Get auto-update URI setting (if empty use global setting)
815 if(!empty($_POST["auto_update_uri"])) {
816 $auto_update_uri_current = intval($_POST["auto_update_uri"]);
817 } else if(!empty($_POST["action"]) && $_POST['action'] == 'inline-save') {
818 $auto_update_uri_current = get_post_meta($post_id, "auto_update_uri", true);
819 }
820 $auto_update_uri = (!empty($auto_update_uri_current)) ? $auto_update_uri_current : $permalink_manager_options["general"]["auto_update_uris"];
821
822 // Update the slug (if changed)
823 if(isset($_POST['permalink-manager-edit-uri-element-slug']) && isset($_POST['native_slug']) && ($_POST['native_slug'] !== $_POST['permalink-manager-edit-uri-element-slug'])) {
824
825 // Make sure that '_wp_old_slug' is saved
826 if(!empty($_POST['post_name'])) {
827 $post_before = $post;
828
829 // Clone the instance of WP_Post object
830 $post_after = unserialize(serialize($post));
831 $post_after->post_name = sanitize_title($_POST['native_slug']);
832
833 wp_check_for_changed_slugs($post_id, $post_after, $post_before);
834 }
835
836 self::update_slug_by_id($_POST['native_slug'], $post_id);
837 clean_post_cache($post_id);
838 }
839
840 $default_uri = self::get_default_post_uri($post_id);
841 $native_uri = self::get_default_post_uri($post_id, true);
842 $old_uri = (isset($permalink_manager_uris[$post->ID])) ? $permalink_manager_uris[$post->ID] : $native_uri;
843
844 // Use default URI if URI is cleared by user OR URI should be automatically updated
845 $new_uri = (($_POST['custom_uri'] == '') || $auto_update_uri == 1) ? $default_uri : Permalink_Manager_Helper_Functions::sanitize_title($_POST['custom_uri'], true);
846
847 // Save or remove "Auto-update URI" settings
848 if(!empty($auto_update_uri_current)) {
849 update_post_meta($post_id, "auto_update_uri", $auto_update_uri_current);
850 } elseif(isset($_POST['auto_update_uri'])) {
851 delete_post_meta($post_id, "auto_update_uri");
852 }
853
854 // Save only changed URIs
855 if(is_array($permalink_manager_uris)) {
856 $permalink_manager_uris[$post_id] = $new_uri;
857 update_option('permalink-manager-uris', $permalink_manager_uris);
858 }
859
860 do_action('permalink_manager_updated_post_uri', $post_id, $new_uri, $old_uri, $native_uri, $default_uri, $single_update = true);
861 }
862
863 /**
864 * Remove URI from options array after post is moved to the trash
865 */
866 function remove_post_uri($post_id) {
867 global $permalink_manager_uris;
868
869 // Check if the custom permalink is assigned to this post
870 if(isset($permalink_manager_uris[$post_id])) {
871 unset($permalink_manager_uris[$post_id]);
872 }
873
874 if(is_array($permalink_manager_uris)) {
875 update_option('permalink-manager-uris', $permalink_manager_uris);
876 }
877 }
878
879 }
880