Commit 9f7aaa23 authored by webchick's avatar webchick

#351797 by catch: Allow loading multiple vocabularies at once (with tests).

parent a0cca9a4
......@@ -20,8 +20,10 @@
* @param $vocabulary
* A taxonomy vocabulary object.
*/
function hook_taxonomy_vocabulary_load($vocabulary) {
$vocabulary->synonyms = variable_get('taxonomy_' . $vocabulary->vid . '_synonyms', FALSE);
function hook_taxonomy_vocabulary_load($vocabularies) {
foreach ($vocabularies as $vocabulary) {
$vocabulary->synonyms = variable_get('taxonomy_' . $vocabulary->vid . '_synonyms', FALSE);
}
}
/**
......
......@@ -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));
}
/**
......
......@@ -213,7 +213,7 @@ function getInfo() {
* Ensure that the vocabulary static reset works correctly.
*/
function testTaxonomyVocabularyLoadStaticReset() {
$original_vocabulary = taxonomy_vocabulary_load($this->vocabulary->vid);
$original_vocabulary = taxonomy_vocabulary_load($this->vocabulary->vid, TRUE);
$this->assertTrue(is_object($original_vocabulary), t('Vocabulary loaded successfully'));
$this->assertEqual($this->vocabulary->name, $original_vocabulary->name, t('Vocabulary loaded successfully'));
......@@ -233,6 +233,48 @@ function getInfo() {
$vocabularies = taxonomy_get_vocabularies();
$this->assertTrue(!isset($vocabularies[$this->vocabulary->vid]), t('The vocabulary was deleted'));
}
/**
* Tests for loading multiple vocabularies.
*/
function testTaxonomyVocabularyLoadMultiple() {
// Delete any existing vocabularies.
foreach (taxonomy_get_vocabularies() as $vocabulary) {
taxonomy_vocabulary_delete($vocabulary->vid);
}
// Create some vocabularies and assign weights.
$vocabulary1 = $this->createVocabulary();
$vocabulary1->weight = 0;
taxonomy_vocabulary_save($vocabulary1);
$vocabulary2 = $this->createVocabulary();
$vocabulary2->weight = 1;
taxonomy_vocabulary_save($vocabulary2);
$vocabulary3 = $this->createVocabulary();
$vocabulary3->weight = 2;
taxonomy_vocabulary_save($vocabulary3);
// Fetch all of the vocabularies using taxonomy_get_vocabularies().
// Confirm that the vocabularies are ordered by weight.
$vocabularies = taxonomy_get_vocabularies();
$this->assertEqual(array_shift($vocabularies), $vocabulary1, t('Vocabulary was found in the vocabularies array.'));
$this->assertEqual(array_shift($vocabularies), $vocabulary2, t('Vocabulary was found in the vocabularies array.'));
$this->assertEqual(array_shift($vocabularies), $vocabulary3, t('Vocabulary was found in the vocabularies array.'));
// Fetch the vocabularies with taxonomy_vocabulary_load_multiple(), specifying IDs.
// Ensure they are returned in the same order as the original array.
$vocabularies = taxonomy_vocabulary_load_multiple(array($vocabulary3->vid, $vocabulary2->vid, $vocabulary1->vid));
$this->assertEqual(array_shift($vocabularies), $vocabulary3, t('Vocabulary loaded successfully by ID.'));
$this->assertEqual(array_shift($vocabularies), $vocabulary2, t('Vocabulary loaded successfully by ID.'));
$this->assertEqual(array_shift($vocabularies), $vocabulary1, t('Vocabulary loaded successfully by ID.'));
// Fetch vocabulary 1 by name.
$this->assertTrue(current(taxonomy_vocabulary_load_multiple(array(), array('name' => $vocabulary1->name))) == $vocabulary1, t('Vocabulary loaded successfully by name.'));
// Fetch vocabulary 1 by name and ID.
$this->assertTrue(current(taxonomy_vocabulary_load_multiple(array($vocabulary1->vid), array('name' => $vocabulary1->name))) == $vocabulary1, t('Vocabulary loaded successfully by name and ID.'));
}
}
/**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment