diff --git a/core/includes/common.inc b/core/includes/common.inc index 19e0d59..a528edd 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -6420,8 +6420,20 @@ function element_info_property($type, $property_name, $default = NULL) { * Second item for comparison. */ function drupal_sort_weight($a, $b) { - $a_weight = (is_array($a) && isset($a['weight'])) ? $a['weight'] : 0; - $b_weight = (is_array($b) && isset($b['weight'])) ? $b['weight'] : 0; + $a_weight = 0; + if (is_array($a) && isset($a['weight'])) { + $a_weight = $a['weight']; + } + elseif (is_object($a) && isset($a->weight)) { + $a_weight = $a->weight; + } + $b_weight = 0; + if (is_array($b) && isset($b['weight'])) { + $b_weight = $b['weight']; + } + elseif (is_object($b) && isset($b->weight)) { + $b_weight = $b->weight; + } if ($a_weight == $b_weight) { return 0; } diff --git a/core/includes/config.inc b/core/includes/config.inc index 3589aa7..13d236a 100644 --- a/core/includes/config.inc +++ b/core/includes/config.inc @@ -118,3 +118,61 @@ function config_get_storage_names_with_prefix($prefix = '') { function config($name, $class = 'Drupal\Core\Config\DrupalConfig') { return new $class(new DatabaseStorage($name)); } + +function config_load_all($prefix, $load_callback = NULL) { + $objects = array(); + + // Ensure $prefix ends in a period. + if (substr($prefix, -1) !== '.') { + $prefix .= '.'; + } + + // @todo Allow to retrieve the suffix of without prefix. + $list = config_get_storage_names_with_prefix($prefix); + foreach ($list as $config_name) { + $suffix = str_replace($prefix, '', $config_name); + if (isset($load_callback)) { + // @todo Only support classes. + if (strpos($load_callback, '\\') !== FALSE) { + $object = new $load_callback($suffix); + } + else { + $object = $load_callback($suffix); + } + } + else { + $object = $config($config_name)->get(); + } + $objects[$suffix] = $object; + } + return $objects; +} + +function config_save($prefix, $name_key, array $new_config, array $old_config = NULL) { + $name = $new_config[$name_key]; + $config = config($prefix . '.' . $name); + + // Provide the original configuration in $config->original when it is updated. + // If it was explicitly provided (renames...?!), take it. + if (isset($old_config)) { + $config->original = $old_config; + } + // Otherwise, clone the current. + else { + $old_name = $config->get($name_key); + if (isset($old_name)) { + $config->original = clone $config; + } + } + + // Reset the entire configuration object. + $config->clear(); + + // Save the new configuration. + foreach ($new_config as $key => $value) { + $config->set($key, $value); + } + $config->save(); + + return $config; +} diff --git a/core/lib/Drupal/Core/Config/ConfigObjectBase.php b/core/lib/Drupal/Core/Config/ConfigObjectBase.php new file mode 100644 index 0000000..67e103c --- /dev/null +++ b/core/lib/Drupal/Core/Config/ConfigObjectBase.php @@ -0,0 +1,182 @@ +id() === ->bundle()? (hence, removed) + */ +abstract class ConfigObjectBase implements ConfigObjectInterface { + + /** + * @todo The DrupalConfig object representing this? + */ + //protected $config; + + /** + * The language code of the configuration object's default language. + * + * @var string + */ + //public $langcode = LANGUAGE_NOT_SPECIFIED; + + /** + * Boolean indicating whether the configuration object should be forced to be new. + * + * @var bool + */ + protected $enforceIsNew; + + /** + * Constructs a new configuration object. + */ + public function __construct($id, array $values = array()) { + $this->load($id); + // Set initial values. + foreach ($values as $key => $value) { + // Skip keys that do not exist as properties. + if (property_exists($this, $key)) { + $this->$key = $value; + } + } + } + + /** + * Implements ConfigObjectInterface::id(). + */ + public function id() { + return isset($this->id) ? $this->id : NULL; + } + + /** + * Implements ConfigObjectInterface::name(). + */ + public function name() { + return $this->getPrefix() . '.' . $this->id; + } + + /** + * Implements ConfigObjectInterface::isNew(). + */ + public function isNew() { + return !empty($this->enforceIsNew) || !$this->id(); + } + + /** + * Implements ConfigObjectInterface::enforceIsNew(). + */ + public function enforceIsNew($value = TRUE) { + $this->enforceIsNew = $value; + } + + /** + * Implements ConfigObjectInterface::label(). + */ + public function label() { + // Default to the ID (machine name). + // Configuration object implementations containing human-readable names + // likely want to override this. + return $this->id(); + } + + /** + * Implements ConfigObjectInterface::uri(). + */ + public function uri() { + // @todo Check whether this makes sense. + return NULL; + } + + /** + * Implements ConfigObjectInterface::language(). + */ +// public function language() { +// return module_exists('language') ? language_load($this->langcode) : FALSE; +// } + + /** + * Implements ConfigObjectInterface::translations(). + */ +// public function translations() { +// $languages = array(); +// return $languages; +// } + + /** + * Implements ConfigObjectInterface::get(). + */ + public function get($property_name, $langcode = NULL) { + return isset($this->{$property_name}) ? $this->{$property_name} : NULL; + } + + /** + * Implements ConfigObjectInterface::set(). + */ + public function set($property_name, $value, $langcode = NULL) { + $this->{$property_name} = $value; + return $this; + } + + /** + * Implements ConfigObjectInterface::load(). + */ + public function load($id) { + // @todo Vocabulary overrides the id() method. + $this->id = $id; + foreach (config($this->name())->get() as $key => $value) { + $this->set($key, $value); + } + return $this; + } + + /** + * Implements ConfigObjectInterface::save(). + */ + public function save() { + $config = config($this->name()); + + $data = array_diff_key(get_object_vars($this), array( + 'enforceIsNew' => 0, + 'original' => 0, + )); + + // Provide the original configuration in $config->original when it is updated. + // If it was explicitly provided (renames...?!), take it. + // @todo Need $this->idKey to load the actual original in case of renames. + $this->original = new $this($this->id, $config->get()); + + // Save the new configuration. + $config->setData($data)->save(); + + return $this; + } + + /** + * Implements ConfigObjectInterface::delete(). + */ + public function delete() { + if (!$this->isNew()) { + config($this->name())->delete(); + } + } + + /** + * Implements ConfigObjectInterface::createDuplicate(). + */ + public function createDuplicate() { + $duplicate = clone $this; + $duplicate->id = NULL; + return $duplicate; + } +} diff --git a/core/lib/Drupal/Core/Config/ConfigObjectInterface.php b/core/lib/Drupal/Core/Config/ConfigObjectInterface.php new file mode 100644 index 0000000..329ed58 --- /dev/null +++ b/core/lib/Drupal/Core/Config/ConfigObjectInterface.php @@ -0,0 +1,185 @@ +data = $data; + return $this; + } + + /** * Sets value in this config object. * * @param $key @@ -185,9 +196,15 @@ class DrupalConfig { * Unsets value in this config object. * * @param $key - * Name of the key whose value should be unset. + * (optional) Name of the key whose value should be unset. If omitted, all + * keys are unset. */ - public function clear($key) { + public function clear($key = NULL) { + if (!isset($key)) { + $this->data = array(); + return; + } + $parts = explode('.', $key); if (count($parts) == 1) { unset($this->data[$key]); diff --git a/core/modules/entity/tests/entity_crud_hook_test.test b/core/modules/entity/tests/entity_crud_hook_test.test index dd4aa70..c963726 100644 --- a/core/modules/entity/tests/entity_crud_hook_test.test +++ b/core/modules/entity/tests/entity_crud_hook_test.test @@ -6,6 +6,7 @@ */ use Drupal\simpletest\WebTestBase; +use Drupal\taxonomy\Vocabulary; /** * Tests invocation of hooks when performing an action. @@ -247,12 +248,9 @@ class EntityCrudHookTestCase extends WebTestBase { * Tests hook invocations for CRUD operations on taxonomy terms. */ public function testTaxonomyTermHooks() { - $vocabulary = entity_create('taxonomy_vocabulary', array( + $vocabulary = new Vocabulary('test', array( 'name' => 'Test vocabulary', - 'machine_name' => 'test', - 'langcode' => LANGUAGE_NOT_SPECIFIED, - 'description' => NULL, - 'module' => 'entity_crud_hook_test', + 'vid' => 'test', )); taxonomy_vocabulary_save($vocabulary); @@ -307,12 +305,9 @@ class EntityCrudHookTestCase extends WebTestBase { * Tests hook invocations for CRUD operations on taxonomy vocabularies. */ public function testTaxonomyVocabularyHooks() { - $vocabulary = entity_create('taxonomy_vocabulary', array( + $vocabulary = new Vocabulary('test', array( 'name' => 'Test vocabulary', - 'machine_name' => 'test', - 'langcode' => LANGUAGE_NOT_SPECIFIED, - 'description' => NULL, - 'module' => 'entity_crud_hook_test', + 'vid' => 'test', )); $_SESSION['entity_crud_hook_test'] = array(); taxonomy_vocabulary_save($vocabulary); diff --git a/core/modules/field_ui/field_ui.test b/core/modules/field_ui/field_ui.test index c33552c..3cff9dd 100644 --- a/core/modules/field_ui/field_ui.test +++ b/core/modules/field_ui/field_ui.test @@ -7,6 +7,7 @@ use Drupal\node\Node; use Drupal\simpletest\WebTestBase; +use Drupal\taxonomy\Vocabulary; /** * Provides common functionality for the Field UI test classes. @@ -160,21 +161,20 @@ class FieldUIManageFieldsTestCase extends FieldUITestCase { $this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article')); // Create a vocabulary named "Tags". - $vocabulary = entity_create('taxonomy_vocabulary', array( + $vocabulary = new Vocabulary('tags', array( 'name' => 'Tags', - 'machine_name' => 'tags', - 'langcode' => LANGUAGE_NOT_SPECIFIED, + 'vid' => 'tags', )); taxonomy_vocabulary_save($vocabulary); $field = array( - 'field_name' => 'field_' . $vocabulary->machine_name, + 'field_name' => 'field_' . $vocabulary->vid, 'type' => 'taxonomy_term_reference', ); field_create_field($field); $instance = array( - 'field_name' => 'field_' . $vocabulary->machine_name, + 'field_name' => 'field_' . $vocabulary->vid, 'entity_type' => 'node', 'label' => 'Tags', 'bundle' => 'article', @@ -237,8 +237,8 @@ class FieldUIManageFieldsTestCase extends FieldUITestCase { // Assert the field appears in the "add existing field" section for // different entity types; e.g. if a field was added in a node entity, it // should also appear in the 'taxonomy term' entity. - $vocabulary = taxonomy_vocabulary_load(1); - $this->drupalGet('admin/structure/taxonomy/' . $vocabulary->machine_name . '/fields'); + $vocabulary = taxonomy_vocabulary_load('tags'); + $this->drupalGet('admin/structure/taxonomy/' . $vocabulary->vid . '/fields'); $this->assertTrue($this->xpath('//select[@name="fields[_add_existing_field][field_name]"]//option[@value="' . $this->field_name . '"]'), t('Existing field was found in account settings.')); } diff --git a/core/modules/forum/forum.install b/core/modules/forum/forum.install index a16858c..205819f 100644 --- a/core/modules/forum/forum.install +++ b/core/modules/forum/forum.install @@ -5,6 +5,8 @@ * Install, update and uninstall functions for the forum module. */ +use Drupal\taxonomy\Vocabulary; + /** * Implements hook_install(). */ @@ -30,13 +32,12 @@ function forum_enable() { // Create the forum vocabulary if it does not exist. $vocabulary = taxonomy_vocabulary_load(variable_get('forum_nav_vocabulary', 0)); if (!$vocabulary) { - $vocabulary = entity_create('taxonomy_vocabulary', array( + $vocabulary = new Vocabulary('forums', array( 'name' => t('Forums'), - 'machine_name' => 'forums', + 'vid' => 'forums', 'langcode' => language_default()->langcode, 'description' => t('Forum navigation vocabulary'), 'hierarchy' => 1, - 'module' => 'forum', 'weight' => -10, )); taxonomy_vocabulary_save($vocabulary); @@ -51,7 +52,7 @@ function forum_enable() { 'settings' => array( 'allowed_values' => array( array( - 'vocabulary' => $vocabulary->machine_name, + 'vocabulary' => $vocabulary->vid, 'parent' => 0, ), ), diff --git a/core/modules/forum/forum.module b/core/modules/forum/forum.module index 28e7f17..c179d3c 100644 --- a/core/modules/forum/forum.module +++ b/core/modules/forum/forum.module @@ -220,18 +220,7 @@ function forum_menu_local_tasks_alter(&$data, $router_item, $root_path) { function forum_entity_info_alter(&$info) { // Take over URI construction for taxonomy terms that are forums. if ($vid = variable_get('forum_nav_vocabulary', 0)) { - // Within hook_entity_info(), we can't invoke entity_load() as that would - // cause infinite recursion, so we call taxonomy_vocabulary_get_names() - // instead of taxonomy_vocabulary_load(). All we need is the machine name - // of $vid, so retrieving and iterating all the vocabulary names is somewhat - // inefficient, but entity info is cached across page requests, and an - // iteration of all vocabularies once per cache clearing isn't a big deal, - // and is done as part of taxonomy_entity_info() anyway. - foreach (taxonomy_vocabulary_get_names() as $machine_name => $vocabulary) { - if ($vid == $vocabulary->vid) { - $info['taxonomy_term']['bundles'][$machine_name]['uri callback'] = 'forum_uri'; - } - } + $info['taxonomy_term']['bundles'][$vid]['uri callback'] = 'forum_uri'; } } diff --git a/core/modules/forum/forum.test b/core/modules/forum/forum.test index 4561092..6c6ba45 100644 --- a/core/modules/forum/forum.test +++ b/core/modules/forum/forum.test @@ -7,6 +7,7 @@ use Drupal\node\Node; use Drupal\simpletest\WebTestBase; +use Drupal\taxonomy\Vocabulary; class ForumTestCase extends WebTestBase { protected $admin_user; @@ -265,13 +266,10 @@ class ForumTestCase extends WebTestBase { // Create a default vocabulary named "Tags". $description = 'Use tags to group articles on similar topics into categories.'; - $help = 'Enter a comma-separated list of words to describe your content.'; - $vocabulary = entity_create('taxonomy_vocabulary', array( + $vocabulary = new Vocabulary('tags', array( 'name' => 'Tags', 'description' => $description, - 'machine_name' => 'tags', - 'langcode' => language_default()->langcode, - 'help' => $help, + 'vid' => 'tags', )); taxonomy_vocabulary_save($vocabulary); // Test tags vocabulary form is not affected. @@ -301,16 +299,15 @@ class ForumTestCase extends WebTestBase { $edit = array( 'name' => $title, 'description' => $description, - 'machine_name' => drupal_strtolower(drupal_substr($this->randomName(), 3, 9)), + 'vid' => drupal_strtolower(drupal_substr($this->randomName(), 3, 9)), ); // Edit the vocabulary. - $this->drupalPost('admin/structure/taxonomy/' . $original_settings->machine_name . '/edit', $edit, t('Save')); + $this->drupalPost('admin/structure/taxonomy/' . $original_settings->vid . '/edit', $edit, t('Save')); $this->assertResponse(200); $this->assertRaw(t('Updated vocabulary %name.', array('%name' => $title)), t('Vocabulary was edited')); // Grab the newly edited vocabulary. - entity_get_controller('taxonomy_vocabulary')->resetCache(); $current_settings = taxonomy_vocabulary_load($vid); // Make sure we actually edited the vocabulary properly. @@ -319,7 +316,6 @@ class ForumTestCase extends WebTestBase { // Restore the original vocabulary. taxonomy_vocabulary_save($original_settings); - drupal_static_reset('taxonomy_vocabulary_load'); $current_settings = taxonomy_vocabulary_load($vid); $this->assertEqual($current_settings->name, $original_settings->name, 'The original vocabulary settings were restored'); } diff --git a/core/modules/image/image.module b/core/modules/image/image.module index 3edf83c..04211e6 100644 --- a/core/modules/image/image.module +++ b/core/modules/image/image.module @@ -502,32 +502,7 @@ function image_path_flush($path) { * @see image_style_load() */ function image_styles() { - // @todo Configuration must not be statically cached nor cache-system cached. - // However, there's a drupal_alter() involved here. - -// $styles = &drupal_static(__FUNCTION__); -// -// // Grab from cache or build the array. -// if (!isset($styles)) { -// if ($cache = cache()->get('image_styles')) { -// $styles = $cache->data; -// } -// else { - $styles = array(); - - // Select the styles we have configured. - $configured_styles = config_get_storage_names_with_prefix('image.style'); - foreach ($configured_styles as $config_name) { - // @todo Allow to retrieve the name without prefix only. - $style = image_style_load(str_replace('image.style.', '', $config_name)); - $styles[$style['name']] = $style; - } - drupal_alter('image_styles', $styles); -// cache()->set('image_styles', $styles); -// } -// } - - return $styles; + return config_load_all('image.style', 'image_style_load'); } /** @@ -567,24 +542,19 @@ function image_style_load($name) { /** * Save an image style. * - * @param style + * @param array $style * An image style array. + * * @return * An image style array. */ function image_style_save($style) { - $config = config('image.style.' . $style['name']); - $config->set('name', $style['name']); - if (isset($style['effects'])) { - $config->set('effects', $style['effects']); + if (!isset($style['effects'])) { + $style['effects'] = array(); } - else { - $config->set('effects', array()); - } - $config->save(); - // @todo is_new must only be set when the configuration object did not exist - // yet. - $style['is_new'] = TRUE; + $config = config_save('image.style', 'name', $style); + + $style['is_new'] = !isset($config->original); // Let other modules update as necessary on save. module_invoke_all('image_style_save', $style); diff --git a/core/modules/path/path.test b/core/modules/path/path.test index c742ad5..a03d496 100644 --- a/core/modules/path/path.test +++ b/core/modules/path/path.test @@ -6,6 +6,7 @@ */ use Drupal\simpletest\WebTestBase; +use Drupal\taxonomy\Vocabulary; /** * Provides a base class for testing the Path module. @@ -244,9 +245,9 @@ class PathTaxonomyTermTestCase extends PathTestCase { parent::setUp(array('taxonomy')); // Create a Tags vocabulary for the Article node type. - $vocabulary = entity_create('taxonomy_vocabulary', array( + $vocabulary = new Vocabulary('tags', array( 'name' => t('Tags'), - 'machine_name' => 'tags', + 'vid' => 'tags', )); $vocabulary->save(); @@ -260,13 +261,13 @@ class PathTaxonomyTermTestCase extends PathTestCase { */ function testTermAlias() { // Create a term in the default 'Tags' vocabulary with URL alias. - $vocabulary = taxonomy_vocabulary_load(1); + $vocabulary = taxonomy_vocabulary_load('tags'); $description = $this->randomName();; $edit = array(); $edit['name'] = $this->randomName(); $edit['description[value]'] = $description; $edit['path[alias]'] = $this->randomName(); - $this->drupalPost('admin/structure/taxonomy/' . $vocabulary->machine_name . '/add', $edit, t('Save')); + $this->drupalPost('admin/structure/taxonomy/' . $vocabulary->vid . '/add', $edit, t('Save')); // Confirm that the alias works. $this->drupalGet($edit['path[alias]']); diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Term.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Term.php index 323d0dd..cebc676 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Term.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Term.php @@ -74,16 +74,6 @@ class Term extends Entity { public $parent; /** - * The machine name of the vocabulary the term is assigned to. - * - * If not given, this value will be set automatically by loading the - * vocabulary based on the $entity->vid property. - * - * @var string - */ - public $vocabulary_machine_name; - - /** * Implements Drupal\entity\EntityInterface::id(). */ public function id() { @@ -94,6 +84,6 @@ class Term extends Entity { * Implements Drupal\entity\EntityInterface::bundle(). */ public function bundle() { - return $this->vocabulary_machine_name; + return $this->vid; } } diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/TermStorageController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/TermStorageController.php index 5f511be..0805e43 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/TermStorageController.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/TermStorageController.php @@ -24,14 +24,6 @@ class TermStorageController extends EntityDatabaseStorageController { */ public function create(array $values) { $entity = parent::create($values); - // Ensure the vocabulary machine name is initialized as it is used as the - // bundle key. - // @todo Move to Term::bundle() once field API has been converted - // to make use of it. - if (!isset($entity->vocabulary_machine_name)) { - $vocabulary = taxonomy_vocabulary_load($entity->vid); - $entity->vocabulary_machine_name = $vocabulary->machine_name; - } // Save new terms with no parents by default. if (!isset($entity->parent)) { $entity->parent = array(0); @@ -56,9 +48,6 @@ class TermStorageController extends EntityDatabaseStorageController { } } } - // Add the machine name field from the {taxonomy_vocabulary} table. - $query->innerJoin('taxonomy_vocabulary', 'v', 'base.vid = v.vid'); - $query->addField('v', 'machine_name', 'vocabulary_machine_name'); return $query; } diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Vocabulary.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Vocabulary.php index 0305f77..7a87fd9 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Vocabulary.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Vocabulary.php @@ -7,17 +7,17 @@ namespace Drupal\taxonomy; -use Drupal\entity\Entity; +use Drupal\Core\Config\ConfigObjectBase; /** - * Defines the taxonomy vocabulary entity. + * Defines the taxonomy vocabulary configuration object. */ -class Vocabulary extends Entity { +class Vocabulary extends ConfigObjectBase { /** - * The taxonomy vocabulary ID. + * The vocabulary machine name. * - * @var integer + * @var string */ public $vid; @@ -29,13 +29,6 @@ class Vocabulary extends Entity { public $name; /** - * The vocabulary machine name. - * - * @var string - */ - public $machine_name; - - /** * Description of the vocabulary. * * @var string @@ -62,9 +55,23 @@ class Vocabulary extends Entity { public $weight = 0; /** - * Implements Drupal\entity\EntityInterface::id(). + * Implements Drupal\Core\Config\ConfigObjectInterface::getPrefix(). + */ + public function getPrefix() { + return 'taxonomy.vocabulary'; + } + + /** + * Implements Drupal\Core\Config\ConfigObjectInterface::id(). */ public function id() { return $this->vid; } + + /** + * Implements Drupal\Core\Config\ConfigObjectInterface::label(). + */ + public function label() { + return $this->name; + } } diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyStorageController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyStorageController.php deleted file mode 100644 index 8d64467..0000000 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyStorageController.php +++ /dev/null @@ -1,89 +0,0 @@ -addTag('translatable'); - $query->orderBy('base.weight'); - $query->orderBy('base.name'); - return $query; - } - - /** - * Overrides Drupal\entity\EntityDatabaseStorageController::postSave(). - */ - protected function postSave(EntityInterface $entity, $update) { - if (!$update) { - field_attach_create_bundle('taxonomy_term', $entity->machine_name); - } - elseif ($entity->original->machine_name != $entity->machine_name) { - field_attach_rename_bundle('taxonomy_term', $entity->original->machine_name, $entity->machine_name); - } - } - - /** - * Overrides Drupal\entity\EntityDatabaseStorageController::preDelete(). - */ - protected function preDelete($entities) { - // Only load terms without a parent, child terms will get deleted too. - $tids = db_query('SELECT t.tid FROM {taxonomy_term_data} t INNER JOIN {taxonomy_term_hierarchy} th ON th.tid = t.tid WHERE t.vid IN (:vids) AND th.parent = 0', array(':vids' => array_keys($entities)))->fetchCol(); - taxonomy_term_delete_multiple($tids); - } - - /** - * Overrides Drupal\entity\EntityDatabaseStorageController::postDelete(). - */ - protected function postDelete($entities) { - // Load all Taxonomy module fields and delete those which use only this - // vocabulary. - $taxonomy_fields = field_read_fields(array('module' => 'taxonomy')); - foreach ($taxonomy_fields as $field_name => $taxonomy_field) { - $modified_field = FALSE; - // Term reference fields may reference terms from more than one - // vocabulary. - foreach ($taxonomy_field['settings']['allowed_values'] as $key => $allowed_value) { - foreach ($entities as $vocabulary) { - if ($allowed_value['vocabulary'] == $vocabulary->machine_name) { - unset($taxonomy_field['settings']['allowed_values'][$key]); - $modified_field = TRUE; - } - } - } - if ($modified_field) { - if (empty($taxonomy_field['settings']['allowed_values'])) { - field_delete_field($field_name); - } - else { - // Update the field definition with the new allowed values. - field_update_field($taxonomy_field); - } - } - } - } - - /** - * Implements Drupal\entity\DrupalEntityControllerInterface::resetCache(). - */ - public function resetCache(array $ids = NULL) { - drupal_static_reset('taxonomy_vocabulary_get_names'); - parent::resetCache($ids); - cache_clear_all(); - } -} diff --git a/core/modules/taxonomy/taxonomy.admin.inc b/core/modules/taxonomy/taxonomy.admin.inc index db83d84..45380c2 100644 --- a/core/modules/taxonomy/taxonomy.admin.inc +++ b/core/modules/taxonomy/taxonomy.admin.inc @@ -16,7 +16,7 @@ use Drupal\taxonomy\Vocabulary; * @see theme_taxonomy_overview_vocabularies() */ function taxonomy_overview_vocabularies($form) { - $vocabularies = taxonomy_vocabulary_load_multiple(FALSE); + $vocabularies = taxonomy_vocabulary_load_all(); $form['#tree'] = TRUE; foreach ($vocabularies as $vocabulary) { $form[$vocabulary->vid]['#vocabulary'] = $vocabulary; @@ -28,9 +28,9 @@ function taxonomy_overview_vocabularies($form) { '#delta' => 10, '#default_value' => $vocabulary->weight, ); - $form[$vocabulary->vid]['edit'] = array('#type' => 'link', '#title' => t('edit vocabulary'), '#href' => "admin/structure/taxonomy/$vocabulary->machine_name/edit"); - $form[$vocabulary->vid]['list'] = array('#type' => 'link', '#title' => t('list terms'), '#href' => "admin/structure/taxonomy/$vocabulary->machine_name"); - $form[$vocabulary->vid]['add'] = array('#type' => 'link', '#title' => t('add terms'), '#href' => "admin/structure/taxonomy/$vocabulary->machine_name/add"); + $form[$vocabulary->vid]['edit'] = array('#type' => 'link', '#title' => t('edit vocabulary'), '#href' => "admin/structure/taxonomy/$vocabulary->vid/edit"); + $form[$vocabulary->vid]['list'] = array('#type' => 'link', '#title' => t('list terms'), '#href' => "admin/structure/taxonomy/$vocabulary->vid"); + $form[$vocabulary->vid]['add'] = array('#type' => 'link', '#title' => t('add terms'), '#href' => "admin/structure/taxonomy/$vocabulary->vid/add"); } // Only make this form include a submit button and weight if more than one @@ -51,8 +51,10 @@ function taxonomy_overview_vocabularies($form) { * @see taxonomy_overview_vocabularies() */ function taxonomy_overview_vocabularies_submit($form, &$form_state) { + form_state_values_clean($form_state); + foreach ($form_state['values'] as $vid => $vocabulary) { - if (is_numeric($vid) && $form[$vid]['#vocabulary']->weight != $form_state['values'][$vid]['weight']) { + if (isset($form[$vid]['#vocabulary']) && $form[$vid]['#vocabulary']->weight != $form_state['values'][$vid]['weight']) { $form[$vid]['#vocabulary']->weight = $form_state['values'][$vid]['weight']; taxonomy_vocabulary_save($form[$vid]['#vocabulary']); } @@ -117,9 +119,9 @@ function taxonomy_form_vocabulary($form, &$form_state, Vocabulary $vocabulary = // during form building and processing. During a rebuild, use what is in the // form state. if (!isset($form_state['vocabulary'])) { - // Create a new Vocabulary entity for the add form. + // Create new configuration data for the add form. if (!isset($vocabulary)) { - $vocabulary = entity_create('taxonomy_vocabulary', array( + $vocabulary = new Vocabulary(NULL, array( // Default the new vocabulary to the site's default language. This is // the most likely default value until we have better flexible settings. // @todo See http://drupal.org/node/258785 and followups. @@ -147,12 +149,12 @@ function taxonomy_form_vocabulary($form, &$form_state, Vocabulary $vocabulary = '#maxlength' => 255, '#required' => TRUE, ); - $form['machine_name'] = array( + $form['vid'] = array( '#type' => 'machine_name', - '#default_value' => $vocabulary->machine_name, + '#default_value' => $vocabulary->vid, '#maxlength' => 255, '#machine_name' => array( - 'exists' => 'taxonomy_vocabulary_machine_name_load', + 'exists' => 'taxonomy_vocabulary_load', ), ); $form['description'] = array( @@ -164,7 +166,11 @@ function taxonomy_form_vocabulary($form, &$form_state, Vocabulary $vocabulary = // vocabulary form and standardizes the term form. $form['hierarchy'] = array( '#type' => 'value', - '#value' => '0', + '#value' => $vocabulary->hierarchy, + ); + $form['weight'] = array( + '#type' => 'value', + '#value' => $vocabulary->weight, ); $form['actions'] = array('#type' => 'actions'); @@ -189,14 +195,10 @@ function taxonomy_form_vocabulary($form, &$form_state, Vocabulary $vocabulary = * @see taxonomy_form_vocabulary_submit() */ function taxonomy_form_vocabulary_validate($form, &$form_state) { - // During the deletion there is no 'machine_name' key - if (isset($form_state['values']['machine_name'])) { - // Do not allow machine names to conflict with taxonomy path arguments. - $machine_name = $form_state['values']['machine_name']; - $disallowed = array('add', 'list'); - if (in_array($machine_name, $disallowed)) { - form_set_error('machine_name', t('The machine-readable name cannot be "add" or "list".')); - } + // Do not allow machine names to conflict with taxonomy path arguments. + $disallowed = array('add', 'list'); + if (in_array($form_state['values']['vid'], $disallowed)) { + form_set_error('vid', t('The machine-readable name cannot be "add" or "list".')); } } @@ -214,24 +216,22 @@ function taxonomy_form_vocabulary_submit($form, &$form_state) { return; } - $vocabulary = $form_state['vocabulary']; - entity_form_submit_build_entity('taxonomy_vocabulary', $vocabulary, $form, $form_state); + form_state_values_clean($form_state); + $vocabulary = new Vocabulary($form_state['values']['vid'], $form_state['values']); // Prevent leading and trailing spaces in vocabulary names. $vocabulary->name = trim($vocabulary->name); - switch (taxonomy_vocabulary_save($vocabulary)) { - case SAVED_NEW: + taxonomy_vocabulary_save($vocabulary); + if (!isset($vocabulary->original)) { drupal_set_message(t('Created new vocabulary %name.', array('%name' => $vocabulary->name))); - watchdog('taxonomy', 'Created new vocabulary %name.', array('%name' => $vocabulary->name), WATCHDOG_NOTICE, l(t('edit'), 'admin/structure/taxonomy/' . $vocabulary->machine_name . '/edit')); - $form_state['redirect'] = 'admin/structure/taxonomy/' . $vocabulary->machine_name; - break; - - case SAVED_UPDATED: + watchdog('taxonomy', 'Created new vocabulary %name.', array('%name' => $vocabulary->name), WATCHDOG_NOTICE, l(t('edit'), 'admin/structure/taxonomy/' . $vocabulary->vid . '/edit')); + $form_state['redirect'] = 'admin/structure/taxonomy/' . $vocabulary->vid; + } + else { drupal_set_message(t('Updated vocabulary %name.', array('%name' => $vocabulary->name))); - watchdog('taxonomy', 'Updated vocabulary %name.', array('%name' => $vocabulary->name), WATCHDOG_NOTICE, l(t('edit'), 'admin/structure/taxonomy/' . $vocabulary->machine_name . '/edit')); + watchdog('taxonomy', 'Updated vocabulary %name.', array('%name' => $vocabulary->name), WATCHDOG_NOTICE, l(t('edit'), 'admin/structure/taxonomy/' . $vocabulary->vid . '/edit')); $form_state['redirect'] = 'admin/structure/taxonomy'; - break; } $form_state['values']['vid'] = $vocabulary->vid; @@ -413,7 +413,7 @@ function taxonomy_overview_terms($form, &$form_state, Vocabulary $vocabulary) { $form['#page_entries'] = $page_entries; $form['#back_step'] = $back_step; $form['#forward_step'] = $forward_step; - $form['#empty_text'] = t('No terms available. Add term.', array('@link' => url('admin/structure/taxonomy/' . $vocabulary->machine_name . '/add'))); + $form['#empty_text'] = t('No terms available. Add term.', array('@link' => url('admin/structure/taxonomy/' . $vocabulary->vid . '/add'))); if ($vocabulary->hierarchy != TAXONOMY_HIERARCHY_MULTIPLE && count($tree) > 1) { $form['actions'] = array('#type' => 'actions', '#tree' => FALSE); @@ -665,7 +665,6 @@ function taxonomy_form_term($form, &$form_state, Term $term = NULL, Vocabulary $ if (!isset($term)) { $term = entity_create('taxonomy_term', array( 'vid' => $vocabulary->vid, - 'vocabulary_machine_name' => $vocabulary->machine_name, // Default the new vocabulary to the site's default language. This is // the most likely default value until we have better flexible settings. // @todo See http://drupal.org/node/258785 and followups. @@ -705,9 +704,9 @@ function taxonomy_form_term($form, &$form_state, Term $term = NULL, Vocabulary $ '#weight' => 0, ); - $form['vocabulary_machine_name'] = array( + $form['vid'] = array( '#type' => 'value', - '#value' => isset($term->vocabulary_machine_name) ? $term->vocabulary_machine_name : $vocabulary->name, + '#value' => isset($term->vid) ? $term->vid: $vocabulary->vid, ); field_attach_form('taxonomy_term', $term, $form, $form_state); @@ -900,7 +899,7 @@ function taxonomy_term_confirm_delete($form, &$form_state, $term) { $form['#vocabulary'] = taxonomy_vocabulary_load($term->vid);; $form['type'] = array('#type' => 'value', '#value' => 'term'); $form['name'] = array('#type' => 'value', '#value' => $term->name); - $form['vocabulary_machine_name'] = array('#type' => 'value', '#value' => $term->vocabulary_machine_name); + $form['vid'] = array('#type' => 'value', '#value' => $term->vid); $form['delete'] = array('#type' => 'value', '#value' => TRUE); return confirm_form($form, t('Are you sure you want to delete the term %title?', @@ -979,13 +978,12 @@ function taxonomy_vocabulary_confirm_reset_alphabetical($form, &$form_state, $vi $form['type'] = array('#type' => 'value', '#value' => 'vocabulary'); $form['vid'] = array('#type' => 'value', '#value' => $vid); - $form['machine_name'] = array('#type' => 'value', '#value' => $vocabulary->machine_name); $form['name'] = array('#type' => 'value', '#value' => $vocabulary->name); $form['reset_alphabetical'] = array('#type' => 'value', '#value' => TRUE); return confirm_form($form, t('Are you sure you want to reset the vocabulary %title to alphabetical order?', array('%title' => $vocabulary->name)), - 'admin/structure/taxonomy/' . $vocabulary->machine_name, + 'admin/structure/taxonomy/' . $vocabulary->vid, t('Resetting a vocabulary will discard all custom ordering and sort items alphabetically.'), t('Reset to alphabetical'), t('Cancel')); @@ -1003,5 +1001,5 @@ function taxonomy_vocabulary_confirm_reset_alphabetical_submit($form, &$form_sta ->execute(); drupal_set_message(t('Reset vocabulary %name to alphabetical order.', array('%name' => $form_state['values']['name']))); watchdog('taxonomy', 'Reset vocabulary %name to alphabetical order.', array('%name' => $form_state['values']['name']), WATCHDOG_NOTICE); - $form_state['redirect'] = 'admin/structure/taxonomy/' . $form_state['values']['machine_name']; + $form_state['redirect'] = 'admin/structure/taxonomy/' . $form_state['values']['vid']; } diff --git a/core/modules/taxonomy/taxonomy.api.php b/core/modules/taxonomy/taxonomy.api.php index 5f053fb..3ec94cf 100644 --- a/core/modules/taxonomy/taxonomy.api.php +++ b/core/modules/taxonomy/taxonomy.api.php @@ -11,22 +11,6 @@ */ /** - * Act on taxonomy vocabularies when loaded. - * - * Modules implementing this hook can act on the vocabulary objects before they - * are returned by taxonomy_vocabulary_load_multiple(). - * - * @param array $vocabularies - * An array of taxonomy vocabulary entities. - */ -function hook_taxonomy_vocabulary_load(array $vocabularies) { - foreach ($vocabularies as $vocabulary) { - $vocabulary->synonyms = variable_get('taxonomy_' . $vocabulary->vid . '_synonyms', FALSE); - } -} - - -/** * Act on taxonomy vocabularies before they are saved. * * Modules implementing this hook can act on the vocabulary object before it is diff --git a/core/modules/taxonomy/taxonomy.install b/core/modules/taxonomy/taxonomy.install index 14b6956..1ac97db 100644 --- a/core/modules/taxonomy/taxonomy.install +++ b/core/modules/taxonomy/taxonomy.install @@ -13,7 +13,7 @@ function taxonomy_uninstall() { variable_del('taxonomy_override_selector'); variable_del('taxonomy_terms_per_page_admin'); // Remove taxonomy_term bundles. - $vocabularies = db_query("SELECT machine_name FROM {taxonomy_vocabulary}")->fetchCol(); + $vocabularies = config_load_all('taxonomy.vocabulary', 'Drupal\taxonomy\Vocabulary'); foreach ($vocabularies as $vocabulary) { field_attach_delete_bundle('taxonomy_term', $vocabulary); } @@ -33,11 +33,10 @@ function taxonomy_schema() { 'description' => 'Primary Key: Unique term ID.', ), 'vid' => array( - 'type' => 'int', - 'unsigned' => TRUE, + 'type' => 'varchar', + 'length' => 255, 'not null' => TRUE, - 'default' => 0, - 'description' => 'The {taxonomy_vocabulary}.vid of the vocabulary to which the term is assigned.', + 'description' => 'The machine name of vocabulary to which the term is assigned.', ), 'langcode' => array( 'description' => 'The {language}.langcode of this term.', @@ -75,12 +74,6 @@ function taxonomy_schema() { ), ), 'primary key' => array('tid'), - 'foreign keys' => array( - 'vocabulary' => array( - 'table' => 'taxonomy_vocabulary', - 'columns' => array('vid' => 'vid'), - ), - ), 'indexes' => array( 'taxonomy_tree' => array('vid', 'weight', 'name'), 'vid_name' => array('vid', 'name'), @@ -118,68 +111,6 @@ function taxonomy_schema() { 'primary key' => array('tid', 'parent'), ); - $schema['taxonomy_vocabulary'] = array( - 'description' => 'Stores vocabulary information.', - 'fields' => array( - 'vid' => array( - 'type' => 'serial', - 'unsigned' => TRUE, - 'not null' => TRUE, - 'description' => 'Primary Key: Unique vocabulary ID.', - ), - 'langcode' => array( - 'description' => 'The {language}.langcode of this vocabulary.', - 'type' => 'varchar', - 'length' => 12, - 'not null' => TRUE, - 'default' => '', - ), - 'name' => array( - 'type' => 'varchar', - 'length' => 255, - 'not null' => TRUE, - 'default' => '', - 'description' => 'Name of the vocabulary.', - 'translatable' => TRUE, - ), - 'machine_name' => array( - 'type' => 'varchar', - 'length' => 255, - 'not null' => TRUE, - 'default' => '', - 'description' => 'The vocabulary machine name.', - ), - 'description' => array( - 'type' => 'text', - 'not null' => FALSE, - 'size' => 'big', - 'description' => 'Description of the vocabulary.', - 'translatable' => TRUE, - ), - 'hierarchy' => array( - 'type' => 'int', - 'unsigned' => TRUE, - 'not null' => TRUE, - 'default' => 0, - 'size' => 'tiny', - 'description' => 'The type of hierarchy allowed within the vocabulary. (0 = disabled, 1 = single, 2 = multiple)', - ), - 'weight' => array( - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - 'description' => 'The weight of this vocabulary in relation to other vocabularies.', - ), - ), - 'primary key' => array('vid'), - 'indexes' => array( - 'list' => array('weight', 'name'), - ), - 'unique keys' => array( - 'machine_name' => array('machine_name'), - ), - ); - $schema['taxonomy_index'] = array( 'description' => 'Maintains denormalized information about node/term relationships.', 'fields' => array( @@ -255,13 +186,6 @@ function taxonomy_field_schema($field) { } /** - * Remove the {taxonomy_vocabulary}.module field. - */ -function taxonomy_update_8000() { - db_drop_field('taxonomy_vocabulary', 'module'); -} - -/** * Adds langcode field to {taxonomy_term_data} and {taxonomy_vocabulary}. * * @see http://drupal.org/node/1454538 @@ -269,7 +193,6 @@ function taxonomy_update_8000() { function taxonomy_update_8001() { $descriptions = array( 'taxonomy_term_data' => 'The {language}.langcode of this term.', - 'taxonomy_vocabulary' => 'The {language}.langcode of this vocabulary.', ); foreach ($descriptions as $table => $description) { $langcode_field = array( @@ -300,3 +223,31 @@ function taxonomy_update_8001() { } } } + +/** + * Convert taxonomy vocabularies into configuration. + */ +function taxonomy_update_8002() { + $result = db_query('SELECT * FROM {taxonomy_vocabulary}'); + foreach ($result as $vocabulary) { + // @todo Prefer machine name over vid? + // All field bundles are based on the machine_name already. The parallel + // serial vid shouldn't have existed in the first place. + // Can there actually be vocabularies without a machine_name? + $name = (!empty($vocabulary->machine_name) ? $vocabulary->machine_name : $vocabulary->vid); + $config = config('taxonomy.vocabulary.' . $name); + $config->set('vid', $name); + // If a Drupal 7 contrib module already added a langcode field to support + // internationalization, keep it, but standardize the specification. + // @see taxonomy_update_8001() + $config->set('langcode', isset($vocabulary->langcode) ? $vocabulary->langcode : language_default()->langcode); + $config->set('name', $vocabulary->name); + $config->set('description', $vocabulary->description); + $config->set('hierarchy', $vocabulary->hierarchy); + $config->set('weight', $vocabulary->weight); + $config->save(); + } + // Delete the database table. + db_drop_table('taxonomy_vocabulary'); +} + diff --git a/core/modules/taxonomy/taxonomy.module b/core/modules/taxonomy/taxonomy.module index 7fdb8a2..2a02f69 100644 --- a/core/modules/taxonomy/taxonomy.module +++ b/core/modules/taxonomy/taxonomy.module @@ -68,7 +68,7 @@ function taxonomy_help($path, $arg) { $output = '

' . t('Taxonomy is for categorizing content. Terms are grouped into vocabularies. For example, a vocabulary called "Fruit" would contain the terms "Apple" and "Banana".') . '

'; return $output; case 'admin/structure/taxonomy/%': - $vocabulary = taxonomy_vocabulary_machine_name_load($arg[3]); + $vocabulary = taxonomy_vocabulary_load($arg[3]); switch ($vocabulary->hierarchy) { case TAXONOMY_HIERARCHY_DISABLED: return '

' . t('You can reorganize the terms in %capital_name using their drag-and-drop handles, and group terms under a parent term by sliding them under and to the right of the parent.', array('%capital_name' => drupal_ucfirst($vocabulary->name), '%name' => $vocabulary->name)) . '

'; @@ -89,7 +89,7 @@ function taxonomy_permission() { 'title' => t('Administer vocabularies and terms'), ), ); - foreach (taxonomy_vocabulary_load_multiple(FALSE) as $vocabulary) { + foreach (taxonomy_vocabulary_load_all() as $vocabulary) { $permissions += array( 'edit terms in ' . $vocabulary->vid => array( 'title' => t('Edit terms in %vocabulary', array('%vocabulary' => $vocabulary->name)), @@ -118,11 +118,11 @@ function taxonomy_entity_info() { 'fieldable' => TRUE, 'entity keys' => array( 'id' => 'tid', - 'bundle' => 'vocabulary_machine_name', + 'bundle' => 'vid', 'label' => 'name', ), 'bundle keys' => array( - 'bundle' => 'machine_name', + 'bundle' => 'vid', ), 'bundles' => array(), 'view modes' => array( @@ -134,28 +134,17 @@ function taxonomy_entity_info() { ), ), ); - foreach (taxonomy_vocabulary_get_names() as $machine_name => $vocabulary) { - $return['taxonomy_term']['bundles'][$machine_name] = array( + foreach (taxonomy_vocabulary_load_all() as $name => $vocabulary) { + $return['taxonomy_term']['bundles'][$name] = array( 'label' => $vocabulary->name, 'admin' => array( - 'path' => 'admin/structure/taxonomy/%taxonomy_vocabulary_machine_name', - 'real path' => 'admin/structure/taxonomy/' . $machine_name, + 'path' => 'admin/structure/taxonomy/%taxonomy_vocabulary', + 'real path' => 'admin/structure/taxonomy/' . $name, 'bundle argument' => 3, 'access arguments' => array('administer taxonomy'), ), ); } - $return['taxonomy_vocabulary'] = array( - 'label' => t('Taxonomy vocabulary'), - 'entity class' => 'Drupal\taxonomy\Vocabulary', - 'controller class' => 'Drupal\taxonomy\VocabularyStorageController', - 'base table' => 'taxonomy_vocabulary', - 'entity keys' => array( - 'id' => 'vid', - 'label' => 'name', - ), - 'fieldable' => FALSE, - ); return $return; } @@ -353,7 +342,7 @@ function taxonomy_menu() { 'file' => 'taxonomy.pages.inc', ); - $items['admin/structure/taxonomy/%taxonomy_vocabulary_machine_name'] = array( + $items['admin/structure/taxonomy/%taxonomy_vocabulary'] = array( 'title callback' => 'taxonomy_admin_vocabulary_title_callback', 'title arguments' => array(3), 'page callback' => 'drupal_get_form', @@ -361,12 +350,12 @@ function taxonomy_menu() { 'access arguments' => array('administer taxonomy'), 'file' => 'taxonomy.admin.inc', ); - $items['admin/structure/taxonomy/%taxonomy_vocabulary_machine_name/list'] = array( + $items['admin/structure/taxonomy/%taxonomy_vocabulary/list'] = array( 'title' => 'List', 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -20, ); - $items['admin/structure/taxonomy/%taxonomy_vocabulary_machine_name/edit'] = array( + $items['admin/structure/taxonomy/%taxonomy_vocabulary/edit'] = array( 'title' => 'Edit', 'page callback' => 'drupal_get_form', 'page arguments' => array('taxonomy_form_vocabulary', 3), @@ -376,7 +365,7 @@ function taxonomy_menu() { 'file' => 'taxonomy.admin.inc', ); - $items['admin/structure/taxonomy/%taxonomy_vocabulary_machine_name/add'] = array( + $items['admin/structure/taxonomy/%taxonomy_vocabulary/add'] = array( 'title' => 'Add term', 'page callback' => 'drupal_get_form', 'page arguments' => array('taxonomy_form_term', NULL, 3), @@ -433,13 +422,60 @@ function taxonomy_admin_vocabulary_title_callback(Vocabulary $vocabulary) { } /** + * Loads all taxonomy vocabularies. + * + * @return array + * An associative array containing vocabulary configuration objects keyed by + * vocabulary ID. + */ +function taxonomy_vocabulary_load_all() { + $vocabularies = config_load_all('taxonomy.vocabulary', 'Drupal\taxonomy\Vocabulary'); + uasort($vocabularies, 'drupal_sort_weight'); + return $vocabularies; +} + +/** + * Return the taxonomy vocabulary entity matching a vocabulary ID. + * + * @param int $vid + * The vocabulary's ID. + * + * @return array|false + * The taxonomy vocabulary configuration object, if exists, FALSE otherwise. + */ +function taxonomy_vocabulary_load($vid) { + $vocabulary = new Vocabulary($vid); + return $vocabulary->isNew() ? FALSE : $vocabulary; +} + +/** * Saves a vocabulary. * * @param Drupal\taxonomy\Vocabulary $vocabulary - * The taxonomy vocabulary entity to be saved. + * The taxonomy vocabulary configuration to be saved. */ function taxonomy_vocabulary_save(Vocabulary $vocabulary) { - return $vocabulary->save(); + module_invoke_all('taxonomy_vocabulary_presave', $vocabulary); + + $vocabulary->save(); + // Vocabularies are entity bundles. + entity_info_cache_clear(); + + // Create a taxonomy term bundle for new vocabularies. + if (!isset($vocabulary->original->vid)) { + field_attach_create_bundle('taxonomy_term', $vocabulary->vid); + + module_invoke_all('taxonomy_vocabulary_insert', $vocabulary); + } + else { + // Rename the taxonomy term bundle, if necessary. + if ($vocabulary->original->vid != $vocabulary->vid) { + field_attach_rename_bundle('taxonomy_term', $vocabulary->original->vid, $vocabulary->vid); + } + module_invoke_all('taxonomy_vocabulary_update', $vocabulary); + } + + return $vocabulary; } /** @@ -447,20 +483,47 @@ function taxonomy_vocabulary_save(Vocabulary $vocabulary) { * * @param $vid * A vocabulary ID. - * */ function taxonomy_vocabulary_delete($vid) { - taxonomy_vocabulary_delete_multiple(array($vid)); -} + $vocabulary = new Vocabulary($vid); + + // @todo Module hooks for config objects are very very very uncertain and not really foreseen at this point. + module_invoke_all('taxonomy_vocabulary_predelete', $vocabulary); + + // Only load terms without a parent, child terms will get deleted too. + $tids = db_query('SELECT t.tid FROM {taxonomy_term_data} t INNER JOIN {taxonomy_term_hierarchy} th ON th.tid = t.tid WHERE t.vid = :vid AND th.parent = 0', array(':vid' => $vid))->fetchCol(); + taxonomy_term_delete_multiple($tids); + + $vocabulary->delete(); + // Vocabularies are entity bundles. + entity_info_cache_clear(); + + // Load all Taxonomy module fields and delete those which use only this + // vocabulary. + $taxonomy_fields = field_read_fields(array('module' => 'taxonomy')); + foreach ($taxonomy_fields as $field_name => $taxonomy_field) { + $modified_field = FALSE; + // Term reference fields may reference terms from more than one vocabulary. + foreach ($taxonomy_field['settings']['allowed_values'] as $key => $allowed_value) { + foreach ($entities as $vocabulary) { + if ($allowed_value['vocabulary'] == $vocabulary->vid) { + unset($taxonomy_field['settings']['allowed_values'][$key]); + $modified_field = TRUE; + } + } + } + if ($modified_field) { + if (empty($taxonomy_field['settings']['allowed_values'])) { + field_delete_field($field_name); + } + else { + // Update the field definition with the new allowed values. + field_update_field($taxonomy_field); + } + } + } -/** - * Deletes vocabularies. - * - * @param $vids - * The vocabulary ids. - */ -function taxonomy_vocabulary_delete_multiple(array $vids) { - entity_delete_multiple('taxonomy_vocabulary', $vids); + module_invoke_all('taxonomy_vocabulary_delete', $vocabulary); } /** @@ -469,14 +532,14 @@ function taxonomy_vocabulary_delete_multiple(array $vids) { function taxonomy_taxonomy_vocabulary_update(Vocabulary $vocabulary) { // Reflect machine name changes in the definitions of existing 'taxonomy' // fields. - if (!empty($vocabulary->original->machine_name) && $vocabulary->original->machine_name != $vocabulary->machine_name) { + if (isset($vocabulary->original) && $vocabulary->original->vid != $vocabulary->vid) { $fields = field_read_fields(); foreach ($fields as $field_name => $field) { $update = FALSE; if ($field['type'] == 'taxonomy_term_reference') { foreach ($field['settings']['allowed_values'] as $key => &$value) { - if ($value['vocabulary'] == $vocabulary->original->machine_name) { - $value['vocabulary'] = $vocabulary->machine_name; + if ($value['vocabulary'] == $vocabulary->original->vid) { + $value['vocabulary'] = $vocabulary->vid; $update = TRUE; } } @@ -647,10 +710,10 @@ function template_preprocess_taxonomy_term(&$variables) { field_attach_preprocess('taxonomy_term', $term, $variables['content'], $variables); // Gather classes, and clean up name so there are no underscores. - $vocabulary_name_css = str_replace('_', '-', $term->vocabulary_machine_name); + $vocabulary_name_css = str_replace('_', '-', $term->vid); $variables['classes_array'][] = 'vocabulary-' . $vocabulary_name_css; - $variables['theme_hook_suggestions'][] = 'taxonomy_term__' . $term->vocabulary_machine_name; + $variables['theme_hook_suggestions'][] = 'taxonomy_term__' . $term->vid; $variables['theme_hook_suggestions'][] = 'taxonomy_term__' . $term->tid; } @@ -673,36 +736,6 @@ function taxonomy_terms_static_reset() { } /** - * Clear all static cache variables for vocabularies. - * - * @param $ids - * An array of ids to reset in entity controller cache. - */ -function taxonomy_vocabulary_static_reset(array $ids = NULL) { - entity_get_controller('taxonomy_vocabulary')->resetCache($ids); -} - -/** - * Get names for all taxonomy vocabularies. - * - * @return - * An associative array of objects keyed by vocabulary machine name with - * information about taxonomy vocabularies. Each object has properties: - * - name: The vocabulary name. - * - machine_name: The machine name. - * - vid: The vocabulary ID. - */ -function taxonomy_vocabulary_get_names() { - $names = &drupal_static(__FUNCTION__); - - if (!isset($names)) { - $names = db_query('SELECT name, machine_name, vid FROM {taxonomy_vocabulary}')->fetchAllAssoc('machine_name'); - } - - return $names; -} - -/** * Finds all parents of a given term ID. * * @param $tid @@ -923,7 +956,7 @@ function taxonomy_get_tree($vid, $parent = 0, $max_depth = NULL, $load_entities function taxonomy_term_load_multiple_by_name($name, $vocabulary = NULL) { $conditions = array('name' => trim($name)); if (isset($vocabulary)) { - $vocabularies = taxonomy_vocabulary_get_names(); + $vocabularies = taxonomy_vocabulary_load_all(); if (isset($vocabularies[$vocabulary])){ $conditions['vid'] = $vocabularies[$vocabulary]->vid; } @@ -965,60 +998,6 @@ function taxonomy_term_load_multiple($tids = array(), array $conditions = array( } /** - * Loads multiple taxonomy vocabularies based on certain conditions. - * - * 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. - * - * @see entity_load_multiple() - * - * @param array|bool $vids - * An array of taxonomy vocabulary IDs, or FALSE to load all vocabularies. - * @param array $conditions - * An array of conditions to add to the query. - * - * @return array - * An array of vocabulary objects, indexed by vid. - */ -function taxonomy_vocabulary_load_multiple($vids = array(), array $conditions = array()) { - return entity_load_multiple('taxonomy_vocabulary', $vids, $conditions); -} - -/** - * Return the taxonomy vocabulary entity matching a vocabulary ID. - * - * @param int $vid - * The vocabulary's ID. - * - * @return Drupal\taxonomy\Vocabulary|false - * The taxonomy vocabulary entity, if exists, FALSE otherwise. Results are - * statically cached. - * - * @see taxonomy_vocabulary_machine_name_load() - */ -function taxonomy_vocabulary_load($vid) { - return entity_load('taxonomy_vocabulary', $vid); -} - -/** - * Return the taxonomy vocabulary entity matching a vocabulary machine name. - * - * @param $name - * The vocabulary's machine name. - * - * @return Drupal\taxonomy\Vocabulary|false - * The taxonomy vocabulary entity, if exists, FALSE otherwise. Results are - * statically cached. - * - * @see taxonomy_vocabulary_load() - */ -function taxonomy_vocabulary_machine_name_load($name) { - $result = entity_load_multiple('taxonomy_vocabulary', FALSE, array('machine_name' => $name)); - return reset($result); -} - -/** * Return the taxonomy term entity matching a term ID. * * @param $tid @@ -1162,7 +1141,7 @@ function taxonomy_field_validate($entity_type, $entity, $field, $instance, $lang foreach ($field['settings']['allowed_values'] as $settings) { // If no parent is specified, check if the term is in the vocabulary. if (isset($settings['vocabulary']) && empty($settings['parent'])) { - if ($settings['vocabulary'] == $terms[$item['tid']]->vocabulary_machine_name) { + if ($settings['vocabulary'] == $terms[$item['tid']]->vid) { $validate = TRUE; break; } @@ -1287,7 +1266,7 @@ function taxonomy_field_formatter_view($entity_type, $entity, $field, $instance, function taxonomy_allowed_values($field) { $options = array(); foreach ($field['settings']['allowed_values'] as $tree) { - if ($vocabulary = taxonomy_vocabulary_machine_name_load($tree['vocabulary'])) { + if ($vocabulary = taxonomy_vocabulary_load($tree['vocabulary'])) { if ($terms = taxonomy_get_tree($vocabulary->vid, $tree['parent'])) { foreach ($terms as $term) { $options[$term->tid] = str_repeat('-', $term->depth) . $term->name; @@ -1394,7 +1373,7 @@ function taxonomy_autocomplete_validate($element, &$form_state) { $field = field_widget_field($element, $form_state); $vocabularies = array(); foreach ($field['settings']['allowed_values'] as $tree) { - if ($vocabulary = taxonomy_vocabulary_machine_name_load($tree['vocabulary'])) { + if ($vocabulary = taxonomy_vocabulary_load($tree['vocabulary'])) { $vocabularies[$vocabulary->vid] = $vocabulary; } } @@ -1413,7 +1392,6 @@ function taxonomy_autocomplete_validate($element, &$form_state) { 'tid' => 'autocreate', 'vid' => $vocabulary->vid, 'name' => $typed_term, - 'vocabulary_machine_name' => $vocabulary->machine_name, ); } $value[] = (array)$term; @@ -1434,10 +1412,10 @@ function taxonomy_field_widget_error($element, $error, $form, &$form_state) { */ function taxonomy_field_settings_form($field, $instance, $has_data) { // Get proper values for 'allowed_values_function', which is a core setting. - $vocabularies = taxonomy_vocabulary_load_multiple(FALSE); + $vocabularies = taxonomy_vocabulary_load_all(); $options = array(); foreach ($vocabularies as $vocabulary) { - $options[$vocabulary->machine_name] = $vocabulary->name; + $options[$vocabulary->vid] = $vocabulary->name; } $form['allowed_values'] = array( '#tree' => TRUE, diff --git a/core/modules/taxonomy/taxonomy.pages.inc b/core/modules/taxonomy/taxonomy.pages.inc index c84a6bd..7367903 100644 --- a/core/modules/taxonomy/taxonomy.pages.inc +++ b/core/modules/taxonomy/taxonomy.pages.inc @@ -131,7 +131,7 @@ function taxonomy_autocomplete($field_name, $tags_typed = '') { // Part of the criteria for the query come from the field's own settings. $vids = array(); - $vocabularies = taxonomy_vocabulary_get_names(); + $vocabularies = taxonomy_vocabulary_load_all(); foreach ($field['settings']['allowed_values'] as $tree) { $vids[] = $vocabularies[$tree['vocabulary']]->vid; } diff --git a/core/modules/taxonomy/taxonomy.test b/core/modules/taxonomy/taxonomy.test index 55b30fa..eecd7ff 100644 --- a/core/modules/taxonomy/taxonomy.test +++ b/core/modules/taxonomy/taxonomy.test @@ -8,6 +8,7 @@ use Drupal\field\FieldValidationException; use Drupal\simpletest\WebTestBase; use Drupal\entity\EntityFieldQuery; +use Drupal\taxonomy\Vocabulary; /** * Provides common helper methods for Taxonomy module tests. @@ -33,13 +34,11 @@ class TaxonomyWebTestCase extends WebTestBase { */ function createVocabulary() { // Create a vocabulary. - $vocabulary = entity_create('taxonomy_vocabulary', array( + $vid = drupal_strtolower($this->randomName()); + $vocabulary = new Vocabulary($vid, array( 'name' => $this->randomName(), 'description' => $this->randomName(), - 'machine_name' => drupal_strtolower($this->randomName()), - 'langcode' => LANGUAGE_NOT_SPECIFIED, - 'help' => '', - 'nodes' => array('article' => 'article'), + 'vid' => $vid, 'weight' => mt_rand(0, 10), )); taxonomy_vocabulary_save($vocabulary); @@ -94,10 +93,10 @@ class TaxonomyVocabularyFunctionalTest extends TaxonomyWebTestCase { // Create a new vocabulary. $this->clickLink(t('Add vocabulary')); $edit = array(); - $machine_name = drupal_strtolower($this->randomName()); + $vid = drupal_strtolower($this->randomName()); $edit['name'] = $this->randomName(); $edit['description'] = $this->randomName(); - $edit['machine_name'] = $machine_name; + $edit['vid'] = $vid; $this->drupalPost(NULL, $edit, t('Save')); $this->assertRaw(t('Created new vocabulary %name.', array('%name' => $edit['name'])), 'Vocabulary created successfully.'); @@ -112,12 +111,12 @@ class TaxonomyVocabularyFunctionalTest extends TaxonomyWebTestCase { $this->assertText($edit['name'], 'Vocabulary found in the vocabulary overview listing.'); // Try to submit a vocabulary with a duplicate machine name. - $edit['machine_name'] = $machine_name; + $edit['vid'] = $vid; $this->drupalPost('admin/structure/taxonomy/add', $edit, t('Save')); $this->assertText(t('The machine-readable name is already in use. It must be unique.')); // Try to submit an invalid machine name. - $edit['machine_name'] = '!&^%'; + $edit['vid'] = '!&^%'; $this->drupalPost('admin/structure/taxonomy/add', $edit, t('Save')); $this->assertText(t('The machine-readable name must contain only lowercase letters, numbers, and underscores.')); } @@ -131,7 +130,7 @@ class TaxonomyVocabularyFunctionalTest extends TaxonomyWebTestCase { $this->createVocabulary(); } // Get all vocabularies and change their weights. - $vocabularies = taxonomy_vocabulary_load_multiple(FALSE); + $vocabularies = taxonomy_vocabulary_load_all(); $edit = array(); foreach ($vocabularies as $key => $vocabulary) { $vocabulary->weight = -$vocabulary->weight; @@ -142,7 +141,7 @@ class TaxonomyVocabularyFunctionalTest extends TaxonomyWebTestCase { $this->drupalPost('admin/structure/taxonomy', $edit, t('Save')); // Load the vocabularies from the database. - $new_vocabularies = taxonomy_vocabulary_load_multiple(FALSE); + $new_vocabularies = taxonomy_vocabulary_load_all(); // Check that the weights are saved in the database correctly. foreach ($vocabularies as $key => $vocabulary) { @@ -155,12 +154,12 @@ class TaxonomyVocabularyFunctionalTest extends TaxonomyWebTestCase { */ function testTaxonomyAdminNoVocabularies() { // Delete all vocabularies. - $vocabularies = taxonomy_vocabulary_load_multiple(FALSE); + $vocabularies = taxonomy_vocabulary_load_all(); foreach ($vocabularies as $key => $vocabulary) { taxonomy_vocabulary_delete($key); } // Confirm that no vocabularies are found in the database. - $this->assertFalse(taxonomy_vocabulary_load_multiple(FALSE), 'No vocabularies found in the database.'); + $this->assertFalse(taxonomy_vocabulary_load_all(), 'No vocabularies found in the database.'); $this->drupalGet('admin/structure/taxonomy'); // Check the default message for no vocabularies. $this->assertText(t('No vocabularies available.'), 'No vocabularies were found.'); @@ -173,28 +172,26 @@ class TaxonomyVocabularyFunctionalTest extends TaxonomyWebTestCase { // Create a vocabulary. $edit = array( 'name' => $this->randomName(), - 'machine_name' => drupal_strtolower($this->randomName()), + 'vid' => drupal_strtolower($this->randomName()), ); $this->drupalPost('admin/structure/taxonomy/add', $edit, t('Save')); $this->assertText(t('Created new vocabulary'), 'New vocabulary was created.'); // Check the created vocabulary. - $vocabularies = taxonomy_vocabulary_load_multiple(FALSE); + $vocabularies = taxonomy_vocabulary_load_all(); $vid = $vocabularies[count($vocabularies) - 1]->vid; - entity_get_controller('taxonomy_vocabulary')->resetCache(); $vocabulary = taxonomy_vocabulary_load($vid); $this->assertTrue($vocabulary, 'Vocabulary found in database.'); // Delete the vocabulary. $edit = array(); - $this->drupalPost('admin/structure/taxonomy/' . $vocabulary->machine_name . '/edit', $edit, t('Delete')); + $this->drupalPost('admin/structure/taxonomy/' . $vocabulary->vid . '/edit', $edit, t('Delete')); $this->assertRaw(t('Are you sure you want to delete the vocabulary %name?', array('%name' => $vocabulary->name)), '[confirm deletion] Asks for confirmation.'); $this->assertText(t('Deleting a vocabulary will delete all the terms in it. This action cannot be undone.'), '[confirm deletion] Inform that all terms will be deleted.'); // Confirm deletion. $this->drupalPost(NULL, NULL, t('Delete')); $this->assertRaw(t('Deleted vocabulary %name.', array('%name' => $vocabulary->name)), 'Vocabulary deleted.'); - entity_get_controller('taxonomy_vocabulary')->resetCache(); $this->assertFalse(taxonomy_vocabulary_load($vid), t('Vocabulary is not found in the database')); } @@ -221,32 +218,11 @@ class TaxonomyVocabularyUnitTest extends TaxonomyWebTestCase { } /** - * Ensure that when an invalid vocabulary vid is loaded, it is possible - * to load the same vid successfully if it subsequently becomes valid. - */ - function testTaxonomyVocabularyLoadReturnFalse() { - // Load a vocabulary that doesn't exist. - $vocabularies = taxonomy_vocabulary_load_multiple(FALSE); - $vid = count($vocabularies) + 1; - $vocabulary = taxonomy_vocabulary_load($vid); - // This should not return an object because no such vocabulary exists. - $this->assertTrue(empty($vocabulary), 'No object loaded.'); - - // Create a new vocabulary. - $this->createVocabulary(); - // Load the vocabulary with the same $vid from earlier. - // This should return a vocabulary object since it now matches a real vid. - $vocabulary = taxonomy_vocabulary_load($vid); - $this->assertTrue(!empty($vocabulary) && is_object($vocabulary), 'Vocabulary is an object.'); - $this->assertEqual($vocabulary->vid, $vid, 'Valid vocabulary vid is the same as our previously invalid one.'); - } - - /** * Test deleting a taxonomy that contains terms. */ function testTaxonomyVocabularyDeleteWithTerms() { // Delete any existing vocabularies. - foreach (taxonomy_vocabulary_load_multiple(FALSE) as $vocabulary) { + foreach (taxonomy_vocabulary_load_all() as $vocabulary) { taxonomy_vocabulary_delete($vocabulary->vid); } @@ -296,17 +272,16 @@ class TaxonomyVocabularyUnitTest extends TaxonomyWebTestCase { // Delete the vocabulary. taxonomy_vocabulary_delete($this->vocabulary->vid); - $vocabularies = taxonomy_vocabulary_load_multiple(FALSE); + $vocabularies = taxonomy_vocabulary_load_all(); $this->assertTrue(!isset($vocabularies[$this->vocabulary->vid]), 'The vocabulary was deleted.'); } /** - * Tests for loading multiple vocabularies. + * Tests loading all vocabularies. */ - function testTaxonomyVocabularyLoadMultiple() { - + function testTaxonomyVocabularyLoadAll() { // Delete any existing vocabularies. - foreach (taxonomy_vocabulary_load_multiple(FALSE) as $vocabulary) { + foreach (taxonomy_vocabulary_load_all() as $vocabulary) { taxonomy_vocabulary_delete($vocabulary->vid); } @@ -323,29 +298,15 @@ class TaxonomyVocabularyUnitTest extends TaxonomyWebTestCase { // Fetch the names for all vocabularies, confirm that they are keyed by // machine name. - $names = taxonomy_vocabulary_get_names(); - $this->assertEqual($names[$vocabulary1->machine_name]->name, $vocabulary1->name, 'Vocabulary 1 name found.'); + $names = taxonomy_vocabulary_load_all(); + $this->assertEqual($names[$vocabulary1->vid]->name, $vocabulary1->name, 'Vocabulary 1 name found.'); - // Fetch all of the vocabularies using taxonomy_vocabulary_load_multiple(FALSE). + // Fetch all of the vocabularies using taxonomy_vocabulary_load_all(). // Confirm that the vocabularies are ordered by weight. - $vocabularies = taxonomy_vocabulary_load_multiple(FALSE); + $vocabularies = taxonomy_vocabulary_load_all(); $this->assertEqual(array_shift($vocabularies)->vid, $vocabulary1->vid, 'Vocabulary was found in the vocabularies array.'); $this->assertEqual(array_shift($vocabularies)->vid, $vocabulary2->vid, 'Vocabulary was found in the vocabularies array.'); $this->assertEqual(array_shift($vocabularies)->vid, $vocabulary3->vid, '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)->vid, $vocabulary3->vid, 'Vocabulary loaded successfully by ID.'); - $this->assertEqual(array_shift($vocabularies)->vid, $vocabulary2->vid, 'Vocabulary loaded successfully by ID.'); - $this->assertEqual(array_shift($vocabularies)->vid, $vocabulary1->vid, 'Vocabulary loaded successfully by ID.'); - - // Fetch vocabulary 1 by name. - $vocabulary = current(taxonomy_vocabulary_load_multiple(array(), array('name' => $vocabulary1->name))); - $this->assertEqual($vocabulary->vid, $vocabulary1->vid, 'Vocabulary loaded successfully by name.'); - - // Fetch vocabulary 1 by name and ID. - $this->assertEqual(current(taxonomy_vocabulary_load_multiple(array($vocabulary1->vid), array('name' => $vocabulary1->name)))->vid, $vocabulary1->vid, 'Vocabulary loaded successfully by name and ID.'); } /** @@ -361,14 +322,14 @@ class TaxonomyVocabularyUnitTest extends TaxonomyWebTestCase { $instance = array( 'field_name' => 'field_test', 'entity_type' => 'taxonomy_term', - 'bundle' => $this->vocabulary->machine_name, + 'bundle' => $this->vocabulary->vid, ); field_create_instance($instance); // Change the machine name. - $old_name = $this->vocabulary->machine_name; + $old_name = $this->vocabulary->vid; $new_name = drupal_strtolower($this->randomName()); - $this->vocabulary->machine_name = $new_name; + $this->vocabulary->vid = $new_name; taxonomy_vocabulary_save($this->vocabulary); // Check that entity bundles are properly updated. @@ -392,7 +353,7 @@ class TaxonomyVocabularyUnitTest extends TaxonomyWebTestCase { $this->instance = array( 'field_name' => $this->field_name, 'entity_type' => 'taxonomy_term', - 'bundle' => $this->vocabulary->machine_name, + 'bundle' => $this->vocabulary->vid, 'label' => $this->randomName() . '_label', ); field_create_instance($this->instance); @@ -555,13 +516,13 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase { $this->vocabulary = $this->createVocabulary(); $field = array( - 'field_name' => 'taxonomy_' . $this->vocabulary->machine_name, + 'field_name' => 'taxonomy_' . $this->vocabulary->vid, 'type' => 'taxonomy_term_reference', 'cardinality' => FIELD_CARDINALITY_UNLIMITED, 'settings' => array( 'allowed_values' => array( array( - 'vocabulary' => $this->vocabulary->machine_name, + 'vocabulary' => $this->vocabulary->vid, 'parent' => 0, ), ), @@ -570,7 +531,7 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase { field_create_field($field); $this->instance = array( - 'field_name' => 'taxonomy_' . $this->vocabulary->machine_name, + 'field_name' => 'taxonomy_' . $this->vocabulary->vid, 'bundle' => 'article', 'entity_type' => 'node', 'widget' => array( @@ -728,13 +689,13 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase { // Test autocomplete on term 3, which contains a comma. // The term will be quoted, and the " will be encoded in unicode (\u0022). $input = substr($term_objects['term3']->name, 0, 3); - $this->drupalGet('taxonomy/autocomplete/taxonomy_' . $this->vocabulary->machine_name . '/' . $input); + $this->drupalGet('taxonomy/autocomplete/taxonomy_' . $this->vocabulary->vid . '/' . $input); $this->assertRaw('{"\u0022' . $term_objects['term3']->name . '\u0022":"' . $term_objects['term3']->name . '"}', format_string('Autocomplete returns term %term_name after typing the first 3 letters.', array('%term_name' => $term_objects['term3']->name))); // Test autocomplete on term 4 - it is alphanumeric only, so no extra // quoting. $input = substr($term_objects['term4']->name, 0, 3); - $this->drupalGet('taxonomy/autocomplete/taxonomy_' . $this->vocabulary->machine_name . '/' . $input); + $this->drupalGet('taxonomy/autocomplete/taxonomy_' . $this->vocabulary->vid . '/' . $input); $this->assertRaw('{"' . $term_objects['term4']->name . '":"' . $term_objects['term4']->name . '"}', format_string('Autocomplete returns term %term_name after typing the first 3 letters.', array('%term_name' => $term_objects['term4']->name))); // Test taxonomy autocomplete with a nonexistent field. @@ -767,7 +728,7 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase { // We should get both term in a json encoded string. $input = '10/'; $path = 'taxonomy/autocomplete/taxonomy_'; - $path .= $this->vocabulary->machine_name . '/' . $input; + $path .= $this->vocabulary->vid . '/' . $input; // The result order is not guaranteed, so check each term separately. $url = url($path, array('absolute' => TRUE)); $result = drupal_http_request($url); @@ -779,7 +740,7 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase { // We should only get the first term in a json encoded string. $input = '10/16'; $url = 'taxonomy/autocomplete/taxonomy_'; - $url .= $this->vocabulary->machine_name . '/' . $input; + $url .= $this->vocabulary->vid . '/' . $input; $this->drupalGet($url); $target = array($first_term->name => check_plain($first_term->name)); $this->assertRaw(drupal_json_encode($target), 'Autocomplete returns only the expected matching term.'); @@ -787,7 +748,7 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase { // Try to autocomplete a term name with both a comma and a slash. $input = '"term with, comma and / a'; $url = 'taxonomy/autocomplete/taxonomy_'; - $url .= $this->vocabulary->machine_name . '/' . $input; + $url .= $this->vocabulary->vid . '/' . $input; $this->drupalGet($url); $n = $third_term->name; // Term names containing commas or quotes must be wrapped in quotes. @@ -811,14 +772,14 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase { $edit['parent[]'] = array(0); // Create the term to edit. - $this->drupalPost('admin/structure/taxonomy/' . $this->vocabulary->machine_name . '/add', $edit, t('Save')); + $this->drupalPost('admin/structure/taxonomy/' . $this->vocabulary->vid . '/add', $edit, t('Save')); $terms = taxonomy_term_load_multiple_by_name($edit['name']); $term = reset($terms); $this->assertNotNull($term, 'Term found in database.'); // Submitting a term takes us to the add page; we need the List page. - $this->drupalGet('admin/structure/taxonomy/' . $this->vocabulary->machine_name); + $this->drupalGet('admin/structure/taxonomy/' . $this->vocabulary->vid); // Test edit link as accessed from Taxonomy administration pages. // Because Simpletest creates its own database when running tests, we know @@ -837,7 +798,7 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase { $this->drupalPost('taxonomy/term/' . $term->tid . '/edit', $edit, t('Save')); // Check that the term is still present at admin UI after edit. - $this->drupalGet('admin/structure/taxonomy/' . $this->vocabulary->machine_name); + $this->drupalGet('admin/structure/taxonomy/' . $this->vocabulary->vid); $this->assertText($edit['name'], 'The randomly generated term name is present.'); $this->assertLink(t('edit')); @@ -885,7 +846,7 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase { drupal_static_reset('taxonomy_get_treeterms'); list($term1, $term2, $term3) = taxonomy_get_tree($this->vocabulary->vid); - $this->drupalGet('admin/structure/taxonomy/' . $this->vocabulary->machine_name); + $this->drupalGet('admin/structure/taxonomy/' . $this->vocabulary->vid); // Each term has four hidden fields, "tid:1:0[tid]", "tid:1:0[parent]", // "tid:1:0[depth]", and "tid:1:0[weight]". Change the order to term2, @@ -915,7 +876,7 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase { $this->assertEqual($terms[1]->parents, array($term2->tid), 'Term 3 was made a child of term 2.'); $this->assertEqual($terms[2]->tid, $term1->tid, 'Term 1 was moved below term 2.'); - $this->drupalPost('admin/structure/taxonomy/' . $this->vocabulary->machine_name, array(), t('Reset to alphabetical')); + $this->drupalPost('admin/structure/taxonomy/' . $this->vocabulary->vid, array(), t('Reset to alphabetical')); // Submit confirmation form. $this->drupalPost(NULL, array(), t('Reset to alphabetical')); @@ -943,7 +904,7 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase { 'parent[]' => array(0, $parent->tid), ); // Save the new term. - $this->drupalPost('admin/structure/taxonomy/' . $this->vocabulary->machine_name . '/add', $edit, t('Save')); + $this->drupalPost('admin/structure/taxonomy/' . $this->vocabulary->vid . '/add', $edit, t('Save')); // Check that the term was successfully created. $terms = taxonomy_term_load_multiple_by_name($edit['name']); @@ -1001,7 +962,7 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase { $this->assertEqual(count($terms), 2, 'Two terms loaded with the same name.'); // Load single term when restricted to one vocabulary. - $terms = taxonomy_term_load_multiple_by_name($term->name, $this->vocabulary->machine_name); + $terms = taxonomy_term_load_multiple_by_name($term->name, $this->vocabulary->vid); $this->assertEqual(count($terms), 1, 'One term loaded when restricted by vocabulary.'); $this->assertTrue(isset($terms[$term->tid]), 'Term loaded using exact name and vocabulary machine name.'); @@ -1010,7 +971,7 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase { // Try to load a term by name that doesn't exist in this vocabulary but // exists in another vocabulary. - $terms = taxonomy_term_load_multiple_by_name($term2->name, $new_vocabulary->machine_name); + $terms = taxonomy_term_load_multiple_by_name($term2->name, $new_vocabulary->vid); $this->assertFalse($terms, 'Invalid term name restricted by vocabulary machine name not loaded.'); // Try to load terms filtering by a non-existing vocabulary. @@ -1040,13 +1001,13 @@ class TaxonomyRSSTestCase extends TaxonomyWebTestCase { $this->vocabulary = $this->createVocabulary(); $field = array( - 'field_name' => 'taxonomy_' . $this->vocabulary->machine_name, + 'field_name' => 'taxonomy_' . $this->vocabulary->vid, 'type' => 'taxonomy_term_reference', 'cardinality' => FIELD_CARDINALITY_UNLIMITED, 'settings' => array( 'allowed_values' => array( array( - 'vocabulary' => $this->vocabulary->machine_name, + 'vocabulary' => $this->vocabulary->vid, 'parent' => 0, ), ), @@ -1055,7 +1016,7 @@ class TaxonomyRSSTestCase extends TaxonomyWebTestCase { field_create_field($field); $this->instance = array( - 'field_name' => 'taxonomy_' . $this->vocabulary->machine_name, + 'field_name' => 'taxonomy_' . $this->vocabulary->vid, 'bundle' => 'article', 'entity_type' => 'node', 'widget' => array( @@ -1089,7 +1050,7 @@ class TaxonomyRSSTestCase extends TaxonomyWebTestCase { // Change the format to 'RSS category'. $this->drupalGet("admin/structure/types/manage/article/display/rss"); $edit = array( - "fields[taxonomy_" . $this->vocabulary->machine_name . "][type]" => 'taxonomy_term_reference_rss_category', + "fields[taxonomy_" . $this->vocabulary->vid . "][type]" => 'taxonomy_term_reference_rss_category', ); $this->drupalPost(NULL, $edit, t('Save')); @@ -1145,7 +1106,7 @@ class TaxonomyTermIndexTestCase extends TaxonomyWebTestCase { 'settings' => array( 'allowed_values' => array( array( - 'vocabulary' => $this->vocabulary->machine_name, + 'vocabulary' => $this->vocabulary->vid, 'parent' => 0, ), ), @@ -1175,7 +1136,7 @@ class TaxonomyTermIndexTestCase extends TaxonomyWebTestCase { 'settings' => array( 'allowed_values' => array( array( - 'vocabulary' => $this->vocabulary->machine_name, + 'vocabulary' => $this->vocabulary->vid, 'parent' => 0, ), ), @@ -1423,7 +1384,7 @@ class TaxonomyHooksTestCase extends TaxonomyWebTestCase { 'name' => $this->randomName(), 'antonym' => 'Long', ); - $this->drupalPost('admin/structure/taxonomy/' . $vocabulary->machine_name . '/add', $edit, t('Save')); + $this->drupalPost('admin/structure/taxonomy/' . $vocabulary->vid . '/add', $edit, t('Save')); $terms = taxonomy_term_load_multiple_by_name($edit['name']); $term = reset($terms); $this->assertEqual($term->antonym, $edit['antonym'], 'Antonym was loaded into the term object.'); @@ -1477,7 +1438,7 @@ class TaxonomyTermFieldTestCase extends TaxonomyWebTestCase { 'settings' => array( 'allowed_values' => array( array( - 'vocabulary' => $this->vocabulary->machine_name, + 'vocabulary' => $this->vocabulary->vid, 'parent' => '0', ), ), @@ -1572,11 +1533,11 @@ class TaxonomyTermFieldTestCase extends TaxonomyWebTestCase { // they all get updated. $this->field['settings']['allowed_values'] = array( array( - 'vocabulary' => $this->vocabulary->machine_name, + 'vocabulary' => $this->vocabulary->vid, 'parent' => '0', ), array( - 'vocabulary' => $this->vocabulary->machine_name, + 'vocabulary' => $this->vocabulary->vid, 'parent' => '0', ), array( @@ -1587,7 +1548,7 @@ class TaxonomyTermFieldTestCase extends TaxonomyWebTestCase { field_update_field($this->field); // Change the machine name. $new_name = drupal_strtolower($this->randomName()); - $this->vocabulary->machine_name = $new_name; + $this->vocabulary->vid = $new_name; taxonomy_vocabulary_save($this->vocabulary); // Check that the field instance is still attached to the vocabulary. @@ -1634,11 +1595,11 @@ class TaxonomyTermFieldMultipleVocabularyTestCase extends TaxonomyWebTestCase { 'settings' => array( 'allowed_values' => array( array( - 'vocabulary' => $this->vocabulary1->machine_name, + 'vocabulary' => $this->vocabulary1->vid, 'parent' => '0', ), array( - 'vocabulary' => $this->vocabulary2->machine_name, + 'vocabulary' => $this->vocabulary2->vid, 'parent' => '0', ), ), @@ -1743,13 +1704,13 @@ class TaxonomyTokenReplaceTestCase extends TaxonomyWebTestCase { $this->langcode = LANGUAGE_NOT_SPECIFIED; $field = array( - 'field_name' => 'taxonomy_' . $this->vocabulary->machine_name, + 'field_name' => 'taxonomy_' . $this->vocabulary->vid, 'type' => 'taxonomy_term_reference', 'cardinality' => FIELD_CARDINALITY_UNLIMITED, 'settings' => array( 'allowed_values' => array( array( - 'vocabulary' => $this->vocabulary->machine_name, + 'vocabulary' => $this->vocabulary->vid, 'parent' => 0, ), ), @@ -1758,7 +1719,7 @@ class TaxonomyTokenReplaceTestCase extends TaxonomyWebTestCase { field_create_field($field); $this->instance = array( - 'field_name' => 'taxonomy_' . $this->vocabulary->machine_name, + 'field_name' => 'taxonomy_' . $this->vocabulary->vid, 'bundle' => 'article', 'entity_type' => 'node', 'widget' => array( @@ -1903,7 +1864,7 @@ class TaxonomyThemeTestCase extends TaxonomyWebTestCase { // Adding a term to a vocabulary is considered an administrative action and // should use the administrative theme. $vocabulary = $this->createVocabulary(); - $this->drupalGet('admin/structure/taxonomy/' . $vocabulary->machine_name . '/add'); + $this->drupalGet('admin/structure/taxonomy/' . $vocabulary->vid . '/add'); $this->assertRaw('seven/style.css', t("The administrative theme's CSS appears on the page for adding a taxonomy term.")); // Viewing a taxonomy term should use the default theme. diff --git a/profiles/standard/standard.install b/profiles/standard/standard.install index eef8d0c..264ddaa 100644 --- a/profiles/standard/standard.install +++ b/profiles/standard/standard.install @@ -4,6 +4,8 @@ * Install, update and uninstall functions for the standard install profile. */ +use Drupal\taxonomy\Vocabulary; + /** * Implements hook_install(). * @@ -284,25 +286,24 @@ function standard_install() { // Create a default vocabulary named "Tags", enabled for the 'article' content type. $description = st('Use tags to group articles on similar topics into categories.'); - $help = st('Enter a comma-separated list of words to describe your content.'); - $vocabulary = entity_create('taxonomy_vocabulary', array( + $tags_help = st('Enter a comma-separated list of words to describe your content.'); + $vocabulary = new Vocabulary('tags', array( 'name' => st('Tags'), 'description' => $description, - 'machine_name' => 'tags', + 'vid' => 'tags', 'langcode' => language_default()->langcode, - 'help' => $help, )); taxonomy_vocabulary_save($vocabulary); $field = array( - 'field_name' => 'field_' . $vocabulary->machine_name, + 'field_name' => 'field_' . $vocabulary->vid, 'type' => 'taxonomy_term_reference', // Set cardinality to unlimited for tagging. 'cardinality' => FIELD_CARDINALITY_UNLIMITED, 'settings' => array( 'allowed_values' => array( array( - 'vocabulary' => $vocabulary->machine_name, + 'vocabulary' => $vocabulary->vid, 'parent' => 0, ), ), @@ -311,11 +312,11 @@ function standard_install() { field_create_field($field); $instance = array( - 'field_name' => 'field_' . $vocabulary->machine_name, + 'field_name' => 'field_' . $vocabulary->vid, 'entity_type' => 'node', 'label' => 'Tags', 'bundle' => 'article', - 'description' => $vocabulary->help, + 'description' => $tags_help, 'widget' => array( 'type' => 'taxonomy_autocomplete', 'weight' => -4,