PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 4.1.2
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v4.1.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 / Request.php

Request.php in BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot 4.1.2, at includes/Core/Request.php

260 lines 7.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 WPDeveloper\BetterDocs\Utils\Base;
6
7 class Request extends Base {
8 /**
9 * Flag for already parsed or not
10 *
11 * Specially needed for those who don't update pro yet.
12 * @var boolean
13 */
14 protected static $already_parsed = false;
15
16 /**
17 * List of BetterDocs Perma Structure
18 * @var array
19 */
20 private $perma_structure = [];
21
22 /**
23 * List of BetterDocs Query Vars Agains Page Structure.
24 * @var array
25 */
26 private $query_vars = [];
27
28 /**
29 * List of Query Variables from $wp->query_vars.
30 * @var array
31 */
32 private $wp_query_vars = [];
33
34 /**
35 * Rewrite Class Reference of BetterDocs
36 * @var Rewrite
37 */
38 protected $rewrite;
39
40 /**
41 * Settings Class Reference of BetterDocs
42 * @var Settings
43 */
44 protected $settings;
45
46 public function __construct( Rewrite $rewrite, Settings $settings ) {
47 $this->rewrite = $rewrite;
48 $this->settings = $settings;
49 }
50
51 public function init() {
52 if ( is_admin() ) {
53 return;
54 }
55
56 $this->perma_structure = [
57 'is_docs' => trim( $this->rewrite->get_base_slug(), '/' ),
58 'is_docs_feed' => trim( $this->rewrite->get_base_slug(), '/' ) . '/%feed%',
59 'is_docs_category' => trim( $this->settings->get( 'category_slug', 'docs-category' ), '/' ) . '/%doc_category%',
60 'is_docs_tag' => trim( $this->settings->get( 'tag_slug', 'docs-tag' ), '/' ) . '/%doc_tag%',
61 'is_single_docs' => trim( $this->settings->get( 'permalink_structure', 'docs' ), '/' ) . '/%name%',
62 'is_docs_author' => trim( $this->rewrite->get_base_slug(), '/' ) . '/authors/%author%'
63 ];
64
65 $this->query_vars = [
66 'is_docs' => ['post_type'],
67 'is_docs_feed' => ['doc_category'],
68 'is_docs_category' => ['doc_category'],
69 'is_docs_tag' => ['doc_tag'],
70 'is_single_docs' => ['name', 'docs', 'post_type'],
71 'is_docs_author' => ['post_type', 'author']
72 ];
73
74 add_action( 'parse_request', [ $this, 'parse' ] );
75
76 /**
77 * This is for Backward compatibility if pro not updated.
78 */
79 add_action( 'parse_request', [ $this, 'backward_compability' ], 11 );
80
81 /**
82 * Make Compatible With Permalink Manager Plugin
83 */
84 add_filter( 'permalink_manager_detected_element_id', [ $this, 'provide_compatibility' ], 10, 3 );
85 }
86
87 public function provide_compatibility( $element_id, $uri_parts, $request_url ) {
88 if ( $request_url == $this->settings->get( 'docs_slug' ) ) {
89 $element_id = '';
90 }
91 return $element_id;
92 }
93
94 protected function is_docs( &$query_vars ) {
95 if ( ! $this->settings->get( 'builtin_doc_page', true ) ) {
96 $query_vars['post_type'] = 'page';
97 $query_vars['name'] = trim( $this->rewrite->get_base_slug(), '/' );
98 }
99
100 return $query_vars;
101 }
102
103 public function is_docs_feed( $query_vars ) {
104 global $wp_rewrite;
105 return isset( $query_vars['feed'] ) && in_array( $query_vars['feed'], $wp_rewrite->feeds );
106 }
107
108 public function is_docs_author( $query_vars ) {
109 return isset( $query_vars['author'] ) ? true : false;
110 }
111
112 protected function is_single_docs( $query_vars ) {
113 if ( ! isset( $query_vars['name'] ) ) {
114 return false;
115 }
116
117 global $wpdb;
118 $name = $query_vars['name'];
119
120 $_post_id = (int) $wpdb->get_var(
121 $wpdb->prepare(
122 "SELECT ID FROM {$wpdb->posts} WHERE post_name = %s AND post_type = %s LIMIT 1",
123 esc_sql( $name ),
124 'docs'
125 )
126 );
127
128 return $_post_id > 0;
129 }
130
131 protected function is_docs_category( $query_vars ) {
132 return $this->term_exists( $query_vars, 'doc_category' );
133 }
134
135 protected function is_docs_tag( $query_vars ) {
136 return $this->term_exists( $query_vars, 'doc_tag' );
137 }
138
139 protected function term_exists( $query_vars, $taxonomy ) {
140 if ( ! isset( $query_vars[ $taxonomy ] ) ) {
141 return false;
142 }
143
144 return term_exists( $query_vars[ $taxonomy ], $taxonomy );
145 }
146
147 public function set_perma_structure( $structures = [] ) {
148 $this->perma_structure = array_merge( $this->perma_structure, $structures );
149 }
150
151 public function set_query_vars( $query_vars = [] ) {
152 $this->query_vars = array_merge( $this->query_vars, $query_vars );
153 }
154
155 public function backward_compability( $wp ) {
156 if ( static::$already_parsed ) {
157 return;
158 }
159
160 $this->permalink_magic( $wp );
161 }
162
163 public function parse( $wp ) {
164 static::$already_parsed = true;
165
166 $this->perma_structure = apply_filters('docs_rewrite_rules', $this->perma_structure);
167
168 $this->permalink_magic( $wp );
169 }
170
171 protected function permalink_magic( $wp ) {
172 $this->wp_query_vars = $wp->query_vars;
173
174 if ( ! empty( $this->perma_structure ) ) {
175 $_valid = [];
176
177 foreach ( $this->perma_structure as $_type => $structure ) {
178 $_perma_vars = $this->is_perma_valid_for( $structure, $wp->request );
179
180 // $_valid = empty( $_valid ) && $_perma_vars ? [ 'type' => $_type, 'query_vars' => $_perma_vars ] : $_valid;
181 if ( ( $_perma_vars && method_exists( $this, $_type ) && call_user_func_array( [$this, $_type], [ & $_perma_vars] ) ) ) {
182 // dump( $_type, $_perma_vars );
183 if ( $_type === 'is_single_docs' || $_type == 'is_docs_feed' || $_type == 'is_docs_author' ) {
184 $_perma_vars['post_type'] = 'docs';
185 }
186 $_valid = ['type' => $_type, 'query_vars' => $_perma_vars];
187 }
188 }
189
190 $type = isset( $_valid['type'] ) ? $_valid['type'] : '';
191 $query_vars = isset( $_valid['query_vars'] ) ? $_valid['query_vars'] : [];
192
193 if ( ! empty( $type ) ) {
194 unset( $this->query_vars[ $type ] );
195 array_map(
196 function ( $_vars ) use ( &$wp ) {
197 array_map(
198 function ( $_var ) use ( &$wp ) {
199 unset( $wp->query_vars[ $_var ] );
200 },
201 $_vars
202 );
203 },
204 $this->query_vars
205 );
206 }
207
208 $wp->query_vars = is_array( $query_vars ) ? array_merge( $wp->query_vars, $query_vars ) : $wp->query_vars;
209 // Fallback
210 if ( ! empty( $_valid ) ) {
211 unset( $wp->query_vars['attachment'] );
212 }
213 }
214 }
215
216 /**
217 * This method is responsible for checking a structure is valid again a request.
218 *
219 * @param string $structure
220 * @param string $request
221 * @return array|bool
222 */
223 private function is_perma_valid_for( $structure, $request ) {
224 if ( empty( $structure ) ) {
225 return false;
226 }
227
228 $_tags = explode( '/', trim( $structure, '/' ) );
229 $_replace_matched_tags = [];
230
231 $_replace_tags = array_filter(
232 $_tags,
233 function ( $item ) use ( &$_replace_matched_tags ) {
234 $_is_valid = strpos( $item, '%' ) !== false;
235 if ( $_is_valid ) {
236 $_replace_matched_tags[] = trim( $item, '%' );
237 }
238 return $_is_valid;
239 }
240 );
241
242 $_perma_structure = preg_quote( $structure, '/' );
243 $_perma_structure = str_replace( $_replace_tags, '([^\/]+)', $_perma_structure );
244
245 preg_match( "/^$_perma_structure$/", $request, $matches );
246
247 if ( empty( $matches ) || ! is_array( $matches ) ) {
248 return false;
249 }
250
251 if ( count( $matches ) === 1 ) {
252 return [ 'post_type' => 'docs' ];
253 }
254
255 unset( $matches[0] );
256
257 return array_combine( $_replace_matched_tags, $matches );
258 }
259 }
260