@@ -39,6 +39,10 @@ public function __construct() {
3939 Hook_Registry::add_action ( 'restrict_manage_posts ' , array ( $ this , 'add_product_filter_dropdown ' ) );
4040 Hook_Registry::add_action ( 'pre_get_posts ' , array ( $ this , 'filter_articles_by_product ' ) );
4141
42+ // Register Product filter for Sections taxonomy screen.
43+ Hook_Registry::add_action ( 'admin_enqueue_scripts ' , array ( $ this , 'enqueue_sections_filter_script ' ) );
44+ Hook_Registry::add_filter ( 'terms_clauses ' , array ( $ this , 'filter_sections_by_product ' ), 10 , 2 );
45+
4246 // Add sorting.
4347 Hook_Registry::add_filter ( 'terms_clauses ' , array ( $ this , 'sort_terms_by_product ' ), 10 , 2 );
4448 }
@@ -203,7 +207,7 @@ public function add_product_filter_dropdown() {
203207 }
204208
205209 /**
206- * Apply Product filter to Articles admin query .
210+ * Filter articles by the product in the admin .
207211 *
208212 * @since 3.0.0
209213 *
@@ -244,4 +248,152 @@ public function filter_articles_by_product( $query ) {
244248
245249 $ query ->set ( 'tax_query ' , $ tax_query );
246250 }
247- }
251+
252+ /**
253+ * Enqueue script for product filter on Sections taxonomy screen.
254+ *
255+ * @since 3.0.0
256+ */
257+ public function enqueue_sections_filter_script () {
258+ $ screen = get_current_screen ();
259+ if ( ! $ screen || 'edit-tags ' !== $ screen ->base || 'wzkb_category ' !== $ screen ->taxonomy ) {
260+ return ;
261+ }
262+
263+ if ( ! current_user_can ( 'manage_categories ' ) ) {
264+ return ;
265+ }
266+
267+ $ products = get_terms (
268+ array (
269+ 'taxonomy ' => 'wzkb_product ' ,
270+ 'hide_empty ' => false ,
271+ 'orderby ' => 'name ' ,
272+ 'order ' => 'ASC ' ,
273+ )
274+ );
275+
276+ if ( empty ( $ products ) || is_wp_error ( $ products ) ) {
277+ return ;
278+ }
279+
280+ // Format products data for JS.
281+ $ products_data = array ();
282+ foreach ( $ products as $ product ) {
283+ $ products_data [] = array (
284+ 'term_id ' => $ product ->term_id ,
285+ 'name ' => $ product ->name ,
286+ );
287+ }
288+
289+ // Get current query parameters to preserve them.
290+ $ query_params = array ();
291+ // phpcs:disable WordPress.Security.NonceVerification.Recommended
292+ if ( ! empty ( $ _GET ) ) {
293+ foreach ( $ _GET as $ key => $ value ) {
294+ if ( 'wzkb_product ' !== $ key ) {
295+ // Properly sanitize GET parameters based on expected types.
296+ $ sanitized_key = sanitize_key ( $ key );
297+
298+ // Handle common WordPress admin parameters appropriately.
299+ switch ( $ sanitized_key ) {
300+ case 'taxonomy ' :
301+ case 'post_type ' :
302+ case 'orderby ' :
303+ case 'order ' :
304+ $ query_params [ $ sanitized_key ] = sanitize_text_field ( $ value );
305+ break ;
306+
307+ case 'page ' :
308+ case 'paged ' :
309+ $ query_params [ $ sanitized_key ] = absint ( $ value );
310+ break ;
311+
312+ case 's ' : // Search term.
313+ $ query_params [ $ sanitized_key ] = sanitize_text_field ( $ value );
314+ break ;
315+
316+ default :
317+ // For any other parameters, apply general sanitization.
318+ if ( is_array ( $ value ) ) {
319+ $ query_params [ $ sanitized_key ] = array_map ( 'sanitize_text_field ' , $ value );
320+ } else {
321+ $ query_params [ $ sanitized_key ] = sanitize_text_field ( $ value );
322+ }
323+ break ;
324+ }
325+ }
326+ }
327+ }
328+ // phpcs:enable WordPress.Security.NonceVerification.Recommended
329+
330+ $ selected = isset ( $ _GET ['wzkb_product ' ] ) ? absint ( $ _GET ['wzkb_product ' ] ) : 0 ; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
331+
332+ // Register and enqueue script.
333+ $ minimize = defined ( 'SCRIPT_DEBUG ' ) && SCRIPT_DEBUG ? '' : '.min ' ;
334+ wp_register_script (
335+ 'wzkb-sections-product-filter ' ,
336+ plugins_url ( 'js/sections-product-filter ' . $ minimize . '.js ' , __FILE__ ),
337+ array ( 'jquery ' ),
338+ WZKB_VERSION ,
339+ true
340+ );
341+
342+ wp_localize_script (
343+ 'wzkb-sections-product-filter ' ,
344+ 'knowledgebaseProductFilter ' ,
345+ array (
346+ 'products ' => $ products_data ,
347+ 'selectedProduct ' => $ selected ,
348+ 'queryParams ' => $ query_params ,
349+ 'strings ' => array (
350+ 'allProducts ' => __ ( 'All Products ' , 'knowledgebase ' ),
351+ 'filter ' => __ ( 'Filter ' , 'knowledgebase ' ),
352+ 'productLabel ' => __ ( 'Product: ' , 'knowledgebase ' ),
353+ 'searchPlaceholder ' => __ ( 'Search sections... ' , 'knowledgebase ' ),
354+ ),
355+ )
356+ );
357+
358+ wp_enqueue_script ( 'wzkb-sections-product-filter ' );
359+ }
360+
361+ /**
362+ * Filter Sections by selected Product.
363+ *
364+ * @since 3.0.0
365+ *
366+ * @param array $pieces Array of query SQL clauses.
367+ * @param array $taxonomies Array of taxonomy names.
368+ * @return array Modified query SQL clauses.
369+ */
370+ public function filter_sections_by_product ( $ pieces , $ taxonomies ) {
371+ global $ wpdb ;
372+
373+ // Only run for wzkb_category taxonomy queries.
374+ if ( ! in_array ( 'wzkb_category ' , $ taxonomies , true ) ) {
375+ return $ pieces ;
376+ }
377+
378+ $ screen = get_current_screen ();
379+ if ( ! $ screen || 'edit-tags ' !== $ screen ->base || 'wzkb_category ' !== $ screen ->taxonomy ) {
380+ return $ pieces ;
381+ }
382+
383+ if ( ! current_user_can ( 'manage_categories ' ) ) {
384+ return $ pieces ;
385+ }
386+
387+ if ( empty ( $ _GET ['wzkb_product ' ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
388+ return $ pieces ;
389+ }
390+
391+ $ product_id = absint ( $ _GET ['wzkb_product ' ] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
392+ if ( $ product_id ) {
393+ $ pieces ['join ' ] .= " INNER JOIN {$ wpdb ->termmeta } AS tm ON t.term_id = tm.term_id " ;
394+ $ pieces ['where ' ] .= $ wpdb ->prepare ( " AND tm.meta_key = 'product_id' AND tm.meta_value = %d " , $ product_id );
395+ }
396+
397+ return $ pieces ;
398+ }
399+ }
0 commit comments