diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 9414d4e..0000000 --- a/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -.idea -.git -.DS_Store* diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index b20b93d..0000000 --- a/.travis.yml +++ /dev/null @@ -1,4 +0,0 @@ -language: php -php: - - 5.5 - - 5.4 diff --git a/README.rst b/README.rst index f8a43fa..8b54bde 100644 --- a/README.rst +++ b/README.rst @@ -1,11 +1,8 @@ ====== User Tags ====== -Tags: taxonomy, user taxonomy, user tags -Tested up to: 3.9.1 -Stable tag: trunk -Allows creating and managing User Taxonomies from Backend +Allows creating and managing User Taxonomy from WordPress admin. Description ====== @@ -17,15 +14,15 @@ Ref: [Justin Tadlock](http://justintadlock.com/archives/2011/10/20/custom-user-t Installation ====== -1. Upload the `wp-user-taxonomies` folder to the `/wp-content/plugins/` directory +1. Upload the `user-tags` folder to the `/wp-content/plugins/` directory 2. Activate the plugin through the 'Plugins' menu in WordPress -3. Go to Taxonomies under Users option to create taxonomies for User +3. Go to Taxonomy under Users option to create taxonomy for User Filters Available ====== 1. 'ut_template_heading' => Can be used to modify Template Page Heading -2. 'ut_tepmplate_content' => Can be used to modify users list style, +2. 'ut_template_content' => Can be used to modify users list style, args => 1 , $users => List of Users 3. 'ut_template_content_empty' => Display custom message, if there are no users for term 4. 'ut_tag_cloud_heading', Allow to modify Tag cloud heading diff --git a/UserTags.php b/UserTags.php deleted file mode 100755 index f84981c..0000000 --- a/UserTags.php +++ /dev/null @@ -1,721 +0,0 @@ - - * Author URI:http://codechutney.com - * Description: Adds User Taxonomy functionality, that allows you to categorize users on tags and taxonomy basis - * Version: 1.2.7 - * Reference : http://justintadlock.com/archives/2011/10/20/custom-user-taxonomies-in-wordpress - * Text Domain : user_taxonomy - */ -define( 'WP_UT_TRANSLATION_DOMAIN', 'user_taxonomy' ); -define( 'WP_UT_URL', plugins_url( '', __FILE__ ) ); -define( 'WP_UT_PLUGIN_FOLDER', dirname( __FILE__ ) ); -define( 'WP_UT_TEMPLATES', trailingslashit( WP_UT_PLUGIN_FOLDER ) . trailingslashit( 'templates' ) ); - -/* Define all necessary variables first */ -define( 'WP_UT_CSS', WP_UT_URL . "/assets/css/" ); -define( 'WP_UT_JS', WP_UT_URL . "/assets/js/" ); -if ( ! class_exists( 'WP_List_Table' ) ) { - require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' ); -} -// Includes PHP files located in 'lib' folder -foreach ( glob( dirname( __FILE__ ) . "/lib/*.php" ) as $lib_filename ) { - require_once( $lib_filename ); -} - -class UserTags { - private static $taxonomies = array(); - - /** - * Register all the hooks and filters we can in advance - * Some will need to be registered later on, as they require knowledge of the taxonomy name - */ - public function __construct() { - add_action( 'wp_ajax_ut_delete_taxonomy', array( $this, 'ut_delete_taxonomy_callback' ) ); - - /** - * Tag suggestion ajax handler - */ - add_action( 'wp_ajax_ut_load_tag_suggestions', array( $this, 'ut_load_tag_suggestions_callback' ) ); - add_action( 'wp_ajax_nopriv_ut_load_tag_suggestions', array( $this, 'ut_load_tag_suggestions_callback' ) ); - - // Taxonomies - add_action( 'admin_enqueue_scripts', array( $this, 'ut_enqueue_scripts' ) ); - add_action( 'wp_enqueue_scripts', array( $this, 'ut_enqueue_scripts' ) ); - if ( ! empty( $_POST['taxonomy_name'] ) ) { - $this->ut_update_taxonomy_list(); - } - add_action( 'registered_taxonomy', array( $this, 'ut_registered_taxonomy' ), 10, 3 ); - - /** - * Register all the available taxonomies - */ - $this->ut_register_taxonomies(); - - // Menus - add_action( 'admin_menu', array( $this, 'admin_menu' ) ); - add_filter( 'parent_file', array( $this, 'parent_menu' ) ); - - // User Profiles - add_action( 'show_user_profile', array( $this, 'user_profile' ) ); - add_action( 'edit_user_profile', array( $this, 'user_profile' ) ); - add_action( 'personal_options_update', array( $this, 'ut_save_profile' ) ); - add_action( 'edit_user_profile_update', array( $this, 'ut_save_profile' ) ); - add_filter( 'sanitize_user', array( $this, 'restrict_username' ) ); - add_action( 'wp_head', array( $this, 'admin_ajax' ) ); - - // User Query Filter - add_filter( 'pre_user_query', array( $this, 'ut_users_filter_query' ) ); - add_action( 'restrict_manage_users', array( $this, 'ut_users_filter' ) ); - } - - function ut_enqueue_scripts() { - wp_enqueue_style( 'ut-style', WP_UT_CSS . 'style.css' ); - wp_register_script( 'user_taxonomy_js', WP_UT_JS . 'user_taxonomy.js', array( 'jquery' ), false, true ); - wp_enqueue_script( 'user_taxonomy_js' ); - } - - /** - * After registered taxonomies, store them in private var - * It's fired at the end of the register_taxonomy function - * - * @param String $taxonomy - The name of the taxonomy being registered - * @param String $object - The object type the taxonomy is for; We only care if this is "user" - * @param Array $args - The user supplied + default arguments for registering the taxonomy - */ - public function ut_registered_taxonomy( $taxonomy, $object, $args ) { - global $wp_taxonomies; - - // Only modify user taxonomies, everything else can stay as is - if ( $object != 'user' ) { - return; - } - - // Array => Object - $args = (object) $args; - - // Register any hooks/filters that rely on knowing the taxonomy now - add_filter( "manage_edit-{$taxonomy}_columns", array( $this, 'set_user_column' ) ); - add_filter( "manage_{$taxonomy}_custom_column", array( $this, 'set_user_column_values' ), 10, 3 ); - - // Save changes - $wp_taxonomies[ $taxonomy ] = $args; - self::$taxonomies[ $taxonomy ] = $args; - } - - /** - *Adds a Taxonomy Sub page to Users menu - */ - public function admin_menu() { - global $users_taxonomy; - if ( is_super_admin() ) { - $users_taxonomy = add_users_page( __( 'User Taxonomies', WP_UT_TRANSLATION_DOMAIN ), __( 'Taxonomies', WP_UT_TRANSLATION_DOMAIN ), 'read', 'user-taxonomies', array( - $this, - "ut_user_taxonomies" - ) ); - } - } - - /** - * Displays the New Taxonomy Form and if taxonomy is set in url allows to update - * the name and other values for taxonomy - */ - public function ut_user_taxonomies() { - $page_title = 'Add New Taxonomy'; - $taxonomy_name = $taxonomy_description = ''; - if ( ! empty( $_GET['taxonomy'] ) ) { - $slug = $_GET['taxonomy']; - $page_title = 'Edit Taxonomy: ' . $slug; - $taxonomy = get_taxonomy( $slug ); - $taxonomy_name = ! empty( $taxonomy ) ? $taxonomy->labels->name : ''; - $ut_taxonomies = get_site_option( 'ut_taxonomies' ); - if ( ! empty( $ut_taxonomies ) ) { - foreach ( $ut_taxonomies as $ut_taxonomy ) { - if ( $ut_taxonomy['slug'] == $slug ) { - $taxonomy_description = ! empty( $ut_taxonomy['description'] ) ? trim( $ut_taxonomy['description'] ) : ''; - } - } - } - } ?> -
-

-

- -
-
prepare_items(); ?> -
display(); ?> -
-
-
-
-
-

- -
- - - - - - - - - - - - - - - ' : ''; ?> -
- - - - -

-
- - -

-
- - - - -

-
- - - -
-
-
-
-
- -
$ut_taxonomy ) { - if ( empty( $taxonomy_slug ) && ( $ut_taxonomy['name'] == $taxonomy_name || $ut_taxonomy['slug'] == ut_taxonomy_name( $taxonomy_name ) ) ) { - $taxonomy_exists = true; - break; - } elseif ( ! empty( $taxonomy_slug ) && $taxonomy_slug == $ut_taxonomy['slug'] ) { - $taxonomy_exists = true; - $taxonomy_key = $ut_taxonomy_key; - break; - } - } - if ( ! $taxonomy_exists ) { - $ut_taxonomies[] = array( - 'name' => $taxonomy_name, - 'slug' => !empty( $taxonomy_slug ) ? ut_taxonomy_name( $taxonomy_slug ) : ut_taxonomy_name( $taxonomy_name ), - 'description' => $taxonomy_description - ); - update_site_option( 'ut_taxonomies', $ut_taxonomies ); - //a new taxonomy added, so flush rules required - update_site_option( 'ut_new_taxonomy', true ); - - add_action( 'admin_notices', 'ut_taxonomy_created' ); - } elseif ( $taxonomy_exists && ! empty( $taxonomy_slug ) ) { - //Update Taxonomy - $ut_taxonomies[ $taxonomy_key ]['name'] = $taxonomy_name; - $ut_taxonomies[ $taxonomy_key ]['description'] = $taxonomy_description; - update_site_option( 'ut_taxonomies', $ut_taxonomies ); - add_action( 'admin_notices', 'ut_taxonomy_updated' ); - } else { - //Warning - add_action( 'admin_notices', array( $this, 'taxonomy_exists_notice' ) ); - } - } - - function taxonomy_exists_notice() { - echo '
' . __( 'Taxonomy already exists', WP_UT_TRANSLATION_DOMAIN ) . '
'; - } - - /** - * Function for updating the 'profession' taxonomy count. What this does is update the count of a specific term - * by the number of users that have been given the term. We're not doing any checks for users specifically here. - * We're just updating the count with no specifics for simplicity. - * - * See the _update_post_term_count() function in WordPress for more info. - * - * @param array $terms List of Term taxonomy IDs - * @param object $taxonomy Current taxonomy object of terms - */ - public static function update_users_count( $terms, $taxonomy ) { - global $wpdb; - - foreach ( (array) $terms as $term ) { - - $count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->term_relationships WHERE term_taxonomy_id = %d", $term ) ); - - do_action( 'edit_term_taxonomy', $term, $taxonomy ); - $wpdb->update( $wpdb->term_taxonomy, compact( 'count' ), array( 'term_taxonomy_id' => $term ) ); - do_action( 'edited_term_taxonomy', $term, $taxonomy ); - } - } - - /** - * Get all the Taxonomies from site option 'ut_taxonomies' and register the taxonomies - * - */ - function ut_register_taxonomies() { - $ut_taxonomies = get_site_option( 'ut_taxonomies' ); - $errors = array(); - if ( empty( $ut_taxonomies ) || ! is_array( $ut_taxonomies ) ) { - return; - } - foreach ( $ut_taxonomies as $ut_taxonomy ) { - extract( $ut_taxonomy ); - $taxonomy_slug = ! empty( $slug ) ? $slug : ut_taxonomy_name( $name ); - //make sure taxonomy name is less than 32 - $taxonomy_slug = strlen( $taxonomy_slug ) > 32 ? substr( $taxonomy_slug, 0, 32 ) : $taxonomy_slug; - $url_prefix = apply_filters( 'ut_tag_url_prefix', 'tag' ); - $url_prefix = ! empty( $url_prefix ) ? trailingslashit( $url_prefix ) : ''; - $registered = register_taxonomy( - $taxonomy_slug, - 'user', - array( - 'public' => true, - 'hierarchical' => false, - 'labels' => array( - 'name' => __( $name ), - 'singular_name' => __( $name ), - 'menu_name' => __( $name ), - 'search_items' => __( 'Search ' . $name ), - 'popular_items' => __( 'Popular ' . $name ), - 'all_items' => __( 'All ' . $name ), - 'edit_item' => __( 'Edit ' . $name ), - 'update_item' => __( 'Update ' . $name ), - 'add_new_item' => __( 'Add New ' . $name ), - 'new_item_name' => __( 'New ' . $name ), - 'separate_items_with_commas' => __( 'Separate ' . $name . ' with commas' ), - 'add_or_remove_items' => __( 'Add or remove ' . $name ), - 'choose_from_most_used' => __( 'Choose from the most popular ' . $name ), - 'topic_count_text' => __( 'Choose from the most popular ' . $name ), - ), - 'rewrite' => array( - 'with_front' => true, - 'slug' => $url_prefix . $taxonomy_slug // Use 'author' (default WP user slug). - ), - 'capabilities' => array( - 'manage_terms' => 'edit_users', // Using 'edit_users' cap to keep this simple. - 'edit_terms' => 'edit_users', - 'delete_terms' => 'edit_users', - 'assign_terms' => 'read', - ), - 'update_count_callback' => array( 'UserTags', 'update_users_count' ) - ) - ); - if ( is_wp_error( $registered ) ) { - $errors[] = $registered; - } - } - //End of foreach - } - - /** - * Highlight User Menu item - * - * @param string $parent - * - * @return string - */ - function parent_menu( $parent = '' ) { - global $pagenow; - - // If we're editing one of the user taxonomies - // We must be within the users menu, so highlight that - if ( ! empty( $_GET['taxonomy'] ) && $pagenow == 'edit-tags.php' && isset( self::$taxonomies[ $_GET['taxonomy'] ] ) ) { - $parent = 'users.php'; - } - - return $parent; - } - - /** - * Correct the column names for user taxonomies - * Need to replace "Posts" with "Users" - * - * @param $columns - */ - public function set_user_column( $columns ) { - if ( empty( $columns ) ) { - return; - } - unset( $columns['posts'] ); - $columns['users'] = __( 'Users' ); - - return $columns; - } - - /** - * Set values for custom columns in user taxonomies - * - * @param $display - * @param $column - * @param $term_id - * - * @return mixed|string|void - */ - public function set_user_column_values( $display, $column, $term_id ) { - if ( empty( $column ) ) { - return; - } - if ( 'users' === $column && ! empty( $_GET['taxonomy'] ) ) { - $term = get_term( $term_id, $_GET['taxonomy'] ); - - $count = $term->count; - } else { - return; - } - $count = number_format_i18n( $count ); - - $tax = get_taxonomy( $_GET['taxonomy'] ); - - if ( $tax->query_var ) { - $args = array( $tax->query_var => $term->slug ); - } else { - $args = array( 'taxonomy' => $tax->name, 'term' => $term->slug ); - } - - return "".$count.""; - } - - /** - * Add the taxonomies to the user view/edit screen - * - * @param Object $user - The user of the view/edit screen - */ - public function user_profile( $user ) { - wp_nonce_field( 'user-tags', 'user-tags' ); ?> -
$taxonomy ): // Check the current user can assign terms for this taxonomy - { - if ( ! current_user_can( $taxonomy->cap->assign_terms ) ) { - continue; - } - - // Get all the terms in this taxonomy - - $terms = wp_get_object_terms( $user->ID, $taxonomy->name ); - $num = 0; - $html = ''; - $user_tags = ''; - $choose_from_text = apply_filters( 'ut_tag_cloud_heading', $taxonomy->labels->choose_from_most_used, $taxonomy ); - if ( ! empty( $terms ) ) { - foreach ( $terms as $term ) { - $user_tags[] = $term->name; - $term_url = site_url() . '/' . $taxonomy->rewrite['slug'] . '/' . $term->slug; - $html .= "
"; - $html .= 'x ' . $term->name . ''; - $html .= "
"; - $num ++; - } - $user_tags = implode( ',', $user_tags ); - } ?> - - - - - -
- - - - - -

- -
- - -

- -

-
-
$taxonomy_terms ) { - // Check the current user can edit this user and assign terms for this taxonomy - if ( ! current_user_can( 'edit_user', $user_id ) && current_user_can( $taxonomy->cap->assign_terms ) ) { - return false; - } - - // Save the data - if ( ! empty( $taxonomy_terms ) ) { - $taxonomy_terms = array_map( 'trim', explode( ',', $taxonomy_terms ) ); - wp_set_object_terms( $user_id, $taxonomy_terms, $taxonomy, false ); - } else { - //No terms left, delete all terms - wp_set_object_terms( $user_id, array(), $taxonomy, false ); - } - } - } - - /** - * Usernames can't match any of our user taxonomies - * As otherwise it will cause a URL conflict - * This method prevents that happening - * - * @param $username - * - * @return string - */ - public function restrict_username( $username ) { - if ( isset( self::$taxonomies[ $username ] ) ) { - return ''; - } - - return $username; - } - - /** - * Ajax Callback function to delete a taxonomy - * @return boolean - */ - - function ut_delete_taxonomy_callback() { - if ( empty( $_POST ) || empty( $_POST['nonce'] ) || empty( $_POST['delete_taxonomy'] ) ) { - return false; - } - $delete_taxonomy = ''; - extract( $_POST ); - if ( ! wp_verify_nonce( $nonce, 'delete-taxonomy-' . $delete_taxonomy ) ) { - return false; - } - $ut_taxonomies = get_site_option( 'ut_taxonomies' ); - foreach ( $ut_taxonomies as $ut_taxonomy_key => $ut_taxonomy_array ) { - if ( ut_stripallslashes( $ut_taxonomy_array['slug'] ) == ut_stripallslashes( $delete_taxonomy ) ) { - unset( $ut_taxonomies[ $ut_taxonomy_key ] ); - } - } - $updated = update_site_option( 'ut_taxonomies', $ut_taxonomies ); - - if ( $updated ) { - wp_send_json_success('updated'); - } else { - wp_send_json_error('failed'); - } - die( 1 ); - } - - /** - * Loads Tag Suggestions - * @return boolean - */ - function ut_load_tag_suggestions_callback() { - if ( empty( $_POST ) || empty( $_POST['nonce'] ) || empty( $_POST['q'] ) || empty( $_POST['taxonomy'] ) ) { - return false; - } - extract( $_POST ); - if ( ! wp_verify_nonce( $nonce, 'user-tags' ) ) { - return false; - } - $tags = get_terms( $taxonomy, array( - 'orderby' => 'count', - 'hide_empty' => 0 - ) ); - if ( empty( $tags ) || ! is_array( $tags ) ) { - return false; - } - $tag_list = array(); - foreach ( $tags as $tag ) { - $tag_list[] = $tag->name; - } - - //Matching Tags - $input = preg_quote( trim( $q ), '~' ); - $result = preg_grep( '~' . $input . '~i', $tag_list ); - if ( empty( $result ) ) { - return; - } - $output = ''; - if ( ! empty( $output ) ) { - echo $output; - } - die( 1 ); - } - - /** - * Admin ajax URL - */ - function admin_ajax() { - ?> - 32 ? substr( $taxonomy_slug, 0, 32 ) : $taxonomy_slug; - $taxonomy = get_taxonomy($taxonomy_slug); - if ( $taxonomy && isset( $_GET[$taxonomy_slug] ) && ! empty( $_GET[$taxonomy_slug] ) ) { - $term_slug = $_GET[$taxonomy_slug]; - continue; - } - } - } - } - - if ( ! empty( $term_slug ) ) { - $query->query_from .= " INNER JOIN {$wpdb->term_relationships} ON {$wpdb->users}.`ID` = {$wpdb->term_relationships}.`object_id` INNER JOIN {$wpdb->term_taxonomy} ON {$wpdb->term_relationships}.`term_taxonomy_id` = {$wpdb->term_taxonomy}.`term_taxonomy_id` INNER JOIN {$wpdb->terms} ON {$wpdb->terms}.`term_id` = {$wpdb->term_taxonomy}.`term_id`"; - $query->query_where .= " AND {$wpdb->terms}.`slug` = '{$term_slug}'"; - } - - return $query; - - } - - /** - * User Filter - */ - function ut_users_filter() { - $ut_taxonomies = get_site_option( 'ut_taxonomies' ); - if ( empty( $ut_taxonomies ) || ! is_array( $ut_taxonomies ) ) { - return; - } - - foreach ( $ut_taxonomies as $ut_taxonomy ) { - extract( $ut_taxonomy ); - $taxonomy_slug = ! empty( $slug ) ? $slug : ut_taxonomy_name( $name ); - $taxonomy_slug = strlen( $taxonomy_slug ) > 32 ? substr( $taxonomy_slug, 0, 32 ) : $taxonomy_slug; - $taxonomy = get_taxonomy($taxonomy_slug); - if ( $taxonomy ) { ?> - - - - Reset Filters - flush_rules( false ); - update_site_option( 'ut_new_taxonomy', 'FALSE' ); - } -} - -/** - * Show admin message for taxonomy creation - */ -function ut_taxonomy_created() { - echo '
' . __( 'Taxonomy created', WP_UT_TRANSLATION_DOMAIN ) . '
'; -} - -/** - * Updating a taxonomy - */ -function ut_taxonomy_updated() { - echo '
' . __( 'Taxonomy updated', WP_UT_TRANSLATION_DOMAIN ) . '
'; -} - -/** - * Class object - */ -function ut_user_tags() { - global $user_tags; - $user_tags = new UserTags(); -} - -/** - * If a new taxonomy was created, Flush rules for template - */ -add_action( 'init', 'wp_ut_flush_rules', 10 ); \ No newline at end of file diff --git a/assets/css/style.css b/assets/css/style.css index 14047fc..5db1bc5 100755 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -15,10 +15,11 @@ } .user-taxonomy-wrapper .tagchecklist { - font-size: inherit; - margin-left: inherit; + display: flex; + flex-wrap: wrap; + max-width: 600px; + margin-left: 0; padding: 10px 10px 10px 0; - width: 300px; overflow: hidden; } @@ -50,9 +51,9 @@ td.ajaxtag { .term-link { float: left; - margin-right: 20px; line-height: 1.7; - margin-left: 10px; + margin: 0; + padding: 0 8px; } #message.updated { @@ -81,10 +82,11 @@ td.ajaxtag { } .tag-hldr { + align-items: center; background: #444; - display: inline-block; + display: flex; margin: 2px 3px; - padding: 3px; + padding: 5px; } .tag-hldr:hover { @@ -92,16 +94,14 @@ td.ajaxtag { } .tag-hldr span { - background: rgb(185, 185, 185); + align-items: center; + background: rgb(155, 140, 140); border-radius: 50%; - display: inline-block; - float: none; - height: 16px; - margin: 4px 0 0 0; + display: flex; + margin-right: 5px; + max-width: 19px; position: relative; - vertical-align: middle; text-align: center; - width: 16px; } .tag-hldr span:hover { @@ -111,6 +111,7 @@ td.ajaxtag { .tag-hldr a { color: white; + font-size: 1.3em; text-decoration: none; } @@ -131,14 +132,21 @@ a.ntdelbutton { } .user-taxonomy-wrapper .tagchecklist span a { - margin: -1px 0 0 4px; - width: auto; + font-size: 18px; + margin: auto; + position: relative; } ul.user-taxonomy-wrapper .tagchecklist span a { margin: -1px 0 0 0; } .profile-php .user-taxonomy-wrapper .tagchecklist span a { - margin: -1px 0 0 5px; + font-size: 1em; + font-weight: bold; + height: auto; + line-height: 1.6; + margin: 0 auto; + position: relative; + text-shadow: 1px 1px #08090917; } diff --git a/assets/js/user_taxonomy.js b/assets/js/user_taxonomy.js index 43de928..5c2bbfd 100755 --- a/assets/js/user_taxonomy.js +++ b/assets/js/user_taxonomy.js @@ -2,294 +2,356 @@ * Check for empty fields */ function validate_form(parameters) { - $empty_fields = []; - $i = 0; - jQuery('#editusertaxonomy input, #editusertaxonomy textarea').each(function () { - if (!jQuery(this).is('textarea')) { - $input_value = jQuery(this).val(); - } - if (!$input_value && jQuery(this).attr('data-required')) { - jQuery(this).parents().eq(1).addClass('form-invalid'); - $empty_fields[$i] = jQuery(this).attr('name'); - $i++; - } - }); - return $empty_fields; + let $empty_fields = new Array(); + let $i = 0; + jQuery('#editusertaxonomy input, #editusertaxonomy textarea').each(function () { + if (!jQuery(this).is('textarea')) { + $input_value = jQuery(this).val(); + } + if (!$input_value && jQuery(this).attr('data-required')) { + jQuery(this).parents().eq(1).addClass('form-invalid'); + $empty_fields[$i] = jQuery(this).attr('name'); + $i++; + } + }); + return $empty_fields; } + /** - * Insert Tags - * @param {type} $this - * @param {type} $taxonomy_name - * @param {type} $term - * @param {type} $tag_html - * @returns {undefined} + * Creates Tag from input value in the form + * @param $tag_input Input field + * @param $taxonomy_name + * @param $term + * @param $tag_html Tag markup to be displayed. */ function insert_tags($tag_input, $taxonomy_name, $term, $tag_html) { - //Fetch current values and split from comma to array - $user_tag_input = jQuery('#user-tags-' + $taxonomy_name); - $user_tag_input_val = $user_tag_input.val(); - if ($user_tag_input_val) { - $user_tag_input_val_array = $user_tag_input_val.split(','); - $insert = true; - for ($i = 0; $i < $user_tag_input_val_array.length; $i++) { - if (jQuery.trim($user_tag_input_val_array[$i]) == jQuery.trim($term)) { - $insert = false; - break; - } - } - if ($insert) { - $user_tag_input.val($user_tag_input_val + ', ' + $term); - $tag_checklist.append($tag_html); - } - } else { - $user_tag_input.val($term); - $tag_checklist.append($tag_html); - } - $tag_input.val(''); - jQuery('body .tag-suggestion').remove(); + //Fetch current values and split from comma to array + let $input = jQuery('#user-tags-' + $taxonomy_name); + let $input_val = $input.val(); + let $tag_checklist = $input.siblings('.tagchecklist'); + + // Append to the existing values. + if ($input_val) { + let $input_val_array = $input_val.split(','); + let $insert = true; + for (let $i = 0; $i < $input_val_array.length; $i++) { + let val = $input_val_array[$i]; + if (jQuery.trim(val) == jQuery.trim($term)) { + $insert = false; + break; + } + } + if ($insert) { + $input.val($input_val + ', ' + $term); + $tag_checklist.append($tag_html); + } + } else { + // Add a value. + $input.val($term); + $tag_checklist.append($tag_html); + } + + $tag_input.val(''); + // Remove the particular suggestion. + jQuery('body .tag-suggestion').remove(); } + jQuery(document).ready(function ($) { - jQuery('body').on('submit', '#editusertaxonomy', function (e) { - $empty_fields = validate_form(); - if (!$empty_fields.length) { - return true; - } else { - return false; - } - }); - jQuery('#editusertaxonomy input').on('keyup', function () { - if (jQuery(this).parents().eq(1).hasClass('form-invalid')) { - $input_value = jQuery(this).val(); - if ($input_value) { - jQuery(this).parents().eq(1).removeClass('form-invalid'); - } - } - }); - //Delete Taxonomy - jQuery('body').on('click', '.delete-taxonomy a', function (e) { - e.preventDefault(); - if( !confirm("Are you sure, you want to delete the taxonomy?") ) { - return false; - } - $this = jQuery(this); - $taxonomy_id = $this.attr('id'); - if ($taxonomy_id) { - $taxonomy_id = $taxonomy_id.split('-'); - $taxonomy_id = $taxonomy_id[1]; - } - $taxonomy_name = $this.attr('data-name'); - $nonce = jQuery('#delete-taxonomy-' + $taxonomy_id).val(); - jQuery.ajax({ - 'type': 'POST', - 'url': ajaxurl, - 'data': { - action: 'ut_delete_taxonomy', - delete_taxonomy: $taxonomy_name, - nonce: $nonce - }, - success: function (resp_data) { - if (typeof resp_data.success !== 'undefined' && resp_data.success ) { - $message = '

Taxonomy deleted.

'; - jQuery('.user-taxonomies-page h2:first').after($message); - $this.parents().eq(3).remove(); - setInterval(function () { - jQuery('.user-taxonomies-page #message.below-h2').hide('slow', function () { - jQuery('.user-taxonomies-page #message.below-h2').remove(); - }); - }, 3000); - if (!jQuery('#the-taxonomy-list tr').length) { - $no_taxonomies = 'No Taxonomies found.'; - jQuery('#the-taxonomy-list').append($no_taxonomies); - } - } else { - $error_div = '

Taxonomy not deleted.

'; - jQuery('.user-taxonomies-page h2:first').after($error_div); - setInterval(function () { - jQuery('.user-taxonomies-page #message.below-h2').hide('slow', function () { - jQuery('.user-taxonomies-page #message.below-h2').remove(); - }); - }, 3000); - } - }, - error: function (resp_error) { - console.log(resp_error); - } - - }); - }); - var delay = (function () { - var timer = 0; - return function (callback, ms) { - clearTimeout(timer); - timer = setTimeout(callback, ms); - }; - })(); - jQuery('.user-profile-taxonomy').on('keyup', '.newtag', function () { - - $this = jQuery(this); - $tag_input_value = $this.val().split(','); - $tag_input_value = jQuery.trim($tag_input_value[$tag_input_value.length - 1]); - - if ($tag_input_value.length >= 2) { - delay(function () { - $tag_id = $this.attr('id'); - $tag_name = $tag_id.split('new-tag-user_tag_'); - jQuery.ajax({ - 'type': 'post', - 'url': wp_ut_ajax_url, - 'data': { - 'action': 'ut_load_tag_suggestions', - 'tag': 'user_tag', - 'q': $tag_input_value, - 'taxonomy': $tag_name[1], - 'nonce': jQuery('#user-tags').val() - }, - 'success': function (res_data) { - jQuery('.tag-suggestion').remove(); - if (res_data != '' && res_data != 0) { - $this.siblings('p.howto').before(res_data); - } - }, - 'error': function (res_error) { - console.log(res_error); - } - }); - }, 200); - } - else { - jQuery('.tag-suggestion').remove(); - } - }); - //Tags UI - jQuery('body').on('click', '.tag-suggestion li', function () { - $this = jQuery(this); - $taxonomy_name = ''; - $term = $this.html(); - $tag_checklist = $this.parent().siblings('.tagchecklist'); - $num = ( $tag_checklist.length ); - - $taxonomy_id = $this.parent().siblings('.newtag').attr('id'); - if ($taxonomy_id) { - $taxonomy_id = $taxonomy_id.split('new-tag-user_tag_'); - $taxonomy_name = $taxonomy_id[1]; - } - $tag_html = '
x ' + $term + '' + $newtag_val[$i] + '
'; - insert_tags($sibling, $taxonomy_name, $newtag_val[$i], $tag_html); - } - jQuery('.tag-suggestion').remove(); - }); - //Delete Tag - jQuery('body').on('click', '.ntdelbutton', function () { - $this = jQuery(this); - $term = $this.parent().next('.term-link').html(); - $tags_input = $this.parents().eq(2).siblings('input[type="hidden"]').val(); - $tags_input = $tags_input.split(','); - - $tags_input = jQuery.grep($tags_input, function (value) { - return value != $term; - }); - - $this.parents().eq(2).siblings('input[type="hidden"]').val($tags_input.join(',')); - $this.parent().next('.term-link').remove(); - $this.parent().parent().remove(); - }); - jQuery('body').on('click', '.term-link', function (e) { - if (jQuery(this).attr('href') != '#') return true; - else { - e.preventDefault(); - return false; - } - }); - var doing_ajax = false; - //Most Popular tag list - jQuery('body').on('click', '.tagcloud-link.user-taxonomy', function (e) { - e.preventDefault(); - if (doing_ajax) { - return false; - } - if (jQuery(this).parent().find('.the-tagcloud').length) { - jQuery(this).parent().find('.the-tagcloud').remove(); - return true; - } - doing_ajax = true; - var id = jQuery(this).attr('id'); - var tax = id.substr(id.indexOf("-") + 1); - jQuery.post(ajaxurl, {'action': 'get-tagcloud', 'tax': tax}, function (r, stat) { - doing_ajax = false; - if (0 === r || 'success' != stat) - r = wpAjax.broken; - - r = jQuery('

' + r + '

'); - jQuery('a', r).click(function () { - $this = jQuery(this); - $taxonomy_name = ''; - $term = $this.html(); - $tag_checklist = $this.parents().eq(1).siblings('.tagchecklist'); - $sibling = $this.parents().eq(1).siblings('.newtag'); - if ($tag_checklist.length === 0) { - $tag_checklist = $this.parents().eq(1).siblings('.taxonomy-wrapper').find('.tagchecklist'); - } - if ($sibling.length === 0) { - $sibling = $this.parents().eq(1).siblings('.taxonomy-wrapper').find('.newtag'); - } - $num = ( $tag_checklist.length ); - - $taxonomy_id = $sibling.attr('id'); - if ($taxonomy_id) { - $taxonomy_id = $taxonomy_id.split('new-tag-user_tag_'); - $taxonomy_name = $taxonomy_id[1]; - } - $tag_html = '
x ' + $term + '= 2) { + delay(function () { + $tag_id = $this.attr('id'); + $tag_name = $tag_id.split('new-tag-user_tag_'); + $.ajax({ + 'type': 'post', + 'url': wp_ut_ajax_url, + 'data': { + 'action': 'ut_load_tag_suggestions', + 'tag': 'user_tag', + 'q': $tag_input_value, + 'taxonomy': $tag_name[1], + 'nonce': jQuery('#user-tags').val() + }, + 'success': function (res) { + $('.tag-suggestion').remove(); + if ( res.success && 'undefined' !== typeof (res.data)) { + $this.siblings('p.howto').before(res.data); + } + }, + 'error': function (res_error) { + console.log(res_error); + } + }); + }, 200); + } else { + jQuery('.tag-suggestion').remove(); + } + }); + + //Tags UI + $('body').on('click', '.tag-suggestion li', function () { + let $this = $(this); + let $taxonomy_name = ''; + let $term = $this.html(); + let $tag_checklist = $this.parent().siblings('.tagchecklist'); + let $num = ($tag_checklist.length); + + let $taxonomy_id = $this.parent().siblings('.newtag').attr('id'); + if ($taxonomy_id) { + $taxonomy_id = $taxonomy_id.split('new-tag-user_tag_'); + $taxonomy_name = $taxonomy_id[1]; + } + let $tag_html = '
' + $term + '
'; + insert_tags($sibling, $taxonomy_name, $newtag_val[$i], $tag_html); + } + $('.tag-suggestion').remove(); + }); + + // Handle tag delete click. + $('body').on('click', '.ntdelbutton', function () { + let $this = $(this); + let parent = $this.parents().eq(1); + let $term = parent.find('.term-link').html(); + let $tags_list = $this.parents().eq(2).siblings('input[type="hidden"]'); + + let $current_tags = $tags_list.val(); + $current_tags = $current_tags.split(','); + + // Delete the tag from the list. + let $updated_tags = $.grep($current_tags, function (value) { + return value != $term; + }); + + // Store the updated list. + $tags_list.val($updated_tags.join(',')); + + // Remove tag holder. + parent.remove(); + + }); + + $('body').on('click', '.term-link', function (e) { + if ($(this).attr('href') != '#') return true; + else { + e.preventDefault(); + return false; + } + }); + + let doing_ajax = false; + + // Load most Popular tag list. + $('body').on('click', '.tagcloud-link.user-taxonomy', function (e) { + e.preventDefault(); + if (doing_ajax) { + return false; + } + doing_ajax = true; + if ($(this).parent().find('.the-tagcloud').length) { + $(this).parent().find('.the-tagcloud').remove(); + return true; + } + var id = $(this).attr('id'); + var tax = id.substr(id.indexOf("-") + 1); + $.post(ajaxurl, {'action': 'get-tagcloud', 'tax': tax}, function (r, stat) { + if (0 === r || 'success' != stat) + r = wpAjax.broken; + + r = jQuery('

' + r + '

'); + $('a', r).click(function () { + let $this = $(this); + let $taxonomy_name = ''; + + let $term_name = $this.html(); + let $tag_checklist = $this.parents().eq(2).siblings('.tagchecklist'); + let $tax_input = $this.parents().eq(2).siblings('.newtag'); + + if ($tag_checklist.length === 0) { + $tag_checklist = $this.parents().eq(3).siblings('.taxonomy-wrapper').find('.tagchecklist'); + } + + if ($tax_input.length === 0) { + $tax_input = $this.parents().eq(3).siblings('.taxonomy-wrapper').find('.newtag'); + } + + let $num = ($tag_checklist.length); + + let $taxonomy_id = $tax_input.attr('id'); + if ($taxonomy_id) { + $taxonomy_id = $taxonomy_id.split('new-tag-user_tag_'); + $taxonomy_name = $taxonomy_id[1]; + } + + let $tag_html = '
' + $term_name + ' + * + */ + +class User_Tag_Cloud { + function __construct() { + add_shortcode( 'user-tags-cloud', array( $this, 'tag_cloud' ) ); + } + + function tag_cloud( $attr ) { + + $atts = shortcode_atts( + array( + 'term' => '', + 'limit' => 25, + ), + $attr, + 'user-tags-cloud' + ); + + $term = $atts['term']; + $limit = $atts['limit']; + + } +} + +$user_tag_cloud = new User_Tag_Cloud(); diff --git a/inc/class-user-tags-list.php b/inc/class-user-tags-list.php new file mode 100755 index 0000000..eb02f33 --- /dev/null +++ b/inc/class-user-tags-list.php @@ -0,0 +1,135 @@ + + * + */ + +// If WP List table isn't included. +if ( ! class_exists( 'WP_List_Table' ) ) { + require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php'; +} + +class User_Tags_List extends WP_List_Table { + public function __construct() { + + // Define singular and plural labels, as well as whether we support AJAX. + parent::__construct( + array( + 'ajax' => false, + 'plural' => 'taxonomies', + 'singular' => 'taxonomy', + ) + ); + $this->count_context = null; + } + + /** + * Default Function to handle Column Names + * + * @param object $item + * @param string $column_name + * + * @return mixed + */ + function column_default( $item, $column_name ) { + switch ( $column_name ) { + case 'cb': + case 'name': + case 'taxonomy': + return $item[ $column_name ]; + default: + return print_r( $item, true ); // Show the whole array for troubleshooting purposes + } + } + + function prepare_items() { + /* -- Register the Columns -- */ + $columns = $this->get_columns(); + $hidden = array(); + $sortable = $this->get_sortable_columns(); + + $this->_column_headers = array( $columns, $hidden, $sortable ); + + $this->process_bulk_action(); + + $this->items = $this->ut_list_taxonomies(); + + } + + function ut_list_taxonomies() { + /* -- Fetch the items -- */ + $ut_taxonomies = get_site_option( 'ut_taxonomies', array() ); + + return $ut_taxonomies; + } + + function no_items() { + esc_html_e( 'No Taxonomy found.', 'user_taxonomy' ); + } + + function get_bulk_actions() { + $actions = array(); + $actions['delete'] = esc_html__( 'Delete', 'user_taxonomy' ) . ''; + + return $actions; + } + + function get_columns() { + return array( + 'cb' => '', + 'name' => esc_html__( 'Display Name', 'user_taxonomy' ), + 'taxonomy' => esc_html__( 'Taxonomy', 'user_taxonomy' ), + ); + } + + function column_cb( $item ) { + ?> + + + + + + +
+ | + + + + +
+ $ut_taxonomy_array ) { + if ( $ut_taxonomy_array['name'] == $taxonomy ) { + unset( $ut_taxonomies[ $ut_taxonomy_key ] ); + } + } + } + update_site_option( 'ut_taxonomies', $ut_taxonomies ); + } + +} diff --git a/inc/class-usertags.php b/inc/class-usertags.php new file mode 100644 index 0000000..44e7198 --- /dev/null +++ b/inc/class-usertags.php @@ -0,0 +1,747 @@ +ut_register_taxonomies(); + + // Menus + add_action( 'admin_menu', array( $this, 'register_page' ) ); + add_filter( 'parent_file', array( $this, 'parent_menu' ) ); + + // User Profiles + add_action( 'show_user_profile', array( $this, 'user_profile' ) ); + add_action( 'edit_user_profile', array( $this, 'user_profile' ) ); + + add_action( 'personal_options_update', array( $this, 'ut_save_profile' ) ); + add_action( 'edit_user_profile_update', array( $this, 'ut_save_profile' ) ); + + add_filter( 'sanitize_user', array( $this, 'restrict_username' ) ); + add_action( 'wp_head', array( $this, 'admin_ajax' ) ); + + // User Query Filter +// add_filter( 'pre_user_query', array( $this, 'ut_users_filter_query' ) ); +// add_action( 'restrict_manage_users', array( $this, 'ut_users_filter' ) ); + + // Clear up related tags and taxonomies, when a user is deleted + add_action( 'deleted_user', array( $this, 'update_user_list' ) ); + } + + function ut_enqueue_scripts() { + + $js_mtime = filemtime( UT_DIR . '/assets/js/user_taxonomy.js'); + $version = UT_VERSION . $js_mtime; + wp_register_script( 'user_taxonomy_js', UT_JS_URL . 'user_taxonomy.js', array( 'jquery' ), $version, true ); + + $css_mtime = filemtime( UT_DIR . '/assets/css/style.css'); + $version = UT_VERSION . $css_mtime; + wp_enqueue_style( 'ut-style', UT_CSS_URL . 'style.css', '', $version ); + + wp_localize_script( 'user_taxonomy_js', 'wp_ut_ajax_url', admin_url( 'admin-ajax.php' ) ); + + + wp_enqueue_script( 'user_taxonomy_js' ); + } + + /** + * After registered taxonomies, store them in private var + * It's fired at the end of the register_taxonomy function + * + * @param String $taxonomy - The name of the taxonomy being registered + * @param String $object - The object type the taxonomy is for; We only care if this is "user" + * @param Array $args - The user supplied + default arguments for registering the taxonomy + */ + public function ut_registered_taxonomy( $taxonomy, $object, $args ) { + global $wp_taxonomies; + + // Only modify user taxonomies, everything else can stay as is + if ( 'user' !== $object ) { + return; + } + + // Array => Object + $args = (object) $args; + + // Register any hooks/filters that rely on knowing the taxonomy now + add_filter( "manage_edit-{$taxonomy}_columns", array( $this, 'set_user_column' ) ); + add_filter( "manage_{$taxonomy}_custom_column", array( $this, 'set_user_column_values' ), 10, 3 ); + + // Save changes + self::$taxonomies[ $taxonomy ] = $args; + } + + /** + * Adds a Taxonomy Sub page to Users menu + */ + public function register_page() { + if ( apply_filters( 'ut_is_admin', is_super_admin() ) ) { + $this->settings_page = add_users_page( + esc_html__( 'User Taxonomy', 'user_taxonomy' ), esc_html__( 'Taxonomy', 'user_taxonomy' ), 'read', 'user-taxonomies', array( + $this, + 'ut_user_taxonomies', + ) + ); + } + } + + /** + * Displays the New Taxonomy Form and if taxonomy is set in url allows to update + * the name and other values for taxonomy + */ + public function ut_user_taxonomies() { + $page_title = esc_html__( 'Add new Taxonomy', 'user_taxonomy' ); + $taxonomy_description = ''; + $slug = ''; + $taxonomy_name = ''; + + if ( ! empty( $_GET['taxonomy'] ) ) { + $slug = sanitize_text_field( wp_unslash( $_GET['taxonomy'] ) ); + + $page_title = 'Edit Taxonomy: ' . $slug; + $taxonomy = get_taxonomy( $slug ); + + $taxonomy_name = ! empty( $taxonomy ) ? $taxonomy->labels->name : ''; + $ut_taxonomies = get_site_option( 'ut_taxonomies' ); + + if ( ! empty( $ut_taxonomies ) ) { + foreach ( $ut_taxonomies as $ut_taxonomy ) { + if ( $ut_taxonomy['slug'] == $slug ) { + $taxonomy_description = ! empty( $ut_taxonomy['description'] ) ? trim( $ut_taxonomy['description'] ) : ''; + } + } + } + } ?> +
+

+ +
+
+
+
+

+ +
+
+ + +

The name is how it appears on your site.

+
+ +
+ + +

+
+ +
+ + +

+
+ ' : ''; + ?> +

+ + +

+ + + +
+
+
+
+
+ prepare_items(); + ?> +
+ display(); + ?> +
+
+
+ +
+ $ut_taxonomy ) { + if ( empty( $slug ) && ( $name === $ut_taxonomy['name'] || ut_taxonomy_name( $name ) === $ut_taxonomy['slug'] ) ) { + $taxonomy_exists = true; + break; + } elseif ( ! empty( $slug ) && $slug == $ut_taxonomy['slug'] ) { + $taxonomy_exists = true; + $taxonomy_key = $ut_taxonomy_key; + break; + } + } + if ( ! $taxonomy_exists ) { + $ut_taxonomies[] = array( + 'name' => $name, + 'slug' => ! empty( $slug ) ? ut_taxonomy_name( $slug ) : ut_taxonomy_name( $name ), + 'description' => $description, + ); + update_site_option( 'ut_taxonomies', $ut_taxonomies ); + // a new taxonomy added, so flush rules required. + update_site_option( 'ut_new_taxonomy', true ); + + add_action( 'admin_notices', 'ut_taxonomy_created' ); + } elseif ( $taxonomy_exists && ! empty( $slug ) ) { + // Update Taxonomy + $ut_taxonomies[ $taxonomy_key ]['name'] = $name; + $ut_taxonomies[ $taxonomy_key ]['description'] = $description; + update_site_option( 'ut_taxonomies', $ut_taxonomies ); + add_action( 'admin_notices', 'ut_taxonomy_updated' ); + } else { + // Warning + add_action( 'admin_notices', array( $this, 'taxonomy_exists_notice' ) ); + } + } + + function taxonomy_exists_notice() { + echo '
' . esc_html__( 'Taxonomy already exists', 'user_taxonomy' ) . '
'; + } + + /** + * Keep a track of users count for each taxonomy. + * + * See the _update_post_term_count() function in WordPress for more info. + * + * @param array $terms List of Term taxonomy IDs + * @param object $taxonomy Current taxonomy object of terms + */ + public static function update_users_count( $terms, $taxonomy ) { + global $wpdb; + + foreach ( (array) $terms as $term ) { + + $count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->term_relationships WHERE term_taxonomy_id = %d", $term ) ); + + do_action( 'edit_term_taxonomy', $term, $taxonomy ); + $wpdb->update( $wpdb->term_taxonomy, compact( 'count' ), array( 'term_taxonomy_id' => $term ) ); + do_action( 'edited_term_taxonomy', $term, $taxonomy ); + } + } + + /** + * Get all the Taxonomies from site option 'ut_taxonomies' and register the taxonomies + */ + function ut_register_taxonomies() { + $ut_taxonomies = get_site_option( 'ut_taxonomies' ); + $errors = array(); + if ( empty( $ut_taxonomies ) || ! is_array( $ut_taxonomies ) ) { + return; + } + foreach ( $ut_taxonomies as $ut_taxonomy ) { + + //@todo: Test and remove extract, based on data stored in DB. + extract( $ut_taxonomy ); + + $name = $ut_taxonomy['name']; + $slug = $ut_taxonomy['slug']; + + $taxonomy_slug = ! empty( $slug ) ? $slug : ut_taxonomy_name( $name ); + + // make sure taxonomy name is less than 32 + $taxonomy_slug = 32 < strlen( $taxonomy_slug ) ? substr( $taxonomy_slug, 0, 32 ) : $taxonomy_slug; + + $args = array( + 'public' => true, + 'hierarchical' => false, + 'labels' => array( + 'name' => $name, + 'singular_name' => $name, + 'menu_name' => $name, + 'search_items' => 'Search ' . $name, + 'popular_items' => 'Popular ' . $name, + 'all_items' => 'All ' . $name, + 'edit_item' => 'Edit ' . $name, + 'update_item' => 'Update ' . $name, + 'add_new_item' => 'Add New ' . $name, + 'new_item_name' => 'New ' . $name, + 'separate_items_with_commas' => 'Separate ' . $name . ' with commas', + 'add_or_remove_items' => 'Add or remove ' . $name, + 'choose_from_most_used' => 'Choose from the most popular ' . $name, + 'topic_count_text' => 'Choose from the most popular ' . $name, + ), + 'show_in_rest' => false, + 'rewrite' => array( + 'slug' => get_url_prefix() . $taxonomy_slug, + ), + 'capabilities' => array( + 'manage_terms' => 'edit_users', // Using 'edit_users' cap to keep this simple. + 'edit_terms' => 'edit_users', + 'delete_terms' => 'edit_users', + 'assign_terms' => 'read', + ), + 'update_count_callback' => array( $this, 'update_users_count' ), + ); + + $registered = register_taxonomy( + $taxonomy_slug, + 'user', + $args + ); + + if ( is_wp_error( $registered ) ) { + $errors[] = $registered; + } + } + // End of foreach + } + + /** + * Set Users menu as parent for User Taxonomy edit page. + * + * @param string $parent + * + * @return string + */ + function parent_menu( $parent = '' ) { + global $pagenow; + + // If we're editing one of the user taxonomies + // We must be within the users menu, so highlight that + if ( ! empty( $_GET['taxonomy'] ) && 'edit-tags.php' === $pagenow && isset( self::$taxonomies[ sanitize_key( $_GET['taxonomy'] ) ] ) ) { + $parent = 'users.php'; + } + + return $parent; + } + + /** + * Correct the column names for user taxonomies + * Need to replace "Posts" with "Users" + * + * @param $columns + */ + public function set_user_column( $columns ) { + if ( empty( $columns ) ) { + return; + } + unset( $columns['posts'] ); + $columns['users'] = esc_html__( 'Users' ); + + return $columns; + } + + /** + * Set values for custom columns in user taxonomies + * + * @param $display + * @param $column + * @param $term_id + * + * @return mixed|string|void + */ + public function set_user_column_values( $display, $column, $term_id ) { + if ( empty( $column ) ) { + return; + } + + $input_taxonomy = ''; + + if ( ! empty( $_GET['taxonomy'] ) ) : + $input_taxonomy = sanitize_text_field( wp_unslash( $_GET['taxonomy'] ) ); + endif; + + if ( 'users' === $column && ! empty( $_GET['taxonomy'] ) ) { + $term = get_term( $term_id, $input_taxonomy ); + + $count = $term->count; + } else { + return; + } + $count = number_format_i18n( $count ); + + $tax = get_taxonomy( $input_taxonomy ); + + if ( $tax->query_var ) { + $args = array( $tax->query_var => $term->slug ); + } else { + $args = array( + 'taxonomy' => $tax->name, + 'term' => $term->slug, + ); + } + + return sprintf( '%2$d', esc_url( add_query_arg( $args, 'users.php' ) ), $count ); + } + + /** + * Add the taxonomies to the user view/edit screen + * + * @param Object $user - The user of the view/edit screen + */ + public function user_profile( $user ) { + ?> +

User Tags

+
+ $taxonomy ) { // Check the current user can assign terms for this taxonomy + if ( ! current_user_can( $taxonomy->cap->assign_terms ) ) { + continue; + } + + // Get all the terms in this taxonomy + $terms = wp_get_object_terms( $user->ID, $taxonomy->name ); + $num = 0; + $html = ''; + $user_tags = array(); + + $choose_from_text = apply_filters( 'ut_tag_cloud_heading', $taxonomy->labels->choose_from_most_used, $taxonomy ); + if ( ! empty( $terms ) ) { + foreach ( $terms as $term ) { + $user_tags[] = $term->name; + $term_url = site_url() . '/' . $taxonomy->rewrite['slug'] . '/' . $term->slug; + $html .= '
'; + $html .= sprintf( '%s', esc_url( $term_url ), $term->name ); + $html .= '
'; + $num ++; + } + $user_tags = implode( ',', $user_tags ); + } + + ?> + + + + + + + +
+ $taxonomy_terms ) { + // Check the current user can edit this user and assign terms for this taxonomy + if ( ! current_user_can( 'edit_user', $user_id ) && current_user_can( $taxonomy->cap->assign_terms ) ) { + return false; + } + + // Save the data + if ( ! empty( $taxonomy_terms ) ) { + $taxonomy_terms = array_map( 'trim', explode( ',', $taxonomy_terms ) ); + wp_set_object_terms( $user_id, $taxonomy_terms, $taxonomy, false ); + } else { + // No terms left, delete all terms + wp_set_object_terms( $user_id, array(), $taxonomy, false ); + } + } + } + + /** + * Usernames can't match any of our user taxonomies + * As otherwise it will cause a URL conflict + * This method prevents that happening + * + * @param $username + * + * @return string + */ + public function restrict_username( $username ) { + if ( isset( self::$taxonomies[ $username ] ) ) { + return ''; + } + + return $username; + } + + /** + * Ajax Callback function to delete a taxonomy + * + * @return boolean + */ + + function ut_delete_taxonomy_callback() { + + if ( empty( $_POST ) || empty( $_POST['nonce'] ) || empty( $_POST['delete_taxonomy'] ) ) { + return false; + } + + $nonce = sanitize_key( $_POST['nonce'] ); + $taxnomy = sanitize_key( $_POST['delete_taxonomy'] ); + if ( ! wp_verify_nonce( $nonce, 'delete-taxonomy-' . $taxnomy ) ) { + return false; + } + $ut_taxonomies = get_site_option( 'ut_taxonomies' ); + foreach ( $ut_taxonomies as $ut_taxonomy_key => $ut_taxonomy_array ) { + if ( ut_stripallslashes( $ut_taxonomy_array['slug'] ) == ut_stripallslashes( $taxnomy ) ) { + unset( $ut_taxonomies[ $ut_taxonomy_key ] ); + } + } + $updated = update_site_option( 'ut_taxonomies', $ut_taxonomies ); + + if ( $updated ) { + wp_send_json_success( 'updated' ); + } else { + wp_send_json_error( 'failed' ); + } + } + + /** + * Loads Tag Suggestions + * + * @return boolean + */ + function ut_load_tag_suggestions_callback() { + if ( empty( $_POST ) || empty( $_POST['nonce'] ) || empty( $_POST['q'] ) || empty( $_POST['taxonomy'] ) ) { + wp_send_json_error( array( 'error' => 'Invalid request.' ) ); + } + + $nonce = sanitize_text_field( wp_unslash( $_POST['nonce'] ) ); + $taxonomy = sanitize_text_field( wp_unslash( $_POST['taxonomy'] ) ); + $q = sanitize_text_field( wp_unslash( $_POST['q'] ) ); + + if ( ! wp_verify_nonce( $nonce, 'user-tags' ) ) { + wp_send_json_error( array( 'error' => 'Couldn\'t validate the request.' ) ); + } + + $tags = get_terms( + $taxonomy, + array( + 'orderby' => 'count', + 'hide_empty' => 0, + ) + ); + if ( empty( $tags ) || ! is_array( $tags ) ) { + wp_send_json_error(); + } + $tag_list = array(); + foreach ( $tags as $tag ) { + $tag_list[] = $tag->name; + } + + // Matching Tags + $input = preg_quote( trim( $q ), '~' ); + $result = preg_grep( '~' . $input . '~i', $tag_list ); + if ( empty( $result ) ) { + wp_send_json_error(); + } + ob_start(); + ?> + + + + 32 ? substr( $taxonomy_slug, 0, 32 ) : $taxonomy_slug; + $taxonomy = get_taxonomy( $taxonomy_slug ); + if ( $taxonomy && isset( $_GET[ $taxonomy_slug ] ) && ! empty( $_GET[ $taxonomy_slug ] ) ) { + $term_slug = sanitize_text_field( $_GET[ $taxonomy_slug ] ); + continue; + } + } + } + } + + if ( ! empty( $term_slug ) ) { + $query->query_from .= " INNER JOIN {$wpdb->term_relationships} ON {$wpdb->users}.`ID` = {$wpdb->term_relationships}.`object_id` INNER JOIN {$wpdb->term_taxonomy} ON {$wpdb->term_relationships}.`term_taxonomy_id` = {$wpdb->term_taxonomy}.`term_taxonomy_id` INNER JOIN {$wpdb->terms} ON {$wpdb->terms}.`term_id` = {$wpdb->term_taxonomy}.`term_id`"; + $query->query_where .= " AND {$wpdb->terms}.`slug` = '{$term_slug}'"; + } + + return $query; + + } + + /** + * Adds a dropdown for each taxonomy and used tags to allow filtering of users list + * + * @author Garrett Eclipse + */ + function ut_users_filter() { + // Show All the taxonomies in single drop down + $ut_taxonomies = get_site_option( 'ut_taxonomies' ); + if ( empty( $ut_taxonomies ) || ! is_array( $ut_taxonomies ) ) { + return; + } + ?> + + + + + Reset Filters + $taxonomy ) { + $taxonomy_list[] = $key; + } + // Delete the relation for a user + if ( ! empty( $taxonomy_list ) && is_array( $taxonomy_list ) ) { + wp_delete_object_term_relationships( $user_id, $taxonomy_list ); + } + } + +} diff --git a/inc/functions.php b/inc/functions.php new file mode 100755 index 0000000..7d65384 --- /dev/null +++ b/inc/functions.php @@ -0,0 +1,175 @@ + 32 ? substr( $taxonomy_slug, 0, 32 ) : $taxonomy_slug; + + return esc_html( ut_stripallslashes( $taxonomy_slug ) ); +} + +/** + * + */ +add_filter( 'taxonomy_template', 'user_taxonomy_template' ); +/** + * @param string $template + * + * @return string + */ +function user_taxonomy_template( $template = '' ) { + + $taxonomy = get_query_var( 'taxonomy' ); + + // check if taxonomy is for user or not + $user_taxonomies = get_object_taxonomies( 'user', 'object' ); + + if ( ! array( $user_taxonomies ) || empty( $user_taxonomies[ $taxonomy ] ) ) { + return $template; + } + + // Check if theme is overriding the template + $overridden_template = locate_template( 'user-taxonomy-template.php', false, false ); + + if ( ! empty( $overridden_template ) ) { + $taxonomy_template = $overridden_template; + } else { + $taxonomy_template = UT_TEMPLATE_PATH . 'user-taxonomy-template.php'; + } + + $file_headers = @get_headers( $taxonomy_template ); + if ( 'HTTP/1.0 404 Not Found' !== $file_headers[0] ) { + return $taxonomy_template; + } + + return $template; +} + +/** + * Shortcode for Tags UI in frontend + */ +function wp_ut_tag_box() { + $user_id = get_current_user_id(); + $taxonomies = get_object_taxonomies( 'user', 'object' ); + wp_nonce_field( 'user-tags', 'user-tags' ); + wp_enqueue_script( 'user_taxonomy_js' ); + if ( empty( $taxonomies ) ) { + ?> +

+ + +
+ + + +
+ $taxonomy_terms ) { + // Check the current user can edit this user and assign terms for this taxonomy + if ( ! current_user_can( 'edit_user', $user_id ) && current_user_can( $taxonomy->cap->assign_terms ) ) { + return false; + } + + // Save the data + if ( ! empty( $taxonomy_terms ) ) { + $taxonomy_terms = array_map( 'trim', explode( ',', $taxonomy_terms ) ); + } + wp_set_object_terms( $user_id, $taxonomy_terms, $taxonomy, false ); + } +} + +function get_url_prefix() { + $url_prefix = apply_filters( 'ut_tag_url_prefix', 'tag' ); + + return trailingslashit( $url_prefix ); +} diff --git a/lib/class-ut-user-tags-list.php b/lib/class-ut-user-tags-list.php deleted file mode 100755 index 3665b1b..0000000 --- a/lib/class-ut-user-tags-list.php +++ /dev/null @@ -1,135 +0,0 @@ - - * - */ -require_once( dirname( __FILE__ ) . "/functions.php" ); - -class User_Tags_List extends WP_List_Table { - public function __construct() { - - // Define singular and plural labels, as well as whether we support AJAX. - parent::__construct( array( - 'ajax' => false, - 'plural' => 'taxonomies', - 'singular' => 'taxonomy', - ) ); - $this->count_context = null; - } - - function prepare_items() { - /* -- Register the Columns -- */ - $columns = $this->get_columns(); - $hidden = array(); - $sortable = $this->get_sortable_columns(); - $this->_column_headers = array( $columns, $hidden, $sortable ); - $this->process_bulk_action(); - - $this->items = $this->ut_list_taxonomies(); - - } - - function ut_list_taxonomies() { - /* -- Fetch the items -- */ - $ut_taxonomies = get_site_option( 'ut_taxonomies' ); - - return $ut_taxonomies; - } - - function get_column_info() { - $this->_column_headers = array( - $this->get_columns(), - array(), - $this->get_sortable_columns(), - ); - - return $this->_column_headers; - } - - function no_items() { - _e( 'No Taxonomies found.', WP_UT_TRANSLATION_DOMAIN ); - } - - function display() { - $this->display_tablenav( 'top' ); ?> - - - - print_column_headers(); ?> - - - - - print_column_headers( false ); ?> - - - - display_rows_or_placeholder(); ?> - -
- display_tablenav( 'bottom' ); - } - - function single_row( $item ) { - static $row_class = ''; - if ( empty( $row_class ) ) { - $row_class = ' class="alternate"'; - } else { - $row_class = ''; - } - echo ''; - echo $this->single_row_columns( $item ); - echo ''; - } - - function get_bulk_actions() { - $actions = array(); - $actions['delete'] = __( 'Delete', WP_UT_TRANSLATION_DOMAIN ) . ''; - - return $actions; - } - - function get_columns() { - return array( - 'cb' => '', - 'name' => __( 'Display Name', WP_UT_TRANSLATION_DOMAIN ), - 'taxonomy' => __( 'Taxonomy', WP_UT_TRANSLATION_DOMAIN ), - ); - } - - function column_cb( $item ) { - printf( '', $this->_args['plural'], $item['name'] ); - } - - function column_taxonomy( $item ) { - $taxonomy_slug = ! empty( $item['slug'] ) ? $item['slug'] : ut_taxonomy_name( $item['name'] ); - //var_dump($user_info); - echo $taxonomy_slug; - } - - function column_name( $item ) { - $taxonomy_slug = ! empty( $item['slug'] ) ? $item['slug'] : ut_taxonomy_name( $item['name'] ); - echo ' ' . $item['name'] . '
' . __( 'Edit', WP_UT_TRANSLATION_DOMAIN ) . ' |'; - wp_nonce_field( 'delete-taxonomy-' . $taxonomy_slug, 'delete-taxonomy-' . $taxonomy_slug ); - echo ' ' . __( 'Trash', WP_UT_TRANSLATION_DOMAIN ) . '
'; - } - - function process_bulk_action() { - if ( empty( $_REQUEST['taxonomies'] ) ) { - return; - } - extract( $_POST ); - $ut_taxonomies = get_site_option( 'ut_taxonomies' ); - foreach ( $taxonomies as $taxonomy ) { - foreach ( $ut_taxonomies as $ut_taxonomy_key => $ut_taxonomy_array ) { - if ( $ut_taxonomy_array['name'] == $taxonomy ) { - unset( $ut_taxonomies[ $ut_taxonomy_key ] ); - } - } - } - update_site_option( 'ut_taxonomies', $ut_taxonomies ); - } - -} \ No newline at end of file diff --git a/lib/class-ut-user-tags-shortcode.php b/lib/class-ut-user-tags-shortcode.php deleted file mode 100755 index 0ec2842..0000000 --- a/lib/class-ut-user-tags-shortcode.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - */ -class Ut_User_Tag_Cloud { - function __construct() { - add_shortcode('user-tags-cloud', array( $this, 'tag_cloud') ); - } - function tag_cloud( $atts ) { - - extract(shortcode_atts(array( - 'term' => '', - 'limit' => 25 - ), $atts)); - echo "
Variables";
-		print_r( $term);
-		print_r( $limit );
-		echo "
"; - } -} -new Ut_User_Tag_Cloud(); \ No newline at end of file diff --git a/lib/functions.php b/lib/functions.php deleted file mode 100755 index 1411c51..0000000 --- a/lib/functions.php +++ /dev/null @@ -1,157 +0,0 @@ - 32 ? substr( $taxonomy_slug, 0, 32 ) : $taxonomy_slug; - - return esc_html( ut_stripallslashes( $taxonomy_slug ) ); -} - -/** - * - */ -add_filter( 'taxonomy_template', 'get_custom_taxonomy_template' ); -/** - * @param string $template - * - * @return string - */ -function get_custom_taxonomy_template( $template = '' ) { - - $taxonomy = get_query_var( 'taxonomy' ); - - //check if taxonomy is for user or not - $user_taxonomies = get_object_taxonomies( 'user', 'object' ); - - if ( ! array( $user_taxonomies ) || empty( $user_taxonomies[ $taxonomy ] ) ) { - return; - } - - $taxonomy_template = WP_UT_TEMPLATES . "user-taxonomy-template.php"; - $file_headers = @get_headers( $taxonomy_template ); - if ( $file_headers[0] != 'HTTP/1.0 404 Not Found' ) { - return $taxonomy_template; - } - - return $template; -} - -/** - * Shortcode for Tags UI in frontend - */ -function wp_ut_tag_box() { - $user_id = get_current_user_id(); - $taxonomies = get_object_taxonomies( 'user', 'object' ); - wp_nonce_field( 'user-tags', 'user-tags' ); - wp_enqueue_script( 'user_taxonomy_js' ); - if ( empty ( $taxonomies ) ) { - ?> -

- -
- - - -
- $taxonomy_terms ) { - // Check the current user can edit this user and assign terms for this taxonomy - if ( ! current_user_can( 'edit_user', $user_id ) && current_user_can( $taxonomy->cap->assign_terms ) ) { - return false; - } - - // Save the data - if ( ! empty( $taxonomy_terms ) ) { - $taxonomy_terms = array_map( 'trim', explode( ',', $taxonomy_terms ) ); - } - wp_set_object_terms( $user_id, $taxonomy_terms, $taxonomy, false ); - } - } -} \ No newline at end of file diff --git a/readme.txt b/readme.txt index fda9ea4..d03103a 100755 --- a/readme.txt +++ b/readme.txt @@ -1,18 +1,18 @@ === User Tags === -Contributors: UmeshSingla,garrett-eclipse -Donate link: https://www.paypal.com/ +Contributors: UmeshSingla +Donate link: https://paypal.me/SinglaUmesh Tags: Tags, taxonomies, user taxonomy, user tags License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html -Requires at least: 3.0 -Tested up to: 4.1 +Requires at least: 5.4 +Tested up to: 5.5.3 Stable tag: trunk -Adds an admin option to allow creating User Taxonomies and create tags for different taxonomies. +Adds an admin option to allow creating User Taxonomy and create tags for different taxonomies. == Description == -Adds a **Taxonomies** option under **User** to create custom user taxonomy. +Adds a **Taxonomy** option under **User** to create custom user taxonomy. All taxonomies are listed in Profile page for all users which allows users to add tags for the taxonomy. Each Tag is associated with a template, listing all users who added that tag in their profile. @@ -24,17 +24,33 @@ Users can add new tags. == Installation == -1. Upload the `wp-user-taxonomies` folder to the `/wp-content/plugins/` directory -2. Activate the plugin through the 'Plugins' menu in WordPress -3. Go to Taxonomies under Users option to create taxonomies for User +1. Upload the `user-tags` folder to the `/wp-content/plugins/` directory. +2. Activate the plugin through the 'Plugins' menu in WordPress. +3. To create new Taxonomy Go to User -> Taxonomy screen. == Changelog == += 1.2.8 = + +* Fixed: Updated filter name 'ut_tepmplate_content' => ut_template_content : https://github.com/UmeshSingla/user-tags/issues/7 +* Fixed: Return $template variable in functions.php https://github.com/UmeshSingla/user-tags/issues/8 +* Fixed: string to array conversion. +* Fixed: Compat with WordPress >= 5.5 ( Fixed fatal error ) +* Updated: Switch to div instead of table for new User Taxonomy screen + = 1.2.7 = -* New - Filter: `ut_tag_url_prefix` to filter the way, tags URLs are formed -* New - Specify a slug for taxonomy -* New - User Tag cloud shortcode -* Fixed - Tag delete link in admin screen, added alert before deletion +* New + * Filter: `ut_tag_url_prefix` to filter the way tags URLs are formed + * Added option to specify a slug for taxonomy + * User Tag cloud shortcode + * Set up tag filter on the User Query + * Link User Count column of Taxonomy Tables to Filtered Users.php + * Filter Users list according to tags + * Update Terms when a user is deleted + * Allow to override User Tag list Template from theme or child theme +* Fixed + * Tag delete link in admin screen, added alert before deletion + * Broken style for tags in user profile = 1.2.6 = * New - Filter: `ut_template_users` in Taxonomy template to filter the list of users before displaying @@ -50,7 +66,7 @@ Users can add new tags. * Fixed - Bubbling up of multiple list on repeated click over most used tags link * Fixed - Tag being saved for admin too on editing other user profile -( Thank you @Tempera for reporting all the issues ) +( Credits: @Tempera ) = 1.2.3 = * Fixed - 'ut_template_content' filter args @@ -94,7 +110,7 @@ Users can add new tags. == Upgrade Notice == -Requires Wordpress 3.0 atleast +Requires Wordpress 4.8 atleast == Frequently Asked Questions == diff --git a/templates/user-taxonomy-template.php b/templates/user-taxonomy-template.php index dc1eb41..9b33f8e 100755 --- a/templates/user-taxonomy-template.php +++ b/templates/user-taxonomy-template.php @@ -1,57 +1,83 @@ -
-
- taxonomy ); + $users = get_objects_in_term( $term_id, $term->taxonomy ); - /** - * Allows to filter user list before displaying it in template - * can be used for sorting the users as per username - */ - $users = apply_filters( 'ut_template_users', $users ); - $template_content = ''; - if ( ! empty( $users ) ) { - ?> -
-
    ' . - get_avatar( $user_id, '96' ) . ' -

    ' . get_the_author_meta( 'display_name', $user_id ) . '

    -
    ' . - wpautop( get_the_author_meta( 'description', $user_id ) ) . ' -
    + /** + * Allows to filter user list before displaying it in template + * can be used for sorting the users as per username + */ + $users = apply_filters( 'ut_template_users', $users ); + $template_content = ''; + if ( ! empty( $users ) ) { + ?> +
    +
      + taxonomy ); + continue; + } + $c = '
    • ' . get_avatar( $user_id, '96' ) . + '

      ' . get_the_author_meta( 'display_name', $user_id ) . '

      +
      ' . wpautop( get_the_author_meta( 'description', $user_id ) ) . '
    • '; - $template_content .= apply_filters( 'ut_tepmplate_content', $c, $user_id ); - } - echo $template_content; ?> -
    -
    - No Users found.

    "; - echo apply_filters( 'ut_template_content_empty', __( $content ) ); - } ?> -
- -
+ +
+ No Users found.

' ); + echo esc_html( $content ); + } + ?> +
+ + + + + * Author URI:http://codechutney.com + * Description: Adds User Taxonomy functionality, It allows you to categorize users on tags and taxonomy basis. + * Version: 1.2.8 + * Reference : http://justintadlock.com/archives/2011/10/20/custom-user-taxonomies-in-wordpress + * Text Domain : user_taxonomy + */ + + +define( 'UT_URL', plugins_url( '', __FILE__ ) ); +define( 'UT_DIR', trailingslashit( dirname( __FILE__ ) ) ); +define( 'UT_TEMPLATE_PATH', trailingslashit( UT_DIR ) . trailingslashit( 'templates' ) ); + +define( 'UT_VERSION', '1.2.8' ); + +/* Define all necessary variables first */ +define( 'UT_CSS_URL', UT_URL . '/assets/css/' ); +define( 'UT_JS_URL', UT_URL . '/assets/js/' ); + +// Includes PHP files located in 'inc' folder +require_once UT_DIR . 'inc/functions.php'; +require_once UT_DIR . 'inc/class-usertags.php'; +require_once UT_DIR . 'inc/class-user-tags-list.php'; +require_once UT_DIR . 'inc/class-user-tag-cloud.php'; + +/** + * Class object + */ +add_action( 'init', 'ut_user_tags' ); + +// Flush rewrite rules +function wp_ut_flush_rules() { + // Check if there is new taxonomy, if there flush rules + $ut_new_taxonomy = get_site_option( 'ut_new_taxonomy', '' ); + if ( 'FALSE' !== $ut_new_taxonomy ) { + global $wp_rewrite; + $wp_rewrite->flush_rules( false ); + delete_site_option( 'ut_new_taxonomy' ); + } +} + +/** + * Show admin message for taxonomy creation + */ +function ut_taxonomy_created() { + echo '
' . esc_html__( 'Taxonomy created', 'user_taxonomy' ) . '
'; +} + +/** + * Updating a taxonomy + */ +function ut_taxonomy_updated() { + echo '
' . esc_html__( 'Taxonomy updated', 'user_taxonomy' ) . '
'; +} + +/** + * Class object + */ +function ut_user_tags() { + global $user_tags; + $user_tags = new UserTags(); +} + +/** + * If a new taxonomy was created, Flush rules for template + */ +add_action( 'init', 'wp_ut_flush_rules', 10 ); + +// Register plugin activation hook, Set/update plugin version. +register_activation_hook( __FILE__, 'ut_activated' ); + +function ut_activated() { + + $version = get_site_option( 'ut_version' ); + if ( ! $version || UT_VERSION !== $version ) { + update_site_option( 'ut_version', UT_VERSION ); + } +}