Skip to content

Instantly share code, notes, and snippets.

@timkelty
Created August 10, 2024 20:14
Show Gist options
  • Save timkelty/1cfb09a9611587552ed0f81ab99b1af7 to your computer and use it in GitHub Desktop.
Save timkelty/1cfb09a9611587552ed0f81ab99b1af7 to your computer and use it in GitHub Desktop.
Craft 5 afterSave element bug
<!DOCTYPE html>
<html lang="en-US">
<head>
</head>
<body>
{% macro errorList(errors) %}
{% if errors %}
{{ ul(errors, {class: 'errors'}) }}
{% endif %}
{% endmacro %}
{# Load section + entry type definitions: #}
{% set section = craft.app.entries.getSectionByHandle('blog') %}
{% set entryType = craft.app.entries.getEntryTypeByHandle('blog') %}
{# If there were any validation errors, an `entry` variable will be
passed back to the template, containing the POSTed values, as-is,
and validation errors. If that’s *not* present, we stub out a new
entry object: #}
{% set entry = entry ?? create({
class: 'craft\\elements\\Entry',
sectionId: section.id,
typeId: entryType.id,
}) %}
{# Add `enctype="multipart/form-data"` to `<form>` if you’re uploading files! #}
<form method="post" accept-charset="UTF-8">
{{ csrfInput() }}
{{ actionInput('entries/save-entry') }}
{{ redirectInput('{url}') }}
{# Output the section + entry type values so they are preserved when data is sent to Craft: #}
{{ hiddenInput('sectionId', entry.sectionId) }}
{{ hiddenInput('typeId', entry.typeId) }}
{{ hiddenInput('enabled', true) }}
<label for="title">Title</label>
{{ input('text', 'title', entry.title, {
id: 'title',
}) }}
{{ _self.errorList(entry.getErrors('title')) }}
<button type="submit">Publish</button>
</form>
</body>
</html>
<?php
namespace modules\testmodule;
use Craft;
use craft\base\Element;
use craft\base\Model;
use craft\elements\Entry;
use craft\events\DefineBehaviorsEvent;
use craft\events\ModelEvent;
use craft\helpers\ElementHelper;
use craft\helpers\UrlHelper;
use yii\base\Event;
use yii\base\Module as BaseModule;
/**
* test-module module
*
* @method static Module getInstance()
*/
class Module extends BaseModule
{
public function init(): void
{
Craft::setAlias('@modules/testmodule', __DIR__);
// Set the controllerNamespace based on whether this is a console or web request
if (Craft::$app->request->isConsoleRequest) {
$this->controllerNamespace = 'modules\\testmodule\\console\\controllers';
} else {
$this->controllerNamespace = 'modules\\testmodule\\controllers';
}
parent::init();
// Defer most setup tasks until Craft is fully initialized
Craft::$app->onInit(function() {
$this->attachEventHandlers();
// ...
});
}
private function attachEventHandlers(): void
{
Event::on(
Entry::class,
Element::EVENT_AFTER_SAVE,
function (ModelEvent $event) {
if (ElementHelper::isDraftOrRevision($event->sender)) {
return;
}
$title = "Entry #{$event->sender->id}";
if ($event->sender->title !== $title) {
$event->sender->title = $title;
// In Craft 5, this is required to avoid integrity constraint violation
// $event->sender->isNewForSite = false;
Craft::$app->getElements()->saveElement($event->sender);
}
}
);
}
}
@alexmazaltov
Copy link

Hello @timkelty, thank you for your code.
Please explain what the bug is. Is it solved with your gist?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment