* @since 1.0.0 */ if ( ! defined( 'ABSPATH' ) ) { die(); } if ( class_exists( 'Attachment_Taxonomies_Core' ) ) { return; } /** * Contains core methods to handle attachment taxonomies. * * @since 1.0.0 */ final class Attachment_Taxonomies_Core { /** * The Singleton instance. * * @since 1.0.0 * @static * @var Attachment_Taxonomies_Core|null */ private static $instance = null; /** * The Singleton instance. * * @since 1.0.0 * @static * * @return Attachment_Taxonomies_Core The Singleton class instance. */ public static function instance() { if ( null === self::$instance ) { self::$instance = new self(); } return self::$instance; } /** * Constructor. * * @since 1.0.0 */ private function __construct() {} /** * Checks whether there are any attachment taxonomies registered. * * @since 1.0.0 * * @return bool True if there are attachment taxonomies, otherwise false. */ public function has_taxonomies() { $taxonomies = $this->get_taxonomies(); return 0 < count( $taxonomies ); } /** * Returns attachment taxonomies. * * @since 1.0.0 * * @param string $mode Either 'names' (for an array of taxonomy slugs) or 'objects' (for an array of objects). * @return array A list of taxonomy names or objects. */ public function get_taxonomies( $mode = 'names' ) { return get_object_taxonomies( 'attachment', $mode ); } /** * Returns all terms for a specific taxonomy. * * Empty terms are also included. * * @since 1.0.0 * @since 1.1.0 The $args parameter has been added. * * @param string $taxonomy_slug The taxonomy to get the terms for. * @param array $args Optional. Additional query arguments. Default empty array. * @return array|WP_Error A list of term objects or an error if the taxonomy does not exist. */ public function get_terms_for_taxonomy( $taxonomy_slug, $args = array() ) { $args = wp_parse_args( $args, array( 'hide_empty' => false, ) ); if ( version_compare( get_bloginfo( 'version' ), '4.5', '<' ) ) { return get_terms( $taxonomy_slug, $args ); } $args['taxonomy'] = $taxonomy_slug; return get_terms( $args ); } /** * Renders attachment taxonomy filter dropdowns. * * This is only used for the PHP-based part of the media library (i.e. the regular list). * The JavaScript implementation using Backbone is used elsewhere. * * This method is hooked into the `restrict_manage_posts` action. * * @since 1.0.0 * * @param string $post_type The current post type. */ public function render_taxonomy_filters( $post_type ) { if ( 'attachment' !== $post_type && 'upload' !== get_current_screen()->base ) { return; } if ( isset( $_REQUEST['attachment-filter'] ) && 'trash' === $_REQUEST['attachment-filter'] ) { return; } foreach ( $this->get_taxonomies( 'objects' ) as $taxonomy_slug => $taxonomy ) { if ( ! $taxonomy->query_var ) { continue; } $value = isset( $_REQUEST[ $taxonomy->query_var ] ) ? $_REQUEST[ $taxonomy->query_var ] : ''; ?> has_taxonomies() ) { return; } $taxonomies = array(); $all_items = array(); $filter_by_item = array(); foreach ( $this->get_taxonomies( 'objects' ) as $taxonomy_slug => $taxonomy ) { if ( ! $taxonomy->query_var ) { continue; } $js_slug = $this->make_js_slug( $taxonomy_slug ); $taxonomies[] = $this->prepare_taxonomy_for_js( $taxonomy_slug, $taxonomy ); $all_items[ $js_slug ] = $taxonomy->labels->all_items; $filter_by_item[ $js_slug ] = $this->get_filter_by_label( $taxonomy ); } $min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min'; wp_enqueue_script( 'attachment-taxonomies', Attachment_Taxonomies::instance()->get_url( 'assets/dist/js/library' . $min . '.js' ), array( 'jquery', 'media-views' ), Attachment_Taxonomies::VERSION, true ); wp_localize_script( 'attachment-taxonomies', '_attachment_taxonomies', array( 'data' => $taxonomies, 'l10n' => array( 'all' => $all_items, 'filterBy' => $filter_by_item, ), ) ); } /** * Prints some inline styles for the taxonomy filters and term dropdowns. * * The styles are only printed from within the `admin_footer` action. * Otherwise the function will hook itself into this action and bail. * * This method is hooked into the `wp_enqueue_media` action. * * @since 1.0.0 */ public function print_styles() { $taxonomies = $this->get_taxonomies(); if ( 0 === count( $taxonomies ) ) { return; } if ( ! doing_action( 'admin_footer' ) ) { add_action( 'admin_footer', array( $this, 'print_styles' ) ); return; } $count = 2 + count( $taxonomies ); $percentage = intval( round( 84 / $count ) ); $percentage_calc = intval( round( 96 / $count ) ); ?> make_js_slug( $taxonomy_slug ); return array( 'name' => $taxonomy->label, 'slug' => $js_slug, 'slugId' => str_replace( '_', '-', $taxonomy_slug ), 'queryVar' => $taxonomy->query_var, 'terms' => array_map( array( $this, 'get_term_array' ), $this->get_terms_for_taxonomy( $taxonomy_slug ) ), ); } /** * Transforms a taxonomy slug into a slug for JavaScript. * * This is basically a transformation into camel case. * * @since 1.0.0 * * @param string $taxonomy_slug The taxonomy slug to transform. * @return string The camel case taxonomy slug. */ private function make_js_slug( $taxonomy_slug ) { return lcfirst( implode( array_map( 'ucfirst', explode( '_', $taxonomy_slug ) ) ) ); } /** * Transforms a term object into an array. * * @since 1.0.0 * * @param object $term A term object (`WP_Term` if WordPress >= 4.4). * @return array A term array. */ private function get_term_array( $term ) { if ( ! class_exists( 'WP_Term' ) || ! is_a( $term, 'WP_Term' ) ) { return get_object_vars( $term ); } return $term->to_array(); } /** * Returns the "Filter by" label for a taxonomy. * * This is an additional taxonomy label. To define it for a custom taxonomy, * a 'filter_by_item' key must be added to the labels array. * * If it is not defined, the default label will be used. * * @since 1.0.0 * * @param object $taxonomy The taxonomy object. * @return string The "Filter by" label for that taxonomy. */ private function get_filter_by_label( $taxonomy ) { if ( isset( $taxonomy->labels->filter_by_item ) ) { return $taxonomy->labels->filter_by_item; } elseif ( $taxonomy->hierarchical ) { return __( 'Filter by Category', 'attachment-taxonomies' ); } else { return __( 'Filter by Tag', 'attachment-taxonomies' ); } } }