$columns * @return array */ public function columns(array $columns): array { unset($columns['taxonomy-' . PostTypes::AMENITY_TAXONOMY]); $new_columns = []; foreach ($columns as $key => $label) { $new_columns[$key] = $label; if ('title' === $key) { $new_columns['bizdexul_city'] = __('City', 'advanced-connector-for-uplisting'); $new_columns['bizdexul_state'] = __('State', 'advanced-connector-for-uplisting'); $new_columns['bizdexul_guests'] = __('Guests', 'advanced-connector-for-uplisting'); $new_columns['bizdexul_bedrooms'] = __('Bedrooms', 'advanced-connector-for-uplisting'); $new_columns['bizdexul_bathrooms'] = __('Bathrooms', 'advanced-connector-for-uplisting'); } } return $new_columns; } /** * Output custom column content for a property list row. * * @param string $column * @param int $post_id */ public function column_content(string $column, int $post_id): void { $map = [ 'bizdexul_city' => 'city', 'bizdexul_state' => 'state_territory', 'bizdexul_guests' => 'guests', 'bizdexul_bedrooms' => 'bedrooms', 'bizdexul_bathrooms' => 'bathrooms', ]; if (!isset($map[$column])) { return; } $value = bizdex_uplisting_get_post_meta($post_id, $map[$column]); echo esc_html((string) $value); } /** * Mark custom property list columns as sortable. * * @param array $columns * @return array */ public function sortable_columns(array $columns): array { $columns['bizdexul_city'] = 'bizdexul_city'; $columns['bizdexul_state'] = 'bizdexul_state'; $columns['bizdexul_guests'] = 'bizdexul_guests'; $columns['bizdexul_bedrooms'] = 'bizdexul_bedrooms'; $columns['bizdexul_bathrooms'] = 'bizdexul_bathrooms'; return $columns; } /** * Output filter dropdowns above the properties list table. * * @param string $post_type */ public function render_filters(string $post_type): void { if ($post_type !== PostTypes::PROPERTY_POST_TYPE) { return; } $filters = [ self::FILTER_CITY => ['label' => __('All Cities', 'advanced-connector-for-uplisting'), 'key' => bizdex_uplisting_meta_key('city')], self::FILTER_STATE => ['label' => __('All States', 'advanced-connector-for-uplisting'), 'key' => bizdex_uplisting_meta_key('state_territory')], self::FILTER_GUESTS => ['label' => __('All Guests', 'advanced-connector-for-uplisting'), 'key' => bizdex_uplisting_meta_key('guests')], self::FILTER_BEDROOMS => ['label' => __('All Bedrooms', 'advanced-connector-for-uplisting'), 'key' => bizdex_uplisting_meta_key('bedrooms')], self::FILTER_BATHROOMS => ['label' => __('All Bathrooms', 'advanced-connector-for-uplisting'), 'key' => bizdex_uplisting_meta_key('bathrooms')], ]; foreach ($filters as $param => $config) { $current = Request::text('get', $param); $options = $this->get_distinct_meta_values($config['key']); echo ''; } } /** * Apply sorting and meta filters to the properties admin query. * * @param \WP_Query $query */ public function handle_query(\WP_Query $query): void { if (!is_admin() || !$query->is_main_query()) { return; } if ($query->get('post_type') !== PostTypes::PROPERTY_POST_TYPE) { return; } $sort_map = [ 'bizdexul_city' => ['city', 'CHAR'], 'bizdexul_state' => ['state_territory', 'CHAR'], 'bizdexul_guests' => ['guests', 'NUMERIC'], 'bizdexul_bedrooms' => ['bedrooms', 'NUMERIC'], 'bizdexul_bathrooms' => ['bathrooms', 'NUMERIC'], ]; $orderby = (string) $query->get('orderby'); if (isset($sort_map[$orderby])) { [$meta_key, $type] = $sort_map[$orderby]; $query->set('meta_key', bizdex_uplisting_meta_key($meta_key)); $query->set('orderby', 'NUMERIC' === $type ? 'meta_value_num' : 'meta_value'); } $meta_query = []; $filter_map = [ self::FILTER_CITY => 'city', self::FILTER_STATE => 'state_territory', self::FILTER_GUESTS => 'guests', self::FILTER_BEDROOMS => 'bedrooms', self::FILTER_BATHROOMS => 'bathrooms', ]; $numeric_keys = ['guests', 'bedrooms', 'bathrooms']; foreach ($filter_map as $param => $meta_key) { $value = Request::text('get', $param); if ('' === $value) { continue; } $stored_key = bizdex_uplisting_meta_key($meta_key); $allowed_values = $this->get_distinct_meta_values($stored_key); if (!in_array($value, $allowed_values, true)) { continue; } $clause = [ 'key' => $stored_key, 'value' => $value, 'compare' => '=', ]; if (in_array($meta_key, $numeric_keys, true)) { $clause['type'] = 'NUMERIC'; } $meta_query[] = $clause; } if (!empty($meta_query)) { $query->set('meta_query', $meta_query); } } /** * Return distinct meta values for a property meta key (used by filters). * * @param string $meta_key * @return string[] */ private function get_distinct_meta_values(string $meta_key): array { global $wpdb; $cache_key = 'bizdex_uplisting_distinct_meta_' . md5($meta_key); $cached = wp_cache_get($cache_key, 'bizdex_uplisting'); if (is_array($cached)) { return $cached; } // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Distinct filter values; result is cached above. $values = $wpdb->get_col( $wpdb->prepare( "SELECT DISTINCT pm.meta_value FROM {$wpdb->postmeta} pm INNER JOIN {$wpdb->posts} p ON p.ID = pm.post_id WHERE p.post_type = %s AND pm.meta_key = %s AND pm.meta_value != '' ORDER BY pm.meta_value ASC", PostTypes::PROPERTY_POST_TYPE, $meta_key ) ); if (!is_array($values)) { return []; } $result = array_values(array_filter(array_map('strval', $values))); wp_cache_set($cache_key, $result, 'bizdex_uplisting', HOUR_IN_SECONDS); return $result; } }