diff --git a/core/includes/form.inc b/core/includes/form.inc index 42206a4..b4c43f9 100644 --- a/core/includes/form.inc +++ b/core/includes/form.inc @@ -983,7 +983,7 @@ function form_select_options($element, $choices = NULL) { $options .= form_select_options($element, $choice); $options .= ''; } - elseif (is_object($choice)) { + elseif (is_object($choice) && property_exists($choice, 'option')) { $options .= form_select_options($element, $choice->option); } else { diff --git a/core/lib/Drupal/Core/Annotation/Translation.php b/core/lib/Drupal/Core/Annotation/Translation.php index ad32b5e..b33beee 100644 --- a/core/lib/Drupal/Core/Annotation/Translation.php +++ b/core/lib/Drupal/Core/Annotation/Translation.php @@ -55,11 +55,25 @@ class Translation extends AnnotationBase { use StringTranslationTrait; /** - * The translation of the value passed to the constructor of the class. + * The string to be translated. * * @var string */ - protected $translation; + protected $string; + + /** + * The translation arguments. + * + * @var array + */ + protected $arguments; + + /** + * The translation options. + * + * @var array + */ + protected $options; /** * Constructs a new class instance. @@ -75,22 +89,45 @@ class Translation extends AnnotationBase { * - context (optional): a string that describes the context of "value"; */ public function __construct(array $values) { - $string = $values['value']; - $arguments = isset($values['arguments']) ? $values['arguments'] : array(); - $options = array(); + $this->string = $values['value']; + $this->arguments = isset($values['arguments']) ? $values['arguments'] : array(); + $this->options = array(); if (!empty($values['context'])) { - $options = array( + $this->options = array( 'context' => $values['context'], ); } - $this->translation = $this->t($string, $arguments, $options); } /** - * Implements Drupal\Core\Annotation\AnnotationInterface::get(). + * {@inheritdoc} */ public function get() { - return $this->translation; + return $this; + } + + /** + * {@inheritdoc} + */ + public function __toString() { + return $this->render(); + } + + /** + * Renders the object as a string. + * + * @return string + * The translated string. + */ + public function render() { + return $this->t($this->string, $this->arguments, $this->options); + } + + /** + * Magic __sleep() method to avoid serializing the string translator. + */ + function __sleep() { + return array('string', 'arguments', 'options'); } } diff --git a/core/lib/Drupal/Core/Config/StorableConfigBase.php b/core/lib/Drupal/Core/Config/StorableConfigBase.php index 4a5fd1d..581ff31 100644 --- a/core/lib/Drupal/Core/Config/StorableConfigBase.php +++ b/core/lib/Drupal/Core/Config/StorableConfigBase.php @@ -183,6 +183,9 @@ protected function castValue($key, $value) { if ($element && ($element instanceof Undefined || $element instanceof Ignore)) { return $value; } + if (is_object($value) && method_exists($value, '__toString')) { + $value = (string) $value; + } if ((is_scalar($value) || $value === NULL)) { if ($element && $element instanceof PrimitiveInterface) { // Special handling for integers and floats since the configuration diff --git a/core/lib/Drupal/Core/Form/OptGroup.php b/core/lib/Drupal/Core/Form/OptGroup.php index f94d62d..745ef13 100644 --- a/core/lib/Drupal/Core/Form/OptGroup.php +++ b/core/lib/Drupal/Core/Form/OptGroup.php @@ -43,7 +43,7 @@ public static function flattenOptions(array $array) { */ protected static function doFlattenOptions(array $array, array &$options) { foreach ($array as $key => $value) { - if (is_object($value)) { + if (is_object($value) && property_exists($value, 'option')) { static::doFlattenOptions($value->option, $options); } elseif (is_array($value)) { diff --git a/core/modules/block/src/BlockBase.php b/core/modules/block/src/BlockBase.php index 68f5f36..958da0b 100644 --- a/core/modules/block/src/BlockBase.php +++ b/core/modules/block/src/BlockBase.php @@ -36,7 +36,7 @@ public function label() { } $definition = $this->getPluginDefinition(); - return $definition['admin_label']; + return (string) $definition['admin_label']; } /** diff --git a/core/modules/editor/src/Tests/EditorManagerTest.php b/core/modules/editor/src/Tests/EditorManagerTest.php index 997d861..51cd285 100644 --- a/core/modules/editor/src/Tests/EditorManagerTest.php +++ b/core/modules/editor/src/Tests/EditorManagerTest.php @@ -82,7 +82,7 @@ public function testManager() { $this->editorManager->clearCachedDefinitions(); // Case 2: a text editor available. - $this->assertIdentical(array('unicorn' => 'Unicorn Editor'), $this->editorManager->listOptions(), 'When some text editor is enabled, the manager works correctly.'); + $this->assertIdentical('Unicorn Editor', (string) $this->editorManager->listOptions()['unicorn'], 'When some text editor is enabled, the manager works correctly.'); // Case 3: a text editor available & associated (but associated only with // the 'Full HTML' text format). diff --git a/core/modules/system/src/Tests/Plugin/Discovery/DiscoveryTestBase.php b/core/modules/system/src/Tests/Plugin/Discovery/DiscoveryTestBase.php index 9d0be54..d93bfcb 100644 --- a/core/modules/system/src/Tests/Plugin/Discovery/DiscoveryTestBase.php +++ b/core/modules/system/src/Tests/Plugin/Discovery/DiscoveryTestBase.php @@ -7,6 +7,7 @@ namespace Drupal\system\Tests\Plugin\Discovery; +use Drupal\Core\Annotation\Translation; use Drupal\simpletest\UnitTestBase; /** @@ -49,7 +50,7 @@ function testDiscoveryInterface() { // Ensure that getDefinition() returns the expected definition. foreach ($this->expectedDefinitions as $id => $definition) { - $this->assertIdentical($this->discovery->getDefinition($id), $definition); + $this->assertDefinitionIdentical($this->discovery->getDefinition($id), $definition); } // Ensure that an empty array is returned if no plugin definitions are found. @@ -58,5 +59,30 @@ function testDiscoveryInterface() { // Ensure that NULL is returned as the definition of a non-existing plugin. $this->assertIdentical($this->emptyDiscovery->getDefinition('non_existing', FALSE), NULL, 'NULL returned as the definition of a non-existing plugin.'); } + + /** + * Asserts a definition against an expected definition. + * + * Converts any instances of \Drupal\Core\Annotation\Translation to a string. + * + * @param array $definition + * The definition to test. + * @param array $expected_definition + * The expected definition to test against. + * + * @return + * TRUE if the assertion succeeded, FALSE otherwise. + */ + protected function assertDefinitionIdentical(array $definition, array $expected_definition) { + $func = function (&$item, $key){ + if ($item instanceof Translation) { + $item = (string) $item; + } + }; + array_walk_recursive($definition, $func); + array_walk_recursive($expected_definition, $func); + return $this->assertIdentical($definition, $expected_definition); + } + } diff --git a/core/modules/views/src/Plugin/views/filter/FilterPluginBase.php b/core/modules/views/src/Plugin/views/filter/FilterPluginBase.php index 902b543..8bf44c1 100644 --- a/core/modules/views/src/Plugin/views/filter/FilterPluginBase.php +++ b/core/modules/views/src/Plugin/views/filter/FilterPluginBase.php @@ -1160,11 +1160,11 @@ protected function prepareFilterSelectOptions(&$options) { } // FAPI has some special value to allow hierarchy. // @see _form_options_flatten - elseif (is_object($label)) { + elseif (is_object($label) && property_exists($label, 'option')) { $this->prepareFilterSelectOptions($options[$value]->option); } else { - $options[$value] = strip_tags(decode_entities($label)); + $options[$value] = strip_tags(decode_entities((string) $label)); } } } diff --git a/core/modules/views_ui/src/ViewListBuilder.php b/core/modules/views_ui/src/ViewListBuilder.php index 68ad5b0..1e9d496 100644 --- a/core/modules/views_ui/src/ViewListBuilder.php +++ b/core/modules/views_ui/src/ViewListBuilder.php @@ -229,8 +229,8 @@ protected function getDisplaysList(EntityInterface $view) { $displays = array(); foreach ($view->get('display') as $display) { $definition = $this->displayManager->getDefinition($display['display_plugin']); - if (!empty($definition['admin'])) { - $displays[$definition['admin']] = TRUE; + if (isset($definition['admin']) && $display_admin = (string) $definition['admin']) { + $displays[$display_admin] = TRUE; } } diff --git a/core/tests/Drupal/Tests/Core/Annotation/TranslationTest.php b/core/tests/Drupal/Tests/Core/Annotation/TranslationTest.php index 071df3e..bcfe00d 100644 --- a/core/tests/Drupal/Tests/Core/Annotation/TranslationTest.php +++ b/core/tests/Drupal/Tests/Core/Annotation/TranslationTest.php @@ -62,7 +62,7 @@ public function testGet(array $values, $expected) { $annotation = new Translation($values); - $this->assertSame($expected, $annotation->get()); + $this->assertSame($expected, (string) $annotation->get()); } /** diff --git a/core/tests/Drupal/Tests/Core/Form/OptGroupTest.php b/core/tests/Drupal/Tests/Core/Form/OptGroupTest.php index 0807448..febc6c6 100644 --- a/core/tests/Drupal/Tests/Core/Form/OptGroupTest.php +++ b/core/tests/Drupal/Tests/Core/Form/OptGroupTest.php @@ -50,11 +50,15 @@ public function providerTestFlattenOptions() { $object1->option = array('foo' => 'foo'); $object2 = new \stdClass(); $object2->option = array(array('foo' => 'foo'), array('foo' => 'foo')); + $object3 = new \stdClass(); return array( array(array('foo' => 'foo')), array(array(array('foo' => 'foo'))), array(array($object1)), array(array($object2)), + array(array($object1, $object2)), + array(array('foo' => $object3)), + array(array('foo' => $object3, $object1, array('foo' => 'foo'))), ); }