Commit f7716551 authored by webchick's avatar webchick

Issue #2552799 by heddn, glenshewchuck, Xano, deepakaryan1988, swentel,...

Issue #2552799 by heddn, glenshewchuck, Xano, deepakaryan1988, swentel, jordanpagewhite, yched, tim.plunkett: FieldType with no available widget causes Fatal error
parent aced68bf
......@@ -297,14 +297,17 @@ public function getConstraints() {
*/
public function defaultValuesForm(array &$form, FormStateInterface $form_state) {
if (empty($this->getFieldDefinition()->getDefaultValueCallback())) {
if ($widget = $this->defaultValueWidget($form_state)) {
// Place the input in a separate place in the submitted values tree.
$widget = $this->defaultValueWidget($form_state);
$element = array('#parents' => array('default_value_input'));
$element += $widget->form($this, $element, $form_state);
return $element;
}
else {
return ['#markup' => $this->t('No widget available for: %type.', ['%type' => $this->getFieldDefinition()->getType()])];
}
}
}
/**
......@@ -312,7 +315,7 @@ public function defaultValuesForm(array &$form, FormStateInterface $form_state)
*/
public function defaultValuesFormValidate(array $element, array &$form, FormStateInterface $form_state) {
// Extract the submitted value, and validate it.
$widget = $this->defaultValueWidget($form_state);
if ($widget = $this->defaultValueWidget($form_state)) {
$widget->extractFormValues($this, $element, $form_state);
// Force a non-required field definition.
// @see self::defaultValueWidget().
......@@ -324,16 +327,18 @@ public function defaultValuesFormValidate(array $element, array &$form, FormStat
$widget->flagErrors($this, $violations, $element, $form_state);
}
}
}
/**
* {@inheritdoc}
*/
public function defaultValuesFormSubmit(array $element, array &$form, FormStateInterface $form_state) {
// Extract the submitted value, and return it as an array.
$widget = $this->defaultValueWidget($form_state);
if ($widget = $this->defaultValueWidget($form_state)) {
$widget->extractFormValues($this, $element, $form_state);
return $this->getValue();
}
}
/**
* {@inheritdoc}
......@@ -348,8 +353,8 @@ public static function processDefaultValue($default_value, FieldableEntityInterf
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state of the (entire) configuration form.
*
* @return \Drupal\Core\Field\WidgetInterface
* A Widget object.
* @return \Drupal\Core\Field\WidgetInterface|null
* A Widget object or NULL if no widget is available.
*/
protected function defaultValueWidget(FormStateInterface $form_state) {
if (!$form_state->has('default_value_widget')) {
......
......@@ -18,6 +18,8 @@
* label = @Translation("Last changed"),
* description = @Translation("An entity field containing a UNIX timestamp of when the entity has been last updated."),
* no_ui = TRUE,
* default_widget = "datetime_default",
* default_formatter = "timestamp",
* list_class = "\Drupal\Core\Field\ChangedFieldItemList"
* )
*
......
......@@ -15,7 +15,8 @@
* label = @Translation("Created"),
* description = @Translation("An entity field containing a UNIX timestamp of when the entity has been created."),
* no_ui = TRUE,
* default_formatter = "timestamp",
* default_widget = "datetime_default",
* default_formatter = "timestamp"
* )
*/
class CreatedItem extends TimestampItem {
......
......@@ -32,6 +32,7 @@
* description = @Translation("An entity field containing an entity reference."),
* category = @Translation("Reference"),
* no_ui = TRUE,
* default_widget = "entity_reference_autocomplete",
* default_formatter = "entity_reference_label",
* list_class = "\Drupal\Core\Field\EntityReferenceFieldItemList",
* constraints = {"ValidReference" = {}}
......
......@@ -19,6 +19,7 @@
* label = @Translation("Timestamp"),
* description = @Translation("An entity field containing a UNIX timestamp value."),
* no_ui = TRUE,
* default_widget = "datetime_default",
* default_formatter = "timestamp",
* constraints = {
* "ComplexData" = {
......
......@@ -151,7 +151,7 @@ public function prepareConfiguration($field_type, array $configuration) {
// If no widget is specified, use the default widget.
if (!isset($configuration['type'])) {
$field_type = $this->fieldTypeManager->getDefinition($field_type);
$configuration['type'] = $field_type['default_widget'];
$configuration['type'] = isset($field_type['default_widget']) ? $field_type['default_widget'] : NULL;
}
// Filter out unknown settings, and fill in defaults for missing settings.
$default_settings = $this->getDefaultSettings($configuration['type']);
......
......@@ -276,6 +276,12 @@ protected function buildFieldRow(FieldDefinitionInterface $field_definition, arr
$display_options = $this->entity->getComponent($field_name);
$label = $field_definition->getLabel();
// Disable fields without any applicable plugins.
if (empty($this->getApplicablePluginOptions($field_definition))) {
$this->entity->removeComponent($field_name)->save();
$display_options = $this->entity->getComponent($field_name);
}
$regions = array_keys($this->getRegions());
$field_row = array(
'#attributes' => array('class' => array('draggable', 'tabledrag-leaf')),
......@@ -814,15 +820,15 @@ protected function getExtraFields() {
abstract protected function getEntityDisplay($entity_type_id, $bundle, $mode);
/**
* Returns an array of widget or formatter options for a field.
* Returns an array of applicable widget or formatter options for a field.
*
* @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
* The field definition.
*
* @return array
* An array of widget or formatter options.
* An array of applicable widget or formatter options.
*/
protected function getPluginOptions(FieldDefinitionInterface $field_definition) {
protected function getApplicablePluginOptions(FieldDefinitionInterface $field_definition) {
$options = $this->pluginManager->getOptions($field_definition->getType());
$applicable_options = array();
foreach ($options as $option => $label) {
......@@ -831,6 +837,20 @@ protected function getPluginOptions(FieldDefinitionInterface $field_definition)
$applicable_options[$option] = $label;
}
}
return $applicable_options;
}
/**
* Returns an array of widget or formatter options for a field.
*
* @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
* The field definition.
*
* @return array
* An array of widget or formatter options.
*/
protected function getPluginOptions(FieldDefinitionInterface $field_definition) {
$applicable_options = $this->getApplicablePluginOptions($field_definition);
return $applicable_options + array('hidden' => '- ' . $this->t('Hidden') . ' -');
}
......
......@@ -8,8 +8,10 @@
namespace Drupal\Tests\Core\Field;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemInterface;
use Drupal\Core\Field\FieldItemList;
use Drupal\Core\Form\FormState;
use Drupal\Tests\UnitTestCase;
/**
......@@ -155,4 +157,60 @@ public function testEqualsEmptyItems() {
$this->assertEquals(TRUE, $field_list_a->equals($field_list_b));
}
/**
* @covers ::defaultValuesForm
*/
public function testDefaultValuesForm() {
$field_definition = $this->getMock(FieldDefinitionInterface::class);
$field_definition->expects($this->any())
->method('getType')
->willReturn('field_type');
/** @var \Drupal\Core\Field\FieldItemList|\PHPUnit_Framework_MockObject_MockObject $field_list */
$field_list = $this->getMock(FieldItemList::class, ['defaultValueWidget'], [$field_definition]);
$field_list->expects($this->any())
->method('defaultValueWidget')
->willReturn(NULL);
$form = [];
$form_state = new FormState();
$string_translation = $this->getStringTranslationStub();
$field_list->setStringTranslation($string_translation);
$this->assertEquals('No widget available for: <em class="placeholder">field_type</em>.', $field_list->defaultValuesForm($form, $form_state)['#markup']);
}
/**
* @covers ::defaultValuesFormValidate
*/
public function testDefaultValuesFormValidate() {
$field_definition = $this->getMock(FieldDefinitionInterface::class);
/** @var \Drupal\Core\Field\FieldItemList|\PHPUnit_Framework_MockObject_MockObject $field_list */
$field_list = $this->getMock(FieldItemList::class, ['defaultValueWidget', 'validate'], [$field_definition]);
$field_list->expects($this->any())
->method('defaultValueWidget')
->willReturn(NULL);
$field_list->expects($this->never())
->method('validate');
$form = [];
$form_state = new FormState();
$field_list->defaultValuesFormValidate([], $form, $form_state);
}
/**
* @covers ::defaultValuesFormSubmit
*/
public function testDefaultValuesFormSubmit() {
$field_definition = $this->getMock(FieldDefinitionInterface::class);
/** @var \Drupal\Core\Field\FieldItemList|\PHPUnit_Framework_MockObject_MockObject $field_list */
$field_list = $this->getMock(FieldItemList::class, ['defaultValueWidget', 'getValue'], [$field_definition]);
$field_list->expects($this->any())
->method('defaultValueWidget')
->willReturn(NULL);
$form = [];
$form_state = new FormState();
$field_list->expects($this->never())
->method('getValue');
$this->assertNull($field_list->defaultValuesFormSubmit([], $form, $form_state));
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment