Custom Permalinks - Version 1.2

Version Description

  • Enhancements
    • Added Filter to Exclude/Ignore URL to be processed
    • Added Translation Capability
    • Split the Code using OOPS Concept to improve performance and applied the filters according to the need
    • Removed some unnecessary filters
    • Bugs
    • Fixed Vulnerability Issues
Download this release

Release Info

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

Code changes from version 1.1 to 1.2

admin/class-custom-permalinks-admin.php CHANGED
@@ -1,395 +1,404 @@
1
  <?php
2
-
3
  /**
4
  * @package CustomPermalinks\Admin
5
  */
6
 
7
  class Custom_Permalinks_Admin {
8
-
9
  /**
10
  * Initializes WordPress hooks
11
  */
12
  function __construct() {
13
- add_action( 'admin_menu', array($this, 'custom_permalinks_menu') );
14
- }
15
 
16
  /**
17
  * Added Pages in Menu for Settings
18
  */
19
  public function custom_permalinks_menu() {
20
- add_menu_page( 'PostTypes Permalinks', 'Custom Permalinks', 'administrator', 'custom-permalinks-post-permalinks', array($this,'custom_permalinks_post_permalinks'), 'dashicons-admin-links' );
21
- add_submenu_page( 'custom-permalinks-post-permalinks', 'PostTypes Permalinks', 'PostTypes Permalinks', 'administrator', 'custom-permalinks-post-permalinks', array($this, 'custom_permalinks_post_permalinks') );
22
- add_submenu_page( 'custom-permalinks-post-permalinks', 'Category Permalinks', 'Category Permalinks', 'administrator', 'custom-permalinks-category-permalinks', array($this, 'custom_permalinks_category_permalinks') );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  }
24
 
25
- /**
26
- * Shows all the Permalinks created by using this Plugin with Pager and Search Functionality of Posts/Pages
27
- */
28
- public function custom_permalinks_post_permalinks() {
29
- global $wpdb;
30
- $filter_options = '';
31
- $search_permalink = '';
32
- $html = '';
33
-
34
- // Handle Bulk Operations
35
- if ( (isset($_POST['action']) && $_POST['action'] == 'delete') || (isset($_POST['action2']) && $_POST['action2'] == 'delete') && isset($_POST['permalink']) && !empty($_POST['permalink']) ) {
36
- $post_ids = implode(', ', $_POST['permalink']);
37
- $wpdb->query("DELETE FROM $wpdb->postmeta WHERE post_id IN ($post_ids) AND meta_key = 'custom_permalink'");
38
- }
39
- $html .= '<div class="wrap">
40
- <h1 class="wp-heading-inline">'.__('PostTypes Permalinks', 'custom-permalinks').'</h1>';
41
-
42
- $search_value = '';
43
- if (isset($_GET['s']) && !empty($_GET['s'])) {
44
- $filter_permalink = 'AND pm.meta_value LIKE "%'.$_GET['s'].'%"';
45
- $search_permalink = '&s='.$_GET['s'].'';
46
- $html .= '<span class="subtitle">Search results for "'.$_GET['s'].'"</span>';
47
- $search_value = htmlspecialchars($_GET['s']);
48
- }
49
- $page_limit = 'LIMIT 0, 20';
50
- if (isset($_GET['paged']) && is_numeric($_GET['paged']) && $_GET['paged'] > 1) {
51
- $pager = 20 * ($_GET['paged'] - 1);
52
- $page_limit = 'LIMIT '.$pager.', 20';
53
- }
54
- $sorting_by = 'ORDER By p.ID DESC';
55
- $order_by = 'asc';
56
- $order_by_class = 'desc';
57
- if (isset($_GET['orderby']) && $_GET['orderby'] == 'title') {
58
- $filter_options .= '<input type="hidden" name="orderby" value="title" />';
59
- if (isset($_GET['order']) && $_GET['order'] == 'desc') {
60
- $sorting_by = 'ORDER By p.post_title DESC';
61
- $order_by = 'asc';
62
- $order_by_class = 'desc';
63
- $filter_options .= '<input type="hidden" name="order" value="desc" />';
64
- } else {
65
- $sorting_by = 'ORDER By p.post_title';
66
- $order_by = 'desc';
67
- $order_by_class = 'asc';
68
- $filter_options .= '<input type="hidden" name="order" value="asc" />';
69
- }
70
- }
71
- $count_query = "SELECT COUNT(p.ID) AS total_permalinks FROM $wpdb->posts AS p LEFT JOIN $wpdb->postmeta AS pm ON (p.ID = pm.post_id) WHERE pm.meta_key = 'custom_permalink' AND pm.meta_value != '' ". $filter_permalink ."";
72
- $count_posts = $wpdb->get_row($count_query);
73
-
74
- $html .= '<form action="'.$_SERVER["REQUEST_URI"].'" method="get">';
75
- $html .= '<p class="search-box">';
76
- $html .= '<input type="hidden" name="page" value="custom-permalinks-post-permalinks" />';
77
- $html .= $filter_options;
78
- $html .= '<label class="screen-reader-text" for="custom-permalink-search-input">Search Custom Permalink:</label>';
79
- $html .= '<input type="search" id="custom-permalink-search-input" name="s" value="'. $search_value .'">';
80
- $html .= '<input type="submit" id="search-submit" class="button" value="Search Permalink"></p>';
81
- $html .= '</form>';
82
- $html .= '<form action="'.$_SERVER["REQUEST_URI"].'" method="post">';
83
- $html .= '<div class="tablenav top">';
84
- $html .= '<div class="alignleft actions bulkactions">
85
- <label for="bulk-action-selector-top" class="screen-reader-text">Select bulk action</label>
86
- <select name="action" id="bulk-action-selector-top">
87
- <option value="-1">'. __("Bulk Actions", "custom-permalinks") .'</option>
88
- <option value="delete">'. __("Delete Permalinks", "custom-permalinks") .'</option>
89
- </select>
90
- <input type="submit" id="doaction" class="button action" value="Apply">
91
- </div>';
92
-
93
- $posts = 0;
94
- if (isset($count_posts->total_permalinks) && $count_posts->total_permalinks > 0) {
95
-
96
- $html .= '<h2 class="screen-reader-text">Custom Permalink navigation</h2>';
97
-
98
- $query = "SELECT p.ID, p.post_title, p.post_type, pm.meta_value FROM $wpdb->posts AS p LEFT JOIN $wpdb->postmeta AS pm ON (p.ID = pm.post_id) WHERE pm.meta_key = 'custom_permalink' AND pm.meta_value != '' ". $filter_permalink ." ". $sorting_by ." ". $page_limit ."";
99
- $posts = $wpdb->get_results($query);
100
-
101
- $pagination_html = '';
102
- $total_pages = ceil($count_posts->total_permalinks / 20);
103
- if (isset($_GET['paged']) && is_numeric($_GET['paged']) && $_GET['paged'] > 0) {
104
- $pagination_html = $this->custom_permalinks_pager($count_posts->total_permalinks, $_GET['paged'], $total_pages);
105
- if ( $_GET['paged'] > $total_pages ) {
106
- $redirect_uri = explode('&paged='. $_GET['paged'] .'', $_SERVER['REQUEST_URI']);
107
- header('Location: ' . $redirect_uri[0], 301);
108
- exit();
109
- }
110
- } else if (!isset($_GET['paged'])) {
111
- $pagination_html = $this->custom_permalinks_pager($count_posts->total_permalinks, 1, $total_pages);
112
- }
113
-
114
- $html .= $pagination_html;
115
- }
116
- $table_navigation = $this->custom_permalink_tablenav_posts($order_by_class, $order_by, $search_permalink);
117
-
118
- $html .= '</div>';
119
- $html .= '<table class="wp-list-table widefat fixed striped posts">
120
- <thead>'. $table_navigation .'</thead>
121
- <tbody>';
122
- if ($posts != 0 && !empty($posts)) {
123
- foreach ( $posts as $post ) {
124
- $html .= '<tr valign="top">';
125
- $html .= '<th scope="row" class="check-column"><input type="checkbox" name="permalink[]" value="'.$post->ID.'" /></th>';
126
- $html .= '<td><strong><a class="row-title" href="post.php?action=edit&post='. $post->ID .'">'. $post->post_title .'</a></strong></td>';
127
- $html .= '<td>'. ucwords( $post->post_type ).'</td>';
128
- $html .= '<td><a href="/'.$post->meta_value.'" target="_blank" title="'.__("Visit ".$post->post_title, "custom-permalinks").'">/'. urldecode($post->meta_value) .'</a></td></tr>';
129
- }
130
- } else {
131
- $html .= '<tr class="no-items"><td class="colspanchange" colspan="10">No permalinks found.</td></tr>';
132
- }
133
- $html .= '</tbody>
134
- <tfoot>'. $table_navigation .'</tfoot>
135
- </table>';
136
-
137
- $html .= '<div class="tablenav bottom">
138
- <div class="alignleft actions bulkactions">
139
- <label for="bulk-action-selector-bottom" class="screen-reader-text">Select bulk action</label>
140
- <select name="action2" id="bulk-action-selector-bottom">
141
- <option value="-1">'. __("Bulk Actions", "custom-permalinks") .'</option>
142
- <option value="delete">'. __("Delete Permalinks", "custom-permalinks") .'</option>
143
- </select>
144
- <input type="submit" id="doaction2" class="button action" value="Apply">
145
- </div>
146
- '. $pagination_html .'
147
- </div>';
148
- $html .= '</form>
149
- </div>';
150
- echo $html;
151
- }
152
-
153
- /**
154
- * Return the Navigation row HTML same as Default Posts page for PostTypes
155
- */
156
- private function custom_permalink_tablenav_posts($order_by_class, $order_by, $search_permalink) {
157
- $nav = '<tr>
158
- <td id="cb" class="manage-column column-cb check-column"><label class="screen-reader-text" for="cb-select-all-1">Select All</label><input id="cb-select-all-1" type="checkbox"></td>
159
- <th scope="col" id="title" class="manage-column column-title column-primary sortable '. $order_by_class .'"><a href="/wp-admin/admin.php?page=custom-permalinks-post-permalinks&amp;orderby=title&amp;order='. $order_by . $search_permalink .'"><span>'.__("Title", "custom-permalinks").'</span><span class="sorting-indicator"></span></a></th>
160
- <th scope="col">'.__("Type", "custom-permalinks").'</th>
161
- <th scope="col">'.__("Permalink", "custom-permalinks").'</th>
162
- </tr>';
163
- return $nav;
164
- }
165
-
166
- /**
167
- * Shows all the Permalinks created by using this Plugin with Pager and Search Functionality of Category/Tags
168
- */
169
- public function custom_permalinks_category_permalinks() {
170
-
171
- $search_permalink = '';
172
- $html = '';
173
-
174
- // Handle Bulk Operations
175
- if ( (isset($_POST['action']) && $_POST['action'] == 'delete') || (isset($_POST['action2']) && $_POST['action2'] == 'delete') && isset($_POST['permalink']) && !empty($_POST['permalink']) ) {
176
- $remove_perm = $_POST['permalink'];
177
- $data = get_option('custom_permalink_table');
178
- if ( isset($data) && is_array($data) ) {
179
- $i = 0;
180
- foreach ( $data as $link => $info ) {
181
- if ( in_array($info['id'], $remove_perm) ) {
182
- unset($data[$link]);
183
- unset($remove_perm[$i]);
184
- if ( !is_array($remove_perm) || empty($remove_perm) )
185
- break;
186
- }
187
- $i++;
188
- }
189
- }
190
- update_option('custom_permalink_table', $data);
191
- }
192
- $html .= '<div class="wrap">
193
- <h1 class="wp-heading-inline">'.__('Category/Tags Permalinks', 'custom-permalinks').'</h1>';
194
-
195
- $search_value = '';
196
- if (isset($_GET['s']) && !empty($_GET['s'])) {
197
- $search_permalink = '&s='.$_GET['s'].'';
198
- $html .= '<span class="subtitle">Search results for "'.$_GET['s'].'"</span>';
199
- $search_value = htmlspecialchars($_GET['s']);
200
- }
201
- $pager_offset = '0';
202
- $page_limit = 20;
203
- if (isset($_GET['paged']) && is_numeric($_GET['paged']) && $_GET['paged'] > 1) {
204
- $pager_offset = 20 * ($_GET['paged'] - 1);
205
- $page_limit = $pager_offset + 20;
206
- }
207
- $html .= '<form action="'. $_SERVER["REQUEST_URI"] .'" method="get">';
208
- $html .= '<p class="search-box">';
209
- $html .= '<input type="hidden" name="page" value="custom-permalinks-category-permalinks" />';
210
- $html .= '<label class="screen-reader-text" for="custom-permalink-search-input">Search Custom Permalink:</label>';
211
- $html .= '<input type="search" id="custom-permalink-search-input" name="s" value="'. $search_value .'">';
212
- $html .= '<input type="submit" id="search-submit" class="button" value="Search Permalink"></p>';
213
- $html .= '</form>';
214
- $html .= '<form action="'. $_SERVER["REQUEST_URI"] .'" method="post">';
215
- $html .= '<div class="tablenav top">';
216
- $html .= '<div class="alignleft actions bulkactions">
217
- <label for="bulk-action-selector-top" class="screen-reader-text">Select bulk action</label>
218
- <select name="action" id="bulk-action-selector-top">
219
- <option value="-1">'. __("Bulk Actions", "custom-permalinks") .'</option>
220
- <option value="delete">'. __("Delete Permalinks", "custom-permalinks") .'</option>
221
- </select>
222
- <input type="submit" id="doaction" class="button action" value="Apply">
223
- </div>';
224
-
225
- $posts = 0;
226
- $table = get_option('custom_permalink_table');
227
- $count_tags = count($table);
228
- if ( isset($table) && is_array($table) && $count_tags > 0) {
229
-
230
- $filtered = array();
231
- if ($search_value != '') {
232
- foreach($table as $key => $value) {
233
- if(preg_match('/'. $search_value .'/',$key)) {
234
- $filtered[$key] = $value;
235
- }
236
- }
237
- $table = $filtered;
238
- $count_tags = count($table);
239
- }
240
-
241
- $html .= '<h2 class="screen-reader-text">Custom Permalink navigation</h2>';
242
-
243
- $pagination_html = '';
244
- $total_pages = ceil($count_tags / 20);
245
- if (isset($_GET['paged']) && is_numeric($_GET['paged']) && $_GET['paged'] > 0) {
246
- $pagination_html = $this->custom_permalinks_pager($count_tags, $_GET['paged'], $total_pages);
247
- if ( $_GET['paged'] > $total_pages ) {
248
- $redirect_uri = explode('&paged='. $_GET['paged'] .'', $_SERVER['REQUEST_URI']);
249
- header('Location: ' . $redirect_uri[0], 301);
250
- exit();
251
- }
252
- } else if (!isset($_GET['paged'])) {
253
- $pagination_html = $this->custom_permalinks_pager($count_tags, 1, $total_pages);
254
- }
255
-
256
- $html .= $pagination_html;
257
- }
258
- $table_navigation = $this->custom_permalink_tablenav_category($search_permalink);
259
-
260
- $html .= '</div>';
261
- $html .= '<table class="wp-list-table widefat fixed striped posts">
262
- <thead>'. $table_navigation .'</thead>
263
- <tbody>';
264
-
265
- if ( $table && is_array($table) && $count_tags > 0) {
266
- uasort($table, array('Custom_Permalinks_Admin', 'custom_permalinks_sort_array'));
267
- $i = -1;
268
- foreach ( $table as $permalink => $info ) {
269
- $i++;
270
- if ($i < $pager_offset)
271
- continue;
272
-
273
- if ($i >= $page_limit)
274
- break;
275
-
276
- $type = $info['kind'] == 'tag' ? 'post_tag' : 'category';
277
- $term = get_term($info['id'], $type);
278
- $html .= '<tr valign="top">';
279
- $html .= '<th scope="row" class="check-column"><input type="checkbox" name="permalink[]" value="'. $info['id'] .'" /></th>';
280
- $html .= '<td><strong><a class="row-title" href="edit-tags.php?action=edit&taxonomy='. $type .'&tag_ID='. $info['id'] .' ">'. $term->name .'</a></strong></td>';
281
- $html .= '<td>'. ucwords( $info['kind'] ) .'</td>';
282
- $html .= '<td><a href="/'. $permalink .'" target="_blank" title="'.__("Visit ". $term->name, "custom-permalinks").'">/'. $permalink .'</a></td></tr>';
283
- }
284
- } else {
285
- $html .= '<tr class="no-items"><td class="colspanchange" colspan="10">No permalinks found.</td></tr>';
286
- }
287
- $html .= '</tbody>
288
- <tfoot>'. $table_navigation .'</tfoot>
289
- </table>';
290
-
291
- $html .= '<div class="tablenav bottom">
292
- <div class="alignleft actions bulkactions">
293
- <label for="bulk-action-selector-bottom" class="screen-reader-text">Select bulk action</label>
294
- <select name="action2" id="bulk-action-selector-bottom">
295
- <option value="-1">'. __("Bulk Actions", "custom-permalinks") .'</option>
296
- <option value="delete">'. __("Delete Permalinks", "custom-permalinks") .'</option>
297
- </select>
298
- <input type="submit" id="doaction2" class="button action" value="Apply">
299
- </div>
300
- '. $pagination_html .'
301
- </div>';
302
- $html .= '</form>
303
- </div>';
304
- echo $html;
305
- }
306
-
307
- /**
308
- * Sort the terms array in desc order using term id
309
- */
310
- private static function custom_permalinks_sort_array($a, $b) {
311
- return $b['id'] - $a['id'];
312
- }
313
-
314
- /**
315
- * Return the Navigation row HTML same as Default Posts page for Category
316
- */
317
- private function custom_permalink_tablenav_category($search_permalink) {
318
- $nav = '<tr>
319
- <td id="cb" class="manage-column column-cb check-column"><label class="screen-reader-text" for="cb-select-all-1">Select All</label><input id="cb-select-all-1" type="checkbox"></td>
320
- <th scope="col" id="title" class="manage-column column-title column-primary">'. __("Title", "custom-permalinks") .'</th>
321
- <th scope="col">'.__("Type", "custom-permalinks").'</th>
322
- <th scope="col">'.__("Permalink", "custom-permalinks").'</th>
323
- </tr>';
324
- return $nav;
325
- }
326
-
327
- /**
328
- * Return the Pager HTML
329
- */
330
- private function custom_permalinks_pager($total_permalinks, $current_pager_value = 1, $total_pager = 0) {
331
-
332
- if ($total_pager == 0) return;
333
-
334
- if ($total_pager == 1) {
335
- $pagination_html = '<div class="tablenav-pages one-page">
336
- <span class="displaying-num">'.$total_permalinks.' items</span>
337
- </div>';
338
- return $pagination_html;
339
- }
340
-
341
- $remove_pager_uri = explode('&paged='. $current_pager_value .'', $_SERVER['REQUEST_URI']);
342
- $pagination_html = '<div class="tablenav-pages">
343
- <span class="displaying-num">'.$total_permalinks.' items</span>
344
- <span class="pagination-links">';
345
-
346
- if ( $current_pager_value == 1 ) {
347
- $pagination_html .= '<span class="tablenav-pages-navspan" aria-hidden="true">&laquo; </span>
348
- <span class="tablenav-pages-navspan" aria-hidden="true">&lsaquo; </span>';
349
- } else {
350
- $prev_page = $current_pager_value - 1;
351
- if ($prev_page == 1) {
352
- $pagination_html .= '<span class="tablenav-pages-navspan" aria-hidden="true">&laquo;</span>';
353
- } else {
354
- $pagination_html .= ' <a href="'. $remove_pager_uri[0] .'&paged=1" title="First page" class="first-page">
355
- <span class="screen-reader-text">First page</span>
356
- <span aria-hidden="true">&laquo;</span>
357
- </a> ';
358
- }
359
- $pagination_html .= ' <a href="'. $remove_pager_uri[0] .'&paged='. $prev_page .'" title="Previous page" class="prev-page">
360
- <span class="screen-reader-text">Previous page</span>
361
- <span aria-hidden="true">&lsaquo;</span>
362
- </a> ';
363
- }
364
-
365
- $pagination_html .= '<span class="paging-input">
366
- <label for="current-page-selector" class="screen-reader-text">Current Page</label>
367
- <input class="current-page" id="current-page-selector" type="text" name="paged" value="'. $current_pager_value .'" size="1" aria-describedby="table-paging" />
368
- <span class="tablenav-paging-text"> of <span class="total-pages">'. $total_pager .' </span> </span>
369
- </span>';
370
-
371
- if ( $current_pager_value == $total_pager ) {
372
- $pagination_html .= '<span class="tablenav-pages-navspan" aria-hidden="true">&rsaquo; </span>
373
- <span class="tablenav-pages-navspan" aria-hidden="true">&raquo; </span>';
374
- } else {
375
- $next_page = $current_pager_value + 1;
376
- $pagination_html .= ' <a href="'. $remove_pager_uri[0] .'&paged='. $next_page .'" title="Next page" class="next-page">
377
- <span class="screen-reader-text">Next page</span>
378
- <span aria-hidden="true">&rsaquo;</span>
379
- </a> ';
380
- if ( $total_pager == $next_page) {
381
- $pagination_html .= '<span class="tablenav-pages-navspan" aria-hidden="true">&raquo;</span>';
382
- } else {
383
- $pagination_html .= ' <a href="'. $remove_pager_uri[0] .'&paged='. $total_pager .'" title="Last page" class="last-page">
384
- <span class="screen-reader-text">Last page</span>
385
- <span aria-hidden="true">&raquo;</span>
386
- </a> ';
387
- }
388
-
389
- }
390
- $pagination_html .= '</span></div>';
391
-
392
- return $pagination_html;
393
- }
394
-
395
  }
1
  <?php
 
2
  /**
3
  * @package CustomPermalinks\Admin
4
  */
5
 
6
  class Custom_Permalinks_Admin {
7
+
8
  /**
9
  * Initializes WordPress hooks
10
  */
11
  function __construct() {
12
+ add_action( 'admin_menu', array( $this, 'custom_permalinks_menu' ) );
13
+ }
14
 
15
  /**
16
  * Added Pages in Menu for Settings
17
  */
18
  public function custom_permalinks_menu() {
19
+ add_menu_page( 'PostTypes Permalinks', 'Custom Permalinks', 'administrator', 'custom-permalinks-post-permalinks', array( $this,'custom_permalinks_post_permalinks' ), 'dashicons-admin-links' );
20
+ add_submenu_page( 'custom-permalinks-post-permalinks', 'PostTypes Permalinks', 'PostTypes Permalinks', 'administrator', 'custom-permalinks-post-permalinks', array( $this, 'custom_permalinks_post_permalinks' ) );
21
+ add_submenu_page( 'custom-permalinks-post-permalinks', 'Category Permalinks', 'Category Permalinks', 'administrator', 'custom-permalinks-category-permalinks', array( $this, 'custom_permalinks_category_permalinks' ) );
22
+ }
23
+
24
+ /**
25
+ * Shows all the Permalinks created by using this Plugin with Pager and Search Functionality of Posts/Pages
26
+ */
27
+ public function custom_permalinks_post_permalinks() {
28
+ global $wpdb;
29
+ $filter_options = '';
30
+ $search_permalink = '';
31
+ $html = '';
32
+ $error = '';
33
+
34
+ // Handle Bulk Operations
35
+ if ( ( isset( $_POST['action'] ) && $_POST['action'] == 'delete' )
36
+ || ( isset( $_POST['action2'] ) && $_POST['action2'] == 'delete' )
37
+ && isset( $_POST['permalink'] ) && !empty( $_POST['permalink'] ) ) {
38
+ $post_ids = implode( ',', $_POST['permalink'] );
39
+ if ( preg_match( '/^\d+(?:,\d+)*$/', $post_ids ) ) {
40
+ $wpdb->query( "DELETE FROM $wpdb->postmeta WHERE post_id IN ($post_ids) AND meta_key = 'custom_permalink'" );
41
+ } else {
42
+ $error = '<div id="message" class="error"><p>' . __( 'There is some error to proceed your request. Please retry with your request or contact to the plugin author.', 'custom-permalinks' ) . '</p></div>';
43
+ }
44
+ }
45
+ $html .= '<div class="wrap">
46
+ <h1 class="wp-heading-inline">' . __( 'PostTypes Permalinks', 'custom-permalinks' ) . '</h1>';
47
+ $html .= $error;
48
+
49
+ $search_value = '';
50
+ if ( isset( $_GET['s'] ) && ! empty( $_GET['s'] ) ) {
51
+ $filter_permalink = 'AND pm.meta_value LIKE "%' . $_GET['s'] . '%"';
52
+ $search_permalink = '&s=' . $_GET['s'] . '';
53
+ $search_value = ltrim( htmlspecialchars( $_GET['s'] ), '/' );
54
+ $html .= '<span class="subtitle">Search results for "' . $search_value . '"</span>';
55
+ }
56
+ $page_limit = 'LIMIT 0, 20';
57
+ if ( isset( $_GET['paged'] ) && is_numeric( $_GET['paged'] ) && $_GET['paged'] > 1 ) {
58
+ $pager = 20 * ( $_GET['paged'] - 1 );
59
+ $page_limit = 'LIMIT ' . $pager . ', 20';
60
+ }
61
+ $sorting_by = 'ORDER By p.ID DESC';
62
+ $order_by = 'asc';
63
+ $order_by_class = 'desc';
64
+ if ( isset( $_GET['orderby'] ) && $_GET['orderby'] == 'title' ) {
65
+ $filter_options .= '<input type="hidden" name="orderby" value="title" />';
66
+ if ( isset( $_GET['order'] ) && $_GET['order'] == 'desc' ) {
67
+ $sorting_by = 'ORDER By p.post_title DESC';
68
+ $order_by = 'asc';
69
+ $order_by_class = 'desc';
70
+ $filter_options .= '<input type="hidden" name="order" value="desc" />';
71
+ } else {
72
+ $sorting_by = 'ORDER By p.post_title';
73
+ $order_by = 'desc';
74
+ $order_by_class = 'asc';
75
+ $filter_options .= '<input type="hidden" name="order" value="asc" />';
76
+ }
77
+ }
78
+ $count_query = "SELECT COUNT(p.ID) AS total_permalinks FROM $wpdb->posts AS p LEFT JOIN $wpdb->postmeta AS pm ON (p.ID = pm.post_id) WHERE pm.meta_key = 'custom_permalink' AND pm.meta_value != '' " . $filter_permalink . "";
79
+ $count_posts = $wpdb->get_row( $count_query );
80
+
81
+ $html .= '<form action="' . $_SERVER["REQUEST_URI"] . '" method="get">';
82
+ $html .= '<p class="search-box">';
83
+ $html .= '<input type="hidden" name="page" value="custom-permalinks-post-permalinks" />';
84
+ $html .= $filter_options;
85
+ $html .= '<label class="screen-reader-text" for="custom-permalink-search-input">Search Custom Permalink:</label>';
86
+ $html .= '<input type="search" id="custom-permalink-search-input" name="s" value="' . $search_value . '">';
87
+ $html .= '<input type="submit" id="search-submit" class="button" value="Search Permalink"></p>';
88
+ $html .= '</form>';
89
+ $html .= '<form action="' . $_SERVER["REQUEST_URI"] . '" method="post">';
90
+ $html .= '<div class="tablenav top">';
91
+ $html .= '<div class="alignleft actions bulkactions">
92
+ <label for="bulk-action-selector-top" class="screen-reader-text">Select bulk action</label>
93
+ <select name="action" id="bulk-action-selector-top">
94
+ <option value="-1">' . __( "Bulk Actions", "custom-permalinks" ) . '</option>
95
+ <option value="delete">' . __( "Delete Permalinks", "custom-permalinks" ) . '</option>
96
+ </select>
97
+ <input type="submit" id="doaction" class="button action" value="Apply">
98
+ </div>';
99
+
100
+ $posts = 0;
101
+ if ( isset( $count_posts->total_permalinks ) && $count_posts->total_permalinks > 0 ) {
102
+
103
+ $html .= '<h2 class="screen-reader-text">Custom Permalink navigation</h2>';
104
+
105
+ $query = "SELECT p.ID, p.post_title, p.post_type, pm.meta_value FROM $wpdb->posts AS p LEFT JOIN $wpdb->postmeta AS pm ON (p.ID = pm.post_id) WHERE pm.meta_key = 'custom_permalink' AND pm.meta_value != '' " . $filter_permalink . " " . $sorting_by . " " . $page_limit . "";
106
+ $posts = $wpdb->get_results( $query );
107
+
108
+ $pagination_html = '';
109
+ $total_pages = ceil( $count_posts->total_permalinks / 20 );
110
+ if ( isset( $_GET['paged'] ) && is_numeric( $_GET['paged'] ) && $_GET['paged'] > 0 ) {
111
+ $pagination_html = $this->custom_permalinks_pager( $count_posts->total_permalinks, $_GET['paged'], $total_pages );
112
+ if ( $_GET['paged'] > $total_pages ) {
113
+ $redirect_uri = explode( '&paged=' . $_GET['paged'] . '', $_SERVER['REQUEST_URI'] );
114
+ header( 'Location: ' . $redirect_uri[0], 301 );
115
+ exit();
116
+ }
117
+ } elseif ( ! isset( $_GET['paged'] ) ) {
118
+ $pagination_html = $this->custom_permalinks_pager( $count_posts->total_permalinks, 1, $total_pages );
119
+ }
120
+
121
+ $html .= $pagination_html;
122
+ }
123
+ $table_navigation = $this->custom_permalink_tablenav_posts( $order_by_class, $order_by, $search_permalink );
124
+
125
+ $html .= '</div>';
126
+ $html .= '<table class="wp-list-table widefat fixed striped posts">
127
+ <thead>' . $table_navigation . '</thead>
128
+ <tbody>';
129
+ if ( $posts != 0 && ! empty( $posts ) ) {
130
+ foreach ( $posts as $post ) {
131
+ $html .= '<tr valign="top">';
132
+ $html .= '<th scope="row" class="check-column"><input type="checkbox" name="permalink[]" value="' . $post->ID . '" /></th>';
133
+ $html .= '<td><strong><a class="row-title" href="post.php?action=edit&post=' . $post->ID . '">' . $post->post_title . '</a></strong></td>';
134
+ $html .= '<td>' . ucwords( $post->post_type ) . '</td>';
135
+ $html .= '<td><a href="/' . $post->meta_value . '" target="_blank" title="' . __( "Visit " . $post->post_title, "custom-permalinks" ) . '">/' . urldecode( $post->meta_value ) . '</a></td></tr>';
136
+ }
137
+ } else {
138
+ $html .= '<tr class="no-items"><td class="colspanchange" colspan="10">No permalinks found.</td></tr>';
139
+ }
140
+ $html .= '</tbody>
141
+ <tfoot>' . $table_navigation . '</tfoot>
142
+ </table>';
143
+
144
+ $html .= '<div class="tablenav bottom">
145
+ <div class="alignleft actions bulkactions">
146
+ <label for="bulk-action-selector-bottom" class="screen-reader-text">Select bulk action</label>
147
+ <select name="action2" id="bulk-action-selector-bottom">
148
+ <option value="-1">' . __( "Bulk Actions", "custom-permalinks" ) . '</option>
149
+ <option value="delete">' . __( "Delete Permalinks", "custom-permalinks" ) . '</option>
150
+ </select>
151
+ <input type="submit" id="doaction2" class="button action" value="Apply">
152
+ </div>
153
+ ' . $pagination_html . '
154
+ </div>';
155
+ $html .= '</form>
156
+ </div>';
157
+ echo $html;
158
+ }
159
+
160
+ /**
161
+ * Return the Navigation row HTML same as Default Posts page for PostTypes
162
+ */
163
+ private function custom_permalink_tablenav_posts( $order_by_class, $order_by, $search_permalink ) {
164
+ $nav = '<tr>
165
+ <td id="cb" class="manage-column column-cb check-column"><label class="screen-reader-text" for="cb-select-all-1">Select All</label><input id="cb-select-all-1" type="checkbox"></td>
166
+ <th scope="col" id="title" class="manage-column column-title column-primary sortable ' . $order_by_class . '"><a href="/wp-admin/admin.php?page=custom-permalinks-post-permalinks&amp;orderby=title&amp;order=' . $order_by . $search_permalink . '"><span>' . __( "Title", "custom-permalinks" ) . '</span><span class="sorting-indicator"></span></a></th>
167
+ <th scope="col">' . __( "Type", "custom-permalinks" ) . '</th>
168
+ <th scope="col">' . __( "Permalink", "custom-permalinks" ) . '</th>
169
+ </tr>';
170
+ return $nav;
171
+ }
172
+
173
+ /**
174
+ * Shows all the Permalinks created by using this Plugin with Pager and Search Functionality of Category/Tags
175
+ */
176
+ public function custom_permalinks_category_permalinks() {
177
+
178
+ $search_permalink = '';
179
+ $html = '';
180
+
181
+ // Handle Bulk Operations
182
+ if ( ( isset( $_POST['action'] ) && $_POST['action'] == 'delete' )
183
+ || ( isset( $_POST['action2'] ) && $_POST['action2'] == 'delete' )
184
+ && isset( $_POST['permalink'] ) && ! empty( $_POST['permalink'] ) ) {
185
+ $remove_perm = $_POST['permalink'];
186
+ $data = get_option( 'custom_permalink_table' );
187
+ if ( isset( $data ) && is_array( $data ) ) {
188
+ $i = 0;
189
+ foreach ( $data as $link => $info ) {
190
+ if ( in_array( $info['id'], $remove_perm ) ) {
191
+ unset( $data[$link] );
192
+ unset( $remove_perm[$i] );
193
+ if ( ! is_array( $remove_perm ) || empty( $remove_perm ) )
194
+ break;
195
+ }
196
+ $i++;
197
+ }
198
+ }
199
+ update_option( 'custom_permalink_table', $data );
200
+ }
201
+ $html .= '<div class="wrap">
202
+ <h1 class="wp-heading-inline">' . __( 'Category/Tags Permalinks', 'custom-permalinks' ) . '</h1>';
203
+
204
+ $search_value = '';
205
+ if ( isset( $_GET['s'] ) && ! empty( $_GET['s'] ) ) {
206
+ $search_permalink = '&s=' . $_GET['s'] . '';
207
+ $search_value = ltrim( htmlspecialchars( $_GET['s'] ), '/' );
208
+ $html .= '<span class="subtitle">Search results for "' . $search_value . '"</span>';
209
+ }
210
+ $pager_offset = '0';
211
+ $page_limit = 20;
212
+ if ( isset( $_GET['paged'] ) && is_numeric( $_GET['paged'] ) && $_GET['paged'] > 1 ) {
213
+ $pager_offset = 20 * ( $_GET['paged'] - 1 );
214
+ $page_limit = $pager_offset + 20;
215
+ }
216
+ $html .= '<form action="' . $_SERVER["REQUEST_URI"] . '" method="get">';
217
+ $html .= '<p class="search-box">';
218
+ $html .= '<input type="hidden" name="page" value="custom-permalinks-category-permalinks" />';
219
+ $html .= '<label class="screen-reader-text" for="custom-permalink-search-input">Search Custom Permalink:</label>';
220
+ $html .= '<input type="search" id="custom-permalink-search-input" name="s" value="' . $search_value . '">';
221
+ $html .= '<input type="submit" id="search-submit" class="button" value="Search Permalink"></p>';
222
+ $html .= '</form>';
223
+ $html .= '<form action="' . $_SERVER["REQUEST_URI"] . '" method="post">';
224
+ $html .= '<div class="tablenav top">';
225
+ $html .= '<div class="alignleft actions bulkactions">
226
+ <label for="bulk-action-selector-top" class="screen-reader-text">Select bulk action</label>
227
+ <select name="action" id="bulk-action-selector-top">
228
+ <option value="-1">' . __( "Bulk Actions", "custom-permalinks" ) . '</option>
229
+ <option value="delete">' . __( "Delete Permalinks", "custom-permalinks" ) . '</option>
230
+ </select>
231
+ <input type="submit" id="doaction" class="button action" value="Apply">
232
+ </div>';
233
+
234
+ $posts = 0;
235
+ $table = get_option( 'custom_permalink_table' );
236
+ $count_tags = count( $table );
237
+ if ( isset( $table ) && is_array( $table ) && $count_tags > 0 ) {
238
+
239
+ $filtered = array();
240
+ if ( $search_value != '' ) {
241
+ foreach ( $table as $key => $value ) {
242
+ if( preg_match( '/' . $search_value . '/', $key) ) {
243
+ $filtered[$key] = $value;
244
+ }
245
+ }
246
+ $table = $filtered;
247
+ $count_tags = count( $table );
248
+ }
249
+
250
+ $html .= '<h2 class="screen-reader-text">Custom Permalink navigation</h2>';
251
+
252
+ $pagination_html = '';
253
+ $total_pages = ceil( $count_tags / 20 );
254
+ if ( isset( $_GET['paged'] ) && is_numeric( $_GET['paged'] ) && $_GET['paged'] > 0) {
255
+ $pagination_html = $this->custom_permalinks_pager( $count_tags, $_GET['paged'], $total_pages);
256
+ if ( $_GET['paged'] > $total_pages ) {
257
+ $redirect_uri = explode( '&paged=' . $_GET['paged'] . '', $_SERVER['REQUEST_URI'] );
258
+ header( 'Location: ' . $redirect_uri[0], 301 );
259
+ exit();
260
+ }
261
+ } elseif ( ! isset( $_GET['paged'] ) ) {
262
+ $pagination_html = $this->custom_permalinks_pager( $count_tags, 1, $total_pages );
263
+ }
264
+
265
+ $html .= $pagination_html;
266
+ }
267
+ $table_navigation = $this->custom_permalink_tablenav_category( $search_permalink );
268
+
269
+ $html .= '</div>';
270
+ $html .= '<table class="wp-list-table widefat fixed striped posts">
271
+ <thead>' . $table_navigation . '</thead>
272
+ <tbody>';
273
+
274
+ if ( $table && is_array( $table ) && $count_tags > 0 ) {
275
+ uasort( $table, array( 'Custom_Permalinks_Admin', 'custom_permalinks_sort_array' ) );
276
+ $i = -1;
277
+ foreach ( $table as $permalink => $info ) {
278
+ $i++;
279
+ if ( $i < $pager_offset )
280
+ continue;
281
+
282
+ if ( $i >= $page_limit )
283
+ break;
284
+
285
+ $type = $info['kind'] == 'tag' ? 'post_tag' : 'category';
286
+ $term = get_term( $info['id'], $type );
287
+ $html .= '<tr valign="top">';
288
+ $html .= '<th scope="row" class="check-column"><input type="checkbox" name="permalink[]" value="' . $info['id'] . '" /></th>';
289
+ $html .= '<td><strong><a class="row-title" href="edit-tags.php?action=edit&taxonomy=' . $type . '&tag_ID=' . $info['id'] . ' ">' . $term->name . '</a></strong></td>';
290
+ $html .= '<td>' . ucwords( $info['kind'] ) . '</td>';
291
+ $html .= '<td><a href="/' . $permalink . '" target="_blank" title="' . __( "Visit " . $term->name, "custom-permalinks" ) . '">/' . $permalink . '</a></td></tr>';
292
+ }
293
+ } else {
294
+ $html .= '<tr class="no-items"><td class="colspanchange" colspan="10">No permalinks found.</td></tr>';
295
+ }
296
+ $html .= '</tbody>
297
+ <tfoot>' . $table_navigation . '</tfoot>
298
+ </table>';
299
+
300
+ $html .= '<div class="tablenav bottom">
301
+ <div class="alignleft actions bulkactions">
302
+ <label for="bulk-action-selector-bottom" class="screen-reader-text">Select bulk action</label>
303
+ <select name="action2" id="bulk-action-selector-bottom">
304
+ <option value="-1">' . __( "Bulk Actions", "custom-permalinks" ) . '</option>
305
+ <option value="delete">' . __( "Delete Permalinks", "custom-permalinks" ) . '</option>
306
+ </select>
307
+ <input type="submit" id="doaction2" class="button action" value="Apply">
308
+ </div>
309
+ ' . $pagination_html . '
310
+ </div>';
311
+ $html .= '</form>
312
+ </div>';
313
+ echo $html;
314
+ }
315
+
316
+ /**
317
+ * Sort the terms array in desc order using term id
318
+ */
319
+ private static function custom_permalinks_sort_array( $a, $b ) {
320
+ return $b['id'] - $a['id'];
321
+ }
322
+
323
+ /**
324
+ * Return the Navigation row HTML same as Default Posts page for Category
325
+ */
326
+ private function custom_permalink_tablenav_category( $search_permalink ) {
327
+ $nav = '<tr>
328
+ <td id="cb" class="manage-column column-cb check-column"><label class="screen-reader-text" for="cb-select-all-1">Select All</label><input id="cb-select-all-1" type="checkbox"></td>
329
+ <th scope="col" id="title" class="manage-column column-title column-primary">' . __( "Title", "custom-permalinks" ) . '</th>
330
+ <th scope="col">' . __( "Type", "custom-permalinks" ) . '</th>
331
+ <th scope="col">' . __( "Permalink", "custom-permalinks" ) . '</th>
332
+ </tr>';
333
+ return $nav;
334
+ }
335
+
336
+ /**
337
+ * Return the Pager HTML
338
+ */
339
+ private function custom_permalinks_pager( $total_permalinks, $current_pager_value = 1, $total_pager = 0 ) {
340
+
341
+ if ( $total_pager == 0 ) return;
342
+
343
+ if ( $total_pager == 1 ) {
344
+ $pagination_html = '<div class="tablenav-pages one-page">
345
+ <span class="displaying-num">' . $total_permalinks . ' items</span>
346
+ </div>';
347
+ return $pagination_html;
348
+ }
349
+
350
+ $remove_pager_uri = explode( '&paged=' . $current_pager_value . '', $_SERVER['REQUEST_URI'] );
351
+ $pagination_html = '<div class="tablenav-pages">
352
+ <span class="displaying-num">' . $total_permalinks . ' items</span>
353
+ <span class="pagination-links">';
354
+
355
+ if ( $current_pager_value == 1 ) {
356
+ $pagination_html .= '<span class="tablenav-pages-navspan" aria-hidden="true">&laquo; </span>
357
+ <span class="tablenav-pages-navspan" aria-hidden="true">&lsaquo; </span>';
358
+ } else {
359
+ $prev_page = $current_pager_value - 1;
360
+ if ( $prev_page == 1 ) {
361
+ $pagination_html .= '<span class="tablenav-pages-navspan" aria-hidden="true">&laquo;</span>';
362
+ } else {
363
+ $pagination_html .= ' <a href="' . $remove_pager_uri[0] . '&paged=1" title="First page" class="first-page">
364
+ <span class="screen-reader-text">First page</span>
365
+ <span aria-hidden="true">&laquo;</span>
366
+ </a> ';
367
+ }
368
+ $pagination_html .= ' <a href="' . $remove_pager_uri[0] . '&paged=' . $prev_page . '" title="Previous page" class="prev-page">
369
+ <span class="screen-reader-text">Previous page</span>
370
+ <span aria-hidden="true">&lsaquo;</span>
371
+ </a> ';
372
+ }
373
+
374
+ $pagination_html .= '<span class="paging-input">
375
+ <label for="current-page-selector" class="screen-reader-text">Current Page</label>
376
+ <input class="current-page" id="current-page-selector" type="text" name="paged" value="' . $current_pager_value . '" size="1" aria-describedby="table-paging" />
377
+ <span class="tablenav-paging-text"> of <span class="total-pages">' . $total_pager . ' </span> </span>
378
+ </span>';
379
+
380
+ if ( $current_pager_value == $total_pager ) {
381
+ $pagination_html .= '<span class="tablenav-pages-navspan" aria-hidden="true">&rsaquo; </span>
382
+ <span class="tablenav-pages-navspan" aria-hidden="true">&raquo; </span>';
383
+ } else {
384
+ $next_page = $current_pager_value + 1;
385
+ $pagination_html .= ' <a href="' . $remove_pager_uri[0] . '&paged=' . $next_page . '" title="Next page" class="next-page">
386
+ <span class="screen-reader-text">Next page</span>
387
+ <span aria-hidden="true">&rsaquo;</span>
388
+ </a> ';
389
+ if ( $total_pager == $next_page) {
390
+ $pagination_html .= '<span class="tablenav-pages-navspan" aria-hidden="true">&raquo;</span>';
391
+ } else {
392
+ $pagination_html .= ' <a href="' . $remove_pager_uri[0] . '&paged=' . $total_pager . '" title="Last page" class="last-page">
393
+ <span class="screen-reader-text">Last page</span>
394
+ <span aria-hidden="true">&raquo;</span>
395
+ </a> ';
396
+ }
397
+
398
+ }
399
+ $pagination_html .= '</span></div>';
400
+
401
+ return $pagination_html;
402
  }
403
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
404
  }
admin/class-custom-permalinks-form.php ADDED
@@ -0,0 +1,329 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @package CustomPermalinks\Admin\Form
4
+ */
5
+
6
+ class Custom_Permalinks_Form {
7
+
8
+ /**
9
+ * Initialize WordPress Hooks
10
+ */
11
+ public function init() {
12
+
13
+ add_filter( 'get_sample_permalink_html', array( $this, 'custom_permalinks_get_sample_permalink_html' ), 10, 4 );
14
+
15
+ add_action( 'save_post', array( $this, 'custom_permalinks_save_post' ), 10, 3 );
16
+ add_action( 'delete_post', array( $this, 'custom_permalinks_delete_permalink' ), 10 );
17
+
18
+ add_action( 'edit_tag_form', array( $this, 'custom_permalinks_term_options' ) );
19
+ add_action( 'add_tag_form', array( $this, 'custom_permalinks_term_options' ) );
20
+ add_action( 'edit_category_form', array( $this, 'custom_permalinks_term_options' ) );
21
+
22
+ add_action( 'edited_post_tag', array( $this, 'custom_permalinks_save_tag' ) );
23
+ add_action( 'edited_category', array( $this, 'custom_permalinks_save_category' ) );
24
+ add_action( 'create_post_tag', array( $this, 'custom_permalinks_save_tag' ) );
25
+ add_action( 'create_category', array( $this, 'custom_permalinks_save_category' ) );
26
+ add_action( 'delete_post_tag', array( $this, 'custom_permalinks_delete_term' ) );
27
+ add_action( 'delete_post_category', array( $this, 'custom_permalinks_delete_term' ) );
28
+ }
29
+
30
+ /**
31
+ * Save per-post options
32
+ */
33
+ public function custom_permalinks_save_post( $id ) {
34
+ if ( ! isset( $_REQUEST['custom_permalinks_edit'] ) ) {
35
+ return;
36
+ }
37
+
38
+ delete_post_meta( $id, 'custom_permalink' );
39
+
40
+ require_once( CUSTOM_PERMALINKS_PATH . 'frontend/class-custom-permalinks-frontend.php' );
41
+ $custom_permalinks_frontend = new Custom_Permalinks_Frontend();
42
+ $original_link = $custom_permalinks_frontend->custom_permalinks_original_post_link( $id );
43
+ $permalink_structure = get_option( 'permalink_structure' );
44
+
45
+ if ( $_REQUEST['custom_permalink'] && $_REQUEST['custom_permalink'] != $original_link ) {
46
+ add_post_meta( $id, 'custom_permalink',
47
+ str_replace( '%2F', '/',
48
+ urlencode( ltrim( stripcslashes( $_REQUEST['custom_permalink'] ), "/" ) )
49
+ )
50
+ );
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Delete post
56
+ */
57
+ public function custom_permalinks_delete_permalink( $id ) {
58
+ global $wpdb;
59
+ $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->postmeta WHERE meta_key = 'custom_permalink' AND `post_id` = %d", $id ) );
60
+ }
61
+
62
+ /**
63
+ * Per-post/page options (Wordpress > 2.9)
64
+ */
65
+ public function custom_permalinks_get_sample_permalink_html( $html, $id, $new_title, $new_slug ) {
66
+ if ( $post->post_type == 'attachment' || $post->ID == get_option( 'page_on_front' ) ) {
67
+ return $html;
68
+ }
69
+
70
+ $permalink = get_post_meta( $id, 'custom_permalink', true );
71
+ $post = get_post( $id );
72
+
73
+ ob_start();
74
+
75
+ require_once( CUSTOM_PERMALINKS_PATH . 'frontend/class-custom-permalinks-frontend.php' );
76
+ $custom_permalinks_frontend = new Custom_Permalinks_Frontend();
77
+ if ( $post->post_type == "page" ) {
78
+ $original_page_url = $custom_permalinks_frontend->custom_permalinks_original_page_link( $id );
79
+ $this->custom_permalinks_get_form( $permalink, $original_page_url, false );
80
+ } else {
81
+ $original_post_url = $custom_permalinks_frontend->custom_permalinks_original_post_link( $id );
82
+ $this->custom_permalinks_get_form( $permalink, $original_post_url, false );
83
+ }
84
+
85
+ $content = ob_get_contents();
86
+ ob_end_clean();
87
+
88
+ if ( 'publish' == $post->post_status ) {
89
+ $view_post = 'page' == $post->post_type ? __( 'View Page', 'custom-permalinks' ) : __( 'View Post', 'custom-permalinks' );
90
+ }
91
+
92
+ if ( preg_match( "@view-post-btn.*?href='([^']+)'@s", $html, $matches ) ) {
93
+ $permalink = $matches[1];
94
+ } else {
95
+ list( $permalink, $post_name ) = get_sample_permalink( $post->ID, $new_title, $new_slug );
96
+ if ( false !== strpos( $permalink, '%postname%' )
97
+ || false !== strpos( $permalink, '%pagename%' ) ) {
98
+ $permalink = str_replace( array( '%pagename%','%postname%' ), $post_name, $permalink );
99
+ }
100
+ }
101
+
102
+ return '<strong>' . __('Permalink:', 'custom-permalinks') . "</strong>\n" . $content .
103
+ ( isset( $view_post ) ? "<span id='view-post-btn'><a href='$permalink' class='button button-small' target='_blank'>$view_post</a></span>\n" : "" );
104
+ }
105
+
106
+ /**
107
+ * Per-post options (Wordpress < 2.9)
108
+ */
109
+ public function custom_permalinks_post_options() {
110
+ global $post;
111
+ $post_id = $post;
112
+ if ( is_object( $post_id ) ) {
113
+ $post_id = $post_id->ID;
114
+ }
115
+
116
+ $permalink = get_post_meta( $post_id, 'custom_permalink', true );
117
+ ?>
118
+ <div class="postbox closed">
119
+ <h3><?php _e( 'Custom Permalink', 'custom-permalinks' ) ?></h3>
120
+ <div class="inside">
121
+ <?php
122
+ require_once( CUSTOM_PERMALINKS_PATH . 'frontend/class-custom-permalinks-frontend.php' );
123
+ $custom_permalinks_frontend = new Custom_Permalinks_Frontend();
124
+ $custom_permalinks_frontend->custom_permalinks_get_form( $permalink, $this->custom_permalinks_original_post_link( $post_id ) );
125
+ ?>
126
+ </div>
127
+ </div>
128
+ <?php
129
+ }
130
+
131
+ /**
132
+ * Per-page options (Wordpress < 2.9)
133
+ */
134
+ public function custom_permalinks_page_options() {
135
+ global $post;
136
+ $post_id = $post;
137
+ if (is_object( $post_id ) ) {
138
+ $post_id = $post_id->ID;
139
+ }
140
+
141
+ $permalink = get_post_meta( $post_id, 'custom_permalink', true );
142
+
143
+ ?>
144
+ <div class="postbox closed">
145
+ <h3><?php _e( 'Custom Permalink', 'custom-permalinks' ); ?></h3>
146
+ <div class="inside">
147
+ <?php
148
+ require_once( CUSTOM_PERMALINKS_PATH . 'frontend/class-custom-permalinks-frontend.php' );
149
+ $custom_permalinks_frontend = new Custom_Permalinks_Frontend();
150
+ $page_permalink = $custom_permalinks_frontend->custom_permalinks_original_page_link( $post_id );
151
+ $this->custom_permalinks_get_form( $permalink, $page_permalink );
152
+ ?>
153
+ </div>
154
+ </div>
155
+ <?php
156
+ }
157
+
158
+ /**
159
+ * Per-category/tag options
160
+ */
161
+ public function custom_permalinks_term_options( $object ) {
162
+ if ( is_object( $object ) && isset( $object->term_id ) ) {
163
+ $permalink = $this->custom_permalinks_permalink_for_term( $object->term_id );
164
+
165
+ if ( $object->term_id ) {
166
+ require_once( CUSTOM_PERMALINKS_PATH . 'frontend/class-custom-permalinks-frontend.php' );
167
+ $custom_permalinks_frontend = new Custom_Permalinks_Frontend();
168
+ if ( $object->taxonomy == 'post_tag' ) {
169
+ $originalPermalink = $custom_permalinks_frontend->custom_permalinks_original_tag_link( $object->term_id );
170
+ } else {
171
+ $originalPermalink = $custom_permalinks_frontend->custom_permalinks_original_category_link( $object->term_id );
172
+ }
173
+ }
174
+
175
+ $this->custom_permalinks_get_form( $permalink, $originalPermalink );
176
+ } else {
177
+ $this->custom_permalinks_get_form( '' );
178
+ }
179
+
180
+ // Move the save button to above this form
181
+ wp_enqueue_script( 'jquery' );
182
+ ?>
183
+ <script type="text/javascript">
184
+ jQuery(document).ready(function() {
185
+ var button = jQuery('#custom_permalink_form').parent().find('.submit');
186
+ button.remove().insertAfter(jQuery('#custom_permalink_form'));
187
+ });
188
+ </script>
189
+ <?php
190
+ }
191
+
192
+ /**
193
+ * Helper function to render form
194
+ */
195
+ private function custom_permalinks_get_form( $permalink, $original = "", $renderContainers = true ) {
196
+ ?>
197
+ <input value="true" type="hidden" name="custom_permalinks_edit" />
198
+ <input value="<?php echo htmlspecialchars( urldecode( $permalink ) ); ?>" type="hidden" name="custom_permalink" id="custom_permalink" />
199
+
200
+ <?php if ( $renderContainers ) : ?>
201
+ <table class="form-table" id="custom_permalink_form">
202
+ <tr>
203
+ <th scope="row"><?php _e( 'Custom Permalink', 'custom-permalinks' ); ?></th>
204
+ <td>
205
+ <?php endif; ?>
206
+
207
+ <?php
208
+ if ( $permalink == '' ) {
209
+ $original = $this->custom_permalinks_check_conflicts( $original );
210
+ }
211
+ ?>
212
+
213
+ <?php echo home_url() ?>/
214
+ <span id="editable-post-name" title="Click to edit this part of the permalink">
215
+ <?php
216
+ $post_slug = htmlspecialchars( $permalink ? urldecode( $permalink ) : urldecode( $original ) );
217
+ $original_encoded_url = htmlspecialchars( urldecode( $original ) );
218
+ ?>
219
+ <input type="text" id="new-post-slug" class="text" value="<?php echo $post_slug; ?>"
220
+ style="width: 250px; <?php if ( !$permalink ) echo 'color: #ddd'; ?>"
221
+ onfocus="if ( this.style.color = '#ddd' ) { this.style.color = '#000'; }"
222
+ onblur="document.getElementById('custom_permalink').value = this.value; if ( this.value == '' || this.value == '<?php echo $original_encoded_url; ?>' ) { this.value = '<?php echo $original_encoded_url; ?>'; this.style.color = '#ddd'; }" />
223
+ </span>
224
+
225
+ <?php if ( $renderContainers ) : ?>
226
+ <br />
227
+ <small><?php _e( 'Leave blank to disable', 'custom-permalinks' ); ?></small>
228
+ </td>
229
+ </tr>
230
+ </table>
231
+ <?php
232
+ endif;
233
+ }
234
+
235
+ /**
236
+ * Save per-tag options
237
+ */
238
+ public function custom_permalinks_save_tag( $id ) {
239
+ if ( ! isset( $_REQUEST['custom_permalinks_edit'] )
240
+ || isset( $_REQUEST['post_ID'] ) ) {
241
+ return;
242
+ }
243
+ $newPermalink = ltrim( stripcslashes( $_REQUEST['custom_permalink'] ), "/" );
244
+
245
+ require_once( CUSTOM_PERMALINKS_PATH . 'frontend/class-custom-permalinks-frontend.php' );
246
+ $custom_permalinks_frontend = new Custom_Permalinks_Frontend();
247
+ if ( $newPermalink == $custom_permalinks_frontend->custom_permalinks_original_tag_link( $id ) )
248
+ $newPermalink = '';
249
+
250
+ $term = get_term( $id, 'post_tag' );
251
+ $this->custom_permalinks_save_term( $term, str_replace( '%2F', '/', urlencode( $newPermalink ) ) );
252
+ }
253
+
254
+ /**
255
+ * Save per-category options
256
+ */
257
+ public function custom_permalinks_save_category( $id ) {
258
+ if ( ! isset( $_REQUEST['custom_permalinks_edit'] )
259
+ || isset( $_REQUEST['post_ID'] ) ) {
260
+ return;
261
+ }
262
+ $newPermalink = ltrim( stripcslashes( $_REQUEST['custom_permalink'] ), "/" );
263
+
264
+ require_once( CUSTOM_PERMALINKS_PATH . 'frontend/class-custom-permalinks-frontend.php' );
265
+ $custom_permalinks_frontend = new Custom_Permalinks_Frontend();
266
+ if ( $newPermalink == $custom_permalinks_frontend->custom_permalinks_original_category_link( $id ) )
267
+ $newPermalink = '';
268
+
269
+ $term = get_term( $id, 'category' );
270
+ $this->custom_permalinks_save_term( $term, str_replace( '%2F', '/', urlencode( $newPermalink ) ) );
271
+ }
272
+
273
+ /**
274
+ * Save term (common to tags and categories)
275
+ */
276
+ public function custom_permalinks_save_term( $term, $permalink ) {
277
+
278
+ $this->custom_permalinks_delete_term( $term->term_id );
279
+ $table = get_option( 'custom_permalink_table' );
280
+ if ( $permalink ) {
281
+ $table[$permalink] = array(
282
+ 'id' => $term->term_id,
283
+ 'kind' => ( $term->taxonomy == 'category' ? 'category' : 'tag' ),
284
+ 'slug' => $term->slug
285
+ );
286
+ }
287
+
288
+ update_option( 'custom_permalink_table', $table );
289
+ }
290
+
291
+ /**
292
+ * Delete term
293
+ */
294
+ public function custom_permalinks_delete_term( $id ) {
295
+ $table = get_option( 'custom_permalink_table' );
296
+ if ( $table ) {
297
+ foreach ( $table as $link => $info ) {
298
+ if ( $info['id'] == $id ) {
299
+ unset( $table[$link] );
300
+ break;
301
+ }
302
+ }
303
+ }
304
+ update_option( 'custom_permalink_table', $table );
305
+ }
306
+
307
+ /**
308
+ * Check Conflicts and resolve it (e.g: Polylang)
309
+ */
310
+ public function custom_permalinks_check_conflicts( $requested_url = '' ) {
311
+ if ( $requested_url == '' ) return;
312
+
313
+ // Check if the Polylang Plugin is installed so, make changes in the URL
314
+ if ( defined( 'POLYLANG_VERSION' ) ) {
315
+ $polylang_config = get_option( 'polylang' );
316
+ if ( $polylang_config['force_lang'] == 1 ) {
317
+
318
+ if ( strpos( $requested_url, 'language/' ) !== false )
319
+ $requested_url = str_replace( "language/", "", $requested_url );
320
+
321
+ $remove_lang = ltrim( strstr( $requested_url, '/' ), '/');
322
+ if ( $remove_lang != '' )
323
+ return $remove_lang;
324
+ }
325
+ }
326
+ return $requested_url;
327
+ }
328
+
329
+ }
custom-permalinks-main.php CHANGED
@@ -1,770 +1,43 @@
1
  <?php
2
-
3
  /**
4
  * @package CustomPermalinks\Main
5
  */
6
 
7
  // Make sure we don't expose any info if called directly
8
- if ( !defined( 'ABSPATH' ) ) {
9
- echo 'Hi there! I\'m just a plugin, not much I can do when called directly.';
10
- exit;
11
  }
12
 
13
- if ( !function_exists("add_action") || !function_exists("add_filter") ) {
14
- header( 'Status: 403 Forbidden' );
15
- header( 'HTTP/1.1 403 Forbidden' );
16
- exit();
17
  }
18
 
19
- define('CUSTOM_PERMALINKS_PLUGIN_VERSION', '1.1');
20
-
21
- if ( !defined('CUSTOM_PERMALINKS_PATH') ) {
22
- define('CUSTOM_PERMALINKS_PATH', plugin_dir_path( __FILE__ ));
23
- }
24
-
25
- if ( is_admin() ) {
26
- require_once(CUSTOM_PERMALINKS_PATH.'admin/class-custom-permalinks-admin.php');
27
- new Custom_Permalinks_Admin();
28
- }
29
-
30
- /**
31
- * Filter to replace the post permalink with the custom one
32
- */
33
- function custom_permalinks_post_link($permalink, $post) {
34
- $custom_permalink = get_post_meta( $post->ID, 'custom_permalink', true );
35
- if ( $custom_permalink ) {
36
- $post_type = isset($post->post_type) ? $post->post_type : 'post';
37
- $language_code = apply_filters( 'wpml_element_language_code', null, array( 'element_id' => $post->ID, 'element_type' => $post_type ) );
38
- if ( $language_code )
39
- return apply_filters( 'wpml_permalink', home_url()."/".$custom_permalink, $language_code );
40
- else
41
- return apply_filters( 'wpml_permalink', home_url()."/".$custom_permalink );
42
- }
43
 
44
- return $permalink;
45
- }
46
-
47
- /**
48
- * Filter to replace the page permalink with the custom one
49
- */
50
- function custom_permalinks_page_link($permalink, $page) {
51
- $custom_permalink = get_post_meta( $page, 'custom_permalink', true );
52
- if ( $custom_permalink ) {
53
- $language_code = apply_filters( 'wpml_element_language_code', null, array( 'element_id' => $page, 'element_type' => 'page' ) );
54
- if ( $language_code )
55
- return apply_filters( 'wpml_permalink', home_url()."/".$custom_permalink, $language_code );
56
- else
57
- return apply_filters( 'wpml_permalink', home_url()."/".$custom_permalink );
58
- }
59
-
60
- return $permalink;
61
- }
62
-
63
- /**
64
- * Filter to replace the term permalink with the custom one
65
- */
66
- function custom_permalinks_term_link($permalink, $term) {
67
- $table = get_option('custom_permalink_table');
68
- if ( is_object($term) ) $term = $term->term_id;
69
-
70
- $custom_permalink = custom_permalinks_permalink_for_term($term);
71
- if ( $custom_permalink ) {
72
- $taxonomy = get_term($term);
73
- if ( isset($taxonomy) && isset($taxonomy->term_taxonomy_id) ) {
74
- $term_type = isset($taxonomy->taxonomy) ? $taxonomy->taxonomy : 'category';
75
- $language_code = apply_filters( 'wpml_element_language_code', null, array( 'element_id' => $taxonomy->term_taxonomy_id, 'element_type' => $term_type ) );
76
- return apply_filters( 'wpml_permalink', home_url()."/".$custom_permalink, $language_code );
77
- } else {
78
- return apply_filters( 'wpml_permalink', home_url()."/".$custom_permalink );
79
- }
80
- }
81
-
82
- return $permalink;
83
  }
84
 
85
- /**
86
- * Action to redirect to the custom permalink
87
- */
88
- function custom_permalinks_redirect() {
89
- // Get request URI, strip parameters
90
- $url = parse_url(get_bloginfo('url'));
91
- $url = isset($url['path']) ? $url['path'] : '';
92
- $request = ltrim(substr($_SERVER['REQUEST_URI'], strlen($url)),'/');
93
- if ( ($pos=strpos($request, "?")) ) $request = substr($request, 0, $pos);
94
-
95
- $request = custom_permalinks_check_conflicts($request);
96
-
97
- global $wp_query;
98
-
99
- $custom_permalink = '';
100
- $original_permalink = '';
101
-
102
- // If the post/tag/category we're on has a custom permalink, get it and check against the request
103
- if ( (is_single() || is_page()) && !empty($wp_query->post) ) {
104
- $post = $wp_query->post;
105
- $custom_permalink = get_post_meta( $post->ID, 'custom_permalink', true );
106
- $original_permalink = ( $post->post_type == 'page' ? custom_permalinks_original_page_link( $post->ID ) : custom_permalinks_original_post_link( $post->ID ) );
107
- } else if ( is_tag() || is_category() ) {
108
- $theTerm = $wp_query->get_queried_object();
109
- $custom_permalink = custom_permalinks_permalink_for_term($theTerm->term_id);
110
- $original_permalink = (is_tag() ? custom_permalinks_original_tag_link($theTerm->term_id) : custom_permalinks_original_category_link($theTerm->term_id));
111
- }
112
-
113
- if ( $custom_permalink && (substr($request, 0, strlen($custom_permalink)) != $custom_permalink || $request == $custom_permalink."/" ) ) {
114
- // Request doesn't match permalink - redirect
115
- $url = $custom_permalink;
116
-
117
- if ( substr($request, 0, strlen($original_permalink)) == $original_permalink && trim($request,'/') != trim($original_permalink,'/') ) {
118
- // This is the original link; we can use this url to derive the new one
119
- $url = preg_replace('@//*@', '/', str_replace(trim($original_permalink,'/'), trim($custom_permalink,'/'), $request));
120
- $url = preg_replace('@([^?]*)&@', '\1?', $url);
121
- }
122
-
123
- // Append any query compenent
124
- $url .= strstr($_SERVER['REQUEST_URI'], "?");
125
-
126
- wp_redirect( home_url()."/".$url, 301 );
127
- exit();
128
- }
129
- }
130
-
131
- /**
132
- * Filter to rewrite the query if we have a matching post
133
- */
134
- function custom_permalinks_request($query) {
135
- global $wpdb;
136
- global $_CPRegisteredURL;
137
-
138
- // First, search for a matching custom permalink, and if found, generate the corresponding
139
- // original URL
140
-
141
- $originalUrl = NULL;
142
-
143
- // Get request URI, strip parameters and /'s
144
- $url = parse_url(get_bloginfo('url'));
145
- $url = isset($url['path']) ? $url['path'] : '';
146
- $request = ltrim(substr($_SERVER['REQUEST_URI'], strlen($url)),'/');
147
- $request = (($pos=strpos($request, '?')) ? substr($request, 0, $pos) : $request);
148
-
149
- if ( !$request ) return $query;
150
-
151
- $request = custom_permalinks_check_conflicts($request);
152
- $request_noslash = preg_replace('@/+@','/', trim($request, '/'));
153
-
154
- $sql = $wpdb->prepare("SELECT $wpdb->posts.ID, $wpdb->postmeta.meta_value, $wpdb->posts.post_type, $wpdb->posts.post_status FROM $wpdb->posts ".
155
- "LEFT JOIN $wpdb->postmeta ON ($wpdb->posts.ID = $wpdb->postmeta.post_id) WHERE ".
156
- " meta_key = 'custom_permalink' AND ".
157
- " meta_value != '' AND ".
158
- " ( LOWER(meta_value) = LEFT(LOWER('%s'), LENGTH(meta_value)) OR ".
159
- " LOWER(meta_value) = LEFT(LOWER('%s'), LENGTH(meta_value)) ) ".
160
- " AND post_status != 'trash' AND post_type != 'nav_menu_item'".
161
- " ORDER BY LENGTH(meta_value) DESC, ".
162
- " FIELD(post_status,'publish','private','draft','auto-draft','inherit'),".
163
- " FIELD(post_type,'post','page'),".
164
- "$wpdb->posts.ID ASC LIMIT 1",
165
- $request_noslash,
166
- $request_noslash."/");
167
-
168
- $posts = $wpdb->get_results($sql);
169
-
170
- if ( $posts ) {
171
- // A post matches our request
172
-
173
- // Preserve this url for later if it's the same as the permalink (no extra stuff)
174
- if ( $request_noslash == trim($posts[0]->meta_value,'/') )
175
- $_CPRegisteredURL = $request;
176
-
177
- if ( $posts[0]->post_status == 'draft' ) {
178
- if( $posts[0]->post_type == 'page' ) {
179
- $originalUrl = "?page_id=" . $posts[0]->ID;
180
- } else {
181
- $originalUrl = "?post_type=".$posts[0]->post_type."&p=" . $posts[0]->ID;
182
- }
183
- } else {
184
- $originalUrl = preg_replace( '@/+@', '/', str_replace( trim( strtolower($posts[0]->meta_value),'/' ),
185
- ( $posts[0]->post_type == 'page' ?
186
- custom_permalinks_original_page_link($posts[0]->ID)
187
- : custom_permalinks_original_post_link($posts[0]->ID) ),
188
- strtolower($request_noslash) ) );
189
- }
190
- }
191
-
192
- if ( $originalUrl === NULL ) {
193
- // See if any terms have a matching permalink
194
- $table = get_option('custom_permalink_table');
195
- if ( !$table ) return $query;
196
-
197
- foreach ( array_keys($table) as $permalink ) {
198
- if ( $permalink == substr($request_noslash, 0, strlen($permalink)) ||
199
- $permalink == substr($request_noslash."/", 0, strlen($permalink)) ) {
200
- $term = $table[$permalink];
201
-
202
- // Preserve this url for later if it's the same as the permalink (no extra stuff)
203
- if ( $request_noslash == trim($permalink,'/') )
204
- $_CPRegisteredURL = $request;
205
-
206
-
207
- if ( $term['kind'] == 'category') {
208
- $originalUrl = str_replace(trim($permalink,'/'),
209
- custom_permalinks_original_category_link($term['id']),
210
- trim($request,'/'));
211
- } else {
212
- $originalUrl = str_replace(trim($permalink,'/'),
213
- custom_permalinks_original_tag_link($term['id']),
214
- trim($request,'/'));
215
- }
216
- }
217
- }
218
- }
219
-
220
- if ( $originalUrl !== NULL ) {
221
- $originalUrl = str_replace('//', '/', $originalUrl);
222
-
223
- if ( ($pos=strpos($_SERVER['REQUEST_URI'], '?')) !== false ) {
224
- $queryVars = substr($_SERVER['REQUEST_URI'], $pos+1);
225
- $originalUrl .= (strpos($originalUrl, '?') === false ? '?' : '&') . $queryVars;
226
- }
227
-
228
- // Now we have the original URL, run this back through WP->parse_request, in order to
229
- // parse parameters properly. We set $_SERVER variables to fool the function.
230
- $oldRequestUri = $_SERVER['REQUEST_URI']; $oldQueryString = $_SERVER['QUERY_STRING'];
231
- $_SERVER['REQUEST_URI'] = '/'.ltrim($originalUrl,'/');
232
- $_SERVER['QUERY_STRING'] = (($pos=strpos($originalUrl, '?')) !== false ? substr($originalUrl, $pos+1) : '');
233
- parse_str($_SERVER['QUERY_STRING'], $queryArray);
234
- $oldValues = array();
235
- if ( is_array($queryArray) )
236
- foreach ( $queryArray as $key => $value ) {
237
- $oldValues[$key] = $_REQUEST[$key];
238
- $_REQUEST[$key] = $_GET[$key] = $value;
239
- }
240
-
241
- // Re-run the filter, now with original environment in place
242
- remove_filter( 'request', 'custom_permalinks_request', 10, 1 );
243
- global $wp;
244
- $wp->parse_request();
245
- $query = $wp->query_vars;
246
- add_filter( 'request', 'custom_permalinks_request', 10, 1 );
247
 
248
- // Restore values
249
- $_SERVER['REQUEST_URI'] = $oldRequestUri; $_SERVER['QUERY_STRING'] = $oldQueryString;
250
- foreach ( $oldValues as $key => $value ) {
251
- $_REQUEST[$key] = $value;
252
- }
253
- }
254
 
255
- return $query;
256
- }
257
-
258
- /**
259
- * Filter to handle trailing slashes correctly
260
- */
261
- function custom_permalinks_trailingslash($string, $type) {
262
- global $_CPRegisteredURL;
263
-
264
- remove_filter( 'user_trailingslashit', 'custom_permalinks_trailingslash', 10, 2 );
265
- $url = parse_url(get_bloginfo('url'));
266
- $request = ltrim(isset($url['path']) ? substr($string, strlen($url['path'])) : $string, '/');
267
- add_filter( 'user_trailingslashit', 'custom_permalinks_trailingslash', 10, 2 );
268
-
269
- if ( !trim($request) ) return $string;
270
-
271
- if ( trim($_CPRegisteredURL,'/') == trim($request,'/') ) {
272
- if( isset($url['path']) ) {
273
- return ($string{0} == '/' ? '/' : '') . trailingslashit($url['path']) . $_CPRegisteredURL;
274
- } else {
275
- return ($string{0} == '/' ? '/' : '') . $_CPRegisteredURL;
276
- }
277
- }
278
- return $string;
279
- }
280
-
281
- /**
282
- * Per-post/page options (Wordpress > 2.9)
283
- */
284
- function custom_permalink_get_sample_permalink_html($html, $id, $new_title, $new_slug) {
285
- $permalink = get_post_meta( $id, 'custom_permalink', true );
286
- $post = get_post($id);
287
-
288
- ob_start();
289
- ?>
290
- <?php custom_permalinks_form($permalink, ($post->post_type == "page" ? custom_permalinks_original_page_link($id) : custom_permalinks_original_post_link($id)), false); ?>
291
- <?php
292
- $content = ob_get_contents();
293
- ob_end_clean();
294
-
295
- if ( 'publish' == $post->post_status ) {
296
- $view_post = 'page' == $post->post_type ? __('View Page', 'custom-permalinks') : __('View Post', 'custom-permalinks');
297
- }
298
- if ( $post->post_type == 'attachment' || $post->ID == get_option('page_on_front') ) {
299
- return $html;
300
- }
301
-
302
- if ( preg_match("@view-post-btn.*?href='([^']+)'@s", $html, $matches) ) {
303
- $permalink = $matches[1];
304
- } else {
305
- list($permalink, $post_name) = get_sample_permalink($post->ID, $new_title, $new_slug);
306
- if ( false !== strpos($permalink, '%postname%') || false !== strpos($permalink, '%pagename%') ) {
307
- $permalink = str_replace(array('%pagename%','%postname%'), $post_name, $permalink);
308
- }
309
- }
310
-
311
- return '<strong>' . __('Permalink:', 'custom-permalinks') . "</strong>\n" . $content .
312
- ( isset($view_post) ? "<span id='view-post-btn'><a href='$permalink' class='button button-small' target='_blank'>$view_post</a></span>\n" : "" );
313
- }
314
-
315
-
316
- /**
317
- * Per-post options (Wordpress < 2.9)
318
- */
319
- function custom_permalinks_post_options() {
320
- global $post;
321
- $post_id = $post;
322
- if (is_object($post_id)) {
323
- $post_id = $post_id->ID;
324
- }
325
-
326
- $permalink = get_post_meta( $post_id, 'custom_permalink', true );
327
-
328
- ?>
329
- <div class="postbox closed">
330
- <h3><?php _e('Custom Permalink', 'custom-permalinks') ?></h3>
331
- <div class="inside">
332
- <?php custom_permalinks_form($permalink, custom_permalinks_original_post_link($post_id)); ?>
333
- </div>
334
- </div>
335
- <?php
336
- }
337
-
338
- /**
339
- * Per-page options (Wordpress < 2.9)
340
- */
341
- function custom_permalinks_page_options() {
342
- global $post;
343
- $post_id = $post;
344
- if (is_object($post_id)) {
345
- $post_id = $post_id->ID;
346
- }
347
-
348
- $permalink = get_post_meta( $post_id, 'custom_permalink', true );
349
-
350
- ?>
351
- <div class="postbox closed">
352
- <h3><?php _e('Custom Permalink', 'custom-permalinks') ?></h3>
353
- <div class="inside">
354
- <?php custom_permalinks_form($permalink, custom_permalinks_original_page_link($post_id)); ?>
355
- </div>
356
- </div>
357
- <?php
358
- }
359
-
360
- /**
361
- * Per-category/tag options
362
- */
363
- function custom_permalinks_term_options($object) {
364
- if ( is_object($object) && isset($object->term_id) ) {
365
- $permalink = custom_permalinks_permalink_for_term($object->term_id);
366
-
367
- if ( $object->term_id ) {
368
- $originalPermalink = ($object->taxonomy == 'post_tag' ?
369
- custom_permalinks_original_tag_link($object->term_id) :
370
- custom_permalinks_original_category_link($object->term_id) );
371
- }
372
-
373
- custom_permalinks_form($permalink, $originalPermalink);
374
- } else {
375
- custom_permalinks_form('');
376
- }
377
-
378
- // Move the save button to above this form
379
- wp_enqueue_script('jquery');
380
- ?>
381
- <script type="text/javascript">
382
- jQuery(document).ready(function() {
383
- var button = jQuery('#custom_permalink_form').parent().find('.submit');
384
- button.remove().insertAfter(jQuery('#custom_permalink_form'));
385
- });
386
- </script>
387
- <?php
388
- }
389
-
390
- /**
391
- * Helper function to render form
392
- */
393
- function custom_permalinks_form($permalink, $original="", $renderContainers=true) {
394
- ?>
395
- <input value="true" type="hidden" name="custom_permalinks_edit" />
396
- <input value="<?php echo htmlspecialchars(urldecode($permalink)) ?>" type="hidden" name="custom_permalink" id="custom_permalink" />
397
-
398
- <?php if ( $renderContainers ) : ?>
399
- <table class="form-table" id="custom_permalink_form">
400
- <tr>
401
- <th scope="row"><?php _e('Custom Permalink', 'custom-permalinks') ?></th>
402
- <td>
403
- <?php endif; ?>
404
-
405
- <?php
406
- if ($permalink == '') {
407
- $original = custom_permalinks_check_conflicts($original);
408
- }
409
- ?>
410
-
411
- <?php echo home_url() ?>/
412
- <span id="editable-post-name" title="Click to edit this part of the permalink">
413
- <input type="text" id="new-post-slug" class="text" value="<?php echo htmlspecialchars($permalink ? urldecode($permalink) : urldecode($original)) ?>"
414
- style="width: 250px; <?php if ( !$permalink ) echo 'color: #ddd;' ?>"
415
- onfocus="if ( this.style.color = '#ddd' ) { this.style.color = '#000'; }"
416
- 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'; }"/>
417
- </span>
418
- <?php if ( $renderContainers ) : ?>
419
- <br />
420
- <small><?php _e('Leave blank to disable', 'custom-permalinks') ?></small>
421
-
422
- </td>
423
- </tr>
424
- </table>
425
- <?php
426
- endif;
427
- }
428
-
429
- /**
430
- * Save per-post options
431
- */
432
- function custom_permalinks_save_post($id) {
433
- if ( !isset($_REQUEST['custom_permalinks_edit']) ) return;
434
-
435
- delete_post_meta( $id, 'custom_permalink' );
436
-
437
- $original_link = custom_permalinks_original_post_link($id);
438
- $permalink_structure = get_option('permalink_structure');
439
-
440
- if ( $_REQUEST['custom_permalink'] && $_REQUEST['custom_permalink'] != $original_link ) {
441
- add_post_meta( $id, 'custom_permalink', str_replace('%2F', '/', urlencode(ltrim(stripcslashes($_REQUEST['custom_permalink']),"/"))) );
442
- }
443
- }
444
-
445
- /**
446
- * Save per-tag options
447
- */
448
- function custom_permalinks_save_tag($id) {
449
- if ( !isset($_REQUEST['custom_permalinks_edit']) || isset($_REQUEST['post_ID']) ) return;
450
- $newPermalink = ltrim(stripcslashes($_REQUEST['custom_permalink']),"/");
451
-
452
- if ( $newPermalink == custom_permalinks_original_tag_link($id) )
453
- $newPermalink = '';
454
-
455
- $term = get_term($id, 'post_tag');
456
- custom_permalinks_save_term($term, str_replace('%2F', '/', urlencode($newPermalink)));
457
- }
458
-
459
- /**
460
- * Save per-category options
461
- */
462
- function custom_permalinks_save_category($id) {
463
- if ( !isset($_REQUEST['custom_permalinks_edit']) || isset($_REQUEST['post_ID']) ) return;
464
- $newPermalink = ltrim(stripcslashes($_REQUEST['custom_permalink']),"/");
465
-
466
- if ( $newPermalink == custom_permalinks_original_category_link($id) )
467
- $newPermalink = '';
468
-
469
- $term = get_term($id, 'category');
470
- custom_permalinks_save_term($term, str_replace('%2F', '/', urlencode($newPermalink)));
471
- }
472
-
473
- /**
474
- * Save term (common to tags and categories)
475
- */
476
- function custom_permalinks_save_term($term, $permalink) {
477
-
478
- custom_permalinks_delete_term($term->term_id);
479
- $table = get_option('custom_permalink_table');
480
- if ( $permalink )
481
- $table[$permalink] = array(
482
- 'id' => $term->term_id,
483
- 'kind' => ($term->taxonomy == 'category' ? 'category' : 'tag'),
484
- 'slug' => $term->slug);
485
-
486
- update_option('custom_permalink_table', $table);
487
- }
488
-
489
- /**
490
- * Delete post
491
- */
492
- function custom_permalinks_delete_permalink( $id ){
493
- global $wpdb;
494
- // Queries are now WP3.9 compatible (by Steve from Sowmedia.nl)
495
- $wpdb->query($wpdb->prepare("DELETE FROM $wpdb->postmeta WHERE `meta_key` = 'custom_permalink' AND `post_id` = %d", $id));
496
- }
497
-
498
- /**
499
- * Delete term
500
- */
501
- function custom_permalinks_delete_term($id) {
502
-
503
- $table = get_option('custom_permalink_table');
504
- if ( $table )
505
- foreach ( $table as $link => $info ) {
506
- if ( $info['id'] == $id ) {
507
- unset($table[$link]);
508
- break;
509
- }
510
- }
511
-
512
- update_option('custom_permalink_table', $table);
513
- }
514
-
515
- /**
516
- * Options page
517
- */
518
- function custom_permalinks_options_page() {
519
-
520
- // Handle revert
521
- if ( isset($_REQUEST['revertit']) && isset($_REQUEST['revert']) ) {
522
- check_admin_referer('custom-permalinks-bulk');
523
- foreach ( (array)$_REQUEST['revert'] as $identifier ) {
524
- list($kind, $id) = explode('.', $identifier);
525
- switch ( $kind ) {
526
- case 'post':
527
- case 'page':
528
- delete_post_meta( $id, 'custom_permalink' );
529
- break;
530
- case 'tag':
531
- case 'category':
532
- custom_permalinks_delete_term($id);
533
- break;
534
- }
535
- }
536
-
537
- // Redirect
538
- $redirectUrl = $_SERVER['REQUEST_URI'];
539
- ?>
540
- <script type="text/javascript">
541
- document.location = '<?php echo $redirectUrl ?>'
542
- </script>
543
- <?php ;
544
- }
545
-
546
- ?>
547
- <div class="wrap">
548
- <h2><?php _e('Custom Permalinks', 'custom-permalinks') ?></h2>
549
-
550
- <form method="post" action="<?php echo $_SERVER['REQUEST_URI'] ?>">
551
- <?php wp_nonce_field('custom-permalinks-bulk') ?>
552
-
553
- <div class="tablenav">
554
- <div class="alignleft">
555
- <input type="submit" value="<?php _e('Revert', 'custom-permalinks'); ?>" name="revertit" class="button-secondary delete" />
556
- </div>
557
- <br class="clear" />
558
- </div>
559
- <br class="clear" />
560
- <table class="widefat">
561
- <thead>
562
- <tr>
563
- <th scope="col" class="check-column"><input type="checkbox" /></th>
564
- <th scope="col"><?php _e('Title', 'custom-permalinks') ?></th>
565
- <th scope="col"><?php _e('Type', 'custom-permalinks') ?></th>
566
- <th scope="col"><?php _e('Permalink', 'custom-permalinks') ?></th>
567
- </tr>
568
- </thead>
569
- <tbody>
570
- <?php
571
- $rows = custom_permalinks_admin_rows();
572
- foreach ( $rows as $row ) {
573
- ?>
574
- <tr valign="top">
575
- <th scope="row" class="check-column"><input type="checkbox" name="revert[]" value="<?php echo $row['id'] ?>" /></th>
576
- <td><strong><a class="row-title" href="<?php echo htmlspecialchars($row['editlink']) ?>"><?php echo htmlspecialchars($row['title']) ?></a></strong></td>
577
- <td><?php echo htmlspecialchars($row['type']) ?></td>
578
- <td><a href="<?php echo $row['permalink'] ?>" target="_blank" title="<?php printf(__('Visit %s', 'custom-permalinks'), htmlspecialchars($row['title'])) ?>">
579
- <?php echo htmlspecialchars(urldecode($row['permalink'])) ?>
580
- </a>
581
- </td>
582
- </tr>
583
- <?php
584
- }
585
- ?>
586
- </tbody>
587
- </table>
588
- </form>
589
- </div>
590
- <?php
591
- }
592
-
593
- /**
594
- * Get rows for management view
595
- */
596
- function custom_permalinks_admin_rows() {
597
- $rows = array();
598
-
599
- // List tags/categories
600
- $table = get_option('custom_permalink_table');
601
- if ( $table && is_array($table) ) {
602
- foreach ( $table as $permalink => $info ) {
603
- $row = array();
604
- $term = get_term($info['id'], ($info['kind'] == 'tag' ? 'post_tag' : 'category'));
605
- $row['id'] = $info['kind'].'.'.$info['id'];
606
- $row['permalink'] = home_url()."/".$permalink;
607
- $row['type'] = ucwords($info['kind']);
608
- $row['title'] = $term->name;
609
- $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'] );
610
- $rows[] = $row;
611
- }
612
- }
613
-
614
- // List posts/pages
615
- global $wpdb;
616
- $query = "SELECT $wpdb->posts.* FROM $wpdb->posts LEFT JOIN $wpdb->postmeta ON ($wpdb->posts.ID = $wpdb->postmeta.post_id) WHERE
617
- $wpdb->postmeta.meta_key = 'custom_permalink' AND $wpdb->postmeta.meta_value != '';";
618
- $posts = $wpdb->get_results($query);
619
- foreach ( $posts as $post ) {
620
- $row = array();
621
- $row['id'] = 'post.'.$post->ID;
622
- $row['permalink'] = get_permalink($post->ID);
623
- $row['type'] = ucwords( $post->post_type );
624
- $row['title'] = $post->post_title;
625
- $row['editlink'] = 'post.php?action=edit&post='.$post->ID;
626
- $rows[] = $row;
627
- }
628
-
629
- return $rows;
630
- }
631
-
632
- /**
633
- * Get original permalink for post
634
- */
635
- function custom_permalinks_original_post_link($post_id) {
636
- remove_filter( 'post_link', 'custom_permalinks_post_link', 10, 3 ); // original hook
637
- remove_filter( 'post_type_link', 'custom_permalinks_post_link', 10, 2 );
638
-
639
- require_once ABSPATH . '/wp-admin/includes/post.php';
640
- list( $permalink, $post_name ) = get_sample_permalink( $post_id );
641
- $permalink = str_replace(array('%pagename%','%postname%'), $post_name, $permalink);
642
- $permalink = ltrim(str_replace(home_url(), '', $permalink), '/');
643
-
644
- add_filter( 'post_link', 'custom_permalinks_post_link', 10, 3 ); // original hook
645
- add_filter( 'post_type_link', 'custom_permalinks_post_link', 10, 2 );
646
-
647
- return $permalink;
648
- }
649
-
650
- /**
651
- * Get original permalink for page
652
- */
653
- function custom_permalinks_original_page_link($post_id) {
654
- remove_filter( 'page_link', 'custom_permalinks_page_link', 10, 2 );
655
- remove_filter( 'user_trailingslashit', 'custom_permalinks_trailingslash', 10, 2 );
656
-
657
- require_once ABSPATH . '/wp-admin/includes/post.php';
658
- list( $permalink, $post_name ) = get_sample_permalink( $post_id );
659
- $permalink = str_replace(array('%pagename%','%postname%'), $post_name, $permalink);
660
- $permalink = ltrim(str_replace(home_url(), '', $permalink), '/');
661
-
662
- add_filter( 'user_trailingslashit', 'custom_permalinks_trailingslash', 10, 2 );
663
- add_filter( 'page_link', 'custom_permalinks_page_link', 10, 2 );
664
- return $permalink;
665
- }
666
-
667
- /**
668
- * Get original permalink for tag
669
- */
670
- function custom_permalinks_original_tag_link($tag_id) {
671
- remove_filter( 'tag_link', 'custom_permalinks_term_link', 10, 2 );
672
- remove_filter( 'user_trailingslashit', 'custom_permalinks_trailingslash', 10, 2 );
673
- $originalPermalink = ltrim(str_replace(home_url(), '', get_tag_link($tag_id)), '/');
674
- add_filter( 'user_trailingslashit', 'custom_permalinks_trailingslash', 10, 2 );
675
- add_filter( 'tag_link', 'custom_permalinks_term_link', 10, 2 );
676
- return $originalPermalink;
677
- }
678
-
679
- /**
680
- * Get original permalink for category
681
- */
682
- function custom_permalinks_original_category_link($category_id) {
683
- remove_filter( 'category_link', 'custom_permalinks_term_link', 10, 2 );
684
- remove_filter( 'user_trailingslashit', 'custom_permalinks_trailingslash', 10, 2 );
685
- $originalPermalink = ltrim(str_replace(home_url(), '', get_category_link($category_id)), '/');
686
- add_filter( 'user_trailingslashit', 'custom_permalinks_trailingslash', 10, 2 );
687
- add_filter( 'category_link', 'custom_permalinks_term_link', 10, 2 );
688
- return $originalPermalink;
689
- }
690
-
691
- /**
692
- * Get permalink for term
693
- */
694
- function custom_permalinks_permalink_for_term($id) {
695
- $table = get_option('custom_permalink_table');
696
- if ( $table )
697
- foreach ( $table as $link => $info ) {
698
- if ( $info['id'] == $id ) {
699
- return $link;
700
- }
701
- }
702
- return false;
703
- }
704
-
705
- /**
706
- * Set up administration menu
707
- */
708
- function custom_permalinks_setup_admin_menu() {
709
- add_management_page( 'Custom Permalinks', 'Custom Permalinks', 'edit_others_pages', 'custom_permalinks', 'custom_permalinks_options_page' );
710
  }
711
 
712
  /**
713
- * Check Conflicts and resolve it (e.g: Polylang)
714
  */
715
- function custom_permalinks_check_conflicts($requested_url = '') {
716
-
717
- if ($requested_url == '') return;
718
-
719
- // Check if the Polylang Plugin is installed so, make changes in the URL
720
- if (defined( 'POLYLANG_VERSION' )) {
721
- $polylang_config = get_option('polylang');
722
- if ($polylang_config['force_lang'] == 1) {
723
-
724
- if(strpos($requested_url, 'language/') !== false)
725
- $requested_url = str_replace("language/", "", $requested_url);
726
-
727
- $remove_lang = ltrim(strstr($requested_url, '/'), '/');
728
- if ($remove_lang != '')
729
- return $remove_lang;
730
- }
731
- }
732
-
733
- return $requested_url;
734
- }
735
-
736
- if (function_exists("add_action") && function_exists("add_filter")) {
737
- add_action( 'template_redirect', 'custom_permalinks_redirect', 5 );
738
- add_filter( 'post_link', 'custom_permalinks_post_link', 10, 3 );
739
- add_filter( 'post_type_link', 'custom_permalinks_post_link', 10, 2 );
740
- add_filter( 'page_link', 'custom_permalinks_page_link', 10, 2 );
741
- add_filter( 'tag_link', 'custom_permalinks_term_link', 10, 2 );
742
- add_filter( 'category_link', 'custom_permalinks_term_link', 10, 2 );
743
- add_filter( 'request', 'custom_permalinks_request', 10, 1 );
744
- add_filter( 'user_trailingslashit', 'custom_permalinks_trailingslash', 10, 2 );
745
-
746
- if (function_exists("get_bloginfo")) {
747
- $v = explode('.', get_bloginfo('version'));
748
- }
749
-
750
- if ( $v[0] >= 2 ) {
751
- add_filter( 'get_sample_permalink_html', 'custom_permalink_get_sample_permalink_html', 10, 4 );
752
- } else {
753
- add_action( 'edit_form_advanced', 'custom_permalinks_post_options' );
754
- add_action( 'edit_page_form', 'custom_permalinks_page_options' );
755
- }
756
-
757
- add_action( 'edit_tag_form', 'custom_permalinks_term_options' );
758
- add_action( 'add_tag_form', 'custom_permalinks_term_options' );
759
- add_action( 'edit_category_form', 'custom_permalinks_term_options' );
760
- add_action( 'save_post', 'custom_permalinks_save_post' );
761
- add_action( 'save_page', 'custom_permalinks_save_post' );
762
- add_action( 'edited_post_tag', 'custom_permalinks_save_tag' );
763
- add_action( 'edited_category', 'custom_permalinks_save_category' );
764
- add_action( 'create_post_tag', 'custom_permalinks_save_tag' );
765
- add_action( 'create_category', 'custom_permalinks_save_category' );
766
- add_action( 'delete_post', 'custom_permalinks_delete_permalink', 10);
767
- add_action( 'delete_post_tag', 'custom_permalinks_delete_term' );
768
- add_action( 'delete_post_category', 'custom_permalinks_delete_term' );
769
- add_action( 'admin_menu', 'custom_permalinks_setup_admin_menu' );
770
  }
 
1
  <?php
 
2
  /**
3
  * @package CustomPermalinks\Main
4
  */
5
 
6
  // Make sure we don't expose any info if called directly
7
+ if ( ! defined( 'ABSPATH' ) ) {
8
+ echo 'Hi there! I\'m just a plugin, not much I can do when called directly.';
9
+ exit;
10
  }
11
 
12
+ if ( ! function_exists( "add_action" ) || ! function_exists( "add_filter" ) ) {
13
+ header( 'Status: 403 Forbidden' );
14
+ header( 'HTTP/1.1 403 Forbidden' );
15
+ exit();
16
  }
17
 
18
+ define( 'CUSTOM_PERMALINKS_PLUGIN_VERSION', '1.2' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
+ if ( ! defined( 'CUSTOM_PERMALINKS_PATH' ) ) {
21
+ define( 'CUSTOM_PERMALINKS_PATH', plugin_dir_path( __FILE__ ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  }
23
 
24
+ require_once( CUSTOM_PERMALINKS_PATH . 'frontend/class-custom-permalinks-frontend.php' );
25
+ $custom_permalinks_frontend = new Custom_Permalinks_Frontend();
26
+ $custom_permalinks_frontend->init();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
 
28
+ require_once( CUSTOM_PERMALINKS_PATH . 'admin/class-custom-permalinks-form.php' );
29
+ $custom_permalinks_form = new Custom_Permalinks_Form();
30
+ $custom_permalinks_form->init();
 
 
 
31
 
32
+ if ( is_admin() ) {
33
+ require_once( CUSTOM_PERMALINKS_PATH . 'admin/class-custom-permalinks-admin.php' );
34
+ new Custom_Permalinks_Admin();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  }
36
 
37
  /**
38
+ * Add textdomain hook for translation
39
  */
40
+ function custom_permalinks_translation_capability() {
41
+ load_plugin_textdomain( 'custom-permalinks', FALSE, basename( dirname( __FILE__ ) ) . '/languages/' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  }
43
+ add_action( 'plugins_loaded', 'custom_permalinks_translation_capability' );
custom-permalinks.php CHANGED
@@ -1,21 +1,23 @@
1
  <?php
2
 
3
- /**
4
- * @package CustomPermalinks
5
- */
6
-
7
  /**
8
  * Plugin Name: Custom Permalinks
9
  * Plugin URI: https://wordpress.org/plugins/custom-permalinks/
10
- * Donate link: https://www.paypal.me/yasglobal
11
  * Description: Set custom permalinks on a per-post basis
12
- * Version: 1.1
13
  * Author: Sami Ahmed Siddiqui
14
  * Author URI: https://www.yasglobal.com/web-design-development/wordpress/custom-permalinks/
 
 
 
15
  * Text Domain: custom-permalinks
 
 
 
16
  */
17
 
18
  /**
 
19
  * Copyright 2008-2017 Sami Ahmed Siddiqui <sami@samisiddiqui.com>
20
  *
21
  * This program is free software; you can redistribute it and/or modify
@@ -35,11 +37,11 @@
35
 
36
  // Make sure we don't expose any info if called directly
37
  if ( ! defined( 'ABSPATH' ) ) {
38
- echo 'Hi there! I\'m just a plugin, not much I can do when called directly.';
39
- exit;
40
  }
41
 
42
- if ( !function_exists("add_action") || !function_exists("add_filter") ) {
43
  header( 'Status: 403 Forbidden' );
44
  header( 'HTTP/1.1 403 Forbidden' );
45
  exit();
1
  <?php
2
 
 
 
 
 
3
  /**
4
  * Plugin Name: Custom Permalinks
5
  * Plugin URI: https://wordpress.org/plugins/custom-permalinks/
 
6
  * Description: Set custom permalinks on a per-post basis
7
+ * Version: 1.2
8
  * Author: Sami Ahmed Siddiqui
9
  * Author URI: https://www.yasglobal.com/web-design-development/wordpress/custom-permalinks/
10
+ * Donate link: https://www.paypal.me/yasglobal
11
+ * License: GPLv2 or later
12
+ *
13
  * Text Domain: custom-permalinks
14
+ * Domain Path: /languages/
15
+ *
16
+ * @package CustomPermalinks
17
  */
18
 
19
  /**
20
+ * Custom Permalinks Plugin
21
  * Copyright 2008-2017 Sami Ahmed Siddiqui <sami@samisiddiqui.com>
22
  *
23
  * This program is free software; you can redistribute it and/or modify
37
 
38
  // Make sure we don't expose any info if called directly
39
  if ( ! defined( 'ABSPATH' ) ) {
40
+ echo 'Hi there! I\'m just a plugin, not much I can do when called directly.';
41
+ exit;
42
  }
43
 
44
+ if ( ! function_exists( "add_action" ) || ! function_exists( "add_filter" ) ) {
45
  header( 'Status: 403 Forbidden' );
46
  header( 'HTTP/1.1 403 Forbidden' );
47
  exit();
frontend/class-custom-permalinks-frontend.php ADDED
@@ -0,0 +1,376 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @package CustomPermalinks\Frontend
4
+ */
5
+
6
+ class Custom_Permalinks_Frontend {
7
+
8
+ /**
9
+ * Initialize WordPress Hooks
10
+ */
11
+ public function init() {
12
+ add_filter( 'request', array( $this, 'custom_permalinks_request' ), 10, 1 );
13
+
14
+ add_action( 'template_redirect', array( $this, 'custom_permalinks_redirect' ), 5 );
15
+
16
+ add_filter( 'post_link', array( $this, 'custom_permalinks_post_link' ), 10, 2 );
17
+ add_filter( 'post_type_link', array( $this, 'custom_permalinks_post_link' ), 10, 2 );
18
+ add_filter( 'page_link', array( $this, 'custom_permalinks_page_link' ), 10, 2 );
19
+
20
+ add_filter( 'tag_link', array( $this, 'custom_permalinks_term_link' ), 10, 2 );
21
+ add_filter( 'category_link', array( $this, 'custom_permalinks_term_link' ), 10, 2 );
22
+
23
+ add_filter( 'user_trailingslashit', array( $this, 'custom_permalinks_trailingslash' ), 10, 2 );
24
+ }
25
+
26
+ /**
27
+ * Filter to rewrite the query if we have a matching post
28
+ */
29
+ public function custom_permalinks_request( $query ) {
30
+ global $wpdb;
31
+ global $_CPRegisteredURL;
32
+
33
+ // First, search for a matching custom permalink,
34
+ // and if found, generate the corresponding original URL
35
+
36
+ $original_url = NULL;
37
+
38
+ // Get request URI, strip parameters and /'s
39
+ $url = parse_url( get_bloginfo( 'url' ) );
40
+ $url = isset( $url['path'] ) ? $url['path'] : '';
41
+ $request = ltrim( substr( $_SERVER['REQUEST_URI'], strlen( $url ) ), '/' );
42
+ $request = ( ( $pos = strpos( $request, '?' ) ) ? substr( $request, 0, $pos ) : $request );
43
+
44
+ if ( ! $request ) return $query;
45
+
46
+ $ignore = apply_filters( 'custom_permalinks_request_ignore', $request );
47
+
48
+ if ( $ignore === '__true' ) return $query;
49
+
50
+ if ( defined( 'POLYLANG_VERSION' ) ) {
51
+ require_once( CUSTOM_PERMALINKS_PATH . 'admin/class-custom-permalinks-admin.php' );
52
+ $custom_permalinks_admin = new Custom_Permalinks_Admin();
53
+ $request = $custom_permalinks_admin->custom_permalinks_check_conflicts( $request );
54
+ }
55
+ $request_noslash = preg_replace( '@/+@','/', trim( $request, '/' ) );
56
+
57
+ $sql = $wpdb->prepare( "SELECT $wpdb->posts.ID, $wpdb->postmeta.meta_value, $wpdb->posts.post_type, $wpdb->posts.post_status FROM $wpdb->posts " .
58
+ " LEFT JOIN $wpdb->postmeta ON ($wpdb->posts.ID = $wpdb->postmeta.post_id) WHERE " .
59
+ " meta_key = 'custom_permalink' AND meta_value != '' AND " .
60
+ " ( LOWER(meta_value) = LEFT(LOWER('%s'), LENGTH(meta_value)) OR " .
61
+ " LOWER(meta_value) = LEFT(LOWER('%s'), LENGTH(meta_value)) ) " .
62
+ " AND post_status != 'trash' AND post_type != 'nav_menu_item'" .
63
+ " ORDER BY LENGTH(meta_value) DESC, " .
64
+ " FIELD(post_status,'publish','private','draft','auto-draft','inherit')," .
65
+ " FIELD(post_type,'post','page'), $wpdb->posts.ID ASC LIMIT 1",
66
+ $request_noslash, $request_noslash . "/" );
67
+
68
+ $posts = $wpdb->get_results( $sql );
69
+
70
+ if ( $posts ) {
71
+ // A post matches our request
72
+
73
+ // Preserve this url for later if it's the same as the permalink (no extra stuff)
74
+ if ( $request_noslash == trim( $posts[0]->meta_value, '/') )
75
+ $_CPRegisteredURL = $request;
76
+
77
+ if ( $posts[0]->post_status == 'draft' ) {
78
+ if ( $posts[0]->post_type == 'page' ) {
79
+ $original_url = "?page_id=" . $posts[0]->ID;
80
+ } else {
81
+ $original_url = "?post_type=".$posts[0]->post_type."&p=" . $posts[0]->ID;
82
+ }
83
+ } else {
84
+ $post_meta = trim( strtolower( $posts[0]->meta_value ), '/' );
85
+ if ( $posts[0]->post_type == 'page' ) {
86
+ $get_original_url = $this->custom_permalinks_original_page_link( $posts[0]->ID );
87
+ $original_url = preg_replace( '@/+@', '/',
88
+ str_replace( $post_meta, $get_original_url, strtolower( $request_noslash ) )
89
+ );
90
+ } else {
91
+ $get_original_url = $this->custom_permalinks_original_post_link( $posts[0]->ID );
92
+ $original_url = preg_replace( '@/+@', '/',
93
+ str_replace( $post_meta, $get_original_url, strtolower( $request_noslash ) )
94
+ );
95
+ }
96
+ }
97
+ }
98
+
99
+ if ( $original_url === NULL ) {
100
+ // See if any terms have a matching permalink
101
+ $table = get_option('custom_permalink_table');
102
+ if ( ! $table ) return $query;
103
+
104
+ foreach ( array_keys( $table ) as $permalink ) {
105
+ if ( $permalink == substr( $request_noslash, 0, strlen( $permalink ) )
106
+ || $permalink == substr( $request_noslash . "/", 0, strlen( $permalink ) ) ) {
107
+ $term = $table[$permalink];
108
+
109
+ // Preserve this url for later if it's the same as the permalink (no extra stuff)
110
+ if ( $request_noslash == trim( $permalink, '/' ) )
111
+ $_CPRegisteredURL = $request;
112
+
113
+ if ( $term['kind'] == 'category') {
114
+ $category_link = $this->custom_permalinks_original_category_link( $term['id'] );
115
+ $original_url = str_replace( trim( $permalink, '/' ), $category_link, trim( $request, '/' ) );
116
+ } else {
117
+ $category_link = $this->custom_permalinks_original_tag_link( $term['id'] );
118
+ $original_url = str_replace( trim( $permalink, '/' ), $category_link, trim( $request, '/' ) );
119
+ }
120
+ }
121
+ }
122
+ }
123
+
124
+ if ( $original_url !== NULL ) {
125
+ $original_url = str_replace( '//', '/', $original_url );
126
+
127
+ if ( ( $pos = strpos( $_SERVER['REQUEST_URI'], '?' ) ) !== false ) {
128
+ $query_vars = substr( $_SERVER['REQUEST_URI'], $pos + 1);
129
+ $original_url .= ( strpos( $original_url, '?' ) === false ? '?' : '&') . $query_vars;
130
+ }
131
+
132
+ // Now we have the original URL, run this back through WP->parse_request, in order to
133
+ // parse parameters properly. We set $_SERVER variables to fool the function.
134
+ $old_request_uri = $_SERVER['REQUEST_URI']; $old_query_string = $_SERVER['QUERY_STRING'];
135
+ $_SERVER['REQUEST_URI'] = '/' . ltrim( $original_url, '/');
136
+ $_SERVER['QUERY_STRING'] = ( ( $pos = strpos( $original_url, '?' ) ) !== false ? substr( $original_url, $pos + 1 ) : '');
137
+ parse_str( $_SERVER['QUERY_STRING'], $query_array );
138
+ $old_values = array();
139
+ if ( is_array( $query_array ) )
140
+ foreach ( $query_array as $key => $value ) {
141
+ $old_values[$key] = $_REQUEST[$key];
142
+ $_REQUEST[$key] = $_GET[$key] = $value;
143
+ }
144
+
145
+ // Re-run the filter, now with original environment in place
146
+ remove_filter( 'request', array( $this, 'custom_permalinks_request'), 10, 1 );
147
+ global $wp;
148
+ $wp->parse_request();
149
+ $query = $wp->query_vars;
150
+ add_filter( 'request', array( $this, 'custom_permalinks_request'), 10, 1 );
151
+
152
+ // Restore values
153
+ $_SERVER['REQUEST_URI'] = $old_request_uri; $_SERVER['QUERY_STRING'] = $old_query_string;
154
+ foreach ( $old_values as $key => $value ) {
155
+ $_REQUEST[$key] = $value;
156
+ }
157
+ }
158
+
159
+ return $query;
160
+ }
161
+
162
+ /**
163
+ * Action to redirect to the custom permalink
164
+ */
165
+ public function custom_permalinks_redirect() {
166
+ // Get request URI, strip parameters
167
+ $url = parse_url( get_bloginfo( 'url' ) );
168
+ $url = isset( $url['path'] ) ? $url['path'] : '';
169
+ $request = ltrim( substr( $_SERVER['REQUEST_URI'], strlen( $url ) ), '/' );
170
+ if ( ( $pos = strpos( $request, "?" ) ) ) $request = substr( $request, 0, $pos );
171
+
172
+ if ( defined( 'POLYLANG_VERSION' ) ) {
173
+ require_once( CUSTOM_PERMALINKS_PATH . 'admin/class-custom-permalinks-admin.php' );
174
+ $custom_permalinks_admin = new Custom_Permalinks_Admin();
175
+ $request = $custom_permalinks_admin->custom_permalinks_check_conflicts( $request );
176
+ }
177
+
178
+ global $wp_query;
179
+
180
+ $custom_permalink = '';
181
+ $original_permalink = '';
182
+
183
+ // If the post/tag/category we're on has a custom permalink, get it and check against the request
184
+ if ( ( is_single() || is_page() ) && ! empty( $wp_query->post ) ) {
185
+ $post = $wp_query->post;
186
+ $custom_permalink = get_post_meta( $post->ID, 'custom_permalink', true );
187
+ if ( $post->post_type == 'page' ) {
188
+ $original_permalink = $this->custom_permalinks_original_page_link( $post->ID );
189
+ } else {
190
+ $original_permalink = $this->custom_permalinks_original_post_link( $post->ID );
191
+ }
192
+ } else if ( is_tag() || is_category() ) {
193
+ $theTerm = $wp_query->get_queried_object();
194
+ $custom_permalink = $this->custom_permalinks_permalink_for_term( $theTerm->term_id );
195
+ if ( is_tag() ) {
196
+ $original_permalink = $this->custom_permalinks_original_tag_link( $theTerm->term_id );
197
+ } else {
198
+ $original_permalink = $this->custom_permalinks_original_category_link( $theTerm->term_id );
199
+ }
200
+ }
201
+
202
+ if ( $custom_permalink
203
+ && ( substr($request, 0, strlen( $custom_permalink ) ) != $custom_permalink
204
+ || $request == $custom_permalink . "/" ) ) {
205
+
206
+ // Request doesn't match permalink - redirect
207
+ $url = $custom_permalink;
208
+
209
+ if ( substr( $request, 0, strlen( $original_permalink ) ) == $original_permalink
210
+ && trim( $request, '/' ) != trim( $original_permalink, '/' ) ) {
211
+ // This is the original link; we can use this url to derive the new one
212
+ $url = preg_replace( '@//*@', '/', str_replace( trim( $original_permalink, '/' ), trim( $custom_permalink, '/' ), $request ) );
213
+ $url = preg_replace( '@([^?]*)&@', '\1?', $url );
214
+ }
215
+
216
+ // Append any query compenent
217
+ $url .= strstr( $_SERVER['REQUEST_URI'], "?" );
218
+
219
+ wp_redirect( home_url() . "/" . $url, 301 );
220
+ exit();
221
+ }
222
+ }
223
+
224
+ /**
225
+ * Filter to replace the post permalink with the custom one
226
+ */
227
+ public function custom_permalinks_post_link( $permalink, $post ) {
228
+ $custom_permalink = get_post_meta( $post->ID, 'custom_permalink', true );
229
+ if ( $custom_permalink ) {
230
+ $post_type = isset( $post->post_type ) ? $post->post_type : 'post';
231
+ $language_code = apply_filters( 'wpml_element_language_code', null, array( 'element_id' => $post->ID, 'element_type' => $post_type ) );
232
+ if ( $language_code )
233
+ return apply_filters( 'wpml_permalink', home_url() . "/" . $custom_permalink, $language_code );
234
+ else
235
+ return apply_filters( 'wpml_permalink', home_url() . "/" . $custom_permalink );
236
+ }
237
+
238
+ return $permalink;
239
+ }
240
+
241
+ /**
242
+ * Filter to replace the page permalink with the custom one
243
+ */
244
+ public function custom_permalinks_page_link( $permalink, $page ) {
245
+ $custom_permalink = get_post_meta( $page, 'custom_permalink', true );
246
+ if ( $custom_permalink ) {
247
+ $language_code = apply_filters( 'wpml_element_language_code', null, array( 'element_id' => $page, 'element_type' => 'page' ) );
248
+ if ( $language_code )
249
+ return apply_filters( 'wpml_permalink', home_url() . "/" . $custom_permalink, $language_code );
250
+ else
251
+ return apply_filters( 'wpml_permalink', home_url() . "/" . $custom_permalink );
252
+ }
253
+
254
+ return $permalink;
255
+ }
256
+
257
+ /**
258
+ * Filter to replace the term permalink with the custom one
259
+ */
260
+ public function custom_permalinks_term_link( $permalink, $term ) {
261
+ $table = get_option('custom_permalink_table');
262
+ if ( is_object($term) ) $term = $term->term_id;
263
+
264
+ $custom_permalink = $this->custom_permalinks_permalink_for_term( $term );
265
+ if ( $custom_permalink ) {
266
+ $taxonomy = get_term( $term );
267
+ if ( isset( $taxonomy ) && isset( $taxonomy->term_taxonomy_id ) ) {
268
+ $term_type = isset( $taxonomy->taxonomy ) ? $taxonomy->taxonomy : 'category';
269
+ $language_code = apply_filters( 'wpml_element_language_code', null, array( 'element_id' => $taxonomy->term_taxonomy_id, 'element_type' => $term_type ) );
270
+ return apply_filters( 'wpml_permalink', home_url() . "/" . $custom_permalink, $language_code );
271
+ } else {
272
+ return apply_filters( 'wpml_permalink', home_url() . "/" . $custom_permalink );
273
+ }
274
+ }
275
+
276
+ return $permalink;
277
+ }
278
+
279
+ /**
280
+ * Get original permalink for post
281
+ */
282
+ public function custom_permalinks_original_post_link( $post_id ) {
283
+ remove_filter( 'post_link', array( $this, 'custom_permalinks_post_link' ), 10, 3 );
284
+ remove_filter( 'post_type_link', array( $this, 'custom_permalinks_post_link' ), 10, 2 );
285
+
286
+ require_once ABSPATH . '/wp-admin/includes/post.php';
287
+ list( $permalink, $post_name ) = get_sample_permalink( $post_id );
288
+ $permalink = str_replace( array( '%pagename%','%postname%' ), $post_name, $permalink );
289
+ $permalink = ltrim( str_replace( home_url(), '', $permalink ), '/' );
290
+
291
+ add_filter( 'post_link', array( $this, 'custom_permalinks_post_link' ), 10, 3 );
292
+ add_filter( 'post_type_link', array( $this, 'custom_permalinks_post_link' ), 10, 2 );
293
+
294
+ return $permalink;
295
+ }
296
+
297
+ /**
298
+ * Get original permalink for page
299
+ */
300
+ public function custom_permalinks_original_page_link( $post_id ) {
301
+ remove_filter( 'page_link', array( $this, 'custom_permalinks_page_link' ), 10, 2 );
302
+ remove_filter( 'user_trailingslashit', array( $this, 'custom_permalinks_trailingslash' ), 10, 2 );
303
+
304
+ require_once ABSPATH . '/wp-admin/includes/post.php';
305
+ list( $permalink, $post_name ) = get_sample_permalink( $post_id );
306
+ $permalink = str_replace( array( '%pagename%','%postname%' ), $post_name, $permalink );
307
+ $permalink = ltrim( str_replace( home_url(), '', $permalink ), '/' );
308
+
309
+ add_filter( 'user_trailingslashit', array( $this, 'custom_permalinks_trailingslash' ), 10, 2 );
310
+ add_filter( 'page_link', array( $this, 'custom_permalinks_page_link' ), 10, 2 );
311
+ return $permalink;
312
+ }
313
+
314
+ /**
315
+ * Get original permalink for tag
316
+ */
317
+ public function custom_permalinks_original_tag_link( $tag_id ) {
318
+ remove_filter( 'tag_link', array( $this, 'custom_permalinks_term_link' ), 10, 2 );
319
+ remove_filter( 'user_trailingslashit', array( $this, 'custom_permalinks_trailingslash' ), 10, 2 );
320
+ $originalPermalink = ltrim( str_replace( home_url(), '', get_tag_link( $tag_id ) ), '/' );
321
+ add_filter( 'user_trailingslashit', array( $this, 'custom_permalinks_trailingslash' ), 10, 2 );
322
+ add_filter( 'tag_link', array( $this, 'custom_permalinks_term_link' ), 10, 2 );
323
+ return $originalPermalink;
324
+ }
325
+
326
+ /**
327
+ * Get original permalink for category
328
+ */
329
+ public function custom_permalinks_original_category_link( $category_id ) {
330
+ remove_filter( 'category_link', array( $this, 'custom_permalinks_term_link' ), 10, 2 );
331
+ remove_filter( 'user_trailingslashit', array( $this, 'custom_permalinks_trailingslash' ), 10, 2 );
332
+ $originalPermalink = ltrim( str_replace( home_url(), '', get_category_link( $category_id ) ), '/' );
333
+ add_filter( 'user_trailingslashit', array( $this, 'custom_permalinks_trailingslash' ), 10, 2 );
334
+ add_filter( 'category_link', array( $this, 'custom_permalinks_term_link' ), 10, 2 );
335
+ return $originalPermalink;
336
+ }
337
+
338
+ /**
339
+ * Filter to handle trailing slashes correctly
340
+ */
341
+ public function custom_permalinks_trailingslash( $string, $type ) {
342
+ global $_CPRegisteredURL;
343
+
344
+ remove_filter( 'user_trailingslashit', array( $this, 'custom_permalinks_trailingslash' ), 10, 2 );
345
+ $url = parse_url( get_bloginfo( 'url' ) );
346
+ $request = ltrim( isset( $url['path'] ) ? substr( $string, strlen( $url['path'] ) ) : $string, '/');
347
+ add_filter( 'user_trailingslashit', array( $this, 'custom_permalinks_trailingslash' ), 10, 2 );
348
+
349
+ if ( ! trim( $request ) ) return $string;
350
+
351
+ if ( trim( $_CPRegisteredURL, '/' ) == trim( $request, '/' ) ) {
352
+ if ( isset( $url['path'] ) ) {
353
+ return ( $string{0} == '/' ? '/' : '') . trailingslashit( $url['path'] ) . $_CPRegisteredURL;
354
+ } else {
355
+ return ( $string{0} == '/' ? '/' : '' ) . $_CPRegisteredURL;
356
+ }
357
+ }
358
+ return $string;
359
+ }
360
+
361
+
362
+ /**
363
+ * Get permalink for term
364
+ */
365
+ public function custom_permalinks_permalink_for_term( $id ) {
366
+ $table = get_option( 'custom_permalink_table' );
367
+ if ( $table )
368
+ foreach ( $table as $link => $info ) {
369
+ if ( $info['id'] == $id ) {
370
+ return $link;
371
+ }
372
+ }
373
+ return false;
374
+ }
375
+
376
+ }
frontend/index.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Silence is golden
4
+ */
index.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Silence is golden
4
+ */
readme.txt CHANGED
@@ -1,282 +1,305 @@
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.1
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.1 =
38
-
39
- * Enhancements
40
- * Added PostTypes Permalinks Page
41
- * View all the PostTypes permalinks
42
- * Search Permalinks
43
- * Sort by Title
44
- * Pagination
45
- * Added Categories Permalinks Page
46
- * View all the Category/Tags permalinks
47
- * Search Permalinks
48
- * Pagination
49
-
50
- * Bug Fixes
51
- * 404 Issues
52
- * Child pages bug
53
-
54
- = 1.0.2 =
55
-
56
- * Fixed Notice and some URL Issues
57
-
58
- = 1.0.1 =
59
-
60
- * Fixed issue with AMP Pages
61
-
62
- = 1.0 =
63
-
64
- * Updated Query on the `custom_permalinks_request` Function
65
-
66
- = 0.9.3 =
67
-
68
- * Fixed PolyLang Conflicts
69
-
70
- = 0.9.2 =
71
-
72
- * Fixed WPML Conflicts
73
-
74
- = 0.9.1 =
75
-
76
- * Fixed issues of Filters and Actions (Replaces 'edit_files' with 10)
77
-
78
- = 0.9 =
79
-
80
- * Resolved the conflict with PolyLang Plugin
81
-
82
- = 0.8 =
83
-
84
- * Fixed (Draft preview issue for custom post types + some PHP Warnings)
85
-
86
- = 0.7.28 =
87
-
88
- * Fixed draft preview issue(posts + pages)
89
-
90
- = 0.7.27 =
91
-
92
- * Fixed Loop Redirecting issue
93
-
94
- = 0.7.26 =
95
-
96
- * Fixed PHP Notice issue
97
-
98
- = 0.7.25 =
99
-
100
- * Fixed draft preview issue
101
-
102
- = 0.7.24 =
103
-
104
- * Fixed a problem with page URLs
105
-
106
- = 0.7.23 =
107
-
108
- * Fixed a problem with permalinks with "/" components
109
-
110
- = 0.7.22 =
111
-
112
- * Fixed PHP warning
113
- * Fixed initial permalink display for new posts/pages
114
-
115
- = 0.7.21 =
116
-
117
- * Minor internationalization fixes
118
-
119
- = 0.7.20 =
120
-
121
- * Addressed a noisy warning
122
- * Revised addition of admin forms js (don't use is_admin())
123
- * Updated Roles and Capabilities from depreciated numerical to label capabilities (by OF-6)
124
- * Added css/html to match WP 3.5+ layout (by OF-6)
125
-
126
- = 0.7.19 =
127
-
128
- * WP 3.9 compatibility fix, thanks to Sowmedia
129
-
130
- = 0.7.18 =
131
-
132
- * Patch to address 404 errors when displaying a page/post that shares a permalink with a trashed page/post, thanks to Tor Johnson
133
-
134
- = 0.7.17 =
135
-
136
- * Patch to address SSL problems, thanks to Amin Mirzaee
137
-
138
- = 0.7.16 =
139
-
140
- * Security and compatibility fixes by Hans-Michael Varbaek of Sense of Security
141
-
142
- = 0.7.15 =
143
-
144
- * Permalinks are now case-insensitive (thanks to @ericmann)
145
-
146
- = 0.7.14 =
147
-
148
- * Delete permalinks upon page/post deletion
149
-
150
- = 0.7.13 =
151
-
152
- * Fixed issue with term permalinks not working properly on some installations
153
-
154
- = 0.7.12 =
155
-
156
- * Fixed issue with feed URLs in non-webroot blog installations
157
-
158
- = 0.7.11 =
159
-
160
- * Fixed issue with pending/draft posts with permalinks
161
- * Fixed infinite redirect issue with permalinks without trailing slash, on blogs not hosted in the webroot
162
-
163
- = 0.7.10 =
164
-
165
- * Fix for 404 error on static front page with custom permalink set, by Eric TF Bat
166
-
167
- = 0.7.9 =
168
-
169
- * Support for custom post types, by Balázs Németh
170
-
171
- = 0.7.8 =
172
-
173
- * Support for non-ASCII characters in URLs
174
- * Fixed bug where adding a new tag when saving a post with a custom permalink attaches that permalink to the new tag
175
- * Some compatibility fixes for WP 3.2.1
176
-
177
- = 0.7.7 =
178
-
179
- * Minor change to permalink saving routine to fix some possible issues
180
- * Fixed issue with %-encoded permalinks
181
-
182
- = 0.7.6 =
183
-
184
- * Fixed permalink saving issue when not using ".../%postname%" or similar permalink structure
185
-
186
- = 0.7.5 =
187
-
188
- * Fixed issue where changes to trailing "/" aren't saved
189
-
190
- = 0.7.4 =
191
-
192
- * Added support for changing post/page slug only
193
- * Fixed incorrect admin edit link
194
-
195
- = 0.7.3 =
196
-
197
- * Fix problem with /page/# URLs on WP 3.1.3
198
-
199
- = 0.7.2 =
200
-
201
- * Don't clobber query parameters when redirecting to the custom permalink from the original URL
202
-
203
- = 0.7.1 =
204
-
205
- * Compatiblity fix for last update
206
-
207
- = 0.7 =
208
-
209
- * Added support for SSL sites, thanks to Dan from todaywasawesome.com
210
-
211
- = 0.6.1 =
212
-
213
- * Fix bug causing incorrect link from "View Post"/"View Page" button in post/page editor
214
-
215
- = 0.6 =
216
-
217
- * Fix infinite redirect for permalinks ending in a / (critical fix)
218
- * Moved post/page permalinks settings to top of edit form, replacing prior permalink display
219
-
220
- = 0.5.3 =
221
-
222
- * 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)
223
-
224
- = 0.5.2 =
225
-
226
- * Bugfix for matching posts when there are multiple posts that match parts of the query
227
-
228
- = 0.5.1 =
229
-
230
- * Compatibility fix for WP 2.7's tag/category pages
231
-
232
- = 0.5 =
233
-
234
- * Support for Wordpress sites in subdirectories (i.e., not located at the webroot)
235
-
236
- = 0.4.1 =
237
-
238
- * 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
239
-
240
- = 0.4 =
241
-
242
- * Support for pages, and a fix for draft posts/pages
243
-
244
- = 0.3.1 =
245
-
246
- * Discovered a typo that broke categories
247
-
248
- = 0.3 =
249
-
250
- * Largely rewritten to provide more robust handling of trailing slashes, proper support for trailing URL components (eg. paging)
251
-
252
- = 0.2.2 =
253
-
254
- * Fixed bug with not matching permalinks when / appended to the URL, and workaround for infinite redirect when another plugin is enforcing trailing /
255
-
256
- = 0.2.1 =
257
-
258
- * Better handling of trailing slashes
259
-
260
- = 0.2 =
261
-
262
- * Added 'Custom Permalinks' section under 'Manage' to show existing custom permalinks, and allow reverting to the defaults
263
-
264
- = 0.1.1 =
265
-
266
- * Fixed bug with categories
267
-
268
- == Upgrade Notice ==
269
-
270
- = 0.6.1 =
271
-
272
- * This release fixes a bug causing incorrect link from the "View Post"/"View Page" button in the editor
273
-
274
- = 0.6 =
275
-
276
- 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!
277
-
278
- = 0.5.3 =
279
-
280
- 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),
281
- upgrade: This has now been fixed.
282
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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.2
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
+ == Filter ==
30
+
31
+ If you want to exclude some Permalink to processed with the plugin so, just add the filter looks like this:
32
+ `
33
+ function check_xml_sitemap_url( $permalink ) {
34
+ if ( strpos( $permalink, 'sitemap.xml' ) !== false ) {
35
+ return '__true';
36
+ }
37
+ return;
38
+ }
39
+ add_filter( 'custom_permalinks_request_ignore', 'check_xml_sitemap_url' );
40
+ `
41
+
42
+ == Installation ==
43
+
44
+ 1. Unzip the package, and upload `custom-permalinks` to the `/wp-content/plugins/` directory
45
+ 2. Activate the plugin through the 'Plugins' menu in WordPress
46
+ 3. Edit any post, page, tag or category to set a custom permalink.
47
+
48
+ == Changelog ==
49
+
50
+ = 1.2 =
51
+
52
+ * Enhancements
53
+ * Added Filter to Exclude/Ignore URL to be processed
54
+ * Added Translation Capability
55
+ * Split the Code using OOPS Concept to improve performance and applied the filters according to the need
56
+ * Removed some unnecessary filters
57
+ * Bugs
58
+ * Fixed Vulnerability Issues
59
+
60
+ = 1.1 =
61
+
62
+ * Enhancements
63
+ * Added PostTypes Permalinks Page
64
+ * View all the PostTypes permalinks
65
+ * Search Permalinks
66
+ * Sort by Title
67
+ * Pagination
68
+ * Added Categories Permalinks Page
69
+ * View all the Category/Tags permalinks
70
+ * Search Permalinks
71
+ * Pagination
72
+
73
+ * Bug Fixes
74
+ * 404 Issues
75
+ * Child pages bug
76
+
77
+ = 1.0.2 =
78
+
79
+ * Fixed Notice and some URL Issues
80
+
81
+ = 1.0.1 =
82
+
83
+ * Fixed issue with AMP Pages
84
+
85
+ = 1.0 =
86
+
87
+ * Updated Query on the `custom_permalinks_request` Function
88
+
89
+ = 0.9.3 =
90
+
91
+ * Fixed PolyLang Conflicts
92
+
93
+ = 0.9.2 =
94
+
95
+ * Fixed WPML Conflicts
96
+
97
+ = 0.9.1 =
98
+
99
+ * Fixed issues of Filters and Actions (Replaces 'edit_files' with 10)
100
+
101
+ = 0.9 =
102
+
103
+ * Resolved the conflict with PolyLang Plugin
104
+
105
+ = 0.8 =
106
+
107
+ * Fixed (Draft preview issue for custom post types + some PHP Warnings)
108
+
109
+ = 0.7.28 =
110
+
111
+ * Fixed draft preview issue(posts + pages)
112
+
113
+ = 0.7.27 =
114
+
115
+ * Fixed Loop Redirecting issue
116
+
117
+ = 0.7.26 =
118
+
119
+ * Fixed PHP Notice issue
120
+
121
+ = 0.7.25 =
122
+
123
+ * Fixed draft preview issue
124
+
125
+ = 0.7.24 =
126
+
127
+ * Fixed a problem with page URLs
128
+
129
+ = 0.7.23 =
130
+
131
+ * Fixed a problem with permalinks with "/" components
132
+
133
+ = 0.7.22 =
134
+
135
+ * Fixed PHP warning
136
+ * Fixed initial permalink display for new posts/pages
137
+
138
+ = 0.7.21 =
139
+
140
+ * Minor internationalization fixes
141
+
142
+ = 0.7.20 =
143
+
144
+ * Addressed a noisy warning
145
+ * Revised addition of admin forms js (don't use is_admin())
146
+ * Updated Roles and Capabilities from depreciated numerical to label capabilities (by OF-6)
147
+ * Added css/html to match WP 3.5+ layout (by OF-6)
148
+
149
+ = 0.7.19 =
150
+
151
+ * WP 3.9 compatibility fix, thanks to Sowmedia
152
+
153
+ = 0.7.18 =
154
+
155
+ * Patch to address 404 errors when displaying a page/post that shares a permalink with a trashed page/post, thanks to Tor Johnson
156
+
157
+ = 0.7.17 =
158
+
159
+ * Patch to address SSL problems, thanks to Amin Mirzaee
160
+
161
+ = 0.7.16 =
162
+
163
+ * Security and compatibility fixes by Hans-Michael Varbaek of Sense of Security
164
+
165
+ = 0.7.15 =
166
+
167
+ * Permalinks are now case-insensitive (thanks to @ericmann)
168
+
169
+ = 0.7.14 =
170
+
171
+ * Delete permalinks upon page/post deletion
172
+
173
+ = 0.7.13 =
174
+
175
+ * Fixed issue with term permalinks not working properly on some installations
176
+
177
+ = 0.7.12 =
178
+
179
+ * Fixed issue with feed URLs in non-webroot blog installations
180
+
181
+ = 0.7.11 =
182
+
183
+ * Fixed issue with pending/draft posts with permalinks
184
+ * Fixed infinite redirect issue with permalinks without trailing slash, on blogs not hosted in the webroot
185
+
186
+ = 0.7.10 =
187
+
188
+ * Fix for 404 error on static front page with custom permalink set, by Eric TF Bat
189
+
190
+ = 0.7.9 =
191
+
192
+ * Support for custom post types, by Balázs Németh
193
+
194
+ = 0.7.8 =
195
+
196
+ * Support for non-ASCII characters in URLs
197
+ * Fixed bug where adding a new tag when saving a post with a custom permalink attaches that permalink to the new tag
198
+ * Some compatibility fixes for WP 3.2.1
199
+
200
+ = 0.7.7 =
201
+
202
+ * Minor change to permalink saving routine to fix some possible issues
203
+ * Fixed issue with %-encoded permalinks
204
+
205
+ = 0.7.6 =
206
+
207
+ * Fixed permalink saving issue when not using ".../%postname%" or similar permalink structure
208
+
209
+ = 0.7.5 =
210
+
211
+ * Fixed issue where changes to trailing "/" aren't saved
212
+
213
+ = 0.7.4 =
214
+
215
+ * Added support for changing post/page slug only
216
+ * Fixed incorrect admin edit link
217
+
218
+ = 0.7.3 =
219
+
220
+ * Fix problem with /page/# URLs on WP 3.1.3
221
+
222
+ = 0.7.2 =
223
+
224
+ * Don't clobber query parameters when redirecting to the custom permalink from the original URL
225
+
226
+ = 0.7.1 =
227
+
228
+ * Compatiblity fix for last update
229
+
230
+ = 0.7 =
231
+
232
+ * Added support for SSL sites, thanks to Dan from todaywasawesome.com
233
+
234
+ = 0.6.1 =
235
+
236
+ * Fix bug causing incorrect link from "View Post"/"View Page" button in post/page editor
237
+
238
+ = 0.6 =
239
+
240
+ * Fix infinite redirect for permalinks ending in a / (critical fix)
241
+ * Moved post/page permalinks settings to top of edit form, replacing prior permalink display
242
+
243
+ = 0.5.3 =
244
+
245
+ * 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)
246
+
247
+ = 0.5.2 =
248
+
249
+ * Bugfix for matching posts when there are multiple posts that match parts of the query
250
+
251
+ = 0.5.1 =
252
+
253
+ * Compatibility fix for WP 2.7's tag/category pages
254
+
255
+ = 0.5 =
256
+
257
+ * Support for Wordpress sites in subdirectories (i.e., not located at the webroot)
258
+
259
+ = 0.4.1 =
260
+
261
+ * 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
262
+
263
+ = 0.4 =
264
+
265
+ * Support for pages, and a fix for draft posts/pages
266
+
267
+ = 0.3.1 =
268
+
269
+ * Discovered a typo that broke categories
270
+
271
+ = 0.3 =
272
+
273
+ * Largely rewritten to provide more robust handling of trailing slashes, proper support for trailing URL components (eg. paging)
274
+
275
+ = 0.2.2 =
276
+
277
+ * Fixed bug with not matching permalinks when / appended to the URL, and workaround for infinite redirect when another plugin is enforcing trailing /
278
+
279
+ = 0.2.1 =
280
+
281
+ * Better handling of trailing slashes
282
+
283
+ = 0.2 =
284
+
285
+ * Added 'Custom Permalinks' section under 'Manage' to show existing custom permalinks, and allow reverting to the defaults
286
+
287
+ = 0.1.1 =
288
+
289
+ * Fixed bug with categories
290
+
291
+ == Upgrade Notice ==
292
+
293
+ = 0.6.1 =
294
+
295
+ * This release fixes a bug causing incorrect link from the "View Post"/"View Page" button in the editor
296
+
297
+ = 0.6 =
298
+
299
+ 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!
300
+
301
+ = 0.5.3 =
302
+
303
+ 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),
304
+ upgrade: This has now been fixed.
305
+