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

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