PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 3.8.1
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v3.8.1
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.1, at includes/Core/Rewrite.php

269 lines 9.0 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( $permalink_array, function ( $item ) {
45 return $item !== '%knowledge_base%';
46 } );
47
48 return trailingslashit( implode( '/', $permalink_array ) );
49 }
50
51 /**
52 * This method is hooked with an action called 'betterdocs::settings::saved'
53 *
54 * @since 2.5.0
55 *
56 * @param bool $_saved
57 * @param array $_settings
58 * @param array $_old_settings
59 *
60 * @return void
61 */
62 public function save_permalink_structure( $_saved, $_settings, $_old_settings ) {
63 if ( ! isset( $_settings['permalink_structure'] ) ) {
64 return;
65 }
66
67 $_permalink_structure = $_settings['permalink_structure'];
68
69 /**
70 * TODO: Let's re-check later to optimize it.
71 */
72 if ( ! betterdocs()->is_pro_active() ) {
73 $_permalink_structure = $this->remove_knowledge_base_placeholder( $_permalink_structure );
74 }
75
76 if ( $_permalink_structure !== $_old_settings['permalink_structure'] ) {
77 $this->settings->save( 'permalink_structure', $this->permalink_structure( $_permalink_structure ) );
78 }
79
80 $old_docs_page = isset( $_old_settings['docs_page'] ) ? $_old_settings['docs_page'] : '';
81 $current_docs_page = isset( $_settings['docs_page'] ) ? $_settings['docs_page'] : '';
82
83 /**
84 * This block of code decides whether it needs to be flushed or not.
85 * Flush happens after register the post type.
86 */
87 switch ( true ) {
88 case $_permalink_structure !== $_old_settings['permalink_structure']:
89 case $_settings['docs_slug'] !== $_old_settings['docs_slug']:
90 case $_settings['builtin_doc_page'] !== $_old_settings['builtin_doc_page']:
91 case $current_docs_page !== $old_docs_page:
92 case $_settings['tag_slug'] !== $_old_settings['tag_slug']:
93 case $_settings['category_slug'] !== $_old_settings['category_slug']:
94 $this->database->set_transient( 'betterdocs_flush_rewrite_rules', true );
95 break;
96 }
97 }
98
99 public function permalink_structure( $structure = '', $output = 'string' ) {
100 if ( empty( $structure ) ) {
101 $structure = $this->settings->get( 'permalink_structure', 'docs' );
102 }
103
104 $docs_slug = $this->get_base_slug();
105
106 $_structure_array = explode( '%', $structure );
107 if ( $_structure_array[0] == '/' ) {
108 $structure = $docs_slug . $structure;
109 } else if ( $_structure_array[0] == '' ) {
110 $structure = $docs_slug . '/' . $structure;
111 }
112
113 $structure = trim( $structure, '/' );
114
115 if ( $output === 'string' ) {
116 return $structure;
117 }
118
119 if ( $output === 'array' ) {
120 $structure = explode( '/', $structure );
121 $structure = array_map( function ( $item ) {
122 return trim( $item, "/%" );
123 }, $structure );
124 }
125
126 if ( $output === 'arraywithpercent' ) {
127 $structure = explode( '/', $structure );
128 $structure = array_map( function ( $item ) {
129 return trim( $item, "/" );
130 }, $structure );
131 }
132
133 return $structure;
134 }
135
136 public function get_base_slug() {
137 $docs_slug = $this->settings->get( 'docs_slug', 'docs' );
138 $docs_page = $this->settings->get( 'docs_page', 0 );
139 $builtin_doc_page = $this->settings->get( 'builtin_doc_page', true );
140
141 if ( ! $builtin_doc_page && $docs_page !== 0 ) {
142 $post_info = get_post( $docs_page );
143 $docs_slug = $post_info instanceof WP_Post ? $post_info->post_name : $docs_slug;
144 }
145
146 $docs_slug = trim( $docs_slug, '/' );
147
148 return $docs_slug;
149 }
150
151 public function normalzie_doc_perma_structure( $structure ) {
152 $structure = $this->permalink_structure( $structure, 'arraywithpercent' );
153 $structure = array_reduce( $structure, function ( $carry, $item ) {
154 if ( strpos( $item, '%' ) !== false ) {
155 $carry[] = $item;
156 } else {
157 if ( $carry && strpos( end( $carry ), '%' ) === false ) {
158 $carry[count( $carry ) - 1] .= "/$item";
159 } else {
160 $carry[] = $item;
161 }
162 }
163
164 return $carry;
165 }, [] );
166
167 $structure[] = '%docs%';
168
169 $group = array_filter( $structure, function ( $item ) {
170 return strpos( $item, '%' ) === 0;
171 } );
172
173 return [
174 'raw' => $structure,
175 'group' => $group
176 ];
177 }
178
179 public function make_regex( $segments ) {
180 return array_reduce( $segments, function ( $carry, $item ) {
181 $carry .= ( strpos( $item, '%' ) !== false ? "([^/]+)" : $item ) . '/';
182 return $carry;
183 }, '' ) . '?$';
184 }
185
186 public function make_query( $segments ) {
187 $query = [];
188 $matchId = 1;
189
190 foreach ( $segments as $segment ) {
191 $query[] = trim( $segment, '%' ) . '=$matches[' . $matchId . ']';
192 $matchId++;
193 }
194
195 return 'index.php?' . implode( '&', $query ) . '&post_type=docs';
196 }
197
198 public function rules() {
199 /**
200 * docs can be dynamic / as its a root slug
201 *
202 * https://url/docs/kb-slug
203 * https://url/docs/kb-slug/category-slug
204 * https://url/docs-category/category-slug
205 *
206 * Docs Visit:
207 * docs can be dynamic / as its a root slug
208 * or docs can be change by settings.
209 *
210 * https://url/docs/(docs-slug)
211 * https://url/docs/(cat-slug)/(docs-slug)
212 * https://url/docs/(kb-slug)/(docs-slug)
213 * https://url/docs/(kb-slug)/(cat-slug)/(docs-slug)
214 * https://url/docs/(cat-slug)/(kb-slug)/(docs-slug)
215 */
216
217 $base = $this->get_base_slug();
218
219 // Add rule to handle pagination attempts
220 $this->add_rewrite_rule(
221 $base . '/page/([0-9]+)/?$',
222 'index.php?post_type=docs',
223 'top'
224 );
225
226 /**
227 * This code of blocks used to determine single docs permalink.
228 */
229 $_docs_perma_struct = betterdocs()->settings->get( 'permalink_structure', 'docs' );
230 $_normalized_structure = $this->normalzie_doc_perma_structure( $_docs_perma_struct );
231
232 $_feed_regex = $_normalized_structure['raw'];
233 $_feed_regex[] = '(feed|rdf|rss|rss2|atom)';
234 $_feed_group = $_normalized_structure['group'];
235 $_feed_group[] = '%feed%';
236
237 $this->add_rewrite_rule( $this->make_regex( $_feed_regex ), $this->make_query( $_feed_group ) );
238
239 $this->add_rewrite_rule(
240 $this->make_regex( $_normalized_structure['raw'] ),
241 $this->make_query( $_normalized_structure['group'] )
242 );
243
244 $this->add_rewrite_rule( $base . '/(feed|rdf|rss|rss2|atom)/?$', 'index.php?post_type=docs&feed=$matches[1]' );
245 }
246
247 public function add_rewrite_rule( $regex, $query, $after = 'top' ) {
248 add_rewrite_rule( $regex, $query, $after );
249 }
250
251 public function docs_type_rewrite( $rewrite, $slug ) {
252 $permalink = betterdocs()->settings->get( 'permalink_structure', 'docs/' );
253 $permalink_structure = $this->permalink_structure( $permalink, 'array' );
254 $permalink = apply_filters( 'betterdocs_docs_type_rewrite_permalink', $permalink, $slug, $permalink_structure );
255
256 /**
257 * TODO: Let's re-check later for optimization.
258 */
259 if ( ! betterdocs()->is_pro_active() ) {
260 $permalink = $this->remove_knowledge_base_placeholder( $permalink );
261 }
262
263 return apply_filters( 'betterdocs_docs_rewrite', [
264 'slug' => trim( $permalink, '/' ),
265 'with_front' => false
266 ], $slug );
267 }
268 }
269