* @since 1.0.0 * * @wordpress-plugin * Plugin Name: Attachment Taxonomies * Plugin URI: https://wordpress.org/plugins/attachment-taxonomies/ * Description: This plugin adds categories and tags to the WordPress media library - lightweight and developer-friendly. * Version: 1.1.1 * Author: Felix Arntz * Author URI: https://leaves-and-love.net * License: GNU General Public License v3 * License URI: http://www.gnu.org/licenses/gpl-3.0.html * Text Domain: attachment-taxonomies * Tags: attachment, media, taxonomy, categories, tags */ if ( ! defined( 'ABSPATH' ) ) { die(); } /** * Initializes the plugin and contains API methods. * * @since 1.0.0 */ final class Attachment_Taxonomies { /** * The plugin version. * * @since 1.0.0 * @var string */ const VERSION = '1.1.1'; /** * The Singleton instance. * * @since 1.0.0 * @static * @var Attachment_Taxonomies|null */ private static $instance = null; /** * Returns the Singleton instance. * * @since 1.0.0 * @static * * @return Attachment_Taxonomies The Singleton class instance. */ public static function instance() { if ( null === self::$instance ) { self::$instance = new self(); } return self::$instance; } /** * Whether the plugin is a must-use plugin. * * @since 1.0.0 * @var bool */ private $is_mu_plugin = false; /** * The relative path to the plugin files, relative from this file's directory. * * This is empty for a regular plugin, but contains the directory name for a must-use plugin. * * @since 1.0.0 * @var string */ private $base_path_relative = ''; /** * The custom taxonomies which are added through the plugin's API. * * @since 1.0.0 * @var array */ private $taxonomies = array(); /** * Constructor. * * Determines whether the plugin is used as a must-use plugin or not. * Then it loads the plugin files and hooks in the bootstrapping action. * * @since 1.0.0 */ private function __construct() { $file = wp_normalize_path( __FILE__ ); $mu_plugin_dir = wp_normalize_path( WPMU_PLUGIN_DIR ); if ( preg_match( '#^' . preg_quote( $mu_plugin_dir, '#' ) . '/#', $file ) ) { $this->is_mu_plugin = true; if ( file_exists( $mu_plugin_dir . '/attachment-taxonomies.php' ) ) { $this->base_path_relative = 'attachment-taxonomies/'; } add_action( 'muplugins_loaded', array( $this, 'bootstrap' ), 1 ); } else { add_action( 'plugins_loaded', array( $this, 'bootstrap' ), 1 ); } require_once $this->get_path( 'inc/Taxonomies_Core.php' ); require_once $this->get_path( 'inc/Taxonomy_Edit.php' ); require_once $this->get_path( 'inc/Taxonomy_Capabilities.php' ); require_once $this->get_path( 'inc/Taxonomy_Shortcode.php' ); require_once $this->get_path( 'inc/Taxonomy_Default_Terms.php' ); require_once $this->get_path( 'inc/Taxonomy.php' ); require_once $this->get_path( 'inc/Existing_Taxonomy.php' ); require_once $this->get_path( 'inc/Category.php' ); require_once $this->get_path( 'inc/Tag.php' ); } /** * Bootstraps the plugin. * * The textdomain is loaded and actions and filters are hooked in. * Furthermore the two custom attachment taxonomies the plugin defines by default are added. * * @since 1.0.0 */ public function bootstrap() { if ( $this->is_mu_plugin ) { load_muplugin_textdomain( 'attachment-taxonomies' ); } else { load_plugin_textdomain( 'attachment-taxonomies' ); } $core = Attachment_Taxonomies_Core::instance(); add_action( 'restrict_manage_posts', array( $core, 'render_taxonomy_filters' ), 10, 1 ); add_action( 'wp_enqueue_media', array( $core, 'enqueue_script' ) ); add_action( 'wp_enqueue_media', array( $core, 'print_styles' ) ); $edit = Attachment_Taxonomy_Edit::instance(); add_action( 'edit_attachment', array( $edit, 'save_ajax_attachment_taxonomies' ), 10, 1 ); add_action( 'add_attachment', array( $edit, 'save_ajax_attachment_taxonomies' ), 10, 1 ); add_filter( 'wp_prepare_attachment_for_js', array( $edit, 'add_taxonomies_to_attachment_js' ), 10, 3 ); add_filter( 'attachment_fields_to_edit', array( $edit, 'remove_taxonomies_from_attachment_compat' ), 10, 2 ); add_action( 'wp_enqueue_media', array( $edit, 'adjust_media_templates' ) ); $capabilities = Attachment_Taxonomy_Capabilities::instance(); add_filter( 'map_meta_cap', array( $capabilities, 'map_meta_cap' ), 10, 3 ); $shortcode = Attachment_Taxonomy_Shortcode::instance(); add_filter( 'shortcode_atts_gallery', array( $shortcode, 'support_gallery_taxonomy_attributes' ), 10, 3 ); $default_terms = Attachment_Taxonomy_Default_Terms::instance(); add_action( 'edit_attachment', array( $default_terms, 'ensure_default_attachment_taxonomy_terms' ), 100, 1 ); add_action( 'add_attachment', array( $default_terms, 'ensure_default_attachment_taxonomy_terms' ), 100, 1 ); add_action( 'rest_api_init', array( $default_terms, 'register_settings' ), 10, 0 ); add_action( 'admin_init', array( $default_terms, 'register_settings' ), 10, 0 ); add_action( 'admin_init', array( $default_terms, 'add_settings_fields' ), 10, 0 ); /** * Filters the taxonomy class names that will be instantiated by default. * * @since 1.1.0 * * @param array $taxonomy_class_names Array of taxonomy class names. */ $taxonomy_class_names = apply_filters( 'attachment_taxonomy_class_names', array( 'Attachment_Category', 'Attachment_Tag' ) ); $taxonomy_class_names = array_filter( array_unique( $taxonomy_class_names ), 'class_exists' ); foreach ( $taxonomy_class_names as $class_name ) { $this->add_taxonomy( new $class_name() ); } } /** * Adds an attachment taxonomy. * * The first argument must be an object of a class that is derived from the class * `Attachment_Taxonomy` or from `Attachment_Existing_Taxonomy` (if the second parameter * is set to true). * * @since 1.0.0 * @since 1.1.0 The second parameter has been deprecated. * * @param Attachment_Taxonomy $taxonomy The taxonomy object. * @param bool $deprecated Deprecated argument. * @return bool True if successful, otherwise false. */ public function add_taxonomy( $taxonomy, $deprecated = null ) { if ( is_bool( $deprecated ) || $deprecated ) { $this->deprecated_argument( __METHOD__, '1.1.0' ); } if ( ! is_a( $taxonomy, 'Attachment_Taxonomy' ) ) { return false; } $taxonomy_slug = $taxonomy->get_slug(); if ( isset( $this->taxonomies[ $taxonomy_slug ] ) ) { return false; } $this->taxonomies[ $taxonomy_slug ] = $taxonomy; if ( doing_action( 'init' ) || did_action( 'init' ) ) { $this->taxonomies[ $taxonomy_slug ]->register(); } else { add_action( 'init', array( $this->taxonomies[ $taxonomy_slug ], 'register' ) ); } return true; } /** * Returns the taxonomy object for a specific taxonomy. * * @since 1.0.0 * @since 1.1.0 The second parameter has been deprecated. * * @param string $taxonomy_slug The taxonomy slug. * @param bool $deprecated Deprecated argument. * @return Attachment_Taxonomy|null The object (class derived from Attachment_Taxonomy) or null if it does not exist. */ public function get_taxonomy( $taxonomy_slug, $deprecated = null ) { if ( is_bool( $deprecated ) || $deprecated ) { $this->deprecated_argument( __METHOD__, '1.1.0' ); } if ( ! isset( $this->taxonomies[ $taxonomy_slug ] ) ) { return null; } return $this->taxonomies[ $taxonomy_slug ]; } /** * Removes a specific taxonomy. * * @since 1.0.0 * @since 1.1.0 The second parameter has been deprecated. * * @param string $taxonomy_slug The taxonomy slug. * @param bool $deprecated Deprecated argument. * @return bool True if successful, otherwise false. */ public function remove_taxonomy( $taxonomy_slug, $deprecated = null ) { if ( is_bool( $deprecated ) || $deprecated ) { $this->deprecated_argument( __METHOD__, '1.1.0' ); } if ( ! isset( $this->taxonomies[ $taxonomy_slug ] ) ) { return false; } if ( doing_action( 'init' ) || did_action( 'init' ) ) { $this->taxonomies[ $taxonomy_slug ]->unregister(); } else { remove_action( 'init', array( $this->taxonomies[ $taxonomy_slug ], 'register' ) ); } unset( $this->taxonomies[ $taxonomy_slug ] ); return true; } /** * Returns the full path to a path relative from the plugin's directory. * * This also works when the plugin is used as a must-use plugin. * * @since 1.0.0 * * @param string $rel_path Path relative from the plugin's directory. * @return string The full path. */ public function get_path( $rel_path ) { return plugin_dir_path( __FILE__ ) . $this->base_path_relative . ltrim( $rel_path, '/' ); } /** * Returns the full URL to a path relative from the plugin's directory. * * This also works when the plugin is used as a must-use plugin. * * @since 1.0.0 * * @param string $rel_path Path relative from the plugin's directory. * @return string The full URL. */ public function get_url( $rel_path ) { return plugin_dir_url( __FILE__ ) . $this->base_path_relative . ltrim( $rel_path, '/' ); } /** * Marks a function argument as deprecated and informs when it has been used. * * @since 1.1.0 * * @param string $function The function that was called. * @param string $version The version of Attachment Taxonomies that deprecated the argument used. * @param string $message Optional. A message regarding the change. Default null. */ private function deprecated_argument( $function, $version, $message = null ) { /* This filter is documented in wp-includes/functions.php */ if ( WP_DEBUG && apply_filters( 'deprecated_argument_trigger_error', true ) ) { if ( ! is_null( $message ) ) { /* translators: 1: function name, 2: version number, 3: message */ trigger_error( sprintf( __( '%1$s was called with an argument that is deprecated since Attachment Taxonomies version %2$s! %3$s', 'attachment-taxonomies' ), $function, $version, $message ) ); } else { /* translators: 1: function name, 2: version number */ trigger_error( sprintf( __( '%1$s was called with an argument that is deprecated since Attachment Taxonomies version %2$s with no alternative available.', 'attachment-taxonomies' ), $function, $version ) ); } } } } Attachment_Taxonomies::instance();