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

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

987 lines 37.3 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\Editors;
4
5 if ( ! defined( 'ABSPATH' ) ) {
6 exit; // Exit if accessed directly
7 }
8
9 use Elementor\Controls_Manager;
10 use Elementor\Api as ElementorAPI;
11 use Elementor\Plugin as ElementorPlugin;
12 use WPDeveloper\BetterDocs\Core\Settings;
13 use WPDeveloper\BetterDocs\Utils\Enqueue;
14 use WPDeveloper\BetterDocs\Editors\Elementor\Helper;
15 use WPDeveloper\BetterDocs\Editors\Elementor\SingleDocs;
16 use WPDeveloper\BetterDocs\Editors\Elementor\Widget\ToC;
17 use WPDeveloper\BetterDocs\Editors\Elementor\Widget\DocAuthor;
18 use WPDeveloper\BetterDocs\Editors\Elementor\DocsArchive;
19 use WPDeveloper\BetterDocs\Editors\Elementor\Widget\Title;
20 use WPDeveloper\BetterDocs\Editors\Elementor\Tags\TitleTag;
21 use WPDeveloper\BetterDocs\Editors\Elementor\TemplateSource;
22 use WPDeveloper\BetterDocs\Editors\Elementor\Widget\Content;
23 use WPDeveloper\BetterDocs\Editors\Elementor\Widget\DocDate;
24 use WPDeveloper\BetterDocs\Editors\Elementor\Widget\Sidebar;
25 use WPDeveloper\BetterDocs\Editors\Elementor\Widget\DocShare;
26 use WPDeveloper\BetterDocs\Editors\Elementor\Widget\Feedback;
27 use WPDeveloper\BetterDocs\Editors\Elementor\Widget\Basic\FAQ;
28 use WPDeveloper\BetterDocs\Editors\Elementor\Widget\Reactions;
29 use WPDeveloper\BetterDocs\Editors\Elementor\Widget\Navigation;
30 use WPDeveloper\BetterDocs\Editors\Elementor\Widget\CodeSnippet;
31 use WPDeveloper\BetterDocs\Editors\Elementor\Widget\ArchiveList;
32 use WPDeveloper\BetterDocs\Editors\Elementor\Widget\PrintButton;
33 use WPDeveloper\BetterDocs\Editors\Elementor\Widget\Breadcrumbs;
34 use WPDeveloper\BetterDocs\Editors\Elementor\Widget\ReadingTime;
35 use WPDeveloper\BetterDocs\Editors\Elementor\Widget\ArticleSummary;
36 use WPDeveloper\BetterDocs\Editors\Elementor\Widget\Basic\SearchForm;
37 use WPDeveloper\BetterDocs\Editors\Elementor\Widget\Basic\CategoryBox;
38 use WPDeveloper\BetterDocs\Editors\Elementor\Widget\Basic\CategoryGrid;
39 use WPDeveloper\BetterDocs\Editors\Elementor\Widget\Basic\CategorySlateLayout;
40 use WPDeveloper\BetterDocs\Editors\Elementor\Conditions\ArchiveCondition;
41 use WPDeveloper\BetterDocs\Editors\Elementor\Widget\Tags;
42 use WPDeveloper\BetterDocs\Editors\Elementor\Widget\CategoryArchiveHeader;
43
44 class Elementor extends BaseEditor {
45 protected $is_elementor_active = false;
46 protected $is_elementor_pro_active = false;
47 protected static $is_templates_added = false;
48
49 /**
50 * Elementor plugin class
51 * @var ElementorPlugin
52 */
53 protected $elementor;
54
55 /**
56 * Elementor Helper class
57 * @var Helper
58 */
59 protected $helper;
60
61 public function __construct( Settings $settings, Enqueue $enqueue, Helper $helper ) {
62 parent::__construct( $settings, $enqueue );
63
64 $this->helper = $helper;
65 $this->is_elementor_active = betterdocs()->helper->is_plugin_active( 'elementor/elementor.php' );
66 $this->is_elementor_pro_active = betterdocs()->helper->is_plugin_active( 'elementor-pro/elementor-pro.php' );
67
68 if ( ! $this->is_elementor_active || ! class_exists( ElementorPlugin::class ) ) {
69 return;
70 }
71
72 $this->elementor = ElementorPlugin::instance();
73 }
74
75 public function init() {
76 if ( ! $this->is_elementor_active || $this->elementor == null ) {
77 return;
78 }
79
80 add_action( 'wp_enqueue_scripts', [$this, 'enqueue_scripts'] );
81
82 add_action( 'elementor/elements/categories_registered', [$this, 'register_widget_category'] );
83 add_action( 'elementor/widgets/register', [$this, 'register_basic_widgets'] );
84
85 add_action( 'elementor/editor/before_enqueue_scripts', [$this, 'editor_enqueue_scripts'] );
86 add_filter( 'elementor/editor/localize_settings', [$this, 'promote_pro_elements'] );
87
88 add_filter( 'elementor/theme/need_override_location', [$this, 'override_location'], 10, 2 );
89 add_action( 'betterdocs/elementor/widgets/query', [$this, 'betterdocs_query'], 10, 2 );
90 add_filter( 'betterdocs_base_terms_args', [$this, 'handle_editor_mode_terms_args'], 10, 1 );
91
92 if ( $this->is_elementor_pro_active ) {
93 add_action( 'elementor/dynamic_tags/register', [$this, 'register_basic_tags'] );
94 add_action( 'elementor/widgets/register', [$this, 'register_theme_builder_widgets'] );
95 add_action( 'elementor/theme/register_conditions', [$this, 'register_conditions'] );
96
97 //(Conflict Fix)Solves the issue with plugin - Sticky Header Effects for Elementor(Plugin)
98 if ( ! did_action( 'elementor/documents/register' ) ) {
99 add_action( 'elementor/documents/register', [$this, 'register_documents'] );
100 } else {
101 $this->elementor->documents->register_document_type( 'docs', SingleDocs::get_class_full_name() );
102 $this->elementor->documents->register_document_type( 'doc-archive', DocsArchive::get_class_full_name() );
103 }
104 }
105
106 $this->betterdocs_init();
107 }
108
109 public function editor_enqueue_scripts() {
110 betterdocs()->assets->enqueue( 'betterdocs-el-icon', 'elementor/css/betterdocs-el-icon.css' );
111 }
112
113 public function register_documents( $documents_manager ) {
114 $documents_manager->register_document_type( 'docs', SingleDocs::get_class_full_name() );
115 $documents_manager->register_document_type( 'doc-archive', DocsArchive::get_class_full_name() );
116 }
117
118 public function override_location( $need_override_location, $location ) {
119 if ( is_singular( ['docs'] ) && 'single' === $location ) {
120 $need_override_location = true;
121 }
122
123 return $need_override_location;
124 }
125
126 /**
127 * Query Controls
128 *
129 */
130 public function betterdocs_query( $wb, $taxonomy ) {
131 $wb->start_controls_section(
132 'eael_section_post__filters',
133 [
134 'label' => __( 'Query', 'betterdocs' )
135 ]
136 );
137
138 $default_multiple_kb = $this->multiple_kb_status();
139
140 if ( $default_multiple_kb && $taxonomy != 'knowledge_base' ) {
141 $multiple_kb_terms = $this->get_kb_terms( true, false );
142 $default_slug = count( $multiple_kb_terms ) > 0 ? array_keys( $multiple_kb_terms )[0] : '';
143
144 $wb->add_control(
145 'selected_knowledge_base',
146 [
147 'label' => __( 'Knowledge Bases', 'betterdocs' ),
148 'label_block' => true,
149 'type' => Controls_Manager::SELECT2,
150 'options' => $multiple_kb_terms,
151 'multiple' => false,
152 'default' => '',
153 'select2options' => [
154 'placeholder' => __( 'All Knowledge Base', 'betterdocs' ),
155 'allowClear' => true
156 ]
157 ]
158 );
159 }
160
161 if ( $wb->get_name() === 'betterdocs-category-grid' ) {
162 $wb->add_control(
163 'grid_query_heading',
164 [
165 'label' => __( 'Category Grid', 'betterdocs' ),
166 'type' => Controls_Manager::HEADING
167 ]
168 );
169 }
170
171 $wb->add_control(
172 'include',
173 [
174 'label' => __( 'Include', 'betterdocs' ),
175 'label_block' => true,
176 'type' => Controls_Manager::SELECT2,
177 'options' => $this->helper->get_terms( $taxonomy, 'term_id' ),
178 'multiple' => true,
179 'default' => []
180 ]
181 );
182
183 $wb->add_control(
184 'exclude',
185 [
186 'label' => __( 'Exclude', 'betterdocs' ),
187 'type' => Controls_Manager::SELECT2,
188 'options' => $this->helper->get_terms( $taxonomy, 'term_id' ),
189 'label_block' => true,
190 'post_type' => '',
191 'multiple' => true
192 ]
193 );
194
195 if ( $wb->get_name() === 'betterdocs-category-grid' ) {
196 $wb->add_control(
197 'grid_per_page',
198 [
199 'label' => __( 'Grid Per Page', 'betterdocs' ),
200 'type' => Controls_Manager::NUMBER,
201 'default' => '8'
202 ]
203 );
204 } else if ( $wb->get_name() !== 'betterdocs-sidebar' ) {
205 $wb->add_control(
206 'box_per_page',
207 [
208 'label' => __( $wb->get_name() == 'betterdocs-tab-view-list' ? 'Tabs Per Page' : 'Box Per Page', 'betterdocs' ),
209 'type' => Controls_Manager::NUMBER,
210 'default' => '8'
211 ]
212 );
213 }
214
215 $wb->add_control(
216 'offset',
217 [
218 'label' => __( 'Offset', 'betterdocs' ),
219 'type' => Controls_Manager::NUMBER,
220 'default' => '0'
221 ]
222 );
223
224 // difference between betterdocs-sidebar and betterdocs-category-grid is the default order
225 if ( $wb->get_name() === 'betterdocs-sidebar' ) {
226 $wb->add_control(
227 'orderby',
228 [
229 'label' => __( 'Terms Order By', 'betterdocs' ),
230 'type' => Controls_Manager::SELECT,
231 'options' => [
232 'none' => __( 'No order', 'betterdocs' ),
233 'name' => __( 'Name', 'betterdocs' ),
234 'slug' => __( 'Slug', 'betterdocs' ),
235 'term_group' => __( 'Term Group', 'betterdocs' ),
236 'term_id' => __( 'Term ID', 'betterdocs' ),
237 'id' => __( 'ID', 'betterdocs' ),
238 'description' => __( 'Description', 'betterdocs' ),
239 'parent' => __( 'Parent', 'betterdocs' ),
240 'betterdocs_order' => __( 'BetterDocs Order', 'betterdocs' )
241 ],
242 'default' => $this->settings->get( 'terms_orderby', 'betterdocs_order' )
243 ]
244 );
245
246 $wb->add_control(
247 'order',
248 [
249 'label' => __( 'Terms Order', 'betterdocs' ),
250 'type' => Controls_Manager::SELECT,
251 'options' => [
252 'ASC' => 'Ascending',
253 'DESC' => 'Descending'
254 ],
255 'default' => $this->settings->get( 'terms_order', 'ASC' ),
256 'condition' => [
257 'orderby!' => 'betterdocs_order'
258 ]
259
260 ]
261 );
262
263 $wb->add_control(
264 'post_orderby',
265 [
266 'label' => __( 'Docs Order By', 'betterdocs' ),
267 'type' => Controls_Manager::SELECT,
268 'options' => $this->helper->orderby_options(),
269 'default' => 'date'
270 ]
271 );
272
273 $wb->add_control(
274 'post_order',
275 [
276 'label' => __( 'Docs Order', 'betterdocs' ),
277 'type' => Controls_Manager::SELECT,
278 'options' => [
279 'asc' => 'Ascending',
280 'desc' => 'Descending'
281 ],
282 'default' => 'asc',
283 'condition' => [
284 'post_orderby!' => 'betterdocs_order'
285 ]
286 ]
287 );
288 } else {
289 $wb->add_control(
290 'orderby',
291 [
292 'label' => __( 'Order By', 'betterdocs' ),
293 'type' => Controls_Manager::SELECT,
294 'options' => [
295 'none' => __( 'No order', 'betterdocs' ),
296 'name' => __( 'Name', 'betterdocs' ),
297 'slug' => __( 'Slug', 'betterdocs' ),
298 'term_group' => __( 'Term Group', 'betterdocs' ),
299 'term_id' => __( 'Term ID', 'betterdocs' ),
300 'id' => __( 'ID', 'betterdocs' ),
301 'description' => __( 'Description', 'betterdocs' ),
302 'parent' => __( 'Parent', 'betterdocs' ),
303 'betterdocs_order' => __( 'BetterDocs Order', 'betterdocs' )
304 ],
305 'default' => 'name'
306 ]
307 );
308
309 $wb->add_control(
310 'order',
311 [
312 'label' => __( 'Order', 'betterdocs' ),
313 'type' => Controls_Manager::SELECT,
314 'options' => [
315 'ASC' => 'Ascending',
316 'DESC' => 'Descending'
317 ],
318 'default' => 'ASC',
319 'condition' => [
320 'orderby!' => 'betterdocs_order'
321 ]
322
323 ]
324 );
325 }
326
327 if ( $wb->get_name() === 'betterdocs-category-grid' || $wb->get_name() === 'betterdocs-category-slate-layout' ) {
328 $wb->add_control(
329 'grid_posts_query_heading',
330 [
331 'label' => __( 'Grid List Posts', 'betterdocs' ),
332 'type' => Controls_Manager::HEADING,
333 'separator' => 'before'
334 ]
335 );
336
337 $wb->add_control(
338 'post_per_page',
339 [
340 'label' => __( 'Post Per Page', 'betterdocs' ),
341 'type' => Controls_Manager::NUMBER,
342 'default' => '6'
343 ]
344 );
345
346 $wb->add_control(
347 'post_orderby',
348 [
349 'label' => __( 'Order By', 'betterdocs' ),
350 'type' => Controls_Manager::SELECT,
351 'options' => $this->helper->orderby_options(),
352 'default' => 'betterdocs_order'
353 ]
354 );
355
356 $wb->add_control(
357 'post_order',
358 [
359 'label' => __( 'Order', 'betterdocs' ),
360 'type' => Controls_Manager::SELECT,
361 'options' => [
362 'asc' => 'Ascending',
363 'desc' => 'Descending'
364 ],
365 'default' => 'asc',
366 'condition' => [
367 'post_orderby!' => 'betterdocs_order'
368 ]
369 ]
370 );
371 }
372
373 if ( $wb->get_name() === 'betterdocs-category-grid' ) {
374 $wb->add_control(
375 'nested_subcategory',
376 [
377 'label' => __( 'Enable Nested Subcategory', 'betterdocs' ),
378 'type' => Controls_Manager::SWITCHER,
379 'label_on' => __( 'Yes', 'betterdocs' ),
380 'label_off' => __( 'No', 'betterdocs' ),
381 'return_value' => 'true',
382 'default' => false
383 ]
384 );
385
386 $wb->add_control(
387 'subcategory_per_grid',
388 [
389 'label' => __( 'Subcategory Per Grid', 'betterdocs' ),
390 'type' => Controls_Manager::NUMBER,
391 'default' => '2',
392 'condition' => [
393 'nested_subcategory' => 'true'
394 ]
395 ]
396 );
397
398 $wb->add_control(
399 'post_per_subcat',
400 [
401 'label' => __( 'Post Per Subcategory', 'betterdocs' ),
402 'type' => Controls_Manager::NUMBER,
403 'default' => '6',
404 'condition' => [
405 'nested_subcategory' => 'true'
406 ]
407 ]
408 );
409 }
410
411 if ( $wb->get_name() === 'betterdocs-category-box' ) {
412 $wb->add_control(
413 'nested_subcategory',
414 [
415 'label' => __( 'Nested Subcategory', 'betterdocs' ),
416 'type' => Controls_Manager::SWITCHER,
417 'label_on' => __( 'Yes', 'betterdocs' ),
418 'label_off' => __( 'No', 'betterdocs' ),
419 'return_value' => 'true',
420 'default' => 'true',
421 ]
422 );
423
424 $wb->add_control(
425 'show_dynamic_categories_in_doc_category_template',
426 [
427 'label' => __( 'Show Categories Dynamically', 'betterdocs' ),
428 'type' => Controls_Manager::SWITCHER,
429 'label_on' => __( 'Yes', 'betterdocs' ),
430 'label_off' => __( 'No', 'betterdocs' ),
431 'return_value' => 'true',
432 'default' => 'true',
433 ]
434 );
435
436 $wb->add_control(
437 'show_dynamic_categories_in_doc_category_template_description',
438 [
439 'type' => Controls_Manager::RAW_HTML,
440 'raw' => __( "Note: This option is only applicable for BetterDocs Category Archive page. If enabled, this will show the Categories dynamically in your BetterDocs Category Archive page.", 'betterdocs' ),
441 'content_classes' => 'elementor-panel-alert elementor-panel-alert-info'
442 ]
443 );
444 }
445
446 if ( $wb->get_name() === 'betterdocs-sidebar' ) {
447 $wb->add_control(
448 'nested_subcategory',
449 [
450 'label' => __( 'Nested Subcategory', 'betterdocs' ),
451 'type' => Controls_Manager::SWITCHER,
452 'label_on' => __( 'Yes', 'betterdocs' ),
453 'label_off' => __( 'No', 'betterdocs' ),
454 'return_value' => 'true',
455 'default' => ( $this->settings->get( 'archive_nested_subcategory' ) == 1 ) ? 'true' : ''
456 ]
457 );
458 }
459
460 if ( $wb->get_name() === 'betterdocs-tab-view-list' ) {
461 $wb->add_control(
462 'tab_posts_query_heading',
463 [
464 'label' => __( 'Tab List Posts', 'betterdocs' ),
465 'type' => Controls_Manager::HEADING,
466 'separator' => 'before'
467 ]
468 );
469
470 $wb->add_control(
471 'tab_box_per_tabs',
472 [
473 'label' => __( 'Box Per Tabs', 'betterdocs' ),
474 'type' => Controls_Manager::NUMBER,
475 'default' => '10'
476 ]
477 );
478
479 $wb->add_control(
480 'post_per_tab',
481 [
482 'label' => __( 'Posts Per Tab', 'betterdocs' ),
483 'type' => Controls_Manager::NUMBER,
484 'default' => '10'
485 ]
486 );
487
488 $wb->add_control(
489 'tab_list_posts_orderby',
490 [
491 'label' => __( 'Posts Order By', 'betterdocs' ),
492 'type' => Controls_Manager::SELECT,
493 'options' => [
494 'name' => __( 'Name', 'betterdocs' ),
495 'slug' => __( 'Slug', 'betterdocs' ),
496 'term_group' => __( 'Term Group', 'betterdocs' ),
497 'term_id' => __( 'Term ID', 'betterdocs' ),
498 'id' => __( 'ID', 'betterdocs' ),
499 'description' => __( 'Description', 'betterdocs' ),
500 'parent' => __( 'Parent', 'betterdocs' ),
501 'betterdocs_order' => __( 'BetterDocs Order', 'betterdocs' )
502 ],
503 'default' => 'name'
504 ]
505 );
506
507 $wb->add_control(
508 'tab_list_order',
509 [
510 'label' => __( 'Order', 'betterdocs' ),
511 'type' => Controls_Manager::SELECT,
512 'options' => [
513 'ASC' => 'Ascending',
514 'DESC' => 'Descending'
515 ],
516 'default' => 'ASC'
517
518 ]
519 );
520
521 $wb->add_control(
522 'nested_subcategory_tab_list',
523 [
524 'label' => __( 'Nested Subcategory', 'betterdocs' ),
525 'type' => Controls_Manager::SWITCHER,
526 'label_on' => __( 'Yes', 'betterdocs' ),
527 'label_off' => __( 'No', 'betterdocs' ),
528 'return_value' => 'true',
529 'default' => 'true'
530 ]
531 );
532
533 $wb->add_control(
534 'nested_posts_per_page',
535 [
536 'label' => __( 'Posts Per Page', 'betterdocs' ),
537 'type' => Controls_Manager::NUMBER,
538 'default' => '-1',
539 'condition' => [
540 'nested_subcategory_tab_list' => 'true'
541 ]
542 ]
543 );
544
545 $wb->add_control(
546 'nested_sub_cat_order',
547 [
548 'label' => __( 'Nested Subcategory Order', 'betterdocs' ),
549 'type' => Controls_Manager::SELECT,
550 'options' => [
551 'ASC' => 'Ascending',
552 'DESC' => 'Descending'
553 ],
554 'default' => 'ASC',
555 'condition' => [
556 'nested_subcategory_tab_list' => 'true'
557 ]
558 ]
559 );
560
561 $wb->add_control(
562 'nested_sub_cat_orderby',
563 [
564 'label' => __( 'Nested Subcategory Order By', 'betterdocs' ),
565 'type' => Controls_Manager::SELECT,
566 'options' => [
567 'none' => __( 'No order', 'betterdocs' ),
568 'name' => __( 'Name', 'betterdocs' ),
569 'slug' => __( 'Slug', 'betterdocs' ),
570 'term_group' => __( 'Term Group', 'betterdocs' ),
571 'term_id' => __( 'Term ID', 'betterdocs' ),
572 'id' => __( 'ID', 'betterdocs' ),
573 'description' => __( 'Description', 'betterdocs' ),
574 'parent' => __( 'Parent', 'betterdocs' ),
575 'betterdocs_order' => __( 'BetterDocs Order', 'betterdocs' )
576 ],
577 'default' => 'name',
578 'condition' => [
579 'nested_subcategory_tab_list' => 'true'
580 ]
581 ]
582 );
583 }
584
585 $wb->end_controls_section();
586 }
587
588 public function multiple_kb_status() {
589 if ( $this->settings->get( 'multiple_kb' ) == 1 ) {
590 return 'true';
591 }
592
593 return '';
594 }
595
596 public function get_kb_terms( $prettify = false, $term_id = true ) {
597 $args = [
598 'taxonomy' => 'knowledge_base',
599 'hide_empty' => true,
600 'parent' => 0
601 ];
602
603 $terms_query_args = betterdocs()->query->terms_query( $args );
604 $terms = betterdocs()->query->get_terms( $terms_query_args );
605
606 if ( is_wp_error( $terms ) ) {
607 return [];
608 }
609
610 if ( $prettify ) {
611 $pretty_taxonomies = [];
612
613 foreach ( $terms as $term ) {
614 $pretty_taxonomies[$term_id ? $term->term_id : $term->slug] = $term->name;
615 }
616
617 return $pretty_taxonomies;
618 }
619
620 return $terms;
621 }
622
623 public function register_basic_tags( $module ) {
624 $module->register( new TitleTag );
625 }
626
627 /**
628 * Handle editor mode for terms query args
629 *
630 * @param array $args Terms query arguments
631 * @return array Modified arguments
632 */
633 public function handle_editor_mode_terms_args( $args ) {
634 // Only modify if we're in Elementor editor mode
635 if ( $this->elementor && $this->elementor->editor->is_edit_mode() ) {
636 // Show empty categories in editor mode for better preview
637 $args['hide_empty'] = false;
638 }
639
640 return $args;
641 }
642
643 public function register_basic_widgets( $widgets_manager ) {
644 foreach ( $this->basic_widget_lists() as $value ) {
645 $widgets_manager->register( new $value );
646 }
647 }
648
649 /**
650 *
651 * Mange all widget for single docs
652 *
653 * @return string[]
654 * @since 1.3.0
655 */
656 private function basic_widget_lists() {
657 $widget_arr = [
658 'betterdocs-elementor-search-form' => SearchForm::class,
659 'betterdocs-elementor-category-grid' => CategoryGrid::class,
660 'betterdocs-elementor-category-box' => CategoryBox::class,
661 'betterdocs-elementor-category-slate' => CategorySlateLayout::class,
662 'betterdocs-faq-widget' => FAQ::class,
663 'betterdocs-code-snippet' => CodeSnippet::class
664 ];
665
666 return $widget_arr;
667 }
668
669 public function register_widget_category( $elements_manager ) {
670 $elements_manager->add_category( 'betterdocs-elements', [
671 'title' => __( 'BetterDocs', 'betterdocs' ),
672 'icon' => 'font'
673 ], 1 );
674 }
675
676 public function promote_pro_elements( $config ) {
677 if ( $this->is_pro_active ) {
678 return $config;
679 }
680
681 $promotion_widgets = [];
682
683 if ( isset( $config['promotionWidgets'] ) ) {
684 $promotion_widgets = $config['promotionWidgets'];
685 }
686
687 $combine_array = array_merge( $promotion_widgets, [
688 [
689 'name' => 'betterdocs-multiple-kb',
690 'title' => __( 'BetterDocs Multiple KB', 'betterdocs' ),
691 'icon' => 'betterdocs-icon-category-box',
692 'categories' => '["docs-archive"]'
693 ]
694 ] );
695
696 $config['promotionWidgets'] = $combine_array;
697
698 return $config;
699 }
700
701 public function is_templates() {
702 if ( $this->is_elementor_active && $this->is_elementor_pro_active ) {
703 $post_id = get_the_ID();
704 if ( $this->elementor->editor->is_edit_mode() || (
705 get_post_meta( $post_id, '_elementor_template_type', true )
706 && $this->elementor->documents->get( $post_id )->is_built_with_elementor()
707 ) ) {
708 return true;
709 }
710 }
711
712 return null;
713 }
714
715 public function enqueue_scripts() {
716 $assets = betterdocs()->assets;
717
718 /**
719 * Widget's CSS
720 */
721 $assets->register( 'betterdocs-el-category-grid', 'elementor/css/category-grid.css' );
722 $assets->register( 'betterdocs-el-category-box', 'elementor/css/category-box.css' );
723 $assets->register( 'betterdocs-el-articles-list', 'elementor/css/articles-list.css' );
724 $assets->register( 'betterdocs-el-navigation', 'elementor/css/navigation.css' );
725 $assets->register( 'betterdocs-code-snippet', 'public/css/code-snippet.css' );
726
727 /**
728 * Widget's JS
729 */
730 $assets->register( 'betterdocs-el-category-grid', 'elementor/js/category-grid.js', ['jquery', 'betterdocs-category-toggler'] );
731 $assets->register( 'betterdocs-code-snippet', 'public/js/code-snippet.js', ['jquery'] );
732
733 /**
734 * Localize This In Order To Know If This Block Is Arriving From Betterdocs Templates Or Not
735 */
736 betterdocs()->assets->localize( 'betterdocs-el-category-grid', 'betterdocsCategoryGridConfig', [
737 'is_betterdocs_templates' => betterdocs()->helper->is_templates() ? true : false
738 ] );
739
740 if ( betterdocs()->helper->is_el_templates() == true ) {
741 $assets->enqueue( 'betterdocs-elementor-editor', 'elementor/css/betterdocs-el-edit.css' );
742
743 if ( ! $this->is_pro_active ) {
744 $assets->enqueue( 'betterdocs-elementor-editor', 'elementor/js/editor.js', ['jquery'] );
745 }
746 }
747
748 do_action( 'betterdocs_elementor_enqueue_scripts', $this );
749 }
750
751 public function register_theme_builder_widgets( $widgets_manager ) {
752 foreach ( $this->builder_widget_list() as $value ) {
753 if ( class_exists( $value ) ) {
754 $widgets_manager->register( new $value );
755 }
756 }
757 }
758
759 /**
760 * Mange all widget for single docs
761 *
762 * @return array<string>
763 * @since 1.3.0
764 */
765 public function builder_widget_list() {
766 return apply_filters( 'betterdocs_elementor_pro_widgets', [
767 'betterdocs-elementor-toc' => ToC::class,
768 'betterdocs-elementor-title' => Title::class,
769 'betterdocs-elementor-sidebar' => Sidebar::class,
770 'betterdocs-elementor-content' => Content::class,
771 'betterdocs-elementor-doc-date' => DocDate::class,
772 'betterdocs-elementor-doc-share' => DocShare::class,
773 'betterdocs-elementor-feedback' => Feedback::class,
774 'betterdocs-elementor-reactions' => Reactions::class,
775 'betterdocs-article-summary' => ArticleSummary::class,
776 'betterdocs-elementor-navigation' => Navigation::class,
777 'betterdocs-elementor-breadcrumbs' => Breadcrumbs::class,
778 'betterdocs-elementor-category-archive-list' => ArchiveList::class,
779 'betteredocs-elementor-reading-time' => ReadingTime::class,
780 'betterdocs-print-button' => PrintButton::class,
781 'betterdocs-elementor-doc-author' => DocAuthor::class,
782 'betteredocs-elementor-doc-category-archive-header' => CategoryArchiveHeader::class,
783 'betterdocs-elementor-tags' => Tags::class
784 ] );
785 }
786
787 /**
788 * @param \ElementorPro\Modules\ThemeBuilder\Classes\Conditions_Manager $conditions_manager
789 */
790 public function register_conditions( $conditions_manager ) {
791 $betterdocs_condition = betterdocs()->container->get( ArchiveCondition::class );
792 $conditions_manager->get_condition( 'general' )->register_sub_condition( $betterdocs_condition );
793 }
794
795 public function betterdocs_init() {
796 add_action( 'elementor/init', [$this, 'register_template_instance'], 20 );
797
798 static $is_done = false;
799 if ( defined( 'Elementor\Api::LIBRARY_OPTION_KEY' ) && ! $is_done ) {
800 $is_done = true;
801 add_filter( 'option_' . ElementorAPI::LIBRARY_OPTION_KEY, [$this, 'prepend_categories'] );
802 }
803
804 add_action( 'elementor/ajax/register_actions', [$this, 'modified_ajax_action'], 20 );
805
806 if ( defined( 'ELEMENTOR_VERSION' ) && version_compare( ELEMENTOR_VERSION, '3.10.0', '>=' ) && ! self::$is_templates_added ) {
807 self::$is_templates_added = true;
808 add_filter( 'http_response', [$this, 'http_response_modify_for_bd_template'], 10, 3 );
809 } elseif ( defined( 'ELEMENTOR_VERSION' ) && version_compare( ELEMENTOR_VERSION, '3.5.0', '>=' ) && ! self::$is_templates_added ) {
810 self::$is_templates_added = true;
811 add_filter( 'option_' . ElementorAPI::LIBRARY_OPTION_KEY, [$this, 'added_bd_template'] );
812 }
813 }
814
815 /**
816 * Added BetterDocs template with Elementor core templates list
817 *
818 * @param $response
819 * @param $parsed_args
820 * @param $url
821 *
822 * @return mixed
823 * @since 2.3.5
824 */
825 public function http_response_modify_for_bd_template( $response, $parsed_args, $url ) {
826 if ( $url === \Elementor\TemplateLibrary\Source_Remote::API_TEMPLATES_URL ) {
827 $templates_list = json_decode( wp_remote_retrieve_body( $response ), true );
828 $bd_templates = $this->get_templates();
829
830 if ( ! empty( $bd_templates ) ) {
831 $templates_list = array_merge( (array) $templates_list, (array) $bd_templates );
832 }
833
834 $response['body'] = json_encode( $templates_list );
835 }
836
837 return $response;
838 }
839
840 public function register_template_instance() {
841 $this->elementor->templates_manager->register_source( TemplateSource::class );
842 }
843
844 public function prepend_categories( $library_data ) {
845 $categories = $this->template_categories();
846 if ( ! empty( $categories ) ) {
847 $library_data['types_data']['block']['categories'] = array_merge(
848 $categories,
849 isset( $library_data['types_data']['block']['categories'] ) ? $library_data['types_data']['block']['categories'] : []
850 );
851 }
852 return $library_data;
853 }
854
855 public function template_categories() {
856 return [
857 'Single Docs',
858 'Docs Archive'
859 ];
860 }
861
862 /**
863 * Added BetterDocs template with Elementor core templates list
864 *
865 * added_template
866 *
867 * @param $templates_list array elementor template list
868 *
869 * @return array
870 * @since 2.0.7
871 *
872 */
873 public function added_bd_template( array $templates_list ) {
874 $templates = $this->get_templates();
875
876 if ( ! empty( $templates ) ) {
877 $templates_list['templates'] = array_merge( $templates_list['templates'], $templates );
878 }
879
880 return $templates_list;
881 }
882
883 /**
884 * get_templates
885 *
886 * Get Better docs template list and cache this list
887 *
888 * @return array|mixed
889 * @since 2.0.0
890 */
891 public function get_templates() {
892 $_cache_key = 'betterdocs_template_library_' . betterdocs()->version;
893 $source = new TemplateSource;
894 $local_ids = array_column( $source->get_local_templates(), 'template_id' );
895 $templates = get_transient( $_cache_key );
896
897 if ( ! $templates ) {
898 // Only cache remote templates — local templates are always appended fresh below
899 $all_templates = $source->get_items();
900 $remote_only = array_values( array_filter( $all_templates, function ( $t ) use ( $local_ids ) {
901 return ! in_array( $t['template_id'], $local_ids, true );
902 } ) );
903
904 if ( ! empty( $remote_only ) ) {
905 $remote_only = array_map( function ( $template ) {
906 $template['id'] = $template['template_id'];
907 $template['tmpl_created'] = $template['date'];
908 $template['tags'] = json_encode( $template['tags'] );
909 $template['is_pro'] = $template['isPro'];
910 $template['access_level'] = $template['accessLevel'];
911 $template['popularity_index'] = $template['popularityIndex'];
912 $template['trend_index'] = $template['trendIndex'];
913 $template['has_page_settings'] = $template['hasPageSettings'];
914
915 return $template;
916 }, $remote_only );
917
918 set_transient( $_cache_key, $remote_only, WEEK_IN_SECONDS );
919 $templates = $remote_only;
920 } else {
921 $templates = [];
922 }
923 } else {
924 // Strip any local templates that may have been cached in a previous version
925 $templates = array_values( array_filter( $templates, function ( $t ) use ( $local_ids ) {
926 $id = isset( $t['template_id'] ) ? $t['template_id'] : ( isset( $t['id'] ) ? $t['id'] : '' );
927 return ! in_array( $id, $local_ids, true );
928 } ) );
929 }
930
931 // Always append local templates fresh so they are never stale-cached
932 $local_templates = array_map( function ( $template ) {
933 $template['id'] = $template['template_id'];
934 $template['tmpl_created'] = $template['date'];
935 $template['tags'] = json_encode( $template['tags'] );
936 $template['is_pro'] = $template['isPro'];
937 $template['access_level'] = $template['accessLevel'];
938 $template['popularity_index'] = $template['popularityIndex'];
939 $template['trend_index'] = $template['trendIndex'];
940 $template['has_page_settings'] = $template['hasPageSettings'];
941
942 return $template;
943 }, $source->get_local_templates() );
944
945 return array_merge( $templates, $local_templates );
946 }
947
948 public function modified_ajax_action( $ajax ) {
949 if ( ! isset( $_REQUEST['actions'] ) ) {
950 return;
951 }
952
953 $actions = json_decode( stripslashes( $_REQUEST['actions'] ), true );
954 $data = false;
955
956 foreach ( $actions as $id => $action_data ) {
957 if ( ! isset( $action_data['get_template_data'] ) ) {
958 $data = $action_data;
959 }
960 }
961
962 if ( ! $data ) {
963 return;
964 }
965
966 if ( ! isset( $data['data'] ) ) {
967 return;
968 }
969
970 $data = $data['data'];
971
972 if ( empty( $data['template_id'] ) ) {
973 return;
974 }
975
976 if ( false === strpos( $data['template_id'], 'betterdocs_' ) ) {
977 return;
978 }
979 $ajax->register_ajax_action( 'get_template_data', [$this, 'get_template_data'] );
980 }
981
982 public function get_template_data( $args ) {
983 $source = new TemplateSource;
984 return $source->get_data( $args );
985 }
986 }
987