diff -u b/field_example/field_example.module b/field_example/field_example.module --- b/field_example/field_example.module +++ b/field_example/field_example.module @@ -82,13 +82,13 @@ // Keeping it simple, only 6-digit hex values accepted. if (strlen($value) != 6) { - \Drupal::formBuilder()->setError($element, t("Please enter a 6-digit hexadecimal value.")); + \Drupal::formBuilder()->setError($element, $form_state, t("Please enter a 6-digit hexadecimal value.")); return; } // Validate that this is a legit hex value. if (!ctype_xdigit($value)) { - \Drupal::formBuilder()->setError($element, t("Please enter a valid hexadecimal value.")); + \Drupal::formBuilder()->setError($element, $form_state, t("Please enter a valid hexadecimal value.")); } // Add a preceding pound sign. @@ -111,7 +111,7 @@ } // If they gave us anything that's not hex, reject it. if ((strlen($values[$colorfield]) != 2) || !ctype_xdigit($values[$colorfield])) { - \Drupal::formBuilder()->setError($element[$colorfield], t("Saturation value must be a 2-digit hexadecimal value between 00 and ff.")); + \Drupal::formBuilder()->setError($element[$colorfield], $form_state, t("Saturation value must be a 2-digit hexadecimal value between 00 and ff.")); } } diff -u b/field_example/lib/Drupal/field_example/Plugin/Field/FieldFormatter/ColorBackgroudFormatter.php b/field_example/lib/Drupal/field_example/Plugin/Field/FieldFormatter/ColorBackgroudFormatter.php --- b/field_example/lib/Drupal/field_example/Plugin/Field/FieldFormatter/ColorBackgroudFormatter.php +++ b/field_example/lib/Drupal/field_example/Plugin/Field/FieldFormatter/ColorBackgroudFormatter.php @@ -30,7 +30,7 @@ $elements = array(); foreach ($items as $delta => $item) { - $elements[$delta] = array( + $elements[$delta] = array( '#type' => 'html_tag', '#tag' => 'p', '#value' => t('The content area color has been changed to @code', array('@code' => $item->value)), diff -u b/field_example/lib/Drupal/field_example/Plugin/Field/FieldType/RgbItem.php b/field_example/lib/Drupal/field_example/Plugin/Field/FieldType/RgbItem.php --- b/field_example/lib/Drupal/field_example/Plugin/Field/FieldType/RgbItem.php +++ b/field_example/lib/Drupal/field_example/Plugin/Field/FieldType/RgbItem.php @@ -7,8 +7,9 @@ namespace Drupal\field_example\Plugin\Field\FieldType; -use Drupal\Core\Field\ConfigFieldItemBase; -use Drupal\field\FieldInterface; +use Drupal\Core\Field\FieldItemBase; +use Drupal\Core\Field\FieldDefinitionInterface; +use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\TypedData\DataDefinition; /** @@ -23,30 +24,11 @@ * default_formatter = "field_example_simple_text" * ) */ -class RgbItem extends ConfigFieldItemBase { - - /** - * Definitions of the contained properties. - * - * @var array - */ - static $propertyDefinitions; - +class RgbItem extends FieldItemBase { /** * {@inheritdoc} */ - public function getPropertyDefinitions() { - if (!isset(static::$propertyDefinitions)) { - static::$propertyDefinitions['value'] = DataDefinition::create('string') - ->setLabel(t('Hex value')); - } - return static::$propertyDefinitions; - } - - /** - * {@inheritdoc} - */ - public static function schema(FieldInterface $field) { + public static function schema(FieldStorageDefinitionInterface $field_definition) { return array( 'columns' => array( 'value' => array( @@ -67,2 +49,12 @@ } + + /** + * {@inheritdoc} + */ + public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) { + $properties['value'] = DataDefinition::create('string') + ->setLabel(t('Hex value')); + + return $properties; + } } diff -u b/field_example/lib/Drupal/field_example/Plugin/Field/FieldWidget/ColorPickerWidget.php b/field_example/lib/Drupal/field_example/Plugin/Field/FieldWidget/ColorPickerWidget.php --- b/field_example/lib/Drupal/field_example/Plugin/Field/FieldWidget/ColorPickerWidget.php +++ b/field_example/lib/Drupal/field_example/Plugin/Field/FieldWidget/ColorPickerWidget.php @@ -2,7 +2,7 @@ /** * @file - * Contains \Drupal\field_example\Plugin\field\widget\ColorPickerWidget. + * Contains \Drupal\field_example\Plugin\Field\FieldWidget\ColorPickerWidget. */ namespace Drupal\field_example\Plugin\Field\FieldWidget; @@ -27,18 +27,19 @@ */ public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, array &$form_state) { $element = parent::formElement($items, $delta, $element, $form, $form_state); - $element += array( + $element['value'] += array( '#suffix' => '
', '#attributes' => array('class' => array('edit-field-example-colorpicker')), '#attached' => array( // Add Farbtastic color picker. 'library' => array( - array('system', 'jquery.farbtastic'), + 'core/jquery.farbtastic', ), // Add javascript to trigger the colorpicker. 'js' => array(drupal_get_path('module', 'field_example') . '/field_example.js'), ), ); + return $element; } diff -u b/field_example/lib/Drupal/field_example/Plugin/Field/FieldWidget/Text3Widget.php b/field_example/lib/Drupal/field_example/Plugin/Field/FieldWidget/Text3Widget.php --- b/field_example/lib/Drupal/field_example/Plugin/Field/FieldWidget/Text3Widget.php +++ b/field_example/lib/Drupal/field_example/Plugin/Field/FieldWidget/Text3Widget.php @@ -59,7 +59,7 @@ $element[$key]['#required'] = TRUE; } } - return $element; + return array('value' => $element); } } diff -u b/field_example/lib/Drupal/field_example/Plugin/Field/FieldWidget/TextWidget.php b/field_example/lib/Drupal/field_example/Plugin/Field/FieldWidget/TextWidget.php --- b/field_example/lib/Drupal/field_example/Plugin/Field/FieldWidget/TextWidget.php +++ b/field_example/lib/Drupal/field_example/Plugin/Field/FieldWidget/TextWidget.php @@ -38,7 +38,7 @@ '#maxlength' => 7, '#element_validate' => array('field_example_text_validate'), ); - return $element; + return array('value' => $element); } } reverted: --- b/field_example/lib/Drupal/field_example/Tests/FieldExampleTest.php +++ /dev/null @@ -1,165 +0,0 @@ - 'Field Example', - 'description' => 'Create a content type with example_field_rgb fields, create a node, check for correct values.', - 'group' => 'Examples', - ); - } - - /** - * Test basic functionality of the example field. - * - * - Creates a content type. - * - Adds a single-valued field_example_rgb to it. - * - Adds a multivalued field_example_rgb to it. - * - Creates a node of the new type. - * - Populates the single-valued field. - * - Populates the multivalued field with two items. - * - Tests the result. - */ - function testExampleFieldBasic() { - $content_type_machine = strtolower($this->randomName(10)); - $title = $this->randomName(20); - - // Create and login user. - $account = $this->drupalCreateUser(array('administer content types')); - $this->drupalLogin($account); - - // Add a content type. - $this->drupalGet('admin/structure/types/add'); - $edit = array( - 'name' => $content_type_machine, - 'type' => $content_type_machine, - ); - $this->drupalPostForm(NULL, $edit, t('Save and manage fields')); - $this->assertText(t('The content type @name has been added.', array('@name' => $content_type_machine))); - - $single_text_field = strtolower($this->randomName(10)); - $single_colorpicker_field = strtolower($this->randomName(10)); - $single_3text_field = strtolower($this->randomName(10)); - $multivalue_3text_field = strtolower($this->randomName(10)); - - // Description of fields to be created; - $fields[$single_text_field] = array( - 'widget' => 'field_example_text', - 'cardinality' => '1', - ); - $fields[$single_colorpicker_field] = array( - 'widget' => 'field_example_colorpicker', - 'cardinality' => 1, - ); - $fields[$single_3text_field] = array( - 'widget' => 'field_example_3text', - 'cardinality' => 1, - ); - $fields[$multivalue_3text_field] = array( - 'widget' => 'field_example_3text', - 'cardinality' => -1, - ); - - foreach ($fields as $fieldname => $details) { - $this->create_field($fieldname, $details['widget'], $details['cardinality']); - } - - menu_router_rebuild(); - $type_exists = db_query('SELECT 1 FROM {node_type} WHERE type = :type', array(':type' => $content_type_machine))->fetchField(); - $this->assertTrue($type_exists, 'The new content type has been created in the database.'); - - $permission = 'create ' . $content_type_machine . ' content'; - // Reset the permissions cache. - $this->checkPermissions(array($permission), TRUE); - - // Now that we have a new content type, create a user that has privileges - // on the content type. - $account = $this->drupalCreateUser(array($permission)); - $this->drupalLogin($account); - - $this->drupalGet('node/add/' . $content_type_machine); - - // Add a node. - $edit = array( - 'title' => $title, - 'field_' . $single_text_field . '[und][0][rgb]' => '#000001', - 'field_' . $single_colorpicker_field . '[und][0][rgb]' => '#000002', - - 'field_' . $single_3text_field . '[und][0][rgb][r]' => '00', - 'field_' . $single_3text_field . '[und][0][rgb][g]' => '00', - 'field_' . $single_3text_field . '[und][0][rgb][b]' => '03', - - 'field_' . $multivalue_3text_field . '[und][0][rgb][r]' => '00', - 'field_' . $multivalue_3text_field . '[und][0][rgb][g]' => '00', - 'field_' . $multivalue_3text_field . '[und][0][rgb][b]' => '04', - - ); - // We want to add a 2nd item to the multivalue field, so hit "add another". - $this->drupalPostForm(NULL, $edit, t('Add another item')); - - $edit = array( - 'field_' . $multivalue_3text_field . '[und][1][rgb][r]' => '00', - 'field_' . $multivalue_3text_field . '[und][1][rgb][g]' => '00', - 'field_' . $multivalue_3text_field . '[und][1][rgb][b]' => '05', - ); - // Now we can fill in the second item in the multivalue field and save. - $this->drupalPostForm(NULL, $edit, t('Save')); - $this->assertText(t('@content_type_machine @title has been created', array('@content_type_machine' => $content_type_machine, '@title' => $title))); - - - $output_strings = $this->xpath("//div[contains(@class,'field-type-field-example-rgb')]/div/div/p/text()"); - - $this->assertEqual((string)$output_strings[0], "The color code in this field is #000001"); - $this->assertEqual((string)$output_strings[1], "The color code in this field is #000002"); - $this->assertEqual((string)$output_strings[2], "The color code in this field is #000003"); - $this->assertEqual((string)$output_strings[3], "The color code in this field is #000004"); - $this->assertEqual((string)$output_strings[4], "The color code in this field is #000005"); - } - - /** - * Utility function to create fields on a content type. - * @param $field_name - * Name of the field, like field_something - * @param $widget_type - * Widget type, like field_example_3text - * @param $cardinality - * Cardinality - */ - protected function create_field($field_name, $widget_type, $cardinality) { - // Add a singleton field_example_text field. - $edit = array( - 'fields[_add_new_field][label]' => $field_name, - 'fields[_add_new_field][field_name]' => $field_name, - 'fields[_add_new_field][type]' => 'field_example_rgb', - //'fields[_add_new_field][widget_type]' => $widget_type, - ); - $this->drupalPostForm(NULL, $edit, t('Save')); - - // There are no settings for this, so just press the button. - $this->drupalPostForm(NULL, array(), t('Save field settings')); - - $edit = array('field[cardinality]' => (string)$cardinality); - - // Using all the default settings, so press the button. - $this->drupalPostForm(NULL, $edit, t('Save settings')); - debug(t('Saved settings for field %field_name with widget %widget_type and cardinality %cardinality', array('%field_name' => $field_name, '%widget_type' => $widget_type, '%cardinality' => $cardinality))); - $this->assertText(t('Saved @name configuration.', array('@name' => $field_name))); - } -} only in patch2: unchanged: --- /dev/null +++ b/field_example/lib/Drupal/field_example/FieldExampleWebTestBase.php @@ -0,0 +1,123 @@ +administratorAccount = $this->drupalCreateUser($permissions); + parent::drupalLogin($this->administratorAccount); + + // Prepare a new content type where the field will be added. + $this->contentTypeName = strtolower($this->randomName(10)); + $this->drupalGet('admin/structure/types/add'); + $edit = array( + 'name' => $this->contentTypeName, + 'type' => $this->contentTypeName, + ); + $this->drupalPostForm(NULL, $edit, t('Save and manage fields')); + $this->assertText(t('The content type @name has been added.', array('@name' => $this->contentTypeName))); + + // Reset the permission cache. + $create_permission = 'create ' . $this->contentTypeName . ' content'; + $this->checkPermissions(array($create_permission), TRUE); + + // Now that we have a new content type, create a user that has privileges + // on the content type. + $this->authorAccount = $this->drupalCreateUser(array($create_permission)); + } + + /** + * Create a field on the content type created during setUp(). + * + * @param string $type + * The storage field type to create + * @param string $widget_type + * The widget to use when editing this field + * @param int|string $cardinality + * Cardinality of the field. + * + * @return string + * Name of the field, like field_something + */ + protected function createField($type = 'field_example_rgb', $widget_type = 'field_example_text', $cardinality = 'number') { + $this->drupalGet('admin/structure/types/manage/' . $this->contentTypeName . '/fields'); + + $field_name = strtolower($this->randomName(10)); + // Add a singleton field_example_text field. + $edit = array( + 'fields[_add_new_field][label]' => $field_name, + 'fields[_add_new_field][field_name]' => $field_name, + 'fields[_add_new_field][type]' => $type, + ); + $this->drupalPostForm(NULL, $edit, t('Save')); + + $edit = array('field[cardinality]' => (string) $cardinality); + + // Using all the default settings, so press the button. + $this->drupalPostForm(NULL, $edit, t('Save field settings')); + debug(t('Saved settings for field %field_name with widget %widget_type and cardinality %cardinality', + array( + '%field_name' => $field_name, + '%widget_type' => $widget_type, + '%cardinality' => $cardinality, + ) + )); + $this->assertText(t('Updated field @name field settings.', array('@name' => $field_name))); + + // Set the widget type for the newly created field. + $this->drupalGet('admin/structure/types/manage/' . $this->contentTypeName . '/form-display'); + $edit = array( + 'fields[field_' . $field_name . '][type]' => $widget_type, + ); + $this->drupalPostForm(NULL, $edit, t('Save')); + + return $field_name; + } +} only in patch2: unchanged: --- /dev/null +++ b/field_example/lib/Drupal/field_example/Tests/Text3WidgetTest.php @@ -0,0 +1,110 @@ + 'Field Example with Text3Widget', + 'description' => 'Create a content type with a example_field_rgb field, configure it with the field_example_text-widget, create a node and check for correct values.', + 'group' => 'Examples', + ); + } + + /** + * Test basic functionality of the example field. + * + * - Creates a content type. + * - Adds a single-valued field_example_rgb to it. + * - Adds a multivalued field_example_rgb to it. + * - Creates a node of the new type. + * - Populates the single-valued field. + * - Populates the multivalued field with two items. + * - Tests the result. + */ + public function testSingleValueField() { + // Add a single field as administrator user. + $this->drupalLogin($this->administratorAccount); + $this->fieldName = $this->createField('field_example_rgb', 'field_example_3text', 'number'); + // Post-condition: Content type now has the desired field. + + // Switch to the author user to create content with this type and field. + $this->drupalLogin($this->authorAccount); + $this->drupalGet('node/add/' . $this->contentTypeName); + + // Fill the create form. + $title = $this->randomName(20); + $edit = array( + 'title[0][value]' => $title, + 'field_' . $this->fieldName . '[0][value][r]' => '00', + 'field_' . $this->fieldName . '[0][value][g]' => '0a', + 'field_' . $this->fieldName . '[0][value][b]' => '01', + ); + + // Create the content. + $this->drupalPostForm(NULL, $edit, t('Save')); + $this->assertText(t('@type @title has been created', array('@type' => $this->contentTypeName, '@title' => $title))); + + // Verify the value is shown when viewing this node. + $output_strings = $this->xpath("//div[contains(@class,'field-type-field-example-rgb')]/div/div/p/text()"); + $this->assertEqual((string) $output_strings[0], "The color code in this field is #000a01"); + } + + /** + * Test basic functionality of the example field. + * + * - Creates a content type. + * - Adds a single-valued field_example_rgb to it. + * - Adds a multivalued field_example_rgb to it. + * - Creates a node of the new type. + * - Populates the single-valued field. + * - Populates the multivalued field with two items. + * - Tests the result. + */ + public function testMultiValueField() { + // Add a single field as administrator user. + $this->drupalLogin($this->administratorAccount); + $this->fieldName = $this->createField('field_example_rgb', 'field_example_3text', '-1'); + // Post-condition: Content type now has the desired field. + + // Switch to the author user to create content with this type and field. + $this->drupalLogin($this->authorAccount); + $this->drupalGet('node/add/' . $this->contentTypeName); + + // Fill the create form. + $title = $this->randomName(20); + $edit = array( + 'title[0][value]' => $title, + 'field_' . $this->fieldName . '[0][value][r]' => '00', + 'field_' . $this->fieldName . '[0][value][g]' => 'ff', + 'field_' . $this->fieldName . '[0][value][b]' => '00', + ); + + // Add a 2nd item to the multivalue field, so hit "add another". + $this->drupalPostForm(NULL, $edit, t('Add another item')); + $edit = array( + 'field_' . $this->fieldName . '[1][value][r]' => 'ff', + 'field_' . $this->fieldName . '[1][value][g]' => 'ff', + 'field_' . $this->fieldName . '[1][value][b]' => 'ff', + ); + + // Create the content. + $this->drupalPostForm(NULL, $edit, t('Save')); + $this->assertText(t('@type @title has been created', array('@type' => $this->contentTypeName, '@title' => $title))); + + // Verify the values are shown when viewing this node. + $output_strings = $this->xpath("//div[contains(@class,'field-type-field-example-rgb')]/div/div/p/text()"); + $this->assertEqual((string) $output_strings[0], "The color code in this field is #00ff00"); + $this->assertEqual((string) $output_strings[1], "The color code in this field is #ffffff"); + } +} only in patch2: unchanged: --- /dev/null +++ b/field_example/lib/Drupal/field_example/Tests/TextWidgetTest.php @@ -0,0 +1,103 @@ + 'Field Example with Text Widget', + 'description' => 'Create a content type with a example_field_rgb field, configure it with the field_example_text-widget, create a node and check for correct values.', + 'group' => 'Examples', + ); + } + + /** + * Test basic functionality of the example field. + * + * - Creates a content type. + * - Adds a single-valued field_example_rgb to it. + * - Adds a multivalued field_example_rgb to it. + * - Creates a node of the new type. + * - Populates the single-valued field. + * - Populates the multivalued field with two items. + * - Tests the result. + */ + public function testSingleValueField() { + // Add a single field as administrator user. + $this->drupalLogin($this->administratorAccount); + $this->fieldName = $this->createField('field_example_rgb', 'field_example_text', 'number'); + + // Now that we have a content type with the desired field, switch to the author user to create content with it. + $this->drupalLogin($this->authorAccount); + $this->drupalGet('node/add/' . $this->contentTypeName); + + // Add a node. + $title = $this->randomName(20); + $edit = array( + 'title[0][value]' => $title, + 'field_' . $this->fieldName . '[0][value]' => '#000001', + ); + + // Create the content. + $this->drupalPostForm(NULL, $edit, t('Save')); + $this->assertText(t('@type @title has been created', array('@type' => $this->contentTypeName, '@title' => $title))); + + // Verify the value is shown when viewing this node. + $output_strings = $this->xpath("//div[contains(@class,'field-type-field-example-rgb')]/div/div/p/text()"); + $this->assertEqual((string) $output_strings[0], "The color code in this field is #000001"); + } + + /** + * Test basic functionality of the example field. + * + * - Creates a content type. + * - Adds a single-valued field_example_rgb to it. + * - Adds a multivalued field_example_rgb to it. + * - Creates a node of the new type. + * - Populates the single-valued field. + * - Populates the multivalued field with two items. + * - Tests the result. + */ + public function testMultiValueField() { + // Add a single field as administrator user. + $this->drupalLogin($this->administratorAccount); + $this->fieldName = $this->createField('field_example_rgb', 'field_example_text', '-1'); + + // Now that we have a content type with the desired field, switch to the author user to create content with it. + $this->drupalLogin($this->authorAccount); + $this->drupalGet('node/add/' . $this->contentTypeName); + + // Add a node. + $title = $this->randomName(20); + $edit = array( + 'title[0][value]' => $title, + 'field_' . $this->fieldName . '[0][value]' => '#00ff00', + ); + + // We want to add a 2nd item to the multivalue field, so hit "add another". + $this->drupalPostForm(NULL, $edit, t('Add another item')); + + $edit = array( + 'field_' . $this->fieldName . '[1][value]' => '#ffffff', + ); + + // Now we can fill in the second item in the multivalue field and save. + $this->drupalPostForm(NULL, $edit, t('Save')); + $this->assertText(t('@type @title has been created', array('@type' => $this->contentTypeName, '@title' => $title))); + + // Verify the value is shown when viewing this node. + $output_strings = $this->xpath("//div[contains(@class,'field-type-field-example-rgb')]/div/div/p/text()"); + $this->assertEqual((string) $output_strings[0], "The color code in this field is #00ff00"); + $this->assertEqual((string) $output_strings[1], "The color code in this field is #ffffff"); + } +}