diff --git a/core/misc/vertical-tabs.css b/core/misc/vertical-tabs.css index c946503..d1b657d 100644 --- a/core/misc/vertical-tabs.css +++ b/core/misc/vertical-tabs.css @@ -62,7 +62,7 @@ fieldset.vertical-tabs-pane > legend { * with "box-sizing" to prevent box model issues from occurring in most browsers. */ .vertical-tabs .form-type-textfield input { - width: 100%; + max-width: 100%; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; diff --git a/core/modules/path/lib/Drupal/path/Plugin/field/widget/NullWidget.php b/core/modules/path/lib/Drupal/path/Plugin/field/widget/NullWidget.php new file mode 100644 index 0000000..5f79f0e --- /dev/null +++ b/core/modules/path/lib/Drupal/path/Plugin/field/widget/NullWidget.php @@ -0,0 +1,106 @@ +instance['settings']['pattern']['prefix'])) { + $prefix = $this->instance['settings']['pattern']['prefix'] . '/'; + } + else { + $prefix = ''; + } + $prefix_length = drupal_strlen($prefix); + + // @todo Consider to move this into path_field_load(). OTOH, that would + // (needlessly?) load URL aliases for every loaded entity. But then again, + // field data is cached, no? + $path = array(); + if (!$entity->isNew()) { + $uri = $entity->uri(); + $conditions = array( + 'source' => $uri['path'], + ); + if ($langcode != LANGUAGE_NOT_SPECIFIED) { + $conditions['langcode'] = $langcode; + } + if ($path = path_load($conditions)) { + // If there is an alias for this entity already, the configured prefix + // needs to be removed from it if it is identical, since the field is + // only supposed to store the actual user input. + if (drupal_substr($path['alias'], 0, $prefix_length) === $prefix) { + $path['value'] = drupal_substr($path['alias'], $prefix_length); + } + // If it is not, then the stored alias uses a different prefix than the + // one configured for this field instance, which can happen when + // manually saving an URL alias via Path module's administration pages, + // but also in case the field instance setting was not properly updated. + else { + $prefix = ''; + $path['value'] = $path['alias']; + } + } + else { + $path = $conditions; + } + } + $path += array( + 'pid' => NULL, + 'source' => NULL, + 'value' => isset($items[$delta]['value']) ? $items[$delta]['value'] : NULL, + 'langcode' => $langcode, + ); + + $element += array( + '#access' => FALSE, + '#tree' => TRUE, + ); + $element['prefix'] = array( + '#type' => 'value', + '#value' => $prefix, + ); + $element['value'] = array( + '#type' => 'value', + '#default_value' => $path['value'], + ); + $element['pid'] = array( + '#type' => 'value', + '#value' => $path['pid'], + ); + return $element; + } + +} diff --git a/core/modules/path/lib/Drupal/path/Plugin/field/widget/PathWidget.php b/core/modules/path/lib/Drupal/path/Plugin/field/widget/PathWidget.php new file mode 100644 index 0000000..71e7180 --- /dev/null +++ b/core/modules/path/lib/Drupal/path/Plugin/field/widget/PathWidget.php @@ -0,0 +1,158 @@ +instance['settings']['pattern']['prefix'])) { + $prefix = $this->instance['settings']['pattern']['prefix'] . '/'; + } + else { + $prefix = ''; + } + $prefix_length = drupal_strlen($prefix); + + // @todo Consider to move this into path_field_load(). OTOH, that would + // (needlessly?) load URL aliases for every loaded entity. But then again, + // field data is cached, no? + $path = array(); + if (!$entity->isNew()) { + $uri = $entity->uri(); + $conditions = array( + 'source' => $uri['path'], + ); + if ($langcode != LANGUAGE_NOT_SPECIFIED) { + $conditions['langcode'] = $langcode; + } + if ($path = path_load($conditions)) { + // If there is an alias for this entity already, the configured prefix + // needs to be removed from it if it is identical, since the field is + // only supposed to store the actual user input. + if (drupal_substr($path['alias'], 0, $prefix_length) === $prefix) { + $path['value'] = drupal_substr($path['alias'], $prefix_length); + } + // If it is not, then the stored alias uses a different prefix than the + // one configured for this field instance, which can happen when + // manually saving an URL alias via Path module's administration pages, + // but also in case the field instance setting was not properly updated. + else { + $prefix = ''; + $path['value'] = $path['alias']; + } + } + else { + $path = $conditions; + } + } + $path += array( + 'pid' => NULL, + 'source' => NULL, + 'value' => isset($items[$delta]['value']) ? $items[$delta]['value'] : NULL, + 'langcode' => $langcode, + ); + // @todo Entity-specific, dynamic token replacement for user-customizable + // part. Potentially use #ajax for this. + + $element += array( + '#type' => 'container', + '#attributes' => array( + 'class' => array('path-form'), + ), + '#attached' => array( + 'library' => array(array('path', 'drupal.path')), + ), + '#access' => user_access('create url aliases') || user_access('administer url aliases'), + '#tree' => TRUE, + '#element_validate' => array(array($this, 'validatePath')), + ); + $element['pid'] = array( + '#type' => 'value', + '#value' => $path['pid'], + ); + $element['prefix'] = array( + '#type' => 'value', + '#value' => $prefix, + ); + $element['value'] = array( + '#type' => 'textfield', + // @todo Use the field instance label ($element['#title']) here or always + // identical default for consistency? Are fields able to provide default + // labels for instances somehow? + '#title' => t('Permalink'), + '#field_prefix' => check_plain(url($prefix, array('absolute' => TRUE))), + '#default_value' => $path['value'], + '#required' => $element['#required'], + '#maxlength' => 255 - drupal_strlen($prefix), + ); + $element['source'] = array( + '#type' => 'value', + '#value' => $path['source'], + ); + $element['langcode'] = array( + '#type' => 'value', + '#value' => $path['langcode'], + ); + return $element; + } + + /** + * Form element validation handler for PathWidget. + */ + public function validatePath(&$element, &$form_state, $form) { + if ($element['value']['#value'] !== '') { + // Trim the submitted value. + $element['value']['#value'] = trim($element['value']['#value']); + form_set_value($element['value'], $element['value']['#value'], $form_state); + // Entity language needs special care. Since the language of the URL alias + // depends on the entity language, and the entity language may be switched + // right within the same form, we need to conditionally overload the + // originally assigned URL alias language. + // @todo Remove this after stopping Locale module from abusing the content + // language system. + if (isset($form_state['values']['langcode'])) { + form_set_value($element['langcode'], $form_state['values']['langcode'], $form_state); + } + + // Ensure that the submitted alias does not exist yet. + $query = db_select('url_alias') + ->condition('alias', $element['prefix']['#value'] . $element['value']['#value']) + ->condition('langcode', $element['langcode']['#value']); + if (!empty($element['source']['#value'])) { + $query->condition('source', $element['source']['#value'], '<>'); + } + $query->addExpression('1'); + $query->range(0, 1); + if ($query->execute()->fetchField()) { + form_error($element['value'], t('The alias is already in use.')); + } + } + } + +} diff --git a/core/modules/path/lib/Drupal/path/Tests/PathFieldCRUDTest.php b/core/modules/path/lib/Drupal/path/Tests/PathFieldCRUDTest.php new file mode 100644 index 0000000..5788700 --- /dev/null +++ b/core/modules/path/lib/Drupal/path/Tests/PathFieldCRUDTest.php @@ -0,0 +1,155 @@ + 'Path field CRUD operations', + 'description' => 'Tests path field CRUD operations.', + 'group' => 'Path', + ); + } + + function setUp() { + parent::setUp(); + +// $this->enableModules(array('field', 'node')); +// $this->installSchema('system', 'url_alias'); + + $this->nodeType = (object) array( + 'type' => 'article', + 'name' => 'Article', + ); + node_type_save($this->nodeType); + + // Create a path field for the node type. + $this->field_name = drupal_strtolower($this->randomName()); + $this->langcode = LANGUAGE_NOT_SPECIFIED; + $this->prefix = 'test/prefix'; + $this->field = array( + 'field_name' => $this->field_name, + 'type' => 'path', + ); + field_create_field($this->field); + $this->instance = array( + 'field_name' => $this->field_name, + 'entity_type' => 'node', + 'bundle' => $this->nodeType->type, + 'settings' => array( + 'pattern' => array( + 'prefix' => $this->prefix, + 'auto' => FALSE, + ), + ), + 'widget' => array( + 'type' => 'path_default', + ), + ); + field_create_instance($this->instance); + } + + /** + * Tests a basic CRUD flow for path fields. + */ + function testBasicCRUD() { + // Create and save an entity with an alias. + $entity = entity_create('node', array( + 'type' => $this->nodeType->type, + 'title' => $this->randomName(), + )); + $edit = array( + 'value' => 'test-alias', + ); + $entity->{$this->field_name}[$this->langcode][0] = $edit; + $entity->save(); + $uri = $entity->uri(); + + // Verify that field data and the URL alias was stored. + $data = $entity->{$this->field_name}[$this->langcode][0]; + $this->assertTrue($data['pid']); + $this->assertIdentical($data['value'], $edit['value']); + $this->assertIdentical($data['alias'], $this->prefix . '/' . $edit['value']); + $path = path_load($data['pid']); + $this->assertIdentical($path['source'], $uri['path']); + $this->assertIdentical($path['alias'], $this->prefix . '/' . $edit['value']); + + // Edit the field value and update the entity. + $updated_value = 'updated-alias'; + $entity->{$this->field_name}[$this->langcode][0]['value'] = $updated_value; + $entity->save(); + + // Verify that field data and the URL alias was stored. + $data = $entity->{$this->field_name}[$this->langcode][0]; + $this->assertIdentical($data['pid'], $path['pid']); + $this->assertIdentical($data['value'], $updated_value); + $this->assertIdentical($data['alias'], $this->prefix . '/' . $updated_value); + $path = path_load($data['pid']); + $this->assertIdentical($path['source'], $uri['path']); + $this->assertIdentical($path['alias'], $this->prefix . '/' . $updated_value); + + // Verify that there is only one alias. + $count = db_query('SELECT COUNT(*) FROM {url_alias} WHERE source = :source', array( + ':source' => $uri['path'], + ))->fetchField(); + $this->assertEqual($count, 1); + + // Delete the entity. + $entity->delete(); + + // Verify that the alias no longer exists. + $path = path_load($data['pid']); + $this->assertFalse($path); + $count = db_query('SELECT COUNT(*) FROM {url_alias} WHERE source = :source', array( + ':source' => $uri['path'], + ))->fetchField(); + $this->assertEqual($count, 0); + } + + function xtestCRUDWithChangedPrefix() { + } + + /** + * Tests updating of field data after deletion of aliases via URL alias API. + */ + function testPathDelete() { + // Create and save an entity with an alias. + $entity = entity_create('node', array( + 'type' => $this->nodeType->type, + 'title' => $this->randomName(), + )); + $edit = array( + 'value' => 'test-alias', + ); + $entity->{$this->field_name}[$this->langcode][0] = $edit; + $entity->save(); + $uri = $entity->uri(); + + // Delete the alias. + path_delete(array('source' => $uri['path'])); + + // Reload the entity and verify that the alias no longer exists. + $entity = entity_load('node', $entity->id()); + $this->assertFalse($entity->{$this->field_name}); + } + +} diff --git a/core/modules/path/path.install b/core/modules/path/path.install new file mode 100644 index 0000000..a1f206d --- /dev/null +++ b/core/modules/path/path.install @@ -0,0 +1,42 @@ + array( + 'description' => 'A unique path alias identifier.', + 'type' => 'int', + 'not null' => FALSE, + ), + // This partially duplicates {url_alias}.alias, but contains the actual user + // input, which should be stored per field, to make it an inherent part of + // an entity's life-cycle; e.g., also exposing a changed value in field + // revisions. Additionally, a change to the URL alias prefix in the field's + // instance settings should potentially trigger a bulk-update of existing + // aliases, using the same custom part but with a new prefix. + 'value' => array( + 'description' => 'The user-customizable part of the URL alias.', + 'type' => 'varchar', + 'length' => 255, + 'not null' => FALSE, + ), + ); + return array( + 'columns' => $columns, + 'foreign keys' => array( + 'path_url_alias' => array( + 'table' => 'url_alias', + 'columns' => array( + 'pid' => 'pid', + ), + ), + ), + ); +} diff --git a/core/modules/path/path.module b/core/modules/path/path.module index 942fbb6..0c3b316 100644 --- a/core/modules/path/path.module +++ b/core/modules/path/path.module @@ -5,9 +5,7 @@ * Enables users to rename URLs. */ -use Drupal\node\Plugin\Core\Entity\Node; - -use Drupal\taxonomy\Plugin\Core\Entity\Term; +use Drupal\Core\Entity\EntityInterface; /** * Implements hook_help(). @@ -39,6 +37,160 @@ function path_help($path, $arg) { } /** + * Implements hook_field_info(). + */ +function path_field_info() { + $types['path'] = array( + 'label' => t('URL alias'), + 'description' => t('This field stores an URL alias in the database.'), + 'default_widget' => 'path_default', + 'instance_settings' => array( + 'pattern' => array( + 'prefix' => NULL, + 'auto' => FALSE, + 'default' => NULL, + ), + ), + ); + return $types; +} + +/** + * Implements hook_field_is_empty(). + */ +function path_field_is_empty($item, $field) { + return !isset($item['value']) || $item['value'] === ''; +} + +/** + * Implements hook_field_insert(). + */ +function path_field_insert($entity_type, $entity, $field, $instance, $langcode, &$items) { + foreach ($items as &$item) { + $item['value'] = trim($item['value']); + if (!empty($item['value'])) { + $uri = $entity->uri(); + $item['source'] = $uri['path']; + $item['langcode'] = $langcode; + if (!empty($instance['settings']['pattern']['prefix'])) { + $item['alias'] = $instance['settings']['pattern']['prefix'] . '/' . $item['value']; + } + else { + $item['alias'] = $item['value']; + } + // path_save() populates $item['pid']. + path_save($item); + } + } +} + +/** + * Implements hook_field_update(). + */ +function path_field_update($entity_type, $entity, $field, $instance, $langcode, &$items) { + foreach ($items as &$item) { + $item['value'] = trim($item['value']); + // Delete old alias if it was erased. + if (!empty($item['pid']) && empty($item['value'])) { + path_delete($item['pid']); + $item['pid'] = NULL; + } + if (!empty($item['value'])) { + $uri = $entity->uri(); + $item['source'] = $uri['path']; + $item['langcode'] = $langcode; + // The field widget might override the prefix, in case the prefix + // configured for the field instance is not part of the stored alias. + // @todo This looks wrong and will utterly fail when updating an entity + // programmatically, but not sure how to address the possibility differently. + if (isset($item['prefix'])) { + $item['alias'] = $item['prefix'] . $item['value']; + } + elseif (!empty($instance['settings']['pattern']['prefix'])) { + $item['alias'] = $instance['settings']['pattern']['prefix'] . '/' . $item['value']; + } + else { + $item['alias'] = $item['value']; + } + // path_save() populates $item['pid']. + path_save($item); + } + } +} + +/** + * Implements hook_field_delete(). + */ +function path_field_delete($entity_type, $entity, $field, $instance, $langcode, &$items) { + foreach ($items as &$item) { + if (!empty($item['pid'])) { + path_delete($item['pid']); + } + } +} + +/** + * Implements hook_field_instance_settings_form(). + */ +function path_field_instance_settings_form($field, $instance) { + $settings = $instance['settings']; + + if (!isset($settings['pattern']['prefix'])) { + $settings['pattern']['prefix'] = $instance['bundle']; + } + + $form['pattern'] = array( + '#type' => 'fieldset', + '#title' => t('URL alias pattern'), + '#collapsible' => FALSE, + '#element_validate' => array('path_field_instance_settings_form_pattern_validate'), + ); + $form['pattern']['prefix'] = array( + '#type' => 'textfield', + '#title' => t('Prefix'), + '#default_value' => isset($settings['pattern']['prefix']) ? $settings['pattern']['prefix'] : NULL, + '#maxlength' => 128, + '#description' => t('Enter a non-customizable URL alias prefix for all aliases of this field; e.g., !example.', array( + '!example' => "'" . check_plain($instance['entity_type'] . '/' . $instance['bundle']) . "'", + )), + ); + $form['pattern']['auto'] = array( + '#type' => 'checkbox', + '#title' => t('Automatically create alias'), + '#default_value' => isset($settings['pattern']['auto']) ? $settings['pattern']['auto'] : NULL, + // @todo Add token support. + '#access' => FALSE, + ); + $form['pattern']['default'] = array( + '#type' => 'textfield', + '#title' => t('Default alias'), + '#default_value' => isset($settings['pattern']['default']) ? $settings['pattern']['default'] : NULL, + '#maxlength' => 128, + // @todo Add token support. + '#access' => FALSE, + '#description' => t('@todo Output some example tokens specific to the entity type/bundle.'), + '#states' => array( + 'visible' => array( + ':input[name*="pattern][auto"]' => array('checked' => TRUE), + ), + ), + ); + return $form; +} + +/** + * #element_validate handler for 'pattern' in path_field_instance_settings_form(). + */ +function path_field_instance_settings_form_pattern_validate(&$element, &$form_state) { + // Ensure that the prefix does not contain a leading or trailing slash. + $element['prefix']['#value'] = trim($element['prefix']['#value'], '/'); + form_set_value($element['prefix'], $element['prefix']['#value'], $form_state); + + // @todo Validate that tokens in 'prefix' and 'default' exist. + // @todo Validate that 'default' contains at least one token. +} + +/** * Implements hook_permission(). */ function path_permission() { @@ -95,225 +247,67 @@ function path_menu() { } /** - * Implements hook_form_BASE_FORM_ID_alter() for node_form(). - * - * @see path_form_element_validate() + * Implements hook_entity_delete(). */ -function path_form_node_form_alter(&$form, $form_state) { - $node = $form_state['controller']->getEntity($form_state); - $path = array(); - if (!empty($node->nid)) { - $conditions = array('source' => 'node/' . $node->nid); - if ($node->langcode != LANGUAGE_NOT_SPECIFIED) { - $conditions['langcode'] = $node->langcode; - } - $path = path_load($conditions); - if ($path === FALSE) { - $path = array(); - } - } - $path += array( - 'pid' => NULL, - 'source' => isset($node->nid) ? 'node/' . $node->nid : NULL, - 'alias' => '', - 'langcode' => isset($node->langcode) ? $node->langcode : LANGUAGE_NOT_SPECIFIED, - ); - - $form['path'] = array( - '#type' => 'fieldset', - '#title' => t('URL path settings'), - '#collapsible' => TRUE, - '#collapsed' => empty($path['alias']), - '#group' => 'additional_settings', - '#attributes' => array( - 'class' => array('path-form'), - ), - '#attached' => array( - 'library' => array(array('path', 'drupal.path')), - ), - '#access' => user_access('create url aliases') || user_access('administer url aliases'), - '#weight' => 30, - '#tree' => TRUE, - '#element_validate' => array('path_form_element_validate'), - ); - $form['path']['alias'] = array( - '#type' => 'textfield', - '#title' => t('URL alias'), - '#default_value' => $path['alias'], - '#maxlength' => 255, - '#description' => t('The alternative URL for this content. Use a relative path without a trailing slash. For example, enter "about" for the about page.'), - ); - $form['path']['pid'] = array('#type' => 'value', '#value' => $path['pid']); - $form['path']['source'] = array('#type' => 'value', '#value' => $path['source']); - $form['path']['langcode'] = array('#type' => 'value', '#value' => $path['langcode']); -} - -/** - * Form element validation handler for URL alias form element. - * - * @see path_form_node_form_alter() - */ -function path_form_element_validate($element, &$form_state, $complete_form) { - if (!empty($form_state['values']['path']['alias'])) { - // Trim the submitted value. - $alias = trim($form_state['values']['path']['alias']); - form_set_value($element['alias'], $alias, $form_state); - // Node language needs special care. Since the language of the URL alias - // depends on the node language, and the node language can be switched - // right within the same form, we need to conditionally overload the - // originally assigned URL alias language. - // @todo Remove this after converting Path module to a field, and, after - // stopping Locale module from abusing the content language system. - if (isset($form_state['values']['langcode'])) { - form_set_value($element['langcode'], $form_state['values']['langcode'], $form_state); - } - - $path = $form_state['values']['path']; - - // Ensure that the submitted alias does not exist yet. - $query = db_select('url_alias') - ->condition('alias', $path['alias']) - ->condition('langcode', $path['langcode']); - if (!empty($path['source'])) { - $query->condition('source', $path['source'], '<>'); - } - $query->addExpression('1'); - $query->range(0, 1); - if ($query->execute()->fetchField()) { - form_error($element, t('The alias is already in use.')); - } - } -} - -/** - * Implements hook_node_insert(). - */ -function path_node_insert(Node $node) { - if (isset($node->path)) { - $path = $node->path; - $path['alias'] = trim($path['alias']); - // Only save a non-empty alias. - if (!empty($path['alias'])) { - // Ensure fields for programmatic executions. - $path['source'] = 'node/' . $node->nid; - $path['langcode'] = isset($node->langcode) ? $node->langcode : LANGUAGE_NOT_SPECIFIED; - path_save($path); - } - } +function path_entity_delete(EntityInterface $entity) { + // Delete all aliases associated with this entity. + $uri = $entity->uri(); + path_delete(array('source' => $uri['path'])); } /** - * Implements hook_node_update(). + * Implements hook_path_delete(). */ -function path_node_update(Node $node) { - if (isset($node->path)) { - $path = $node->path; - $path['alias'] = trim($path['alias']); - // Delete old alias if user erased it. - if (!empty($path['pid']) && empty($path['alias'])) { - path_delete($path['pid']); - } - // Only save a non-empty alias. - if (!empty($path['alias'])) { - // Ensure fields for programmatic executions. - $path['source'] = 'node/' . $node->nid; - $path['langcode'] = isset($node->langcode) ? $node->langcode : LANGUAGE_NOT_SPECIFIED; - path_save($path); +function path_path_delete($path) { + // EntityFieldQuery does not support field queries across entity types, so + // iterate over all path field instances individually and update their field + // values accordingly. + // Please note that the entirety of the following code will update a *single* + // entity only, but Drupal core no longer provides a simple way for retrieving + // all entities that have a certain field value. + $entity_types = array(); + foreach (field_info_field_map() as $field_name => $info) { + if ($info['type'] == 'path') { + foreach ($info['bundles'] as $entity_type => $bundles) { + $entity_types[$entity_type][$field_name] = $bundles; + } } } -} - -/** - * Implements hook_node_predelete(). - */ -function path_node_predelete(Node $node) { - // Delete all aliases associated with this node. - path_delete(array('source' => 'node/' . $node->nid)); -} - -/** - * Implements hook_form_FORM_ID_alter() for taxonomy_term_form(). - */ -function path_form_taxonomy_term_form_alter(&$form, $form_state) { - // Make sure this does not show up on the delete confirmation form. - if (empty($form_state['confirm_delete'])) { - $term = $form_state['controller']->getEntity($form_state); - $path = (isset($term->tid) ? path_load('taxonomy/term/' . $term->tid) : array()); - if ($path === FALSE) { - $path = array(); + foreach ($entity_types as $entity_type => $field_info) { + $query = entity_query($entity_type); + $group = $query->orConditionGroup(); + foreach ($field_info as $field_name => $bundles) { + $group->condition($field_name . '.pid', $path['pid']); } - $path += array( - 'pid' => NULL, - 'source' => isset($term->tid) ? 'taxonomy/term/' . $term->tid : NULL, - 'alias' => '', - 'langcode' => LANGUAGE_NOT_SPECIFIED, - ); - $form['path'] = array( - '#access' => user_access('create url aliases') || user_access('administer url aliases'), - '#tree' => TRUE, - '#element_validate' => array('path_form_element_validate'), - ); - $form['path']['alias'] = array( - '#type' => 'textfield', - '#title' => t('URL alias'), - '#default_value' => $path['alias'], - '#maxlength' => 255, - '#weight' => 0, - '#description' => t("Optionally specify an alternative URL by which this term can be accessed. Use a relative path and don't add a trailing slash or the URL alias won't work."), - ); - $form['path']['pid'] = array('#type' => 'value', '#value' => $path['pid']); - $form['path']['source'] = array('#type' => 'value', '#value' => $path['source']); - $form['path']['langcode'] = array('#type' => 'value', '#value' => $path['langcode']); - } -} - -/** - * Implements hook_taxonomy_term_insert(). - */ -function path_taxonomy_term_insert(Term $term) { - if (isset($term->path)) { - $path = $term->path; - $path['alias'] = trim($path['alias']); - // Only save a non-empty alias. - if (!empty($path['alias'])) { - // Ensure fields for programmatic executions. - $path['source'] = 'taxonomy/term/' . $term->tid; - $path['langcode'] = LANGUAGE_NOT_SPECIFIED; - path_save($path); + $query->condition($group); + $ids = $query->execute(); + if (!$ids) { + continue; } - } -} -/** - * Implements hook_taxonomy_term_update(). - */ -function path_taxonomy_term_update(Term $term) { - if (isset($term->path)) { - $path = $term->path; - $path['alias'] = trim($path['alias']); - // Delete old alias if user erased it. - if (!empty($path['pid']) && empty($path['alias'])) { - path_delete($path['pid']); - } - // Only save a non-empty alias. - if (!empty($path['alias'])) { - // Ensure fields for programmatic executions. - $path['source'] = 'taxonomy/term/' . $term->tid; - $path['langcode'] = LANGUAGE_NOT_SPECIFIED; - path_save($path); + foreach (entity_load_multiple($entity_type, $ids) as $id => $entity) { + $changed = FALSE; + foreach ($field_info as $field_name => $bundles) { + // @todo Update for EntityNG, once core entities are converted. + if (isset($entity->{$field_name})) { + foreach ($entity->{$field_name} as $langcode => &$items) { + foreach ($items as $delta => $item) { + if (isset($item['pid']) && $item['pid'] == $path['pid']) { + unset($items[$delta]); + $changed = TRUE; + } + } + } + } + } + if ($changed) { + $entity->save(); + } } } } /** - * Implements hook_taxonomy_term_delete(). - */ -function path_taxonomy_term_delete(Term $term) { - // Delete all aliases associated with this term. - path_delete(array('source' => 'taxonomy/term/' . $term->tid)); -} - -/** * Implements hook_library_info(). */ function path_library_info() {