security update for entity_reference

This commit is contained in:
2018-04-21 00:03:39 +02:00
parent 85772b4ca7
commit 226561ffd4
18 changed files with 475 additions and 138 deletions

View File

@@ -144,18 +144,20 @@ class EntityReferenceBehavior_TaxonomyIndex extends EntityReference_BehaviorHand
// already inserted in taxonomy_build_node_index().
$tid_all = array_diff($tid_all, $original_tid_all);
// Insert index entries for all the node's terms.
// Insert index entries for all the node's terms, preventing duplicates.
if (!empty($tid_all)) {
$query = db_insert('taxonomy_index')->fields(array('nid', 'tid', 'sticky', 'created'));
foreach ($tid_all as $tid) {
$query->values(array(
$row = array(
'nid' => $node->nid,
'tid' => $tid,
'sticky' => $sticky,
'created' => $node->created,
));
);
$query = db_merge('taxonomy_index')
->key($row)
->fields($row);
$query->execute();
}
$query->execute();
}
}
}

View File

@@ -208,7 +208,11 @@ class EntityReference_SelectionHandler_Generic implements EntityReference_Select
* Implements EntityReferenceHandler::validateAutocompleteInput().
*/
public function validateAutocompleteInput($input, &$element, &$form_state, $form) {
$entities = $this->getReferencableEntities($input, '=', 6);
$bundled_entities = $this->getReferencableEntities($input, '=', 6);
$entities = array();
foreach($bundled_entities as $entities_list) {
$entities += $entities_list;
}
if (empty($entities)) {
// Error if there are no entities available for a required field.
form_error($element, t('There are no entities matching "%value"', array('%value' => $input)));
@@ -305,7 +309,7 @@ class EntityReference_SelectionHandler_Generic implements EntityReference_Select
*/
public function getLabel($entity) {
$target_type = $this->field['settings']['target_type'];
return entity_access('view', $target_type, $entity) ? entity_label($target_type, $entity) : t('- Restricted access -');
return entity_access('view', $target_type, $entity) ? entity_label($target_type, $entity) : t(ENTITYREFERENCE_DENIED);
}
/**
@@ -339,9 +343,11 @@ class EntityReference_SelectionHandler_Generic implements EntityReference_Select
// Join the known base-table.
$target_type = $this->field['settings']['target_type'];
$entity_info = entity_get_info($target_type);
$target_type_base_table = $entity_info['base table'];
$id = $entity_info['entity keys']['id'];
// Return the alias of the table.
return $query->innerJoin($target_type, NULL, "%alias.$id = $alias.entity_id");
return $query->innerJoin($target_type_base_table, NULL, "%alias.$id = $alias.entity_id");
}
}
@@ -370,28 +376,6 @@ class EntityReference_SelectionHandler_Generic_node extends EntityReference_Sele
* This only exists to workaround core bugs.
*/
class EntityReference_SelectionHandler_Generic_user extends EntityReference_SelectionHandler_Generic {
/**
* Implements EntityReferenceHandler::settingsForm().
*/
public static function settingsForm($field, $instance) {
$settings = $field['settings']['handler_settings'];
$form = parent::settingsForm($field, $instance);
$form['referenceable_roles'] = array(
'#type' => 'checkboxes',
'#title' => t('User roles that can be referenced'),
'#default_value' => isset($settings['referenceable_roles']) ? array_filter($settings['referenceable_roles']) : array(),
'#options' => user_roles(TRUE),
);
$form['referenceable_status'] = array(
'#type' => 'checkboxes',
'#title' => t('User status that can be referenced'),
'#default_value' => isset($settings['referenceable_status']) ? array_filter($settings['referenceable_status']) : array('active' => 'active'),
'#options' => array('active' => t('Active'), 'blocked' => t('Blocked')),
);
return $form;
}
public function buildEntityFieldQuery($match = NULL, $match_operator = 'CONTAINS') {
$query = parent::buildEntityFieldQuery($match, $match_operator);
@@ -400,22 +384,11 @@ class EntityReference_SelectionHandler_Generic_user extends EntityReference_Sele
$query->propertyCondition('name', $match, $match_operator);
}
$field = $this->field;
$settings = $field['settings']['handler_settings'];
$referenceable_roles = isset($settings['referenceable_roles']) ? array_filter($settings['referenceable_roles']) : array();
$referenceable_status = isset($settings['referenceable_status']) ? array_filter($settings['referenceable_status']) : array('active' => 'active');
// If this filter is not filled, use the users access permissions.
if (empty($referenceable_status)) {
// 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->propertyCondition('status', 1);
}
}
elseif (count($referenceable_status) == 1) {
$values = array('active' => 1, 'blocked' => 0);
$query->propertyCondition('status', $values[key($referenceable_status)]);
// 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->propertyCondition('status', 1);
}
return $query;
}
@@ -576,7 +549,7 @@ class EntityReference_SelectionHandler_Generic_taxonomy_term extends EntityRefer
if ($vocabulary = taxonomy_vocabulary_machine_name_load($bundle)) {
if ($terms = taxonomy_get_tree($vocabulary->vid, 0, NULL, TRUE)) {
foreach ($terms as $term) {
$options[$vocabulary->machine_name][$term->tid] = str_repeat('-', $term->depth) . check_plain($term->name);
$options[$vocabulary->machine_name][$term->tid] = str_repeat('-', $term->depth) . check_plain(entity_label('taxonomy_term', $term));
}
}
}

View File

@@ -9,12 +9,13 @@ class EntityReference_SelectionHandler_Views implements EntityReference_Selectio
* Implements EntityReferenceHandler::getInstance().
*/
public static function getInstance($field, $instance = NULL, $entity_type = NULL, $entity = NULL) {
return new EntityReference_SelectionHandler_Views($field, $instance);
return new EntityReference_SelectionHandler_Views($field, $instance, $entity);
}
protected function __construct($field, $instance) {
protected function __construct($field, $instance, $entity) {
$this->field = $field;
$this->instance = $instance;
$this->entity = $entity;
}
/**
@@ -52,13 +53,32 @@ class EntityReference_SelectionHandler_Views implements EntityReference_Selectio
);
$default = !empty($view_settings['args']) ? implode(', ', $view_settings['args']) : '';
$description = t('Provide a comma separated list of arguments to pass to the view.') . '<br />' . t('This field supports tokens.');
if (!module_exists('token')) {
$description .= '<br>' . t('Install the <a href="@url">token module</a> to get more tokens and display available once.', array('@url' => 'http://drupal.org/project/token'));
}
$form['view']['args'] = array(
'#type' => 'textfield',
'#title' => t('View arguments'),
'#default_value' => $default,
'#required' => FALSE,
'#description' => t('Provide a comma separated list of arguments to pass to the view.'),
'#description' => $description,
'#maxlength' => '512',
);
if (module_exists('token')) {
// Get the token type for the entity type our field is in (a type 'taxonomy_term' has a 'term' type token).
$info = entity_get_info($instance['entity_type']);
$form['view']['tokens'] = array(
'#theme' => 'token_tree',
'#token_types' => array($info['token type']),
'#global_types' => TRUE,
'#click_insert' => TRUE,
'#dialog' => TRUE,
);
}
}
else {
$form['view']['no_view_help'] = array(
@@ -84,6 +104,7 @@ class EntityReference_SelectionHandler_Views implements EntityReference_Selectio
return FALSE;
}
$this->view->set_display($display_name);
$this->view->pre_execute();
// Make sure the query is not cached.
$this->view->is_cacheable = FALSE;
@@ -104,7 +125,7 @@ class EntityReference_SelectionHandler_Views implements EntityReference_Selectio
*/
public function getReferencableEntities($match = NULL, $match_operator = 'CONTAINS', $limit = 0) {
$display_name = $this->field['settings']['handler_settings']['view']['display_name'];
$args = $this->field['settings']['handler_settings']['view']['args'];
$args = $this->handleArgs($this->field['settings']['handler_settings']['view']['args']);
$result = array();
if ($this->initializeView($match, $match_operator, $limit)) {
// Get the results.
@@ -133,12 +154,14 @@ class EntityReference_SelectionHandler_Views implements EntityReference_Selectio
function validateReferencableEntities(array $ids) {
$display_name = $this->field['settings']['handler_settings']['view']['display_name'];
$args = $this->field['settings']['handler_settings']['view']['args'];
$args = $this->handleArgs($this->field['settings']['handler_settings']['view']['args']);
$result = array();
if ($this->initializeView(NULL, 'CONTAINS', 0, $ids)) {
// Get the results.
$entities = $this->view->execute_display($display_name, $args);
$result = array_keys($entities);
if (!empty($entities)) {
$result = array_keys($entities);
}
}
return $result;
}
@@ -164,6 +187,49 @@ class EntityReference_SelectionHandler_Views implements EntityReference_Selectio
}
/**
* Handles arguments for views.
*
* Replaces tokens using token_replace().
*
* @param array $args
* Usually $this->field['settings']['handler_settings']['view']['args'].
*
* @return array
* The arguments to be send to the View.
*/
protected function handleArgs($args) {
if (!module_exists('token')) {
return $args;
}
// Parameters for token_replace().
$data = array();
$options = array('clear' => TRUE);
if ($entity = $this->entity) {
// D7 HACK: For new entities, entity and revision id are not set. This leads to
// * token replacement emitting PHP warnings
// * views choking on empty arguments
// We workaround this by filling in '0' for these IDs
// and use a clone to leave no traces of our unholy doings.
$info = entity_get_info($this->instance['entity_type']);
if (!isset($entity->{$info['entity keys']['id']})) {
$entity = clone $entity;
$entity->{$info['entity keys']['id']} = '0';
if (!empty($info['entity keys']['revision'])) {
$entity->{$info['entity keys']['revision']} = '0';
}
}
$data[$info['token type']] = $entity;
}
// Replace tokens for each argument.
foreach ($args as $key => $arg) {
$args[$key] = token_replace($arg, $data, $options);
}
return $args;
}
}
function entityreference_view_settings_validate($element, &$form_state, $form) {

View File

@@ -21,8 +21,9 @@ interface EntityReference_SelectionHandler {
* Return a list of referencable entities.
*
* @return
* An array of referencable entities, which keys are entity ids and
* values (safe HTML) labels to be displayed to the user.
* A nested array of entities, the first level is keyed by the
* entity bundle, which contains an array of entity labels (safe HTML),
* keyed by the entity ID.
*/
public function getReferencableEntities($match = NULL, $match_operator = 'CONTAINS', $limit = 0);