elgentos / magento2-prismicio

Magento 2 Prismic integration
GNU General Public License v3.0
38 stars 18 forks source link

TypeError: Prismic\Dom\RichText::asHtml(): Argument #3 ($htmlSerializer) must be of type ?closure #71

Closed speedupmate closed 2 years ago

speedupmate commented 2 years ago

Seems like it fails to display rich-text fields defined in prismic content types due prismic-sdk now requiring a closure instead of array

TypeError: Prismic\Dom\RichText::asHtml(): Argument #3 ($htmlSerializer) must be of type ?closure, array given, called in /var/www/store/vendor/elgentos/module-prismicio/Block/Dom/RichText.php on line 41 and defined in /var/www/store/vendor/elgentos/prismic-php-sdk/src/Prismic/Dom/RichText.php:43
Stack trace:
#0 /var/www/store/vendor/elgentos/module-prismicio/Block/Dom/RichText.php(41): Prismic\Dom\RichText::asHtml()
#1 /var/www/store/vendor/elgentos/module-prismicio/Block/AbstractBlock.php(56): Elgentos\PrismicIO\Block\Dom\RichText->fetchDocumentView()
#2 /var/www/store/vendor/magento/framework/View/Element/AbstractBlock.php(1095): Elgentos\PrismicIO\Block\AbstractBlock->_toHtml()
#3 /var/www/store/vendor/magento/framework/View/Element/AbstractBlock.php(1099): Magento\Framework\View\Element\AbstractBlock->Magento\Framework\View\Element\{closure}()
#4 /var/www/store/vendor/magento/framework/View/Element/AbstractBlock.php(660): Magento\Framework\View\Element\AbstractBlock->_loadCache()
#5 /var/www/store/vendor/magento/framework/View/Layout.php(578): Magento\Framework\View\Element\AbstractBlock->toHtml()
#6 /var/www/store/vendor/magento/framework/View/Layout.php(555): Magento\Framework\View\Layout->_renderBlock()
#7 /var/www/store/generated/code/Magento/Framework/View/Layout/Interceptor.php(149): Magento\Framework\View\Layout->renderNonCachedElement()
#8 /var/www/store/vendor/magento/framework/View/Layout.php(510): Magento\Framework\View\Layout\Interceptor->renderNonCachedElement()
#9 /var/www/store/generated/code/Magento/Framework/View/Layout/Interceptor.php(140): Magento\Framework\View\Layout->renderElement()
#10 /var/www/store/vendor/magento/framework/View/Layout.php(606): Magento\Framework\View\Layout\Interceptor->renderElement()
#11 /var/www/store/vendor/magento/framework/View/Layout.php(557): Magento\Framework\View\Layout->_renderContainer()
#12 /var/www/store/generated/code/Magento/Framework/View/Layout/Interceptor.php(149): Magento\Framework\View\Layout->renderNonCachedElement()
#13 /var/www/store/vendor/magento/framework/View/Layout.php(510): Magento\Framework\View\Layout\Interceptor->renderNonCachedElement()
#14 /var/www/store/generated/code/Magento/Framework/View/Layout/Interceptor.php(140): Magento\Framework\View\Layout->renderElement()
#15 /var/www/store/vendor/magento/framework/View/Layout.php(606): Magento\Framework\View\Layout\Interceptor->renderElement()
#16 /var/www/store/vendor/magento/framework/View/Layout.php(557): Magento\Framework\View\Layout->_renderContainer()
#17 /var/www/store/generated/code/Magento/Framework/View/Layout/Interceptor.php(149): Magento\Framework\View\Layout->renderNonCachedElement()
#18 /var/www/store/vendor/magento/framework/View/Layout.php(510): Magento\Framework\View\Layout\Interceptor->renderNonCachedElement()
#19 /var/www/store/generated/code/Magento/Framework/View/Layout/Interceptor.php(140): Magento\Framework\View\Layout->renderElement()
#20 /var/www/store/vendor/magento/framework/View/Layout.php(606): Magento\Framework\View\Layout\Interceptor->renderElement()
#21 /var/www/store/vendor/magento/framework/View/Layout.php(557): Magento\Framework\View\Layout->_renderContainer()
#22 /var/www/store/generated/code/Magento/Framework/View/Layout/Interceptor.php(149): Magento\Framework\View\Layout->renderNonCachedElement()
#23 /var/www/store/vendor/magento/framework/View/Layout.php(510): Magento\Framework\View\Layout\Interceptor->renderNonCachedElement()
#24 /var/www/store/generated/code/Magento/Framework/View/Layout/Interceptor.php(140): Magento\Framework\View\Layout->renderElement()
#25 /var/www/store/vendor/magento/framework/View/Layout.php(606): Magento\Framework\View\Layout\Interceptor->renderElement()
#26 /var/www/store/vendor/magento/framework/View/Layout.php(557): Magento\Framework\View\Layout->_renderContainer()
#27 /var/www/store/generated/code/Magento/Framework/View/Layout/Interceptor.php(149): Magento\Framework\View\Layout->renderNonCachedElement()
#28 /var/www/store/vendor/magento/framework/View/Layout.php(510): Magento\Framework\View\Layout\Interceptor->renderNonCachedElement()
#29 /var/www/store/generated/code/Magento/Framework/View/Layout/Interceptor.php(140): Magento\Framework\View\Layout->renderElement()
#30 /var/www/store/vendor/magento/framework/View/Layout.php(606): Magento\Framework\View\Layout\Interceptor->renderElement()
#31 /var/www/store/vendor/magento/framework/View/Layout.php(557): Magento\Framework\View\Layout->_renderContainer()
#32 /var/www/store/generated/code/Magento/Framework/View/Layout/Interceptor.php(149): Magento\Framework\View\Layout->renderNonCachedElement()
#33 /var/www/store/vendor/magento/framework/View/Layout.php(510): Magento\Framework\View\Layout\Interceptor->renderNonCachedElement()
#34 /var/www/store/generated/code/Magento/Framework/View/Layout/Interceptor.php(140): Magento\Framework\View\Layout->renderElement()
#35 /var/www/store/vendor/magento/framework/View/Layout.php(606): Magento\Framework\View\Layout\Interceptor->renderElement()
#36 /var/www/store/vendor/magento/framework/View/Layout.php(557): Magento\Framework\View\Layout->_renderContainer()
#37 /var/www/store/generated/code/Magento/Framework/View/Layout/Interceptor.php(149): Magento\Framework\View\Layout->renderNonCachedElement()
#38 /var/www/store/vendor/magento/framework/View/Layout.php(510): Magento\Framework\View\Layout\Interceptor->renderNonCachedElement()
#39 /var/www/store/generated/code/Magento/Framework/View/Layout/Interceptor.php(140): Magento\Framework\View\Layout->renderElement()
#40 /var/www/store/vendor/magento/framework/View/Layout.php(606): Magento\Framework\View\Layout\Interceptor->renderElement()
#41 /var/www/store/vendor/magento/framework/View/Layout.php(557): Magento\Framework\View\Layout->_renderContainer()
#42 /var/www/store/generated/code/Magento/Framework/View/Layout/Interceptor.php(149): Magento\Framework\View\Layout->renderNonCachedElement()
#43 /var/www/store/vendor/magento/framework/View/Layout.php(510): Magento\Framework\View\Layout\Interceptor->renderNonCachedElement()
#44 /var/www/store/generated/code/Magento/Framework/View/Layout/Interceptor.php(140): Magento\Framework\View\Layout->renderElement()
#45 /var/www/store/vendor/magento/framework/View/Layout.php(975): Magento\Framework\View\Layout\Interceptor->renderElement()
#46 /var/www/store/vendor/magento/framework/Interception/Interceptor.php(58): Magento\Framework\View\Layout->getOutput()
#47 /var/www/store/vendor/magento/framework/Interception/Interceptor.php(138): Magento\Framework\View\Layout\Interceptor->___callParent()
#48 /var/www/store/vendor/magento/framework/Interception/Interceptor.php(153): Magento\Framework\View\Layout\Interceptor->Magento\Framework\Interception\{closure}()
#49 /var/www/store/generated/code/Magento/Framework/View/Layout/Interceptor.php(347): Magento\Framework\View\Layout\Interceptor->___callPlugins()
#50 /var/www/store/vendor/magento/framework/View/Result/Page.php(260): Magento\Framework\View\Layout\Interceptor->getOutput()
#51 /var/www/store/vendor/magento/framework/View/Result/Layout.php(171): Magento\Framework\View\Result\Page->render()
#52 /var/www/store/vendor/magento/framework/Interception/Interceptor.php(58): Magento\Framework\View\Result\Layout->renderResult()
#53 /var/www/store/vendor/magento/framework/Interception/Interceptor.php(138): Magento\Framework\View\Result\Page\Interceptor->___callParent()
#54 /var/www/store/vendor/magento/framework/Interception/Interceptor.php(153): Magento\Framework\View\Result\Page\Interceptor->Magento\Framework\Interception\{closure}()
#55 /var/www/store/generated/code/Magento/Framework/View/Result/Page/Interceptor.php(95): Magento\Framework\View\Result\Page\Interceptor->___callPlugins()
#56 /var/www/store/vendor/magento/framework/App/Http.php(120): Magento\Framework\View\Result\Page\Interceptor->renderResult()
#57 /var/www/store/generated/code/Magento/Framework/App/Http/Interceptor.php(23): Magento\Framework\App\Http->launch()
#58 /var/www/store/vendor/magento/framework/App/Bootstrap.php(264): Magento\Framework\App\Http\Interceptor->launch()
#59 /var/www/store/pub/index.php(33): Magento\Framework\App\Bootstrap->run()
#60 {main}
speedupmate commented 2 years ago

As I did a deeper investigation how this works then currently although serialiser is implemented there's no way to pass a custom serialiser closure to each element that gets rendered .

Would be cool if we could attach a serialiser method inside our own block or inject it within our templates set, get to child or parent or current block and that would allow access to RichText html fragments and make it possible to manipulate those per content type and content field . Usecase would be here like : H2 title in prismic > serialise > H2 class="tailwindclass" as output

JeroenBoersma commented 2 years ago

Hi @speedupmate thanks for bringing this up, the SDK is not that pluggable as Magento is...

By default, Prismic uses a custom labels concept... This means you need to think ahead and it will become the responsibility of content editors to select the correct "label" which will reflect as a "class" in all Prismic implementations.. [Here](https://github.com/elgentos/prismicio-php- kit/blob/4bcf06cf1194625fae0391ed0e7c97573009206b/src/Prismic/Fragment/AttributesTrait.php#L14) is an example how default Prismic processes this...

Back to a custom serializer and the implementation in Prismic. This is possible, but needs some extra work!

tbd (will update this message)

JeroenBoersma commented 2 years ago

I finally see the error... duh

JeroenBoersma commented 2 years ago

I've updated https://github.com/elgentos/prismicio-php-kit/blob/master/src/Prismic/Dom/RichText.php#L46

This now only accepts a closure... I will add a fn() => ... around it and it will be fixed!

Many thanks for bringing this up, this is a bug I created :)

JeroenBoersma commented 2 years ago

To use a custom serializer in Magento you can create a plugin on \Elgentos\PrismicIO\ViewModel\HtmlSerializer::serialize A afterSerialize would get string $result = null, \Prismic\Fragment\BlockInterface $object, string $content

function afterSerialize (null $result, \Prismic\Fragment\BlockInterface $object, string $content)
{
    if ($object->type === 'heading1') {
        return '<h1 class="awesome">' . $content . '</h1>';
    }

    return $result;
}

If a custom serializer does not return null that result will be returned, else the default serializer of Prismic will render the content

JeroenBoersma commented 2 years ago

Again, sorry I broke it!

speedupmate commented 2 years ago

Actually you could just shortcut this to block scope and add getHtmlSerializer() type of reference on method and that would allow to just override any custom-type directly in template level where you work with the custom-type and donät have to detect it extra as you would in plugin :

https://github.com/elgentos/magento2-prismicio/blob/9e81a9449a83989f0bc5839759fa2a3ddbe0d9de/Block/Dom/RichText.php#L41

you could

public function fetchDocumentView(): string
{
    $html = PrismicRichText::asHtml(
        $this->getContext(),
        $this->getLinkResolver(),
        $this->getHtmlSerializer() ?? fn($object, string $content) => $this->htmlSerializer->serialize($object, $content)
    );

    return $this->replaceRelativeUrl($html);
}

and then just in some template or block without the complexity of a plugin

$block->setHtmlSerializer(yourfunction)
JeroenBoersma commented 2 years ago

Done https://github.com/elgentos/magento2-prismicio/releases/tag/1.9.1

speedupmate commented 2 years ago

Thanks