示例#1
0
 /**
  * {@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()));
 }
 /**
  * {@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);
         }
     }
 }
示例#3
0
 /**
  * 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);
 }
示例#4
0
 /**
  * {@inheritdoc}
  */
 public function getConstraints()
 {
     $constraint_manager = $this->getTypedDataManager()->getValidationConstraintManager();
     $constraints = array();
     foreach ($this->definition->getConstraints() as $name => $options) {
         $constraints[] = $constraint_manager->create($name, $options);
     }
     return $constraints;
 }
示例#5
0
 /**
  * {@inheritdoc}
  */
 public function getConstraints()
 {
     // @todo: Add the typed data manager as proper dependency.
     $constraint_manager = \Drupal::typedDataManager()->getValidationConstraintManager();
     $constraints = array();
     foreach ($this->definition->getConstraints() as $name => $options) {
         $constraints[] = $constraint_manager->create($name, $options);
     }
     return $constraints;
 }
示例#6
0
 /**
  * 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);
 }
示例#7
0
 /**
  * Gets default constraints for the given data definition.
  *
  * This generates default constraint definitions based on the data definition;
  * e.g. a NotNull constraint is generated if the data is defined as required.
  * Besides that any constraints defined for the data type, i.e. below the
  * 'constraint' key of the type's plugin definition, are taken into account.
  *
  * @param \Drupal\Core\TypedData\DataDefinitionInterface $definition
  *   A data definition.
  *
  * @return array
  *   An array of validation constraint definitions, keyed by constraint name.
  *   Each constraint definition can be used for instantiating
  *   \Symfony\Component\Validator\Constraint objects.
  */
 public function getDefaultConstraints(DataDefinitionInterface $definition)
 {
     $constraints = array();
     $type_definition = $this->getDefinition($definition->getDataType());
     // Auto-generate a constraint for data types implementing a primitive
     // interface.
     if (is_subclass_of($type_definition['class'], '\\Drupal\\Core\\TypedData\\PrimitiveInterface')) {
         $constraints['PrimitiveType'] = array();
     }
     // Add in constraints specified by the data type.
     if (isset($type_definition['constraints'])) {
         $constraints += $type_definition['constraints'];
     }
     // Add the NotNull constraint for required data.
     if ($definition->isRequired()) {
         $constraints['NotNull'] = array();
     }
     // Check if the class provides allowed values.
     if (is_subclass_of($definition->getClass(), 'Drupal\\Core\\TypedData\\OptionsProviderInterface')) {
         $constraints['AllowedValues'] = array();
     }
     // Add any constraints about referenced data.
     if ($definition instanceof DataReferenceDefinitionInterface) {
         $constraints += $definition->getTargetDefinition()->getConstraints();
     }
     return $constraints;
 }
示例#8
0
 /**
  * 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);
 }
示例#9
0
 /**
  * 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)));
 }
示例#11
0
 /**
  * {@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()));
 }
示例#12
0
 /**
  * {@inheritdoc}
  */
 public function getMatchingContexts(array $contexts, DataDefinitionInterface $definition)
 {
     return array_filter($contexts, function (ContextInterface $context) use($definition) {
         $context_definition = $context->getContextDefinition()->getDataDefinition();
         // If the data types do not match, this context is invalid.
         if ($definition->getDataType() != $context_definition->getDataType()) {
             return FALSE;
         }
         // If any constraint does not match, this context is invalid.
         // @todo This is too restrictive, consider only relying on data types.
         foreach ($definition->getConstraints() as $constraint_name => $constraint) {
             if ($context_definition->getConstraint($constraint_name) != $constraint) {
                 return FALSE;
             }
         }
         // All contexts with matching data type and contexts are valid.
         return TRUE;
     });
 }
示例#13
0
 /**
  * Checks that the data type of a mapped variable matches the expectation.
  *
  * @param \Drupal\Core\Plugin\Context\ContextDefinitionInterface $context_definition
  *   The context definition of the context on the plugin.
  * @param \Drupal\Core\TypedData\DataDefinitionInterface $provided
  *   The data definition of the mapped variable to the context.
  * @param string $context_name
  *   The name of the context on the plugin.
  * @param \Drupal\rules\Engine\IntegrityViolationList $violation_list
  *   The list of violations where new ones will be added.
  */
 protected function checkDataTypeCompatible(ContextDefinitionInterface $context_definition, DataDefinitionInterface $provided, $context_name, IntegrityViolationList $violation_list)
 {
     $expected_class = $context_definition->getDataDefinition()->getClass();
     $provided_class = $provided->getClass();
     $expected_type_problem = NULL;
     if (is_subclass_of($expected_class, PrimitiveInterface::class) && !is_subclass_of($provided_class, PrimitiveInterface::class)) {
         $expected_type_problem = $this->t('primitive');
     } elseif (is_subclass_of($expected_class, ListInterface::class) && !is_subclass_of($provided_class, ListInterface::class)) {
         $expected_type_problem = $this->t('list');
     } elseif (is_subclass_of($expected_class, ComplexDataInterface::class) && !is_subclass_of($provided_class, ComplexDataInterface::class)) {
         $expected_type_problem = $this->t('complex');
     }
     if ($expected_type_problem) {
         $violation = new IntegrityViolation();
         $violation->setMessage($this->t('Expected a @expected_type data type for context %context_name but got a @provided_type data type instead.', ['@expected_type' => $expected_type_problem, '%context_name' => $context_definition->getLabel(), '@provided_type' => $provided->getDataType()]));
         $violation->setContextName($context_name);
         $violation_list->add($violation);
     }
 }
示例#14
0
 /**
  * {@inheritdoc}
  */
 public function canFilter(DataDefinitionInterface $definition)
 {
     return is_subclass_of($definition->getClass(), DateTimeInterface::class);
 }
示例#15
0
 /**
  * {@inheritdoc}
  */
 public function addConstraint($constraint_name, $options = NULL) {
   return $this->wrappedProperty->addConstraint($constraint_name, $options);
 }
 /**
  * Checks that the data type of a mapped variable matches the expectation.
  *
  * @param \Drupal\Core\Plugin\Context\ContextDefinitionInterface $context_definition
  *   The context definition of the context on the plugin.
  * @param \Drupal\Core\TypedData\DataDefinitionInterface $provided
  *   The data definition of the mapped variable to the context.
  * @param string $context_name
  *   The name of the context on the plugin.
  * @param \Drupal\rules\Engine\IntegrityViolationList $violation_list
  *   The list of violations where new ones will be added.
  */
 protected function checkDataTypeCompatible(CoreContextDefinitionInterface $context_definition, DataDefinitionInterface $provided, $context_name, IntegrityViolationList $violation_list)
 {
     // Compare data types. For now, fail if they are not equal.
     // @todo: Add support for matching based upon type-inheritance.
     $target_type = $context_definition->getDataDefinition()->getDataType();
     // Special case any and entity target types for now.
     if ($target_type == 'any' || $target_type == 'entity' && strpos($provided->getDataType(), 'entity:') !== FALSE) {
         return;
     }
     if ($target_type != $provided->getDataType()) {
         $expected_type_problem = $context_definition->getDataDefinition()->getDataType();
         $violation = new IntegrityViolation();
         $violation->setMessage($this->t('Expected a @expected_type data type for context %context_name but got a @provided_type data type instead.', ['@expected_type' => $expected_type_problem, '%context_name' => $context_definition->getLabel(), '@provided_type' => $provided->getDataType()]));
         $violation->setContextName($context_name);
         $violation->setUuid($this->getUuid());
         $violation_list->add($violation);
     }
 }