f87472ed by Jeff Balicki

stuff

Signed-off-by: Jeff <jeff@gotenzing.com>
1 parent 93ceb336
......@@ -54,18 +54,26 @@ namespace :deploy do
desc 'Install composer packages in msf-child theme'
task :install_theme_packages do
on roles(:web), in: :sequence, wait: 5 do
execute "cd '#{release_path}/wp-content/themes/msf-child'; /usr/bin/php74 /home/tenzing_www/composer.phar install --no-dev --prefer-dist --no-interaction --quiet --optimize-autoloader"
execute "cd '#{release_path}/wp-content/themes/msf-child/'; /usr/bin/php74 /home/tenzing_www/composer.phar install --quiet"
end
end
end
namespace :deploy do
desc 'Install composer packages in root'
task :install_root_packages do
on roles(:web), in: :sequence, wait: 5 do
execute "cd '#{release_path}'; /usr/bin/php74 /home/tenzing_www/composer.phar install --no-dev --prefer-dist --no-interaction --quiet --optimize-autoloader"
end
end
end
namespace :deploy do
desc 'set file permissions'
task :set_permissions do
on roles(:web), in: :sequence, wait: 5 do
execute "cd '#{release_path}/'; chmod -Rf 777 .htaccess wp-config.php"
execute "cd '#{release_path}/'; chmod -Rf 777 .htaccess"
end
end
end
......@@ -99,7 +107,8 @@ end
# Uncomment the following line to run it on deploys if needed
# after 'deploy:publishing', 'deploy:update_option_paths'
#after 'deploy:updated', 'deploy:install_theme_packages'
after 'deploy:updated', 'deploy:install_theme_packages'
after 'deploy:updated', 'deploy:install_root_packages'
after 'deploy:updated', 'deploy:sync'
#after 'deploy:updated', 'deploy:set_permissions'
after 'deploy:updated', 'deploy:set_permissions'
after 'deploy:finished', 'deploy:sync_again'
......
/* MEDIA FILTERS */
.media-modal-content .attachments-browser .media-toolbar {
display: flex;
}
.media-modal-content .attachments-browser .media-toolbar .media-toolbar-secondary,
.media-modal-content .attachments-browser .media-toolbar .media-toolbar-primary {
max-width: none;
}
.media-modal-content .attachments-browser .media-toolbar .media-toolbar-secondary {
display: flex;
flex: 1;
align-items: flex-start;
}
body.block-editor-page .media-modal-content .media-frame select.attachment-filters,
.media-modal-content .media-frame .media-toolbar select.attachment-filters {
flex: 1;
width: 50%;
margin-right: 10px;
}
.media-modal-content .media-frame .media-toolbar .spinner {
flex: 0 0 20px;
align-self: flex-end;
margin-right: 20px;
margin-bottom: 15px;
}
/* SELECTIZE */
.selectize-control.multi .selectize-input > div,
.selectize-control.multi .selectize-input > div.active {
border-width: 1px;
border-radius: 3px;
}
.compat-item tr.compat-field-selectize {
display: table-row;
overflow: auto;
}
.compat-item tr.compat-field-selectize .selectize-input {
min-height: 38px;
}
.compat-item tr.compat-field-selectize > td.field {
margin-bottom: 5px;
}
.selectize-input {
box-shadow: 0 0 0 transparent;
border-radius: 4px;
border: 1px solid #7e8993;
background-color: #fff;
color: #32373c;
}
.wp-admin .media-frame .selectize-input.input-active,
.selectize-input.input-active {
border-color: #007cba;
box-shadow: 0 0 0 1px #007cba;
}
.admin-color-light .selectize-input.input-active {
border-color: #04a4cc;
box-shadow: 0 0 0 1px #04a4cc;
}
.admin-color-blue .selectize-input.input-active {
border-color: #096484;
box-shadow: 0 0 0 1px #096484;
}
.admin-color-coffee .selectize-input.input-active {
border-color: #c7a589;
box-shadow: 0 0 0 1px #c7a589;
}
.admin-color-ectoplasm .selectize-input.input-active {
border-color: #a3b745;
box-shadow: 0 0 0 1px #a3b745;
}
.admin-color-ectoplasm .selectize-input.input-active {
border-color: #a3b745;
box-shadow: 0 0 0 1px #a3b745;
}
.admin-color-midnight .selectize-input.input-active {
border-color: #e14d43;
box-shadow: 0 0 0 1px #e14d43;
}
.admin-color-ocean .selectize-input.input-active {
border-color: #9ebaa0;
box-shadow: 0 0 0 1px #9ebaa0;
}
.admin-color-sunrise .selectize-input.input-active {
border-color: #dd823b;
box-shadow: 0 0 0 1px #dd823b;
}
.selectize-input .parent-label,
.selectize-dropdown-content .parent-label {
color: #BBBBBB;
}
.selectize-input [data-value] {
position: relative;
padding-right: 24px !important;
}
.selectize-input .remove {
z-index: 1;
position: absolute;
top: 0;
right: 0;
bottom: 0;
width: 17px;
text-align: center;
font-weight: 700;
font-size: 12px;
color: inherit;
text-decoration: none;
vertical-align: middle;
font-family: serif;
padding: 2px 0 0;
border-left: 1px solid #d0d0d0;
-webkit-border-radius: 0 2px 2px 0;
-moz-border-radius: 0 2px 2px 0;
border-radius: 0 2px 2px 0;
box-sizing: border-box;
}
.selectize-input .remove:hover {
background-color: rgba(0,0,0,.05);
}
.selectize-dropdown {
z-index: 1000000;
}
.selectize-dropdown [data-value] {
padding: 5px 8px;
}
.selectize-dropdown .searchhint {
color: rgba(48,48,48,.5);
}
/* .upload-php .selectize-dropdown {
margin-top: -33px;
} */
var f4MediaTaxonomySelectizeFocus = '';
Selectize.define('silent_remove', function(options){
var self = this;
// defang the internal search method when remove has been clicked
this.on('item_remove', function(){
this.plugin_silent_remove_in_remove = true;
});
this.search = (function() {
var original = self.search;
return function() {
if (typeof(this.plugin_silent_remove_in_remove) != "undefined") {
// re-enable normal searching
delete this.plugin_silent_remove_in_remove;
return {
items: {},
query: [],
tokens: []
};
}
else {
return original.apply(this, arguments);
}
};
})();
});
var f4MediaTaxonomySelectize = function(id, taxonomy) {
var $selectize = jQuery(id);
$selectize.closest('tr').addClass('compat-field-selectize');
$selectize.selectize({
plugins: ['remove_button', 'silent_remove'],
placeholder: taxonomy.labels.search,
dropdownParent: null,
preload: 'focus',
closeAfterSelect: true,
load: function(query, callback) {
if(!query.length) {
//this.addOption({'text': taxonomy.labels.search_hint, 'value': 'f4-media-searchhint', 'searchhint': true, 'disabled': true});
//this.refreshOptions(false);
return callback();
}
this.removeOption('f4-media-searchhint');
this.refreshOptions(false);
jQuery.ajax({
url: ajaxurl,
cache: false,
data: {
action: 'f4-media-taxonomies-search-terms',
taxonomy: taxonomy.slug,
query: query
},
success: function(response) {
callback(response.data);
}
});
},
create: function(input, callback) {
jQuery.ajax({
url: ajaxurl,
cache: false,
data: {
action: 'f4-media-taxonomies-add-term',
taxonomy: taxonomy.slug,
term_label: input
},
success: function(response) {
if(typeof response.new_term !== 'undefined') {
callback({
value: response.new_term.slug,
text: response.new_term.name
});
} else {
callback(false);
}
}
});
},
render: {
option_create: function(data, escape) {
return '<div class="create">' + taxonomy.labels.add + ': <strong>' + escape(data.input) + '</strong></div>';
},
option: function(data, escape) {
var label = (typeof data.parents !== 'undefined' && data.parents.length ? '<span class="parent-label">' + escape(data.parents.join(' / ')) + ' /</span> ' : '') + escape(data.text);
if(typeof data.searchhint === 'undefined') {
return '<div>' + label + '</div>';
} else {
return '<div class="searchhint">' + label + '</div>';
}
},
item: function(data, escape) {
var isNewTerm = typeof data.parents === 'undefined';
if(isNewTerm) {
data.parents = [];
let selectedItems = JSON.parse(this.$input.attr('data-selected-items'));
let termSlug = data.text;
if(typeof selectedItems[termSlug] !== 'undefined') {
data.text = selectedItems[termSlug].name;
data.parents = selectedItems[termSlug].parents || [];
}
}
var sortStringArray = data.parents.slice(0);
sortStringArray.push(data.text);
var sort_string = sortStringArray.join('-').toLowerCase();
var label = (data.parents.length ? '<span class="parent-label">' + escape(data.parents.join(' / ')) + ' /</span> ' : '') + escape(data.text);
return '<div data-sort-string="' + escape(sort_string) + '">' + label + '</div>';
}
},
onFocus: function() {
let items = [];
if(this.currentResults) {
items = this.currentResults.items;
}
if(!items.length) {
this.addOption({'text': taxonomy.labels.search_hint, 'value': 'f4-media-searchhint', 'searchhint': true, 'disabled': true});
}
f4MediaTaxonomySelectizeFocus = id;
},
onItemRemove: function() {
f4MediaTaxonomySelectizeFocus = '';
},
onBlur: function() {
this.removeOption('f4-media-searchhint');
this.refreshOptions(false);
f4MediaTaxonomySelectizeFocus = '';
},
onItemAdd: function(value, $element) {
$element.parent().children(':not(input)').sort(function(a, b) {
var upA = jQuery(a).attr('data-sort-string');
var upB = jQuery(b).attr('data-sort-string');
return upA.localeCompare(upB, undefined, {
numeric: true,
sensitivity: 'base'
});
}).removeClass('active').insertBefore($element.parent().children('input'));
}
});
if(f4MediaTaxonomySelectizeFocus === id) {
$selectize[0].selectize.focus();
}
};
(function($){
if(typeof f4MediaTaxonomy === 'undefined' || f4MediaTaxonomy.taxonomies.length === 0) {
return;
}
setTimeout(function() {
// Bulk actions
var $bulk = jQuery('[name="action"], [name="action2"]');
if($bulk.length) {
for(var mediaTaxonomyName in f4MediaTaxonomy.taxonomies) {
var mediaTaxonomy = f4MediaTaxonomy.taxonomies[mediaTaxonomyName];
var $taxonomy = jQuery('<optgroup label="' + mediaTaxonomy.labels.bulk_title + '"></optgroup');
mediaTaxonomy.terms.forEach(function(mediaTerm) {
var $term = jQuery($term);
var indent = Array(mediaTerm.level).join('&nbsp;&nbsp;&nbsp;');
$taxonomy.append('<option value="' + f4MediaTaxonomy.bulk_action_prefix + mediaTerm.term_id + '">' + indent + mediaTerm.name + '</option>');
});
$bulk.append($taxonomy);
}
}
}, 1000);
})(jQuery);
(function($){
if(typeof f4MediaTaxonomy === 'undefined' || f4MediaTaxonomy.taxonomies.length === 0) {
return;
}
// Overlay and grid filters
if(typeof wp !== 'undefined' && typeof wp.media !== 'undefined') {
var media = wp.media;
if(typeof media.view.AttachmentFilters === 'undefined') {
return;
}
var attachmentsBrowser = media.view.AttachmentsBrowser;
var attachmentFilter = media.view.AttachmentFilters.extend({
createFilters: function() {
var filters = {};
var that = this;
_.each(that.options.taxonomy.terms, function(mediaTerm, index) {
var indent = Array(mediaTerm.level).join('&nbsp;&nbsp;&nbsp;');
filters[index] = {
text: indent + mediaTerm.name,
props: {}
};
filters[index].props[that.options.taxonomy.query_var] = mediaTerm.slug;
});
filters.all = {
text: that.options.taxonomy.labels.all_items,
props: {},
priority: 10
};
filters.all.props[that.options.taxonomy.query_var] = '';
this.filters = filters;
}
});
media.view.AttachmentsBrowser = media.view.AttachmentsBrowser.extend({
createToolbar: function() {
var that = this;
attachmentsBrowser.prototype.createToolbar.call(that);
for(var mediaTaxonomyName in f4MediaTaxonomy.taxonomies) {
var mediaTaxonomy = f4MediaTaxonomy.taxonomies[mediaTaxonomyName];
that.toolbar.set('f4-media-taxonomy-' + mediaTaxonomy.slug + '-label', new media.view.Label({
value: mediaTaxonomy.labels.singular,
attributes: {
for: 'f4-media-taxonomy-' + mediaTaxonomy.slug + '-filter'
},
priority: (-75)
}).render());
that.toolbar.set('f4-media-taxonomy-' + mediaTaxonomy.slug + '-filter', new attachmentFilter({
controller: that.controller,
model: that.collection.props,
priority: (-75),
taxonomy: mediaTaxonomy,
id: 'f4-media-taxonomy-' + mediaTaxonomy.slug + '-filter',
className: 'f4-media-taxonomy-filter attachment-filters'
}).render());
}
}
});
}
})(jQuery);
<?php
/*
Plugin Name: F4 Media Taxonomies
Plugin URI: https://github.com/faktorvier/f4-media-taxonomies
Description: Add filters and bulk actions for attachment categories, tags and custom taxonomies.
Version: 1.1.3
Author: FAKTOR VIER
Author URI: https://www.f4dev.ch
License: GPLv2
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: f4-media-taxonomies
Domain Path: /languages/
F4 Media Taxonomies is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
any later version.
F4 Media Taxonomies is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with F4 Media Taxonomies. If not, see https://www.gnu.org/licenses/gpl-2.0.html.
*/
if(!defined('ABSPATH')) exit;
define('F4_MT_VERSION', '1.1.3');
define('F4_MT_SLUG', 'f4-media-taxonomies');
define('F4_MT_MAIN_FILE', __FILE__);
define('F4_MT_BASENAME', plugin_basename(F4_MT_MAIN_FILE));
define('F4_MT_PATH', dirname(F4_MT_MAIN_FILE) . DIRECTORY_SEPARATOR);
define('F4_MT_URL', plugins_url('/', F4_MT_MAIN_FILE));
define('F4_MT_PLUGIN_FILE', basename(F4_MT_BASENAME));
define('F4_MT_PLUGIN_FILE_PATH', F4_MT_PATH . F4_MT_PLUGIN_FILE);
// Add autoloader
spl_autoload_register(function($class) {
$class = ltrim($class, '\\');
$ns_prefix = 'F4\\MT\\';
if(strpos($class, $ns_prefix) !== 0) {
return;
}
$class_name = str_replace($ns_prefix, '', $class);
$class_path = str_replace('\\', DIRECTORY_SEPARATOR, $class_name);
$class_file = F4_MT_PATH . 'modules' . DIRECTORY_SEPARATOR . $class_path . '.php';
if(file_exists($class_file)) {
require_once $class_file;
}
});
// Init modules
F4\MT\Core\Hooks::init();
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: F4 Media Taxonomies\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-07-05 14:06+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: \n"
"Language: \n"
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Loco https://localise.biz/\n"
"X-Loco-Version: 2.3.3; wp-5.4.1"
#. Description of the plugin
msgid ""
"Add filters and bulk actions for attachment categories, tags and custom "
"taxonomies."
msgstr ""
#: modules/Core/Hooks.php:158
msgid "Assign %taxonomy%"
msgstr ""
#: modules/Core/Hooks.php:310
msgid "Attachment(s) updated."
msgstr ""
#: modules/Core/Hooks.php:161
#, php-format
msgid "Please enter %chars% or more characters"
msgstr ""
<?php
namespace F4\MT\Core;
/**
* F4 Media Taxonomies Core Helpers
*
* All the helpers for the core module
*
* @since 1.0.0
* @package F4\MT\Core
*/
class Helpers {
/**
* Get terms sorted by hierarchy
*
* @since 1.0.0
* @access public
* @static
* @param array $args The arguments which should be passed to the get_terms function
* @param int $parent The terms parent id (for recursive usage)
* @param int $level The current level (for recursive usage)
* @param array $parents An array with all the parent terms (for recursive usage)
* @return array $terms_all An array with all the terms for this taxonomy
*/
public static function get_terms_hierarchical($args = array(), $parent = 0, $level = 1, $parents = array()) {
$terms_all = array();
$args['parent'] = $args['child_of'] = $parent;
$terms = get_terms($args);
if (is_wp_error($terms)) {
return $terms_all;
}
foreach((array) $terms as $term) {
$term->level = $level;
$term->parents = $parents;
$term_parents = $parents;
$term_parents[] = $term->name;
$terms_all[] = $term;
$terms_sub = self::get_terms_hierarchical($args, $term->term_id, $level + 1, $term_parents);
if(!empty($terms_sub)) {
$terms_all = array_merge($terms_all, $terms_sub);
}
}
return $terms_all;
}
}
<?php
namespace F4\MT\Core;
/**
* F4 Media Taxonomies Core Hooks
*
* All the WordPress hooks for the core module
*
* @since 1.0.0
* @package F4\MT\Core
*/
class Hooks {
/**
* Initialize the hooks
*
* @since 1.0.0
* @access public
* @static
*/
public static function init() {
add_action('init', __NAMESPACE__ . '\\Hooks::core_loaded');
add_action('init', __NAMESPACE__ . '\\Hooks::load_textdomain');
add_action('init', __NAMESPACE__ . '\\Hooks::load_taxonomies', 99);
add_action('admin_enqueue_scripts', __NAMESPACE__ . '\\Hooks::load_properties', 50);
add_action('F4/MT/Core/set_constants', __NAMESPACE__ . '\\Hooks::set_default_constants', 98);
add_action('admin_head', __NAMESPACE__ . '\\Hooks::add_custom_js');
add_action('customize_controls_print_scripts', __NAMESPACE__ . '\\Hooks::add_custom_js');
add_action('admin_enqueue_scripts', __NAMESPACE__ . '\\Hooks::admin_enqueue_scripts', 60);
add_action('restrict_manage_posts', __NAMESPACE__ . '\\Hooks::add_media_list_filter');
add_action('load-upload.php', __NAMESPACE__ . '\\Hooks::run_bulk_action');
add_action('admin_notices', __NAMESPACE__ . '\\Hooks::show_bulk_action_notice');
add_filter('attachment_fields_to_edit', __NAMESPACE__ . '\\Hooks::attachment_fields_to_edit', 1, 2);
add_filter('update_post_term_count_statuses', __NAMESPACE__ . '\\Hooks::update_post_term_count_statuses', 10, 2);
add_action('wp_ajax_f4-media-taxonomies-add-term', __NAMESPACE__ . '\\Hooks::ajax_add_term');
add_action('wp_ajax_f4-media-taxonomies-search-terms', __NAMESPACE__ . '\\Hooks::ajax_search_terms');
add_action('elementor/editor/after_enqueue_scripts', __NAMESPACE__ . '\\Hooks::load_properties', 50);
add_action('elementor/editor/after_enqueue_scripts', __NAMESPACE__ . '\\Hooks::add_custom_js', 55);
add_action('elementor/editor/after_enqueue_scripts', __NAMESPACE__ . '\\Hooks::admin_enqueue_scripts', 60);
}
/**
* Fires once the core module is loaded
*
* @since 1.0.0
* @access public
* @static
*/
public static function core_loaded() {
do_action('F4/MT/Core/set_constants');
do_action('F4/MT/Core/loaded');
}
/**
* Load and filter all available attachment taxonomies
*
* @since 1.0.0
* @access public
* @static
* @return array $attachment_taxonomies An array with all available attachment taxonomies
*/
public static function load_taxonomies() {
$attachment_taxonomies_raw = get_taxonomies_for_attachments('objects');
$attachment_taxonomies_raw = apply_filters('F4/MT/Core/load_taxonomies', $attachment_taxonomies_raw);
$attachment_taxonomies = array();
foreach($attachment_taxonomies_raw as $attachment_taxonomy) {
if($attachment_taxonomy->show_ui) {
$attachment_taxonomies[] = $attachment_taxonomy;
}
}
Property::$taxonomies = $attachment_taxonomies;
return $attachment_taxonomies;
}
/**
* Load properties
*
* @since 1.0.0
* @access public
* @static
*/
public static function load_properties() {
global $pagenow, $mode, $wp_scripts;
Property::$has_bulk_action = $pagenow === 'upload.php' && $mode !== 'grid';
Property::$has_filter = wp_script_is('media-views') || wp_script_is('acf-input') || apply_filters('F4/MT/Core/has_filter', false) || ($pagenow === 'upload.php' && $mode === 'grid') || apply_filters('cmb2_enqueue_js', true);
Property::$has_assignment = Property::$has_filter;
do_action('F4/MT/Core/load_properties');
}
/**
* Sets the default constants
*
* @since 1.0.0
* @access public
* @static
*/
public static function set_default_constants() {
if(!defined('DS')) {
define('DS', DIRECTORY_SEPARATOR);
}
define('F4_MT_BULK_ACTION_PREFIX', 'f4_mt_toggle_');
}
/**
* Load plugin textdomain
*
* @since 1.0.0
* @access public
* @static
*/
public static function load_textdomain() {
load_plugin_textdomain('f4-media-taxonomies', false, plugin_basename(F4_MT_PATH . 'languages') . DS);
}
/**
* Add custom js into admin head
*
* @since 1.0.0
* @access public
* @static
*/
public static function add_custom_js() {
global $pagenow, $mode;
// Abort if page has no bulk actions or filter
if(!Property::$has_bulk_action && !Property::$has_filter && !Property::$has_assignment) {
return;
}
// Get available media taxonomies
$media_taxonomy_data = array(
'taxonomies' => array(),
'bulk_action_prefix' => F4_MT_BULK_ACTION_PREFIX
);
foreach(Property::$taxonomies as $media_taxonomy) {
$media_taxonomy_data['taxonomies'][$media_taxonomy->name] = array(
'slug' => $media_taxonomy->name,
'terms' => [],
'terms' => Helpers::get_terms_hierarchical(array(
'taxonomy' => $media_taxonomy->name,
'hide_empty' => false
)),
'query_var' => $media_taxonomy->query_var,
'labels' => array(
'all_items' => $media_taxonomy->labels->all_items,
'singular' => $media_taxonomy->labels->singular_name,
'plural' => $media_taxonomy->labels->name,
'bulk_title' => str_replace('%taxonomy%', $media_taxonomy->labels->name, __('Assign %taxonomy%', 'f4-media-taxonomies')),
'search' => $media_taxonomy->labels->search_items,
'add' => $media_taxonomy->labels->add_new_item,
'search_hint' => str_replace('%chars%', '1', __('Please enter %chars% or more characters', 'f4-media-taxonomies'))
)
);
}
// Output media taxonomies as js code
echo '<script>
var f4MediaTaxonomy = ' . json_encode($media_taxonomy_data) . '
</script>';
}
/**
* Enqueue admin script and styles
*
* @since 1.0.0
* @access public
* @static
*/
public static function admin_enqueue_scripts() {
global $pagenow, $mode;
// Enqueue filters script
if(Property::$has_filter) {
wp_enqueue_script(
'f4-media-taxonomies-filter',
F4_MT_URL . 'assets/js/filter.js',
array('media-views'),
false,
true
);
}
// Enqueue bulk script
if(Property::$has_bulk_action) {
wp_enqueue_script(
'f4-media-taxonomies-bulk',
F4_MT_URL . 'assets/js/bulk.js',
array(),
false,
true
);
}
// Eneuque selecrize
if(Property::$has_assignment) {
wp_enqueue_script('selectize', 'https://cdnjs.cloudflare.com/ajax/libs/selectize.js/0.13.5/js/standalone/selectize.js', array(), '0.13.5');
wp_enqueue_style('selectize', 'https://cdnjs.cloudflare.com/ajax/libs/selectize.js/0.13.5/css/selectize.min.css', array(), '0.13.5');
wp_enqueue_script(
'f4-media-taxonomies-assignment',
F4_MT_URL . 'assets/js/assignment.js',
array(),
false,
true
);
}
// Enqueue styles
if(Property::$has_bulk_action || Property::$has_filter || Property::$has_assignment) {
wp_enqueue_style(
'f4-media-taxonomies-styles',
F4_MT_URL . 'assets/css/styles.css'
);
}
}
/**
* Add taxonomy filters to the media library list
*
* @since 1.0.0
* @access public
* @static
*/
public static function add_media_list_filter() {
global $pagenow;
if($pagenow === 'upload.php') {
foreach(Property::$taxonomies as $media_taxonomy) {
$dropdown = wp_dropdown_categories(array(
'taxonomy' => $media_taxonomy->name,
'name' => $media_taxonomy->query_var,
'id' => 'f4-media-taxonomies-' . $media_taxonomy->name . '-filter',
'show_option_none' => $media_taxonomy->labels->all_items,
'option_none_value' => '',
'hide_empty' => false,
'hierarchical' => $media_taxonomy->hierarchical,
'orderby' => 'name',
'order' => 'ASC',
'show_count' => false,
'value_field' => 'slug',
'selected' => isset($_REQUEST[$media_taxonomy->query_var]) ? $_REQUEST[$media_taxonomy->query_var] : -1
));
}
}
}
/**
* Run bulk action
*
* @since 1.0.0
* @access public
* @static
*/
public static function run_bulk_action() {
$is_bulk_action = isset($_REQUEST['action']) && strpos($_REQUEST['action'], F4_MT_BULK_ACTION_PREFIX) !== false;
$is_bulk_action2 = isset($_REQUEST['action2']) && strpos($_REQUEST['action2'], F4_MT_BULK_ACTION_PREFIX) !== false;
if(!isset($_REQUEST['media']) || (!$is_bulk_action && !$is_bulk_action2)) {
return;
}
check_admin_referer('bulk-media');
$media_action = $is_bulk_action2 ? $_REQUEST['action2'] : $_REQUEST['action'];
$media_ids = array_map('intval', $_REQUEST['media']);
$media_term_id = (int)substr($media_action, strlen(F4_MT_BULK_ACTION_PREFIX));
$media_term = get_term($media_term_id);
if(!is_object($media_term) || !is_a($media_term, 'WP_Term')) {
return;
}
$backlink = remove_query_arg(array('action', 'action2', 'media', '_ajax_nonce', 'filter_action', 'toggle-taxonomy'));
$backlink = add_query_arg('toggle-taxonomy', $media_term->taxonomy, $backlink);
foreach($media_ids as $media_id) {
$media_has_term = has_term($media_term_id, $media_term->taxonomy, $media_id);
if($media_has_term) {
wp_remove_object_terms($media_id, $media_term_id, $media_term->taxonomy);
} else {
wp_add_object_terms($media_id, $media_term_id, $media_term->taxonomy);
}
}
wp_redirect($backlink);
exit();
}
/**
* Show bulk action notice after complete
*
* @since 1.0.0
* @access public
* @static
*/
public static function show_bulk_action_notice() {
global $post_type, $pagenow;
if(Property::$has_bulk_action && isset($_GET['toggle-taxonomy'])) {
echo '<div class="notice notice-success is-dismissible"><p>' . __('Attachment(s) updated.', 'f4-media-taxonomies') . '</p></div>';
}
}
/**
* Add fields to attachment
*
* @since 1.0.0
* @access public
* @static
* @param array $fields An array with all fields to edit
* @param \WP_Post $post An object for the current post
* @return array $fields An array with all fields to edit
*/
public static function attachment_fields_to_edit($fields, $post) {
foreach(Property::$taxonomies as $media_taxonomy) {
$terms = get_the_terms($post, $media_taxonomy->name);
$terms_options = array();
if(is_array($terms) && !empty($terms)) {
foreach($terms as $term) {
$term_parent_ids = get_ancestors($term->term_id, $term->taxonomy, 'taxonomy');
$term_parents = [];
foreach($term_parent_ids as $term_parent) {
array_unshift($term_parents, get_term($term_parent)->name);
}
$terms_options[$term->slug] = [
'slug' => $term->slug,
'name' => $term->name,
'parents' => $term_parents,
'sort' => strtolower(!empty($term_parents) ? implode('-', $term_parents) . '-' . $term->name : $term->name)
];
}
uasort($terms_options, function($a, $b) {
return strnatcasecmp($a['sort'], $b['sort']);
});
}
$dropdown = '
<input
type="text"
id="attachments-' . $post->ID .'-' . $media_taxonomy->name . '"
name="attachments[' . $post->ID .'][' . $media_taxonomy->name . ']"
data-selected-items= "' . esc_attr(json_encode($terms_options)) . '"
value="' . implode(',', array_keys($terms_options)) . '"
/>
<script>
if(typeof f4MediaTaxonomySelectize !== "undefined" && typeof f4MediaTaxonomy !== "undefined") {
f4MediaTaxonomySelectize(\'#attachments-' . $post->ID .'-' . $media_taxonomy->name . '\', f4MediaTaxonomy.taxonomies[\'' . $media_taxonomy->name .'\']);
}
</script>
';
$fields[$media_taxonomy->name] = array(
'show_in_edit' => false,
'input' => 'html',
'html' => $dropdown,
'label' => $media_taxonomy->labels->name
);
}
return $fields;
}
/**
* Add inherit post status for attachment taxonomy term count
*
* @since 1.0.16
* @access public
* @static
* @param array $statuses List of post statuses to include in the count
* @param \WP_Taxonomy $taxonomy The current taxonomy object
* @return array $statuses List of post statuses to include in the count
*/
public static function update_post_term_count_statuses($statuses, $taxonomy) {
if(in_array('attachment', $taxonomy->object_type)) {
$statuses[] = 'inherit';
}
return $statuses;
}
/**
* Add new term
*
* @since 1.0.0
* @access public
* @static
*/
public static function ajax_add_term() {
$new_term = wp_insert_term($_REQUEST['term_label'], $_REQUEST['taxonomy']);
if(is_wp_error($new_term)) {
die();
}
$new_term_obj = null;
if(isset($new_term['term_id'])) {
$new_term_obj = get_term($new_term['term_id']);
}
if(!is_wp_error($new_term_obj)) {
wp_send_json(array(
'new_term' => $new_term_obj
));
}
die();
}
/**
* Search terms
*
* @since 1.1.0
* @access public
* @static
*/
public static function ajax_search_terms() {
$terms_raw = Helpers::get_terms_hierarchical(array(
'taxonomy' => $_REQUEST['taxonomy'],
'hide_empty' => false
));
$terms = [];
foreach($terms_raw as $term) {
if(strripos($term->name, trim($_REQUEST['query'])) !== false) {
$terms[] = [
'value' => $term->slug,
'text' => $term->name,
'parents' => $term->parents
];
}
}
wp_send_json_success($terms);
}
}
<?php
namespace F4\MT\Core;
/**
* Core properties
*
* All the properties for the Core module
*
* @since 1.0.0
* @package F4\MT\Core
*/
class Property {
public static $taxonomies = array();
public static $has_bulk_action = false;
public static $has_filter = false;
public static $has_assignment = false;
}
=== F4 Media Taxonomies ===
Contributors: faktorvier
Donate link: https://www.faktorvier.ch/donate/
Tags: media, attachments, library, filter, bulk action, categories, tags, taxonomies, custom taxonomies, attachment, category, tag, taxonomy, custom taxonomy
Requires at least: 4.5.0
Tested up to: 6.1
Stable tag: 1.1.3
License: GPLv2
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Add filters and bulk actions for attachment categories, tags and custom taxonomies.
== Description ==
[F4 Media Taxonomies](https://www.f4dev.ch) provides the ability to filter the media library by categories, tags and/or custom taxonomies.
You can use the built-in taxonomies (category or post_tag) or any custom taxonomy.
If a taxonomy is enabled for attachments, you can assign as many of their terms to an attachment as you need.
You can assign them directly in the media library or in every media-selector overlay.
There is also a nifty bulk function in the media library, which allows you to assign a single term to multiple attachments at once.
Attachments can then be filtered by these terms. The filters are available in the media library and in every media-selector overlay.
Different than other similar plugins, **F4 Media Taxonomies is 100% free!**
= Usage =
See FAQ for a guide how to enable categories, tags and custom taxonomies.
= Features overview =
* Use any taxonomy (built-in or custom)
* Assign one or more terms to an attachment in media library/overlay
* Bulk assign terms to multiple attachments at once in media library
* Filter attachments by terms in media library/overlay
* Easy to use
* Lightweight and optimized
* 100% free!
== Installation ==
1. Upload the plugin files to the `/wp-content/plugins/f4-media-taxonomies` directory, or install the plugin through the WordPress plugins screen directly
1. Activate the plugin through the 'Plugins' screen in WordPress
1. See FAQ for a guide how to enable categories, tags and custom taxonomies
1. All taxonomies that are assigned to the attachment post-type are automatically enabled
== Frequently Asked Questions ==
= How to enable categories =
The built-in taxonomy `category` can be enabled with this snippet. Just put it into your `functions.php`:
add_action('init', function() {
register_taxonomy_for_object_type('category', 'attachment');
});
= How to enable tags =
The built-in taxonomy `post_tag` can be enabled with this snippet. Just put it into your `functions.php`:
add_action('init', function() {
register_taxonomy_for_object_type('post_tag', 'attachment');
});
= How to enable custom taxonomies =
There are two ways to enable custom taxonomies for attachments:
**New taxonomy:**
If the taxonomy does not exist yet and you want to create a new one, you have to set the object_type in the `register_taxonomy()` function to `attachment` ([see WordPress codex](https://codex.wordpress.org/Function_Reference/register_taxonomy#Parameters)).
add_action('init', function() {
register_taxonomy(
'media-category',
'attachment'
);
});
**Existing taxonomy:**
If the taxonomy is already registered, you can assign it with this snippet. Just put it into your `functions.php` and change `media-category` to your taxonomy:
add_action('init', function() {
register_taxonomy_for_object_type('media-category', 'attachment');
});
= The filters do not appear in the media overlay =
For a better performance, we only include the scripts and files when they are needed. Some plugins can cause a problem with this functionality.
For this case we offer a hook, which allows you to enable the filter for special conditions. If this hook returns `true`, the filter is enabled for the current site.
add_filter('F4/MT/Core/has_filter', function() {
return true;
});
= Can I enable taxonomies directly in the backend? =
No. We simply use the taxonomies that are registered in the code. Maybe in the future, but we want to keep this plugin as lightweight and simple as possible.
= Is it really free? =
Yes, absolutely!
== Screenshots ==
1. Filter by taxonomies in media library list
2. Filter by taxonomies in media library grid
3. Assign one or more taxonomies to an attachment
4. Hierarchical dropdown menu for taxonomies assignment
5. Filter by taxonomies in media insert overlay
== Changelog ==
= 1.1.3 =
* Support WordPress 6.1
= 1.1.2 =
* Update www.f4dev.ch links
= 1.1.1 =
* Fix bulk action and taxonomy filter dropdowns
* Improve the grid view performance
= 1.1.0 =
* Terms are now lazy loaded with ajax in assignment select
* Term assignment styles and scripts optimized
* Term assignment sorting fixed
* Update selectize to verison 0.13.5
= 1.0.17 =
* Support WordPress 6.0
= 1.0.16 =
* Correctly update post term count (thanks to @nonverbla for the hint)
* Support WordPress 5.9
= 1.0.15 =
* Support WordPress 5.8
= 1.0.14 =
* Support WordPress 5.7
= 1.0.13 =
* Fix taxonomy select for new jQuery version
* Support WordPress 5.6
= 1.0.12 =
* Fix behaviour after taxonomy selection
= 1.0.11 =
* Support WordPress 5.5
= 1.0.10 =
* Support WordPress 5.4
= 1.0.9 =
* Fix bottom bulk action button in media list
= 1.0.8 =
* Add CMB2 plugin support
= 1.0.7 =
* WordPress 5.3 compatibility fixes
* Optimized dropdown width in media modal
= 1.0.6 =
* Update deprecated get_terms function
= 1.0.5 =
* Few PHP and JS code optimisations
= 1.0.4 =
* Fix customizer error
* Fix missing dropdowns in media overlay
= 1.0.3 =
* Fix filter error
= 1.0.2 =
* Show only taxonomies with show_ui true
= 1.0.1 =
* Version upgrade for correct repository infos
= 1.0.0 =
* Initial stable release