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

242 lines 8.3 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 }
22
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 } );
28
29 return trailingslashit( implode( '/', $permalink_array ) );
30 }
31
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 }
47
48 $_permalink_structure = $_settings['permalink_structure'];
49
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 }
56
57 if ( $_permalink_structure !== $_old_settings['permalink_structure'] ) {
58 $this->settings->save( 'permalink_structure', $this->permalink_structure( $_permalink_structure ) );
59 }
60
61 $old_docs_page = isset( $_old_settings['docs_page'] ) ? $_old_settings['docs_page'] : '';
62 $current_docs_page = isset( $_settings['docs_page'] ) ? $_settings['docs_page'] : '';
63
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 }
79
80 public function permalink_structure( $structure = '', $output = 'string' ) {
81 if ( empty( $structure ) ) {
82 $structure = $this->settings->get( 'permalink_structure', 'docs' );
83 }
84
85 $docs_slug = $this->get_base_slug();
86
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 }
93
94 $structure = trim( $structure, '/' );
95
96 if ( $output === 'string' ) {
97 return $structure;
98 }
99
100 if ( $output === 'array' ) {
101 $structure = explode( '/', $structure );
102 $structure = array_map( function ( $item ) {
103 return trim( $item, "/%" );
104 }, $structure );
105 }
106
107 if ( $output === 'arraywithpercent' ) {
108 $structure = explode( '/', $structure );
109 $structure = array_map( function ( $item ) {
110 return trim( $item, "/" );
111 }, $structure );
112 }
113
114 return $structure;
115 }
116
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 );
121
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 }
126
127 $docs_slug = trim( $docs_slug, '/' );
128
129 return $docs_slug;
130 }
131
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 }
144
145 return $carry;
146 }, [] );
147
148 $structure[] = '%docs%';
149
150 $group = array_filter( $structure, function ( $item ) {
151 return strpos( $item, '%' ) === 0;
152 } );
153
154 return [
155 'raw' => $structure,
156 'group' => $group
157 ];
158 }
159
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 }
166
167 public function make_query( $segments ) {
168 $query = [];
169 $matchId = 1;
170
171 foreach ( $segments as $segment ) {
172 $query[] = trim( $segment, '%' ) . '=$matches[' . $matchId . ']';
173 $matchId++;
174 }
175
176 return 'index.php?' . implode( '&', $query ) . '&post_type=docs';
177 }
178
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 */
197
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 );
203
204 $_feed_regex = $_normalized_structure['raw'];
205 $_feed_regex[] = '(feed|rdf|rss|rss2|atom)';
206 $_feed_group = $_normalized_structure['group'];
207 $_feed_group[] = '%feed%';
208
209 $this->add_rewrite_rule( $this->make_regex( $_feed_regex ), $this->make_query( $_feed_group ) );
210
211 $this->add_rewrite_rule(
212 $this->make_regex( $_normalized_structure['raw'] ),
213 $this->make_query( $_normalized_structure['group'] )
214 );
215
216 $base = $this->get_base_slug();
217 $this->add_rewrite_rule( $base . '/(feed|rdf|rss|rss2|atom)/?$', 'index.php?post_type=docs&feed=$matches[1]' );
218 }
219
220 public function add_rewrite_rule( $regex, $query, $after = 'top' ) {
221 add_rewrite_rule( $regex, $query, $after );
222 }
223
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 );
228
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 }
235
236 return apply_filters( 'betterdocs_docs_rewrite', [
237 'slug' => trim( $permalink, '/' ),
238 'with_front' => false
239 ], $slug );
240 }
241 }
242