-
Notifications
You must be signed in to change notification settings - Fork 11
/
lh-user-taxonomies.php
345 lines (316 loc) · 11.8 KB
/
lh-user-taxonomies.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
<?php
/*
Plugin Name: LH User Taxonomies
Plugin URI: http://lhero.org/plugins/lh-user-taxonomies/
Author: Peter Shaw
Author URI: http://shawfactor.com/
Description: Simplify the process of adding support for custom taxonomies for Users. Just use `register_taxonomy` and everything else is taken care of. With added functions by Peter Shaw.
Version: 1.4
== Changelog ==
= 1.0 =
*Initial Release
= 1.1 =
*Added icon
= 1.2 =
*Added various patches, props nikolaynesov
= 1.3 =
*Better readme.txt
= 1.3.1 =
*Minor fix, thanks lindesvard
= 1.4 =
*Minor fix, and tree logic for hierarchical taxonomies - thanks again Carl-Gerhard Lindesvard
License:
Released under the GPL license
http://www.gnu.org/copyleft/gpl.html
Copyright 2014 Peter Shaw (email : [email protected])
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
class LH_User_Taxonomies_plugin {
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() {
// Taxonomies
add_action('registered_taxonomy', array($this, 'registered_taxonomy'), 10, 3);
// 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, 'save_profile'));
add_action('edit_user_profile_update', array($this, 'save_profile'));
add_action('user_register', array($this, 'save_profile'));
add_filter('sanitize_user', array($this, 'restrict_username'));
add_filter('manage_users_columns', array($this, 'lh_user_taxonomies_add_user_id_column'));
add_action('manage_users_custom_column', array($this, 'lh_user_taxonomies_add_taxonomy_column_content'), 10, 3);
add_action('pre_user_query', array($this, 'user_query'));
}
/**
* This is our way into manipulating registered taxonomies
* 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 registered_taxonomy($taxonomy, $object, $args) {
global $wp_taxonomies;
// Only modify user taxonomies, everything else can stay as is
if($object != 'user') return;
// We're given an array, but expected to work with an object later on
$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_action("manage_{$taxonomy}_custom_column", array($this, 'set_user_column_values'), 10, 3);
// Set the callback to update the count if not already set
if(empty($args->update_count_callback)) {
$args->update_count_callback = array($this, 'update_count');
}
// We're finished, make sure we save out changes
$wp_taxonomies[$taxonomy] = $args;
self::$taxonomies[$taxonomy] = $args;
}
/**
* We need to manually update the number of users for a taxonomy term
*
* @see _update_post_term_count()
* @param Array $terms - List of Term taxonomy IDs
* @param Object $taxonomy - Current taxonomy object of terms
*/
public function update_count($terms, $taxonomy) {
global $wpdb;
foreach((array) $terms as $term) {
$count = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $wpdb->term_relationships, $wpdb->users WHERE $wpdb->term_relationships.object_id = $wpdb->users.ID and $wpdb->term_relationships.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);
}
}
/**
* Add each of the taxonomies to the Users menu
* They will behave in the same was as post taxonomies under the Posts menu item
* Taxonomies will appear in alphabetical order
*/
public function admin_menu() {
// Put the taxonomies in alphabetical order
$taxonomies = self::$taxonomies;
ksort($taxonomies);
foreach($taxonomies as $key=>$taxonomy) {
add_users_page(
$taxonomy->labels->menu_name,
$taxonomy->labels->menu_name,
$taxonomy->cap->manage_terms,
"edit-tags.php?taxonomy={$key}"
);
}
}
/**
* Fix a bug with highlighting the parent menu item
* By default, when on the edit taxonomy page for a user taxonomy, the Posts tab is highlighted
* This will correct that bug
*/
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"
*/
public function set_user_column($columns) {
unset($columns['posts']);
$columns['users'] = __('Users');
return $columns;
}
/**
* Set values for custom columns in user taxonomies
*/
public function set_user_column_values($display, $column, $term_id) {
if('users' === $column) {
$term = get_term($term_id, $_REQUEST['taxonomy']);
echo $term->count;
}
}
private function buildTree( array &$elements, $parentId = 0 ) {
$branch = array();
foreach ($elements as $element) {
if ($element->parent == $parentId) {
$children = $this->buildTree($elements, $element->term_id);
if ($children) {
$element->children = $children;
}
$branch[$element->term_id] = $element;
unset($elements[$element->term_id]);
}
}
return $branch;
}
private function renderTree( $elements, $stack, $user, $key, $input = 'checkbox' ) {
foreach ( $elements as $element ) {
?>
<div>
<input type="<?php echo $input ?>" name="<?php echo $key?>[]" id="<?php echo "{$key}-{$element->slug}"?>" value="<?php echo $element->slug?>" <?php
if ($user->ID){
if (in_array($element->slug, $stack)) {
echo "checked=\"checked\"";
}
}
?> />
<label for="<?php echo "{$key}-{$element->slug}"?>"><?php echo $element->name ?></label>
<?php if( isset( $element->children ) ) {
?><div style="padding-left: 24px;"><?php
$this->renderTree( $element->children, $stack, $user, $key, $input );
?></div><?php
}
?></div><?php
}
}
/**
* Add the taxonomies to the user view/edit screen
*
* @param Object $user - The user of the view/edit screen
*/
public function user_profile($user) {
// Using output buffering as we need to make sure we have something before outputting the header
// But we can't rely on the number of taxonomies, as capabilities may vary
ob_start();
foreach(self::$taxonomies as $key=>$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 = get_terms($key, array('hide_empty'=>false));
$stack = wp_list_pluck( wp_get_object_terms( $user->ID, $key ), 'slug' );
$input_type = ( $taxonomy->single_value ) ? 'radio' : 'checkbox' ;
?>
<table class="form-table">
<tr>
<th><label for=""><?php _e("Select {$taxonomy->labels->singular_name}")?></label></th>
<td>
<?php if(!empty($terms)): ?>
<?php $this->renderTree( $this->buildTree( $terms ), $stack, $user, $key, $input_type ); ?>
<?php else:?>
<?php _e("There are no {$taxonomy->labels->name} available.")?>
<?php endif?>
</td>
</tr>
</table>
<?php endforeach; // Taxonomies
// Output the above if we have anything, with a heading
$output = ob_get_clean();
if(!empty($output)) {
echo '<h3>', __('Taxonomies'), '</h3>';
echo $output;
}
}
/**
* Save the custom user taxonomies when saving a users profile
*
* @param Integer $user_id - The ID of the user to update
*/
public function save_profile($user_id) {
foreach(self::$taxonomies as $key=>$taxonomy) {
// 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;
if (isset($_POST[$key])) {
if (is_array($_POST[$key])){
$term = $_POST[$key];
wp_set_object_terms($user_id, $term, $key, false);
} else {
$term = esc_attr($_POST[$key]);
wp_set_object_terms($user_id, array($term), $key, false);
}
}
// Save the data
clean_object_term_cache($user_id, $key);
}
}
/**
* Usernames can't match any of our user taxonomies
* As otherwise it will cause a URL conflict
* This method prevents that happening
*/
public function restrict_username($username) {
if(isset(self::$taxonomies[$username])) return '';
return $username;
}
/**
* Add columns for columns with
* show_admin_column
*/
public function lh_user_taxonomies_add_user_id_column($columns) {
$args=array(
'object_type' => array('user'),
'show_admin_column' => true
);
$taxonomies = get_taxonomies( $args, "objects");
foreach ($taxonomies as $taxonomy) {
$columns[$taxonomy->name] = $taxonomy->labels->name;
}
return $columns;
}
/**
* Just a private function to
* populate column content
*/
private function lh_user_taxonomies_get_user_taxonomies($user, $taxonomy, $page = null) {
$terms = wp_get_object_terms( $user, $taxonomy);
if(empty($terms)) { return false; }
$in = array();
foreach($terms as $term) {
$href = empty($page) ? add_query_arg(array($taxonomy => $term->slug), admin_url('users.php')) : add_query_arg(array('user-group' => $term->slug), $page);
$in[] = sprintf('%s%s%s', '<a href="'.$href.'" title="'.esc_attr($term->description).'">', $term->name, '</a>');
}
return implode('', $in);
}
/**
* Add the column content
*
*/
public function lh_user_taxonomies_add_taxonomy_column_content($value, $column_name, $user_id) {
if (taxonomy_exists($column_name)) {
return $this->lh_user_taxonomies_get_user_taxonomies($user_id,$column_name);
} else {
return $value;
}
}
/**
* Alters the User query
* to return a different list based on query vars on users.php
*/
public function user_query($Query = '') {
global $pagenow,$wpdb;
if ( $pagenow == 'users.php' ){
$args=array(
'object_type' => array('user'),
'show_admin_column' => true
);
$taxonomies = get_taxonomies( $args, "objects");
foreach ($taxonomies as $taxonomy) {
if(!empty($_GET[$taxonomy->name])) {
$term = get_term_by('slug', esc_attr($_GET[$taxonomy->name]), $taxonomy->name);
$new_ids = get_objects_in_term($term->term_id, $taxonomy->name);
if (!isset($ids) || empty($ids)){
$ids = $new_ids;
} else {
$ids = array_intersect($ids, $new_ids);
}
}
}
if ( isset( $ids ) ){
$ids = implode(',', wp_parse_id_list( $ids ) );
$Query->query_where .= " AND $wpdb->users.ID IN ($ids)";
}
}
}
}
new LH_User_Taxonomies_plugin;