/** * Autocomplete the label of an entity. * * @param \Symfony\Component\HttpFoundation\Request $request * The request object that contains the typed tags. * @param string $target_type * The ID of the target entity type. * @param string $selection_handler * The plugin ID of the entity reference selection handler. * @param string $selection_settings_key * The hashed key of the key/value entry that holds the selection handler * settings. * * @return \Symfony\Component\HttpFoundation\JsonResponse * The matched entity labels as a JSON response. * * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException * Thrown if the selection settings key is not found in the key/value store * or if it does not match the stored data. */ public function handleAutocomplete(Request $request, $target_type, $selection_handler, $selection_settings_key) { $matches = array(); // Get the typed string from the URL, if it exists. if ($input = $request->query->get('q')) { $typed_string = Tags::explode($input); $typed_string = Unicode::strtolower(array_pop($typed_string)); // Selection settings are passed in as a hashed key of a serialized array // stored in the key/value store. $selection_settings = $this->keyValue->get($selection_settings_key, FALSE); if ($selection_settings !== FALSE) { $selection_settings_hash = Crypt::hmacBase64(serialize($selection_settings) . $target_type . $selection_handler, Settings::getHashSalt()); if ($selection_settings_hash !== $selection_settings_key) { // Disallow access when the selection settings hash does not match the // passed-in key. throw new AccessDeniedHttpException('Invalid selection settings key.'); } } else { // Disallow access when the selection settings key is not found in the // key/value store. throw new AccessDeniedHttpException(); } $matches = $this->matcher->getMatches($target_type, $selection_handler, $selection_settings, $typed_string); } return new JsonResponse($matches); }
/** * Implodes a series of tags. */ public function testImplodeTags() { $tags = array_values($this->validTags); // Let's explode and implode to our heart's content. for ($i = 0; $i < 10; $i++) { $string = Tags::implode($tags); $tags = Tags::explode($string); } $this->assertTags($tags); }
/** * Autocomplete the label of an entity. * * @param \Symfony\Component\HttpFoundation\Request $request * The request object that contains the typed tags. * @param string $target_type * The ID of the target entity type. * @param string $selection_handler * The plugin ID of the entity reference selection handler. * @param string $selection_settings * The settings that will be passed to the selection handler. * * @return \Symfony\Component\HttpFoundation\JsonResponse * The matched entity labels as a JSON response. */ public function handleAutocomplete(Request $request, $target_type, $selection_handler, $selection_settings = '') { $matches = array(); // Get the typed string from the URL, if it exists. if ($input = $request->query->get('q')) { $typed_string = Tags::explode($input); $typed_string = Unicode::strtolower(array_pop($typed_string)); // Selection settings are passed in as an encoded serialized array. $selection_settings = $selection_settings ? unserialize(base64_decode($selection_settings)) : array(); $matches = $this->matcher->getMatches($target_type, $selection_handler, $selection_settings, $typed_string); } return new JsonResponse($matches); }
/** * Returns autocompletion content for file name textfield. * * @param \Symfony\Component\HttpFoundation\Request $request * The request of the page. * * @return \Symfony\Component\HttpFoundation\JsonResponse * A JSON response. */ public function autocompleteFilename(Request $request) { $matches = array(); // Get the typed string from the URL, if it exists. if ($input = $request->query->get('q')) { $typed_string = Tags::explode($input); $typed_string = Unicode::strtolower(array_pop($typed_string)); $filenames = db_select('uc_files', 'f')->fields('f', ['filename'])->condition('filename', '%' . db_like($typed_string) . '%', 'LIKE')->execute(); while ($name = $filenames->fetchField()) { $matches[] = array('value' => $name); } } return new JsonResponse($matches); }
public function validateExposed(&$form, &$form_state) { if (empty($this->options['exposed'])) { return; } if (empty($this->options['expose']['identifier'])) { return; } $identifier = $this->options['expose']['identifier']; $input = $form_state['values'][$identifier]; if ($this->options['is_grouped'] && isset($this->options['group_info']['group_items'][$input])) { $this->operator = $this->options['group_info']['group_items'][$input]['operator']; $input = $this->options['group_info']['group_items'][$input]['value']; } $values = Tags::explode($input); if (!$this->options['is_grouped'] || $this->options['is_grouped'] && $input != 'All') { $uids = $this->validate_user_strings($form[$identifier], $form_state, $values); } else { $uids = FALSE; } if ($uids) { $this->validated_exposed_input = $uids; } }
/** * Autocomplete the label of an entity. * * @param Request $request * The request object that contains the typed tags. * @param string $type * The widget type (i.e. 'single' or 'tags'). * @param string $field_name * The name of the entity reference field. * @param string $entity_type * The entity type. * @param string $bundle_name * The bundle name. * @param string $entity_id * (optional) The entity ID the entity reference field is attached to. * Defaults to ''. * * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException * Throws access denied when either the field or field instance does not * exists or the user does not have access to edit the field. * * @return \Symfony\Component\HttpFoundation\JsonResponse * The matched labels as json. */ public function handleAutocomplete(Request $request, $type, $field_name, $entity_type, $bundle_name, $entity_id) { $definitions = $this->entityManager()->getFieldDefinitions($entity_type, $bundle_name); if (!isset($definitions[$field_name])) { throw new AccessDeniedHttpException(); } $field_definition = $definitions[$field_name]; $access_controller = $this->entityManager()->getAccessController($entity_type); if ($field_definition->getType() != 'entity_reference' || !$access_controller->fieldAccess('edit', $field_definition)) { throw new AccessDeniedHttpException(); } // Get the typed string, if exists from the URL. $items_typed = $request->query->get('q'); $items_typed = Tags::explode($items_typed); $last_item = drupal_strtolower(array_pop($items_typed)); $prefix = ''; // The user entered a comma-separated list of entity labels, so we generate // a prefix. if ($type == 'tags' && !empty($last_item)) { $prefix = count($items_typed) ? Tags::implode($items_typed) . ', ' : ''; } $matches = $this->entityReferenceAutocomplete->getMatches($field_definition, $entity_type, $bundle_name, $entity_id, $prefix, $last_item); return new JsonResponse($matches); }
/** * {@inheritdoc} */ public function elementValidate($element, &$form_state, $form) { $value = array(); // If a value was entered into the autocomplete. $handler = \Drupal::service('plugin.manager.entity_reference.selection')->getSelectionHandler($this->fieldDefinition); $bundles = entity_get_bundles($this->getFieldSetting('target_type')); $auto_create = $this->getSelectionHandlerSetting('auto_create'); if (!empty($element['#value'])) { $value = array(); foreach (Tags::explode($element['#value']) as $input) { $match = FALSE; // Take "label (entity id)', match the ID from parenthesis when it's a // number. if (preg_match("/.+\\((\\d+)\\)/", $input, $matches)) { $match = $matches[1]; } elseif (preg_match("/.+\\(([\\w.]+)\\)/", $input, $matches)) { $match = $matches[1]; } else { // Try to get a match from the input string when the user didn't use // the autocomplete but filled in a value manually. $match = $handler->validateAutocompleteInput($input, $element, $form_state, $form, !$auto_create); } if ($match) { $value[] = array('target_id' => $match); } elseif ($auto_create && (count($this->getSelectionHandlerSetting('target_bundles')) == 1 || count($bundles) == 1)) { // Auto-create item. See // \Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem::presave(). $value[] = array('target_id' => NULL, 'entity' => $this->createNewEntity($input, $element['#autocreate_uid'])); } } } // Change the element['#parents'], so in form_set_value() we // populate the correct key. array_pop($element['#parents']); form_set_value($element, $value, $form_state); }
/** * Retrieves suggestions for taxonomy term autocompletion by vocabulary ID. * * @param \Symfony\Component\HttpFoundation\Request $request * The request object. * @param \Drupal\taxonomy\VocabularyInterface $taxonomy_vocabulary * The vocabulary to filter by. * * @return \Symfony\Component\HttpFoundation\JsonResponse * A JSON response containing the autocomplete suggestions for taxonomy * terms. */ public function autocompletePerVid(Request $request, VocabularyInterface $taxonomy_vocabulary) { // A comma-separated list of term names entered in the autocomplete form // element. Only the last term is used for autocompletion. $tags_typed = $request->query->get('q'); $tags_typed = Tags::explode($tags_typed); $tag_last = Unicode::strtolower(array_pop($tags_typed)); $matches = array(); if ($tag_last != '') { $vids = array($taxonomy_vocabulary->id()); $matches = $this->getMatchingTerms($tags_typed, $vids, $tag_last); } return new JsonResponse($matches); }
/** * Provide a full array of possible theme functions to try for a given hook. * * @param string $hook * The hook to use. This is the base theme/template name. * * @return array * An array of theme hook suggestions. */ public function buildThemeFunctions($hook) { $themes = array(); $display = isset($this->display_handler) ? $this->display_handler->display : NULL; $id = $this->storage->id(); if ($display) { $themes[] = $hook . '__' . $id . '__' . $display['id']; $themes[] = $hook . '__' . $display['id']; // Add theme suggestions for each single tag. foreach (Tags::explode($this->storage->get('tag')) as $tag) { $themes[] = $hook . '__' . preg_replace('/[^a-z0-9]/', '_', strtolower($tag)); } if ($display['id'] != $display['display_plugin']) { $themes[] = $hook . '__' . $id . '__' . $display['display_plugin']; $themes[] = $hook . '__' . $display['display_plugin']; } } $themes[] = $hook . '__' . $id; $themes[] = $hook; return $themes; }
/** * {@inheritdoc} */ public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { $this->configuration['keywords'] = Tags::explode($form_state->getValue('keywords')); }
/** * Form element validation handler for entity_autocomplete elements. */ public static function validateEntityAutocomplete(array &$element, FormStateInterface $form_state, array &$complete_form) { $value = NULL; if (!empty($element['#value'])) { $options = array('target_type' => $element['#target_type'], 'handler' => $element['#selection_handler'], 'handler_settings' => $element['#selection_settings']); /** @var /Drupal\Core\Entity\EntityReferenceSelection\SelectionInterface $handler */ $handler = \Drupal::service('plugin.manager.entity_reference_selection')->getInstance($options); $autocreate = (bool) $element['#autocreate'] && $handler instanceof SelectionWithAutocreateInterface; $input_values = $element['#tags'] ? Tags::explode($element['#value']) : array($element['#value']); foreach ($input_values as $input) { $match = static::extractEntityIdFromAutocompleteInput($input); if ($match === NULL) { // Try to get a match from the input string when the user didn't use // the autocomplete but filled in a value manually. $match = static::matchEntityByTitle($handler, $input, $element, $form_state, !$autocreate); } if ($match !== NULL) { $value[] = array('target_id' => $match); } elseif ($autocreate) { /** @var \Drupal\Core\Entity\EntityReferenceSelection\SelectionWithAutocreateInterface $handler */ // Auto-create item. See an example of how this is handled in // \Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem::presave(). $value[] = array('entity' => $handler->createNewEntity($element['#target_type'], $element['#autocreate']['bundle'], $input, $element['#autocreate']['uid'])); } } // Check that the referenced entities are valid, if needed. if ($element['#validate_reference'] && !empty($value)) { // Validate existing entities. $ids = array_reduce($value, function ($return, $item) { if (isset($item['target_id'])) { $return[] = $item['target_id']; } return $return; }); if ($ids) { $valid_ids = $handler->validateReferenceableEntities($ids); if ($invalid_ids = array_diff($ids, $valid_ids)) { foreach ($invalid_ids as $invalid_id) { $form_state->setError($element, t('The referenced entity (%type: %id) does not exist.', array('%type' => $element['#target_type'], '%id' => $invalid_id))); } } } // Validate newly created entities. $new_entities = array_reduce($value, function ($return, $item) { if (isset($item['entity'])) { $return[] = $item['entity']; } return $return; }); if ($new_entities) { if ($autocreate) { $valid_new_entities = $handler->validateReferenceableNewEntities($new_entities); $invalid_new_entities = array_diff_key($new_entities, $valid_new_entities); } else { // If the selection handler does not support referencing newly // created entities, all of them should be invalidated. $invalid_new_entities = $new_entities; } foreach ($invalid_new_entities as $entity) { /** @var \Drupal\Core\Entity\EntityInterface $entity */ $form_state->setError($element, t('This entity (%type: %label) cannot be referenced.', array('%type' => $element['#target_type'], '%label' => $entity->label()))); } } } // Use only the last value if the form element does not support multiple // matches (tags). if (!$element['#tags'] && !empty($value)) { $last_value = $value[count($value) - 1]; $value = isset($last_value['target_id']) ? $last_value['target_id'] : $last_value; } } $form_state->setValueForElement($element, $value); }
/** * {@inheritdoc} */ public function submitConfigurationForm(array &$form, array &$form_state) { $this->configuration['keywords'] = Tags::explode($form_state['values']['keywords']); }
/** * {@inheritdoc} */ public function validateExposed(&$form, FormStateInterface $form_state) { if (empty($this->options['exposed']) || empty($this->options['expose']['identifier'])) { return; } $identifier = $this->options['expose']['identifier']; $input = $form_state->getValues()[$identifier]; if ($this->options['is_grouped'] && isset($this->options['group_info']['group_items'][$input])) { $this->operator = $this->options['group_info']['group_items'][$input]['operator']; $input = $this->options['group_info']['group_items'][$input]['value']; } $values = $this->isMultiValued() ? Tags::explode($input) : array($input); if (!$this->options['is_grouped'] || ($this->options['is_grouped'] && ($input != 'All'))) { $this->validatedExposedInput = $this->validateEntityStrings($form[$identifier], $values, $form_state); } else { $this->validatedExposedInput = FALSE; } }
/** * Retrieves suggestions for taxonomy term autocompletion. * * This function outputs term name suggestions in response to Ajax requests * made by the taxonomy autocomplete widget for taxonomy term reference * fields. The output is a JSON object of plain-text term suggestions, keyed * by the user-entered value with the completed term name appended. * Term names containing commas are wrapped in quotes. * * For example, suppose the user has entered the string 'red fish, blue' in * the field, and there are two taxonomy terms, 'blue fish' and 'blue moon'. * The JSON output would have the following structure: * @code * { * "red fish, blue fish": "blue fish", * "red fish, blue moon": "blue moon", * }; * @endcode * * @param \Symfony\Component\HttpFoundation\Request $request * The request object. * @param string $entity_type * The entity_type. * @param string $field_name * The name of the term reference field. * * @return \Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\Response * When valid field name is specified, a JSON response containing the * autocomplete suggestions for taxonomy terms. Otherwise a normal response * containing an error message. */ public function autocomplete(Request $request, $entity_type, $field_name) { // A comma-separated list of term names entered in the autocomplete form // element. Only the last term is used for autocompletion. $tags_typed = $request->query->get('q'); // Make sure the field exists and is a taxonomy field. $field_storage_definitions = $this->entityManager->getFieldStorageDefinitions($entity_type); if (!isset($field_storage_definitions[$field_name]) || $field_storage_definitions[$field_name]->getType() !== 'taxonomy_term_reference') { // Error string. The JavaScript handler will realize this is not JSON and // will display it as debugging information. return new Response(t('Taxonomy field @field_name not found.', array('@field_name' => $field_name)), 403); } $field_storage = $field_storage_definitions[$field_name]; // The user enters a comma-separated list of tags. We only autocomplete the // last tag. $tags_typed = Tags::explode($tags_typed); $tag_last = Unicode::strtolower(array_pop($tags_typed)); $matches = array(); if ($tag_last != '') { // Part of the criteria for the query come from the field's own settings. $vids = array(); foreach ($field_storage->getSetting('allowed_values') as $tree) { $vids[] = $tree['vocabulary']; } $matches = $this->getMatchingTerms($tags_typed, $vids, $tag_last); } return new JsonResponse($matches); }
public function rowAttributes() { $variables = array(); $active_row_regions = array(); $config_settings = \Drupal::config($this->theme_name . '.settings')->get('settings'); // If rows are empty return early. if (empty($this->layout_config['rows'])) { return; } // Build array of rows with region values. foreach ($this->layout_config['rows'] as $row_name => $row_data) { // Set a bool for active regions, assume false. $variables[$row_name . '__regions']['active'] = FALSE; $i = 1; foreach ($row_data['regions'] as $region_key => $region_name) { $region_source_order[$row_name][$region_key] = $i++; // Set an increment value for each region for the .hr class (has-regions) $row_regions[$row_name][] = $region_key; // Build array to intersect and use for the .arc class (active region count). } // Pass on row wrapper attributes only for rows with active regions $active_row_regions[$row_name]['attributes'] = $row_data['attributes']; // Remove inactive regions. $active_row_regions[$row_name]['regions'] = array_intersect($row_regions[$row_name], $this->active_regions); // Unset inactive rows. if (empty($active_row_regions[$row_name]['regions'])) { unset($active_row_regions[$row_name]); } } // Set additional attributes for rows. foreach ($active_row_regions as $row_key => $row_values) { //if (!empty($row_values['regions'])) {} // If active regions set to true to print the row, basically a catch all condition. $variables[$row_key . '__regions']['active'] = TRUE; // Wrapper attributes. $variables[$row_key . '__wrapper_attributes'] = new Attribute; $variables[$row_key . '__wrapper_attributes']['class'] = array('l-pr', 'page__row', 'pr-' . $row_key); foreach ($row_values['attributes'] as $attribute_type => $attribute_values) { if (is_array($attribute_values)) { $variables[$row_key . '__wrapper_attributes'][$attribute_type] = array(implode(' ', $attribute_values)); } else { $variables[$row_key . '__wrapper_attributes'][$attribute_type] = array($attribute_values); } } // Container attributes. $variables[$row_key . '__container_attributes'] = new Attribute; $variables[$row_key . '__container_attributes']['class'] = array('l-rw', 'regions', 'container', 'pr-'. str_replace('_', '-', $row_key) . '__rw'); // Active Regions: "arc" is "active region count", this is number of active regions in this row on this page. $count = count($row_values['regions']); $variables[$row_key . '__container_attributes']['class'][] = 'arc--'. $count; // Match each active region with its'corrosponding source order increment. foreach ($row_values['regions'] as $region) { if (isset($region_source_order[$row_key][$region])) { $row_has_regions[$row_key][] = $region_source_order[$row_key][$region]; } } // Has Regions: the "hr" class tells us which regions are active by source order (as per the layout markup yml), // this allows us to push layout dependant on exactly which regions are active. if (isset($row_has_regions[$row_key])) { $variables[$row_key . '__container_attributes']['class'][] = 'hr--' . implode('-', $row_has_regions[$row_key]); } // Shortcode classes. if (isset($config_settings['enable_extensions']) && $config_settings['enable_extensions'] === 1) { if (isset($config_settings['enable_shortcodes']) && $config_settings['enable_shortcodes'] === 1) { // Wrapper codes if (!empty($config_settings['page_classes_row_wrapper_' . $row_key])) { $shortcodes = Tags::explode($config_settings['page_classes_row_wrapper_' . $row_key]); foreach ($shortcodes as $class) { $variables[$row_key . '__wrapper_attributes']['class'][] = Html::cleanCssIdentifier($class); } } // Container codes if (!empty($config_settings['page_classes_row_container_' . $row_key])) { $shortcodes = Tags::explode($config_settings['page_classes_row_container_' . $row_key]); foreach ($shortcodes as $class) { $variables[$row_key . '__container_attributes']['class'][] = Html::cleanCssIdentifier($class); } } } } } return $variables; }
public function validateExposed(&$form, &$form_state) { if (empty($this->options['exposed'])) { return; } $identifier = $this->options['expose']['identifier']; // We only validate if they've chosen the text field style. if ($this->options['type'] != 'textfield') { if ($form_state['values'][$identifier] != 'All') { $this->validated_exposed_input = (array) $form_state['values'][$identifier]; } return; } if (empty($this->options['expose']['identifier'])) { return; } $values = Tags::explode($form_state['values'][$identifier]); $tids = $this->validate_term_strings($form[$identifier], $values); if ($tids) { $this->validated_exposed_input = $tids; } }