craftcms / ckeditor

Edit rich text content in Craft CMS using CKEditor.
https://plugins.craftcms.com/ckeditor
GNU General Public License v3.0
45 stars 23 forks source link

Issue with custom TwigFunction after CKEditor 4.1.0 #248

Open thomascoppein opened 2 weeks ago

thomascoppein commented 2 weeks ago

Description

Since the latest update to CKEditor 4.1.0, I have encountered an issue with a custom module that provides a Twig function for use in my longform components. This functionality was working correctly in the previous version of CKEditor.

Steps to reproduce

  1. Create custom module with TwigFunction
  2. Init module
  3. Call Twig function in component

Additional info

i-just commented 2 weeks ago

Hi, @thomascoppein, what’s the issue you’ve encountered? Can you please provide more info on this?

thomascoppein commented 2 weeks ago

Hi @i-just , when adding a new Entry to the CKEditor field I get an Twig Syntax Error that my function is unknown. While in the previous version I never encountered this problem. The function mentioned in the error is from a custom module thats loaded into my project.

i-just commented 2 weeks ago

Can you please share the stack trace for this?

thomascoppein commented 2 weeks ago

Yes, it appears when I save in the admin environment.

Twig\Error\SyntaxError: Unknown "classNames" function. Did you mean "className"? in /Users/user/Documents/workspace/project-name/templates/components/button/index.twig:32
Stack trace:
#0 /Users/user/Documents/workspace/project-name/vendor/twig/twig/src/ExpressionParser.php(477): Twig\ExpressionParser->getFunctionNodeClass('classNames', 32)
#1 /Users/user/Documents/workspace/project-name/vendor/twig/twig/src/ExpressionParser.php(240): Twig\ExpressionParser->getFunctionNode('classNames', 32)
#2 /Users/user/Documents/workspace/project-name/vendor/twig/twig/src/ExpressionParser.php(177): Twig\ExpressionParser->parsePrimaryExpression()
#3 /Users/user/Documents/workspace/project-name/vendor/twig/twig/src/ExpressionParser.php(72): Twig\ExpressionParser->getPrimary()
#4 /Users/user/Documents/workspace/project-name/vendor/twig/twig/src/ExpressionParser.php(406): Twig\ExpressionParser->parseExpression()
#5 /Users/user/Documents/workspace/project-name/vendor/twig/twig/src/ExpressionParser.php(283): Twig\ExpressionParser->parseHashExpression()
#6 /Users/user/Documents/workspace/project-name/vendor/twig/twig/src/ExpressionParser.php(177): Twig\ExpressionParser->parsePrimaryExpression()
#7 /Users/user/Documents/workspace/project-name/vendor/twig/twig/src/ExpressionParser.php(72): Twig\ExpressionParser->getPrimary()
#8 /Users/user/Documents/workspace/project-name/vendor/craftcms/cms/src/web/twig/tokenparsers/TagTokenParser.php(45): Twig\ExpressionParser->parseExpression()
#9 /Users/user/Documents/workspace/project-name/vendor/twig/twig/src/Parser.php(170): craft\web\twig\tokenparsers\TagTokenParser->parse(Object(Twig\Token))
#10 /Users/user/Documents/workspace/project-name/vendor/twig/twig/src/Parser.php(83): Twig\Parser->subparse(NULL, false)
#11 /Users/user/Documents/workspace/project-name/vendor/twig/twig/src/Environment.php(490): Twig\Parser->parse(Object(Twig\TokenStream))
#12 /Users/user/Documents/workspace/project-name/vendor/twig/twig/src/Environment.php(518): Twig\Environment->parse(Object(Twig\TokenStream))
#13 /Users/user/Documents/workspace/project-name/vendor/craftcms/cms/src/web/twig/Environment.php(39): Twig\Environment->compileSource(Object(Twig\Source))
#14 /Users/user/Documents/workspace/project-name/vendor/twig/twig/src/Environment.php(350): craft\web\twig\Environment->compileSource(Object(Twig\Source))
#15 /Users/user/Documents/workspace/project-name/vendor/twig/twig/src/Template.php(322): Twig\Environment->loadTemplate('__TwigTemplate_...', 'components/butt...', NULL)
#16 /Users/user/Documents/workspace/project-name/storage/runtime/compiled_templates/62/62cc9a51907b70483f70365af88c7367.php(38): Twig\Template->loadTemplate('components/butt...', '_partials/entry...', 1)
#17 /Users/user/Documents/workspace/project-name/vendor/twig/twig/src/Template.php(394): __TwigTemplate_13d572a7bf5b754e860f9e2582dae3a6->doDisplay(Array, Array)
#18 /Users/user/Documents/workspace/project-name/vendor/twig/twig/src/Template.php(367): Twig\Template->displayWithErrorHandling(Array, Array)
#19 /Users/user/Documents/workspace/project-name/vendor/twig/twig/src/Template.php(379): Twig\Template->display(Array)
#20 /Users/user/Documents/workspace/project-name/vendor/twig/twig/src/TemplateWrapper.php(38): Twig\Template->render(Array)
#21 /Users/user/Documents/workspace/project-name/vendor/twig/twig/src/Environment.php(280): Twig\TemplateWrapper->render(Array)
#22 /Users/user/Documents/workspace/project-name/vendor/craftcms/cms/src/web/View.php(488): Twig\Environment->render('_partials/entry...', Array)
#23 /Users/user/Documents/workspace/project-name/vendor/craftcms/cms/src/helpers/ElementHelper.php(930): craft\web\View->renderTemplate('_partials/entry...', Array, 'site')
#24 /Users/user/Documents/workspace/project-name/vendor/craftcms/cms/src/base/Element.php(6117): craft\helpers\ElementHelper::renderElements(Array, Array)
#25 /Users/user/Documents/workspace/project-name/vendor/craftcms/ckeditor/src/data/Entry.php(37): craft\base\Element->render()
#26 /Users/user/Documents/workspace/project-name/vendor/craftcms/ckeditor/src/data/FieldData.php(175): craft\ckeditor\data\Entry->getHtml()
#27 [internal function]: craft\ckeditor\data\FieldData->craft\ckeditor\data\{closure}(Object(craft\ckeditor\data\Entry), 1)
#28 /Users/user/Documents/workspace/project-name/vendor/illuminate/collections/Arr.php(600): array_map(Object(Closure), Array, Array)
#29 /Users/user/Documents/workspace/project-name/vendor/illuminate/collections/Collection.php(777): Illuminate\Support\Arr::map(Array, Object(Closure))
#30 /Users/user/Documents/workspace/project-name/vendor/craftcms/ckeditor/src/data/FieldData.php(175): Illuminate\Support\Collection->map(Object(Closure))
#31 /Users/user/Documents/workspace/project-name/vendor/craftcms/ckeditor/src/data/FieldData.php(49): craft\ckeditor\data\FieldData->render()
#32 [internal function]: craft\ckeditor\data\FieldData->__toString()
#33 /Users/user/Documents/workspace/project-name/vendor/twig/twig/src/Extension/CoreExtension.php(1175): strip_tags(Object(craft\ckeditor\data\FieldData), NULL)
#34 /Users/user/Documents/workspace/project-name/storage/runtime/compiled_templates/44/44d436787c4005f7838d411241f81c4a.php(38): twig_striptags(Object(craft\ckeditor\data\FieldData))
#35 /Users/user/Documents/workspace/project-name/vendor/twig/twig/src/Template.php(394): __TwigTemplate_0e2889f8bb2ebc0c7e3db1851f091f3b->doDisplay(Array, Array)
#36 /Users/user/Documents/workspace/project-name/vendor/twig/twig/src/Template.php(367): Twig\Template->displayWithErrorHandling(Array, Array)
#37 /Users/user/Documents/workspace/project-name/vendor/twig/twig/src/Template.php(379): Twig\Template->display(Array)
#38 /Users/user/Documents/workspace/project-name/vendor/twig/twig/src/TemplateWrapper.php(38): Twig\Template->render(Array)
#39 /Users/user/Documents/workspace/project-name/vendor/craftcms/cms/src/web/View.php(671): Twig\TemplateWrapper->render(Array)
#40 /Users/user/Documents/workspace/project-name/vendor/craftcms/cms/src/elements/Entry.php(2162): craft\web\View->renderObjectTemplate('{{ (_variables....', Object(craft\elements\Entry))
#41 /Users/user/Documents/workspace/project-name/vendor/craftcms/cms/src/elements/Entry.php(2287): craft\elements\Entry->updateTitle()
#42 /Users/user/Documents/workspace/project-name/vendor/craftcms/cms/src/services/Elements.php(3438): craft\elements\Entry->beforeSave(false)
#43 /Users/user/Documents/workspace/project-name/vendor/craftcms/cms/src/services/Elements.php(1251): craft\services\Elements->_saveElementInternal(Object(craft\elements\Entry), true, true, NULL, NULL, false, true, true)
#44 /Users/user/Documents/workspace/project-name/vendor/craftcms/cms/src/controllers/ElementsController.php(1246): craft\services\Elements->saveElement(Object(craft\elements\Entry), true, true, NULL, false, true)
#45 [internal function]: craft\controllers\ElementsController->actionSave()
#46 /Users/user/Documents/workspace/project-name/vendor/yiisoft/yii2/base/InlineAction.php(57): call_user_func_array(Array, Array)
#47 /Users/user/Documents/workspace/project-name/vendor/yiisoft/yii2/base/Controller.php(178): yii\base\InlineAction->runWithParams(Array)
#48 /Users/user/Documents/workspace/project-name/vendor/yiisoft/yii2/base/Module.php(552): yii\base\Controller->runAction('save', Array)
#49 /Users/user/Documents/workspace/project-name/vendor/craftcms/cms/src/web/Application.php(349): yii\base\Module->runAction('elements/save', Array)
#50 /Users/user/Documents/workspace/project-name/vendor/craftcms/cms/src/web/Application.php(650): craft\web\Application->runAction('elements/save', Array)
#51 /Users/user/Documents/workspace/project-name/vendor/craftcms/cms/src/web/Application.php(311): craft\web\Application->_processActionRequest(Object(craft\web\Request))
#52 /Users/user/Documents/workspace/project-name/vendor/yiisoft/yii2/base/Application.php(384): craft\web\Application->handleRequest(Object(craft\web\Request))
#53 /Users/user/Documents/workspace/project-name/web/index.php(17): yii\base\Application->run()
#54 /Users/user/.composer/vendor/laravel/valet/server.php(110): require('/Users/user...')
#55 {main}
mmikkel commented 2 weeks ago

Ran into something similar. In my case the issue was that I was conditionally bootstrapping my custom Twig extension for site requests only, i.e.

if (Craft::$app->getRequest()->getIsSiteRequest()) {
    Craft::$app->getView()->registerTwigExtension(new CustomTwigExtension());
}

Removing that condition (making sure that the custom Twig extension is registered for any and all requests) fixed the issue on my end.

i-just commented 2 weeks ago

Thanks, @mmikkel - that’s a very good point.

@thomascoppein - based on the stack trace, I can see that you’re using an Entry Type with an auto-generated title. To be clear, do you get this error when saving the nested entry? What’s the “Title Format” that entry?

thomascoppein commented 2 weeks ago

@i-just - yes, that's correct. The error persists even after updating the title to static text. The error now occurs differently; it is now present in the entry card. See screenshot below.

The title of this entry type is 'Button'. Previously: {buttonLabel} | {buttonEntry.one().url|default('')}{buttonAsset.url|default('')}{buttonUrl|default('')}

Screenshot 2024-06-14 at 13 20 34

Update: by changing the code as @mmikkel suggested, this error is resolved. However, a new error has appeared. I am using the nocache plugin, and now this behavior is 'unexpected'.

Screenshot 2024-06-14 at 13 27 57

brandonkelly commented 2 weeks ago

@thomascoppein Based on your stack trace, this is happening for an entry type whose title format begins with {{ (_variables.. Can you post the full title format?

thomascoppein commented 2 weeks ago

@brandonkelly yes sure: {buttonLabel} | {buttonEntry.one().url|default('')}{buttonAsset.url|default('')}{buttonUrl|default('')}.

mmikkel commented 1 week ago

However, a new error has appeared. I am using the nocache plugin, and now this behavior is 'unexpected'

Looks like basically the same thing; the Nocache plugin only registers its Twig extension for site requests: https://github.com/ttempleton/craft-nocache/blob/52e99ca49d1e6fcc12e4f92d0b8c24ca4ae5b641/src/Plugin.php#L41

I.e., something is causing your nested CKEditor entries to render their partial templates when you save the entry. Presumably you use the {% nocache %} tag somewhere in those templates, hence that exception as that tag does not actually exist due to the rendering happening outside of a site request.

In my case it was search index jobs failing, which made sense to me as I assume Craft is rendering CKEditor content for fields that are indexable. Not sure what's going on in your case though, and I'm also pretty sure this behaviour wasn't occurring prior to CKEditor 4.1.

thomascoppein commented 1 week ago

@mmikkel Yes, that's correct. This issue did not exist prior to CKEditor 4.1. Do you need more information @brandonkelly ?