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

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

348 lines 11.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace WPDeveloper\BetterDocs\FrontEnd;
3
4 if ( ! defined( 'ABSPATH' ) ) {
5 exit;
6 }
7
8
9 use WPDeveloper\BetterDocs\Utils\Base;
10 use WPDeveloper\BetterDocs\Utils\Helper;
11 use WPDeveloper\BetterDocs\Core\Settings;
12 use WPDeveloper\BetterDocs\Utils\Enqueue;
13 use WPDeveloper\BetterDocs\Utils\Database;
14 use WPDeveloper\BetterDocs\Dependencies\DI\Container;
15
16 class FrontEnd extends Base {
17 private $container;
18 private $database;
19 /**
20 * Enqueue
21 * @var Enqueue
22 */
23 private $assets;
24 /**
25 * Settings
26 * @var Settings
27 */
28 private $settings;
29 private $widget_attributes = [];
30 private $widget_type = '';
31
32 public function __construct( Container $container, Database $database, Settings $settings ) {
33 $this->container = $container;
34 $this->database = $database;
35 $this->settings = $settings;
36
37 $this->assets = $this->container->get( Enqueue::class );
38
39 add_action( 'init', [ $this, 'init' ] );
40 add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_scripts' ] );
41
42 /**
43 * Update The 'Edit Site' Url In FSE Mode For Betterdocs Templates Only
44 */
45 if ( Helper::is_plugin_active( 'sitepress-multilingual-cms/sitepress.php' ) && wp_is_block_theme() ) {
46 add_action( 'admin_bar_menu', [$this, 'fse_url_update'], 41, 1 );
47 }
48
49 add_filter( 'betterdocs_layout_filename', [ $this, 'layout_filename' ], 10, 2 );
50
51 add_action( 'betterdocs_docs_before_social', [ $this, 'article_reactions' ] );
52
53 add_action( 'betterdocs_before_render', [ $this, 'before_render' ], 11, 2 );
54 add_action( 'betterdocs_after_render', [ $this, 'after_render' ], 11, 2 );
55
56 //Remove Saliant Theme Script For (Delay Javascript Exection), which causes issue with betterdocs sidebar toggle, issue number (#1234)
57 add_action( 'nectar_hook_before_body_close', [ $this, 'dequeue_saliant_theme_script' ], 99999 );
58
59 //Remove our search selector from from Searchanise plugin for woocommerce, conflicts with betterdocs search (Bug Fix Card -> https://trello.com/c/lXzrtv2f/1313-client-issue-betterdocs-is-conflicting-with-the-searchanise-plugin)
60 add_filter( 'se_load_search_widgets', [ $this, 'exclude_betterdocs_search' ], 10, 1 );
61
62 //Fix Betterdocs Search Issue With HostCluster Theme
63 if ( function_exists( 'hostcluster_search_filter' ) ) {
64 remove_filter( 'pre_get_posts', 'hostcluster_search_filter' );
65 }
66
67 //render authors template
68 add_filter( 'template_include', [$this, 'render_authors_template'], 10, 1 );
69 }
70
71 public function render_authors_template( $template_path ) {
72 $post_type = get_query_var( 'post_type' ) != null ? get_query_var( 'post_type' ) : '';
73 $author_id = get_query_var( 'author' ) != null ? get_query_var( 'author' ) : 0;
74 $author_docs_count = count_user_posts( $author_id, 'docs' );
75
76 // Only override on an actual author archive — otherwise this also fires on
77 // the main docs archive (where $author_id falls back to 0) whenever any doc
78 // has post_author 0, hijacking the docs/MKB archive (and its FSE template)
79 // with the author template.
80 if ( is_author() && $post_type == 'docs' && $author_docs_count > 0 ) {
81 wp_enqueue_style('betterdocs-breadcrumb');
82 $template_path = BETTERDOCS_ABSPATH . 'views/templates/authors/author.php';
83 }
84
85 return $template_path;
86 }
87
88 public function fse_url_update( &$wp_admin_bar ) {
89 $site_edit_node = $wp_admin_bar->get_node( 'site-editor' );
90
91 if ( empty( $site_edit_node ) ) {
92 return;
93 }
94
95 if ( is_post_type_archive( 'docs' ) || is_tax( 'knowledge_base' ) || is_tax( 'doc_category' ) || is_tax( 'doc_tag' ) || is_singular( 'docs' ) ) {
96 $href = isset( $site_edit_node->href ) ? $site_edit_node->href : '';
97 if ( ! empty( $href ) ) {
98 $href = $href . '&lang=' . ICL_LANGUAGE_CODE;
99 $site_edit_node->href = $href;
100 $wp_admin_bar->add_node( $site_edit_node );
101 }
102 }
103 }
104
105 public function exclude_betterdocs_search( $options ) {
106 $options['search_input'] = $options['search_input'] . ':not(.betterdocs-search-field)';
107 return $options;
108 }
109 public function before_render( $widget, $widget_type ) {
110 $this->widget_attributes = isset( $widget->attributes ) ? $widget->attributes : [];
111 $this->widget_type = $widget_type;
112
113 /**
114 * This line of code will run for reactions shortcode, elementor widget and blocks
115 */
116 if ( strpos( $widget->get_name(), 'reactions' ) !== false ) {
117 $this->localize_reactions_data();
118 }
119
120 /**
121 * This line of code will run for Feedback form Shortcode, Elementor widget and blocks
122 */
123 if ( strpos( $widget->get_name(), 'feedback_form' ) ) {
124 $this->localize_feedback_form_data();
125 }
126
127 add_filter( 'betterdocs_nested_terms_args', [ $this, 'terms_args' ], 11, 1 );
128 add_filter( 'betterdocs_nested_docs_args', [ $this, 'docs_args' ], 11, 1 );
129 }
130
131 public function dequeue_saliant_theme_script() {
132 if ( is_singular( 'docs' ) || is_tax( 'doc_category' ) || is_tax( 'doc_tag' ) ) {
133 wp_dequeue_script( 'salient-delay-js' );
134 }
135 }
136
137 public function after_render( $widget, $widget_type ) {
138 remove_filter( 'betterdocs_nested_terms_args', [ $this, 'terms_args' ], 11 );
139 remove_filter( 'betterdocs_nested_docs_args', [ $this, 'docs_args' ], 11 );
140
141 $this->widget_attributes = [];
142 $this->widget_type = '';
143 }
144
145 public function terms_args( $args ) {
146 switch ( $this->widget_type ) {
147 case 'shortcode':
148 if ( isset( $this->widget_attributes['terms_orderby'] ) ) {
149 $args['orderby'] = $this->widget_attributes['terms_orderby'];
150 }
151
152 if ( isset( $this->widget_attributes['terms_order'] ) ) {
153 $args['order'] = $this->widget_attributes['terms_order'];
154 }
155 break;
156 case 'blocks':
157 if ( isset( $this->widget_attributes['orderBy'] ) ) {
158 if ( $this->widget_attributes['orderBy'] == 'doc_category_order' ) {
159 // Use betterdocs_order which handles fallback logic automatically
160 $args['orderby'] = 'betterdocs_order';
161 } else {
162 $args['orderby'] = $this->widget_attributes['orderBy'];
163 }
164 }
165 if ( isset( $this->widget_attributes['order'] ) ) {
166 $args['order'] = $this->widget_attributes['order'];
167 }
168 break;
169 case 'elementor':
170 $args['orderby'] = $this->widget_attributes['orderby'];
171 $args['order'] = $this->widget_attributes['order'];
172 break;
173 }
174
175 return $args;
176 }
177
178 public function docs_args( $args ) {
179 switch ( $this->widget_type ) {
180 case 'shortcode':
181 if ( isset( $this->widget_attributes['orderby'] ) ) {
182 $args['orderby'] = $this->widget_attributes['orderby'];
183 }
184
185 if ( isset( $this->widget_attributes['order'] ) ) {
186 $args['order'] = $this->widget_attributes['order'];
187 }
188 break;
189 case 'blocks':
190 if ( isset( $this->widget_attributes['postsOrderBy'] ) ) {
191 $args['orderby'] = $this->widget_attributes['postsOrderBy'];
192 }
193 if ( isset( $this->widget_attributes['postsOrder'] ) ) {
194 $args['order'] = $this->widget_attributes['postsOrder'];
195 }
196
197 //This is for archive category block only
198 if ( isset( $this->widget_attributes['orderby'] ) ) {
199 $args['orderby'] = $this->widget_attributes['orderby'];
200 }
201 if ( isset( $this->widget_attributes['order'] ) ) {
202 $args['order'] = $this->widget_attributes['order'];
203 }
204 break;
205 case 'elementor':
206 $args['orderby'] = $this->widget_attributes['post_orderby'];
207 $args['order'] = $this->widget_attributes['post_order'];
208 break;
209 }
210
211 return $args;
212 }
213
214 public function article_reactions() {
215 $args = [];
216 $single_layout = $this->database->get_theme_mod( 'betterdocs_single_layout_select', true );
217 $reactions = $this->database->get_theme_mod( 'betterdocs_post_reactions', true );
218
219 // Get the title tag from customizer
220 $text_tag = $this->database->get_theme_mod( 'betterdocs_reactions_title_tag', 'h5' );
221
222 // Collect reaction values and icons
223 $reactions_data = [
224 'happy' => 'betterdocs_post_reactions_happy',
225 'happy_icon' => 'betterdocs_post_reactions_happy_icon',
226 'normal' => 'betterdocs_post_reactions_normal',
227 'normal_icon' => 'betterdocs_post_reactions_normal_icon',
228 'sad' => 'betterdocs_post_reactions_sad',
229 'sad_icon' => 'betterdocs_post_reactions_sad_icon'
230 ];
231
232 foreach ( $reactions_data as $key => $theme_mod ) {
233 $value = betterdocs()->customizer->defaults->get( $theme_mod );
234 if ( $value ) {
235 $args[ $key ] = $value;
236 } else {
237 $args[ $key ] = false;
238 }
239 }
240
241 // Build the attribute string for the shortcode
242 $attr = '';
243 foreach ( $args as $key => $value ) {
244 $attr .= sprintf( ' %s="%s"', esc_attr( $key ), esc_attr( $value ) );
245 }
246
247 // Render the shortcode based on layout and reactions availability
248 if ( ( $single_layout == 'layout-8' || $single_layout == 'layout-10' ) && $reactions ) {
249 echo do_shortcode( '[betterdocs_article_reactions text_tag="' . esc_attr( $text_tag ) . '" layout="layout-2"' . $attr . ']' );
250 } elseif ( $single_layout == 'layout-9' && $reactions ) {
251 echo '';
252 } elseif ( $reactions ) {
253 echo do_shortcode( '[betterdocs_article_reactions text_tag="' . esc_attr( $text_tag ) . '"' . $attr . ']' );
254 }
255 }
256
257
258 public function enqueue_scripts() {
259 if ( is_singular( 'docs' ) ) {
260 wp_enqueue_style( 'betterdocs-single' );
261 wp_enqueue_style( 'betterdocs-article-summary' );
262 wp_enqueue_style( 'betterdocs-encyclopedia' );
263 wp_enqueue_style( 'betterdocs-glossaries' );
264 wp_enqueue_script( 'clipboard' );
265 wp_enqueue_script( 'betterdocs-glossaries' );
266 }
267
268 if ( is_post_type_archive( 'docs' ) ) {
269 wp_enqueue_style( 'betterdocs-category-grid' ); //category grid shortcode is supposed to enqueue this style, but this is called again to fix flicking of UI on Docs Page
270 wp_enqueue_style( 'betterdocs-docs' );
271 }
272
273 if ( is_tax( 'doc_category' ) || is_tax( 'doc_tag' ) ) {
274 wp_enqueue_style( 'betterdocs-doc_category' );
275 }
276
277 if ( is_tax( 'doc_category' ) || is_tax( 'doc_tag' ) || is_singular( 'docs' ) ) {
278 wp_enqueue_style( 'simplebar' );
279 wp_enqueue_script( 'simplebar' );
280 wp_enqueue_script( 'betterdocs-category-grid' );
281 }
282
283 if ( is_post_type_archive( 'docs' ) || is_singular( 'docs' ) || is_tax( 'doc_category' ) || is_tax( 'doc_tag' ) || is_tax( 'knowledge_base' ) ) {
284 wp_enqueue_script( 'betterdocs' );
285 }
286
287 if ( is_tax( 'glossaries' ) ) {
288 wp_enqueue_style( 'betterdocs-encyclopedia' );
289 wp_enqueue_style( 'betterdocs-single' );
290 wp_enqueue_style( 'betterdocs-glossaries' );
291 }
292 }
293
294 public function layout_filename( $filename, $origin_layout ) {
295 $filename = ( $origin_layout === 'layout-2' ) ? 'default' : $filename;
296 return $filename;
297 }
298
299 public function init() {
300 $this->container->get( TemplateLoader::class )->init();
301
302 add_filter( 'betterdocs_articles_args', [ $this, 'article_args' ], 11, 3 );
303 }
304
305 public function article_args( $args, $term_id, $_origin_args ) {
306 if ( null == $term_id || isset( $args['orderby'] ) ) {
307 return $args;
308 }
309
310 $post__in = betterdocs()->query->get_docs_order_by_terms( $term_id );
311
312 if ( ! empty( $post__in ) ) {
313 $args['orderby'] = 'post__in';
314 $args['post__in'] = $post__in;
315 }
316
317 return $args;
318 }
319
320 public function localize_reactions_data() {
321 $this->assets->localize(
322 'betterdocs-reactions',
323 'betterdocsReactionsConfig',
324 [
325 'post_id' => get_the_ID(),
326 'FEEDBACK' => [
327 'DISPLAY' => true,
328 'TEXT' => esc_html__( 'How did you feel?', 'betterdocs' ),
329 'SUCCESS' => betterdocs()->settings->get( 'reaction_feedback_text', __( 'Thanks for your feedback', 'betterdocs' ) ),
330 'URL' => get_rest_url( null, '/betterdocs/v1/feedback' )
331 ]
332 ]
333 );
334 }
335
336 public function localize_feedback_form_data() {
337 $this->assets->localize(
338 'betterdocs',
339 'betterdocsSubmitFormConfig',
340 [
341 'ajax_url' => admin_url( 'admin-ajax.php' ),
342 'post_id' => get_the_ID(),
343 'nonce' => wp_create_nonce( 'betterdocs_submit_data' )
344 ]
345 );
346 }
347 }
348