Custom Permalinks - Version 1.0

Version Description

  • Updated Query on the custom_permalinks_request Function
Download this release

Release Info

Developer sasiddiqui
Plugin Icon Custom Permalinks
Version 1.0
Comparing to
See all releases

Code changes from version 0.9.3 to 1.0

Files changed (2) hide show
  1. custom-permalinks.php +874 -872
  2. readme.txt +257 -253
custom-permalinks.php CHANGED
@@ -1,872 +1,874 @@
1
- <?php
2
-
3
- /**
4
- * Plugin Name: Custom Permalinks
5
- * Plugin URI: https://wordpress.org/plugins/custom-permalinks/
6
- * Donate link: https://www.paypal.me/yasglobal
7
- * Description: Set custom permalinks on a per-post basis
8
- * Version: 0.9.3
9
- * Author: Sami Ahmed Siddiqui
10
- * Author URI: https://www.yasglobal.com/web-design-development/wordpress/custom-permalinks/
11
- * Text Domain: custom-permalinks
12
- */
13
-
14
- /**
15
- * Copyright 2008-2017 Michael Tyson <michael@atastypixel.com> and Sami Ahmed Siddiqui <sami@samisiddiqui.com>
16
- *
17
- * This program is free software; you can redistribute it and/or modify
18
- * it under the terms of the GNU General Public License as published by
19
- * the Free Software Foundation; either version 2 of the License, or
20
- * (at your option) any later version.
21
- *
22
- * This program is distributed in the hope that it will be useful,
23
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
24
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25
- * GNU General Public License for more details.
26
- *
27
- * You should have received a copy of the GNU General Public License
28
- * along with this program; if not, write to the Free Software
29
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30
- */
31
-
32
- // Make sure we don't expose any info if called directly
33
- if ( ! defined( 'ABSPATH' ) ) {
34
- echo 'Hi there! I\'m just a plugin, not much I can do when called directly.';
35
- exit;
36
- }
37
-
38
- /**
39
- ** Actions and filters
40
- **
41
- **/
42
-
43
- /**
44
- * Filter to replace the post permalink with the custom one
45
- */
46
- function custom_permalinks_post_link($permalink, $post) {
47
- $custom_permalink = get_post_meta( $post->ID, 'custom_permalink', true );
48
- if ( $custom_permalink ) {
49
- $post_type = isset($post->post_type) ? $post->post_type : 'post';
50
- $language_code = apply_filters( 'wpml_element_language_code', null, array( 'element_id' => $post->ID, 'element_type' => $post_type ) );
51
- if ( $language_code )
52
- return apply_filters( 'wpml_permalink', home_url()."/".$custom_permalink, $language_code );
53
- else
54
- return apply_filters( 'wpml_permalink', home_url()."/".$custom_permalink );
55
- }
56
-
57
- return $permalink;
58
- }
59
-
60
- /**
61
- * Filter to replace the page permalink with the custom one
62
- */
63
- function custom_permalinks_page_link($permalink, $page) {
64
- $custom_permalink = get_post_meta( $page, 'custom_permalink', true );
65
- if ( $custom_permalink ) {
66
- $language_code = apply_filters( 'wpml_element_language_code', null, array( 'element_id' => $page, 'element_type' => 'page' ) );
67
- if ( $language_code )
68
- return apply_filters( 'wpml_permalink', home_url()."/".$custom_permalink, $language_code );
69
- else
70
- return apply_filters( 'wpml_permalink', home_url()."/".$custom_permalink );
71
- }
72
-
73
- return $permalink;
74
- }
75
-
76
- /**
77
- * Filter to replace the term permalink with the custom one
78
- */
79
- function custom_permalinks_term_link($permalink, $term) {
80
- $table = get_option('custom_permalink_table');
81
- if ( is_object($term) ) $term = $term->term_id;
82
-
83
- $custom_permalink = custom_permalinks_permalink_for_term($term);
84
- if ( $custom_permalink ) {
85
- $taxonomy = get_term($term);
86
- if ( isset($taxonomy) && isset($taxonomy->term_taxonomy_id) ) {
87
- $term_type = isset($taxonomy->taxonomy) ? $taxonomy->taxonomy : 'category';
88
- $language_code = apply_filters( 'wpml_element_language_code', null, array( 'element_id' => $taxonomy->term_taxonomy_id, 'element_type' => $term_type ) );
89
- return apply_filters( 'wpml_permalink', home_url()."/".$custom_permalink, $language_code );
90
- } else {
91
- return apply_filters( 'wpml_permalink', home_url()."/".$custom_permalink );
92
- }
93
- }
94
-
95
- return $permalink;
96
- }
97
-
98
- /**
99
- * Action to redirect to the custom permalink
100
- *
101
- * @package CustomPermalinks
102
- * @since 0.1
103
- */
104
- function custom_permalinks_redirect() {
105
- // Get request URI, strip parameters
106
- $url = parse_url(get_bloginfo('url'));
107
- $url = isset($url['path']) ? $url['path'] : '';
108
- $request = ltrim(substr($_SERVER['REQUEST_URI'], strlen($url)),'/');
109
- if ( ($pos=strpos($request, "?")) ) $request = substr($request, 0, $pos);
110
-
111
- $request = custom_permalinks_check_conflicts($request);
112
-
113
- global $wp_query;
114
-
115
- $custom_permalink = '';
116
- $original_permalink = '';
117
-
118
- // If the post/tag/category we're on has a custom permalink, get it and check against the request
119
- if ( (is_single() || is_page()) && !empty($wp_query->post) ) {
120
- $post = $wp_query->post;
121
- $custom_permalink = get_post_meta( $post->ID, 'custom_permalink', true );
122
- $original_permalink = ( $post->post_type == 'page' ? custom_permalinks_original_page_link( $post->ID ) : custom_permalinks_original_post_link( $post->ID ) );
123
- } else if ( is_tag() || is_category() ) {
124
- $theTerm = $wp_query->get_queried_object();
125
- $custom_permalink = custom_permalinks_permalink_for_term($theTerm->term_id);
126
- $original_permalink = (is_tag() ? custom_permalinks_original_tag_link($theTerm->term_id) :
127
- custom_permalinks_original_category_link($theTerm->term_id));
128
- }
129
-
130
- if ( $custom_permalink &&
131
- (substr($request, 0, strlen($custom_permalink)) != $custom_permalink ||
132
- $request == $custom_permalink."/" ) ) {
133
- // Request doesn't match permalink - redirect
134
- $url = $custom_permalink;
135
-
136
- if ( substr($request, 0, strlen($original_permalink)) == $original_permalink &&
137
- trim($request,'/') != trim($original_permalink,'/') ) {
138
- // This is the original link; we can use this url to derive the new one
139
- $url = preg_replace('@//*@', '/', str_replace(trim($original_permalink,'/'), trim($custom_permalink,'/'), $request));
140
- $url = preg_replace('@([^?]*)&@', '\1?', $url);
141
- }
142
-
143
- // Append any query compenent
144
- $url .= strstr($_SERVER['REQUEST_URI'], "?");
145
-
146
- wp_redirect( home_url()."/".$url, 301 );
147
- exit();
148
- }
149
- }
150
-
151
- /**
152
- * Filter to rewrite the query if we have a matching post
153
- *
154
- * @package CustomPermalinks
155
- * @since 0.1
156
- */
157
- function custom_permalinks_request($query) {
158
- global $wpdb;
159
- global $_CPRegisteredURL;
160
-
161
- // First, search for a matching custom permalink, and if found, generate the corresponding
162
- // original URL
163
-
164
- $originalUrl = NULL;
165
-
166
- // Get request URI, strip parameters and /'s
167
- $url = parse_url(get_bloginfo('url'));
168
- $url = isset($url['path']) ? $url['path'] : '';
169
- $request = ltrim(substr($_SERVER['REQUEST_URI'], strlen($url)),'/');
170
- $request = (($pos=strpos($request, '?')) ? substr($request, 0, $pos) : $request);
171
-
172
- if ( !$request ) return $query;
173
-
174
- $request = custom_permalinks_check_conflicts($request);
175
- $request_noslash = preg_replace('@/+@','/', trim($request, '/'));
176
-
177
- // Queries are now WP3.9 compatible (by Steve from Sowmedia.nl)
178
- $sql = $wpdb->prepare("SELECT $wpdb->posts.ID, $wpdb->postmeta.meta_value, $wpdb->posts.post_type, $wpdb->posts.post_status FROM $wpdb->posts ".
179
- "LEFT JOIN $wpdb->postmeta ON ($wpdb->posts.ID = $wpdb->postmeta.post_id) WHERE ".
180
- " meta_key = 'custom_permalink' AND ".
181
- " meta_value != '' AND ".
182
- " ( LOWER(meta_value) = LEFT(LOWER('%s'), LENGTH(meta_value)) OR ".
183
- " LOWER(meta_value) = LEFT(LOWER('%s'), LENGTH(meta_value)) ) ".
184
- " AND post_status != 'trash' AND post_type != 'nav_menu_item'".
185
- " ORDER BY LENGTH(meta_value) DESC, ".
186
- " FIELD(post_status,'publish','private','draft','auto-draft','inherit'),".
187
- " FIELD(post_type,'post','page'),".
188
- "$wpdb->posts.ID ASC LIMIT 1",
189
- $request_noslash,
190
- $request_noslash."/");
191
-
192
- $posts = $wpdb->get_results($sql);
193
-
194
- if ( $posts ) {
195
- // A post matches our request
196
-
197
- // Preserve this url for later if it's the same as the permalink (no extra stuff)
198
- if ( $request_noslash == trim($posts[0]->meta_value,'/') )
199
- $_CPRegisteredURL = $request;
200
-
201
- if ( $posts[0]->post_status == 'draft' ) {
202
- if( $posts[0]->post_type == 'page' ) {
203
- $originalUrl = "?page_id=" . $posts[0]->ID;
204
- } else {
205
- $originalUrl = "?post_type=".$posts[0]->post_type."&p=" . $posts[0]->ID;
206
- }
207
- } else {
208
- $originalUrl = preg_replace( '@/+@', '/', str_replace( trim( strtolower($posts[0]->meta_value),'/' ),
209
- ( $posts[0]->post_type == 'page' ?
210
- custom_permalinks_original_page_link($posts[0]->ID)
211
- : custom_permalinks_original_post_link($posts[0]->ID) ),
212
- strtolower($request_noslash) ) );
213
- }
214
- }
215
-
216
- if ( $originalUrl === NULL ) {
217
- // See if any terms have a matching permalink
218
- $table = get_option('custom_permalink_table');
219
- if ( !$table ) return $query;
220
-
221
- foreach ( array_keys($table) as $permalink ) {
222
- if ( $permalink == substr($request_noslash, 0, strlen($permalink)) ||
223
- $permalink == substr($request_noslash."/", 0, strlen($permalink)) ) {
224
- $term = $table[$permalink];
225
-
226
- // Preserve this url for later if it's the same as the permalink (no extra stuff)
227
- if ( $request_noslash == trim($permalink,'/') )
228
- $_CPRegisteredURL = $request;
229
-
230
-
231
- if ( $term['kind'] == 'category') {
232
- $originalUrl = str_replace(trim($permalink,'/'),
233
- custom_permalinks_original_category_link($term['id']),
234
- trim($request,'/'));
235
- } else {
236
- $originalUrl = str_replace(trim($permalink,'/'),
237
- custom_permalinks_original_tag_link($term['id']),
238
- trim($request,'/'));
239
- }
240
- }
241
- }
242
- }
243
-
244
- if ( $originalUrl !== NULL ) {
245
- $originalUrl = str_replace('//', '/', $originalUrl);
246
-
247
- if ( ($pos=strpos($_SERVER['REQUEST_URI'], '?')) !== false ) {
248
- $queryVars = substr($_SERVER['REQUEST_URI'], $pos+1);
249
- $originalUrl .= (strpos($originalUrl, '?') === false ? '?' : '&') . $queryVars;
250
- }
251
-
252
- // Now we have the original URL, run this back through WP->parse_request, in order to
253
- // parse parameters properly. We set $_SERVER variables to fool the function.
254
- $oldRequestUri = $_SERVER['REQUEST_URI']; $oldQueryString = $_SERVER['QUERY_STRING'];
255
- $_SERVER['REQUEST_URI'] = '/'.ltrim($originalUrl,'/');
256
- $_SERVER['QUERY_STRING'] = (($pos=strpos($originalUrl, '?')) !== false ? substr($originalUrl, $pos+1) : '');
257
- parse_str($_SERVER['QUERY_STRING'], $queryArray);
258
- $oldValues = array();
259
- if ( is_array($queryArray) )
260
- foreach ( $queryArray as $key => $value ) {
261
- $oldValues[$key] = $_REQUEST[$key];
262
- $_REQUEST[$key] = $_GET[$key] = $value;
263
- }
264
-
265
- // Re-run the filter, now with original environment in place
266
- remove_filter( 'request', 'custom_permalinks_request', 10, 1 );
267
- global $wp;
268
- $wp->parse_request();
269
- $query = $wp->query_vars;
270
- add_filter( 'request', 'custom_permalinks_request', 10, 1 );
271
-
272
- // Restore values
273
- $_SERVER['REQUEST_URI'] = $oldRequestUri; $_SERVER['QUERY_STRING'] = $oldQueryString;
274
- foreach ( $oldValues as $key => $value ) {
275
- $_REQUEST[$key] = $value;
276
- }
277
- }
278
-
279
- return $query;
280
- }
281
-
282
- /**
283
- * Filter to handle trailing slashes correctly
284
- *
285
- * @package CustomPermalinks
286
- * @since 0.3
287
- */
288
- function custom_permalinks_trailingslash($string, $type) {
289
- global $_CPRegisteredURL;
290
-
291
- remove_filter( 'user_trailingslashit', 'custom_permalinks_trailingslash', 10, 2 );
292
- $url = parse_url(get_bloginfo('url'));
293
- $request = ltrim(isset($url['path']) ? substr($string, strlen($url['path'])) : $string, '/');
294
- add_filter( 'user_trailingslashit', 'custom_permalinks_trailingslash', 10, 2 );
295
-
296
- if ( !trim($request) ) return $string;
297
-
298
- if ( trim($_CPRegisteredURL,'/') == trim($request,'/') ) {
299
- if( isset($url['path']) ) {
300
- return ($string{0} == '/' ? '/' : '') . trailingslashit($url['path']) . $_CPRegisteredURL;
301
- } else {
302
- return ($string{0} == '/' ? '/' : '') . $_CPRegisteredURL;
303
- }
304
- }
305
- return $string;
306
- }
307
-
308
- /**
309
- ** Administration
310
- **
311
- **/
312
-
313
- /**
314
- * Per-post/page options (Wordpress > 2.9)
315
- *
316
- * @package CustomPermalinks
317
- * @since 0.6
318
- */
319
- function custom_permalink_get_sample_permalink_html($html, $id, $new_title, $new_slug) {
320
- $permalink = get_post_meta( $id, 'custom_permalink', true );
321
- $post = get_post($id);
322
-
323
- ob_start();
324
- ?>
325
- <?php custom_permalinks_form($permalink, ($post->post_type == "page" ? custom_permalinks_original_page_link($id) : custom_permalinks_original_post_link($id)), false); ?>
326
- <?php
327
- $content = ob_get_contents();
328
- ob_end_clean();
329
-
330
- if ( 'publish' == $post->post_status ) {
331
- $view_post = 'page' == $post->post_type ? __('View Page', 'custom-permalinks') : __('View Post', 'custom-permalinks');
332
- }
333
-
334
- if ( preg_match("@view-post-btn.*?href='([^']+)'@s", $html, $matches) ) {
335
- $permalink = $matches[1];
336
- } else {
337
- list($permalink, $post_name) = get_sample_permalink($post->ID, $new_title, $new_slug);
338
- if ( false !== strpos($permalink, '%postname%') || false !== strpos($permalink, '%pagename%') ) {
339
- $permalink = str_replace(array('%pagename%','%postname%'), $post_name, $permalink);
340
- }
341
- }
342
-
343
- return '<strong>' . __('Permalink:', 'custom-permalinks') . "</strong>\n" . $content .
344
- ( isset($view_post) ? "<span id='view-post-btn'><a href='$permalink' class='button button-small' target='_blank'>$view_post</a></span>\n" : "" );
345
- }
346
-
347
-
348
- /**
349
- * Per-post options (Wordpress < 2.9)
350
- *
351
- * @package CustomPermalinks
352
- * @since 0.1
353
- */
354
- function custom_permalinks_post_options() {
355
- global $post;
356
- $post_id = $post;
357
- if (is_object($post_id)) {
358
- $post_id = $post_id->ID;
359
- }
360
-
361
- $permalink = get_post_meta( $post_id, 'custom_permalink', true );
362
-
363
- ?>
364
- <div class="postbox closed">
365
- <h3><?php _e('Custom Permalink', 'custom-permalinks') ?></h3>
366
- <div class="inside">
367
- <?php custom_permalinks_form($permalink, custom_permalinks_original_post_link($post_id)); ?>
368
- </div>
369
- </div>
370
- <?php
371
- }
372
-
373
- /**
374
- * Per-page options (Wordpress < 2.9)
375
- *
376
- * @package CustomPermalinks
377
- * @since 0.4
378
- */
379
- function custom_permalinks_page_options() {
380
- global $post;
381
- $post_id = $post;
382
- if (is_object($post_id)) {
383
- $post_id = $post_id->ID;
384
- }
385
-
386
- $permalink = get_post_meta( $post_id, 'custom_permalink', true );
387
-
388
- ?>
389
- <div class="postbox closed">
390
- <h3><?php _e('Custom Permalink', 'custom-permalinks') ?></h3>
391
- <div class="inside">
392
- <?php custom_permalinks_form($permalink, custom_permalinks_original_page_link($post_id)); ?>
393
- </div>
394
- </div>
395
- <?php
396
- }
397
-
398
- /**
399
- * Per-category/tag options
400
- *
401
- * @package CustomPermalinks
402
- * @since 0.1
403
- */
404
- function custom_permalinks_term_options($object) {
405
- if ( is_object($object) && isset($object->term_id) ) {
406
- $permalink = custom_permalinks_permalink_for_term($object->term_id);
407
-
408
- if ( $object->term_id ) {
409
- $originalPermalink = ($object->taxonomy == 'post_tag' ?
410
- custom_permalinks_original_tag_link($object->term_id) :
411
- custom_permalinks_original_category_link($object->term_id) );
412
- }
413
-
414
- custom_permalinks_form($permalink, $originalPermalink);
415
- } else {
416
- custom_permalinks_form('');
417
- }
418
-
419
- // Move the save button to above this form
420
- wp_enqueue_script('jquery');
421
- ?>
422
- <script type="text/javascript">
423
- jQuery(document).ready(function() {
424
- var button = jQuery('#custom_permalink_form').parent().find('.submit');
425
- button.remove().insertAfter(jQuery('#custom_permalink_form'));
426
- });
427
- </script>
428
- <?php
429
- }
430
-
431
- /**
432
- * Helper function to render form
433
- *
434
- * @package CustomPermalinks
435
- * @since 0.1
436
- */
437
- function custom_permalinks_form($permalink, $original="", $renderContainers=true) {
438
- ?>
439
- <input value="true" type="hidden" name="custom_permalinks_edit" />
440
- <input value="<?php echo htmlspecialchars(urldecode($permalink)) ?>" type="hidden" name="custom_permalink" id="custom_permalink" />
441
-
442
- <?php if ( $renderContainers ) : ?>
443
- <table class="form-table" id="custom_permalink_form">
444
- <tr>
445
- <th scope="row"><?php _e('Custom Permalink', 'custom-permalinks') ?></th>
446
- <td>
447
- <?php endif; ?>
448
-
449
- <?php
450
- if ($permalink == '') {
451
- $original = custom_permalinks_check_conflicts($original);
452
- }
453
- ?>
454
-
455
- <?php echo home_url() ?>/
456
- <span id="editable-post-name" title="Click to edit this part of the permalink">
457
- <input type="text" id="new-post-slug" class="text" value="<?php echo htmlspecialchars($permalink ? urldecode($permalink) : urldecode($original)) ?>"
458
- style="width: 250px; <?php if ( !$permalink ) echo 'color: #ddd;' ?>"
459
- onfocus="if ( this.style.color = '#ddd' ) { this.style.color = '#000'; }"
460
- onblur="document.getElementById('custom_permalink').value = this.value; if ( this.value == '' || this.value == '<?php echo htmlspecialchars(urldecode($original)) ?>' ) { this.value = '<?php echo htmlspecialchars(urldecode($original)) ?>'; this.style.color = '#ddd'; }"/>
461
- </span>
462
- <?php if ( $renderContainers ) : ?>
463
- <br />
464
- <small><?php _e('Leave blank to disable', 'custom-permalinks') ?></small>
465
-
466
- </td>
467
- </tr>
468
- </table>
469
- <?php
470
- endif;
471
- }
472
-
473
- /**
474
- * Save per-post options
475
- *
476
- * @package CustomPermalinks
477
- * @since 0.1
478
- */
479
- function custom_permalinks_save_post($id) {
480
- if ( !isset($_REQUEST['custom_permalinks_edit']) ) return;
481
-
482
- delete_post_meta( $id, 'custom_permalink' );
483
-
484
- $original_link = custom_permalinks_original_post_link($id);
485
- $permalink_structure = get_option('permalink_structure');
486
-
487
- if ( $_REQUEST['custom_permalink'] && $_REQUEST['custom_permalink'] != $original_link ) {
488
- add_post_meta( $id, 'custom_permalink', str_replace('%2F', '/', urlencode(ltrim(stripcslashes($_REQUEST['custom_permalink']),"/"))) );
489
- }
490
- }
491
-
492
- /**
493
- * Save per-tag options
494
- *
495
- * @package CustomPermalinks
496
- * @since 0.1
497
- */
498
- function custom_permalinks_save_tag($id) {
499
- if ( !isset($_REQUEST['custom_permalinks_edit']) || isset($_REQUEST['post_ID']) ) return;
500
- $newPermalink = ltrim(stripcslashes($_REQUEST['custom_permalink']),"/");
501
-
502
- if ( $newPermalink == custom_permalinks_original_tag_link($id) )
503
- $newPermalink = '';
504
-
505
- $term = get_term($id, 'post_tag');
506
- custom_permalinks_save_term($term, str_replace('%2F', '/', urlencode($newPermalink)));
507
- }
508
-
509
- /**
510
- * Save per-category options
511
- *
512
- * @package CustomPermalinks
513
- * @since 0.1
514
- */
515
- function custom_permalinks_save_category($id) {
516
- if ( !isset($_REQUEST['custom_permalinks_edit']) || isset($_REQUEST['post_ID']) ) return;
517
- $newPermalink = ltrim(stripcslashes($_REQUEST['custom_permalink']),"/");
518
-
519
- if ( $newPermalink == custom_permalinks_original_category_link($id) )
520
- $newPermalink = '';
521
-
522
- $term = get_term($id, 'category');
523
- custom_permalinks_save_term($term, str_replace('%2F', '/', urlencode($newPermalink)));
524
- }
525
-
526
- /**
527
- * Save term (common to tags and categories)
528
- *
529
- * @package CustomPermalinks
530
- * @since 0.1
531
- */
532
- function custom_permalinks_save_term($term, $permalink) {
533
-
534
- custom_permalinks_delete_term($term->term_id);
535
- $table = get_option('custom_permalink_table');
536
- if ( $permalink )
537
- $table[$permalink] = array(
538
- 'id' => $term->term_id,
539
- 'kind' => ($term->taxonomy == 'category' ? 'category' : 'tag'),
540
- 'slug' => $term->slug);
541
-
542
- update_option('custom_permalink_table', $table);
543
- }
544
-
545
- /**
546
- * Delete post
547
- *
548
- * @package CustomPermalinks
549
- * @since 0.7.14
550
- * @author Piero <maltesepiero@gmail.com>
551
- */
552
- function custom_permalinks_delete_permalink( $id ){
553
- global $wpdb;
554
- // Queries are now WP3.9 compatible (by Steve from Sowmedia.nl)
555
- $wpdb->query($wpdb->prepare("DELETE FROM $wpdb->postmeta WHERE `meta_key` = 'custom_permalink' AND `post_id` = %d",$id));
556
- }
557
-
558
- /**
559
- * Delete term
560
- *
561
- * @package CustomPermalinks
562
- * @since 0.1
563
- */
564
- function custom_permalinks_delete_term($id) {
565
-
566
- $table = get_option('custom_permalink_table');
567
- if ( $table )
568
- foreach ( $table as $link => $info ) {
569
- if ( $info['id'] == $id ) {
570
- unset($table[$link]);
571
- break;
572
- }
573
- }
574
-
575
- update_option('custom_permalink_table', $table);
576
- }
577
-
578
- /**
579
- * Options page
580
- *
581
- * @package CustomPermalinks
582
- * @since 0.1
583
- */
584
- function custom_permalinks_options_page() {
585
-
586
- // Handle revert
587
- if ( isset($_REQUEST['revertit']) && isset($_REQUEST['revert']) ) {
588
- check_admin_referer('custom-permalinks-bulk');
589
- foreach ( (array)$_REQUEST['revert'] as $identifier ) {
590
- list($kind, $id) = explode('.', $identifier);
591
- switch ( $kind ) {
592
- case 'post':
593
- case 'page':
594
- delete_post_meta( $id, 'custom_permalink' );
595
- break;
596
- case 'tag':
597
- case 'category':
598
- custom_permalinks_delete_term($id);
599
- break;
600
- }
601
- }
602
-
603
- // Redirect
604
- $redirectUrl = $_SERVER['REQUEST_URI'];
605
- ?>
606
- <script type="text/javascript">
607
- document.location = '<?php echo $redirectUrl ?>'
608
- </script>
609
- <?php ;
610
- }
611
-
612
- ?>
613
- <div class="wrap">
614
- <h2><?php _e('Custom Permalinks', 'custom-permalinks') ?></h2>
615
-
616
- <form method="post" action="<?php echo $_SERVER['REQUEST_URI'] ?>">
617
- <?php wp_nonce_field('custom-permalinks-bulk') ?>
618
-
619
- <div class="tablenav">
620
- <div class="alignleft">
621
- <input type="submit" value="<?php _e('Revert', 'custom-permalinks'); ?>" name="revertit" class="button-secondary delete" />
622
- </div>
623
- <br class="clear" />
624
- </div>
625
- <br class="clear" />
626
- <table class="widefat">
627
- <thead>
628
- <tr>
629
- <th scope="col" class="check-column"><input type="checkbox" /></th>
630
- <th scope="col"><?php _e('Title', 'custom-permalinks') ?></th>
631
- <th scope="col"><?php _e('Type', 'custom-permalinks') ?></th>
632
- <th scope="col"><?php _e('Permalink', 'custom-permalinks') ?></th>
633
- </tr>
634
- </thead>
635
- <tbody>
636
- <?php
637
- $rows = custom_permalinks_admin_rows();
638
- foreach ( $rows as $row ) {
639
- ?>
640
- <tr valign="top">
641
- <th scope="row" class="check-column"><input type="checkbox" name="revert[]" value="<?php echo $row['id'] ?>" /></th>
642
- <td><strong><a class="row-title" href="<?php echo htmlspecialchars($row['editlink']) ?>"><?php echo htmlspecialchars($row['title']) ?></a></strong></td>
643
- <td><?php echo htmlspecialchars($row['type']) ?></td>
644
- <td><a href="<?php echo $row['permalink'] ?>" target="_blank" title="<?php printf(__('Visit %s', 'custom-permalinks'), htmlspecialchars($row['title'])) ?>">
645
- <?php echo htmlspecialchars(urldecode($row['permalink'])) ?>
646
- </a>
647
- </td>
648
- </tr>
649
- <?php
650
- }
651
- ?>
652
- </tbody>
653
- </table>
654
- </form>
655
- </div>
656
- <?php
657
- }
658
-
659
- /**
660
- * Get rows for management view
661
- *
662
- * @package CustomPermalinks
663
- * @since 0.1
664
- */
665
- function custom_permalinks_admin_rows() {
666
- $rows = array();
667
-
668
- // List tags/categories
669
- $table = get_option('custom_permalink_table');
670
- if ( $table && is_array($table) ) {
671
- foreach ( $table as $permalink => $info ) {
672
- $row = array();
673
- $term = get_term($info['id'], ($info['kind'] == 'tag' ? 'post_tag' : 'category'));
674
- $row['id'] = $info['kind'].'.'.$info['id'];
675
- $row['permalink'] = home_url()."/".$permalink;
676
- $row['type'] = ucwords($info['kind']);
677
- $row['title'] = $term->name;
678
- $row['editlink'] = ( $info['kind'] == 'tag' ? 'edit-tags.php?action=edit&taxonomy=post_tag&tag_ID='.$info['id'] : 'edit-tags.php?action=edit&taxonomy=category&tag_ID='.$info['id'] );
679
- $rows[] = $row;
680
- }
681
- }
682
-
683
- // List posts/pages
684
- global $wpdb;
685
- $query = "SELECT $wpdb->posts.* FROM $wpdb->posts LEFT JOIN $wpdb->postmeta ON ($wpdb->posts.ID = $wpdb->postmeta.post_id) WHERE
686
- $wpdb->postmeta.meta_key = 'custom_permalink' AND $wpdb->postmeta.meta_value != '';";
687
- $posts = $wpdb->get_results($query);
688
- foreach ( $posts as $post ) {
689
- $row = array();
690
- $row['id'] = 'post.'.$post->ID;
691
- $row['permalink'] = get_permalink($post->ID);
692
- $row['type'] = ucwords( $post->post_type );
693
- $row['title'] = $post->post_title;
694
- $row['editlink'] = 'post.php?action=edit&post='.$post->ID;
695
- $rows[] = $row;
696
- }
697
-
698
- return $rows;
699
- }
700
-
701
- /**
702
- * Get original permalink for post
703
- *
704
- * @package CustomPermalinks
705
- * @since 0.1
706
- */
707
- function custom_permalinks_original_post_link($post_id) {
708
- remove_filter( 'post_link', 'custom_permalinks_post_link', 10, 3 ); // original hook
709
- remove_filter( 'post_type_link', 'custom_permalinks_post_link', 10, 2 );
710
-
711
- require_once ABSPATH . '/wp-admin/includes/post.php';
712
- list( $permalink, $post_name ) = get_sample_permalink( $post_id );
713
- $permalink = str_replace(array('%pagename%','%postname%'), $post_name, $permalink);
714
- $permalink = ltrim(str_replace(home_url(), '', $permalink), '/');
715
-
716
- add_filter( 'post_link', 'custom_permalinks_post_link', 10, 3 ); // original hook
717
- add_filter( 'post_type_link', 'custom_permalinks_post_link', 10, 2 );
718
-
719
- return $permalink;
720
- }
721
-
722
- /**
723
- * Get original permalink for page
724
- *
725
- * @package CustomPermalinks
726
- * @since 0.4
727
- */
728
- function custom_permalinks_original_page_link($post_id) {
729
- remove_filter( 'page_link', 'custom_permalinks_page_link', 10, 2 );
730
- remove_filter( 'user_trailingslashit', 'custom_permalinks_trailingslash', 10, 2 );
731
-
732
- require_once ABSPATH . '/wp-admin/includes/post.php';
733
- list( $permalink, $post_name ) = get_sample_permalink( $post_id );
734
- $permalink = str_replace(array('%pagename%','%postname%'), $post_name, $permalink);
735
- $permalink = ltrim(str_replace(home_url(), '', $permalink), '/');
736
-
737
- add_filter( 'user_trailingslashit', 'custom_permalinks_trailingslash', 10, 2 );
738
- add_filter( 'page_link', 'custom_permalinks_page_link', 10, 2 );
739
- return $permalink;
740
- }
741
-
742
- /**
743
- * Get original permalink for tag
744
- *
745
- * @package CustomPermalinks
746
- * @since 0.1
747
- */
748
- function custom_permalinks_original_tag_link($tag_id) {
749
- remove_filter( 'tag_link', 'custom_permalinks_term_link', 10, 2 );
750
- remove_filter( 'user_trailingslashit', 'custom_permalinks_trailingslash', 10, 2 );
751
- $originalPermalink = ltrim(str_replace(home_url(), '', get_tag_link($tag_id)), '/');
752
- add_filter( 'user_trailingslashit', 'custom_permalinks_trailingslash', 10, 2 );
753
- add_filter( 'tag_link', 'custom_permalinks_term_link', 10, 2 );
754
- return $originalPermalink;
755
- }
756
-
757
- /**
758
- * Get original permalink for category
759
- *
760
- * @package CustomPermalinks
761
- * @since 0.1
762
- */
763
- function custom_permalinks_original_category_link($category_id) {
764
- remove_filter( 'category_link', 'custom_permalinks_term_link', 10, 2 );
765
- remove_filter( 'user_trailingslashit', 'custom_permalinks_trailingslash', 10, 2 );
766
- $originalPermalink = ltrim(str_replace(home_url(), '', get_category_link($category_id)), '/');
767
- add_filter( 'user_trailingslashit', 'custom_permalinks_trailingslash', 10, 2 );
768
- add_filter( 'category_link', 'custom_permalinks_term_link', 10, 2 );
769
- return $originalPermalink;
770
- }
771
-
772
- /**
773
- * Get permalink for term
774
- *
775
- * @package CustomPermalinks
776
- * @since 0.1
777
- */
778
- function custom_permalinks_permalink_for_term($id) {
779
- $table = get_option('custom_permalink_table');
780
- if ( $table )
781
- foreach ( $table as $link => $info ) {
782
- if ( $info['id'] == $id ) {
783
- return $link;
784
- }
785
- }
786
- return false;
787
- }
788
-
789
- /**
790
- * Set up administration menu
791
- *
792
- * @package CustomPermalinks
793
- * @since 0.1
794
- */
795
- function custom_permalinks_setup_admin_menu() {
796
- add_management_page( 'Custom Permalinks', 'Custom Permalinks', 'edit_others_pages', 'custom_permalinks', 'custom_permalinks_options_page' );
797
- }
798
-
799
- /**
800
- * Set up administration header
801
- *
802
- * @package CustomPermalinks
803
- * @since 0.7.20
804
- */
805
- function custom_permalinks_setup_admin_head() {
806
- wp_enqueue_script('admin-forms');
807
- }
808
-
809
- /**
810
- * Check Conflicts and resolve it (e.g: Polylang)
811
- *
812
- * @package CustomPermalinks
813
- * @since 0.9
814
- */
815
- function custom_permalinks_check_conflicts($requested_url = '') {
816
-
817
- if ($requested_url == '') return;
818
-
819
- // Check if the Polylang Plugin is installed so, make changes in the URL
820
- if (defined( 'POLYLANG_VERSION' )) {
821
- $polylang_config = get_option('polylang');
822
- if ($polylang_config['force_lang'] == 1) {
823
-
824
- if(strpos($requested_url, 'language/') !== false)
825
- $requested_url = str_replace("language/", "", $requested_url);
826
-
827
- $remove_lang = ltrim(strstr($requested_url, '/'), '/');
828
- if ($remove_lang != '')
829
- return $remove_lang;
830
- }
831
- }
832
-
833
- return $requested_url;
834
- }
835
-
836
- if (function_exists("add_action") && function_exists("add_filter")) {
837
- add_action( 'template_redirect', 'custom_permalinks_redirect', 5 );
838
- add_filter( 'post_link', 'custom_permalinks_post_link', 10, 3 );
839
- add_filter( 'post_type_link', 'custom_permalinks_post_link', 10, 2 );
840
- add_filter( 'page_link', 'custom_permalinks_page_link', 10, 2 );
841
- add_filter( 'tag_link', 'custom_permalinks_term_link', 10, 2 );
842
- add_filter( 'category_link', 'custom_permalinks_term_link', 10, 2 );
843
- add_filter( 'request', 'custom_permalinks_request', 10, 1 );
844
- add_filter( 'user_trailingslashit', 'custom_permalinks_trailingslash', 10, 2 );
845
-
846
- if (function_exists("get_bloginfo")) {
847
- $v = explode('.', get_bloginfo('version'));
848
- }
849
-
850
- if ( $v[0] >= 2 ) {
851
- add_filter( 'get_sample_permalink_html', 'custom_permalink_get_sample_permalink_html', 10, 4 );
852
- } else {
853
- add_action( 'edit_form_advanced', 'custom_permalinks_post_options' );
854
- add_action( 'edit_page_form', 'custom_permalinks_page_options' );
855
- }
856
-
857
- add_action( 'edit_tag_form', 'custom_permalinks_term_options' );
858
- add_action( 'add_tag_form', 'custom_permalinks_term_options' );
859
- add_action( 'edit_category_form', 'custom_permalinks_term_options' );
860
- add_action( 'save_post', 'custom_permalinks_save_post' );
861
- add_action( 'save_page', 'custom_permalinks_save_post' );
862
- add_action( 'edited_post_tag', 'custom_permalinks_save_tag' );
863
- add_action( 'edited_category', 'custom_permalinks_save_category' );
864
- add_action( 'create_post_tag', 'custom_permalinks_save_tag' );
865
- add_action( 'create_category', 'custom_permalinks_save_category' );
866
- add_action( 'delete_post', 'custom_permalinks_delete_permalink', 10);
867
- add_action( 'delete_post_tag', 'custom_permalinks_delete_term' );
868
- add_action( 'delete_post_category', 'custom_permalinks_delete_term' );
869
- add_action( 'admin_head', 'custom_permalinks_setup_admin_head' );
870
- add_action( 'admin_menu', 'custom_permalinks_setup_admin_menu' );
871
- }
872
- ?>
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Plugin Name: Custom Permalinks
5
+ * Plugin URI: https://wordpress.org/plugins/custom-permalinks/
6
+ * Donate link: https://www.paypal.me/yasglobal
7
+ * Description: Set custom permalinks on a per-post basis
8
+ * Version: 1.0
9
+ * Author: Sami Ahmed Siddiqui
10
+ * Author URI: https://www.yasglobal.com/web-design-development/wordpress/custom-permalinks/
11
+ * Text Domain: custom-permalinks
12
+ */
13
+
14
+ /**
15
+ * Copyright 2008-2017 Sami Ahmed Siddiqui <sami@samisiddiqui.com>
16
+ *
17
+ * This program is free software; you can redistribute it and/or modify
18
+ * it under the terms of the GNU General Public License as published by
19
+ * the Free Software Foundation; either version 2 of the License, or
20
+ * (at your option) any later version.
21
+ *
22
+ * This program is distributed in the hope that it will be useful,
23
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25
+ * GNU General Public License for more details.
26
+ *
27
+ * You should have received a copy of the GNU General Public License
28
+ * along with this program; if not, write to the Free Software
29
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30
+ */
31
+
32
+ // Make sure we don't expose any info if called directly
33
+ if ( ! defined( 'ABSPATH' ) ) {
34
+ echo 'Hi there! I\'m just a plugin, not much I can do when called directly.';
35
+ exit;
36
+ }
37
+
38
+ /**
39
+ ** Actions and filters
40
+ **
41
+ **/
42
+
43
+ /**
44
+ * Filter to replace the post permalink with the custom one
45
+ */
46
+ function custom_permalinks_post_link($permalink, $post) {
47
+ $custom_permalink = get_post_meta( $post->ID, 'custom_permalink', true );
48
+ if ( $custom_permalink ) {
49
+ $post_type = isset($post->post_type) ? $post->post_type : 'post';
50
+ $language_code = apply_filters( 'wpml_element_language_code', null, array( 'element_id' => $post->ID, 'element_type' => $post_type ) );
51
+ if ( $language_code )
52
+ return apply_filters( 'wpml_permalink', home_url()."/".$custom_permalink, $language_code );
53
+ else
54
+ return apply_filters( 'wpml_permalink', home_url()."/".$custom_permalink );
55
+ }
56
+
57
+ return $permalink;
58
+ }
59
+
60
+ /**
61
+ * Filter to replace the page permalink with the custom one
62
+ */
63
+ function custom_permalinks_page_link($permalink, $page) {
64
+ $custom_permalink = get_post_meta( $page, 'custom_permalink', true );
65
+ if ( $custom_permalink ) {
66
+ $language_code = apply_filters( 'wpml_element_language_code', null, array( 'element_id' => $page, 'element_type' => 'page' ) );
67
+ if ( $language_code )
68
+ return apply_filters( 'wpml_permalink', home_url()."/".$custom_permalink, $language_code );
69
+ else
70
+ return apply_filters( 'wpml_permalink', home_url()."/".$custom_permalink );
71
+ }
72
+
73
+ return $permalink;
74
+ }
75
+
76
+ /**
77
+ * Filter to replace the term permalink with the custom one
78
+ */
79
+ function custom_permalinks_term_link($permalink, $term) {
80
+ $table = get_option('custom_permalink_table');
81
+ if ( is_object($term) ) $term = $term->term_id;
82
+
83
+ $custom_permalink = custom_permalinks_permalink_for_term($term);
84
+ if ( $custom_permalink ) {
85
+ $taxonomy = get_term($term);
86
+ if ( isset($taxonomy) && isset($taxonomy->term_taxonomy_id) ) {
87
+ $term_type = isset($taxonomy->taxonomy) ? $taxonomy->taxonomy : 'category';
88
+ $language_code = apply_filters( 'wpml_element_language_code', null, array( 'element_id' => $taxonomy->term_taxonomy_id, 'element_type' => $term_type ) );
89
+ return apply_filters( 'wpml_permalink', home_url()."/".$custom_permalink, $language_code );
90
+ } else {
91
+ return apply_filters( 'wpml_permalink', home_url()."/".$custom_permalink );
92
+ }
93
+ }
94
+
95
+ return $permalink;
96
+ }
97
+
98
+ /**
99
+ * Action to redirect to the custom permalink
100
+ *
101
+ * @package CustomPermalinks
102
+ * @since 0.1
103
+ */
104
+ function custom_permalinks_redirect() {
105
+ // Get request URI, strip parameters
106
+ $url = parse_url(get_bloginfo('url'));
107
+ $url = isset($url['path']) ? $url['path'] : '';
108
+ $request = ltrim(substr($_SERVER['REQUEST_URI'], strlen($url)),'/');
109
+ if ( ($pos=strpos($request, "?")) ) $request = substr($request, 0, $pos);
110
+
111
+ $request = custom_permalinks_check_conflicts($request);
112
+
113
+ global $wp_query;
114
+
115
+ $custom_permalink = '';
116
+ $original_permalink = '';
117
+
118
+ // If the post/tag/category we're on has a custom permalink, get it and check against the request
119
+ if ( (is_single() || is_page()) && !empty($wp_query->post) ) {
120
+ $post = $wp_query->post;
121
+ $custom_permalink = get_post_meta( $post->ID, 'custom_permalink', true );
122
+ $original_permalink = ( $post->post_type == 'page' ? custom_permalinks_original_page_link( $post->ID ) : custom_permalinks_original_post_link( $post->ID ) );
123
+ } else if ( is_tag() || is_category() ) {
124
+ $theTerm = $wp_query->get_queried_object();
125
+ $custom_permalink = custom_permalinks_permalink_for_term($theTerm->term_id);
126
+ $original_permalink = (is_tag() ? custom_permalinks_original_tag_link($theTerm->term_id) :
127
+ custom_permalinks_original_category_link($theTerm->term_id));
128
+ }
129
+
130
+ if ( $custom_permalink &&
131
+ (substr($request, 0, strlen($custom_permalink)) != $custom_permalink ||
132
+ $request == $custom_permalink."/" ) ) {
133
+ // Request doesn't match permalink - redirect
134
+ $url = $custom_permalink;
135
+
136
+ if ( substr($request, 0, strlen($original_permalink)) == $original_permalink &&
137
+ trim($request,'/') != trim($original_permalink,'/') ) {
138
+ // This is the original link; we can use this url to derive the new one
139
+ $url = preg_replace('@//*@', '/', str_replace(trim($original_permalink,'/'), trim($custom_permalink,'/'), $request));
140
+ $url = preg_replace('@([^?]*)&@', '\1?', $url);
141
+ }
142
+
143
+ // Append any query compenent
144
+ $url .= strstr($_SERVER['REQUEST_URI'], "?");
145
+
146
+ wp_redirect( home_url()."/".$url, 301 );
147
+ exit();
148
+ }
149
+ }
150
+
151
+ /**
152
+ * Filter to rewrite the query if we have a matching post
153
+ *
154
+ * @package CustomPermalinks
155
+ * @since 0.1
156
+ */
157
+ function custom_permalinks_request($query) {
158
+ global $wpdb;
159
+ global $_CPRegisteredURL;
160
+
161
+ // First, search for a matching custom permalink, and if found, generate the corresponding
162
+ // original URL
163
+
164
+ $originalUrl = NULL;
165
+
166
+ // Get request URI, strip parameters and /'s
167
+ $url = parse_url(get_bloginfo('url'));
168
+ $url = isset($url['path']) ? $url['path'] : '';
169
+ $request = ltrim(substr($_SERVER['REQUEST_URI'], strlen($url)),'/');
170
+ $request = (($pos=strpos($request, '?')) ? substr($request, 0, $pos) : $request);
171
+
172
+ if ( !$request ) return $query;
173
+
174
+ $request = custom_permalinks_check_conflicts($request);
175
+ $request_noslash = preg_replace('@/+@','/', trim($request, '/'));
176
+
177
+ // Queries are now WP3.9 compatible (by Steve from Sowmedia.nl)
178
+ /* $sql = $wpdb->prepare("SELECT $wpdb->posts.ID, $wpdb->postmeta.meta_value, $wpdb->posts.post_type, $wpdb->posts.post_status FROM $wpdb->posts ".
179
+ "LEFT JOIN $wpdb->postmeta ON ($wpdb->posts.ID = $wpdb->postmeta.post_id) WHERE ".
180
+ " meta_key = 'custom_permalink' AND ".
181
+ " meta_value != '' AND ".
182
+ " ( LOWER(meta_value) = LEFT(LOWER('%s'), LENGTH(meta_value)) OR ".
183
+ " LOWER(meta_value) = LEFT(LOWER('%s'), LENGTH(meta_value)) ) ".
184
+ " AND post_status != 'trash' AND post_type != 'nav_menu_item'".
185
+ " ORDER BY LENGTH(meta_value) DESC, ".
186
+ " FIELD(post_status,'publish','private','draft','auto-draft','inherit'),".
187
+ " FIELD(post_type,'post','page'),".
188
+ "$wpdb->posts.ID ASC LIMIT 1",
189
+ $request_noslash,
190
+ $request_noslash."/"); */
191
+
192
+ $sql = $wpdb->prepare("SELECT p.ID as ID, pm.meta_value as meta_value, p.post_type as post_type, p.post_status as post_status FROM $wpdb->posts AS p, $wpdb->postmeta AS pm WHERE p.ID = pm.post_id AND pm.meta_key = 'custom_permalink' AND (pm.meta_value = '%s' OR pm.meta_value = '%s') AND p.post_status != 'trash' AND p.post_type != 'nav_menu_item' LIMIT 1", $request_noslash, $request_noslash."/");
193
+
194
+ $posts = $wpdb->get_results($sql);
195
+
196
+ if ( $posts ) {
197
+ // A post matches our request
198
+
199
+ // Preserve this url for later if it's the same as the permalink (no extra stuff)
200
+ if ( $request_noslash == trim($posts[0]->meta_value,'/') )
201
+ $_CPRegisteredURL = $request;
202
+
203
+ if ( $posts[0]->post_status == 'draft' ) {
204
+ if( $posts[0]->post_type == 'page' ) {
205
+ $originalUrl = "?page_id=" . $posts[0]->ID;
206
+ } else {
207
+ $originalUrl = "?post_type=".$posts[0]->post_type."&p=" . $posts[0]->ID;
208
+ }
209
+ } else {
210
+ $originalUrl = preg_replace( '@/+@', '/', str_replace( trim( strtolower($posts[0]->meta_value),'/' ),
211
+ ( $posts[0]->post_type == 'page' ?
212
+ custom_permalinks_original_page_link($posts[0]->ID)
213
+ : custom_permalinks_original_post_link($posts[0]->ID) ),
214
+ strtolower($request_noslash) ) );
215
+ }
216
+ }
217
+
218
+ if ( $originalUrl === NULL ) {
219
+ // See if any terms have a matching permalink
220
+ $table = get_option('custom_permalink_table');
221
+ if ( !$table ) return $query;
222
+
223
+ foreach ( array_keys($table) as $permalink ) {
224
+ if ( $permalink == substr($request_noslash, 0, strlen($permalink)) ||
225
+ $permalink == substr($request_noslash."/", 0, strlen($permalink)) ) {
226
+ $term = $table[$permalink];
227
+
228
+ // Preserve this url for later if it's the same as the permalink (no extra stuff)
229
+ if ( $request_noslash == trim($permalink,'/') )
230
+ $_CPRegisteredURL = $request;
231
+
232
+
233
+ if ( $term['kind'] == 'category') {
234
+ $originalUrl = str_replace(trim($permalink,'/'),
235
+ custom_permalinks_original_category_link($term['id']),
236
+ trim($request,'/'));
237
+ } else {
238
+ $originalUrl = str_replace(trim($permalink,'/'),
239
+ custom_permalinks_original_tag_link($term['id']),
240
+ trim($request,'/'));
241
+ }
242
+ }
243
+ }
244
+ }
245
+
246
+ if ( $originalUrl !== NULL ) {
247
+ $originalUrl = str_replace('//', '/', $originalUrl);
248
+
249
+ if ( ($pos=strpos($_SERVER['REQUEST_URI'], '?')) !== false ) {
250
+ $queryVars = substr($_SERVER['REQUEST_URI'], $pos+1);
251
+ $originalUrl .= (strpos($originalUrl, '?') === false ? '?' : '&') . $queryVars;
252
+ }
253
+
254
+ // Now we have the original URL, run this back through WP->parse_request, in order to
255
+ // parse parameters properly. We set $_SERVER variables to fool the function.
256
+ $oldRequestUri = $_SERVER['REQUEST_URI']; $oldQueryString = $_SERVER['QUERY_STRING'];
257
+ $_SERVER['REQUEST_URI'] = '/'.ltrim($originalUrl,'/');
258
+ $_SERVER['QUERY_STRING'] = (($pos=strpos($originalUrl, '?')) !== false ? substr($originalUrl, $pos+1) : '');
259
+ parse_str($_SERVER['QUERY_STRING'], $queryArray);
260
+ $oldValues = array();
261
+ if ( is_array($queryArray) )
262
+ foreach ( $queryArray as $key => $value ) {
263
+ $oldValues[$key] = $_REQUEST[$key];
264
+ $_REQUEST[$key] = $_GET[$key] = $value;
265
+ }
266
+
267
+ // Re-run the filter, now with original environment in place
268
+ remove_filter( 'request', 'custom_permalinks_request', 10, 1 );
269
+ global $wp;
270
+ $wp->parse_request();
271
+ $query = $wp->query_vars;
272
+ add_filter( 'request', 'custom_permalinks_request', 10, 1 );
273
+
274
+ // Restore values
275
+ $_SERVER['REQUEST_URI'] = $oldRequestUri; $_SERVER['QUERY_STRING'] = $oldQueryString;
276
+ foreach ( $oldValues as $key => $value ) {
277
+ $_REQUEST[$key] = $value;
278
+ }
279
+ }
280
+
281
+ return $query;
282
+ }
283
+
284
+ /**
285
+ * Filter to handle trailing slashes correctly
286
+ *
287
+ * @package CustomPermalinks
288
+ * @since 0.3
289
+ */
290
+ function custom_permalinks_trailingslash($string, $type) {
291
+ global $_CPRegisteredURL;
292
+
293
+ remove_filter( 'user_trailingslashit', 'custom_permalinks_trailingslash', 10, 2 );
294
+ $url = parse_url(get_bloginfo('url'));
295
+ $request = ltrim(isset($url['path']) ? substr($string, strlen($url['path'])) : $string, '/');
296
+ add_filter( 'user_trailingslashit', 'custom_permalinks_trailingslash', 10, 2 );
297
+
298
+ if ( !trim($request) ) return $string;
299
+
300
+ if ( trim($_CPRegisteredURL,'/') == trim($request,'/') ) {
301
+ if( isset($url['path']) ) {
302
+ return ($string{0} == '/' ? '/' : '') . trailingslashit($url['path']) . $_CPRegisteredURL;
303
+ } else {
304
+ return ($string{0} == '/' ? '/' : '') . $_CPRegisteredURL;
305
+ }
306
+ }
307
+ return $string;
308
+ }
309
+
310
+ /**
311
+ ** Administration
312
+ **
313
+ **/
314
+
315
+ /**
316
+ * Per-post/page options (Wordpress > 2.9)
317
+ *
318
+ * @package CustomPermalinks
319
+ * @since 0.6
320
+ */
321
+ function custom_permalink_get_sample_permalink_html($html, $id, $new_title, $new_slug) {
322
+ $permalink = get_post_meta( $id, 'custom_permalink', true );
323
+ $post = get_post($id);
324
+
325
+ ob_start();
326
+ ?>
327
+ <?php custom_permalinks_form($permalink, ($post->post_type == "page" ? custom_permalinks_original_page_link($id) : custom_permalinks_original_post_link($id)), false); ?>
328
+ <?php
329
+ $content = ob_get_contents();
330
+ ob_end_clean();
331
+
332
+ if ( 'publish' == $post->post_status ) {
333
+ $view_post = 'page' == $post->post_type ? __('View Page', 'custom-permalinks') : __('View Post', 'custom-permalinks');
334
+ }
335
+
336
+ if ( preg_match("@view-post-btn.*?href='([^']+)'@s", $html, $matches) ) {
337
+ $permalink = $matches[1];
338
+ } else {
339
+ list($permalink, $post_name) = get_sample_permalink($post->ID, $new_title, $new_slug);
340
+ if ( false !== strpos($permalink, '%postname%') || false !== strpos($permalink, '%pagename%') ) {
341
+ $permalink = str_replace(array('%pagename%','%postname%'), $post_name, $permalink);
342
+ }
343
+ }
344
+
345
+ return '<strong>' . __('Permalink:', 'custom-permalinks') . "</strong>\n" . $content .
346
+ ( isset($view_post) ? "<span id='view-post-btn'><a href='$permalink' class='button button-small' target='_blank'>$view_post</a></span>\n" : "" );
347
+ }
348
+
349
+
350
+ /**
351
+ * Per-post options (Wordpress < 2.9)
352
+ *
353
+ * @package CustomPermalinks
354
+ * @since 0.1
355
+ */
356
+ function custom_permalinks_post_options() {
357
+ global $post;
358
+ $post_id = $post;
359
+ if (is_object($post_id)) {
360
+ $post_id = $post_id->ID;
361
+ }
362
+
363
+ $permalink = get_post_meta( $post_id, 'custom_permalink', true );
364
+
365
+ ?>
366
+ <div class="postbox closed">
367
+ <h3><?php _e('Custom Permalink', 'custom-permalinks') ?></h3>
368
+ <div class="inside">
369
+ <?php custom_permalinks_form($permalink, custom_permalinks_original_post_link($post_id)); ?>
370
+ </div>
371
+ </div>
372
+ <?php
373
+ }
374
+
375
+ /**
376
+ * Per-page options (Wordpress < 2.9)
377
+ *
378
+ * @package CustomPermalinks
379
+ * @since 0.4
380
+ */
381
+ function custom_permalinks_page_options() {
382
+ global $post;
383
+ $post_id = $post;
384
+ if (is_object($post_id)) {
385
+ $post_id = $post_id->ID;
386
+ }
387
+
388
+ $permalink = get_post_meta( $post_id, 'custom_permalink', true );
389
+
390
+ ?>
391
+ <div class="postbox closed">
392
+ <h3><?php _e('Custom Permalink', 'custom-permalinks') ?></h3>
393
+ <div class="inside">
394
+ <?php custom_permalinks_form($permalink, custom_permalinks_original_page_link($post_id)); ?>
395
+ </div>
396
+ </div>
397
+ <?php
398
+ }
399
+
400
+ /**
401
+ * Per-category/tag options
402
+ *
403
+ * @package CustomPermalinks
404
+ * @since 0.1
405
+ */
406
+ function custom_permalinks_term_options($object) {
407
+ if ( is_object($object) && isset($object->term_id) ) {
408
+ $permalink = custom_permalinks_permalink_for_term($object->term_id);
409
+
410
+ if ( $object->term_id ) {
411
+ $originalPermalink = ($object->taxonomy == 'post_tag' ?
412
+ custom_permalinks_original_tag_link($object->term_id) :
413
+ custom_permalinks_original_category_link($object->term_id) );
414
+ }
415
+
416
+ custom_permalinks_form($permalink, $originalPermalink);
417
+ } else {
418
+ custom_permalinks_form('');
419
+ }
420
+
421
+ // Move the save button to above this form
422
+ wp_enqueue_script('jquery');
423
+ ?>
424
+ <script type="text/javascript">
425
+ jQuery(document).ready(function() {
426
+ var button = jQuery('#custom_permalink_form').parent().find('.submit');
427
+ button.remove().insertAfter(jQuery('#custom_permalink_form'));
428
+ });
429
+ </script>
430
+ <?php
431
+ }
432
+
433
+ /**
434
+ * Helper function to render form
435
+ *
436
+ * @package CustomPermalinks
437
+ * @since 0.1
438
+ */
439
+ function custom_permalinks_form($permalink, $original="", $renderContainers=true) {
440
+ ?>
441
+ <input value="true" type="hidden" name="custom_permalinks_edit" />
442
+ <input value="<?php echo htmlspecialchars(urldecode($permalink)) ?>" type="hidden" name="custom_permalink" id="custom_permalink" />
443
+
444
+ <?php if ( $renderContainers ) : ?>
445
+ <table class="form-table" id="custom_permalink_form">
446
+ <tr>
447
+ <th scope="row"><?php _e('Custom Permalink', 'custom-permalinks') ?></th>
448
+ <td>
449
+ <?php endif; ?>
450
+
451
+ <?php
452
+ if ($permalink == '') {
453
+ $original = custom_permalinks_check_conflicts($original);
454
+ }
455
+ ?>
456
+
457
+ <?php echo home_url() ?>/
458
+ <span id="editable-post-name" title="Click to edit this part of the permalink">
459
+ <input type="text" id="new-post-slug" class="text" value="<?php echo htmlspecialchars($permalink ? urldecode($permalink) : urldecode($original)) ?>"
460
+ style="width: 250px; <?php if ( !$permalink ) echo 'color: #ddd;' ?>"
461
+ onfocus="if ( this.style.color = '#ddd' ) { this.style.color = '#000'; }"
462
+ onblur="document.getElementById('custom_permalink').value = this.value; if ( this.value == '' || this.value == '<?php echo htmlspecialchars(urldecode($original)) ?>' ) { this.value = '<?php echo htmlspecialchars(urldecode($original)) ?>'; this.style.color = '#ddd'; }"/>
463
+ </span>
464
+ <?php if ( $renderContainers ) : ?>
465
+ <br />
466
+ <small><?php _e('Leave blank to disable', 'custom-permalinks') ?></small>
467
+
468
+ </td>
469
+ </tr>
470
+ </table>
471
+ <?php
472
+ endif;
473
+ }
474
+
475
+ /**
476
+ * Save per-post options
477
+ *
478
+ * @package CustomPermalinks
479
+ * @since 0.1
480
+ */
481
+ function custom_permalinks_save_post($id) {
482
+ if ( !isset($_REQUEST['custom_permalinks_edit']) ) return;
483
+
484
+ delete_post_meta( $id, 'custom_permalink' );
485
+
486
+ $original_link = custom_permalinks_original_post_link($id);
487
+ $permalink_structure = get_option('permalink_structure');
488
+
489
+ if ( $_REQUEST['custom_permalink'] && $_REQUEST['custom_permalink'] != $original_link ) {
490
+ add_post_meta( $id, 'custom_permalink', str_replace('%2F', '/', urlencode(ltrim(stripcslashes($_REQUEST['custom_permalink']),"/"))) );
491
+ }
492
+ }
493
+
494
+ /**
495
+ * Save per-tag options
496
+ *
497
+ * @package CustomPermalinks
498
+ * @since 0.1
499
+ */
500
+ function custom_permalinks_save_tag($id) {
501
+ if ( !isset($_REQUEST['custom_permalinks_edit']) || isset($_REQUEST['post_ID']) ) return;
502
+ $newPermalink = ltrim(stripcslashes($_REQUEST['custom_permalink']),"/");
503
+
504
+ if ( $newPermalink == custom_permalinks_original_tag_link($id) )
505
+ $newPermalink = '';
506
+
507
+ $term = get_term($id, 'post_tag');
508
+ custom_permalinks_save_term($term, str_replace('%2F', '/', urlencode($newPermalink)));
509
+ }
510
+
511
+ /**
512
+ * Save per-category options
513
+ *
514
+ * @package CustomPermalinks
515
+ * @since 0.1
516
+ */
517
+ function custom_permalinks_save_category($id) {
518
+ if ( !isset($_REQUEST['custom_permalinks_edit']) || isset($_REQUEST['post_ID']) ) return;
519
+ $newPermalink = ltrim(stripcslashes($_REQUEST['custom_permalink']),"/");
520
+
521
+ if ( $newPermalink == custom_permalinks_original_category_link($id) )
522
+ $newPermalink = '';
523
+
524
+ $term = get_term($id, 'category');
525
+ custom_permalinks_save_term($term, str_replace('%2F', '/', urlencode($newPermalink)));
526
+ }
527
+
528
+ /**
529
+ * Save term (common to tags and categories)
530
+ *
531
+ * @package CustomPermalinks
532
+ * @since 0.1
533
+ */
534
+ function custom_permalinks_save_term($term, $permalink) {
535
+
536
+ custom_permalinks_delete_term($term->term_id);
537
+ $table = get_option('custom_permalink_table');
538
+ if ( $permalink )
539
+ $table[$permalink] = array(
540
+ 'id' => $term->term_id,
541
+ 'kind' => ($term->taxonomy == 'category' ? 'category' : 'tag'),
542
+ 'slug' => $term->slug);
543
+
544
+ update_option('custom_permalink_table', $table);
545
+ }
546
+
547
+ /**
548
+ * Delete post
549
+ *
550
+ * @package CustomPermalinks
551
+ * @since 0.7.14
552
+ * @author Piero <maltesepiero@gmail.com>
553
+ */
554
+ function custom_permalinks_delete_permalink( $id ){
555
+ global $wpdb;
556
+ // Queries are now WP3.9 compatible (by Steve from Sowmedia.nl)
557
+ $wpdb->query($wpdb->prepare("DELETE FROM $wpdb->postmeta WHERE `meta_key` = 'custom_permalink' AND `post_id` = %d",$id));
558
+ }
559
+
560
+ /**
561
+ * Delete term
562
+ *
563
+ * @package CustomPermalinks
564
+ * @since 0.1
565
+ */
566
+ function custom_permalinks_delete_term($id) {
567
+
568
+ $table = get_option('custom_permalink_table');
569
+ if ( $table )
570
+ foreach ( $table as $link => $info ) {
571
+ if ( $info['id'] == $id ) {
572
+ unset($table[$link]);
573
+ break;
574
+ }
575
+ }
576
+
577
+ update_option('custom_permalink_table', $table);
578
+ }
579
+
580
+ /**
581
+ * Options page
582
+ *
583
+ * @package CustomPermalinks
584
+ * @since 0.1
585
+ */
586
+ function custom_permalinks_options_page() {
587
+
588
+ // Handle revert
589
+ if ( isset($_REQUEST['revertit']) && isset($_REQUEST['revert']) ) {
590
+ check_admin_referer('custom-permalinks-bulk');
591
+ foreach ( (array)$_REQUEST['revert'] as $identifier ) {
592
+ list($kind, $id) = explode('.', $identifier);
593
+ switch ( $kind ) {
594
+ case 'post':
595
+ case 'page':
596
+ delete_post_meta( $id, 'custom_permalink' );
597
+ break;
598
+ case 'tag':
599
+ case 'category':
600
+ custom_permalinks_delete_term($id);
601
+ break;
602
+ }
603
+ }
604
+
605
+ // Redirect
606
+ $redirectUrl = $_SERVER['REQUEST_URI'];
607
+ ?>
608
+ <script type="text/javascript">
609
+ document.location = '<?php echo $redirectUrl ?>'
610
+ </script>
611
+ <?php ;
612
+ }
613
+
614
+ ?>
615
+ <div class="wrap">
616
+ <h2><?php _e('Custom Permalinks', 'custom-permalinks') ?></h2>
617
+
618
+ <form method="post" action="<?php echo $_SERVER['REQUEST_URI'] ?>">
619
+ <?php wp_nonce_field('custom-permalinks-bulk') ?>
620
+
621
+ <div class="tablenav">
622
+ <div class="alignleft">
623
+ <input type="submit" value="<?php _e('Revert', 'custom-permalinks'); ?>" name="revertit" class="button-secondary delete" />
624
+ </div>
625
+ <br class="clear" />
626
+ </div>
627
+ <br class="clear" />
628
+ <table class="widefat">
629
+ <thead>
630
+ <tr>
631
+ <th scope="col" class="check-column"><input type="checkbox" /></th>
632
+ <th scope="col"><?php _e('Title', 'custom-permalinks') ?></th>
633
+ <th scope="col"><?php _e('Type', 'custom-permalinks') ?></th>
634
+ <th scope="col"><?php _e('Permalink', 'custom-permalinks') ?></th>
635
+ </tr>
636
+ </thead>
637
+ <tbody>
638
+ <?php
639
+ $rows = custom_permalinks_admin_rows();
640
+ foreach ( $rows as $row ) {
641
+ ?>
642
+ <tr valign="top">
643
+ <th scope="row" class="check-column"><input type="checkbox" name="revert[]" value="<?php echo $row['id'] ?>" /></th>
644
+ <td><strong><a class="row-title" href="<?php echo htmlspecialchars($row['editlink']) ?>"><?php echo htmlspecialchars($row['title']) ?></a></strong></td>
645
+ <td><?php echo htmlspecialchars($row['type']) ?></td>
646
+ <td><a href="<?php echo $row['permalink'] ?>" target="_blank" title="<?php printf(__('Visit %s', 'custom-permalinks'), htmlspecialchars($row['title'])) ?>">
647
+ <?php echo htmlspecialchars(urldecode($row['permalink'])) ?>
648
+ </a>
649
+ </td>
650
+ </tr>
651
+ <?php
652
+ }
653
+ ?>
654
+ </tbody>
655
+ </table>
656
+ </form>
657
+ </div>
658
+ <?php
659
+ }
660
+
661
+ /**
662
+ * Get rows for management view
663
+ *
664
+ * @package CustomPermalinks
665
+ * @since 0.1
666
+ */
667
+ function custom_permalinks_admin_rows() {
668
+ $rows = array();
669
+
670
+ // List tags/categories
671
+ $table = get_option('custom_permalink_table');
672
+ if ( $table && is_array($table) ) {
673
+ foreach ( $table as $permalink => $info ) {
674
+ $row = array();
675
+ $term = get_term($info['id'], ($info['kind'] == 'tag' ? 'post_tag' : 'category'));
676
+ $row['id'] = $info['kind'].'.'.$info['id'];
677
+ $row['permalink'] = home_url()."/".$permalink;
678
+ $row['type'] = ucwords($info['kind']);
679
+ $row['title'] = $term->name;
680
+ $row['editlink'] = ( $info['kind'] == 'tag' ? 'edit-tags.php?action=edit&taxonomy=post_tag&tag_ID='.$info['id'] : 'edit-tags.php?action=edit&taxonomy=category&tag_ID='.$info['id'] );
681
+ $rows[] = $row;
682
+ }
683
+ }
684
+
685
+ // List posts/pages
686
+ global $wpdb;
687
+ $query = "SELECT $wpdb->posts.* FROM $wpdb->posts LEFT JOIN $wpdb->postmeta ON ($wpdb->posts.ID = $wpdb->postmeta.post_id) WHERE
688
+ $wpdb->postmeta.meta_key = 'custom_permalink' AND $wpdb->postmeta.meta_value != '';";
689
+ $posts = $wpdb->get_results($query);
690
+ foreach ( $posts as $post ) {
691
+ $row = array();
692
+ $row['id'] = 'post.'.$post->ID;
693
+ $row['permalink'] = get_permalink($post->ID);
694
+ $row['type'] = ucwords( $post->post_type );
695
+ $row['title'] = $post->post_title;
696
+ $row['editlink'] = 'post.php?action=edit&post='.$post->ID;
697
+ $rows[] = $row;
698
+ }
699
+
700
+ return $rows;
701
+ }
702
+
703
+ /**
704
+ * Get original permalink for post
705
+ *
706
+ * @package CustomPermalinks
707
+ * @since 0.1
708
+ */
709
+ function custom_permalinks_original_post_link($post_id) {
710
+ remove_filter( 'post_link', 'custom_permalinks_post_link', 10, 3 ); // original hook
711
+ remove_filter( 'post_type_link', 'custom_permalinks_post_link', 10, 2 );
712
+
713
+ require_once ABSPATH . '/wp-admin/includes/post.php';
714
+ list( $permalink, $post_name ) = get_sample_permalink( $post_id );
715
+ $permalink = str_replace(array('%pagename%','%postname%'), $post_name, $permalink);
716
+ $permalink = ltrim(str_replace(home_url(), '', $permalink), '/');
717
+
718
+ add_filter( 'post_link', 'custom_permalinks_post_link', 10, 3 ); // original hook
719
+ add_filter( 'post_type_link', 'custom_permalinks_post_link', 10, 2 );
720
+
721
+ return $permalink;
722
+ }
723
+
724
+ /**
725
+ * Get original permalink for page
726
+ *
727
+ * @package CustomPermalinks
728
+ * @since 0.4
729
+ */
730
+ function custom_permalinks_original_page_link($post_id) {
731
+ remove_filter( 'page_link', 'custom_permalinks_page_link', 10, 2 );
732
+ remove_filter( 'user_trailingslashit', 'custom_permalinks_trailingslash', 10, 2 );
733
+
734
+ require_once ABSPATH . '/wp-admin/includes/post.php';
735
+ list( $permalink, $post_name ) = get_sample_permalink( $post_id );
736
+ $permalink = str_replace(array('%pagename%','%postname%'), $post_name, $permalink);
737
+ $permalink = ltrim(str_replace(home_url(), '', $permalink), '/');
738
+
739
+ add_filter( 'user_trailingslashit', 'custom_permalinks_trailingslash', 10, 2 );
740
+ add_filter( 'page_link', 'custom_permalinks_page_link', 10, 2 );
741
+ return $permalink;
742
+ }
743
+
744
+ /**
745
+ * Get original permalink for tag
746
+ *
747
+ * @package CustomPermalinks
748
+ * @since 0.1
749
+ */
750
+ function custom_permalinks_original_tag_link($tag_id) {
751
+ remove_filter( 'tag_link', 'custom_permalinks_term_link', 10, 2 );
752
+ remove_filter( 'user_trailingslashit', 'custom_permalinks_trailingslash', 10, 2 );
753
+ $originalPermalink = ltrim(str_replace(home_url(), '', get_tag_link($tag_id)), '/');
754
+ add_filter( 'user_trailingslashit', 'custom_permalinks_trailingslash', 10, 2 );
755
+ add_filter( 'tag_link', 'custom_permalinks_term_link', 10, 2 );
756
+ return $originalPermalink;
757
+ }
758
+
759
+ /**
760
+ * Get original permalink for category
761
+ *
762
+ * @package CustomPermalinks
763
+ * @since 0.1
764
+ */
765
+ function custom_permalinks_original_category_link($category_id) {
766
+ remove_filter( 'category_link', 'custom_permalinks_term_link', 10, 2 );
767
+ remove_filter( 'user_trailingslashit', 'custom_permalinks_trailingslash', 10, 2 );
768
+ $originalPermalink = ltrim(str_replace(home_url(), '', get_category_link($category_id)), '/');
769
+ add_filter( 'user_trailingslashit', 'custom_permalinks_trailingslash', 10, 2 );
770
+ add_filter( 'category_link', 'custom_permalinks_term_link', 10, 2 );
771
+ return $originalPermalink;
772
+ }
773
+
774
+ /**
775
+ * Get permalink for term
776
+ *
777
+ * @package CustomPermalinks
778
+ * @since 0.1
779
+ */
780
+ function custom_permalinks_permalink_for_term($id) {
781
+ $table = get_option('custom_permalink_table');
782
+ if ( $table )
783
+ foreach ( $table as $link => $info ) {
784
+ if ( $info['id'] == $id ) {
785
+ return $link;
786
+ }
787
+ }
788
+ return false;
789
+ }
790
+
791
+ /**
792
+ * Set up administration menu
793
+ *
794
+ * @package CustomPermalinks
795
+ * @since 0.1
796
+ */
797
+ function custom_permalinks_setup_admin_menu() {
798
+ add_management_page( 'Custom Permalinks', 'Custom Permalinks', 'edit_others_pages', 'custom_permalinks', 'custom_permalinks_options_page' );
799
+ }
800
+
801
+ /**
802
+ * Set up administration header
803
+ *
804
+ * @package CustomPermalinks
805
+ * @since 0.7.20
806
+ */
807
+ function custom_permalinks_setup_admin_head() {
808
+ wp_enqueue_script('admin-forms');
809
+ }
810
+
811
+ /**
812
+ * Check Conflicts and resolve it (e.g: Polylang)
813
+ *
814
+ * @package CustomPermalinks
815
+ * @since 0.9
816
+ */
817
+ function custom_permalinks_check_conflicts($requested_url = '') {
818
+
819
+ if ($requested_url == '') return;
820
+
821
+ // Check if the Polylang Plugin is installed so, make changes in the URL
822
+ if (defined( 'POLYLANG_VERSION' )) {
823
+ $polylang_config = get_option('polylang');
824
+ if ($polylang_config['force_lang'] == 1) {
825
+
826
+ if(strpos($requested_url, 'language/') !== false)
827
+ $requested_url = str_replace("language/", "", $requested_url);
828
+
829
+ $remove_lang = ltrim(strstr($requested_url, '/'), '/');
830
+ if ($remove_lang != '')
831
+ return $remove_lang;
832
+ }
833
+ }
834
+
835
+ return $requested_url;
836
+ }
837
+
838
+ if (function_exists("add_action") && function_exists("add_filter")) {
839
+ add_action( 'template_redirect', 'custom_permalinks_redirect', 5 );
840
+ add_filter( 'post_link', 'custom_permalinks_post_link', 10, 3 );
841
+ add_filter( 'post_type_link', 'custom_permalinks_post_link', 10, 2 );
842
+ add_filter( 'page_link', 'custom_permalinks_page_link', 10, 2 );
843
+ add_filter( 'tag_link', 'custom_permalinks_term_link', 10, 2 );
844
+ add_filter( 'category_link', 'custom_permalinks_term_link', 10, 2 );
845
+ add_filter( 'request', 'custom_permalinks_request', 10, 1 );
846
+ add_filter( 'user_trailingslashit', 'custom_permalinks_trailingslash', 10, 2 );
847
+
848
+ if (function_exists("get_bloginfo")) {
849
+ $v = explode('.', get_bloginfo('version'));
850
+ }
851
+
852
+ if ( $v[0] >= 2 ) {
853
+ add_filter( 'get_sample_permalink_html', 'custom_permalink_get_sample_permalink_html', 10, 4 );
854
+ } else {
855
+ add_action( 'edit_form_advanced', 'custom_permalinks_post_options' );
856
+ add_action( 'edit_page_form', 'custom_permalinks_page_options' );
857
+ }
858
+
859
+ add_action( 'edit_tag_form', 'custom_permalinks_term_options' );
860
+ add_action( 'add_tag_form', 'custom_permalinks_term_options' );
861
+ add_action( 'edit_category_form', 'custom_permalinks_term_options' );
862
+ add_action( 'save_post', 'custom_permalinks_save_post' );
863
+ add_action( 'save_page', 'custom_permalinks_save_post' );
864
+ add_action( 'edited_post_tag', 'custom_permalinks_save_tag' );
865
+ add_action( 'edited_category', 'custom_permalinks_save_category' );
866
+ add_action( 'create_post_tag', 'custom_permalinks_save_tag' );
867
+ add_action( 'create_category', 'custom_permalinks_save_category' );
868
+ add_action( 'delete_post', 'custom_permalinks_delete_permalink', 10);
869
+ add_action( 'delete_post_tag', 'custom_permalinks_delete_term' );
870
+ add_action( 'delete_post_category', 'custom_permalinks_delete_term' );
871
+ add_action( 'admin_head', 'custom_permalinks_setup_admin_head' );
872
+ add_action( 'admin_menu', 'custom_permalinks_setup_admin_menu' );
873
+ }
874
+ ?>
readme.txt CHANGED
@@ -1,253 +1,257 @@
1
- === Custom Permalinks ===
2
-
3
- Contributors: sasiddiqui, michaeltyson
4
- Donate link: https://www.paypal.me/yasglobal
5
- Tags: permalink, url, link, address, custom, redirect, custom post type
6
- Requires at least: 2.6
7
- Tested up to: 4.8
8
- Stable tag: 0.9.3
9
- License: GPLv2 or later
10
- License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
-
12
- Set custom permalinks on a per-post, per-tag or per-category basis.
13
-
14
- == Description ==
15
-
16
- Lay out your site the way *you* want it. Set the URL of any post, page, tag or category to anything you want.
17
- Old permalinks will redirect properly to the new address. Custom Permalinks gives you ultimate control
18
- over your site structure.
19
-
20
- Be warned: *This plugin is not a replacement for WordPress's built-in permalink system*. Check your WordPress
21
- administration's "Permalinks" settings page first, to make sure that this doesn't already meet your needs.
22
-
23
- This plugin is only useful for assigning custom permalinks for *individual* posts, pages, tags or categories.
24
- It will not apply whole permalink structures, or automatically apply a category's custom permalink to the posts
25
- within that category.
26
-
27
- > If anyone wants the different Structure Tags for their Post types or use symbols in the URLs So, use the [Permalinks Customizer](https://wordpress.org/plugins/permalinks-customizer/) which is a fork of this plugin and contains the enhancement of this plugin.
28
-
29
- == Installation ==
30
-
31
- 1. Unzip the package, and upload `custom-permalinks` to the `/wp-content/plugins/` directory
32
- 2. Activate the plugin through the 'Plugins' menu in WordPress
33
- 3. Edit any post, page, tag or category to set a custom permalink.
34
-
35
- == Changelog ==
36
-
37
- = 0.9.3 =
38
-
39
- * Fixed PolyLang Conflicts
40
-
41
- = 0.9.2 =
42
-
43
- * Fixed WPML Conflicts
44
-
45
- = 0.9.1 =
46
-
47
- * Fixed issues of Filters and Actions (Replaces 'edit_files' with 10)
48
-
49
- = 0.9 =
50
-
51
- * Resolved the conflict with PolyLang Plugin
52
-
53
- = 0.8 =
54
-
55
- * Fixed (Draft preview issue for custom post types + some PHP Warnings)
56
-
57
- = 0.7.28 =
58
-
59
- * Fixed draft preview issue(posts + pages)
60
-
61
- = 0.7.27 =
62
-
63
- * Fixed Loop Redirecting issue
64
-
65
- = 0.7.26 =
66
-
67
- * Fixed PHP Notice issue
68
-
69
- = 0.7.25 =
70
-
71
- * Fixed draft preview issue
72
-
73
- = 0.7.24 =
74
-
75
- * Fixed a problem with page URLs
76
-
77
- = 0.7.23 =
78
-
79
- * Fixed a problem with permalinks with "/" components
80
-
81
- = 0.7.22 =
82
-
83
- * Fixed PHP warning
84
- * Fixed initial permalink display for new posts/pages
85
-
86
- = 0.7.21 =
87
-
88
- * Minor internationalization fixes
89
-
90
- = 0.7.20 =
91
-
92
- * Addressed a noisy warning
93
- * Revised addition of admin forms js (don't use is_admin())
94
- * Updated Roles and Capabilities from depreciated numerical to label capabilities (by OF-6)
95
- * Added css/html to match WP 3.5+ layout (by OF-6)
96
-
97
- = 0.7.19 =
98
-
99
- * WP 3.9 compatibility fix, thanks to Sowmedia
100
-
101
- = 0.7.18 =
102
-
103
- * Patch to address 404 errors when displaying a page/post that shares a permalink with a trashed page/post, thanks to Tor Johnson
104
-
105
- = 0.7.17 =
106
-
107
- * Patch to address SSL problems, thanks to Amin Mirzaee
108
-
109
- = 0.7.16 =
110
-
111
- * Security and compatibility fixes by Hans-Michael Varbaek of Sense of Security
112
-
113
- = 0.7.15 =
114
-
115
- * Permalinks are now case-insensitive (thanks to @ericmann)
116
-
117
- = 0.7.14 =
118
-
119
- * Delete permalinks upon page/post deletion
120
-
121
- = 0.7.13 =
122
-
123
- * Fixed issue with term permalinks not working properly on some installations
124
-
125
- = 0.7.12 =
126
-
127
- * Fixed issue with feed URLs in non-webroot blog installations
128
-
129
- = 0.7.11 =
130
-
131
- * Fixed issue with pending/draft posts with permalinks
132
- * Fixed infinite redirect issue with permalinks without trailing slash, on blogs not hosted in the webroot
133
-
134
- = 0.7.10 =
135
-
136
- * Fix for 404 error on static front page with custom permalink set, by Eric TF Bat
137
-
138
- = 0.7.9 =
139
-
140
- * Support for custom post types, by Balázs Németh
141
-
142
- = 0.7.8 =
143
-
144
- * Support for non-ASCII characters in URLs
145
- * Fixed bug where adding a new tag when saving a post with a custom permalink attaches that permalink to the new tag
146
- * Some compatibility fixes for WP 3.2.1
147
-
148
- = 0.7.7 =
149
-
150
- * Minor change to permalink saving routine to fix some possible issues
151
- * Fixed issue with %-encoded permalinks
152
-
153
- = 0.7.6 =
154
-
155
- * Fixed permalink saving issue when not using ".../%postname%" or similar permalink structure
156
-
157
- = 0.7.5 =
158
-
159
- * Fixed issue where changes to trailing "/" aren't saved
160
-
161
- = 0.7.4 =
162
-
163
- * Added support for changing post/page slug only
164
- * Fixed incorrect admin edit link
165
-
166
- = 0.7.3 =
167
-
168
- * Fix problem with /page/# URLs on WP 3.1.3
169
-
170
- = 0.7.2 =
171
-
172
- * Don't clobber query parameters when redirecting to the custom permalink from the original URL
173
-
174
- = 0.7.1 =
175
-
176
- * Compatiblity fix for last update
177
-
178
- = 0.7 =
179
-
180
- * Added support for SSL sites, thanks to Dan from todaywasawesome.com
181
-
182
- = 0.6.1 =
183
-
184
- * Fix bug causing incorrect link from "View Post"/"View Page" button in post/page editor
185
-
186
- = 0.6 =
187
-
188
- * Fix infinite redirect for permalinks ending in a / (critical fix)
189
- * Moved post/page permalinks settings to top of edit form, replacing prior permalink display
190
-
191
- = 0.5.3 =
192
-
193
- * Fix for invalid URL redirect (eg. http://domain.comfolder/file.html instead of http://domain.com/folder/file.html) when using permalinks without a trailing slash (like .../%postname%.html)
194
-
195
- = 0.5.2 =
196
-
197
- * Bugfix for matching posts when there are multiple posts that match parts of the query
198
-
199
- = 0.5.1 =
200
-
201
- * Compatibility fix for WP 2.7's tag/category pages
202
-
203
- = 0.5 =
204
-
205
- * Support for Wordpress sites in subdirectories (i.e., not located at the webroot)
206
-
207
- = 0.4.1 =
208
-
209
- * WP 2.7 compatability fixes; fix for bug encountered when publishing a draft, or reverting to draft status, and fix for placeholder permalink value for pages
210
-
211
- = 0.4 =
212
-
213
- * Support for pages, and a fix for draft posts/pages
214
-
215
- = 0.3.1 =
216
-
217
- * Discovered a typo that broke categories
218
-
219
- = 0.3 =
220
-
221
- * Largely rewritten to provide more robust handling of trailing slashes, proper support for trailing URL components (eg. paging)
222
-
223
- = 0.2.2 =
224
-
225
- * Fixed bug with not matching permalinks when / appended to the URL, and workaround for infinite redirect when another plugin is enforcing trailing /
226
-
227
- = 0.2.1 =
228
-
229
- * Better handling of trailing slashes
230
-
231
- = 0.2 =
232
-
233
- * Added 'Custom Permalinks' section under 'Manage' to show existing custom permalinks, and allow reverting to the defaults
234
-
235
- = 0.1.1 =
236
-
237
- * Fixed bug with categories
238
-
239
- == Upgrade Notice ==
240
-
241
- = 0.6.1 =
242
-
243
- * This release fixes a bug causing incorrect link from the "View Post"/"View Page" button in the editor
244
-
245
- = 0.6 =
246
-
247
- In the process of fixing one issue, version 0.5.3 broke permalinks ending with a "/". Update now to fix this, and sorry for the inconvenience!
248
-
249
- = 0.5.3 =
250
-
251
- If you are having problems with Custom Permalinks causing an invalid URL redirect (eg. http://domain.comfolder/file.html instead of http://domain.com/folder/file.html),
252
- upgrade: This has now been fixed.
253
-
 
 
 
 
1
+ === Custom Permalinks ===
2
+
3
+ Contributors: sasiddiqui, michaeltyson
4
+ Donate link: https://www.paypal.me/yasglobal
5
+ Tags: permalink, url, link, address, custom, redirect, custom post type
6
+ Requires at least: 2.6
7
+ Tested up to: 4.8
8
+ Stable tag: 1.0
9
+ License: GPLv2 or later
10
+ License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
+
12
+ Set custom permalinks on a per-post, per-tag or per-category basis.
13
+
14
+ == Description ==
15
+
16
+ Lay out your site the way *you* want it. Set the URL of any post, page, tag or category to anything you want.
17
+ Old permalinks will redirect properly to the new address. Custom Permalinks gives you ultimate control
18
+ over your site structure.
19
+
20
+ Be warned: *This plugin is not a replacement for WordPress's built-in permalink system*. Check your WordPress
21
+ administration's "Permalinks" settings page first, to make sure that this doesn't already meet your needs.
22
+
23
+ This plugin is only useful for assigning custom permalinks for *individual* posts, pages, tags or categories.
24
+ It will not apply whole permalink structures, or automatically apply a category's custom permalink to the posts
25
+ within that category.
26
+
27
+ > If anyone wants the different Structure Tags for their Post types or use symbols in the URLs So, use the [Permalinks Customizer](https://wordpress.org/plugins/permalinks-customizer/) which is a fork of this plugin and contains the enhancement of this plugin.
28
+
29
+ == Installation ==
30
+
31
+ 1. Unzip the package, and upload `custom-permalinks` to the `/wp-content/plugins/` directory
32
+ 2. Activate the plugin through the 'Plugins' menu in WordPress
33
+ 3. Edit any post, page, tag or category to set a custom permalink.
34
+
35
+ == Changelog ==
36
+
37
+ = 1.0 =
38
+
39
+ * Updated Query on the `custom_permalinks_request` Function
40
+
41
+ = 0.9.3 =
42
+
43
+ * Fixed PolyLang Conflicts
44
+
45
+ = 0.9.2 =
46
+
47
+ * Fixed WPML Conflicts
48
+
49
+ = 0.9.1 =
50
+
51
+ * Fixed issues of Filters and Actions (Replaces 'edit_files' with 10)
52
+
53
+ = 0.9 =
54
+
55
+ * Resolved the conflict with PolyLang Plugin
56
+
57
+ = 0.8 =
58
+
59
+ * Fixed (Draft preview issue for custom post types + some PHP Warnings)
60
+
61
+ = 0.7.28 =
62
+
63
+ * Fixed draft preview issue(posts + pages)
64
+
65
+ = 0.7.27 =
66
+
67
+ * Fixed Loop Redirecting issue
68
+
69
+ = 0.7.26 =
70
+
71
+ * Fixed PHP Notice issue
72
+
73
+ = 0.7.25 =
74
+
75
+ * Fixed draft preview issue
76
+
77
+ = 0.7.24 =
78
+
79
+ * Fixed a problem with page URLs
80
+
81
+ = 0.7.23 =
82
+
83
+ * Fixed a problem with permalinks with "/" components
84
+
85
+ = 0.7.22 =
86
+
87
+ * Fixed PHP warning
88
+ * Fixed initial permalink display for new posts/pages
89
+
90
+ = 0.7.21 =
91
+
92
+ * Minor internationalization fixes
93
+
94
+ = 0.7.20 =
95
+
96
+ * Addressed a noisy warning
97
+ * Revised addition of admin forms js (don't use is_admin())
98
+ * Updated Roles and Capabilities from depreciated numerical to label capabilities (by OF-6)
99
+ * Added css/html to match WP 3.5+ layout (by OF-6)
100
+
101
+ = 0.7.19 =
102
+
103
+ * WP 3.9 compatibility fix, thanks to Sowmedia
104
+
105
+ = 0.7.18 =
106
+
107
+ * Patch to address 404 errors when displaying a page/post that shares a permalink with a trashed page/post, thanks to Tor Johnson
108
+
109
+ = 0.7.17 =
110
+
111
+ * Patch to address SSL problems, thanks to Amin Mirzaee
112
+
113
+ = 0.7.16 =
114
+
115
+ * Security and compatibility fixes by Hans-Michael Varbaek of Sense of Security
116
+
117
+ = 0.7.15 =
118
+
119
+ * Permalinks are now case-insensitive (thanks to @ericmann)
120
+
121
+ = 0.7.14 =
122
+
123
+ * Delete permalinks upon page/post deletion
124
+
125
+ = 0.7.13 =
126
+
127
+ * Fixed issue with term permalinks not working properly on some installations
128
+
129
+ = 0.7.12 =
130
+
131
+ * Fixed issue with feed URLs in non-webroot blog installations
132
+
133
+ = 0.7.11 =
134
+
135
+ * Fixed issue with pending/draft posts with permalinks
136
+ * Fixed infinite redirect issue with permalinks without trailing slash, on blogs not hosted in the webroot
137
+
138
+ = 0.7.10 =
139
+
140
+ * Fix for 404 error on static front page with custom permalink set, by Eric TF Bat
141
+
142
+ = 0.7.9 =
143
+
144
+ * Support for custom post types, by Balázs Németh
145
+
146
+ = 0.7.8 =
147
+
148
+ * Support for non-ASCII characters in URLs
149
+ * Fixed bug where adding a new tag when saving a post with a custom permalink attaches that permalink to the new tag
150
+ * Some compatibility fixes for WP 3.2.1
151
+
152
+ = 0.7.7 =
153
+
154
+ * Minor change to permalink saving routine to fix some possible issues
155
+ * Fixed issue with %-encoded permalinks
156
+
157
+ = 0.7.6 =
158
+
159
+ * Fixed permalink saving issue when not using ".../%postname%" or similar permalink structure
160
+
161
+ = 0.7.5 =
162
+
163
+ * Fixed issue where changes to trailing "/" aren't saved
164
+
165
+ = 0.7.4 =
166
+
167
+ * Added support for changing post/page slug only
168
+ * Fixed incorrect admin edit link
169
+
170
+ = 0.7.3 =
171
+
172
+ * Fix problem with /page/# URLs on WP 3.1.3
173
+
174
+ = 0.7.2 =
175
+
176
+ * Don't clobber query parameters when redirecting to the custom permalink from the original URL
177
+
178
+ = 0.7.1 =
179
+
180
+ * Compatiblity fix for last update
181
+
182
+ = 0.7 =
183
+
184
+ * Added support for SSL sites, thanks to Dan from todaywasawesome.com
185
+
186
+ = 0.6.1 =
187
+
188
+ * Fix bug causing incorrect link from "View Post"/"View Page" button in post/page editor
189
+
190
+ = 0.6 =
191
+
192
+ * Fix infinite redirect for permalinks ending in a / (critical fix)
193
+ * Moved post/page permalinks settings to top of edit form, replacing prior permalink display
194
+
195
+ = 0.5.3 =
196
+
197
+ * Fix for invalid URL redirect (eg. http://domain.comfolder/file.html instead of http://domain.com/folder/file.html) when using permalinks without a trailing slash (like .../%postname%.html)
198
+
199
+ = 0.5.2 =
200
+
201
+ * Bugfix for matching posts when there are multiple posts that match parts of the query
202
+
203
+ = 0.5.1 =
204
+
205
+ * Compatibility fix for WP 2.7's tag/category pages
206
+
207
+ = 0.5 =
208
+
209
+ * Support for Wordpress sites in subdirectories (i.e., not located at the webroot)
210
+
211
+ = 0.4.1 =
212
+
213
+ * WP 2.7 compatability fixes; fix for bug encountered when publishing a draft, or reverting to draft status, and fix for placeholder permalink value for pages
214
+
215
+ = 0.4 =
216
+
217
+ * Support for pages, and a fix for draft posts/pages
218
+
219
+ = 0.3.1 =
220
+
221
+ * Discovered a typo that broke categories
222
+
223
+ = 0.3 =
224
+
225
+ * Largely rewritten to provide more robust handling of trailing slashes, proper support for trailing URL components (eg. paging)
226
+
227
+ = 0.2.2 =
228
+
229
+ * Fixed bug with not matching permalinks when / appended to the URL, and workaround for infinite redirect when another plugin is enforcing trailing /
230
+
231
+ = 0.2.1 =
232
+
233
+ * Better handling of trailing slashes
234
+
235
+ = 0.2 =
236
+
237
+ * Added 'Custom Permalinks' section under 'Manage' to show existing custom permalinks, and allow reverting to the defaults
238
+
239
+ = 0.1.1 =
240
+
241
+ * Fixed bug with categories
242
+
243
+ == Upgrade Notice ==
244
+
245
+ = 0.6.1 =
246
+
247
+ * This release fixes a bug causing incorrect link from the "View Post"/"View Page" button in the editor
248
+
249
+ = 0.6 =
250
+
251
+ In the process of fixing one issue, version 0.5.3 broke permalinks ending with a "/". Update now to fix this, and sorry for the inconvenience!
252
+
253
+ = 0.5.3 =
254
+
255
+ If you are having problems with Custom Permalinks causing an invalid URL redirect (eg. http://domain.comfolder/file.html instead of http://domain.com/folder/file.html),
256
+ upgrade: This has now been fixed.
257
+