| @@ -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 | |
| @@ -77,12 +63,9 @@ | ||
| 77 | 63 | 'category_title_link' => false, |
| 78 | 64 | 'layout_type' => '', |
| 79 | 65 | 'list_icon_url' => '', |
| 80 | 66 | 'list_icon_name' => 'list', |
| 81 | - 'show_list_icon' => true, | |
| 82 | - 'sidebar_layout' => '', | |
| 83 | - 'lazy_load' => false, | |
| 84 | - 'wrapper_class' => [] | |
| 67 | + 'sidebar_layout' => '' | |
| 85 | 68 | ]; |
| 86 | 69 | } |
| 87 | 70 | |
| 88 | 71 | public function generate_attributes() { |
| @@ -123,9 +106,8 @@ | ||
| 123 | 106 | $attributes['class'][] = 'single-kb'; |
| 124 | 107 | } |
| 125 | 108 | } |
| 126 | 109 | |
| 127 | - | |
| 128 | 110 | return $attributes; |
| 129 | 111 | } |
| 130 | 112 | |
| 131 | 113 | public function header_layout_sequence( $sequence, $layout, $widget_type, $args ) { |
| @@ -158,9 +140,9 @@ | ||
| 158 | 140 | |
| 159 | 141 | $terms_query = $this->query->terms_query( |
| 160 | 142 | [ |
| 161 | 143 | 'taxonomy' => $this->attributes['taxonomy'], |
| 162 | - 'multiple_kb' => ( $this->attributes['multiple_knowledge_base'] && ! empty( $this->attributes['kb_slug'] ) ) ? true : false, | |
| 144 | + 'multiple_kb' => $this->attributes['multiple_knowledge_base'], | |
| 163 | 145 | 'kb_slug' => $this->attributes['kb_slug'], |
| 164 | 146 | 'terms' => $this->attributes['terms'], |
| 165 | 147 | 'order' => $this->attributes['terms_order'], |
| 166 | 148 | 'orderby' => $this->attributes['terms_orderby'], |
| @@ -194,31 +176,10 @@ | ||
| 194 | 176 | if ( $this->attributes['multiple_knowledge_base'] && ( ! empty( $this->attributes['kb_slug'] ) ) && ( ! betterdocs()->helper->is_templates() ) ) { |
| 195 | 177 | $inner_wrapper_attr['data-mkb-slug'] = $this->attributes['kb_slug']; |
| 196 | 178 | } |
| 197 | 179 | |
| 198 | - // Prepare wrapper attributes with custom classes | |
| 199 | - $wrapper_attr_classes = [ 'betterdocs-category-grid-wrapper' ]; | |
| 200 | - | |
| 201 | - // Add custom wrapper classes if provided | |
| 202 | - if ( $this->isset( 'wrapper_class' ) ) { | |
| 203 | - $wrapper_classes = $this->attributes['wrapper_class']; | |
| 204 | - | |
| 205 | - // Handle both array and string formats | |
| 206 | - if ( is_string( $wrapper_classes ) ) { | |
| 207 | - // Split by comma or space and clean up | |
| 208 | - $wrapper_classes = preg_split( '/[,\s]+/', $wrapper_classes ); | |
| 209 | - $wrapper_classes = array_filter( array_map( 'trim', $wrapper_classes ) ); | |
| 210 | - } elseif ( is_array( $wrapper_classes ) ) { | |
| 211 | - $wrapper_classes = array_filter( $wrapper_classes ); | |
| 212 | - } | |
| 213 | - | |
| 214 | - if ( ! empty( $wrapper_classes ) ) { | |
| 215 | - $wrapper_attr_classes = array_merge( $wrapper_attr_classes, $wrapper_classes ); | |
| 216 | - } | |
| 217 | - } | |
| 218 | - | |
| 219 | 180 | return [ |
| 220 | - 'wrapper_attr' => [ 'class' => $wrapper_attr_classes ], | |
| 181 | + 'wrapper_attr' => [ 'class' => [ 'betterdocs-category-grid-wrapper' ] ], | |
| 221 | 182 | 'inner_wrapper_attr' => $inner_wrapper_attr, |
| 222 | 183 | 'layout' => 'default', |
| 223 | 184 | 'widget_type' => 'category-grid', |
| 224 | 185 | 'terms_query_args' => $terms_query, |
| @@ -223,9 +184,9 @@ | ||
| 223 | 184 | 'widget_type' => 'category-grid', |
| 224 | 185 | 'terms_query_args' => $terms_query, |
| 225 | 186 | 'docs_query_args' => $docs_query, |
| 226 | 187 | 'nested_docs_query_args' => $docs_query, |
| 227 | - 'list_icon_name' => ($this->attributes['list_icon_name'] ?? 'list') == 'list' ? 'list' : [ 'value' => $this->attributes['list_icon_name'] ?? 'list' ], | |
| 188 | + 'list_icon_name' => $this->attributes['list_icon_name'] == 'list' ? 'list' : [ 'value' => $this->attributes['list_icon_name'] ], | |
| 228 | 189 | 'show_header' => true, |
| 229 | 190 | 'show_list' => true, |
| 230 | 191 | 'show_title' => true, |
| 231 | 192 | 'show_button' => $show_button, |
| @@ -231,103 +192,12 @@ | ||
| 231 | 192 | 'show_button' => $show_button, |
| 232 | 193 | 'button_text' => $button_text, |
| 233 | 194 | 'show_button_icon' => true, |
| 234 | 195 | 'button_icon_position' => true, |
| 235 | - 'title_tag' => $this->attributes['title_tag'] ?? 'h2', | |
| 236 | 196 | 'button_icon' => true, |
| 237 | 197 | 'category_title_link' => $category_title_link, |
| 238 | - 'layout_type' => $this->attributes['layout_type'] ?? '', | |
| 239 | - 'list_icon_url' => $this->attributes['list_icon_url'] ?? '', | |
| 240 | - 'show_list_icon' => $this->attributes['show_list_icon'] ?? true, | |
| 241 | - 'sidebar_layout' => $this->attributes['sidebar_layout'] ?? '', | |
| 242 | - 'lazy_load' => ! empty( $this->attributes['lazy_load'] ) | |
| 198 | + 'layout_type' => $this->attributes['layout_type'], | |
| 199 | + 'list_icon_url' => $this->attributes['list_icon_url'], | |
| 200 | + 'sidebar_layout' => $this->attributes['sidebar_layout'] | |
| 243 | 201 | ]; |
| 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 | 202 | } |
| 333 | 203 | } |