diff --git a/core/modules/comment/lib/Drupal/comment/Plugin/entity_reference/selection/CommentSelection.php b/core/modules/comment/lib/Drupal/comment/Plugin/entity_reference/selection/CommentSelection.php new file mode 100644 index 0000000..de91bb1 --- /dev/null +++ b/core/modules/comment/lib/Drupal/comment/Plugin/entity_reference/selection/CommentSelection.php @@ -0,0 +1,81 @@ +condition('status', COMMENT_PUBLISHED); + } + return $query; + } + + /** + * Overrides SelectionBase::entityQueryAlter(). + */ + public function entityQueryAlter(SelectInterface $query) { + $tables = $query->getTables(); + $base_table = $tables['base_table']['alias']; + + // The Comment module doesn't implement any proper comment access, + // and as a consequence doesn't make sure that comments cannot be viewed + // when the user doesn't have access to the node. + $node_alias = $query->innerJoin('node', 'n', '%alias.nid = ' . $base_table . '.nid'); + // Pass the query to the node access control. + $this->reAlterQuery($query, 'node_access', $node_alias); + + // Alas, the comment entity exposes a bundle, but doesn't have a bundle + // column in the database. We have to alter the query ourselves to go fetch + // the bundle. + $conditions = &$query->conditions(); + foreach ($conditions as $key => &$condition) { + if ($key !== '#conjunction' && is_string($condition['field']) && $condition['field'] === 'node_type') { + $condition['field'] = $node_alias . '.type'; + foreach ($condition['value'] as &$value) { + if (substr($value, 0, 13) == 'comment_node_') { + $value = substr($value, 13); + } + } + break; + } + } + + // Passing the query to node_query_node_access_alter() is sadly + // insufficient for nodes. + // @see SelectionEntityTypeNode::entityQueryAlter() + if (!user_access('bypass node access') && !count(module_implements('node_grants'))) { + $query->condition($node_alias . '.status', 1); + } + } +} diff --git a/core/modules/field/modules/entity_reference/entity_reference.install b/core/modules/field/modules/entity_reference/entity_reference.install index efd1971..17030ef 100644 --- a/core/modules/field/modules/entity_reference/entity_reference.install +++ b/core/modules/field/modules/entity_reference/entity_reference.install @@ -32,17 +32,18 @@ function entity_reference_field_schema($field) { ); // Create a foreign key to the target entity type base type. - // @todo It's still not safe to call entity_get_info() in here.. -// $entity_type = $field['settings']['target_type']; -// $entity_info = entity_get_info($entity_type); -// -// $base_table = $entity_info['base_table']; -// $id_column = $entity_info['entity_keys']['id']; -// -// $schema['foreign keys'][$base_table] = array( -// 'table' => $base_table, -// 'columns' => array('target_id' => $id_column), -// ); + // @todo It's still not safe to call entity_get_info() in here. + // see http://drupal.org/node/1847582 + // $entity_type = $field['settings']['target_type']; + // $entity_info = entity_get_info($entity_type); + // + // $base_table = $entity_info['base_table']; + // $id_column = $entity_info['entity_keys']['id']; + // + // $schema['foreign keys'][$base_table] = array( + // 'table' => $base_table, + // 'columns' => array('target_id' => $id_column), + // ); return $schema; } diff --git a/core/modules/field/modules/entity_reference/entity_reference.module b/core/modules/field/modules/entity_reference/entity_reference.module index c94e685..3907ef4 100644 --- a/core/modules/field/modules/entity_reference/entity_reference.module +++ b/core/modules/field/modules/entity_reference/entity_reference.module @@ -16,14 +16,14 @@ function entity_reference_field_info() { $field_info['entity_reference'] = array( 'label' => t('Entity Reference'), - 'description' => t('This field reference another entity.'), + 'description' => t('This field references another entity.'), 'settings' => array( // Default to a primary entity type (i.e. node or user). 'target_type' => module_exists('node') ? 'node' : 'user', ), 'instance_settings' => array( // The selection handler for this instance. - 'handler' => 'generic', + 'handler' => 'base', // The handler settings. 'handler_settings' => array(), ), @@ -164,7 +164,7 @@ function _entity_reference_field_instance_settings_process($form, $form_state) { $instance = isset($form_state['entity_reference']['instance']) ? $form_state['entity_reference']['instance'] : $form['#instance']; $settings = $instance['settings']; - $settings += array('handler' => 'generic'); + $settings += array('handler' => 'base'); // Get all selection plugins for this entity type. $selection_plugins = drupal_container()->get('plugin.manager.entity_reference.selection')->getSelectionGroups($field['settings']['target_type']); @@ -173,8 +173,8 @@ function _entity_reference_field_instance_settings_process($form, $form_state) { $handlers = drupal_container()->get('plugin.manager.entity_reference.selection')->getDefinitions(); $handlers_options = array(); foreach ($handlers as $plugin_id => $plugin) { - // We only display base plugins (e.g. 'generic', 'views', ..) and not entity - // type specific plugins (e.g. 'generic_node', 'generic_user', ...). + // We only display base plugins (e.g. 'base', 'views', ..) and not entity + // type specific plugins (e.g. 'base_node', 'base_user', ...). if (in_array($plugin_id, $handler_groups)) { $handlers_options[$plugin_id] = check_plain($plugin['label']); } diff --git a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceBundle.php b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceBundle.php index 43959c0..3ea12f5 100644 --- a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceBundle.php +++ b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceBundle.php @@ -2,7 +2,7 @@ /** * @file - * Definition of Drupal\entity_reference\EntityReferenceBundle. + * Contains Drupal\entity_reference\EntityReferenceBundle. */ namespace Drupal\entity_reference; diff --git a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceRecursiveRenderingException.php b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceRecursiveRenderingException.php deleted file mode 100644 index a6f6c32..0000000 --- a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceRecursiveRenderingException.php +++ /dev/null @@ -1,14 +0,0 @@ -condition('status', COMMENT_PUBLISHED); - } - return $query; - } - - /** - * Overrides SelectionBase::entityQueryAlter(). - */ - public function entityQueryAlter(SelectInterface $query) { - $tables = $query->getTables(); - $base_table = $tables['base_table']['alias']; - - // The Comment module doesn't implement any proper comment access, - // and as a consequence doesn't make sure that comments cannot be viewed - // when the user doesn't have access to the node. - $node_alias = $query->innerJoin('node', 'n', '%alias.nid = ' . $base_table . '.nid'); - // Pass the query to the node access control. - $this->reAlterQuery($query, 'node_access', $node_alias); - - // Alas, the comment entity exposes a bundle, but doesn't have a bundle - // column in the database. We have to alter the query ourselves to go fetch - // the bundle. - $conditions = &$query->conditions(); - foreach ($conditions as $key => &$condition) { - if ($key !== '#conjunction' && is_string($condition['field']) && $condition['field'] === 'node_type') { - $condition['field'] = $node_alias . '.type'; - foreach ($condition['value'] as &$value) { - if (substr($value, 0, 13) == 'comment_node_') { - $value = substr($value, 13); - } - } - break; - } - } - - // Passing the query to node_query_node_access_alter() is sadly - // insufficient for nodes. - // @see SelectionEntityTypeNode::entityQueryAlter() - if (!user_access('bypass node access') && !count(module_implements('node_grants'))) { - $query->condition($node_alias . '.status', 1); - } - } -} diff --git a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/entity_reference/selection/File.php b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/entity_reference/selection/File.php deleted file mode 100644 index 004a28f..0000000 --- a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/entity_reference/selection/File.php +++ /dev/null @@ -1,36 +0,0 @@ -condition('status', FILE_STATUS_PERMANENT); - } -} diff --git a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/entity_reference/selection/Node.php b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/entity_reference/selection/Node.php deleted file mode 100644 index 8707e35..0000000 --- a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/entity_reference/selection/Node.php +++ /dev/null @@ -1,44 +0,0 @@ -condition('status', NODE_PUBLISHED); - } - return $query; - } -} diff --git a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/entity_reference/selection/SelectionBase.php b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/entity_reference/selection/SelectionBase.php new file mode 100644 index 0000000..1dc9a56 --- /dev/null +++ b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/entity_reference/selection/SelectionBase.php @@ -0,0 +1,344 @@ +field = $field; + $this->instance = $instance; + $this->entity = $entity; + } + + /** + * Implements SelectionInterface::settingsForm(). + */ + public static function settingsForm($field, $instance) { + $entity_info = entity_get_info($field['settings']['target_type']); + + // Merge-in default values. + if (!isset($instance['settings']['handler_settings'])) { + $instance['settings']['handler_settings'] = array(); + } + $instance['settings']['handler_settings'] += array( + 'target_bundles' => array(), + 'sort' => array( + 'type' => 'none', + ) + ); + + if (!empty($entity_info['entity_keys']['bundle'])) { + $bundles = array(); + foreach ($entity_info['bundles'] as $bundle_name => $bundle_info) { + $bundles[$bundle_name] = $bundle_info['label']; + } + + $form['target_bundles'] = array( + '#type' => 'checkboxes', + '#title' => t('Target bundles'), + '#options' => $bundles, + '#default_value' => $instance['settings']['handler_settings']['target_bundles'], + '#size' => 6, + '#multiple' => TRUE, + '#description' => t('The bundles of the entity type that can be referenced. Optional, leave empty for all bundles.'), + '#element_validate' => array('_entity_reference_element_validate_filter'), + ); + } + else { + $form['target_bundles'] = array( + '#type' => 'value', + '#value' => array(), + ); + } + + $form['sort']['type'] = array( + '#type' => 'select', + '#title' => t('Sort by'), + '#options' => array( + 'none' => t("Don't sort"), + 'property' => t('A property of the base table of the entity'), + 'field' => t('A field attached to this entity'), + ), + '#ajax' => TRUE, + '#limit_validation_errors' => array(), + '#default_value' => $instance['settings']['handler_settings']['sort']['type'], + ); + + $form['sort']['settings'] = array( + '#type' => 'container', + '#attributes' => array('class' => array('entity_reference-settings')), + '#process' => array('_entity_reference_form_process_merge_parent'), + ); + + if ($instance['settings']['handler_settings']['sort']['type'] == 'property') { + // Merge-in default values. + $instance['settings']['handler_settings']['sort'] += array( + 'property' => NULL, + ); + + $form['sort']['settings']['property'] = array( + '#type' => 'select', + '#title' => t('Sort property'), + '#required' => TRUE, + '#options' => drupal_map_assoc($entity_info['schema_fields_sql']['base_table']), + '#default_value' => $instance['settings']['handler_settings']['sort']['property'], + ); + } + elseif ($instance['settings']['handler_settings']['sort']['type'] == 'field') { + // Merge-in default values. + $instance['settings']['handler_settings']['sort'] += array( + 'field' => NULL, + ); + + $fields = array(); + foreach (field_info_instances($field['settings']['target_type']) as $bundle_name => $bundle_instances) { + foreach ($bundle_instances as $instance_name => $instance_info) { + $field_info = field_info_field($instance_name); + foreach ($field_info['columns'] as $column_name => $column_info) { + $fields[$instance_name . ':' . $column_name] = t('@label (column @column)', array('@label' => $instance_info['label'], '@column' => $column_name)); + } + } + } + + $form['sort']['settings']['field'] = array( + '#type' => 'select', + '#title' => t('Sort field'), + '#required' => TRUE, + '#options' => $fields, + '#default_value' => $instance['settings']['handler_settings']['sort']['field'], + ); + } + + if ($instance['settings']['handler_settings']['sort']['type'] != 'none') { + // Merge-in default values. + $instance['settings']['handler_settings']['sort'] += array( + 'direction' => 'ASC', + ); + + $form['sort']['settings']['direction'] = array( + '#type' => 'select', + '#title' => t('Sort direction'), + '#required' => TRUE, + '#options' => array( + 'ASC' => t('Ascending'), + 'DESC' => t('Descending'), + ), + '#default_value' => $instance['settings']['handler_settings']['sort']['direction'], + ); + } + + return $form; + } + + /** + * Implements SelectionInterface::getReferencableEntities(). + */ + public function getReferencableEntities($match = NULL, $match_operator = 'CONTAINS', $limit = 0) { + $target_type = $this->field['settings']['target_type']; + + $query = $this->buildEntityQuery($match, $match_operator); + if ($limit > 0) { + $query->range(0, $limit); + } + + $result = $query->execute(); + + if (empty($result)) { + return array(); + } + + $options = array(); + $entities = entity_load_multiple($target_type, $result); + foreach ($entities as $entity_id => $entity) { + $bundle = $entity->bundle(); + $options[$bundle][$entity_id] = check_plain($entity->label()); + } + + return $options; + } + + /** + * Implements SelectionInterface::countReferencableEntities(). + */ + public function countReferencableEntities($match = NULL, $match_operator = 'CONTAINS') { + $query = $this->buildEntityQuery($match, $match_operator); + return $query + ->count() + ->execute(); + } + + /** + * Implements SelectionInterface::validateReferencableEntities(). + */ + public function validateReferencableEntities(array $ids) { + $result = array(); + if ($ids) { + $target_type = $this->field['settings']['target_type']; + $entity_info = entity_get_info($target_type); + $query = $this->buildEntityQuery(); + $result = $query + ->condition($entity_info['entity_keys']['id'], $ids, 'IN') + ->execute(); + } + + return $result; + } + + /** + * Implements SelectionInterface::validateAutocompleteInput(). + */ + public function validateAutocompleteInput($input, &$element, &$form_state, $form) { + $entities = $this->getReferencableEntities($input, '=', 6); + $params = array( + '%value' => $input, + '@value' => $input, + ); + if (empty($entities)) { + // Error if there are no entities available for a required field. + form_error($element, t('There are no entities matching "%value".', $params)); + } + elseif (count($entities) > 5) { + $params['@id'] = key($entities); + // Error if there are more than 5 matching entities. + form_error($element, t('Many entities are called %value. Specify the one you want by appending the id in parentheses, like "@value (@id)".', $params)); + } + elseif (count($entities) > 1) { + // More helpful error if there are only a few matching entities. + $multiples = array(); + foreach ($entities as $id => $name) { + $multiples[] = $name . ' (' . $id . ')'; + } + $params['@id'] = $id; + form_error($element, t('Multiple entities match this reference; "%multiple". Specify the one you want by appending the id in parentheses, like "@value (@id)".', array('%multiple' => implode('", "', $multiples)))); + } + else { + // Take the one and only matching entity. + return key($entities); + } + } + + /** + * Builds an EntityFieldQuery to get referencable entities. + * + * @param string|null $match + * (Optional) Text to match the label against. Defaults to NULL. + * @param string $match_operator + * (Optional) The operation the matching should be done with. Defaults + * to "CONTAINS". + * + * @return + * The query object with the basic conditions and sorting applied to + * it. + */ + public function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS') { + $target_type = $this->field['settings']['target_type']; + $entity_info = entity_get_info($target_type); + + $query = entity_query($target_type); + if (!empty($this->instance['settings']['handler_settings']['target_bundles'])) { + $bundle_key = $entity_info['entity_keys']['bundle']; + $query->condition($bundle_key, $this->instance['settings']['handler_settings']['target_bundles'], 'IN'); + } + + if (isset($match) && isset($entity_info['entity_keys']['label'])) { + $query->condition($entity_info['entity_keys']['label'], $match, $match_operator); + } + + // Add entity-access tag. + $query->addTag($this->field['settings']['target_type'] . '_access'); + + // Add the Selection handler for + // entity_reference_query_entity_reference_alter() + $query->addTag('entity_reference'); + $query->addMetaData('field', $this->field); + $query->addMetaData('entity_reference_selection_handler', $this); + + // Add the sort option. + if (!empty($this->instance['settings']['handler_settings']['sort'])) { + $sort_settings = $this->instance['settings']['handler_settings']['sort']; + if ($sort_settings['type'] == 'property') { + $query->sort($sort_settings['property'], $sort_settings['direction']); + } + elseif ($sort_settings['type'] == 'field') { + list($field, $column) = explode(':', $sort_settings['field'], 2); + $query->sort("$field.$column", $sort_settings['direction']); + } + } + + return $query; + } + + /** + * Implements SelectionInterface::entityQueryAlter(). + */ + public function entityQueryAlter(SelectInterface $query) { } + + /** + * Helper method: Passes a query to the alteration system again. + * + * This allows Entity Reference to add a tag to an existing query so it can + * ask access control mechanisms to alter it again. + */ + protected function reAlterQuery(AlterableInterface $query, $tag, $base_table) { + // Save the old tags and metadata. + // For some reason, those are public. + $old_tags = $query->alterTags; + $old_metadata = $query->alterMetaData; + + $query->alterTags = array($tag => TRUE); + $query->alterMetaData['base_table'] = $base_table; + drupal_alter(array('query', 'query_' . $tag), $query); + + // Restore the tags and metadata. + $query->alterTags = $old_tags; + $query->alterMetaData = $old_metadata; + } +} diff --git a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/entity_reference/selection/SelectionGeneric.php b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/entity_reference/selection/SelectionGeneric.php deleted file mode 100644 index 888e097..0000000 --- a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/entity_reference/selection/SelectionGeneric.php +++ /dev/null @@ -1,334 +0,0 @@ -field = $field; - $this->instance = $instance; - $this->entity = $entity; - } - - /** - * Implements SelectionInterface::settingsForm(). - */ - public static function settingsForm($field, $instance) { - $entity_info = entity_get_info($field['settings']['target_type']); - - // Merge-in default values. - if (!isset($instance['settings']['handler_settings'])) { - $instance['settings']['handler_settings'] = array(); - } - $instance['settings']['handler_settings'] += array( - 'target_bundles' => array(), - 'sort' => array( - 'type' => 'none', - ) - ); - - if (!empty($entity_info['entity_keys']['bundle'])) { - $bundles = array(); - foreach ($entity_info['bundles'] as $bundle_name => $bundle_info) { - $bundles[$bundle_name] = $bundle_info['label']; - } - - $form['target_bundles'] = array( - '#type' => 'checkboxes', - '#title' => t('Target bundles'), - '#options' => $bundles, - '#default_value' => $instance['settings']['handler_settings']['target_bundles'], - '#size' => 6, - '#multiple' => TRUE, - '#description' => t('The bundles of the entity type that can be referenced. Optional, leave empty for all bundles.'), - '#element_validate' => array('_entity_reference_element_validate_filter'), - ); - } - else { - $form['target_bundles'] = array( - '#type' => 'value', - '#value' => array(), - ); - } - - $form['sort']['type'] = array( - '#type' => 'select', - '#title' => t('Sort by'), - '#options' => array( - 'none' => t("Don't sort"), - 'property' => t('A property of the base table of the entity'), - 'field' => t('A field attached to this entity'), - ), - '#ajax' => TRUE, - '#limit_validation_errors' => array(), - '#default_value' => $instance['settings']['handler_settings']['sort']['type'], - ); - - $form['sort']['settings'] = array( - '#type' => 'container', - '#attributes' => array('class' => array('entity_reference-settings')), - '#process' => array('_entity_reference_form_process_merge_parent'), - ); - - if ($instance['settings']['handler_settings']['sort']['type'] == 'property') { - // Merge-in default values. - $instance['settings']['handler_settings']['sort'] += array( - 'property' => NULL, - ); - - $form['sort']['settings']['property'] = array( - '#type' => 'select', - '#title' => t('Sort property'), - '#required' => TRUE, - '#options' => drupal_map_assoc($entity_info['schema_fields_sql']['base_table']), - '#default_value' => $instance['settings']['handler_settings']['sort']['property'], - ); - } - elseif ($instance['settings']['handler_settings']['sort']['type'] == 'field') { - // Merge-in default values. - $instance['settings']['handler_settings']['sort'] += array( - 'field' => NULL, - ); - - $fields = array(); - foreach (field_info_instances($field['settings']['target_type']) as $bundle_name => $bundle_instances) { - foreach ($bundle_instances as $instance_name => $instance_info) { - $field_info = field_info_field($instance_name); - foreach ($field_info['columns'] as $column_name => $column_info) { - $fields[$instance_name . ':' . $column_name] = t('@label (column @column)', array('@label' => $instance_info['label'], '@column' => $column_name)); - } - } - } - - $form['sort']['settings']['field'] = array( - '#type' => 'select', - '#title' => t('Sort field'), - '#required' => TRUE, - '#options' => $fields, - '#default_value' => $instance['settings']['handler_settings']['sort']['field'], - ); - } - - if ($instance['settings']['handler_settings']['sort']['type'] != 'none') { - // Merge-in default values. - $instance['settings']['handler_settings']['sort'] += array( - 'direction' => 'ASC', - ); - - $form['sort']['settings']['direction'] = array( - '#type' => 'select', - '#title' => t('Sort direction'), - '#required' => TRUE, - '#options' => array( - 'ASC' => t('Ascending'), - 'DESC' => t('Descending'), - ), - '#default_value' => $instance['settings']['handler_settings']['sort']['direction'], - ); - } - - return $form; - } - - /** - * Implements SelectionInterface::getReferencableEntities(). - */ - public function getReferencableEntities($match = NULL, $match_operator = 'CONTAINS', $limit = 0) { - $target_type = $this->field['settings']['target_type']; - - $query = $this->buildEntityQuery($match, $match_operator); - if ($limit > 0) { - $query->range(0, $limit); - } - - $result = $query->execute(); - - if (empty($result)) { - return array(); - } - - $options = array(); - $entities = entity_load_multiple($target_type, $result); - foreach ($entities as $entity_id => $entity) { - $bundle = $entity->bundle(); - $options[$bundle][$entity_id] = check_plain($entity->label()); - } - - return $options; - } - - /** - * Implements SelectionInterface::countReferencableEntities(). - */ - public function countReferencableEntities($match = NULL, $match_operator = 'CONTAINS') { - $query = $this->buildEntityQuery($match, $match_operator); - return $query - ->count() - ->execute(); - } - - /** - * Implements SelectionInterface::validateReferencableEntities(). - */ - public function validateReferencableEntities(array $ids) { - $result = array(); - if ($ids) { - $target_type = $this->field['settings']['target_type']; - $entity_info = entity_get_info($target_type); - $query = $this->buildEntityQuery(); - $result = $query - ->condition($entity_info['entity_keys']['id'], $ids, 'IN') - ->execute(); - } - - return $result; - } - - /** - * Implements SelectionInterface::validateAutocompleteInput(). - */ - public function validateAutocompleteInput($input, &$element, &$form_state, $form) { - $entities = $this->getReferencableEntities($input, '=', 6); - $params = array( - '%value' => $input, - '@value' => $input, - ); - if (empty($entities)) { - // Error if there are no entities available for a required field. - form_error($element, t('There are no entities matching "%value".', $params)); - } - elseif (count($entities) > 5) { - $params['@id'] = key($entities); - // Error if there are more than 5 matching entities. - form_error($element, t('Many entities are called %value. Specify the one you want by appending the id in parentheses, like "@value (@id)".', $params)); - } - elseif (count($entities) > 1) { - // More helpful error if there are only a few matching entities. - $multiples = array(); - foreach ($entities as $id => $name) { - $multiples[] = $name . ' (' . $id . ')'; - } - $params['@id'] = $id; - form_error($element, t('Multiple entities match this reference; "%multiple". Specify the one you want by appending the id in parentheses, like "@value (@id)".', array('%multiple' => implode('", "', $multiples)))); - } - else { - // Take the one and only matching entity. - return key($entities); - } - } - - /** - * Builds an EntityFieldQuery to get referencable entities. - */ - public function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS') { - $target_type = $this->field['settings']['target_type']; - $entity_info = entity_get_info($target_type); - - $query = entity_query($target_type); - if (!empty($this->instance['settings']['handler_settings']['target_bundles'])) { - $bundle_key = $entity_info['entity_keys']['bundle']; - $query->condition($bundle_key, $this->instance['settings']['handler_settings']['target_bundles'], 'IN'); - } - - if (isset($match) && isset($entity_info['entity_keys']['label'])) { - $query->condition($entity_info['entity_keys']['label'], $match, $match_operator); - } - - // Add entity-access tag. - $query->addTag($this->field['settings']['target_type'] . '_access'); - - // Add the Selection handler for - // entity_reference_query_entity_reference_alter() - $query->addTag('entity_reference'); - $query->addMetaData('field', $this->field); - $query->addMetaData('entity_reference_selection_handler', $this); - - // Add the sort option. - if (!empty($this->instance['settings']['handler_settings']['sort'])) { - $sort_settings = $this->instance['settings']['handler_settings']['sort']; - if ($sort_settings['type'] == 'property') { - $query->sort($sort_settings['property'], $sort_settings['direction']); - } - elseif ($sort_settings['type'] == 'field') { - list($field, $column) = explode(':', $sort_settings['field'], 2); - $query->sort("$field.$column", $sort_settings['direction']); - } - } - - return $query; - } - - /** - * Implements SelectionInterface::entityQueryAlter(). - */ - public function entityQueryAlter(SelectInterface $query) { } - - /** - * Helper method: Passes a query to the alteration system again. - * - * This allows Entity Reference to add a tag to an existing query so it can - * ask access control mechanisms to alter it again. - */ - protected function reAlterQuery(AlterableInterface $query, $tag, $base_table) { - // Save the old tags and metadata. - // For some reason, those are public. - $old_tags = $query->alterTags; - $old_metadata = $query->alterMetaData; - - $query->alterTags = array($tag => TRUE); - $query->alterMetaData['base_table'] = $base_table; - drupal_alter(array('query', 'query_' . $tag), $query); - - // Restore the tags and metadata. - $query->alterTags = $old_tags; - $query->alterMetaData = $old_metadata; - } -} diff --git a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/entity_reference/selection/Term.php b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/entity_reference/selection/Term.php deleted file mode 100644 index 00e8006..0000000 --- a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/entity_reference/selection/Term.php +++ /dev/null @@ -1,81 +0,0 @@ -getTables(); - $base_table = $tables['base_table']['alias']; - $vocabulary_alias = $query->innerJoin('taxonomy_vocabulary', 'n', '%alias.vid = ' . $base_table . '.vid'); - $query->addMetadata('base_table', $vocabulary_alias); - // Pass the query to the taxonomy access control. - $this->reAlterQuery($query, 'taxonomy_vocabulary_access', $vocabulary_alias); - - // Also, the taxonomy term entity exposes a bundle, but doesn't have a - // bundle column in the database. We have to alter the query ourselves to go - // fetch the bundle. - $conditions = &$query->conditions(); - foreach ($conditions as $key => &$condition) { - if ($key !== '#conjunction' && is_string($condition['field']) && $condition['field'] === 'vocabulary_machine_name') { - $condition['field'] = $vocabulary_alias . '.machine_name'; - break; - } - } - } - - /** - * Overrides SelectionBase::getReferencableEntities(). - */ - public function getReferencableEntities($match = NULL, $match_operator = 'CONTAINS', $limit = 0) { - if ($match || $limit) { - return parent::getReferencableEntities($match , $match_operator, $limit); - } - - $options = array(); - - // We imitate core by calling taxonomy_get_tree(). - $entity_info = entity_get_info('taxonomy_term'); - $bundles = !empty($this->instance['settings']['handler_settings']['target_bundles']) ? $this->instance['settings']['handler_settings']['target_bundles'] : array_keys($entity_info['bundles']); - - foreach ($bundles as $bundle) { - if ($vocabulary = taxonomy_vocabulary_machine_name_load($bundle)) { - if ($terms = taxonomy_get_tree($vocabulary->vid, 0)) { - foreach ($terms as $term) { - $options[$vocabulary->machine_name][$term->tid] = str_repeat('-', $term->depth) . check_plain($term->name); - } - } - } - } - - return $options; - } -} diff --git a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/entity_reference/selection/User.php b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/entity_reference/selection/User.php deleted file mode 100644 index 9c64364..0000000 --- a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/entity_reference/selection/User.php +++ /dev/null @@ -1,85 +0,0 @@ -condition('name', $match, $match_operator); - } - - // Adding the 'user_access' tag is sadly insufficient for users: core - // requires us to also know about the concept of 'blocked' and 'active'. - if (!user_access('administer users')) { - $query->condition('status', 1); - } - return $query; - } - - /** - * Overrides SelectionBase::entityQueryAlter(). - */ - public function entityQueryAlter(SelectInterface $query) { - if (user_access('administer users')) { - // In addition, if the user is administrator, we need to make sure to - // match the anonymous user, that doesn't actually have a name in the - // database. - $conditions = &$query->conditions(); - foreach ($conditions as $key => $condition) { - if ($key !== '#conjunction' && is_string($condition['field']) && $condition['field'] === 'users.name') { - // Remove the condition. - unset($conditions[$key]); - - // Re-add the condition and a condition on uid = 0 so that we end up - // with a query in the form: - // WHERE (name LIKE :name) OR (:anonymous_name LIKE :name AND uid = 0) - $or = db_or(); - $or->condition($condition['field'], $condition['value'], $condition['operator']); - // Sadly, the Database layer doesn't allow us to build a condition - // in the form ':placeholder = :placeholder2', because the 'field' - // part of a condition is always escaped. - // As a (cheap) workaround, we separately build a condition with no - // field, and concatenate the field and the condition separately. - $value_part = db_and(); - $value_part->condition('anonymous_name', $condition['value'], $condition['operator']); - $value_part->compile(Database::getConnection(), $query); - $or->condition(db_and() - ->where(str_replace('anonymous_name', ':anonymous_name', (string) $value_part), $value_part->arguments() + array(':anonymous_name' => user_format_name(user_load(0)))) - ->condition('users.uid', 0) - ); - $query->condition($or); - } - } - } - } -} diff --git a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceEntityFormatter.php b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceEntityFormatter.php index bc811ca..e32621c 100644 --- a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceEntityFormatter.php +++ b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceEntityFormatter.php @@ -2,7 +2,7 @@ /** * @file - * Definition of Drupal\entity_reference\Plugin\field\formatter\EntityReferenceEntityFormatter. + * Contains Drupal\entity_reference\Plugin\field\formatter\EntityReferenceEntityFormatter. */ namespace Drupal\entity_reference\Plugin\field\formatter; @@ -10,7 +10,7 @@ use Drupal\Core\Annotation\Plugin; use Drupal\Core\Annotation\Translation; use Drupal\Core\Entity\EntityInterface; -use Drupal\entity_reference\EntityReferenceRecursiveRenderingException; +use Drupal\entity_reference\RecursiveRenderingException; use Drupal\entity_reference\Plugin\field\formatter\EntityReferenceFormatterBase; /** @@ -94,7 +94,7 @@ public function viewElements(EntityInterface $entity, $langcode, array $items) { static $depth = 0; $depth++; if ($depth > 20) { - throw new EntityReferenceRecursiveRenderingException(format_string('Recursive rendering detected when rendering entity @entity_type(@entity_id). Aborting rendering.', array('@entity_type' => $entity_type, '@entity_id' => $item['target_id']))); + throw new RecursiveRenderingException(format_string('Recursive rendering detected when rendering entity @entity_type(@entity_id). Aborting rendering.', array('@entity_type' => $entity_type, '@entity_id' => $item['target_id']))); } $entity = clone $item['entity']; diff --git a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceFormatterBase.php b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceFormatterBase.php index 61f3606..f6b5fac 100644 --- a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceFormatterBase.php +++ b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceFormatterBase.php @@ -2,7 +2,7 @@ /** * @file - * Definition of Drupal\entity_reference\Plugin\field\formatter\EntityReferenceFormatterBase. + * Contains Drupal\entity_reference\Plugin\field\formatter\EntityReferenceFormatterBase. */ namespace Drupal\entity_reference\Plugin\field\formatter; diff --git a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceIdFormatter.php b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceIdFormatter.php index 033f1cf..148e64d 100644 --- a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceIdFormatter.php +++ b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceIdFormatter.php @@ -2,7 +2,7 @@ /** * @file - * Definition of Drupal\entity_reference\Plugin\field\formatter\EntityReferenceIdFormatter. + * Contains Drupal\entity_reference\Plugin\field\formatter\EntityReferenceIdFormatter. */ namespace Drupal\entity_reference\Plugin\field\formatter; diff --git a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceLabelFormatter.php b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceLabelFormatter.php index 0464bb8..efae069 100644 --- a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceLabelFormatter.php +++ b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceLabelFormatter.php @@ -2,7 +2,7 @@ /** * @file - * Definition of Drupal\entity_reference\Plugin\field\formatter\EntityReferenceLabelFormatter. + * Contains Drupal\entity_reference\Plugin\field\formatter\EntityReferenceLabelFormatter. */ namespace Drupal\entity_reference\Plugin\field\formatter; diff --git a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteTagsWidget.php b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteTagsWidget.php index 56d84d1..c347bc9 100644 --- a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteTagsWidget.php +++ b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteTagsWidget.php @@ -2,7 +2,7 @@ /** * @file - * Definition of Drupal\entity_reference\Plugin\field\widget\AutocompleteTagsWidget. + * Contains Drupal\entity_reference\Plugin\field\widget\AutocompleteTagsWidget. */ namespace Drupal\entity_reference\Plugin\field\widget; diff --git a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidget.php b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidget.php index cf64838..b62dc50 100644 --- a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidget.php +++ b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidget.php @@ -2,7 +2,7 @@ /** * @file - * Definition of Drupal\entity_reference\Plugin\field\widget\AutocompleteWidget. + * Contains Drupal\entity_reference\Plugin\field\widget\AutocompleteWidget. */ namespace Drupal\entity_reference\Plugin\field\widget; diff --git a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidgetBase.php b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidgetBase.php index 5d0bb89..f00a8c2 100644 --- a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidgetBase.php +++ b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidgetBase.php @@ -2,7 +2,7 @@ /** * @file - * Definition of Drupal\entity_reference\Plugin\field\widget\AutocompleteWidgetBase. + * Contains Drupal\entity_reference\Plugin\field\widget\AutocompleteWidgetBase. */ namespace Drupal\entity_reference\Plugin\field\widget; diff --git a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/views/display/EntityReference.php b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/views/display/EntityReference.php index a8b0d1f..4971653 100644 --- a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/views/display/EntityReference.php +++ b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/views/display/EntityReference.php @@ -2,7 +2,7 @@ /** * @file - * Definition of Drupal\entity_reference\Plugin\views\display\EntityReference. + * Contains Drupal\entity_reference\Plugin\views\display\EntityReference. */ namespace Drupal\entity_reference\Plugin\views\display; diff --git a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/views/row/EntityReference.php b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/views/row/EntityReference.php index 9856911..42ad62b 100644 --- a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/views/row/EntityReference.php +++ b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/views/row/EntityReference.php @@ -2,7 +2,7 @@ /** * @file - * Definition of Drupal\entity_reference\Plugin\views\row\EntityReference. + * Contains Drupal\entity_reference\Plugin\views\row\EntityReference. */ namespace Drupal\entity_reference\Plugin\views\row; diff --git a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/views/style/EntityReference.php b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/views/style/EntityReference.php index 1e0f602..897fb7e 100644 --- a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/views/style/EntityReference.php +++ b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Plugin/views/style/EntityReference.php @@ -2,7 +2,7 @@ /** * @file - * Definition of Drupal\entity_reference\Plugin\views\style\EntityReference. + * Contains Drupal\entity_reference\Plugin\views\style\EntityReference. */ namespace Drupal\entity_reference\Plugin\views\style; diff --git a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/RecursiveRenderingException.php b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/RecursiveRenderingException.php new file mode 100644 index 0000000..8834969 --- /dev/null +++ b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/RecursiveRenderingException.php @@ -0,0 +1,14 @@ +drupalPost(NULL, array(), t('Save field settings')); // The base handler should be selected by default. - $this->assertFieldByName('instance[settings][handler]', 'generic'); + $this->assertFieldByName('instance[settings][handler]', 'base'); // The base handler settings should be diplayed. $entity_type = 'node'; diff --git a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionAccessTest.php b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionAccessTest.php index 4b7f594..21a4a46 100644 --- a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionAccessTest.php +++ b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionAccessTest.php @@ -17,7 +17,7 @@ class EntityReferenceSelectionAccessTest extends WebTestBase { public static function getInfo() { return array( 'name' => 'Entity Reference Handlers', - 'description' => 'Tests for the generic handlers provided by Entity Reference.', + 'description' => 'Tests for the base handlers provided by Entity Reference.', 'group' => 'Entity Reference', ); } @@ -28,9 +28,7 @@ function setUp() { parent::setUp(); // Create an Article node type. - if ($this->profile != 'standard') { - $this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article')); - } + $this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article')); } protected function assertReferencable($field, $instance, $tests, $handler_name) { @@ -72,7 +70,7 @@ public function testNodeHandler() { ); $instance = array( 'settings' => array( - 'handler' => 'generic', + 'handler' => 'base', 'handler_settings' => array( 'target_bundles' => array(), ), @@ -210,7 +208,7 @@ public function testUserHandler() { ); $instance = array( 'settings' => array( - 'handler' => 'generic', + 'handler' => 'base', 'handler_settings' => array( 'target_bundles' => array(), ), @@ -350,7 +348,7 @@ public function testCommentHandler() { ); $instance = array( 'settings' => array( - 'handler' => 'generic', + 'handler' => 'base', 'handler_settings' => array( 'target_bundles' => array(), ), diff --git a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionSortTest.php b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionSortTest.php index 1f715f6..6cf4449 100644 --- a/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionSortTest.php +++ b/core/modules/field/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionSortTest.php @@ -28,9 +28,7 @@ function setUp() { parent::setUp(); // Create an Article node type. - if ($this->profile != 'standard') { - $this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article')); - } + $this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article')); } /** @@ -70,7 +68,7 @@ public function testSort() { $instance = array( 'settings' => array( - 'handler' => 'generic', + 'handler' => 'base', 'handler_settings' => array( 'target_bundles' => array(), // Add sorting. diff --git a/core/modules/file/lib/Drupal/file/Plugin/entity_reference/selection/FileSelection.php b/core/modules/file/lib/Drupal/file/Plugin/entity_reference/selection/FileSelection.php new file mode 100644 index 0000000..901a5e7 --- /dev/null +++ b/core/modules/file/lib/Drupal/file/Plugin/entity_reference/selection/FileSelection.php @@ -0,0 +1,36 @@ +condition('status', FILE_STATUS_PERMANENT); + } +} diff --git a/core/modules/node/lib/Drupal/node/Plugin/entity_reference/selection/NodeSelection.php b/core/modules/node/lib/Drupal/node/Plugin/entity_reference/selection/NodeSelection.php new file mode 100644 index 0000000..fd8a61f --- /dev/null +++ b/core/modules/node/lib/Drupal/node/Plugin/entity_reference/selection/NodeSelection.php @@ -0,0 +1,44 @@ +condition('status', NODE_PUBLISHED); + } + return $query; + } +} diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/entity_reference/selection/TermSelection.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/entity_reference/selection/TermSelection.php new file mode 100644 index 0000000..1c42a76 --- /dev/null +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/entity_reference/selection/TermSelection.php @@ -0,0 +1,81 @@ +getTables(); + $base_table = $tables['base_table']['alias']; + $vocabulary_alias = $query->innerJoin('taxonomy_vocabulary', 'n', '%alias.vid = ' . $base_table . '.vid'); + $query->addMetadata('base_table', $vocabulary_alias); + // Pass the query to the taxonomy access control. + $this->reAlterQuery($query, 'taxonomy_vocabulary_access', $vocabulary_alias); + + // Also, the taxonomy term entity exposes a bundle, but doesn't have a + // bundle column in the database. We have to alter the query ourselves to go + // fetch the bundle. + $conditions = &$query->conditions(); + foreach ($conditions as $key => &$condition) { + if ($key !== '#conjunction' && is_string($condition['field']) && $condition['field'] === 'vocabulary_machine_name') { + $condition['field'] = $vocabulary_alias . '.machine_name'; + break; + } + } + } + + /** + * Overrides SelectionBase::getReferencableEntities(). + */ + public function getReferencableEntities($match = NULL, $match_operator = 'CONTAINS', $limit = 0) { + if ($match || $limit) { + return parent::getReferencableEntities($match , $match_operator, $limit); + } + + $options = array(); + + // We imitate core by calling taxonomy_get_tree(). + $entity_info = entity_get_info('taxonomy_term'); + $bundles = !empty($this->instance['settings']['handler_settings']['target_bundles']) ? $this->instance['settings']['handler_settings']['target_bundles'] : array_keys($entity_info['bundles']); + + foreach ($bundles as $bundle) { + if ($vocabulary = taxonomy_vocabulary_machine_name_load($bundle)) { + if ($terms = taxonomy_get_tree($vocabulary->vid, 0)) { + foreach ($terms as $term) { + $options[$vocabulary->machine_name][$term->tid] = str_repeat('-', $term->depth) . check_plain($term->name); + } + } + } + } + + return $options; + } +} diff --git a/core/modules/user/lib/Drupal/user/Plugin/entity_reference/selection/UserSelection.php b/core/modules/user/lib/Drupal/user/Plugin/entity_reference/selection/UserSelection.php new file mode 100644 index 0000000..1ce97ae --- /dev/null +++ b/core/modules/user/lib/Drupal/user/Plugin/entity_reference/selection/UserSelection.php @@ -0,0 +1,85 @@ +condition('name', $match, $match_operator); + } + + // Adding the 'user_access' tag is sadly insufficient for users: core + // requires us to also know about the concept of 'blocked' and 'active'. + if (!user_access('administer users')) { + $query->condition('status', 1); + } + return $query; + } + + /** + * Overrides SelectionBase::entityQueryAlter(). + */ + public function entityQueryAlter(SelectInterface $query) { + if (user_access('administer users')) { + // In addition, if the user is administrator, we need to make sure to + // match the anonymous user, that doesn't actually have a name in the + // database. + $conditions = &$query->conditions(); + foreach ($conditions as $key => $condition) { + if ($key !== '#conjunction' && is_string($condition['field']) && $condition['field'] === 'users.name') { + // Remove the condition. + unset($conditions[$key]); + + // Re-add the condition and a condition on uid = 0 so that we end up + // with a query in the form: + // WHERE (name LIKE :name) OR (:anonymous_name LIKE :name AND uid = 0) + $or = db_or(); + $or->condition($condition['field'], $condition['value'], $condition['operator']); + // Sadly, the Database layer doesn't allow us to build a condition + // in the form ':placeholder = :placeholder2', because the 'field' + // part of a condition is always escaped. + // As a (cheap) workaround, we separately build a condition with no + // field, and concatenate the field and the condition separately. + $value_part = db_and(); + $value_part->condition('anonymous_name', $condition['value'], $condition['operator']); + $value_part->compile(Database::getConnection(), $query); + $or->condition(db_and() + ->where(str_replace('anonymous_name', ':anonymous_name', (string) $value_part), $value_part->arguments() + array(':anonymous_name' => user_format_name(user_load(0)))) + ->condition('users.uid', 0) + ); + $query->condition($or); + } + } + } + } +} diff --git a/core/modules/views/lib/Drupal/views/Plugin/entity_reference/selection/Views.php b/core/modules/views/lib/Drupal/views/Plugin/entity_reference/selection/Views.php deleted file mode 100644 index 0d92cdd..0000000 --- a/core/modules/views/lib/Drupal/views/Plugin/entity_reference/selection/Views.php +++ /dev/null @@ -1,221 +0,0 @@ -field = $field; - $this->instance = $instance; - $this->entity = $entity; - } - - /** - * Implements Drupal\entity_reference\Plugin\Type\Selection\SelectionInterface::settingsForm(). - */ - public static function settingsForm($field, $instance) { - $view_settings = empty($instance['settings']['handler_settings']['view']) ? array() : $instance['settings']['handler_settings']['view']; - $displays = views_get_applicable_views('entity_reference_display'); - // Filter views that list the entity type we want, and group the separate - // displays by view. - $entity_info = entity_get_info($field['settings']['target_type']); - $options = array(); - foreach ($displays as $data) { - list($view, $display_id) = $data; - if ($view->storage->get('base_table') == $entity_info['base_table']) { - $name = $view->storage->get('name'); - $display = $view->storage->get('display'); - $options[$name . ':' . $display_id] = $name . ' - ' . $display[$display_id]['display_title']; - } - } - - // The value of the 'view_and_display' select below will need to be split - // into 'view_name' and 'view_display' in the final submitted values, so - // we massage the data at validate time on the wrapping element (not - // ideal). - $plugin = new static($field, $instance); - $form['view']['#element_validate'] = array(array($plugin, 'settingsFormValidate')); - - if ($options) { - $default = !empty($view_settings['view_name']) ? $view_settings['view_name'] . ':' . $view_settings['display_name'] : NULL; - $form['view']['view_and_display'] = array( - '#type' => 'select', - '#title' => t('View used to select the entities'), - '#required' => TRUE, - '#options' => $options, - '#default_value' => $default, - '#description' => '
' . t('Choose the view and display that select the entities that can be referenced.
Only views with a display of type "Entity Reference" are eligible.') . '
' . t('No eligible views were found. Create a view with an Entity Reference display, or add such a display to an existing view.', array( - '@create' => url('admin/structure/views/add'), - '@existing' => url('admin/structure/views'), - )) . '
', - ); - } - return $form; - } - - /** - * Initializes a view. - * - * @param string $match - * @param string $match_operator - * @param int $limit - * @param array $ids - * - * @return bool - * Return TRUE if the views was initialized, FALSE otherwise. - */ - protected function initializeView($match = NULL, $match_operator = 'CONTAINS', $limit = 0, $ids = NULL) { - $view_name = $this->instance['settings']['handler_settings']['view']['view_name']; - $display_name = $this->instance['settings']['handler_settings']['view']['display_name']; - $arguments = $this->instance['settings']['handler_settings']['view']['arguments']; - $entity_type = $this->field['settings']['target_type']; - - // Check that the view is valid and the display still exists. - $this->view = views_get_view($view_name); - if (!$this->view || !$this->view->access($display_name)) { - throw new ViewsException('The view %view_name is no longer eligible for the %field_name field.', array('%view_name' => $view_name, '%field_name' => $this->instance['label'])); - } - $this->view->setDisplay($display_name); - - // Pass options to the display handler to make them available later. - $entity_reference_options = array( - 'match' => $match, - 'match_operator' => $match_operator, - 'limit' => $limit, - 'ids' => $ids, - ); - $this->view->displayHandlers[$display_name]->setOption('entity_reference_options', $entity_reference_options); - return TRUE; - } - - /** - * Implements Drupal\entity_reference\Plugin\Type\Selection\SelectionInterface::getReferencableEntities(). - */ - public function getReferencableEntities($match = NULL, $match_operator = 'CONTAINS', $limit = 0) { - $display_name = $this->instance['settings']['handler_settings']['view']['display_name']; - $arguments = $this->instance['settings']['handler_settings']['view']['arguments']; - $result = array(); - if ($this->initializeView($match, $match_operator, $limit)) { - // Get the results. - $result = $this->view->executeDisplay($display_name, $arguments); - } - - $return = array(); - if ($result) { - foreach($this->view->result as $row) { - $entity = $row->_entity; - $return[$entity->bundle()][$entity->id()] = $result[$entity->id()]; - } - } - return $return; - } - - /** - * Implements Drupal\entity_reference\Plugin\Type\Selection\SelectionInterface::countReferencableEntities(). - */ - public function countReferencableEntities($match = NULL, $match_operator = 'CONTAINS') { - $this->getReferencableEntities($match, $match_operator); - return $this->view->pager->get_total_items(); - } - - /** - * Implements Drupal\entity_reference\Plugin\Type\Selection\SelectionInterface::validateReferencableEntities(). - */ - public function validateReferencableEntities(array $ids) { - $display_name = $this->instance['settings']['handler_settings']['view']['display_name']; - $arguments = $this->instance['settings']['handler_settings']['view']['arguments']; - $result = array(); - if ($this->initializeView(NULL, 'CONTAINS', 0, $ids)) { - // Get the results. - $entities = $this->view->executeDisplay($display_name, $arguments); - $result = array_keys($entities); - } - return $result; - } - - /** - * Implements Drupal\entity_reference\Plugin\Type\Selection\SelectionInterface::validateAutocompleteInput(). - */ - public function validateAutocompleteInput($input, &$element, &$form_state, $form) { - return NULL; - } - - /** - * Implements Drupal\entity_reference\Plugin\Type\Selection\SelectionInterface::entityQueryAlter(). - */ - public function entityQueryAlter(SelectInterface $query) {} - - /** - * Element validate; Check View is valid. - */ - public function settingsFormValidate($element, &$form_state, $form) { - // Split view name and display name from the 'view_and_display' value. - if (!empty($element['view_and_display']['#value'])) { - list($view, $display) = explode(':', $element['view_and_display']['#value']); - } - else { - form_error($element, t('The views entity selection mode requires a view.')); - return; - } - - // Explode the 'arguments' string into an actual array. Beware, explode() turns an - // empty string into an array with one empty string. We'll need an empty array - // instead. - $arguments_string = trim($element['arguments']['#value']); - if ($arguments_string === '') { - $arguments = array(); - } - else { - // array_map is called to trim whitespaces from the arguments. - $arguments = array_map('trim', explode(',', $arguments_string)); - } - - $value = array('view_name' => $view, 'display_name' => $display, 'arguments' => $arguments); - form_set_value($element, $value, $form_state); - } -} diff --git a/core/modules/views/lib/Drupal/views/Plugin/entity_reference/selection/ViewsSelection.php b/core/modules/views/lib/Drupal/views/Plugin/entity_reference/selection/ViewsSelection.php new file mode 100644 index 0000000..749e470 --- /dev/null +++ b/core/modules/views/lib/Drupal/views/Plugin/entity_reference/selection/ViewsSelection.php @@ -0,0 +1,229 @@ +field = $field; + $this->instance = $instance; + $this->entity = $entity; + } + + /** + * Implements Drupal\entity_reference\Plugin\Type\Selection\SelectionInterface::settingsForm(). + */ + public static function settingsForm($field, $instance) { + $view_settings = empty($instance['settings']['handler_settings']['view']) ? array() : $instance['settings']['handler_settings']['view']; + $displays = views_get_applicable_views('entity_reference_display'); + // Filter views that list the entity type we want, and group the separate + // displays by view. + $entity_info = entity_get_info($field['settings']['target_type']); + $options = array(); + foreach ($displays as $data) { + list($view, $display_id) = $data; + if ($view->storage->get('base_table') == $entity_info['base_table']) { + $name = $view->storage->get('name'); + $display = $view->storage->get('display'); + $options[$name . ':' . $display_id] = $name . ' - ' . $display[$display_id]['display_title']; + } + } + + // The value of the 'view_and_display' select below will need to be split + // into 'view_name' and 'view_display' in the final submitted values, so + // we massage the data at validate time on the wrapping element (not + // ideal). + $plugin = new static($field, $instance); + $form['view']['#element_validate'] = array(array($plugin, 'settingsFormValidate')); + + if ($options) { + $default = !empty($view_settings['view_name']) ? $view_settings['view_name'] . ':' . $view_settings['display_name'] : NULL; + $form['view']['view_and_display'] = array( + '#type' => 'select', + '#title' => t('View used to select the entities'), + '#required' => TRUE, + '#options' => $options, + '#default_value' => $default, + '#description' => '' . t('Choose the view and display that select the entities that can be referenced.
Only views with a display of type "Entity Reference" are eligible.') . '
' . t('No eligible views were found. Create a view with an Entity Reference display, or add such a display to an existing view.', array( + '@create' => url('admin/structure/views/add'), + '@existing' => url('admin/structure/views'), + )) . '
', + ); + } + return $form; + } + + /** + * Initializes a view. + * + * @param string|null $match + * (Optional) Text to match the label against. Defaults to NULL. + * @param string $match_operator + * (Optional) The operation the matching should be done with. Defaults + * to "CONTAINS". + * @param int $limit + * Limit the query to a given number of items. Defaults to 0, which + * indicates no limiting. + * @param array|null $ids + * Array of entity IDs. Defaults to NULL. + * + * @return bool + * Return TRUE if the views was initialized, FALSE otherwise. + */ + protected function initializeView($match = NULL, $match_operator = 'CONTAINS', $limit = 0, $ids = NULL) { + $view_name = $this->instance['settings']['handler_settings']['view']['view_name']; + $display_name = $this->instance['settings']['handler_settings']['view']['display_name']; + $arguments = $this->instance['settings']['handler_settings']['view']['arguments']; + $entity_type = $this->field['settings']['target_type']; + + // Check that the view is valid and the display still exists. + $this->view = views_get_view($view_name); + if (!$this->view || !$this->view->access($display_name)) { + throw new ViewsException('The view %view_name is no longer eligible for the %field_name field.', array('%view_name' => $view_name, '%field_name' => $this->instance['label'])); + } + $this->view->setDisplay($display_name); + + // Pass options to the display handler to make them available later. + $entity_reference_options = array( + 'match' => $match, + 'match_operator' => $match_operator, + 'limit' => $limit, + 'ids' => $ids, + ); + $this->view->displayHandlers[$display_name]->setOption('entity_reference_options', $entity_reference_options); + return TRUE; + } + + /** + * Implements Drupal\entity_reference\Plugin\Type\Selection\SelectionInterface::getReferencableEntities(). + */ + public function getReferencableEntities($match = NULL, $match_operator = 'CONTAINS', $limit = 0) { + $display_name = $this->instance['settings']['handler_settings']['view']['display_name']; + $arguments = $this->instance['settings']['handler_settings']['view']['arguments']; + $result = array(); + if ($this->initializeView($match, $match_operator, $limit)) { + // Get the results. + $result = $this->view->executeDisplay($display_name, $arguments); + } + + $return = array(); + if ($result) { + foreach($this->view->result as $row) { + $entity = $row->_entity; + $return[$entity->bundle()][$entity->id()] = $result[$entity->id()]; + } + } + return $return; + } + + /** + * Implements Drupal\entity_reference\Plugin\Type\Selection\SelectionInterface::countReferencableEntities(). + */ + public function countReferencableEntities($match = NULL, $match_operator = 'CONTAINS') { + $this->getReferencableEntities($match, $match_operator); + return $this->view->pager->get_total_items(); + } + + /** + * Implements Drupal\entity_reference\Plugin\Type\Selection\SelectionInterface::validateReferencableEntities(). + */ + public function validateReferencableEntities(array $ids) { + $display_name = $this->instance['settings']['handler_settings']['view']['display_name']; + $arguments = $this->instance['settings']['handler_settings']['view']['arguments']; + $result = array(); + if ($this->initializeView(NULL, 'CONTAINS', 0, $ids)) { + // Get the results. + $entities = $this->view->executeDisplay($display_name, $arguments); + $result = array_keys($entities); + } + return $result; + } + + /** + * Implements Drupal\entity_reference\Plugin\Type\Selection\SelectionInterface::validateAutocompleteInput(). + */ + public function validateAutocompleteInput($input, &$element, &$form_state, $form) { + return NULL; + } + + /** + * Implements Drupal\entity_reference\Plugin\Type\Selection\SelectionInterface::entityQueryAlter(). + */ + public function entityQueryAlter(SelectInterface $query) {} + + /** + * Element validate; Check View is valid. + */ + public function settingsFormValidate($element, &$form_state, $form) { + // Split view name and display name from the 'view_and_display' value. + if (!empty($element['view_and_display']['#value'])) { + list($view, $display) = explode(':', $element['view_and_display']['#value']); + } + else { + form_error($element, t('The views entity selection mode requires a view.')); + return; + } + + // Explode the 'arguments' string into an actual array. Beware, explode() turns an + // empty string into an array with one empty string. We'll need an empty array + // instead. + $arguments_string = trim($element['arguments']['#value']); + if ($arguments_string === '') { + $arguments = array(); + } + else { + // array_map is called to trim whitespaces from the arguments. + $arguments = array_map('trim', explode(',', $arguments_string)); + } + + $value = array('view_name' => $view, 'display_name' => $display, 'arguments' => $arguments); + form_set_value($element, $value, $form_state); + } +}