root/tags/2.1.1/wp-includes/category.php

Revision 4849, 9.2 kB (checked in by markjaquith, 2 years ago)

run get_categories filter on cached get_categories hits. fixes #3728

  • Property svn:eol-style set to native
Line 
1 <?php
2
3 function get_all_category_ids() {
4     global $wpdb;
5
6     if ( ! $cat_ids = wp_cache_get('all_category_ids', 'category') ) {
7         $cat_ids = $wpdb->get_col("SELECT cat_ID FROM $wpdb->categories");
8         wp_cache_set('all_category_ids', $cat_ids, 'category');
9     }
10
11     return $cat_ids;
12 }
13
14 function &get_categories($args = '') {
15     global $wpdb, $category_links;
16
17     if ( is_array($args) )
18         $r = &$args;
19     else
20         parse_str($args, $r);
21
22     $defaults = array('type' => 'post', 'child_of' => 0, 'orderby' => 'name', 'order' => 'ASC',
23         'hide_empty' => true, 'include_last_update_time' => false, 'hierarchical' => 1, 'exclude' => '', 'include' => '',
24         'number' => '', 'pad_counts' => false);
25     $r = array_merge($defaults, $r);
26     if ( 'count' == $r['orderby'] )
27         $r['orderby'] = 'category_count';
28     else
29         $r['orderby'] = "cat_" . $r['orderby'];  // restricts order by to cat_ID and cat_name fields
30     $r['number'] = (int) $r['number'];
31     extract($r);
32
33     $key = md5( serialize( $r ) );
34     if ( $cache = wp_cache_get( 'get_categories', 'category' ) )
35         if ( isset( $cache[ $key ] ) )
36             return apply_filters('get_categories', $cache[$key], $r);
37
38     $where = 'cat_ID > 0';
39     $inclusions = '';
40     if ( !empty($include) ) {
41         $child_of = 0; //ignore child_of and exclude params if using include
42         $exclude = '';
43         $incategories = preg_split('/[\s,]+/',$include);
44         if ( count($incategories) ) {
45             foreach ( $incategories as $incat ) {
46                 if (empty($inclusions))
47                     $inclusions = ' AND ( cat_ID = ' . intval($incat) . ' ';
48                 else
49                     $inclusions .= ' OR cat_ID = ' . intval($incat) . ' ';
50             }
51         }
52     }
53     if (!empty($inclusions))
54         $inclusions .= ')';
55     $where .= $inclusions;
56
57     $exclusions = '';
58     if ( !empty($exclude) ) {
59         $excategories = preg_split('/[\s,]+/',$exclude);
60         if ( count($excategories) ) {
61             foreach ( $excategories as $excat ) {
62                 if (empty($exclusions))
63                     $exclusions = ' AND ( cat_ID <> ' . intval($excat) . ' ';
64                 else
65                     $exclusions .= ' AND cat_ID <> ' . intval($excat) . ' ';
66                 // TODO: Exclude children of excluded cats?   Note: children are getting excluded
67             }
68         }
69     }
70     if (!empty($exclusions))
71         $exclusions .= ')';
72     $exclusions = apply_filters('list_cats_exclusions', $exclusions, $r );
73     $where .= $exclusions;
74
75     if ( $hide_empty && !$hierarchical ) {
76         if ( 'link' == $type )
77             $where .= ' AND link_count > 0';
78         else
79             $where .= ' AND category_count > 0';
80     }
81
82     if ( !empty($number) )
83         $number = 'LIMIT ' . $number;
84     else
85         $number = '';
86
87     $categories = $wpdb->get_results("SELECT * FROM $wpdb->categories WHERE $where ORDER BY $orderby $order $number");
88
89     if ( empty($categories) )
90         return array();
91
92     // TODO: Integrate this into the main query.
93     if ( $include_last_update_time ) {
94         $stamps = $wpdb->get_results("SELECT category_id, UNIX_TIMESTAMP( MAX(post_date) ) AS ts FROM $wpdb->posts, $wpdb->post2cat, $wpdb->categories
95                             WHERE post_status = 'publish' AND post_id = ID AND $where GROUP BY category_id");
96         global $cat_stamps;
97         foreach ($stamps as $stamp)
98             $cat_stamps[$stamp->category_id] = $stamp->ts;
99         function stamp_cat($cat) {
100             global $cat_stamps;
101             $cat->last_update_timestamp = $cat_stamps[$cat->cat_ID];
102             return $cat;
103         }
104         $categories = array_map('stamp_cat', $categories);
105         unset($cat_stamps);
106     }
107
108     if ( $child_of || $hierarchical )
109         $categories = & _get_cat_children($child_of, $categories);
110
111     // Update category counts to include children.
112     if ( $pad_counts )
113         _pad_category_counts($type, $categories);
114
115     // Make sure we show empty categories that have children.
116     if ( $hierarchical && $hide_empty ) {
117         foreach ( $categories as $k => $category ) {
118             if ( ! $category->{'link' == $type ? 'link_count' : 'category_count'} ) {
119                 $children = _get_cat_children($category->cat_ID, $categories);
120                 foreach ( $children as $child )
121                     if ( $child->{'link' == $type ? 'link_count' : 'category_count'} )
122                         continue 2;
123
124                 // It really is empty
125                 unset($categories[$k]);
126             }
127         }
128     }
129     reset ( $categories );
130
131     $cache[ $key ] = $categories;
132     wp_cache_set( 'get_categories', $cache, 'category' );
133
134     return apply_filters('get_categories', $categories, $r);
135 }
136
137 // Retrieves category data given a category ID or category object.
138 // Handles category caching.
139 function &get_category(&$category, $output = OBJECT) {
140     global $wpdb;
141
142     if ( empty($category) )
143         return null;
144
145     if ( is_object($category) ) {
146         wp_cache_add($category->cat_ID, $category, 'category');
147         $_category = $category;
148     } else {
149         if ( ! $_category = wp_cache_get($category, 'category') ) {
150             $_category = $wpdb->get_row("SELECT * FROM $wpdb->categories WHERE cat_ID = '$category' LIMIT 1");
151             wp_cache_set($category, $_category, 'category');
152         }
153     }
154
155     $_category = apply_filters('get_category', $_category);
156
157     if ( $output == OBJECT ) {
158         return $_category;
159     } elseif ( $output == ARRAY_A ) {
160         return get_object_vars($_category);
161     } elseif ( $output == ARRAY_N ) {
162         return array_values(get_object_vars($_category));
163     } else {
164         return $_category;
165     }
166 }
167
168 function get_category_by_path($category_path, $full_match = true, $output = OBJECT) {
169     global $wpdb;
170     $category_path = rawurlencode(urldecode($category_path));
171     $category_path = str_replace('%2F', '/', $category_path);
172     $category_path = str_replace('%20', ' ', $category_path);
173     $category_paths = '/' . trim($category_path, '/');
174     $leaf_path  = sanitize_title(basename($category_paths));
175     $category_paths = explode('/', $category_paths);
176     $full_path = '';
177     foreach ( (array) $category_paths as $pathdir )
178         $full_path .= ( $pathdir != '' ? '/' : '' ) . sanitize_title($pathdir);
179
180     $categories = $wpdb->get_results("SELECT cat_ID, category_nicename, category_parent FROM $wpdb->categories WHERE category_nicename = '$leaf_path'");
181
182     if ( empty($categories) )
183         return NULL;
184
185     foreach ($categories as $category) {
186         $path = '/' . $leaf_path;
187         $curcategory = $category;
188         while ( ($curcategory->category_parent != 0) && ($curcategory->category_parent != $curcategory->cat_ID) ) {
189             $curcategory = $wpdb->get_row("SELECT cat_ID, category_nicename, category_parent FROM $wpdb->categories WHERE cat_ID = '$curcategory->category_parent'");
190             $path = '/' . $curcategory->category_nicename . $path;
191         }
192
193         if ( $path == $full_path )
194             return get_category($category->cat_ID, $output);
195     }
196
197     // If full matching is not required, return the first cat that matches the leaf.
198     if ( ! $full_match )
199         return get_category($categories[0]->cat_ID, $output);
200
201     return NULL;
202 }
203
204 // Get the ID of a category from its name
205 function get_cat_ID($cat_name='General') {
206     global $wpdb;
207
208     $cid = $wpdb->get_var("SELECT cat_ID FROM $wpdb->categories WHERE cat_name='$cat_name'");
209
210     return $cid?$cid:1;    // default to cat 1
211 }
212
213 // Deprecate
214 function get_catname($cat_ID) {
215     return get_cat_name($cat_ID);
216 }
217
218 // Get the name of a category from its ID
219 function get_cat_name($cat_id) {
220     $cat_id = (int) $cat_id;
221     $category = &get_category($cat_id);
222     return $category->cat_name;
223 }
224
225 function cat_is_ancestor_of($cat1, $cat2) {
226     if ( is_int($cat1) )
227         $cat1 = & get_category($cat1);
228     if ( is_int($cat2) )
229         $cat2 = & get_category($cat2);
230
231     if ( !$cat1->cat_ID || !$cat2->category_parent )
232         return false;
233
234     if ( $cat2->category_parent == $cat1->cat_ID )
235         return true;
236
237     return cat_is_ancestor_of($cat1, get_category($cat2->parent_category));
238 }
239
240 //
241 // Private
242 //
243
244 function &_get_cat_children($category_id, $categories) {
245     if ( empty($categories) )
246         return array();
247
248     $category_list = array();
249     foreach ( $categories as $category ) {
250         if ( $category->cat_ID == $category_id )
251             continue;
252
253         if ( $category->category_parent == $category_id ) {
254             $category_list[] = $category;
255             if ( $children = _get_cat_children($category->cat_ID, $categories) )
256                 $category_list = array_merge($category_list, $children);
257         }
258     }
259
260     return $category_list;
261 }
262
263 // Recalculates link or post counts by including items from child categories
264 // Assumes all relevant children are already in the $categories argument
265 function _pad_category_counts($type, &$categories) {
266     global $wpdb;
267
268     // Set up some useful arrays
269     foreach ( $categories as $key => $cat ) {
270         $cats[$cat->cat_ID] = & $categories[$key];
271         $cat_IDs[] = $cat->cat_ID;
272     }
273
274     // Get the relevant post2cat or link2cat records and stick them in a lookup table
275     if ( $type == 'post' ) {
276         $results = $wpdb->get_results("SELECT post_id, category_id FROM $wpdb->post2cat LEFT JOIN $wpdb->posts ON post_id = ID WHERE category_id IN (".join(',', $cat_IDs).") AND post_type = 'post' AND post_status = 'publish'");
277         foreach ( $results as $row )
278             ++$cat_items[$row->category_id][$row->post_id];
279     } else {
280         $results = $wpdb->get_results("SELECT $wpdb->link2cat.link_id, category_id FROM $wpdb->link2cat LEFT JOIN $wpdb->links USING (link_id) WHERE category_id IN (".join(',', $cat_IDs).") AND link_visible = 'Y'");
281         foreach ( $results as $row )
282             ++$cat_items[$row->category_id][$row->link_id];
283     }
284
285     // Touch every ancestor's lookup row for each post in each category
286     foreach ( $cat_IDs as $cat_ID ) {
287         $child = $cat_ID;
288         while ( $parent = $cats[$child]->category_parent ) {
289             if ( !empty($cat_items[$cat_ID]) )
290                 foreach ( $cat_items[$cat_ID] as $item_id => $touches )
291                     ++$cat_items[$parent][$item_id];
292             $child = $parent;
293         }
294     }
295
296     // Transfer the touched cells
297     foreach ( (array) $cat_items as $id => $items )
298         if ( isset($cats[$id]) )
299             $cats[$id]->{'link' == $type ? 'link_count' : 'category_count'} = count($items);
300 }
301
302 ?>
303
Note: See TracBrowser for help on using the browser.