| @@ -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 | } |