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

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