PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 4.9.4
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v4.9.4
4.9.4 4.9.3 4.9.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 All 202 releases
betterdocs / includes / Editors / BlockEditor / Blocks / CategoryGrid.php

CategoryGrid.php in BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot 4.9.4, at includes/Editors/BlockEditor/Blocks/CategoryGrid.php

243 lines 8.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // phpcs:disable WordPress.DB.SlowDBQuery.slow_db_query_meta_query,WordPress.DB.SlowDBQuery.slow_db_query_meta_key,WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- core block query; meta/tax filtering required.
3 // phpcs:disable WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_exclude -- block exposes user-driven exclusion controls.
4 namespace WPDeveloper\BetterDocs\Editors\BlockEditor\Blocks;
5
6 use WPDeveloper\BetterDocs\Editors\BlockEditor\Block;
7
8 class CategoryGrid extends Block {
9 protected $editor_scripts = [
10 'betterdocs-blocks-editor',
11 'betterdocs-categorygrid'
12 ];
13
14 protected $editor_styles = [
15 'betterdocs-blocks-editor',
16 'betterdocs-fontawesome',
17 'betterdocs-blocks-category-grid'
18 ];
19
20 protected $frontend_scripts = [
21 'betterdocs-category-grid',
22 'betterdocs-categorygrid'
23 ];
24 protected $frontend_styles = [
25 'betterdocs-fontawesome',
26 'betterdocs-blocks-category-grid'
27 ];
28
29 /**
30 * unique name of block
31 * @return string
32 */
33 public function get_name() {
34 return 'categorygrid';
35 }
36
37 public function register_scripts() {
38 //when thrive editor mode is active, do not enqueue this script, this causes an issue with thrive edit mode
39 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only editor detection.
40 $check_for_thrive = isset( $_GET['action'] ) ? sanitize_text_field( wp_unslash( $_GET['action'] ) ) : '';
41 if ( $check_for_thrive === 'architect' ) {
42 return;
43 }
44
45 // Registered only: load_scripts() enqueues it (with masonry) when the
46 // block renders. Enqueuing it here put the script, masonry and
47 // imagesloaded on every page of the site, with or without a grid.
48 $this->assets_manager->register(
49 'betterdocs-categorygrid',
50 'blocks/categorygrid/frontend.js',
51 [ 'masonry' ]
52 );
53 }
54
55 public function get_default_attributes() {
56 return [
57 'blockId' => '',
58 'categories' => [],
59 'includeCategories' => '',
60 'excludeCategories' => '',
61 'gridPerPage' => 9,
62 'subCategoryPerGrid' => 2,
63 'orderBy' => 'doc_category_order',
64 'order' => 'asc',
65 'layout' => 'default',
66 'showTitle' => true,
67 'titleTag' => 'h2',
68 'showCount' => true,
69 'showIcon' => true,
70 'showList' => true,
71 'layoutMode' => 'grid',
72 'showHeader' => true,
73 'showButton' => true,
74 'listIcon' => 'far fa-file-alt',
75 'postsPerPage' => 5,
76 'postsOrderBy' => 'betterdocs_order',
77 'postsOrder' => 'asc',
78 'enableNestedSubcategory' => false,
79 // Default follows the global "Lazy Load Sidebar Docs & Subcategories"
80 // setting, mirroring the Elementor sidebar widget's control default, so
81 // enabling the setting lazy-loads the block too unless overridden.
82 'enableLazyLoad' => (bool) betterdocs()->settings->get( 'archive_lazy_load_descendants' ),
83 'postPerSubcategory' => 3,
84 'buttonIconPosition' => 'after',
85 'buttonIcon' => 'fas fa-angle-right',
86 'buttonPosition' => 'after',
87 'showButtonIcon' => true,
88 'colRange' => 3,
89 'TABcolRange' => 2,
90 'MOBcolRange' => 1,
91 'gridSpaceRange' => 10,
92 'TABgridSpaceRange' => 10,
93 'MOBgridSpaceRange' => 10,
94 'buttonText' => __( 'Explore More', 'betterdocs' ),
95 'categoryTitleLink' => false,
96 'selectKB' => '',
97 'listIconImageUrl' => '',
98 'prefix' => '',
99 'suffix' => '',
100 'suffixSingular' => ''
101 ];
102 }
103
104 public function render( $attributes, $content ) {
105 $this->views( 'layouts/base' );
106 }
107
108 public function view_params() {
109 $attributes = &$this->attributes;
110
111 // Sanitize the layout attribute to prevent path traversal (LFI).
112 $attributes['layout'] = sanitize_file_name( $attributes['layout'] );
113
114 $terms_object = [
115 'taxonomy' => 'doc_category',
116 'order' => $attributes['order'],
117 'orderby' => $attributes['orderBy'],
118 'number' => isset( $attributes['gridPerPage'] ) ? $attributes['gridPerPage'] : 5,
119 'hide_empty' => true
120 ];
121
122 if ( 'doc_category_order' === $attributes['orderBy'] ) {
123 // Use betterdocs_order which handles fallback logic automatically
124 $terms_object['orderby'] = 'betterdocs_order';
125 }
126
127 if ( $attributes['enableNestedSubcategory'] ) {
128 $terms_object['parent'] = 0;
129 }
130
131 $includes = $this->string_to_array( $attributes['includeCategories'] );
132 $excludes = $this->string_to_array( $attributes['excludeCategories'] );
133
134 if ( ! empty( $includes ) ) {
135 $terms_object['include'] = array_diff( $includes, (array) $excludes );
136 }
137
138 if ( ! empty( $excludes ) ) {
139 $terms_object['exclude'] = $excludes;
140 }
141
142 $_wrapper_classes = [
143 'betterdocs-category-grid-wrapper',
144 'betterdocs-blocks-grid'
145 ];
146
147 $layout_class = ( $attributes['layout'] === 'default' ) ? 'layout-1' : $attributes['layout'];
148
149 $_inner_wrapper_classes = [
150 'betterdocs-category-grid-inner-wrapper',
151 'layout-flex',
152 $layout_class,
153 $attributes['layoutMode'],
154 'betterdocs-column-' . $attributes['colRange'],
155 'betterdocs-column-tablet-' . $attributes['TABcolRange'],
156 'betterdocs-column-mobile-' . $attributes['MOBcolRange']
157 ];
158
159 $wrapper_attr = [
160 'class' => $_wrapper_classes
161 ];
162
163 $inner_wrapper_attr = [
164 'class' => $_inner_wrapper_classes,
165 'data-column_desktop' => $attributes['colRange'],
166 'data-column_tab' => $attributes['TABcolRange'],
167 'data-column_mobile' => $attributes['MOBcolRange'],
168 'data-column_space_desktop' => $attributes['gridSpaceRange'],
169 'data-colomn_space_tab' => $attributes['TABgridSpaceRange'],
170 'data-colomn_space_mobile' => $attributes['MOBgridSpaceRange']
171 ];
172
173 $docs_query = [
174 'orderby' => $attributes['postsOrderBy'],
175 'order' => $attributes['postsOrder'],
176 'posts_per_page' => $attributes['postsPerPage'],
177 'nested_subcategory' => $attributes['enableNestedSubcategory']
178 ];
179
180 $default_multiple_kb = betterdocs()->settings->get( 'multiple_kb' );
181
182 $select_kb = isset( $attributes['selectKB'] ) ? $attributes['selectKB'] : '';
183 if ( is_string( $select_kb ) && $select_kb !== '' ) {
184 $decoded = json_decode( $select_kb, true );
185 $select_kb = is_array( $decoded ) ? $decoded : [];
186 }
187 $kb_slug = is_array( $select_kb ) && isset( $select_kb['value'] ) ? $select_kb['value'] : '';
188
189 if ( is_tax( 'knowledge_base' ) && $default_multiple_kb == 1 ) {
190 $object = get_queried_object();
191 $kb_slug = $object->slug;
192 }
193
194 if ( ! empty( $kb_slug ) && $default_multiple_kb == 1 ) {
195 $terms_object['meta_query'] = [
196 'relation' => 'OR',
197 [
198 'key' => 'doc_category_knowledge_base',
199 'value' => $kb_slug,
200 'compare' => 'LIKE'
201 ]
202 ];
203 }
204
205 /**
206 * Add This Attribute When Using Outside Betterdocs Templates Only
207 */
208 if ( $default_multiple_kb == 1 && ( ! empty( $kb_slug ) ) && ( ! betterdocs()->helper->is_templates() ) ) {
209 $inner_wrapper_attr['data-mkb-slug'] = $kb_slug;
210 }
211
212 return [
213 'wrapper_attr' => $wrapper_attr,
214 'inner_wrapper_attr' => $inner_wrapper_attr,
215 'terms_query_args' => betterdocs()->query->terms_query( $terms_object ),
216 'docs_query_args' => $docs_query,
217 'widget_type' => 'category-grid',
218 'multiple_knowledge_base' => ( $default_multiple_kb && ! empty( $kb_slug ) ) ? true : false,
219 'kb_slug' => $kb_slug,
220 'nested_terms_query' => [
221 'number' => $attributes['subCategoryPerGrid']
222 ],
223 'list_icon_url' => '', // not needed for blocks, provided the prop for formality
224 'layout_type' => 'block',
225 'nested_docs_query_args' => [
226 'orderby' => $attributes['postsOrderBy'],
227 'order' => $attributes['postsOrder'],
228 'posts_per_page' => $attributes['postPerSubcategory']
229 ],
230 'list_icon_name' => ! empty( $attributes['listIconImageUrl'] ) ? [ 'value' => [ 'url' => str_replace( 'blob:', '', $attributes['listIconImageUrl'] ) ] ] : ( ! empty( $attributes['listIcon'] ) ? [ 'value' => [ 'url' => $attributes['listIcon'] ] ] : ( ! empty( betterdocs()->settings->get( 'docs_list_icon' ) ) ? [ 'value' => [ 'url' => betterdocs()->settings->get( 'docs_list_icon' )['url'] ] ] : [] ) ),
231 'button_icon' => [
232 'value' => $attributes['buttonIcon']
233 ],
234 'category_title_link' => $attributes['categoryTitleLink'],
235 'count_prefix' => $attributes['prefix'],
236 'count_suffix' => $attributes['suffix'],
237 'count_suffix_singular' => $attributes['suffixSingular'],
238 'title_tag' => $attributes['titleTag'],
239 'lazy_load' => ! empty( $attributes['enableLazyLoad'] )
240 ];
241 }
242 }
243