I started working on existing project and right from beginning, it displayed tons of alerts in specific pages.
This is what Drupal outputs:
Notice: Array to string conversion in Drupal\Core\Template\AttributeArray->__toString() (line 74 of /home/project/drupal/web/core/lib/Drupal/Core/Template/AttributeArray.php) #0 /home/project/drupal/web/core/includes/bootstrap.inc(584): _drupal_error_handler_real(8, 'Array to string...', '/home/jspa/proj...', 74, Array)
#1 [internal function]: _drupal_error_handler(8, 'Array to string...', '/home/jspa/proj...', 74, Array)
#2 /home/project/drupal/web/core/lib/Drupal/Core/Template/AttributeArray.php(74): implode(' ', Array)
#3 /home/project/drupal/web/core/lib/Drupal/Core/Template/AttributeValueBase.php(53): Drupal\Core\Template\AttributeArray->__toString()
#4 /home/project/drupal/web/core/lib/Drupal/Core/Template/Attribute.php(289): Drupal\Core\Template\AttributeValueBase->render()
#5 /home/project/drupal/web/core/lib/Drupal/Core/Render/Element/HtmlTag.php(88): Drupal\Core\Template\Attribute->__toString()
#6 [internal function]: Drupal\Core\Render\Element\HtmlTag::preRenderHtmlTag(Array)
#7 /home/project/drupal/web/core/lib/Drupal/Core/Render/Renderer.php(378): call_user_func(Array, Array)
#8 /home/project/drupal/web/core/lib/Drupal/Core/Render/Renderer.php(450): Drupal\Core\Render\Renderer->doRender(Array)
#9 /home/project/drupal/web/core/lib/Drupal/Core/Render/Renderer.php(195): Drupal\Core\Render\Renderer->doRender(Array, true)
#10 /home/project/drupal/web/core/lib/Drupal/Core/Render/Renderer.php(151): Drupal\Core\Render\Renderer->render(Array, true)
#11 /home/project/drupal/web/core/lib/Drupal/Core/Render/Renderer.php(582): Drupal\Core\Render\Renderer->Drupal\Core\Render\{closure}()
#12 /home/project/drupal/web/core/lib/Drupal/Core/Render/Renderer.php(152): Drupal\Core\Render\Renderer->executeInRenderContext(Object(Drupal\Core\Render\RenderContext), Object(Closure))
#13 /home/project/drupal/web/core/lib/Drupal/Core/Render/HtmlResponseAttachmentsProcessor.php(325): Drupal\Core\Render\Renderer->renderPlain(Array)
#14 /home/project/drupal/web/core/lib/Drupal/Core/Render/HtmlResponseAttachmentsProcessor.php(206): Drupal\Core\Render\HtmlResponseAttachmentsProcessor->renderHtmlResponseAttachmentPlaceholders(Object(Drupal\Core\Render\HtmlResponse), Array, Array)
#15 /home/project/drupal/web/core/modules/big_pipe/src/Render/BigPipeResponseAttachmentsProcessor.php(94): Drupal\Core\Render\HtmlResponseAttachmentsProcessor->processAttachments(Object(Drupal\Core\Render\HtmlResponse))
#16 /home/project/drupal/web/core/lib/Drupal/Core/EventSubscriber/HtmlResponseSubscriber.php(45): Drupal\big_pipe\Render\BigPipeResponseAttachmentsProcessor->processAttachments(Object(Drupal\Core\Render\HtmlResponse))
#17 [internal function]: Drupal\Core\EventSubscriber\HtmlResponseSubscriber->onRespond(Object(Symfony\Component\HttpKernel\Event\FilterResponseEvent), 'kernel.response', Object(Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher))
#18 /home/project/drupal/web/core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php(111): call_user_func(Array, Object(Symfony\Component\HttpKernel\Event\FilterResponseEvent), 'kernel.response', Object(Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher))
#19 /home/project/drupal/vendor/symfony/http-kernel/HttpKernel.php(191): Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch('kernel.response', Object(Symfony\Component\HttpKernel\Event\FilterResponseEvent))
#20 /home/project/drupal/vendor/symfony/http-kernel/HttpKernel.php(173): Symfony\Component\HttpKernel\HttpKernel->filterResponse(Object(Drupal\Core\Render\HtmlResponse), Object(Symfony\Component\HttpFoundation\Request), 1)
#21 /home/project/drupal/vendor/symfony/http-kernel/HttpKernel.php(68): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1)
#22 /home/project/drupal/web/core/lib/Drupal/Core/StackMiddleware/Session.php(57): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#23 /home/project/drupal/web/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(47): Drupal\Core\StackMiddleware\Session->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#24 /home/project/drupal/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(99): Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#25 /home/project/drupal/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(78): Drupal\page_cache\StackMiddleware\PageCache->pass(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#26 /home/project/drupal/web/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(47): Drupal\page_cache\StackMiddleware\PageCache->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#27 /home/project/drupal/web/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(52): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#28 /home/project/drupal/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#29 /home/project/drupal/web/core/lib/Drupal/Core/DrupalKernel.php(693): Stack\StackedHttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#30 /home/project/drupal/web/index.php(21): Drupal\Core\DrupalKernel->handle(Object(Symfony\Component\HttpFoundation\Request))
#31 {main}.
There is no helpful information in there, no indication that the issue is within project codebase. So I went to Drupal\Core\Template\AttributeArray
and changed __toString
method from from
public function __toString() {
// Filter out any empty values before printing.
$this->value = array_unique(array_filter($this->value));
return Html::escape(implode(' ', $this->value));
}
to this
public function __toString() {
// Filter out any empty values before printing.
$this->value = array_unique(array_filter($this->value));
$bad = false;
foreach ($this->value as $k => $v) {
if (!is_string($v)) {
$bad = true;
break;
}
}
if ($bad) {
ksm($this->value);
}
return Html::escape(implode(' ', $this->value));
}
That resulted in possible cause:
The reason is that php implode
function can't implode multi-dimensional array thus resulting in this error.
This happens only in pages where menus are rendered.
- PHP 7.1.26
- Drupal 8.6.9 (via https://github.com/drupal-composer/drupal-project)
The question is - why this could possibly happen, that #allowed_tags
are in there?
Update #1: These issues are something that are inconsistent. Some core areas in backend uses that format by default. I made a quick-fix for those issues according to the idea, that there should be only a list of classes at most.
public function __toString() {
// Normalize value removing any invalid sub-array structures
$normalizedValue = [];
$bad = false;
foreach ($this->value as $k => $v) {
if (is_numeric($k) && is_string($v)) {
$normalizedValue[] = $v;
} else {
$bad = true;
}
}
if ($bad) {
ksm('Invalid attribute array value', $this->value);
}
// Filter out any empty values before printing.
$this->value = array_unique(array_filter($normalizedValue));
return Html::escape(implode(' ', $normalizedValue));
}
This worked well in removing errors, but during normal usage, it still popped out ksm
output noticing about the fact that reason is still there. But alas - this fix broke inline file upload feature within ckeditor, as my code apparently removed important part of form/model or something like that.
'#markup' => 'Content Menu'
and the allowed tags are added mistakenly to an attribute key should reveal the module/theme. – 4k4 Feb 22 '19 at 10:14['class1', 'class2']
. – 4k4 Feb 22 '19 at 10:33