annotate sites/all/modules/entityreference/plugins/selection/EntityReference_SelectionHandler_Generic.class.php @ 11:b0ee71395280

deleted .DS_Store files
author danieleb <danielebarchiesi@me.com>
date Mon, 28 Oct 2013 16:12:13 +0000
parents ce11bbd8f642
children
rev   line source
danielebarchiesi@4 1 <?php
danielebarchiesi@4 2
danielebarchiesi@4 3 /**
danielebarchiesi@4 4 * A generic Entity handler.
danielebarchiesi@4 5 *
danielebarchiesi@4 6 * The generic base implementation has a variety of overrides to workaround
danielebarchiesi@4 7 * core's largely deficient entity handling.
danielebarchiesi@4 8 */
danielebarchiesi@4 9 class EntityReference_SelectionHandler_Generic implements EntityReference_SelectionHandler {
danielebarchiesi@4 10
danielebarchiesi@4 11 /**
danielebarchiesi@4 12 * Implements EntityReferenceHandler::getInstance().
danielebarchiesi@4 13 */
danielebarchiesi@4 14 public static function getInstance($field, $instance = NULL, $entity_type = NULL, $entity = NULL) {
danielebarchiesi@4 15 $target_entity_type = $field['settings']['target_type'];
danielebarchiesi@4 16
danielebarchiesi@4 17 // Check if the entity type does exist and has a base table.
danielebarchiesi@4 18 $entity_info = entity_get_info($target_entity_type);
danielebarchiesi@4 19 if (empty($entity_info['base table'])) {
danielebarchiesi@4 20 return EntityReference_SelectionHandler_Broken::getInstance($field, $instance);
danielebarchiesi@4 21 }
danielebarchiesi@4 22
danielebarchiesi@4 23 if (class_exists($class_name = 'EntityReference_SelectionHandler_Generic_' . $target_entity_type)) {
danielebarchiesi@4 24 return new $class_name($field, $instance, $entity_type, $entity);
danielebarchiesi@4 25 }
danielebarchiesi@4 26 else {
danielebarchiesi@4 27 return new EntityReference_SelectionHandler_Generic($field, $instance, $entity_type, $entity);
danielebarchiesi@4 28 }
danielebarchiesi@4 29 }
danielebarchiesi@4 30
danielebarchiesi@4 31 protected function __construct($field, $instance = NULL, $entity_type = NULL, $entity = NULL) {
danielebarchiesi@4 32 $this->field = $field;
danielebarchiesi@4 33 $this->instance = $instance;
danielebarchiesi@4 34 $this->entity_type = $entity_type;
danielebarchiesi@4 35 $this->entity = $entity;
danielebarchiesi@4 36 }
danielebarchiesi@4 37
danielebarchiesi@4 38 /**
danielebarchiesi@4 39 * Implements EntityReferenceHandler::settingsForm().
danielebarchiesi@4 40 */
danielebarchiesi@4 41 public static function settingsForm($field, $instance) {
danielebarchiesi@4 42 $entity_info = entity_get_info($field['settings']['target_type']);
danielebarchiesi@4 43
danielebarchiesi@4 44 // Merge-in default values.
danielebarchiesi@4 45 $field['settings']['handler_settings'] += array(
danielebarchiesi@4 46 'target_bundles' => array(),
danielebarchiesi@4 47 'sort' => array(
danielebarchiesi@4 48 'type' => 'none',
danielebarchiesi@4 49 )
danielebarchiesi@4 50 );
danielebarchiesi@4 51
danielebarchiesi@4 52 if (!empty($entity_info['entity keys']['bundle'])) {
danielebarchiesi@4 53 $bundles = array();
danielebarchiesi@4 54 foreach ($entity_info['bundles'] as $bundle_name => $bundle_info) {
danielebarchiesi@4 55 $bundles[$bundle_name] = $bundle_info['label'];
danielebarchiesi@4 56 }
danielebarchiesi@4 57
danielebarchiesi@4 58 $form['target_bundles'] = array(
danielebarchiesi@4 59 '#type' => 'checkboxes',
danielebarchiesi@4 60 '#title' => t('Target bundles'),
danielebarchiesi@4 61 '#options' => $bundles,
danielebarchiesi@4 62 '#default_value' => $field['settings']['handler_settings']['target_bundles'],
danielebarchiesi@4 63 '#size' => 6,
danielebarchiesi@4 64 '#multiple' => TRUE,
danielebarchiesi@4 65 '#description' => t('The bundles of the entity type that can be referenced. Optional, leave empty for all bundles.'),
danielebarchiesi@4 66 '#element_validate' => array('_entityreference_element_validate_filter'),
danielebarchiesi@4 67 );
danielebarchiesi@4 68 }
danielebarchiesi@4 69 else {
danielebarchiesi@4 70 $form['target_bundles'] = array(
danielebarchiesi@4 71 '#type' => 'value',
danielebarchiesi@4 72 '#value' => array(),
danielebarchiesi@4 73 );
danielebarchiesi@4 74 }
danielebarchiesi@4 75
danielebarchiesi@4 76 $form['sort']['type'] = array(
danielebarchiesi@4 77 '#type' => 'select',
danielebarchiesi@4 78 '#title' => t('Sort by'),
danielebarchiesi@4 79 '#options' => array(
danielebarchiesi@4 80 'none' => t("Don't sort"),
danielebarchiesi@4 81 'property' => t('A property of the base table of the entity'),
danielebarchiesi@4 82 'field' => t('A field attached to this entity'),
danielebarchiesi@4 83 ),
danielebarchiesi@4 84 '#ajax' => TRUE,
danielebarchiesi@4 85 '#limit_validation_errors' => array(),
danielebarchiesi@4 86 '#default_value' => $field['settings']['handler_settings']['sort']['type'],
danielebarchiesi@4 87 );
danielebarchiesi@4 88
danielebarchiesi@4 89 $form['sort']['settings'] = array(
danielebarchiesi@4 90 '#type' => 'container',
danielebarchiesi@4 91 '#attributes' => array('class' => array('entityreference-settings')),
danielebarchiesi@4 92 '#process' => array('_entityreference_form_process_merge_parent'),
danielebarchiesi@4 93 );
danielebarchiesi@4 94
danielebarchiesi@4 95 if ($field['settings']['handler_settings']['sort']['type'] == 'property') {
danielebarchiesi@4 96 // Merge-in default values.
danielebarchiesi@4 97 $field['settings']['handler_settings']['sort'] += array(
danielebarchiesi@4 98 'property' => NULL,
danielebarchiesi@4 99 );
danielebarchiesi@4 100
danielebarchiesi@4 101 $form['sort']['settings']['property'] = array(
danielebarchiesi@4 102 '#type' => 'select',
danielebarchiesi@4 103 '#title' => t('Sort property'),
danielebarchiesi@4 104 '#required' => TRUE,
danielebarchiesi@4 105 '#options' => drupal_map_assoc($entity_info['schema_fields_sql']['base table']),
danielebarchiesi@4 106 '#default_value' => $field['settings']['handler_settings']['sort']['property'],
danielebarchiesi@4 107 );
danielebarchiesi@4 108 }
danielebarchiesi@4 109 elseif ($field['settings']['handler_settings']['sort']['type'] == 'field') {
danielebarchiesi@4 110 // Merge-in default values.
danielebarchiesi@4 111 $field['settings']['handler_settings']['sort'] += array(
danielebarchiesi@4 112 'field' => NULL,
danielebarchiesi@4 113 );
danielebarchiesi@4 114
danielebarchiesi@4 115 $fields = array();
danielebarchiesi@4 116 foreach (field_info_instances($field['settings']['target_type']) as $bundle_name => $bundle_instances) {
danielebarchiesi@4 117 foreach ($bundle_instances as $instance_name => $instance_info) {
danielebarchiesi@4 118 $field_info = field_info_field($instance_name);
danielebarchiesi@4 119 foreach ($field_info['columns'] as $column_name => $column_info) {
danielebarchiesi@4 120 $fields[$instance_name . ':' . $column_name] = t('@label (column @column)', array('@label' => $instance_info['label'], '@column' => $column_name));
danielebarchiesi@4 121 }
danielebarchiesi@4 122 }
danielebarchiesi@4 123 }
danielebarchiesi@4 124
danielebarchiesi@4 125 $form['sort']['settings']['field'] = array(
danielebarchiesi@4 126 '#type' => 'select',
danielebarchiesi@4 127 '#title' => t('Sort field'),
danielebarchiesi@4 128 '#required' => TRUE,
danielebarchiesi@4 129 '#options' => $fields,
danielebarchiesi@4 130 '#default_value' => $field['settings']['handler_settings']['sort']['field'],
danielebarchiesi@4 131 );
danielebarchiesi@4 132 }
danielebarchiesi@4 133
danielebarchiesi@4 134 if ($field['settings']['handler_settings']['sort']['type'] != 'none') {
danielebarchiesi@4 135 // Merge-in default values.
danielebarchiesi@4 136 $field['settings']['handler_settings']['sort'] += array(
danielebarchiesi@4 137 'direction' => 'ASC',
danielebarchiesi@4 138 );
danielebarchiesi@4 139
danielebarchiesi@4 140 $form['sort']['settings']['direction'] = array(
danielebarchiesi@4 141 '#type' => 'select',
danielebarchiesi@4 142 '#title' => t('Sort direction'),
danielebarchiesi@4 143 '#required' => TRUE,
danielebarchiesi@4 144 '#options' => array(
danielebarchiesi@4 145 'ASC' => t('Ascending'),
danielebarchiesi@4 146 'DESC' => t('Descending'),
danielebarchiesi@4 147 ),
danielebarchiesi@4 148 '#default_value' => $field['settings']['handler_settings']['sort']['direction'],
danielebarchiesi@4 149 );
danielebarchiesi@4 150 }
danielebarchiesi@4 151
danielebarchiesi@4 152 return $form;
danielebarchiesi@4 153 }
danielebarchiesi@4 154
danielebarchiesi@4 155 /**
danielebarchiesi@4 156 * Implements EntityReferenceHandler::getReferencableEntities().
danielebarchiesi@4 157 */
danielebarchiesi@4 158 public function getReferencableEntities($match = NULL, $match_operator = 'CONTAINS', $limit = 0) {
danielebarchiesi@4 159 $options = array();
danielebarchiesi@4 160 $entity_type = $this->field['settings']['target_type'];
danielebarchiesi@4 161
danielebarchiesi@4 162 $query = $this->buildEntityFieldQuery($match, $match_operator);
danielebarchiesi@4 163 if ($limit > 0) {
danielebarchiesi@4 164 $query->range(0, $limit);
danielebarchiesi@4 165 }
danielebarchiesi@4 166
danielebarchiesi@4 167 $results = $query->execute();
danielebarchiesi@4 168
danielebarchiesi@4 169 if (!empty($results[$entity_type])) {
danielebarchiesi@4 170 $entities = entity_load($entity_type, array_keys($results[$entity_type]));
danielebarchiesi@4 171 foreach ($entities as $entity_id => $entity) {
danielebarchiesi@4 172 list(,, $bundle) = entity_extract_ids($entity_type, $entity);
danielebarchiesi@4 173 $options[$bundle][$entity_id] = check_plain($this->getLabel($entity));
danielebarchiesi@4 174 }
danielebarchiesi@4 175 }
danielebarchiesi@4 176
danielebarchiesi@4 177 return $options;
danielebarchiesi@4 178 }
danielebarchiesi@4 179
danielebarchiesi@4 180 /**
danielebarchiesi@4 181 * Implements EntityReferenceHandler::countReferencableEntities().
danielebarchiesi@4 182 */
danielebarchiesi@4 183 public function countReferencableEntities($match = NULL, $match_operator = 'CONTAINS') {
danielebarchiesi@4 184 $query = $this->buildEntityFieldQuery($match, $match_operator);
danielebarchiesi@4 185 return $query
danielebarchiesi@4 186 ->count()
danielebarchiesi@4 187 ->execute();
danielebarchiesi@4 188 }
danielebarchiesi@4 189
danielebarchiesi@4 190 /**
danielebarchiesi@4 191 * Implements EntityReferenceHandler::validateReferencableEntities().
danielebarchiesi@4 192 */
danielebarchiesi@4 193 public function validateReferencableEntities(array $ids) {
danielebarchiesi@4 194 if ($ids) {
danielebarchiesi@4 195 $entity_type = $this->field['settings']['target_type'];
danielebarchiesi@4 196 $query = $this->buildEntityFieldQuery();
danielebarchiesi@4 197 $query->entityCondition('entity_id', $ids, 'IN');
danielebarchiesi@4 198 $result = $query->execute();
danielebarchiesi@4 199 if (!empty($result[$entity_type])) {
danielebarchiesi@4 200 return array_keys($result[$entity_type]);
danielebarchiesi@4 201 }
danielebarchiesi@4 202 }
danielebarchiesi@4 203
danielebarchiesi@4 204 return array();
danielebarchiesi@4 205 }
danielebarchiesi@4 206
danielebarchiesi@4 207 /**
danielebarchiesi@4 208 * Implements EntityReferenceHandler::validateAutocompleteInput().
danielebarchiesi@4 209 */
danielebarchiesi@4 210 public function validateAutocompleteInput($input, &$element, &$form_state, $form) {
danielebarchiesi@4 211 $entities = $this->getReferencableEntities($input, '=', 6);
danielebarchiesi@4 212 if (empty($entities)) {
danielebarchiesi@4 213 // Error if there are no entities available for a required field.
danielebarchiesi@4 214 form_error($element, t('There are no entities matching "%value"', array('%value' => $input)));
danielebarchiesi@4 215 }
danielebarchiesi@4 216 elseif (count($entities) > 5) {
danielebarchiesi@4 217 // Error if there are more than 5 matching entities.
danielebarchiesi@4 218 form_error($element, t('Many entities are called %value. Specify the one you want by appending the id in parentheses, like "@value (@id)"', array(
danielebarchiesi@4 219 '%value' => $input,
danielebarchiesi@4 220 '@value' => $input,
danielebarchiesi@4 221 '@id' => key($entities),
danielebarchiesi@4 222 )));
danielebarchiesi@4 223 }
danielebarchiesi@4 224 elseif (count($entities) > 1) {
danielebarchiesi@4 225 // More helpful error if there are only a few matching entities.
danielebarchiesi@4 226 $multiples = array();
danielebarchiesi@4 227 foreach ($entities as $id => $name) {
danielebarchiesi@4 228 $multiples[] = $name . ' (' . $id . ')';
danielebarchiesi@4 229 }
danielebarchiesi@4 230 form_error($element, t('Multiple entities match this reference; "%multiple"', array('%multiple' => implode('", "', $multiples))));
danielebarchiesi@4 231 }
danielebarchiesi@4 232 else {
danielebarchiesi@4 233 // Take the one and only matching entity.
danielebarchiesi@4 234 return key($entities);
danielebarchiesi@4 235 }
danielebarchiesi@4 236 }
danielebarchiesi@4 237
danielebarchiesi@4 238 /**
danielebarchiesi@4 239 * Build an EntityFieldQuery to get referencable entities.
danielebarchiesi@4 240 */
danielebarchiesi@4 241 protected function buildEntityFieldQuery($match = NULL, $match_operator = 'CONTAINS') {
danielebarchiesi@4 242 $query = new EntityFieldQuery();
danielebarchiesi@4 243 $query->entityCondition('entity_type', $this->field['settings']['target_type']);
danielebarchiesi@4 244 if (!empty($this->field['settings']['handler_settings']['target_bundles'])) {
danielebarchiesi@4 245 $query->entityCondition('bundle', $this->field['settings']['handler_settings']['target_bundles'], 'IN');
danielebarchiesi@4 246 }
danielebarchiesi@4 247 if (isset($match)) {
danielebarchiesi@4 248 $entity_info = entity_get_info($this->field['settings']['target_type']);
danielebarchiesi@4 249 if (isset($entity_info['entity keys']['label'])) {
danielebarchiesi@4 250 $query->propertyCondition($entity_info['entity keys']['label'], $match, $match_operator);
danielebarchiesi@4 251 }
danielebarchiesi@4 252 }
danielebarchiesi@4 253
danielebarchiesi@4 254 // Add a generic entity access tag to the query.
danielebarchiesi@4 255 $query->addTag($this->field['settings']['target_type'] . '_access');
danielebarchiesi@4 256 $query->addTag('entityreference');
danielebarchiesi@4 257 $query->addMetaData('field', $this->field);
danielebarchiesi@4 258 $query->addMetaData('entityreference_selection_handler', $this);
danielebarchiesi@4 259
danielebarchiesi@4 260 // Add the sort option.
danielebarchiesi@4 261 if (!empty($this->field['settings']['handler_settings']['sort'])) {
danielebarchiesi@4 262 $sort_settings = $this->field['settings']['handler_settings']['sort'];
danielebarchiesi@4 263 if ($sort_settings['type'] == 'property') {
danielebarchiesi@4 264 $query->propertyOrderBy($sort_settings['property'], $sort_settings['direction']);
danielebarchiesi@4 265 }
danielebarchiesi@4 266 elseif ($sort_settings['type'] == 'field') {
danielebarchiesi@4 267 list($field, $column) = explode(':', $sort_settings['field'], 2);
danielebarchiesi@4 268 $query->fieldOrderBy($field, $column, $sort_settings['direction']);
danielebarchiesi@4 269 }
danielebarchiesi@4 270 }
danielebarchiesi@4 271
danielebarchiesi@4 272 return $query;
danielebarchiesi@4 273 }
danielebarchiesi@4 274
danielebarchiesi@4 275 /**
danielebarchiesi@4 276 * Implements EntityReferenceHandler::entityFieldQueryAlter().
danielebarchiesi@4 277 */
danielebarchiesi@4 278 public function entityFieldQueryAlter(SelectQueryInterface $query) {
danielebarchiesi@4 279
danielebarchiesi@4 280 }
danielebarchiesi@4 281
danielebarchiesi@4 282 /**
danielebarchiesi@4 283 * Helper method: pass a query to the alteration system again.
danielebarchiesi@4 284 *
danielebarchiesi@4 285 * This allow Entity Reference to add a tag to an existing query, to ask
danielebarchiesi@4 286 * access control mechanisms to alter it again.
danielebarchiesi@4 287 */
danielebarchiesi@4 288 protected function reAlterQuery(SelectQueryInterface $query, $tag, $base_table) {
danielebarchiesi@4 289 // Save the old tags and metadata.
danielebarchiesi@4 290 // For some reason, those are public.
danielebarchiesi@4 291 $old_tags = $query->alterTags;
danielebarchiesi@4 292 $old_metadata = $query->alterMetaData;
danielebarchiesi@4 293
danielebarchiesi@4 294 $query->alterTags = array($tag => TRUE);
danielebarchiesi@4 295 $query->alterMetaData['base_table'] = $base_table;
danielebarchiesi@4 296 drupal_alter(array('query', 'query_' . $tag), $query);
danielebarchiesi@4 297
danielebarchiesi@4 298 // Restore the tags and metadata.
danielebarchiesi@4 299 $query->alterTags = $old_tags;
danielebarchiesi@4 300 $query->alterMetaData = $old_metadata;
danielebarchiesi@4 301 }
danielebarchiesi@4 302
danielebarchiesi@4 303 /**
danielebarchiesi@4 304 * Implements EntityReferenceHandler::getLabel().
danielebarchiesi@4 305 */
danielebarchiesi@4 306 public function getLabel($entity) {
danielebarchiesi@4 307 return entity_label($this->field['settings']['target_type'], $entity);
danielebarchiesi@4 308 }
danielebarchiesi@4 309
danielebarchiesi@4 310 /**
danielebarchiesi@4 311 * Ensure a base table exists for the query.
danielebarchiesi@4 312 *
danielebarchiesi@4 313 * If we have a field-only query, we want to assure we have a base-table
danielebarchiesi@4 314 * so we can later alter the query in entityFieldQueryAlter().
danielebarchiesi@4 315 *
danielebarchiesi@4 316 * @param $query
danielebarchiesi@4 317 * The Select query.
danielebarchiesi@4 318 *
danielebarchiesi@4 319 * @return
danielebarchiesi@4 320 * The alias of the base-table.
danielebarchiesi@4 321 */
danielebarchiesi@4 322 public function ensureBaseTable(SelectQueryInterface $query) {
danielebarchiesi@4 323 $tables = $query->getTables();
danielebarchiesi@4 324
danielebarchiesi@4 325 // Check the current base table.
danielebarchiesi@4 326 foreach ($tables as $table) {
danielebarchiesi@4 327 if (empty($table['join'])) {
danielebarchiesi@4 328 $alias = $table['alias'];
danielebarchiesi@4 329 break;
danielebarchiesi@4 330 }
danielebarchiesi@4 331 }
danielebarchiesi@4 332
danielebarchiesi@4 333 if (strpos($alias, 'field_data_') !== 0) {
danielebarchiesi@4 334 // The existing base-table is the correct one.
danielebarchiesi@4 335 return $alias;
danielebarchiesi@4 336 }
danielebarchiesi@4 337
danielebarchiesi@4 338 // Join the known base-table.
danielebarchiesi@4 339 $target_type = $this->field['settings']['target_type'];
danielebarchiesi@4 340 $entity_info = entity_get_info($target_type);
danielebarchiesi@4 341 $id = $entity_info['entity keys']['id'];
danielebarchiesi@4 342 // Return the alias of the table.
danielebarchiesi@4 343 return $query->innerJoin($target_type, NULL, "$target_type.$id = $alias.entity_id");
danielebarchiesi@4 344 }
danielebarchiesi@4 345 }
danielebarchiesi@4 346
danielebarchiesi@4 347 /**
danielebarchiesi@4 348 * Override for the Node type.
danielebarchiesi@4 349 *
danielebarchiesi@4 350 * This only exists to workaround core bugs.
danielebarchiesi@4 351 */
danielebarchiesi@4 352 class EntityReference_SelectionHandler_Generic_node extends EntityReference_SelectionHandler_Generic {
danielebarchiesi@4 353 public function entityFieldQueryAlter(SelectQueryInterface $query) {
danielebarchiesi@4 354 // Adding the 'node_access' tag is sadly insufficient for nodes: core
danielebarchiesi@4 355 // requires us to also know about the concept of 'published' and
danielebarchiesi@4 356 // 'unpublished'. We need to do that as long as there are no access control
danielebarchiesi@4 357 // modules in use on the site. As long as one access control module is there,
danielebarchiesi@4 358 // it is supposed to handle this check.
danielebarchiesi@4 359 if (!user_access('bypass node access') && !count(module_implements('node_grants'))) {
danielebarchiesi@4 360 $base_table = $this->ensureBaseTable($query);
danielebarchiesi@4 361 $query->condition("$base_table.status", NODE_PUBLISHED);
danielebarchiesi@4 362 }
danielebarchiesi@4 363 }
danielebarchiesi@4 364 }
danielebarchiesi@4 365
danielebarchiesi@4 366 /**
danielebarchiesi@4 367 * Override for the User type.
danielebarchiesi@4 368 *
danielebarchiesi@4 369 * This only exists to workaround core bugs.
danielebarchiesi@4 370 */
danielebarchiesi@4 371 class EntityReference_SelectionHandler_Generic_user extends EntityReference_SelectionHandler_Generic {
danielebarchiesi@4 372 public function buildEntityFieldQuery($match = NULL, $match_operator = 'CONTAINS') {
danielebarchiesi@4 373 $query = parent::buildEntityFieldQuery($match, $match_operator);
danielebarchiesi@4 374
danielebarchiesi@4 375 // The user entity doesn't have a label column.
danielebarchiesi@4 376 if (isset($match)) {
danielebarchiesi@4 377 $query->propertyCondition('name', $match, $match_operator);
danielebarchiesi@4 378 }
danielebarchiesi@4 379
danielebarchiesi@4 380 // Adding the 'user_access' tag is sadly insufficient for users: core
danielebarchiesi@4 381 // requires us to also know about the concept of 'blocked' and
danielebarchiesi@4 382 // 'active'.
danielebarchiesi@4 383 if (!user_access('administer users')) {
danielebarchiesi@4 384 $query->propertyCondition('status', 1);
danielebarchiesi@4 385 }
danielebarchiesi@4 386 return $query;
danielebarchiesi@4 387 }
danielebarchiesi@4 388
danielebarchiesi@4 389 public function entityFieldQueryAlter(SelectQueryInterface $query) {
danielebarchiesi@4 390 if (user_access('administer users')) {
danielebarchiesi@4 391 // In addition, if the user is administrator, we need to make sure to
danielebarchiesi@4 392 // match the anonymous user, that doesn't actually have a name in the
danielebarchiesi@4 393 // database.
danielebarchiesi@4 394 $conditions = &$query->conditions();
danielebarchiesi@4 395 foreach ($conditions as $key => $condition) {
danielebarchiesi@4 396 if ($key !== '#conjunction' && is_string($condition['field']) && $condition['field'] === 'users.name') {
danielebarchiesi@4 397 // Remove the condition.
danielebarchiesi@4 398 unset($conditions[$key]);
danielebarchiesi@4 399
danielebarchiesi@4 400 // Re-add the condition and a condition on uid = 0 so that we end up
danielebarchiesi@4 401 // with a query in the form:
danielebarchiesi@4 402 // WHERE (name LIKE :name) OR (:anonymous_name LIKE :name AND uid = 0)
danielebarchiesi@4 403 $or = db_or();
danielebarchiesi@4 404 $or->condition($condition['field'], $condition['value'], $condition['operator']);
danielebarchiesi@4 405 // Sadly, the Database layer doesn't allow us to build a condition
danielebarchiesi@4 406 // in the form ':placeholder = :placeholder2', because the 'field'
danielebarchiesi@4 407 // part of a condition is always escaped.
danielebarchiesi@4 408 // As a (cheap) workaround, we separately build a condition with no
danielebarchiesi@4 409 // field, and concatenate the field and the condition separately.
danielebarchiesi@4 410 $value_part = db_and();
danielebarchiesi@4 411 $value_part->condition('anonymous_name', $condition['value'], $condition['operator']);
danielebarchiesi@4 412 $value_part->compile(Database::getConnection(), $query);
danielebarchiesi@4 413 $or->condition(db_and()
danielebarchiesi@4 414 ->where(str_replace('anonymous_name', ':anonymous_name', (string) $value_part), $value_part->arguments() + array(':anonymous_name' => format_username(user_load(0))))
danielebarchiesi@4 415 ->condition('users.uid', 0)
danielebarchiesi@4 416 );
danielebarchiesi@4 417 $query->condition($or);
danielebarchiesi@4 418 }
danielebarchiesi@4 419 }
danielebarchiesi@4 420 }
danielebarchiesi@4 421 }
danielebarchiesi@4 422 }
danielebarchiesi@4 423
danielebarchiesi@4 424 /**
danielebarchiesi@4 425 * Override for the Comment type.
danielebarchiesi@4 426 *
danielebarchiesi@4 427 * This only exists to workaround core bugs.
danielebarchiesi@4 428 */
danielebarchiesi@4 429 class EntityReference_SelectionHandler_Generic_comment extends EntityReference_SelectionHandler_Generic {
danielebarchiesi@4 430 public function entityFieldQueryAlter(SelectQueryInterface $query) {
danielebarchiesi@4 431 // Adding the 'comment_access' tag is sadly insufficient for comments: core
danielebarchiesi@4 432 // requires us to also know about the concept of 'published' and
danielebarchiesi@4 433 // 'unpublished'.
danielebarchiesi@4 434 if (!user_access('administer comments')) {
danielebarchiesi@4 435 $base_table = $this->ensureBaseTable($query);
danielebarchiesi@4 436 $query->condition("$base_table.status", COMMENT_PUBLISHED);
danielebarchiesi@4 437 }
danielebarchiesi@4 438
danielebarchiesi@4 439 // The Comment module doesn't implement any proper comment access,
danielebarchiesi@4 440 // and as a consequence doesn't make sure that comments cannot be viewed
danielebarchiesi@4 441 // when the user doesn't have access to the node.
danielebarchiesi@4 442 $tables = $query->getTables();
danielebarchiesi@4 443 $base_table = key($tables);
danielebarchiesi@4 444 $node_alias = $query->innerJoin('node', 'n', '%alias.nid = ' . $base_table . '.nid');
danielebarchiesi@4 445 // Pass the query to the node access control.
danielebarchiesi@4 446 $this->reAlterQuery($query, 'node_access', $node_alias);
danielebarchiesi@4 447
danielebarchiesi@4 448 // Alas, the comment entity exposes a bundle, but doesn't have a bundle column
danielebarchiesi@4 449 // in the database. We have to alter the query ourself to go fetch the
danielebarchiesi@4 450 // bundle.
danielebarchiesi@4 451 $conditions = &$query->conditions();
danielebarchiesi@4 452 foreach ($conditions as $key => &$condition) {
danielebarchiesi@4 453 if ($key !== '#conjunction' && is_string($condition['field']) && $condition['field'] === 'node_type') {
danielebarchiesi@4 454 $condition['field'] = $node_alias . '.type';
danielebarchiesi@4 455 foreach ($condition['value'] as &$value) {
danielebarchiesi@4 456 if (substr($value, 0, 13) == 'comment_node_') {
danielebarchiesi@4 457 $value = substr($value, 13);
danielebarchiesi@4 458 }
danielebarchiesi@4 459 }
danielebarchiesi@4 460 break;
danielebarchiesi@4 461 }
danielebarchiesi@4 462 }
danielebarchiesi@4 463
danielebarchiesi@4 464 // Passing the query to node_query_node_access_alter() is sadly
danielebarchiesi@4 465 // insufficient for nodes.
danielebarchiesi@4 466 // @see EntityReferenceHandler_node::entityFieldQueryAlter()
danielebarchiesi@4 467 if (!user_access('bypass node access') && !count(module_implements('node_grants'))) {
danielebarchiesi@4 468 $query->condition($node_alias . '.status', 1);
danielebarchiesi@4 469 }
danielebarchiesi@4 470 }
danielebarchiesi@4 471 }
danielebarchiesi@4 472
danielebarchiesi@4 473 /**
danielebarchiesi@4 474 * Override for the File type.
danielebarchiesi@4 475 *
danielebarchiesi@4 476 * This only exists to workaround core bugs.
danielebarchiesi@4 477 */
danielebarchiesi@4 478 class EntityReference_SelectionHandler_Generic_file extends EntityReference_SelectionHandler_Generic {
danielebarchiesi@4 479 public function entityFieldQueryAlter(SelectQueryInterface $query) {
danielebarchiesi@4 480 // Core forces us to know about 'permanent' vs. 'temporary' files.
danielebarchiesi@4 481 $tables = $query->getTables();
danielebarchiesi@4 482 $base_table = key($tables);
danielebarchiesi@4 483 $query->condition('status', FILE_STATUS_PERMANENT);
danielebarchiesi@4 484
danielebarchiesi@4 485 // Access control to files is a very difficult business. For now, we are not
danielebarchiesi@4 486 // going to give it a shot.
danielebarchiesi@4 487 // @todo: fix this when core access control is less insane.
danielebarchiesi@4 488 return $query;
danielebarchiesi@4 489 }
danielebarchiesi@4 490
danielebarchiesi@4 491 public function getLabel($entity) {
danielebarchiesi@4 492 // The file entity doesn't have a label. More over, the filename is
danielebarchiesi@4 493 // sometimes empty, so use the basename in that case.
danielebarchiesi@4 494 return $entity->filename !== '' ? $entity->filename : basename($entity->uri);
danielebarchiesi@4 495 }
danielebarchiesi@4 496 }
danielebarchiesi@4 497
danielebarchiesi@4 498 /**
danielebarchiesi@4 499 * Override for the Taxonomy term type.
danielebarchiesi@4 500 *
danielebarchiesi@4 501 * This only exists to workaround core bugs.
danielebarchiesi@4 502 */
danielebarchiesi@4 503 class EntityReference_SelectionHandler_Generic_taxonomy_term extends EntityReference_SelectionHandler_Generic {
danielebarchiesi@4 504 public function entityFieldQueryAlter(SelectQueryInterface $query) {
danielebarchiesi@4 505 // The Taxonomy module doesn't implement any proper taxonomy term access,
danielebarchiesi@4 506 // and as a consequence doesn't make sure that taxonomy terms cannot be viewed
danielebarchiesi@4 507 // when the user doesn't have access to the vocabulary.
danielebarchiesi@4 508 $base_table = $this->ensureBaseTable($query);
danielebarchiesi@4 509 $vocabulary_alias = $query->innerJoin('taxonomy_vocabulary', 'n', '%alias.vid = ' . $base_table . '.vid');
danielebarchiesi@4 510 $query->addMetadata('base_table', $vocabulary_alias);
danielebarchiesi@4 511 // Pass the query to the taxonomy access control.
danielebarchiesi@4 512 $this->reAlterQuery($query, 'taxonomy_vocabulary_access', $vocabulary_alias);
danielebarchiesi@4 513
danielebarchiesi@4 514 // Also, the taxonomy term entity exposes a bundle, but doesn't have a bundle
danielebarchiesi@4 515 // column in the database. We have to alter the query ourself to go fetch
danielebarchiesi@4 516 // the bundle.
danielebarchiesi@4 517 $conditions = &$query->conditions();
danielebarchiesi@4 518 foreach ($conditions as $key => &$condition) {
danielebarchiesi@4 519 if ($key !== '#conjunction' && is_string($condition['field']) && $condition['field'] === 'vocabulary_machine_name') {
danielebarchiesi@4 520 $condition['field'] = $vocabulary_alias . '.machine_name';
danielebarchiesi@4 521 break;
danielebarchiesi@4 522 }
danielebarchiesi@4 523 }
danielebarchiesi@4 524 }
danielebarchiesi@4 525
danielebarchiesi@4 526 /**
danielebarchiesi@4 527 * Implements EntityReferenceHandler::getReferencableEntities().
danielebarchiesi@4 528 */
danielebarchiesi@4 529 public function getReferencableEntities($match = NULL, $match_operator = 'CONTAINS', $limit = 0) {
danielebarchiesi@4 530 if ($match || $limit) {
danielebarchiesi@4 531 return parent::getReferencableEntities($match , $match_operator, $limit);
danielebarchiesi@4 532 }
danielebarchiesi@4 533
danielebarchiesi@4 534 $options = array();
danielebarchiesi@4 535 $entity_type = $this->field['settings']['target_type'];
danielebarchiesi@4 536
danielebarchiesi@4 537 // We imitate core by calling taxonomy_get_tree().
danielebarchiesi@4 538 $entity_info = entity_get_info('taxonomy_term');
danielebarchiesi@4 539 $bundles = !empty($this->field['settings']['handler_settings']['target_bundles']) ? $this->field['settings']['handler_settings']['target_bundles'] : array_keys($entity_info['bundles']);
danielebarchiesi@4 540
danielebarchiesi@4 541 foreach ($bundles as $bundle) {
danielebarchiesi@4 542 if ($vocabulary = taxonomy_vocabulary_machine_name_load($bundle)) {
danielebarchiesi@4 543 if ($terms = taxonomy_get_tree($vocabulary->vid, 0)) {
danielebarchiesi@4 544 foreach ($terms as $term) {
danielebarchiesi@4 545 $options[$vocabulary->machine_name][$term->tid] = str_repeat('-', $term->depth) . check_plain($term->name);
danielebarchiesi@4 546 }
danielebarchiesi@4 547 }
danielebarchiesi@4 548 }
danielebarchiesi@4 549 }
danielebarchiesi@4 550
danielebarchiesi@4 551 return $options;
danielebarchiesi@4 552 }
danielebarchiesi@4 553 }