PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 4.2.6
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v4.2.6
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 3.5.0 3.5.1 All 200 releases
← All changes | includes/Shortcodes/CategoryGrid.php +3 -107 4.9.24.2.6 View file →
@@ -1,17 +1,10 @@
1 1 <?php
2 -// phpcs:disable WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_exclude -- shortcode exposes user-driven exclusion attribute.
2 +
3 3 namespace WPDeveloper\BetterDocs\Shortcodes;
4 4
5 -if ( ! defined( 'ABSPATH' ) ) {
6 - exit;
7 -}
8 -
9 -use WPDeveloper\BetterDocs\Core\Query;
10 5 use WPDeveloper\BetterDocs\Utils\Helper;
11 -use WPDeveloper\BetterDocs\Core\Settings;
12 6 use WPDeveloper\BetterDocs\Core\Shortcode;
13 -use WPDeveloper\BetterDocs\Admin\Customizer\Defaults;
14 7
15 8 class CategoryGrid extends Shortcode {
16 9 protected $layout_class = 'layout-1';
17 10
@@ -25,15 +18,8 @@
25 18 'icon' => 'show_icon',
26 19 'post_counter' => 'show_count'
27 20 ];
28 21
29 - public function __construct( Settings $settings, Query $query, Helper $helper, Defaults $defaults ) {
30 - parent::__construct( $settings, $query, $helper, $defaults );
31 -
32 - add_action( 'wp_ajax_betterdocs_lazy_category_body', [ $this, 'ajax_lazy_category_body' ] );
33 - add_action( 'wp_ajax_nopriv_betterdocs_lazy_category_body', [ $this, 'ajax_lazy_category_body' ] );
34 - }
35 -
36 22 public function get_name() {
37 23 return 'betterdocs_category_grid';
38 24 }
39 25
@@ -79,9 +65,8 @@
79 65 'list_icon_url' => '',
80 66 'list_icon_name' => 'list',
81 67 'show_list_icon' => true,
82 68 'sidebar_layout' => '',
83 - 'lazy_load' => false,
84 69 'wrapper_class' => []
85 70 ];
86 71 }
87 72
@@ -158,9 +143,9 @@
158 143
159 144 $terms_query = $this->query->terms_query(
160 145 [
161 146 'taxonomy' => $this->attributes['taxonomy'],
162 - 'multiple_kb' => ( $this->attributes['multiple_knowledge_base'] && ! empty( $this->attributes['kb_slug'] ) ) ? true : false,
147 + 'multiple_kb' => $this->attributes['multiple_knowledge_base'],
163 148 'kb_slug' => $this->attributes['kb_slug'],
164 149 'terms' => $this->attributes['terms'],
165 150 'order' => $this->attributes['terms_order'],
166 151 'orderby' => $this->attributes['terms_orderby'],
@@ -237,97 +222,8 @@
237 222 'category_title_link' => $category_title_link,
238 223 'layout_type' => $this->attributes['layout_type'] ?? '',
239 224 'list_icon_url' => $this->attributes['list_icon_url'] ?? '',
240 225 'show_list_icon' => $this->attributes['show_list_icon'] ?? true,
241 - 'sidebar_layout' => $this->attributes['sidebar_layout'] ?? '',
242 - 'lazy_load' => ! empty( $this->attributes['lazy_load'] )
226 + 'sidebar_layout' => $this->attributes['sidebar_layout'] ?? ''
243 227 ];
244 - }
245 -
246 - /**
247 - * AJAX handler for lazy-loaded category bodies. Returns the inner HTML of
248 - * a single .betterdocs-body (docs list + nested subcategories) for one term.
249 - * Reuses the same template (`template-parts/category-list`) that the full
250 - * page render uses, which in turn hits the nested-categories fragment cache.
251 - *
252 - * Public read, intentionally no nonce — matches the SearchForm/SearchModal
253 - * nopriv pattern and stays compatible with full-page caching (a per-request
254 - * nonce would go stale on cached anonymous pages and silently break the
255 - * lazy expand). This endpoint only ever returns data that is already public:
256 - * WP_Query runs publish-only and Query::get_doc_ids_by_term applies the same
257 - * capability filtering as the on-page render, so private/draft docs never
258 - * leak. The response is the published doc titles for a term — the same set a
259 - * visitor sees by navigating to that category — so there is nothing to gate
260 - * beyond what the normal archive already exposes.
261 - */
262 - public function ajax_lazy_category_body() {
263 - $term_id = isset( $_POST['term_id'] ) ? (int) $_POST['term_id'] : 0;
264 - $kb_slug = isset( $_POST['kb_slug'] ) ? sanitize_text_field( wp_unslash( $_POST['kb_slug'] ) ) : '';
265 - $multiple_kb = ! empty( $_POST['multiple_kb'] ) && ! empty( $kb_slug );
266 - // category_icon comes from the client when the body is inside a
267 - // sidebar layout that uses folder icons (Sleek / layout-7). Allowed
268 - // values match what nested-categories.php branches on.
269 - $category_icon = '';
270 - if ( isset( $_POST['category_icon'] ) ) {
271 - $raw = sanitize_text_field( wp_unslash( $_POST['category_icon'] ) );
272 - if ( in_array( $raw, array( 'folder', 'folder-open' ), true ) ) {
273 - $category_icon = $raw;
274 - }
275 - }
276 -
277 - if ( $term_id <= 0 ) {
278 - wp_send_json_error( [ 'message' => 'invalid term_id' ], 400 );
279 - }
280 -
281 - $term = get_term( $term_id, 'doc_category' );
282 - if ( ! $term instanceof \WP_Term ) {
283 - wp_send_json_error( [ 'message' => 'term not found' ], 404 );
284 - }
285 -
286 - $docs_query = [
287 - 'orderby' => $this->settings->get( 'alphabetically_order_post', 'betterdocs_order' ),
288 - 'order' => $this->settings->get( 'docs_order', 'ASC' ),
289 - 'posts_per_page' => -1,
290 - 'term_id' => $term->term_id,
291 - 'term_slug' => $term->slug,
292 - 'multiple_kb' => $multiple_kb,
293 - 'kb_slug' => $kb_slug,
294 - ];
295 -
296 - $view_object = betterdocs()->views;
297 -
298 - ob_start();
299 - $view_object->get(
300 - 'template-parts/category-list',
301 - [
302 - 'view_object' => $view_object,
303 - 'term' => $term,
304 - 'query_args' => betterdocs()->query->docs_query_args( $docs_query ),
305 - 'nested_subcategory' => (bool) $this->settings->get( 'archive_nested_subcategory' ),
306 - 'nested_docs_query_args' => [
307 - 'multiple_kb' => $multiple_kb,
308 - 'kb_slug' => $kb_slug,
309 - 'posts_per_page' => -1,
310 - ],
311 - 'nested_terms_query' => [
312 - 'orderby' => $this->settings->get( 'terms_orderby', 'betterdocs_order' ),
313 - 'order' => $this->settings->get( 'terms_order', 'ASC' ),
314 - ],
315 - 'show_list_icon' => true,
316 - 'list_icon_name' => 'list',
317 - 'list_icon_url' => '',
318 - 'layout_type' => '',
319 - 'widget_type' => 'category-grid',
320 - 'sidebar_layout' => '',
321 - 'category_icon' => $category_icon,
322 - 'multiple_knowledge_base' => $multiple_kb,
323 - 'kb_slug' => $kb_slug,
324 - ]
325 - );
326 - $html = ob_get_clean();
327 -
328 - wp_send_json_success( [
329 - 'term_id' => $term->term_id,
330 - 'html' => $html,
331 - ] );
332 228 }
333 229 }