/** * Tests that a list can be chosen with a property path selector. */ public function testPropertyPathList() { $rule = $this->rulesExpressionManager->createRule(); $rule->addAction('rules_variable_add', ContextConfig::create()->setValue('type', 'string')->setValue('value', '')->provideAs('variable_added', 'result')); $loop = $this->rulesExpressionManager->createInstance('rules_loop', ['list' => 'node.field_text']); $loop->addAction('rules_data_set', ContextConfig::create()->map('data', 'result')->setValue('value', '{{result}} {{list_item}}')->process('value', 'rules_tokens')); $rule->addExpressionObject($loop); // Create a fake field for the fake node for testing. $list_definition = $this->typedDataManager->createListDataDefinition('string'); $field_text = new FieldItemList($list_definition); $field_text->setValue(['Hello', 'world', 'this', 'is', 'the', 'loop']); $node = $this->prophesizeEntity(NodeInterface::class); $node->get('field_text')->willReturn($field_text); // We cannot use EntityDataDefinitionInterface here because the context // system in core violates the interface and relies on the actuoal class. // @see https://www.drupal.org/node/2660216 $node_definition = $this->prophesize(EntityDataDefinition::class); $node_definition->getPropertyDefinition("field_text")->willReturn($list_definition); $context_definition = $this->getContextDefinitionFor('entity:node', $node_definition); $component = RulesComponent::create($rule)->addContextDefinition('node', $context_definition)->provideContext('result')->setContextValue('node', $node->reveal()); $violations = $component->checkIntegrity(); $this->assertEquals(0, iterator_count($violations)); $result = $component->execute(); $this->assertEquals(' Hello world this is the loop', $result['result']); }
/** * Asserts correct field access grants for a field. */ public function assertFieldAccess($field, $viewer, $target, $view, $edit) { $field_definition = $this->getMock('Drupal\\Core\\Field\\FieldDefinitionInterface'); $field_definition->expects($this->any())->method('getName')->will($this->returnValue($field)); $this->items->expects($this->any())->method('getEntity')->will($this->returnValue($this->{$target})); foreach (array('view' => $view, 'edit' => $edit) as $operation => $result) { $message = SafeMarkup::format("User @field field access returns @result with operation '@op' for @account accessing @target", array('@field' => $field, '@result' => !isset($result) ? 'null' : ($result ? 'true' : 'false'), '@op' => $operation, '@account' => $viewer, '@target' => $target)); $this->assertSame($result, $this->accessControlHandler->fieldAccess($operation, $field_definition, $this->{$viewer}, $this->items), $message); } }
/** * Asserts correct field access grants for a field. */ public function assertFieldAccess($field, $viewer, $target, $view, $edit) { $field_definition = $this->getMock('Drupal\\Core\\Field\\FieldDefinitionInterface'); $field_definition->expects($this->any())->method('getName')->will($this->returnValue($field)); $this->items->expects($this->any())->method('getEntity')->will($this->returnValue($this->{$target})); foreach (array('view' => $view, 'edit' => $edit) as $operation => $result) { $result_text = !isset($result) ? 'null' : ($result ? 'true' : 'false'); $message = "User '{$field}' field access returns '{$result_text}' with operation '{$operation}' for '{$viewer}' accessing '{$target}'"; $this->assertSame($result, $this->accessControlHandler->fieldAccess($operation, $field_definition, $this->{$viewer}, $this->items), $message); } }
/** * {@inheritdoc} */ public function defaultValuesFormSubmit(array $element, array &$form, FormStateInterface $form_state) { $values = parent::defaultValuesFormSubmit($element, $form, $form_state); foreach ($values as $delta => $value) { unset($values[$delta]['plugin_instance']); } return $values; }
/** * {@inheritdoc} */ public function offsetExists($offset) { // For consistency with what happens in get(), we force offsetExists() to // be TRUE for delta 0. if ($offset === 0) { return TRUE; } return parent::offsetExists($offset); }
/** * {@inheritdoc} */ public function defaultValuesFormSubmit(array $element, array &$form, FormStateInterface $form_state) { $default_value = parent::defaultValuesFormSubmit($element, $form, $form_state); // Convert numeric IDs to UUIDs to ensure config deployability. $ids = array(); foreach ($default_value as $delta => $properties) { $ids[] = $properties['target_id']; } $entities = \Drupal::entityManager()->getStorage($this->getSetting('target_type'))->loadMultiple($ids); foreach ($default_value as $delta => $properties) { unset($default_value[$delta]['target_id']); $default_value[$delta]['target_uuid'] = $entities[$properties['target_id']]->uuid(); } return $default_value; }
/** * {@inheritdoc} */ public function access($operation = 'view', AccountInterface $account = NULL, $return_as_object = FALSE) { if ($operation === 'edit') { // Only users with administer comments permission can edit the comment // status field. $result = AccessResult::allowedIfHasPermission($account ?: \Drupal::currentUser(), 'administer comments'); return $return_as_object ? $result : $result->isAllowed(); } if ($operation === 'view') { // Only users with either post comments or access comments permisison can // view the field value. The formatter, // Drupal\comment\Plugin\Field\FieldFormatter\CommentDefaultFormatter, // takes care of showing the thread and form based on individual // permissions, so if a user only has ‘post comments’ access, only the // form will be shown and not the comments. $result = AccessResult::allowedIfHasPermission($account ?: \Drupal::currentUser(), 'access comments')->orIf(AccessResult::allowedIfHasPermission($account ?: \Drupal::currentUser(), 'post comments')); return $return_as_object ? $result : $result->isAllowed(); } return parent::access($operation, $account, $return_as_object); }
/** * @covers ::equals */ public function testEqualsEmptyItems() { /** @var \Drupal\Core\Field\FieldItemBase $fv */ $first_field_item = $this->getMockForAbstractClass('Drupal\\Core\\Field\\FieldItemBase', [], '', FALSE); $first_field_item->setValue(['0' => 1, '1' => 2]); $second_field_item = $this->getMockForAbstractClass('Drupal\\Core\\Field\\FieldItemBase', [], '', FALSE); $second_field_item->setValue(['1' => 2, '0' => 1]); $empty_field_item = $this->getMockForAbstractClass('Drupal\\Core\\Field\\FieldItemBase', [], '', FALSE); // Mock the field type manager and place it in the container. $field_type_manager = $this->getMock('Drupal\\Core\\Field\\FieldTypePluginManagerInterface'); $container = new ContainerBuilder(); $container->set('plugin.manager.field.field_type', $field_type_manager); \Drupal::setContainer($container); $field_storage_definition = $this->getMock('Drupal\\Core\\Field\\FieldStorageDefinitionInterface'); $field_storage_definition->expects($this->any())->method('getColumns')->willReturn([0 => '0', 1 => '1']); $field_definition = $this->getMock('Drupal\\Core\\Field\\FieldDefinitionInterface'); $field_definition->expects($this->any())->method('getFieldStorageDefinition')->willReturn($field_storage_definition); $field_list_a = new FieldItemList($field_definition); $field_list_b = new FieldItemList($field_definition); // Set up the mocking necessary for creating field items. $field_type_manager->expects($this->any())->method('createFieldItem')->willReturnOnConsecutiveCalls($first_field_item, $second_field_item, $empty_field_item, $empty_field_item); // Set the field item values. $field_list_a->setValue($first_field_item); $field_list_b->setValue($second_field_item); $field_list_a->appendItem($empty_field_item); // Field list A has an empty item. $this->assertEquals(FALSE, $field_list_a->equals($field_list_b)); // Field lists A and B have empty items. $field_list_b->appendItem($empty_field_item); $this->assertEquals(TRUE, $field_list_a->equals($field_list_b)); // Field list B has an empty item. $field_list_a->filterEmptyItems(); $this->assertEquals(FALSE, $field_list_a->equals($field_list_b)); // Neither field lists A and B have empty items. $field_list_b->filterEmptyItems(); $this->assertEquals(TRUE, $field_list_a->equals($field_list_b)); }
/** * @return bool */ public function isEmpty() { return $this->fieldItemList->isEmpty(); }
/** * {@inheritdoc} */ public static function processDefaultValue($default_value, FieldableEntityInterface $entity, FieldDefinitionInterface $definition) { // Explicitly call the base class so that we can get the default value // types. $default_value = FieldItemList::processDefaultValue($default_value, $entity, $definition); // Allow either the start or end date to have a default, but not require // defaults for both. if (!empty($default_value[0]['default_date_type']) || !empty($default_value[0]['default_end_date_type'])) { // A default value should be in the format and timezone used for date // storage. All-day ranges are stored the same as date+time ranges. We // only provide a default value for the first item, as do all fields. // Otherwise, there is no way to clear out unwanted values on multiple // value fields. $storage_format = $definition->getSetting('datetime_type') == DateRangeItem::DATETIME_TYPE_DATE ? DATETIME_DATE_STORAGE_FORMAT : DATETIME_DATETIME_STORAGE_FORMAT; $default_values = [[]]; if (!empty($default_value[0]['default_date_type'])) { $start_date = new DrupalDateTime($default_value[0]['default_date'], DATETIME_STORAGE_TIMEZONE); $start_value = $start_date->format($storage_format); $default_values[0]['value'] = $start_value; $default_values[0]['start_date'] = $start_date; } if (!empty($default_value[0]['default_end_date_type'])) { $end_date = new DrupalDateTime($default_value[0]['default_end_date'], DATETIME_STORAGE_TIMEZONE); $end_value = $end_date->format($storage_format); $default_values[0]['end_value'] = $end_value; $default_values[0]['end_date'] = $end_date; } $default_value = $default_values; } return $default_value; }
/** * {@inheritdoc} */ public static function processDefaultValue($default_value, FieldableEntityInterface $entity, FieldDefinitionInterface $definition) { $default_value = parent::processDefaultValue($default_value, $entity, $definition); if (isset($default_value[0]['default_date_type'])) { // A default value should be in the format and timezone used for date // storage. $date = new DrupalDateTime($default_value[0]['default_date'], DATETIME_STORAGE_TIMEZONE); $storage_format = $definition->getSetting('datetime_type') == DateTimeItem::DATETIME_TYPE_DATE ? DATETIME_DATE_STORAGE_FORMAT : DATETIME_DATETIME_STORAGE_FORMAT; $value = $date->format($storage_format); // We only provide a default value for the first item, as do all fields. // Otherwise, there is no way to clear out unwanted values on multiple value // fields. $default_value = array(array('value' => $value, 'date' => $date)); } return $default_value; }