/** * {@inheritdoc} */ public function getFormElement(DataDefinitionInterface $definition, LanguageInterface $language, $value) { // Estimate a comfortable size of the input textarea. $rows_words = ceil(str_word_count($value) / 5); $rows_newlines = substr_count($value, "\n") + 1; $rows = max($rows_words, $rows_newlines); return array('#type' => 'textarea', '#default_value' => $value, '#title' => $this->t($definition->getLabel()) . '<span class="visually-hidden"> (' . $language->getName() . ')</span>', '#rows' => $rows, '#attributes' => array('lang' => $language->getId())); }
/** * Returns the source element for a given configuration definition. * * This can be either a render array that actually outputs the source values * directly or a read-only form element with the source values depending on * what is considered to provide a more intuitive user interface for the * translator. * * @param \Drupal\Core\Language\LanguageInterface $source_language * Thee source language of the configuration object. * @param mixed $source_config * The configuration value of the element in the source language. * * @return array * A render array for the source value. */ protected function getSourceElement(LanguageInterface $source_language, $source_config) { if ($source_config) { $value = '<span lang="' . $source_language->getId() . '">' . nl2br($source_config) . '</span>'; } else { $value = $this->t('(Empty)'); } return array('#type' => 'item', '#title' => $this->t('@label <span class="visually-hidden">(@source_language)</span>', array('@label' => $this->definition->getLabel(), '@source_language' => $source_language->getName())), '#markup' => $value); }
/** * Returns the source element for a given configuration definition. * * This can be either a render array that actually outputs the source values * directly or a read-only form element with the source values depending on * what is considered to provide a more intuitive user interface for the * translator. * * @param \Drupal\Core\Language\LanguageInterface $source_language * Thee source language of the configuration object. * @param mixed $source_config * The configuration value of the element in the source language. * * @return array * A render array for the source value. */ protected function getSourceElement(LanguageInterface $source_language, $source_config) { // @todo Should support singular+plurals https://www.drupal.org/node/2454829 if ($source_config) { $value = '<span lang="' . $source_language->getId() . '">' . nl2br($source_config) . '</span>'; } else { $value = $this->t('(Empty)'); } return array('#type' => 'item', '#title' => $this->t('!label <span class="visually-hidden">(!source_language)</span>', array('!label' => $this->t($this->definition->getLabel()), '!source_language' => $source_language->getName())), '#markup' => $value); }
/** * {@inheritdoc} */ protected function generateDerivativeDefinition($base_plugin_definition, $data_type_id, $data_type_definition, DataDefinitionInterface $base_definition, $property_name, DataDefinitionInterface $property_definition) { $bundle_info = $base_definition->getConstraint('Bundle'); // Identify base definitions that appear on bundle-able entities. if ($bundle_info && array_filter($bundle_info) && $base_definition->getConstraint('EntityType')) { $base_data_type = 'entity:' . $base_definition->getConstraint('EntityType'); } else { $base_data_type = $data_type_id; } // If we've not processed this thing before. if (!isset($this->derivatives[$base_data_type . ':' . $property_name])) { $derivative = $base_plugin_definition; $derivative['label'] = $this->t($this->label, ['@property' => $property_definition->getLabel(), '@base' => $data_type_definition['label']]); $derivative['data_type'] = $property_definition->getFieldStorageDefinition()->getPropertyDefinition($property_definition->getFieldStorageDefinition()->getMainPropertyName())->getDataType(); $derivative['property_name'] = $property_name; $context_definition = new ContextDefinition($base_data_type, $this->typedDataManager->createDataDefinition($base_data_type)); // Add the constraints of the base definition to the context definition. if ($base_definition->getConstraint('Bundle')) { $context_definition->addConstraint('Bundle', $base_definition->getConstraint('Bundle')); } $derivative['context'] = ['base' => $context_definition]; $derivative['property_name'] = $property_name; $this->derivatives[$base_data_type . ':' . $property_name] = $derivative; } elseif ($property_definition instanceof FieldConfigInterface) { // We should only end up in here on entity bundles. $derivative = $this->derivatives[$base_data_type . ':' . $property_name]; // Update label /** @var \Drupal\Core\StringTranslation\TranslatableMarkup $label */ $label = $derivative['label']; list(, , $argument_name) = explode(':', $data_type_id); $arguments = $label->getArguments(); $arguments['@' . $argument_name] = $data_type_definition['label']; $string_args = $arguments; array_shift($string_args); $last = array_slice($string_args, -1); // The slice doesn't remove, so do that now. array_pop($string_args); $string = count($string_args) >= 2 ? '@property from ' . implode(', ', array_keys($string_args)) . ' and ' . array_keys($last)[0] : '@property from @base and ' . array_keys($last)[0]; $this->derivatives[$base_data_type . ':' . $property_name]['label'] = $this->t($string, $arguments); if ($base_definition->getConstraint('Bundle')) { // Add bundle constraints $context_definition = $derivative['context']['base']; $bundles = $context_definition->getConstraint('Bundle') ?: []; $bundles = array_merge($bundles, $base_definition->getConstraint('Bundle')); $context_definition->addConstraint('Bundle', $bundles); } } }
/** * Creates a new field on an index based on a property. * * Will find and set a new unique field identifier for the field on the index. * * @param \Drupal\search_api\IndexInterface $index * The search index. * @param \Drupal\Core\TypedData\DataDefinitionInterface $property * The data definition of the property. * @param string|null $datasource_id * The ID of the index's datasource this property belongs to, or NULL if it * is a datasource-independent property. * @param string $property_path * The property's property path within the property structure of the * datasource. * @param string|null $field_id * (optional) The identifier to use for the field. If not set, a new unique * field identifier on the index will be chosen automatically. * @param string|null $type * (optional) The type to set for the field, or NULL to determine a default * type automatically. * * @return \Drupal\search_api\Item\FieldInterface * A new field object for the index, based on the given property. * * @throws \Drupal\search_api\SearchApiException * Thrown if no type was given and no default could be determined. */ public static function createFieldFromProperty(IndexInterface $index, DataDefinitionInterface $property, $datasource_id, $property_path, $field_id = NULL, $type = NULL) { if (!isset($field_id)) { $field_id = static::getNewFieldId($index, $property_path); } if (!isset($type)) { $type_mapping = static::getFieldTypeMapping(); $property_type = $property->getDataType(); if (isset($type_mapping[$property_type])) { $type = $type_mapping[$property_type]; } else { $args['%property'] = $property->getLabel(); $args['%property_path'] = $property_path; $args['%type'] = $property_type; $message = new FormattableMarkup('No default data type mapping could be found for property %property (%property_path) of type %type.', $args); throw new SearchApiException($message); } } $field_info = array('label' => $property->getLabel(), 'datasource_id' => $datasource_id, 'property_path' => $property_path, 'type' => $type); return self::createField($index, $field_id, $field_info); }
/** * Returns the translation form element for a given configuration definition. * * For complex data structures (such as mappings) that are translatable * wholesale but contain non-translatable properties, the form element is * responsible for checking access to the source value of those properties. In * case of formatted text, for example, access to the source text format must * be checked. If the translator does not have access to the text format, the * textarea must be disabled and the translator may not be able to translate * this particular configuration element. If the translator does have access * to the text format, the element must be locked down to that particular text * format; in other words, the format may not be changed by the translator * (because the text format property is not itself translatable). * * In addition, the form element is responsible for checking whether the * value of such non-translatable properties in the translated configuration * is equal to the corresponding source values. If not, that means that the * source value has changed after the translation was added. In this case - * again - the translation of this element must be disabled if the translator * does not have access to the source value of the non-translatable property. * For example, if a formatted text element, whose source format was plain * text when it was first translated, gets changed to the Full HTML format, * simply changing the format of the translation would lead to an XSS * vulnerability as the translated text, that was intended to be escaped, * would now be displayed unescaped. Thus, if the translator does not have * access to the Full HTML format, the translation for this particular element * may not be updated at all (the textarea must be disabled). Only if access * to the Full HTML format is granted, an explicit translation taking into * account the updated source value(s) may be submitted. * * In the specific case of formatted text this logic is implemented by * utilizing a form element of type 'text_format' and its #format and * #allowed_formats properties. The access logic explained above is then * handled by the 'text_format' element itself, specifically by * filter_process_format(). In case such a rich element is not available for * translation of complex data, similar access logic must be implemented * manually. * * @param \Drupal\Core\Language\LanguageInterface $translation_language * The language to display the translation form for. * @param mixed $source_config * The configuration value of the element in the source language. * @param mixed $translation_config * The configuration value of the element in the language to translate to. * * @return array * Form API array to represent the form element. * * @see \Drupal\config_translation\FormElement\TextFormat * @see filter_process_format() */ protected function getTranslationElement(LanguageInterface $translation_language, $source_config, $translation_config) { // Add basic properties that apply to all form elements. return array('#title' => $this->t('@label <span class="visually-hidden">(@source_language)</span>', array('@label' => $this->t($this->definition->getLabel()), '@source_language' => $translation_language->getName())), '#default_value' => $translation_config, '#attributes' => array('lang' => $translation_language->getId())); }
/** * {@inheritdoc} */ public function getFormElement(DataDefinitionInterface $definition, LanguageInterface $language, $value) { $description = $this->t('A user-defined date format. See the <a href="@url">PHP manual</a> for available options.', array('@url' => 'http://php.net/manual/function.date.php')); $format = $this->t('Displayed as %date_format', array('%date_format' => \Drupal::service('date.formatter')->format(REQUEST_TIME, 'custom', $value))); return array('#type' => 'textfield', '#title' => $this->t($definition->getLabel()) . '<span class="visually-hidden"> (' . $language->name . ')</span>', '#description' => $description, '#default_value' => $value, '#attributes' => array('lang' => $language->getId()), '#field_suffix' => ' <div class="edit-date-format-suffix"><small id="edit-date-format-suffix">' . $format . '</small></div>', '#ajax' => array('callback' => 'Drupal\\config_translation\\FormElement\\DateFormat::ajaxSample', 'event' => 'keyup', 'progress' => array('type' => 'throbber', 'message' => NULL))); }
/** * {@inheritdoc} */ public function getFormElement(DataDefinitionInterface $definition, LanguageInterface $language, $value) { return array('#type' => 'textfield', '#default_value' => $value, '#title' => $this->t($definition->getLabel()) . '<span class="visually-hidden"> (' . $language->getName() . ')</span>', '#attributes' => array('lang' => $language->getId())); }
/** * {@inheritdoc} */ public function getLabel() { if (!$this->wrappedProperty) { return NULL; } return $this->wrappedProperty->getLabel(); }