craftcms / redactor

Edit rich text content in Craft CMS using Redactor by Imperavi.
https://plugins.craftcms.com/redactor
MIT License
100 stars 48 forks source link

Error when saving Redactor fields with empty links #358

Closed tomkiss closed 2 years ago

tomkiss commented 2 years ago

Description

Got a weird bug I'm seeing when saving entries sometimes.

It's very sporadic and I can't seem to repro on a blank project. Seems to appear when changing the contents of a Redactor field. It's occurring when links are in Redactor fields. Craft and all plugins are up to date.

Assuming I might need to send over a copy of the DB or something.

Additional info

Error:

TypeError: Argument 1 passed to Stringy\Stringy::startsWith() must be of the type string, null given, called in /example.com/vendor/craftcms/cms/src/helpers/StringHelper.php on line 1386 and defined in /example.com/vendor/voku/stringy/src/Stringy.php:4015
Stack trace:
#0 /example.com/vendor/craftcms/cms/src/helpers/StringHelper.php(1386): Stringy\Stringy->startsWith(NULL, true)
#1 /example.com/vendor/craftcms/redactor/src/Field.php(693): craft\helpers\StringHelper::startsWith('https://storybo...', NULL)
#2 [internal function]: craft\redactor\Field->craft\redactor\{closure}(Array)
#3 /example.com/vendor/craftcms/redactor/src/Field.php(685): preg_replace_callback('/(href=|src=)([...', Object(Closure), '<p>The site use...')
#4 /example.com/vendor/craftcms/cms/src/base/Element.php(2134): craft\redactor\Field->serializeValue('<p>The site use...', Object(craft\elements\MatrixBlock))
#5 /example.com/vendor/yiisoft/yii2/validators/InlineValidator.php(84): craft\base\Element->validateCustomFieldContentSize('caption', NULL, Object(yii\validators\InlineValidator), Object(craft\redactor\FieldData))
#6 /example.com/vendor/yiisoft/yii2/validators/Validator.php(261): yii\validators\InlineValidator->validateAttribute(Object(craft\elements\MatrixBlock), 'caption')
#7 /example.com/vendor/yiisoft/yii2/base/Model.php(367): yii\validators\Validator->validateAttributes(Object(craft\elements\MatrixBlock), Array)
#8 /example.com/vendor/craftcms/cms/src/fields/Matrix.php(799): yii\base\Model->validate()
#9 /example.com/vendor/craftcms/cms/src/base/Element.php(2107): craft\fields\Matrix->validateBlocks(Object(craft\elements\Entry), NULL)
#10 /example.com/vendor/yiisoft/yii2/validators/InlineValidator.php(84): craft\base\Element->validateCustomFieldAttribute('field:workArtic...', Array, Object(yii\validators\InlineValidator), Object(craft\elements\db\MatrixBlockQuery))
#11 /example.com/vendor/yiisoft/yii2/validators/Validator.php(261): yii\validators\InlineValidator->validateAttribute(Object(craft\elements\Entry), 'field:workArtic...')
#12 /example.com/vendor/yiisoft/yii2/base/Model.php(367): yii\validators\Validator->validateAttributes(Object(craft\elements\Entry), Array)
#13 /example.com/vendor/craftcms/cms/src/services/Elements.php(2536): yii\base\Model->validate()
#14 /example.com/vendor/craftcms/cms/src/services/Elements.php(784): craft\services\Elements->_saveElementInternal(Object(craft\elements\Entry), true, false, NULL)
#15 /example.com/vendor/craftcms/cms/src/controllers/EntriesController.php(403): craft\services\Elements->saveElement(Object(craft\elements\Entry))
#16 [internal function]: craft\controllers\EntriesController->actionSaveEntry(false)
#17 /example.com/vendor/yiisoft/yii2/base/InlineAction.php(57): call_user_func_array(Array, Array)
#18 /example.com/vendor/yiisoft/yii2/base/Controller.php(178): yii\base\InlineAction->runWithParams(Array)
#19 /example.com/vendor/yiisoft/yii2/base/Module.php(552): yii\base\Controller->runAction('save-entry', Array)
#20 /example.com/vendor/craftcms/cms/src/web/Application.php(287): yii\base\Module->runAction('entries/save-en...', Array)
#21 /example.com/vendor/craftcms/cms/src/web/Application.php(596): craft\web\Application->runAction('entries/save-en...', Array)
#22 /example.com/vendor/craftcms/cms/src/web/Application.php(266): craft\web\Application->_processActionRequest(Object(craft\web\Request))
#23 /example.com/vendor/yiisoft/yii2/base/Application.php(384): craft\web\Application->handleRequest(Object(craft\web\Request))
#24 /example.com/web/index.php(22): yii\base\Application->run()
#25 {main}```

Apache/2.4.46 (Unix) mod_fastcgi/mod_fastcgi-SNAP-0910052141 PHP/7.4.16 OpenSSL/1.0.2u mod_wsgi/3.5 Python/2.7.13 Yii Framework/2.0.44```

Video of the issue failing to auto-save when a link is present:

https://user-images.githubusercontent.com/183310/152540123-2dccc4a0-ff98-404c-9e55-68aaf614e049.mp4

Redactor config:

{
  "buttons": ["html", "bold", "italic", "strikethrough", "unorderedlist", "orderedlist", "link", "sup", "sub"],
  "toolbarFixed": true
}

This happens across both Matrix fields using this Redactor config, and in standalone Redactor fields.

tomkiss commented 2 years ago

OK.

This is caused with a bad site configuration - in this instance, when the site's Base URL was not defined (once was, no idea when that got wiped!).

Anyway, rubber ducking against the internet has worked! 🐤🙌

thomasLiftov commented 2 years ago

Hi, running into the same issue at the moment. I checked my general.php config and there seems to be a base URL in place. Are you maybe talking about another base URL i'm forgetting about?

'siteUrl' => getenv('SITE_URL'),

Many thanks in advance! ✌️

tomkiss commented 2 years ago

Hi, running into the same issue at the moment. I checked my general.php config and there seems to be a base URL in place. Are you maybe talking about another base URL i'm forgetting about?

'siteUrl' => getenv('SITE_URL'),

Many thanks in advance! ✌️

This error will happen when redactor receives an empty link. Hence, you can easily recreate it with the following HTML markup in the redactor field:

<p><a href="">Link</a></p>

So if you're using Redactor to make an entry link or similar, then its likely your config is returning an empty value for the base url. Head to Settings > Sites > [Your default site] > Base URL to check its value.

The siteUrl config setting you mention has been deprecated as of Craft 3.6.

andris-sevcenko commented 2 years ago

Either way, maybe Redactor should be more defensive about this.

thomasLiftov commented 2 years ago

This indeed did the trick for me. Was working on a slightly older project and had upgraded craft without thinking about it too much. Forgot about the deprecated config setting! My bad, should be more mindful when upgrading.

Thanks a lot 😁

markodamis commented 2 years ago

I have the same issue (with empty a tags or with url) but it persists even after updating the config settings which are now set to:

'aliases' => [ '@web' => getenv('DEFAULT_SITE_URL'), ],

and in admin/settings/sites/1 the Base URL is set to @web

tomkiss commented 2 years ago

@markodamis Sanity check but what is your env var of DEFAULT_SITE_URL set to? If it's undefined, null or empty the error will still occur.

markodamis commented 2 years ago

Of course ... DEFAULT_SITE_URL="http://site.localhost" on local and DEFAULT_SITE_URL="http://www.site.come" on production. ...

tomkiss commented 2 years ago

@markodamis Hmmm, I'm not sure then - I would start by hard-coding a value in the offending link (i.e, hard-coding a value for the Base URI or Entry URI Format in the settings for the section/asset/other you're linking to in Redactor) and see where that gets you to.

markodamis commented 2 years ago

@tomkiss In the redactor field I am linking to google.com.

Mathieu-Lichtsteiner commented 2 years ago

I am experiencing the same Issue as described in the initial issue. As an addition: entrylinks and assetlinks work just fine, but links to an external page cause the posted internal server error.

markodamis commented 2 years ago

Tested if entrylinks and assetlinks work and they do. The issue is with links to external pages like Mathieu explained.

Mathieu-Lichtsteiner commented 2 years ago

FYI: With relative Links you can save, so if you want to have a hacky workaround:

  1. Use relative links like: /path_replacement
  2. a) Create a craft route with a {% redirect "external link" %} template or b) .htaccess file
brandonkelly commented 2 years ago

This has been fixed in craftcms/html-field 1.0.9 (for Craft 3) and 2.0.5 (for Craft 4). You can get the fix by running composer update.

ttl-flavio commented 2 years ago

I'm on Craft 4.2.1.1 and craftcms/html-field 2.0.5.

I'm still running into the 403 Error, whether I add a relative or external link in a redactor Field and attempt to save (the ajax call also receives the 403). If I "unlink" the text it saves successfully.

This issue happens on all of my environments except on my local instance, which has http://localhost as my base URL. My Base URL is set accordingly for each environment as an environment variable. I've tried using the env variable or typing out the actual site URL in the CP Settings but the error persisted. I can update other Fields and Matrix Blocks fine. But it must be a server setting since it works on localhost. Any guidance would be much appreciated.