PageRenderTime 30ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/entity_reference/selection/SelectionBase.php

https://bitbucket.org/aswinvk28/smartpan-stock-drupal
PHP | 318 lines | 197 code | 40 blank | 81 comment | 20 complexity | 6de3aaf4ef2c7ec1a6cee93da2e2afb8 MD5 | raw file
Possible License(s): LGPL-2.1
  1. <?php
  2. /**
  3. * @file
  4. * Contains \Drupal\entity_reference\Plugin\entity_reference\selection\SelectionBase.
  5. */
  6. namespace Drupal\entity_reference\Plugin\entity_reference\selection;
  7. use Drupal\Core\Database\Query\AlterableInterface;
  8. use Drupal\Core\Database\Query\SelectInterface;
  9. use Drupal\Core\Entity\EntityInterface;
  10. use Drupal\Core\Field\FieldDefinitionInterface;
  11. use Drupal\Component\Utility\NestedArray;
  12. use Drupal\entity_reference\Plugin\Type\Selection\SelectionInterface;
  13. /**
  14. * Plugin implementation of the 'selection' entity_reference.
  15. *
  16. * @EntityReferenceSelection(
  17. * id = "default",
  18. * label = @Translation("Default"),
  19. * group = "default",
  20. * weight = 0,
  21. * derivative = "Drupal\entity_reference\Plugin\Derivative\SelectionBase"
  22. * )
  23. */
  24. class SelectionBase implements SelectionInterface {
  25. /**
  26. * The field definition.
  27. *
  28. * @var \Drupal\Core\Field\FieldDefinitionInterface
  29. */
  30. protected $fieldDefinition;
  31. /**
  32. * The entity object, or NULL
  33. *
  34. * @var \Drupal\Core\Entity\EntityInterface|null
  35. */
  36. protected $entity;
  37. /**
  38. * Constructs a SelectionBase object.
  39. */
  40. public function __construct(FieldDefinitionInterface $field_definition, EntityInterface $entity = NULL) {
  41. $this->fieldDefinition = $field_definition;
  42. $this->entity = $entity;
  43. }
  44. /**
  45. * {@inheritdoc}
  46. */
  47. public static function settingsForm(FieldDefinitionInterface $field_definition) {
  48. $target_type = $field_definition->getSetting('target_type');
  49. $selection_handler_settings = $field_definition->getSetting('handler_settings') ?: array();
  50. $entity_type = \Drupal::entityManager()->getDefinition($target_type);
  51. $bundles = entity_get_bundles($target_type);
  52. // Merge-in default values.
  53. $selection_handler_settings += array(
  54. 'target_bundles' => array(),
  55. 'sort' => array(
  56. 'field' => '_none',
  57. ),
  58. 'auto_create' => FALSE,
  59. );
  60. if ($entity_type->hasKey('bundle')) {
  61. $bundle_options = array();
  62. foreach ($bundles as $bundle_name => $bundle_info) {
  63. $bundle_options[$bundle_name] = $bundle_info['label'];
  64. }
  65. $target_bundles_title = t('Bundles');
  66. // Default core entity types with sensible labels.
  67. if ($target_type == 'node') {
  68. $target_bundles_title = t('Content types');
  69. }
  70. elseif ($target_type == 'taxonomy_term') {
  71. $target_bundles_title = t('Vocabularies');
  72. }
  73. $form['target_bundles'] = array(
  74. '#type' => 'checkboxes',
  75. '#title' => $target_bundles_title,
  76. '#options' => $bundle_options,
  77. '#default_value' => (!empty($selection_handler_settings['target_bundles'])) ? $selection_handler_settings['target_bundles'] : array(),
  78. '#required' => TRUE,
  79. '#size' => 6,
  80. '#multiple' => TRUE,
  81. '#element_validate' => array('_entity_reference_element_validate_filter'),
  82. );
  83. }
  84. else {
  85. $form['target_bundles'] = array(
  86. '#type' => 'value',
  87. '#value' => array(),
  88. );
  89. }
  90. $target_type_info = \Drupal::entityManager()->getDefinition($target_type);
  91. if ($target_type_info->isSubclassOf('\Drupal\Core\Entity\ContentEntityInterface')) {
  92. // @todo Use Entity::getPropertyDefinitions() when all entity types are
  93. // converted to the new Field API.
  94. $fields = drupal_map_assoc(drupal_schema_fields_sql($entity_type->getBaseTable()));
  95. foreach (field_info_instances($target_type) as $bundle_instances) {
  96. foreach ($bundle_instances as $instance_name => $instance) {
  97. foreach ($instance->getField()->getColumns() as $column_name => $column_info) {
  98. $fields[$instance_name . '.' . $column_name] = t('@label (@column)', array('@label' => $instance->getLabel(), '@column' => $column_name));
  99. }
  100. }
  101. }
  102. $form['sort']['field'] = array(
  103. '#type' => 'select',
  104. '#title' => t('Sort by'),
  105. '#options' => array(
  106. '_none' => t('- None -'),
  107. ) + $fields,
  108. '#ajax' => TRUE,
  109. '#limit_validation_errors' => array(),
  110. '#default_value' => $selection_handler_settings['sort']['field'],
  111. );
  112. $form['sort']['settings'] = array(
  113. '#type' => 'container',
  114. '#attributes' => array('class' => array('entity_reference-settings')),
  115. '#process' => array('_entity_reference_form_process_merge_parent'),
  116. );
  117. if ($selection_handler_settings['sort']['field'] != '_none') {
  118. // Merge-in default values.
  119. $selection_handler_settings['sort'] += array(
  120. 'direction' => 'ASC',
  121. );
  122. $form['sort']['settings']['direction'] = array(
  123. '#type' => 'select',
  124. '#title' => t('Sort direction'),
  125. '#required' => TRUE,
  126. '#options' => array(
  127. 'ASC' => t('Ascending'),
  128. 'DESC' => t('Descending'),
  129. ),
  130. '#default_value' => $selection_handler_settings['sort']['direction'],
  131. );
  132. }
  133. }
  134. return $form;
  135. }
  136. /**
  137. * {@inheritdoc}
  138. */
  139. public function getReferenceableEntities($match = NULL, $match_operator = 'CONTAINS', $limit = 0) {
  140. $target_type = $this->fieldDefinition->getSetting('target_type');
  141. $query = $this->buildEntityQuery($match, $match_operator);
  142. if ($limit > 0) {
  143. $query->range(0, $limit);
  144. }
  145. $result = $query->execute();
  146. if (empty($result)) {
  147. return array();
  148. }
  149. $options = array();
  150. $entities = entity_load_multiple($target_type, $result);
  151. foreach ($entities as $entity_id => $entity) {
  152. $bundle = $entity->bundle();
  153. $options[$bundle][$entity_id] = check_plain($entity->label());
  154. }
  155. return $options;
  156. }
  157. /**
  158. * {@inheritdoc}
  159. */
  160. public function countReferenceableEntities($match = NULL, $match_operator = 'CONTAINS') {
  161. $query = $this->buildEntityQuery($match, $match_operator);
  162. return $query
  163. ->count()
  164. ->execute();
  165. }
  166. /**
  167. * {@inheritdoc}
  168. */
  169. public function validateReferenceableEntities(array $ids) {
  170. $result = array();
  171. if ($ids) {
  172. $target_type = $this->fieldDefinition->getSetting('target_type');
  173. $entity_type = \Drupal::entityManager()->getDefinition($target_type);
  174. $query = $this->buildEntityQuery();
  175. $result = $query
  176. ->condition($entity_type->getKey('id'), $ids, 'IN')
  177. ->execute();
  178. }
  179. return $result;
  180. }
  181. /**
  182. * {@inheritdoc}
  183. */
  184. public function validateAutocompleteInput($input, &$element, &$form_state, $form, $strict = TRUE) {
  185. $entities = $this->getReferenceableEntities($input, '=', 6);
  186. $params = array(
  187. '%value' => $input,
  188. '@value' => $input,
  189. );
  190. if (empty($entities)) {
  191. if ($strict) {
  192. // Error if there are no entities available for a required field.
  193. form_error($element, $form_state, t('There are no entities matching "%value".', $params));
  194. }
  195. }
  196. elseif (count($entities) > 5) {
  197. $params['@id'] = key($entities);
  198. // Error if there are more than 5 matching entities.
  199. form_error($element, $form_state, t('Many entities are called %value. Specify the one you want by appending the id in parentheses, like "@value (@id)".', $params));
  200. }
  201. elseif (count($entities) > 1) {
  202. // More helpful error if there are only a few matching entities.
  203. $multiples = array();
  204. foreach ($entities as $id => $name) {
  205. $multiples[] = $name . ' (' . $id . ')';
  206. }
  207. $params['@id'] = $id;
  208. form_error($element, $form_state, 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))));
  209. }
  210. else {
  211. // Take the one and only matching entity.
  212. return key($entities);
  213. }
  214. }
  215. /**
  216. * Builds an EntityQuery to get referenceable entities.
  217. *
  218. * @param string|null $match
  219. * (Optional) Text to match the label against. Defaults to NULL.
  220. * @param string $match_operator
  221. * (Optional) The operation the matching should be done with. Defaults
  222. * to "CONTAINS".
  223. *
  224. * @return \Drupal\Core\Entity\Query\QueryInterface
  225. * The EntityQuery object with the basic conditions and sorting applied to
  226. * it.
  227. */
  228. public function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS') {
  229. $target_type = $this->fieldDefinition->getSetting('target_type');
  230. $handler_settings = $this->fieldDefinition->getSetting('handler_settings');
  231. $entity_type = \Drupal::entityManager()->getDefinition($target_type);
  232. $query = \Drupal::entityQuery($target_type);
  233. if (!empty($handler_settings['target_bundles'])) {
  234. $query->condition($entity_type->getKey('bundle'), $handler_settings['target_bundles'], 'IN');
  235. }
  236. if (isset($match) && $label_key = $entity_type->getKey('label')) {
  237. $query->condition($label_key, $match, $match_operator);
  238. }
  239. // Add entity-access tag.
  240. $query->addTag($this->fieldDefinition->getSetting('target_type') . '_access');
  241. // Add the Selection handler for
  242. // entity_reference_query_entity_reference_alter().
  243. $query->addTag('entity_reference');
  244. $query->addMetaData('field_definition', $this->fieldDefinition);
  245. $query->addMetaData('entity_reference_selection_handler', $this);
  246. // Add the sort option.
  247. $handler_settings = $this->fieldDefinition->getSetting('handler_settings');
  248. if (!empty($handler_settings['sort'])) {
  249. $sort_settings = $handler_settings['sort'];
  250. if ($sort_settings['field'] != '_none') {
  251. $query->sort($sort_settings['field'], $sort_settings['direction']);
  252. }
  253. }
  254. return $query;
  255. }
  256. /**
  257. * {@inheritdoc}
  258. */
  259. public function entityQueryAlter(SelectInterface $query) { }
  260. /**
  261. * Helper method: Passes a query to the alteration system again.
  262. *
  263. * This allows Entity Reference to add a tag to an existing query so it can
  264. * ask access control mechanisms to alter it again.
  265. */
  266. protected function reAlterQuery(AlterableInterface $query, $tag, $base_table) {
  267. // Save the old tags and metadata.
  268. // For some reason, those are public.
  269. $old_tags = $query->alterTags;
  270. $old_metadata = $query->alterMetaData;
  271. $query->alterTags = array($tag => TRUE);
  272. $query->alterMetaData['base_table'] = $base_table;
  273. drupal_alter(array('query', 'query_' . $tag), $query);
  274. // Restore the tags and metadata.
  275. $query->alterTags = $old_tags;
  276. $query->alterMetaData = $old_metadata;
  277. }
  278. }