0

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:

enter image description here

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.

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.

8
  • No repro here - I have tons of sites based on drupal-project, at 8.6.10 (and previously earlier versions), all rendering menus without this problem. You're probably going to need to start disabling contrib/custom modules/themes one by one to see if you can at least isolate the root cause
    – Clive
    Feb 22, 2019 at 10:08
  • @Clive I just don't know Drupal enough, to be able to know where to search for an issue, even more, this is not my original system. What should I search for in app code?
    – Deele
    Feb 22, 2019 at 10:14
  • A full text search where '#markup' => 'Content Menu' and the allowed tags are added mistakenly to an attribute key should reveal the module/theme.
    – 4uk4
    Feb 22, 2019 at 10:14
  • @4k4 No luck with that. Does Drupal add '#allowed_tags' by itself automatically at certain point?
    – Deele
    Feb 22, 2019 at 10:25
  • No, not to a key of an Attribute object. A valid AttributeArray value would be ['class1', 'class2'].
    – 4uk4
    Feb 22, 2019 at 10:33

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.