summaryrefslogtreecommitdiff
path: root/modules/taxonomy/taxonomy.module
diff options
context:
space:
mode:
authorAngie Byron <webchick@24967.no-reply.drupal.org>2009-03-30 05:18:49 +0000
committerAngie Byron <webchick@24967.no-reply.drupal.org>2009-03-30 05:18:49 +0000
commit9f7aaa2341b914d455949ac5d1044256f25a5856 (patch)
treef43ae6a785787faa00baf3d98b251dbb32c38ca3 /modules/taxonomy/taxonomy.module
parenta0cca9a472b7764f54ad692c8e7943278f09a0be (diff)
downloadbrdo-9f7aaa2341b914d455949ac5d1044256f25a5856.tar.gz
brdo-9f7aaa2341b914d455949ac5d1044256f25a5856.tar.bz2
#351797 by catch: Allow loading multiple vocabularies at once (with tests).
Diffstat (limited to 'modules/taxonomy/taxonomy.module')
-rw-r--r--modules/taxonomy/taxonomy.module187
1 files changed, 139 insertions, 48 deletions
diff --git a/modules/taxonomy/taxonomy.module b/modules/taxonomy/taxonomy.module
index 39ee62af3..96823daa9 100644
--- a/modules/taxonomy/taxonomy.module
+++ b/modules/taxonomy/taxonomy.module
@@ -452,31 +452,9 @@ function taxonomy_form_all($free_tags = 0) {
* @param $type
* If set, return only those vocabularies associated with this node type.
*/
-function taxonomy_get_vocabularies($type = NULL) {
- if ($type) {
- $result = db_query(db_rewrite_sql("SELECT v.vid, v.*, n.type FROM {taxonomy_vocabulary} v LEFT JOIN {taxonomy_vocabulary_node_type} n ON v.vid = n.vid WHERE n.type = '%s' ORDER BY v.weight, v.name", 'v', 'vid'), $type);
- }
- else {
- $result = db_query(db_rewrite_sql('SELECT v.*, n.type FROM {taxonomy_vocabulary} v LEFT JOIN {taxonomy_vocabulary_node_type} n ON v.vid = n.vid ORDER BY v.weight, v.name', 'v', 'vid'));
- }
-
- $vocabularies = array();
- $node_types = array();
- while ($voc = db_fetch_object($result)) {
- // If no node types are associated with a vocabulary, the LEFT JOIN will
- // return a NULL value for type.
- if (isset($voc->type)) {
- $node_types[$voc->vid][$voc->type] = $voc->type;
- unset($voc->type);
- $voc->nodes = $node_types[$voc->vid];
- }
- elseif (!isset($voc->nodes)) {
- $voc->nodes = array();
- }
- $vocabularies[$voc->vid] = $voc;
- }
-
- return $vocabularies;
+function taxonomy_get_vocabularies($type = NULL, $reset = FALSE) {
+ $conditions = !empty($type) ? array('type' => $type) : NULL;
+ return taxonomy_vocabulary_load_multiple(array(), $conditions, $reset);
}
/**
@@ -967,44 +945,157 @@ function taxonomy_get_term_by_name($name) {
}
/**
- * Return the vocabulary object matching a vocabulary ID.
+ * Load multiple taxonomy vocabularies based on certain conditions.
*
- * @param $vid
- * The vocabulary's ID.
+ * This function should be used whenever you need to load more than one
+ * vocabulary from the database. Terms are loaded into memory and will not
+ * require database access if loaded again during the same page request.
*
+ * @param $vids
+ * An array of taxonomy vocabulary IDs.
+ * @param $conditions
+ * An array of conditions to add to the query.
* @param $reset
- * A boolean flag indicating whether to reset the internal cache.
+ * Whether to reset the internal cache.
*
* @return
- * The vocabulary object with all of its metadata, if exists, FALSE otherwise.
- * Results are statically cached.
+ * An array of vocabulary objects, indexed by vid.
*/
-function taxonomy_vocabulary_load($vid, $reset = FALSE) {
- static $vocabularies = array();
+function taxonomy_vocabulary_load_multiple($vids = array(), $conditions = array(), $reset = FALSE) {
+ static $vocabulary_cache = array();
+ // Node type associations are not stored in the vocabulary table, so remove
+ // this from conditions into it's own variable.
+ if (isset($conditions['type'])) {
+ $type = $conditions['type'];
+ unset($conditions['type']);
+ }
if ($reset) {
- unset($vocabularies[$vid]);
+ $vocabulary_cache = array();
+ }
+
+ $vocabularies = array();
+
+ // Create a new variable which is either a prepared version of the $vids
+ // array for later comparison with the term cache, or FALSE if no $vids were
+ // passed. The $vids array is reduced as items are loaded from cache, and we
+ // need to know if it's empty for this reason to avoid querying the database
+ // when all requested items are loaded from cache.
+ $passed_vids = !empty($vids) ? array_flip($vids) : FALSE;
+
+ // Load any available items from the internal cache.
+ if ($vocabulary_cache) {
+ if ($vids) {
+ $vocabularies += array_intersect_key($vocabulary_cache, $passed_vids);
+ // If any items were loaded, remove them from the $vids still to load.
+ $vids = array_keys(array_diff_key($passed_vids, $vocabularies));
+ }
+ // If only conditions is passed, load all items from the cache. Items
+ // which don't match conditions will be removed later.
+ elseif ($conditions) {
+ $vocabularies = $vocabulary_cache;
+ }
}
- if (empty($vocabularies[$vid])) {
- // Initialize so if this vocabulary does not exist, we have
- // that cached, and we will not try to load this later.
- $vocabularies[$vid] = FALSE;
- // Try to load the data and fill up the object.
- $result = db_query('SELECT v.*, n.type FROM {taxonomy_vocabulary} v LEFT JOIN {taxonomy_vocabulary_node_type} n ON v.vid = n.vid WHERE v.vid = %d', $vid);
+ // Remove any loaded terms from the array if they don't match $conditions.
+ if ($conditions || isset($type)) {
+ foreach ($vocabularies as $vocabulary) {
+ $vocabulary_values = (array) $vocabulary;
+ if (array_diff_assoc($conditions, $vocabulary_values)) {
+ unset($vocabularies[$vocabulary->vid]);
+ }
+ if (isset($type) && !in_array($type, $vocabulary->nodes)) {
+ unset($vocabularies[$vocabulary->vid]);
+ }
+ }
+ }
+
+ // Load any remaining vocabularies from the database, this is necessary if
+ // we have $vids still to load, or if no $vids were passed.
+ if ($vids || !$passed_vids) {
+ $query = db_select('taxonomy_vocabulary', 'v');
+ $query->fields('v');
+ $query->addField('n', 'type');
+ $query->orderBy('v.weight');
+ $query->orderBy('v.name');
+
+ if (!empty($type)) {
+ $query->leftJoin('taxonomy_vocabulary_node_type', 'n', 'v.vid = n.vid WHERE n.type = :type', array(':type' => $type));
+ }
+ else {
+ $query->leftJoin('taxonomy_vocabulary_node_type', 'n', 'v.vid = n.vid');
+ }
+
+ // If the $vids array is populated, add those to the query.
+ if ($vids) {
+ $query->condition('v.vid', $vids, 'IN');
+ }
+
+ // If the conditions array is populated, add those to the query.
+ if ($conditions) {
+ foreach ($conditions as $field => $value) {
+ $query->condition('v.' . $field, $value);
+ }
+ }
+ $result = $query->execute();
+
+ $queried_vocabularies = array();
$node_types = array();
- while ($voc = db_fetch_object($result)) {
- if (!empty($voc->type)) {
- $node_types[$voc->type] = $voc->type;
+ foreach ($result as $record) {
+ // If no node types are associated with a vocabulary, the LEFT JOIN will
+ // return a NULL value for type.
+ if (isset($record->type)) {
+ $node_types[$record->vid][$record->type] = $record->type;
+ unset($record->type);
+ $record->nodes = $node_types[$record->vid];
}
- unset($voc->type);
- $voc->nodes = $node_types;
- $vocabularies[$vid] = $voc;
+ elseif (!isset($record->nodes)) {
+ $record->nodes = array();
+ }
+ $queried_vocabularies[$record->vid] = $record;
+ }
+
+ // Invoke hook_taxonomy_vocabulary_load() on the vocabularies loaded from
+ // the database and add them to the static cache.
+ if (!empty($queried_vocabularies)) {
+ foreach (module_implements('taxonomy_vocabulary_load') as $module) {
+ $function = $module . '_taxonomy_vocabulary_load';
+ $function($queried_vocabularies);
+ }
+ $vocabularies += $queried_vocabularies;
+ $vocabulary_cache += $queried_vocabularies;
+ }
+ }
+
+ // Ensure that the returned array is ordered the same as the original $vids
+ // array if this was passed in and remove any invalid vids.
+ if ($passed_vids) {
+ // Remove any invalid vids from the array.
+ $passed_vids = array_intersect_key($passed_vids, $vocabularies);
+ foreach ($vocabularies as $vocabulary) {
+ $passed_vids[$vocabulary->vid] = $vocabulary;
}
+ $vocabularies = $passed_vids;
}
- // Return FALSE if this vocabulary does not exist.
- return !empty($vocabularies[$vid]) ? $vocabularies[$vid] : FALSE;
+ return $vocabularies;
+}
+
+/**
+ * Return the vocabulary object matching a vocabulary ID.
+ *
+ * @param $vid
+ * The vocabulary's ID.
+ *
+ * @param $reset
+ * A boolean flag indicating whether to reset the internal cache.
+ *
+ * @return
+ * The vocabulary object with all of its metadata, if exists, FALSE otherwise.
+ * Results are statically cached.
+ */
+function taxonomy_vocabulary_load($vid, $reset = FALSE) {
+ return reset(taxonomy_vocabulary_load_multiple(array($vid), array(), $reset));
}
/**