PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 3.8.10
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v3.8.10
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 3.5.2 All 199 releases
betterdocs / includes / Core / Rewrite.php

Rewrite.php in BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot 3.8.10, at includes/Core/Rewrite.php

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