er_title; } $category = get_term_by( 'slug', $category, $this->get_wp_slug() ); if ( ! $category instanceof \WP_Term ) { return $header_title; } return $category->name; } /** * Filter the content title for the taxonomy view. * * @since 6.2.0 * * @param string $content_title * @param View $view * * @return string */ public function filter_view_content_title( string $content_title, View $view ): string { $category = $view->get_context()->get( $this->get_wp_slug() ); if ( empty( $category ) ) { return $content_title; } $category = get_term_by( 'slug', $category, $this->get_wp_slug() ); if ( ! $category instanceof \WP_Term ) { return $content_title; } return sprintf( _x( '%1$s from this %3$s of %2$s', 'Content title for the Taxonomy View', 'tribe-events-calendar-pro' ), tribe_get_event_label_plural(), $this->get_linked_post_type_label_plural_lowercase(), strtolower( $this->get_singular_label_without_linked_post() ) ); } /** * Filters the list of taxonomies that can affect the title of the page. * * @since 6.2.0 * * @param array $taxonomies The taxonomies currently included in the title. * * @return array */ public function filter_include_to_title_taxonomies( array $taxonomies ): array { $taxonomies[] = $this->get_wp_slug(); return $taxonomies; } /** * Include the taxonomy as a default argument for the shortcode, using the non-prefixed slug. * * @since 6.2.0 * * @param array $default_arguments * @param Shortcode_Abstract $shortcode * * @return array */ public function filter_shortcode_default_arguments( array $default_arguments, Shortcode_Abstract $shortcode ): array { $slug = $this->get_slug(); $default_arguments[ $slug ] = null; /** * @todo Uncomment when the `linked_post_type_not_in` argument is added to the Events Repository * $default_arguments["exclude-{$wp_slug}"] = null; */ return $default_arguments; } /** * Include the taxonomy to the shortcode aliases. * * @since 6.2.0 * * @param array $aliased_arguments * @param Shortcode_Abstract $shortcode * * @return array */ public function filter_shortcode_aliased_arguments( array $aliased_arguments, Shortcode_Abstract $shortcode ): array { $slug = $this->get_slug(); $wp_slug = $this->get_wp_slug(); $aliased_arguments[ $wp_slug ] = $slug; /** * @todo Uncomment when the `linked_post_type_not_in` argument is added to the Events Repository * $aliased_arguments["exclude-{$wp_slug}"] = "exclude-{$slug}"; */ return $aliased_arguments; } /** * Given a list of arguments, normalize the taxonomy to term IDs. * * @since 6.2.0 * * @param array $arguments_map * @param Shortcode_Abstract $shortcode * * @return array */ public function filter_shortcode_validate_arguments_map( array $arguments_map, Shortcode_Abstract $shortcode ): array { $slug = $this->get_slug(); $taxonomy = $this->get_wp_slug(); $arguments_map[ $slug ] = static function ( $terms ) use ( $taxonomy ) { return Taxonomy::normalize_to_term_ids( $terms, $taxonomy ); }; /** * @todo Uncomment when the `linked_post_type_not_in` argument is added to the Events Repository * $arguments_map["exclude-{$slug}"] = static function ( $terms ) use ( $taxonomy ) { * return Taxonomy::normalize_to_term_ids( $terms, $taxonomy ); * }; */ return $arguments_map; } /** * Toggles the shortcode hooks for Linked Post Taxonomy. * * @since 6.2.0 * * @param bool $toggle * @param Shortcode_Abstract $shortcode */ public function toggle_shortcode_hooks( bool $toggle, Shortcode_Abstract $shortcode ): void { if ( $toggle ) { add_filter( 'tribe_events_views_v2_view_repository_args', [ $this, 'filter_shortcode_repository_args' ], 15, 3 ); } else { remove_filter( 'tribe_events_views_v2_view_repository_args', [ $this, 'filter_shortcode_repository_args' ], 15 ); } } /** * Filter the repository arguments to include the organizers taxonomy * * @since 6.2.0 * * @param array $repository_args * @param Context $context * @param View $view * * @return array */ public function filter_shortcode_repository_args( array $repository_args, Context $context, View $view ): array { if ( ! $context instanceof Context ) { return $repository_args; } $shortcode_id = $context->get( 'shortcode', false ); if ( false === $shortcode_id ) { return $repository_args; } $shortcode_args = tribe( Tribe_Events::class )->get_database_arguments( $shortcode_id ); $slug = $this->get_slug(); if ( ! empty( $shortcode_args[ $slug ] ) ) { $ids = $this->get_linked_post_type_repository()->by( $this->get_wp_slug(), $shortcode_args[ $slug ] )->get_ids(); if ( ! empty( $repository_args[ $this->get_linked_post_type_view_slug() ] ) ) { $repository_args[ $this->get_linked_post_type_view_slug() ] = array_unique( [ ...( (array) $repository_args[ $this->get_linked_post_type_view_slug() ] ), ...$ids ] ); } else { $repository_args[ $this->get_linked_post_type_view_slug() ] = $ids; } } return $repository_args; } /** * Add the relevant rewrite rules for the Linked Post taxonomy. * * @since 6.2.0 * * @param \Tribe__Rewrite $rewrite */ public function add_rewrites( $rewrite ): void { if ( ! $rewrite instanceof TEC_Rewrite ) { return; } $plural_post_type_name = $this->get_linked_post_type_rewrite_slug_plural(); $view_slug = $this->get_linked_post_type_view_slug(); // When a view Slug was not set, we don't need to add any rewrite rules. if ( ! is_string( $view_slug ) ) { return; } $taxonomy_slug = $this->get_slug(); $rewrite->add( [ "{{ archive }}", "{{ {$plural_post_type_name} }}", "{{ {$taxonomy_slug} }}", '(?:[^/]+/)*([^/]+)', ], [ 'eventDisplay' => $view_slug, 'post_type' => $this->get_linked_post_type(), $this->get_wp_slug() => '%1', ] ); $rewrite->add( [ "{{ archive }}", "{{ {$plural_post_type_name} }}", "{{ {$taxonomy_slug} }}", '(?:[^/]+/)*([^/]+)', '{{ page }}', '(\d+)', ], [ 'eventDisplay' => $view_slug, 'post_type' => $this->get_linked_post_type(), $this->get_wp_slug() => '%1', 'paged' => '%2', ] ); } /** * Filters the rewrite bases to add the Linked Post taxonomy. * * @since 6.2.0 * * @param array $bases * * @return array */ public function filter_include_rewrite_bases( array $bases ): array { $bases[ $this->get_slug() ] = [ $this->get_rewrite_slug_singular(), $this->get_rewrite_translated_slug_singular() ]; return $bases; } /** * Filters the rewrite query vars map to add the Linked Post taxonomy. * * @since 6.2.0 * * @param array $query_vars_map * * @return array */ public function filter_include_rewrite_query_vars_map( array $query_vars_map ): array { $query_vars_map[ $this->get_slug() ] = $this->get_wp_slug(); return $query_vars_map; } /** * Filters the Linked Post type admin table columns to include the Linked Post taxonomy. * * @since 6.2.0 * * @param array $defaults * * @return array */ public function filter_include_taxonomy_to_linked_post_type_admin_table( array $defaults ): array { $defaults[ $this->get_wp_slug() ] = $this->get_taxonomy_object()->labels->name; return $defaults; } /** * Filters the dynamic matchers from the rewrite to add the Linked Post taxonomy, allowing navigation to work as expected. * * @todo We dont currently have support for non hierarchical taxonomies, so we need to add it, look at the Rewrite class * in common for the `get_dynamic_matchers` method, and how it handles non-hierarchical taxonomies. Example: `tag`. * * @since 6.2.0 * * @param array $dynamic_matchers * @param array $query_vars * @param \Tribe__Rewrite $rewrite * * @return array */ public function filter_include_taxonomy_to_dynamic_matchers( array $dynamic_matchers, array $query_vars, \Tribe__Rewrite $rewrite ): array { // Handle The Events Calendar category. if ( ! isset( $query_vars[ $this->get_wp_slug() ] ) ) { return $dynamic_matchers; } $bases = (array) $rewrite->get_bases(); $taxonomy_regex = $bases[ $this->get_slug() ]; preg_match( '/^\(\?:(?[^\\)]+)\)/', $taxonomy_regex, $matches ); if ( ! isset( $matches['slugs'] ) ) { return $dynamic_matchers; } $slugs = explode( '|', $matches['slugs'] ); // The localized version is the last. $localized_slug = end( $slugs ); /* * Categories can be hierarchical and the path will be something like * `/events/category/grand-parent/parent/child/list/page/2/`. * If we can match the category to an existing one then let's make sure to build the hierarchical slug. * We cast to comma-separated list to ensure multi-category queries will not resolve to a URL. */ $category_slug = Arr::to_list( $query_vars[ $this->get_wp_slug() ] ); $category_term = get_term_by( 'slug', $category_slug, $this->get_wp_slug() ); if ( $category_term instanceof WP_Term ) { $category_slug = get_term_parents_list( $category_term->term_id, $this->get_wp_slug(), [ 'format' => 'slug', 'separator' => '/', 'link' => false, 'inclusive' => true ] ); // Remove leading/trailing slashes to get something like `grand-parent/parent/child`. $category_slug = trim( $category_slug, '/' ); // Create a capturing and non-capturing version of the taxonomy match. $dynamic_matchers["(?:{$taxonomy_regex})/(?:[^/]+/)*([^/]+)"] = "{$localized_slug}/{$category_slug}"; $dynamic_matchers["{$taxonomy_regex}/(?:[^/]+/)*([^/]+)"] = "{$localized_slug}/{$category_slug}"; } return $dynamic_matchers; } /** * Column content for the Linked Post taxonomy on the Linked Post type admin table. * * @since 6.2.0 * * @param string $column_name * @param int|string $post_id * */ public function render_taxonomy_column_on_linked_post_type_admin_table( string $column_name, $post_id ): void { $no_terms_html = sprintf( '%s', sprintf( __( 'No %1$s.', 'tribe-events-calendar-pro' ), $this->get_taxonomy_object()->labels->name ) ); // Bail when not the correct column. if ( $column_name !== $this->get_wp_slug() ) { echo $no_terms_html; return; } $terms = wp_get_object_terms( $post_id, $this->get_wp_slug() ); if ( empty( $terms ) ) { echo $no_terms_html; return; } if ( is_wp_error( $terms ) ) { echo $no_terms_html; return; } $total_terms = count( $terms ); foreach ( $terms as $i => $term ) { $url = add_query_arg( [ $this->get_wp_slug() => $term->slug, 'post_type' => $this->get_linked_post_type() ], admin_url( 'edit.php' ) ); echo '' . esc_html( $term->name ) . ''; if ( $total_terms !== $i + 1 ) { echo ', '; } } } }