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