PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 3.5.3
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v3.5.3
4.9.2 4.9.1 4.9.0 4.8.2 4.8.1 4.8.0 4.7.0 4.6.2 4.6.1 4.6.0 4.5.6 4.5.5 4.5.4 4.5.3 4.5.2 4.5.1 4.5.0 4.4.1 4.4.0 3.3.4 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 All 200 releases
← All changes | includes/Core/Rewrite.php +190 -266 4.5.63.5.3 View file →
@@ -1,317 +1,241 @@
1 1 <?php
2 +
2 3 namespace WPDeveloper\BetterDocs\Core;
3 4
4 -if ( ! defined( 'ABSPATH' ) ) {
5 - exit;
6 -}
7 -
8 -
9 5 use WP_Post;
10 6 use WPDeveloper\BetterDocs\Utils\Base;
11 7 use WPDeveloper\BetterDocs\Utils\Database;
12 8
13 9 class Rewrite extends Base {
14 - protected $settings;
15 - protected $database;
10 + protected $settings;
11 + protected $database;
16 12
17 - public function __construct( Settings $settings, Database $database ) {
18 - $this->settings = $settings;
19 - $this->database = $database;
20 - }
13 + public function __construct( Settings $settings, Database $database ) {
14 + $this->settings = $settings;
15 + $this->database = $database;
16 + }
21 17
22 - public function init() {
23 - add_action( 'init', [ $this, 'rules' ] );
24 - add_action( 'betterdocs::settings::saved', [ $this, 'save_permalink_structure' ], 2, 3 );
25 - add_action( 'template_redirect', [ $this, 'handle_pagination_redirect' ] );
26 - }
18 + public function init() {
19 + add_action( 'init', [$this, 'rules'] );
20 + add_action( 'betterdocs::settings::saved', [$this, 'save_permalink_structure'], 2, 3 );
21 + }
27 22
28 - /**
29 - * Handle pagination redirect
30 - * Redirects pagination attempts to main archive
31 - */
32 - public function handle_pagination_redirect() {
33 - if ( ! is_post_type_archive( 'docs' ) ) {
34 - return;
35 - }
23 + public function remove_knowledge_base_placeholder( $permalink ) {
24 + $permalink_array = $this->permalink_structure( $permalink, 'arraywithpercent' );
25 + $permalink_array = array_filter( $permalink_array, function ( $item ) {
26 + return $item !== '%knowledge_base%';
27 + } );
36 28
37 - $paged = get_query_var( 'paged' );
38 - if ( $paged > 1 ) {
39 - global $wp_query;
40 - $wp_query->set_404();
41 - status_header( 404 );
42 - nocache_headers();
43 - }
44 - }
29 + return trailingslashit( implode( '/', $permalink_array ) );
30 + }
45 31
46 - public function remove_knowledge_base_placeholder( $permalink ) {
47 - $permalink_array = $this->permalink_structure( $permalink, 'arraywithpercent' );
48 - $permalink_array = array_filter(
49 - $permalink_array,
50 - function ( $item ) {
51 - return $item !== '%knowledge_base%';
52 - }
53 - );
32 + /**
33 + * This method is hooked with an action called 'betterdocs::settings::saved'
34 + *
35 + * @since 2.5.0
36 + *
37 + * @param bool $_saved
38 + * @param array $_settings
39 + * @param array $_old_settings
40 + *
41 + * @return void
42 + */
43 + public function save_permalink_structure( $_saved, $_settings, $_old_settings ) {
44 + if ( ! isset( $_settings['permalink_structure'] ) ) {
45 + return;
46 + }
54 47
55 - return trailingslashit( implode( '/', $permalink_array ) );
56 - }
48 + $_permalink_structure = $_settings['permalink_structure'];
57 49
58 - /**
59 - * This method is hooked with an action called 'betterdocs::settings::saved'
60 - *
61 - * @since 2.5.0
62 - *
63 - * @param bool $_saved
64 - * @param array $_settings
65 - * @param array $_old_settings
66 - *
67 - * @return void
68 - */
69 - public function save_permalink_structure( $_saved, $_settings, $_old_settings ) {
70 - if ( ! isset( $_settings['permalink_structure'] ) ) {
71 - return;
72 - }
50 + /**
51 + * TODO: Let's re-check later to optimize it.
52 + */
53 + if ( ! betterdocs()->is_pro_active() ) {
54 + $_permalink_structure = $this->remove_knowledge_base_placeholder( $_permalink_structure );
55 + }
73 56
74 - $_permalink_structure = $_settings['permalink_structure'];
57 + if ( $_permalink_structure !== $_old_settings['permalink_structure'] ) {
58 + $this->settings->save( 'permalink_structure', $this->permalink_structure( $_permalink_structure ) );
59 + }
75 60
76 - /**
77 - * TODO: Let's re-check later to optimize it.
78 - */
79 - if ( ! betterdocs()->is_pro_active() ) {
80 - $_permalink_structure = $this->remove_knowledge_base_placeholder( $_permalink_structure );
81 - }
61 + $old_docs_page = isset( $_old_settings['docs_page'] ) ? $_old_settings['docs_page'] : '';
62 + $current_docs_page = isset( $_settings['docs_page'] ) ? $_settings['docs_page'] : '';
82 63
83 - if ( $_permalink_structure !== $_old_settings['permalink_structure'] ) {
84 - $this->settings->save( 'permalink_structure', $this->permalink_structure( $_permalink_structure ) );
85 - }
64 + /**
65 + * This block of code decides whether it needs to be flushed or not.
66 + * Flush happens after register the post type.
67 + */
68 + switch ( true ) {
69 + case $_permalink_structure !== $_old_settings['permalink_structure']:
70 + case $_settings['docs_slug'] !== $_old_settings['docs_slug']:
71 + case $_settings['builtin_doc_page'] !== $_old_settings['builtin_doc_page']:
72 + case $current_docs_page !== $old_docs_page:
73 + case $_settings['tag_slug'] !== $_old_settings['tag_slug']:
74 + case $_settings['category_slug'] !== $_old_settings['category_slug']:
75 + $this->database->set_transient( 'betterdocs_flush_rewrite_rules', true );
76 + break;
77 + }
78 + }
86 79
87 - $old_docs_page = isset( $_old_settings['docs_page'] ) ? $_old_settings['docs_page'] : '';
88 - $current_docs_page = isset( $_settings['docs_page'] ) ? $_settings['docs_page'] : '';
80 + public function permalink_structure( $structure = '', $output = 'string' ) {
81 + if ( empty( $structure ) ) {
82 + $structure = $this->settings->get( 'permalink_structure', 'docs' );
83 + }
89 84
90 - /**
91 - * This block of code decides whether it needs to be flushed or not.
92 - * Flush happens after register the post type.
93 - */
94 - switch ( true ) {
95 - case $_permalink_structure !== $_old_settings['permalink_structure']:
96 - case $_settings['docs_slug'] !== $_old_settings['docs_slug']:
97 - case $_settings['builtin_doc_page'] !== $_old_settings['builtin_doc_page']:
98 - case $current_docs_page !== $old_docs_page:
99 - case $_settings['tag_slug'] !== $_old_settings['tag_slug']:
100 - case $_settings['category_slug'] !== $_old_settings['category_slug']:
101 - $this->database->set_transient( 'betterdocs_flush_rewrite_rules', true );
102 - break;
103 - }
104 - }
85 + $docs_slug = $this->get_base_slug();
105 86
106 - public function permalink_structure( $structure = '', $output = 'string' ) {
107 - if ( empty( $structure ) ) {
108 - $structure = $this->settings->get( 'permalink_structure', 'docs' );
109 - }
87 + $_structure_array = explode( '%', $structure );
88 + if ( $_structure_array[0] == '/' ) {
89 + $structure = $docs_slug . $structure;
90 + } else if ( $_structure_array[0] == '' ) {
91 + $structure = $docs_slug . '/' . $structure;
92 + }
110 93
111 - $docs_slug = $this->get_base_slug();
94 + $structure = trim( $structure, '/' );
112 95
113 - $_structure_array = explode( '%', $structure );
114 - if ( $_structure_array[0] == '/' ) {
115 - $structure = $docs_slug . $structure;
116 - } elseif ( $_structure_array[0] == '' ) {
117 - $structure = $docs_slug . '/' . $structure;
118 - }
96 + if ( $output === 'string' ) {
97 + return $structure;
98 + }
119 99
120 - $structure = trim( $structure, '/' );
100 + if ( $output === 'array' ) {
101 + $structure = explode( '/', $structure );
102 + $structure = array_map( function ( $item ) {
103 + return trim( $item, "/%" );
104 + }, $structure );
105 + }
121 106
122 - if ( $output === 'string' ) {
123 - return $structure;
124 - }
107 + if ( $output === 'arraywithpercent' ) {
108 + $structure = explode( '/', $structure );
109 + $structure = array_map( function ( $item ) {
110 + return trim( $item, "/" );
111 + }, $structure );
112 + }
125 113
126 - if ( $output === 'array' ) {
127 - $structure = explode( '/', $structure );
128 - $structure = array_map(
129 - function ( $item ) {
130 - return trim( $item, '/%' );
131 - },
132 - $structure
133 - );
134 - }
114 + return $structure;
115 + }
135 116
136 - if ( $output === 'arraywithpercent' ) {
137 - $structure = explode( '/', $structure );
138 - $structure = array_map(
139 - function ( $item ) {
140 - return trim( $item, '/' );
141 - },
142 - $structure
143 - );
144 - }
117 + public function get_base_slug() {
118 + $docs_slug = $this->settings->get( 'docs_slug', 'docs' );
119 + $docs_page = $this->settings->get( 'docs_page', 0 );
120 + $builtin_doc_page = $this->settings->get( 'builtin_doc_page', true );
145 121
146 - return $structure;
147 - }
122 + if ( ! $builtin_doc_page && $docs_page !== 0 ) {
123 + $post_info = get_post( $docs_page );
124 + $docs_slug = $post_info instanceof WP_Post ? $post_info->post_name : $docs_slug;
125 + }
148 126
149 - public function hierarchy_based_slug_switch() {
150 - $hierarchy_slug = $this->settings->get( 'enable_category_hierarchy_slugs', false );
151 - return $hierarchy_slug;
152 - }
127 + $docs_slug = trim( $docs_slug, '/' );
153 128
154 - public function get_base_slug() {
155 - $docs_slug = $this->settings->get( 'docs_slug', 'docs' );
156 - $docs_page = $this->settings->get( 'docs_page', 0 );
157 - $builtin_doc_page = $this->settings->get( 'builtin_doc_page', true );
129 + return $docs_slug;
130 + }
158 131
159 - if ( ! $builtin_doc_page && $docs_page !== 0 ) {
160 - $post_info = get_post( $docs_page );
161 - $docs_slug = $post_info instanceof WP_Post ? $post_info->post_name : $docs_slug;
162 - }
132 + public function normalzie_doc_perma_structure( $structure ) {
133 + $structure = $this->permalink_structure( $structure, 'arraywithpercent' );
134 + $structure = array_reduce( $structure, function ( $carry, $item ) {
135 + if ( strpos( $item, '%' ) !== false ) {
136 + $carry[] = $item;
137 + } else {
138 + if ( $carry && strpos( end( $carry ), '%' ) === false ) {
139 + $carry[count( $carry ) - 1] .= "/$item";
140 + } else {
141 + $carry[] = $item;
142 + }
143 + }
163 144
164 - $docs_slug = trim( $docs_slug, '/' );
145 + return $carry;
146 + }, [] );
165 147
166 - return $docs_slug;
167 - }
148 + $structure[] = '%docs%';
168 149
169 - public function normalzie_doc_perma_structure( $structure ) {
170 - $structure = $this->permalink_structure( $structure, 'arraywithpercent' );
171 - $structure = array_reduce(
172 - $structure,
173 - function ( $carry, $item ) {
174 - if ( strpos( $item, '%' ) !== false ) {
175 - $carry[] = $item;
176 - } elseif ( $carry && strpos( end( $carry ), '%' ) === false ) {
177 - $carry[ count( $carry ) - 1 ] .= "/$item";
178 - } else {
179 - $carry[] = $item;
180 - }
150 + $group = array_filter( $structure, function ( $item ) {
151 + return strpos( $item, '%' ) === 0;
152 + } );
181 153
182 - return $carry;
183 - },
184 - []
185 - );
154 + return [
155 + 'raw' => $structure,
156 + 'group' => $group
157 + ];
158 + }
186 159
187 - $structure[] = '%docs%';
160 + public function make_regex( $segments ) {
161 + return array_reduce( $segments, function ( $carry, $item ) {
162 + $carry .= ( strpos( $item, '%' ) !== false ? "([^/]+)" : $item ) . '/';
163 + return $carry;
164 + }, '' ) . '?$';
165 + }
188 166
189 - $group = array_filter(
190 - $structure,
191 - function ( $item ) {
192 - return strpos( $item, '%' ) === 0;
193 - }
194 - );
167 + public function make_query( $segments ) {
168 + $query = [];
169 + $matchId = 1;
195 170
196 - return [
197 - 'raw' => $structure,
198 - 'group' => $group
199 - ];
200 - }
171 + foreach ( $segments as $segment ) {
172 + $query[] = trim( $segment, '%' ) . '=$matches[' . $matchId . ']';
173 + $matchId++;
174 + }
201 175
202 - public function make_regex( $segments ) {
203 - return array_reduce(
204 - $segments,
205 - function ( $carry, $item ) {
206 - $carry .= ( strpos( $item, '%' ) !== false ? '([^/]+)' : $item ) . '/';
207 - return $carry;
208 - },
209 - '^'
210 - ) . '?$';
211 - }
176 + return 'index.php?' . implode( '&', $query ) . '&post_type=docs';
177 + }
212 178
213 - public function make_query( $segments ) {
214 - $query = [];
215 - $matchId = 1;
179 + public function rules() {
180 + /**
181 + * docs can be dynamic / as its a root slug
182 + *
183 + * https://url/docs/kb-slug
184 + * https://url/docs/kb-slug/category-slug
185 + * https://url/docs-category/category-slug
186 + *
187 + * Docs Visit:
188 + * docs can be dynamic / as its a root slug
189 + * or docs can be change by settings.
190 + *
191 + * https://url/docs/(docs-slug)
192 + * https://url/docs/(cat-slug)/(docs-slug)
193 + * https://url/docs/(kb-slug)/(docs-slug)
194 + * https://url/docs/(kb-slug)/(cat-slug)/(docs-slug)
195 + * https://url/docs/(cat-slug)/(kb-slug)/(docs-slug)
196 + */
216 197
217 - foreach ( $segments as $segment ) {
218 - $query[] = trim( $segment, '%' ) . '=$matches[' . $matchId . ']';
219 - ++$matchId;
220 - }
198 + /**
199 + * This code of blocks used to determine single docs permalink.
200 + */
201 + $_docs_perma_struct = betterdocs()->settings->get( 'permalink_structure', 'docs' );
202 + $_normalized_structure = $this->normalzie_doc_perma_structure( $_docs_perma_struct );
221 203
222 - return 'index.php?' . implode( '&', $query ) . '&post_type=docs';
223 - }
204 + $_feed_regex = $_normalized_structure['raw'];
205 + $_feed_regex[] = '(feed|rdf|rss|rss2|atom)';
206 + $_feed_group = $_normalized_structure['group'];
207 + $_feed_group[] = '%feed%';
224 208
225 - public function rules() {
226 - /**
227 - * docs can be dynamic / as its a root slug
228 - *
229 - * https://url/docs/kb-slug
230 - * https://url/docs/kb-slug/category-slug
231 - * https://url/docs-category/category-slug
232 - *
233 - * Docs Visit:
234 - * docs can be dynamic / as its a root slug
235 - * or docs can be change by settings.
236 - *
237 - * https://url/docs/(docs-slug)
238 - * https://url/docs/(cat-slug)/(docs-slug)
239 - * https://url/docs/(kb-slug)/(docs-slug)
240 - * https://url/docs/(kb-slug)/(cat-slug)/(docs-slug)
241 - * https://url/docs/(cat-slug)/(kb-slug)/(docs-slug)
242 - */
209 + $this->add_rewrite_rule( $this->make_regex( $_feed_regex ), $this->make_query( $_feed_group ) );
243 210
244 - $base = $this->get_base_slug();
245 - $hierarchy_slug = $this->hierarchy_based_slug_switch();
211 + $this->add_rewrite_rule(
212 + $this->make_regex( $_normalized_structure['raw'] ),
213 + $this->make_query( $_normalized_structure['group'] )
214 + );
246 215
247 - // Add rule to handle pagination attempts
248 - $this->add_rewrite_rule(
249 - '^' . $base . '/page/([0-9]+)/?$',
250 - 'index.php?post_type=docs',
251 - 'top'
252 - );
253 -
254 216 $base = $this->get_base_slug();
255 - $this->add_rewrite_rule( '^' . $base . '/(feed|rdf|rss|rss2|atom)/?$', 'index.php?post_type=docs&feed=$matches[1]' );
256 - $this->add_rewrite_rule( '^' . $base . '/authors/([0-9]+)/?$', 'index.php?post_type=docs&author=$matches[1]' );
257 - $this->add_rewrite_rule( '^' . $base . '/authors/([0-9]+)/page/([0-9]+)/?$', 'index.php?post_type=docs&author=$matches[1]&page=$matches[2]' );
217 + $this->add_rewrite_rule( $base . '/(feed|rdf|rss|rss2|atom)/?$', 'index.php?post_type=docs&feed=$matches[1]' );
218 + }
258 219
259 - /**
260 - * This code of blocks used to determine single docs permalink.
261 - */
262 - $_docs_perma_struct = betterdocs()->settings->get( 'permalink_structure', 'docs' );
263 - $_normalized_structure = $this->normalzie_doc_perma_structure( $_docs_perma_struct );
220 + public function add_rewrite_rule( $regex, $query, $after = 'top' ) {
221 + add_rewrite_rule( $regex, $query, $after );
222 + }
264 223
265 - if( $hierarchy_slug ) { // register hierarchy based slug rewrite rule, for single doc permalink
266 - // When MKB or WPML is used, the actual base for single docs might differ from the generic $base
267 - $perma_base = isset( $_normalized_structure['raw'][0] ) && strpos( $_normalized_structure['raw'][0], '%' ) === false
268 - ? $_normalized_structure['raw'][0]
269 - : $base;
270 -
271 - $this->add_rewrite_rule( '^' . $perma_base . '/(.+?)/([^/]+)(?:/([0-9]+))?/?$', 'index.php?doc_category=$matches[1]&docs=$matches[2]&post_type=docs', 'top' );
272 -
273 - // Removed flush_rewrite_rules() from here. Calling flush_rewrite_rules() on the 'init' hook causes
274 - // infinite database updates and destroys custom rules when WPML or MKB dynamically filters keys.
275 - }
224 + public function docs_type_rewrite( $rewrite, $slug ) {
225 + $permalink = betterdocs()->settings->get( 'permalink_structure', 'docs/' );
226 + $permalink_structure = $this->permalink_structure( $permalink, 'array' );
227 + $permalink = apply_filters( 'betterdocs_docs_type_rewrite_permalink', $permalink, $slug, $permalink_structure );
276 228
277 - $_feed_regex = $_normalized_structure['raw'];
278 - $_feed_regex[] = '(feed|rdf|rss|rss2|atom)';
279 - $_feed_group = $_normalized_structure['group'];
280 - $_feed_group[] = '%feed%';
229 + /**
230 + * TODO: Let's re-check later for optimization.
231 + */
232 + if ( ! betterdocs()->is_pro_active() ) {
233 + $permalink = $this->remove_knowledge_base_placeholder( $permalink );
234 + }
281 235
282 - $this->add_rewrite_rule( $this->make_regex( $_feed_regex ), $this->make_query( $_feed_group ) );
283 -
284 - $this->add_rewrite_rule(
285 - $this->make_regex( $_normalized_structure['raw'] ),
286 - $this->make_query( $_normalized_structure['group'] )
287 - );
288 -
289 - $this->add_rewrite_rule( '^' . $base . '/(feed|rdf|rss|rss2|atom)/?$', 'index.php?post_type=docs&feed=$matches[1]' );
290 - }
291 -
292 - public function add_rewrite_rule( $regex, $query, $after = 'top' ) {
293 - add_rewrite_rule( $regex, $query, $after );
294 - }
295 -
296 - public function docs_type_rewrite( $rewrite, $slug ) {
297 - $permalink = betterdocs()->settings->get( 'permalink_structure', 'docs/' );
298 - $permalink_structure = $this->permalink_structure( $permalink, 'array' );
299 - $permalink = apply_filters( 'betterdocs_docs_type_rewrite_permalink', $permalink, $slug, $permalink_structure );
300 -
301 - /**
302 - * TODO: Let's re-check later for optimization.
303 - */
304 - if ( ! betterdocs()->is_pro_active() ) {
305 - $permalink = $this->remove_knowledge_base_placeholder( $permalink );
306 - }
307 -
308 - return apply_filters(
309 - 'betterdocs_docs_rewrite',
310 - [
311 - 'slug' => trim( $permalink, '/' ),
312 - 'with_front' => false
313 - ],
314 - $slug
315 - );
316 - }
236 + return apply_filters( 'betterdocs_docs_rewrite', [
237 + 'slug' => trim( $permalink, '/' ),
238 + 'with_front' => false
239 + ], $slug );
240 + }
317 241 }