Plugin Directory

Changeset 2431741


Ignore:
Timestamp:
12/04/2020 05:45:12 PM (5 years ago)
Author:
theMikeD
Message:

Improved logic around parent-child terms, bug fixes, WPML support, tested and reviewed refactoring.

Location:
term-management-tools
Files:
24 added
2 deleted
4 edited
3 copied

Legend:

Unmodified
Added
Removed
  • term-management-tools/tags/2.0.0/readme.txt

    r2427873 r2431741  
    11=== Term Management Tools ===
    2 Contributors: scribu 
    3 Tags: admin, category, tag, term, taxonomy, hierarchy, organize, manage 
    4 Requires at least: 3.2 
    5 Tested up to: 4.3 
    6 Stable tag: 1.1.4 
    7 License: GPLv2 or later 
     2Contributors: theMikeD, scribu
     3Tags: admin, category, tag, term, taxonomy, hierarchy, organize, manage, merge, change, parent, child
     4Requires at least: 4.2
     5Tested up to: 5.6
     6Stable tag: 2.0.0
     7License: GPLv2 or later
    88License URI: http://www.gnu.org/licenses/gpl-2.0.html
     9Requires PHP: 7.1
    910
    10 Allows you to merge terms, set term parents in bulk, and swap term taxonomies.
     11Allows you to merge terms, move terms between taxonomies, and set term parents, individually or in bulk. WPML is supported when changing taxonomies.
    1112
    1213== Description ==
    1314
    14 If you need to reorganize your tags and categories, this plugin will make it easier for you. It adds two new options to the Bulk Actions dropdown on term management pages:
     15_Please note this plugin requires at least PHP 7.1._
     16
     17If you need to reorganize your tags and categories, this plugin will make it easier for you. It adds three new options to the Bulk Actions dropdown on term management pages:
    1518
    1619* Merge - combine two or more terms into one
    17 * Set parent - set the parent for one or more terms (for hierarchical taxonomies)
    18 * Change taxonomy - convert terms from one taxonomy to another
     20* Set Parent - set the parent for one or more terms (for hierarchical taxonomies)
     21* Change Taxonomy - convert terms from one taxonomy to another
    1922
    2023It works with tags, categories and [custom taxonomies](http://codex.wordpress.org/Custom_Taxonomies).
    2124
    22 = Usage =
     25== Usage ==
    2326
    24 1. Go to `WP-Admin -> Posts -> Categories`.
    25 2. Find the Bulk Actions dropdown.
    26 3. Reorganize away.
     271. Go to the taxonomy page containing terms you want to modify. For example, for categories go to `WP-Admin → Posts → Categories`.
     282. Select the terms you want to reorganize
     293. Find the Bulk Actions dropdown, and select the task you'd like done.
     304. Disco.
    2731
    28 = No support =
     32== WPML ==
     33[WPML](https://wpml.org)-translated terms are partially supported. Currently only the "Change Taxonomy" task is WPML-aware. If a term with translations is moved to a new taxonomy, its translations are moved as well, and the translation relationships are preserved.
    2934
    30 I, scribu, will not be offering support for this plugin anymore (either free or paid).
     35> Currently only the "Change Taxonomy" task is WPML-aware
    3136
    32 Fixes are submitted by other contributors, on [Github](https://github.com/scribu/wp-term-management-tools).
     37Work on the WPML component was sponsored by the [Rainforest Alliance](https://www.rainforest-alliance.org/).
     38
     39== Support ==
     40Limited support is handled in the forum created for this purpose (see the [support](https://wordpress.org/support/plugin/term-management-tools/) tab on wp.org).
     41
     42Find a problem? Fixes can be submitted on [Github](https://github.com/theMikeD/wp-term-management-tools).
    3343
    3444== Installation ==
    3545
    36 You can either install it automatically from the WordPress admin, or do it manually:
     46Either use the WordPress Plugin Installer (Dashboard → Plugins → Add New, then search for "term management tools"), or manually as follows:
    3747
    38 1. Unzip the "term-management-tools" archive and put the folder into your plugins folder (/wp-content/plugins/).
    39 1. Activate the plugin from the Plugins menu.
     481. Upload the entire `wp-term-management-tools` folder to your `/wp-content/plugins/` directory
     491. DO NOT change the name of the `wp-term-management-tools` folder
     501. Activate the plugin through the 'Plugins' menu in the WordPress Dashboard
     51
     52Note for WordPress Multisite users:
     53
     54* Install the plugin in your `/plugins/` directory (do not install in the `/mu-plugins/` directory).
     55* In order for this plugin to be visible to Site Admins, the plugin has to be activated for each blog by the Network Admin.
     56
     57== Upgrading from a previous version ==
     58
     59Use the upgrade link in the Dashboard (Dashboard → Updates) to upgrade this plugin.
     60
     61== Notes ==
     62Initial version of this plugin was by [scribu](http://scribu.net/), with contributions from others. See full code history on [Github](https://github.com/theMikeD/wp-term-management-tools).
    4063
    4164== Screenshots ==
    4265
    43 1. Merge
    44 2. Set parent
     661. Set Parent option. In this case, the term "New EN" will be set as a child of "Parent One EN"
     672. Merge option. Here, the two selected terms will be merged into a new term named "Merged." In addition, because both source terms share the same parent term ("Parent One EN"), the new term will also have "Parent One EN" as its parent term.
     683. Change Taxonomy option. Here, the "Parent One EN" category will be sent to the custom taxonomy "Hierarchical" (which I added for the sake of testing). A few other things to note here. First, the two child terms will also be moved and, because the target taxonomy is also hierarchical the parent-child relationships will be preserved. Second, if there are any WPML translations of these terms, they will also be moved and the translations maintained.
    4569
    4670== Changelog ==
     71
     72= 2.0.0 =
     73* under new management by @theMikeD :)
     74* full code refactoring
     75* inline documentation
     76* [user documentation](https://www.codenamemiked.com/plugins/term-management-tools)
     77* clean phpcs using Wordpress-Extra
     78* unit/integration tests, all of which pass
     79* term cache clearing now actually works
     80* for the taxonomy change option, only public taxonomies are listed
     81* for the taxonomy change option, WPML-translated terms are also moved
     82* for the term merge option, if all terms to be merged have the same parent term, the merged term will also have that parent term.
     83* for the term parent option, if one of the supplied terms is also the term selected to be the parent, no terms are adjusted.
     84* new filter term_management_tools_changed_taxonomy__terms_as_supplied
     85* new filter term_management_tools_changed_taxonomy__terms_and_child_terms
     86* new filter term_management_tools_changed_taxonomy__reset_parent_for
    4787
    4888= 1.1.4 =
     
    69109* [more info](http://scribu.net/wordpress/term-management-tools/tmt-1-0.html)
    70110
     111== Upgrade Notice ==
     112
     113= 2.0.0 =
     114Improved logic around parent-child terms, bug fixes, WPML support, tested and reviewed refactoring.
  • term-management-tools/tags/2.0.0/term-management-tools.php

    r2427873 r2431741  
    22/*
    33Plugin Name: Term Management Tools
    4 Version: 1.1.4
    5 Description: Allows you to merge terms and set term parents in bulk
    6 Author: scribu
    7 Author URI: http://scribu.net/
    8 Plugin URI: http://scribu.net/wordpress/term-management-tools
     4Version: 2.0.0
     5Description: Allows you to merge terms, move terms between taxonomies, and set term parents, individually or in bulk. The "Change Taxonomy" option supports WPML-translated terms.
     6Author: theMikeD, scribu
     7Author URI: https://www.codenamemiked.com
     8Plugin URI: https://www.codenamemiked.com/plugins/term-management-tools/
    99Text Domain: term-management-tools
    1010Domain Path: /lang
     11Requires PHP: 7.1
    1112*/
    1213
    13 class Term_Management_Tools {
     14define( 'CNMD_TMT_PLUGIN_URL_RELATIVE', basename( dirname( __FILE__ ) ) );
     15define( 'CNMD_TMT_URL', plugin_dir_url( __FILE__ ) );
    1416
    15     static function init() {
    16         add_action( 'load-edit-tags.php', array( __CLASS__, 'handler' ) );
    17         add_action( 'admin_notices', array( __CLASS__, 'notice' ) );
     17/**
     18 * The class autoloader.
     19 */
     20spl_autoload_register(
     21    function( $class ) {
    1822
    19         load_plugin_textdomain( 'term-management-tools', '', basename( dirname( __FILE__ ) ) . '/lang' );
    20     }
    21 
    22     private static function get_actions( $taxonomy ) {
    23         $actions = array(
    24             'merge'        => __( 'Merge', 'term-management-tools' ),
    25             'change_tax'   => __( 'Change taxonomy', 'term-management-tools' ),
    26         );
    27 
    28         if ( is_taxonomy_hierarchical( $taxonomy ) ) {
    29             $actions = array_merge( array(
    30                 'set_parent' => __( 'Set parent', 'term-management-tools' ),
    31             ), $actions );
     23        // We only care about CNMD-namespaced classes
     24        if ( ! preg_match( '/^CNMD\\\TMT/', $class ) ) {
     25            return;
    3226        }
    3327
    34         return $actions;
    35     }
    36 
    37     static function handler() {
    38         $defaults = array(
    39             'taxonomy' => 'post_tag',
    40             'delete_tags' => false,
    41             'action' => false,
    42             'action2' => false
    43         );
    44 
    45         $data = shortcode_atts( $defaults, $_REQUEST );
    46 
    47         $tax = get_taxonomy( $data['taxonomy'] );
    48         if ( !$tax )
     28        $filepath = str_replace( '\\', DIRECTORY_SEPARATOR, $class ) . '.php';
     29        $filename = plugin_dir_path( __FILE__ ) . '/classes/class-' . basename( $filepath );
     30        if ( file_exists( $filename ) ) {
     31            include_once $filename;
    4932            return;
    50 
    51         if ( !current_user_can( $tax->cap->manage_terms ) )
    52             return;
    53 
    54         add_action( 'admin_enqueue_scripts', array( __CLASS__, 'script' ) );
    55         add_action( 'admin_footer', array( __CLASS__, 'inputs' ) );
    56 
    57         $action = false;
    58         foreach ( array( 'action', 'action2' ) as $key ) {
    59             if ( $data[ $key ] && '-1' != $data[ $key ] ) {
    60                 $action = $data[ $key ];
    61             }
    62         }
    63 
    64         if ( !$action )
    65             return;
    66 
    67         self::delegate_handling( $action, $data['taxonomy'], $data['delete_tags'] );
    68     }
    69 
    70     protected static function delegate_handling( $action, $taxonomy, $term_ids ) {
    71         if ( empty( $term_ids ) )
    72             return;
    73 
    74         foreach ( array_keys( self::get_actions( $taxonomy ) ) as $key ) {
    75             if ( 'bulk_' . $key == $action ) {
    76                 check_admin_referer( 'bulk-tags' );
    77                 $r = call_user_func( array( __CLASS__, 'handle_' . $key ), $term_ids, $taxonomy );
    78                 break;
    79             }
    80         }
    81 
    82         if ( !isset( $r ) )
    83             return;
    84 
    85         $referer = wp_get_referer();
    86         if ( $referer && false !== strpos( $referer, 'edit-tags.php' ) ) {
    87             $location = $referer;
    88         } else {
    89             $location = add_query_arg( 'taxonomy', $taxonomy, 'edit-tags.php' );
    90         }
    91 
    92         if ( isset( $_REQUEST['post_type'] ) && 'post' != $_REQUEST['post_type'] ) {
    93             $location = add_query_arg( 'post_type', $_REQUEST['post_type'], $location );
    94         }
    95 
    96         wp_redirect( add_query_arg( 'message', $r ? 'tmt-updated' : 'tmt-error', $location ) );
    97         die;
    98     }
    99 
    100     static function notice() {
    101         if ( !isset( $_GET['message'] ) )
    102             return;
    103 
    104         switch ( $_GET['message'] ) {
    105         case  'tmt-updated':
    106             echo '<div id="message" class="updated"><p>' . __( 'Terms updated.', 'term-management-tools' ) . '</p></div>';
    107             break;
    108 
    109         case 'tmt-error':
    110             echo '<div id="message" class="error"><p>' . __( 'Terms not updated.', 'term-management-tools' ) . '</p></div>';
    111             break;
    11233        }
    11334    }
     35);
    11436
    115     static function handle_merge( $term_ids, $taxonomy ) {
    116         $term_name = $_REQUEST['bulk_to_tag'];
    11737
    118         if ( !$term = term_exists( $term_name, $taxonomy ) )
    119             $term = wp_insert_term( $term_name, $taxonomy );
    120 
    121         if ( is_wp_error( $term ) )
    122             return false;
    123 
    124         $to_term = $term['term_id'];
    125 
    126         $to_term_obj = get_term( $to_term, $taxonomy );
    127 
    128         foreach ( $term_ids as $term_id ) {
    129             if ( $term_id == $to_term )
    130                 continue;
    131 
    132             $old_term = get_term( $term_id, $taxonomy );
    133 
    134             $ret = wp_delete_term( $term_id, $taxonomy, array( 'default' => $to_term, 'force_default' => true ) );
    135             if ( is_wp_error( $ret ) ) {
    136                 continue;
    137             }
    138 
    139             do_action( 'term_management_tools_term_merged', $to_term_obj, $old_term );
    140         }
    141 
    142         return true;
    143     }
    144 
    145     static function handle_set_parent( $term_ids, $taxonomy ) {
    146         $parent_id = $_REQUEST['parent'];
    147 
    148         foreach ( $term_ids as $term_id ) {
    149             if ( $term_id == $parent_id )
    150                 continue;
    151 
    152             $ret = wp_update_term( $term_id, $taxonomy, array( 'parent' => $parent_id ) );
    153 
    154             if ( is_wp_error( $ret ) )
    155                 return false;
    156         }
    157 
    158         return true;
    159     }
    160 
    161     static function handle_change_tax( $term_ids, $taxonomy ) {
    162         global $wpdb;
    163 
    164         $new_tax = $_POST['new_tax'];
    165 
    166         if ( !taxonomy_exists( $new_tax ) )
    167             return false;
    168 
    169         if ( $new_tax == $taxonomy )
    170             return false;
    171 
    172         $tt_ids = array();
    173         foreach ( $term_ids as $term_id ) {
    174             $term = get_term( $term_id, $taxonomy );
    175 
    176             if ( $term->parent && !in_array( $term->parent,$term_ids ) ) {
    177                 $wpdb->update( $wpdb->term_taxonomy,
    178                     array( 'parent' => 0 ),
    179                     array( 'term_taxonomy_id' => $term->term_taxonomy_id )
    180                 );
    181             }
    182 
    183             $tt_ids[] = $term->term_taxonomy_id;
    184 
    185             if ( is_taxonomy_hierarchical( $taxonomy ) ) {
    186                 $child_terms = get_terms( $taxonomy, array(
    187                     'child_of' => $term_id,
    188                     'hide_empty' => false
    189                 ) );
    190                 $tt_ids = array_merge( $tt_ids, wp_list_pluck( $child_terms, 'term_taxonomy_id' ) );
    191             }
    192         }
    193         $tt_ids = implode( ',', array_map( 'absint', $tt_ids ) );
    194 
    195         $wpdb->query( $wpdb->prepare( "
    196             UPDATE $wpdb->term_taxonomy SET taxonomy = %s WHERE term_taxonomy_id IN ($tt_ids)
    197         ", $new_tax ) );
    198 
    199         if ( is_taxonomy_hierarchical( $taxonomy ) && !is_taxonomy_hierarchical( $new_tax ) ) {
    200             $wpdb->query( "UPDATE $wpdb->term_taxonomy SET parent = 0 WHERE term_taxonomy_id IN ($tt_ids)" );
    201         }
    202 
    203         clean_term_cache( $tt_ids, $taxonomy );
    204         clean_term_cache( $tt_ids, $new_tax );
    205 
    206         do_action( 'term_management_tools_term_changed_taxonomy', $tt_ids, $new_tax, $taxonomy );
    207 
    208         return true;
    209     }
    210 
    211     static function script() {
    212         global $taxonomy;
    213 
    214         $js_dev = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '.dev' : '';
    215 
    216         wp_enqueue_script( 'term-management-tools', plugins_url( "script$js_dev.js", __FILE__ ), array( 'jquery' ), '1.1' );
    217 
    218         wp_localize_script( 'term-management-tools', 'tmtL10n', self::get_actions( $taxonomy ) );
    219     }
    220 
    221     static function inputs() {
    222         global $taxonomy;
    223 
    224         foreach ( array_keys( self::get_actions( $taxonomy ) ) as $key ) {
    225             echo "<div id='tmt-input-$key' style='display:none'>\n";
    226             call_user_func( array( __CLASS__, 'input_' . $key ), $taxonomy );
    227             echo "</div>\n";
    228         }
    229     }
    230 
    231     static function input_merge( $taxonomy ) {
    232         printf( __( 'into: %s', 'term-management-tools' ), '<input name="bulk_to_tag" type="text" size="20"></input>' );
    233     }
    234 
    235     static function input_change_tax( $taxonomy ) {
    236         $tax_list = get_taxonomies( array( 'show_ui' => true ), 'objects' );
    237 ?>
    238         <select class="postform" name="new_tax">
    239 <?php
    240         foreach ( $tax_list as $new_tax => $tax_obj ) {
    241             if ( $new_tax == $taxonomy )
    242                 continue;
    243 
    244             echo "<option value='$new_tax'>$tax_obj->label</option>\n";
    245         }
    246 ?>
    247         </select>
    248 <?php
    249     }
    250 
    251     static function input_set_parent( $taxonomy ) {
    252         wp_dropdown_categories( array(
    253             'hide_empty' => 0,
    254             'hide_if_empty' => false,
    255             'name' => 'parent',
    256             'orderby' => 'name',
    257             'taxonomy' => $taxonomy,
    258             'hierarchical' => true,
    259             'show_option_none' => __( 'None', 'term-management-tools' )
    260         ) );
    261     }
     38/**
     39 * Initialize the plugin.
     40 */
     41function init_term_management_tools() {
     42    $tmt = new \CNMD\TMT\TermManagementTools();
     43    $tmt->init();
    26244}
    263 
    264 Term_Management_Tools::init();
    265 
     45init_term_management_tools();
  • term-management-tools/trunk/readme.txt

    r1287838 r2431741  
    11=== Term Management Tools ===
    2 Contributors: scribu 
    3 Tags: admin, category, tag, term, taxonomy, hierarchy, organize, manage 
    4 Requires at least: 3.2 
    5 Tested up to: 4.3 
    6 Stable tag: 1.1.4 
    7 License: GPLv2 or later 
     2Contributors: theMikeD, scribu
     3Tags: admin, category, tag, term, taxonomy, hierarchy, organize, manage, merge, change, parent, child
     4Requires at least: 4.2
     5Tested up to: 5.6
     6Stable tag: 2.0.0
     7License: GPLv2 or later
    88License URI: http://www.gnu.org/licenses/gpl-2.0.html
     9Requires PHP: 7.1
    910
    10 Allows you to merge terms, set term parents in bulk, and swap term taxonomies.
     11Allows you to merge terms, move terms between taxonomies, and set term parents, individually or in bulk. WPML is supported when changing taxonomies.
    1112
    1213== Description ==
    1314
    14 If you need to reorganize your tags and categories, this plugin will make it easier for you. It adds two new options to the Bulk Actions dropdown on term management pages:
     15_Please note this plugin requires at least PHP 7.1._
     16
     17If you need to reorganize your tags and categories, this plugin will make it easier for you. It adds three new options to the Bulk Actions dropdown on term management pages:
    1518
    1619* Merge - combine two or more terms into one
    17 * Set parent - set the parent for one or more terms (for hierarchical taxonomies)
    18 * Change taxonomy - convert terms from one taxonomy to another
     20* Set Parent - set the parent for one or more terms (for hierarchical taxonomies)
     21* Change Taxonomy - convert terms from one taxonomy to another
    1922
    2023It works with tags, categories and [custom taxonomies](http://codex.wordpress.org/Custom_Taxonomies).
    2124
    22 = Usage =
     25== Usage ==
    2326
    24 1. Go to `WP-Admin -> Posts -> Categories`.
    25 2. Find the Bulk Actions dropdown.
    26 3. Reorganize away.
     271. Go to the taxonomy page containing terms you want to modify. For example, for categories go to `WP-Admin → Posts → Categories`.
     282. Select the terms you want to reorganize
     293. Find the Bulk Actions dropdown, and select the task you'd like done.
     304. Disco.
    2731
    28 = No support =
     32== WPML ==
     33[WPML](https://wpml.org)-translated terms are partially supported. Currently only the "Change Taxonomy" task is WPML-aware. If a term with translations is moved to a new taxonomy, its translations are moved as well, and the translation relationships are preserved.
    2934
    30 I, scribu, will not be offering support for this plugin anymore (either free or paid).
     35> Currently only the "Change Taxonomy" task is WPML-aware
    3136
    32 Fixes are submitted by other contributors, on [Github](https://github.com/scribu/wp-term-management-tools).
     37Work on the WPML component was sponsored by the [Rainforest Alliance](https://www.rainforest-alliance.org/).
     38
     39== Support ==
     40Limited support is handled in the forum created for this purpose (see the [support](https://wordpress.org/support/plugin/term-management-tools/) tab on wp.org).
     41
     42Find a problem? Fixes can be submitted on [Github](https://github.com/theMikeD/wp-term-management-tools).
    3343
    3444== Installation ==
    3545
    36 You can either install it automatically from the WordPress admin, or do it manually:
     46Either use the WordPress Plugin Installer (Dashboard → Plugins → Add New, then search for "term management tools"), or manually as follows:
    3747
    38 1. Unzip the "term-management-tools" archive and put the folder into your plugins folder (/wp-content/plugins/).
    39 1. Activate the plugin from the Plugins menu.
     481. Upload the entire `wp-term-management-tools` folder to your `/wp-content/plugins/` directory
     491. DO NOT change the name of the `wp-term-management-tools` folder
     501. Activate the plugin through the 'Plugins' menu in the WordPress Dashboard
     51
     52Note for WordPress Multisite users:
     53
     54* Install the plugin in your `/plugins/` directory (do not install in the `/mu-plugins/` directory).
     55* In order for this plugin to be visible to Site Admins, the plugin has to be activated for each blog by the Network Admin.
     56
     57== Upgrading from a previous version ==
     58
     59Use the upgrade link in the Dashboard (Dashboard → Updates) to upgrade this plugin.
     60
     61== Notes ==
     62Initial version of this plugin was by [scribu](http://scribu.net/), with contributions from others. See full code history on [Github](https://github.com/theMikeD/wp-term-management-tools).
    4063
    4164== Screenshots ==
    4265
    43 1. Merge
    44 2. Set parent
     661. Set Parent option. In this case, the term "New EN" will be set as a child of "Parent One EN"
     672. Merge option. Here, the two selected terms will be merged into a new term named "Merged." In addition, because both source terms share the same parent term ("Parent One EN"), the new term will also have "Parent One EN" as its parent term.
     683. Change Taxonomy option. Here, the "Parent One EN" category will be sent to the custom taxonomy "Hierarchical" (which I added for the sake of testing). A few other things to note here. First, the two child terms will also be moved and, because the target taxonomy is also hierarchical the parent-child relationships will be preserved. Second, if there are any WPML translations of these terms, they will also be moved and the translations maintained.
    4569
    4670== Changelog ==
     71
     72= 2.0.0 =
     73* under new management by @theMikeD :)
     74* full code refactoring
     75* inline documentation
     76* [user documentation](https://www.codenamemiked.com/plugins/term-management-tools)
     77* clean phpcs using Wordpress-Extra
     78* unit/integration tests, all of which pass
     79* term cache clearing now actually works
     80* for the taxonomy change option, only public taxonomies are listed
     81* for the taxonomy change option, WPML-translated terms are also moved
     82* for the term merge option, if all terms to be merged have the same parent term, the merged term will also have that parent term.
     83* for the term parent option, if one of the supplied terms is also the term selected to be the parent, no terms are adjusted.
     84* new filter term_management_tools_changed_taxonomy__terms_as_supplied
     85* new filter term_management_tools_changed_taxonomy__terms_and_child_terms
     86* new filter term_management_tools_changed_taxonomy__reset_parent_for
    4787
    4888= 1.1.4 =
     
    69109* [more info](http://scribu.net/wordpress/term-management-tools/tmt-1-0.html)
    70110
     111== Upgrade Notice ==
     112
     113= 2.0.0 =
     114Improved logic around parent-child terms, bug fixes, WPML support, tested and reviewed refactoring.
  • term-management-tools/trunk/term-management-tools.php

    r1287821 r2431741  
    22/*
    33Plugin Name: Term Management Tools
    4 Version: 1.1.4
    5 Description: Allows you to merge terms and set term parents in bulk
    6 Author: scribu
    7 Author URI: http://scribu.net/
    8 Plugin URI: http://scribu.net/wordpress/term-management-tools
     4Version: 2.0.0
     5Description: Allows you to merge terms, move terms between taxonomies, and set term parents, individually or in bulk. The "Change Taxonomy" option supports WPML-translated terms.
     6Author: theMikeD, scribu
     7Author URI: https://www.codenamemiked.com
     8Plugin URI: https://www.codenamemiked.com/plugins/term-management-tools/
    99Text Domain: term-management-tools
    1010Domain Path: /lang
     11Requires PHP: 7.1
    1112*/
    1213
    13 class Term_Management_Tools {
     14define( 'CNMD_TMT_PLUGIN_URL_RELATIVE', basename( dirname( __FILE__ ) ) );
     15define( 'CNMD_TMT_URL', plugin_dir_url( __FILE__ ) );
    1416
    15     static function init() {
    16         add_action( 'load-edit-tags.php', array( __CLASS__, 'handler' ) );
    17         add_action( 'admin_notices', array( __CLASS__, 'notice' ) );
     17/**
     18 * The class autoloader.
     19 */
     20spl_autoload_register(
     21    function( $class ) {
    1822
    19         load_plugin_textdomain( 'term-management-tools', '', basename( dirname( __FILE__ ) ) . '/lang' );
    20     }
    21 
    22     private static function get_actions( $taxonomy ) {
    23         $actions = array(
    24             'merge'        => __( 'Merge', 'term-management-tools' ),
    25             'change_tax'   => __( 'Change taxonomy', 'term-management-tools' ),
    26         );
    27 
    28         if ( is_taxonomy_hierarchical( $taxonomy ) ) {
    29             $actions = array_merge( array(
    30                 'set_parent' => __( 'Set parent', 'term-management-tools' ),
    31             ), $actions );
     23        // We only care about CNMD-namespaced classes
     24        if ( ! preg_match( '/^CNMD\\\TMT/', $class ) ) {
     25            return;
    3226        }
    3327
    34         return $actions;
    35     }
    36 
    37     static function handler() {
    38         $defaults = array(
    39             'taxonomy' => 'post_tag',
    40             'delete_tags' => false,
    41             'action' => false,
    42             'action2' => false
    43         );
    44 
    45         $data = shortcode_atts( $defaults, $_REQUEST );
    46 
    47         $tax = get_taxonomy( $data['taxonomy'] );
    48         if ( !$tax )
     28        $filepath = str_replace( '\\', DIRECTORY_SEPARATOR, $class ) . '.php';
     29        $filename = plugin_dir_path( __FILE__ ) . '/classes/class-' . basename( $filepath );
     30        if ( file_exists( $filename ) ) {
     31            include_once $filename;
    4932            return;
    50 
    51         if ( !current_user_can( $tax->cap->manage_terms ) )
    52             return;
    53 
    54         add_action( 'admin_enqueue_scripts', array( __CLASS__, 'script' ) );
    55         add_action( 'admin_footer', array( __CLASS__, 'inputs' ) );
    56 
    57         $action = false;
    58         foreach ( array( 'action', 'action2' ) as $key ) {
    59             if ( $data[ $key ] && '-1' != $data[ $key ] ) {
    60                 $action = $data[ $key ];
    61             }
    62         }
    63 
    64         if ( !$action )
    65             return;
    66 
    67         self::delegate_handling( $action, $data['taxonomy'], $data['delete_tags'] );
    68     }
    69 
    70     protected static function delegate_handling( $action, $taxonomy, $term_ids ) {
    71         if ( empty( $term_ids ) )
    72             return;
    73 
    74         foreach ( array_keys( self::get_actions( $taxonomy ) ) as $key ) {
    75             if ( 'bulk_' . $key == $action ) {
    76                 check_admin_referer( 'bulk-tags' );
    77                 $r = call_user_func( array( __CLASS__, 'handle_' . $key ), $term_ids, $taxonomy );
    78                 break;
    79             }
    80         }
    81 
    82         if ( !isset( $r ) )
    83             return;
    84 
    85         $referer = wp_get_referer();
    86         if ( $referer && false !== strpos( $referer, 'edit-tags.php' ) ) {
    87             $location = $referer;
    88         } else {
    89             $location = add_query_arg( 'taxonomy', $taxonomy, 'edit-tags.php' );
    90         }
    91 
    92         if ( isset( $_REQUEST['post_type'] ) && 'post' != $_REQUEST['post_type'] ) {
    93             $location = add_query_arg( 'post_type', $_REQUEST['post_type'], $location );
    94         }
    95 
    96         wp_redirect( add_query_arg( 'message', $r ? 'tmt-updated' : 'tmt-error', $location ) );
    97         die;
    98     }
    99 
    100     static function notice() {
    101         if ( !isset( $_GET['message'] ) )
    102             return;
    103 
    104         switch ( $_GET['message'] ) {
    105         case  'tmt-updated':
    106             echo '<div id="message" class="updated"><p>' . __( 'Terms updated.', 'term-management-tools' ) . '</p></div>';
    107             break;
    108 
    109         case 'tmt-error':
    110             echo '<div id="message" class="error"><p>' . __( 'Terms not updated.', 'term-management-tools' ) . '</p></div>';
    111             break;
    11233        }
    11334    }
     35);
    11436
    115     static function handle_merge( $term_ids, $taxonomy ) {
    116         $term_name = $_REQUEST['bulk_to_tag'];
    11737
    118         if ( !$term = term_exists( $term_name, $taxonomy ) )
    119             $term = wp_insert_term( $term_name, $taxonomy );
    120 
    121         if ( is_wp_error( $term ) )
    122             return false;
    123 
    124         $to_term = $term['term_id'];
    125 
    126         $to_term_obj = get_term( $to_term, $taxonomy );
    127 
    128         foreach ( $term_ids as $term_id ) {
    129             if ( $term_id == $to_term )
    130                 continue;
    131 
    132             $old_term = get_term( $term_id, $taxonomy );
    133 
    134             $ret = wp_delete_term( $term_id, $taxonomy, array( 'default' => $to_term, 'force_default' => true ) );
    135             if ( is_wp_error( $ret ) ) {
    136                 continue;
    137             }
    138 
    139             do_action( 'term_management_tools_term_merged', $to_term_obj, $old_term );
    140         }
    141 
    142         return true;
    143     }
    144 
    145     static function handle_set_parent( $term_ids, $taxonomy ) {
    146         $parent_id = $_REQUEST['parent'];
    147 
    148         foreach ( $term_ids as $term_id ) {
    149             if ( $term_id == $parent_id )
    150                 continue;
    151 
    152             $ret = wp_update_term( $term_id, $taxonomy, array( 'parent' => $parent_id ) );
    153 
    154             if ( is_wp_error( $ret ) )
    155                 return false;
    156         }
    157 
    158         return true;
    159     }
    160 
    161     static function handle_change_tax( $term_ids, $taxonomy ) {
    162         global $wpdb;
    163 
    164         $new_tax = $_POST['new_tax'];
    165 
    166         if ( !taxonomy_exists( $new_tax ) )
    167             return false;
    168 
    169         if ( $new_tax == $taxonomy )
    170             return false;
    171 
    172         $tt_ids = array();
    173         foreach ( $term_ids as $term_id ) {
    174             $term = get_term( $term_id, $taxonomy );
    175 
    176             if ( $term->parent && !in_array( $term->parent,$term_ids ) ) {
    177                 $wpdb->update( $wpdb->term_taxonomy,
    178                     array( 'parent' => 0 ),
    179                     array( 'term_taxonomy_id' => $term->term_taxonomy_id )
    180                 );
    181             }
    182 
    183             $tt_ids[] = $term->term_taxonomy_id;
    184 
    185             if ( is_taxonomy_hierarchical( $taxonomy ) ) {
    186                 $child_terms = get_terms( $taxonomy, array(
    187                     'child_of' => $term_id,
    188                     'hide_empty' => false
    189                 ) );
    190                 $tt_ids = array_merge( $tt_ids, wp_list_pluck( $child_terms, 'term_taxonomy_id' ) );
    191             }
    192         }
    193         $tt_ids = implode( ',', array_map( 'absint', $tt_ids ) );
    194 
    195         $wpdb->query( $wpdb->prepare( "
    196             UPDATE $wpdb->term_taxonomy SET taxonomy = %s WHERE term_taxonomy_id IN ($tt_ids)
    197         ", $new_tax ) );
    198 
    199         if ( is_taxonomy_hierarchical( $taxonomy ) && !is_taxonomy_hierarchical( $new_tax ) ) {
    200             $wpdb->query( "UPDATE $wpdb->term_taxonomy SET parent = 0 WHERE term_taxonomy_id IN ($tt_ids)" );
    201         }
    202 
    203         clean_term_cache( $tt_ids, $taxonomy );
    204         clean_term_cache( $tt_ids, $new_tax );
    205 
    206         do_action( 'term_management_tools_term_changed_taxonomy', $tt_ids, $new_tax, $taxonomy );
    207 
    208         return true;
    209     }
    210 
    211     static function script() {
    212         global $taxonomy;
    213 
    214         $js_dev = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '.dev' : '';
    215 
    216         wp_enqueue_script( 'term-management-tools', plugins_url( "script$js_dev.js", __FILE__ ), array( 'jquery' ), '1.1' );
    217 
    218         wp_localize_script( 'term-management-tools', 'tmtL10n', self::get_actions( $taxonomy ) );
    219     }
    220 
    221     static function inputs() {
    222         global $taxonomy;
    223 
    224         foreach ( array_keys( self::get_actions( $taxonomy ) ) as $key ) {
    225             echo "<div id='tmt-input-$key' style='display:none'>\n";
    226             call_user_func( array( __CLASS__, 'input_' . $key ), $taxonomy );
    227             echo "</div>\n";
    228         }
    229     }
    230 
    231     static function input_merge( $taxonomy ) {
    232         printf( __( 'into: %s', 'term-management-tools' ), '<input name="bulk_to_tag" type="text" size="20"></input>' );
    233     }
    234 
    235     static function input_change_tax( $taxonomy ) {
    236         $tax_list = get_taxonomies( array( 'show_ui' => true ), 'objects' );
    237 ?>
    238         <select class="postform" name="new_tax">
    239 <?php
    240         foreach ( $tax_list as $new_tax => $tax_obj ) {
    241             if ( $new_tax == $taxonomy )
    242                 continue;
    243 
    244             echo "<option value='$new_tax'>$tax_obj->label</option>\n";
    245         }
    246 ?>
    247         </select>
    248 <?php
    249     }
    250 
    251     static function input_set_parent( $taxonomy ) {
    252         wp_dropdown_categories( array(
    253             'hide_empty' => 0,
    254             'hide_if_empty' => false,
    255             'name' => 'parent',
    256             'orderby' => 'name',
    257             'taxonomy' => $taxonomy,
    258             'hierarchical' => true,
    259             'show_option_none' => __( 'None', 'term-management-tools' )
    260         ) );
    261     }
     38/**
     39 * Initialize the plugin.
     40 */
     41function init_term_management_tools() {
     42    $tmt = new \CNMD\TMT\TermManagementTools();
     43    $tmt->init();
    26244}
    263 
    264 Term_Management_Tools::init();
    265 
     45init_term_management_tools();
Note: See TracChangeset for help on using the changeset viewer.