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

222 lines 7.5 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 $group = array_filter( $structure, function( $item ){
142 return strpos($item, '%') === 0;
143 });
144
145 return [
146 'raw' => $structure,
147 'group' => $group
148 ];
149 }
150
151 public function make_regex( $segments ){
152 return array_reduce( $segments, function( $carry, $item ){
153 $carry .= ( strpos( $item, '%' ) !== false ? "([^/]+)" : $item ) . '/';
154 return $carry;
155 }, '') . '?$';
156 }
157
158 public function make_query( $segments ){
159 $query = [];
160 $matchId = 1;
161 $segments[] = 'docs';
162 while( $segment = array_shift($segments) ) {
163 $query[] = trim($segment, '%') . '=$matches[' . $matchId . ']';
164 $matchId++;
165 }
166
167 return 'index.php?' . implode('&', $query) . '&post_type=docs';
168 }
169
170 public function rules() {
171 /**
172 * docs can be dynamic / as its a root slug
173 *
174 * https://url/docs/kb-slug
175 * https://url/docs/kb-slug/category-slug
176 * https://url/docs-category/category-slug
177 *
178 * Docs Visit:
179 * docs can be dynamic / as its a root slug
180 * or docs can be change by settings.
181 *
182 * https://url/docs/(docs-slug)
183 * https://url/docs/(cat-slug)/(docs-slug)
184 * https://url/docs/(kb-slug)/(docs-slug)
185 * https://url/docs/(kb-slug)/(cat-slug)/(docs-slug)
186 * https://url/docs/(cat-slug)/(kb-slug)/(docs-slug)
187 */
188
189 /**
190 * This code of blocks used to determine single docs permalink.
191 */
192 $_docs_perma_struct = betterdocs()->settings->get( 'permalink_structure', 'docs' );
193 $_normalized_structure = $this->normalzie_doc_perma_structure($_docs_perma_struct);
194 $this->add_rewrite_rule(
195 $this->make_regex( $_normalized_structure['raw'] ),
196 $this->make_query( $_normalized_structure['group'] )
197 );
198 }
199
200 public function add_rewrite_rule( $regex, $query, $after = 'top' ) {
201 add_rewrite_rule( $regex, $query, $after );
202 }
203
204 public function docs_type_rewrite( $rewrite, $slug ) {
205 $permalink = betterdocs()->settings->get( 'permalink_structure', 'docs/' );
206 $permalink_structure = $this->permalink_structure( $permalink, 'array' );
207 $permalink = apply_filters( 'betterdocs_docs_type_rewrite_permalink', $permalink, $slug, $permalink_structure );
208
209 /**
210 * TODO: Let's re-check later for optimization.
211 */
212 if ( ! betterdocs()->is_pro_active() ) {
213 $permalink = $this->remove_knowledge_base_placeholder( $permalink );
214 }
215
216 return apply_filters( 'betterdocs_docs_rewrite', [
217 'slug' => trim( $permalink, '/' ),
218 'with_front' => false
219 ], $slug );
220 }
221 }
222