Set updated_at field when fileupload or entries field changes

Hello.
I’m using version 3.6.30. Tailor blueprints created to define several content types.
What I want to accomplish is to set the “updated_at” field of any content type to the current date/time, whenever a ‘fileupload’ or ‘entries’ field is dirty (modified on the backend form). Currently, if I change an uploaded file or an entry selection only, the parent record keeps its current value of “updated_at”, despite the fact that related records did change.

My current approach to accomplish this goal is to use the ‘boot’ method of a custom plugin, like this (not working):

public function boot()
{

// Extend the blueprint for your content types
        Event::listen('tailor.extendBlueprint', function (Blueprint $blueprint) {
            \Log::info('Current Handle is: '. $blueprint->handle);
            if ($blueprint->handle == 'Content\\Video') { // Adjust the handle for your content type
                \Log::info('Handle Video matches');
                // Listen for the form saving event
                $blueprint->extendModel(function($model) {
                    $model->bindEvent('model.save', function() use ($model) {
                        // Check if specific fields like fileupload or entries are dirty
                        if ($model->isDirty('hero_image') || $model->isDirty('authors')) {
                            // Manually update the updated_at field
                            $model->updated_at = now();
                            \Log::info('updated_at field was set to current date/time for video record');
                        }
                    });
                });
            }
        });

}

Thanks in advance for your suggestions.

Hi @jeraso,

I hope you’re doing well.

Here’s a guide on how to extend your Tailor model in OctoberCMS:

Extending Model Constructors

1 Like

After reviewing the documentation about model extension, I came up with this new approach. However, I have trouble comparing the old and new values of the fields. After testing the following code, the old and new values are always the same (the old ones). So, the update is executed all the time.

public function boot()
    {
// Extend the EntryRecord model for the 'Content\\Video' section
        EntryRecord::extendInSection('Content\\Video', function($model) {
            // Property to store old values before saving
            $model->addDynamicProperty('originalRelations', []);

            // Listen for the beforeSave event to capture old values
            $model->bindEvent('model.beforeSave', function () use ($model) {
                // Reload the hero_image relationship (single file)
                $model->reloadRelations('hero_image', 'authors');

                // Store the original value for hero_image (single file)
                $model->originalRelations['hero_image'] = $model->hero_image
                    ? $model->hero_image->only(['disk_name', 'file_name', 'file_size'])
                    : null;

                // Store the original values for authors (multiple entries)
                $model->originalRelations['authors'] = $model->authors->map(function ($author) {
                    return $author->only(['id', 'title']); // Extract relevant properties of authors
                })->toArray();

                // Log the original values
                Log::info('Original hero_image:', $model->originalRelations['hero_image']);
                Log::info('Original authors:', $model->originalRelations['authors']);
            });

            // Listen for the afterSave event to compare new and old values
            $model->bindEvent('model.afterSave', function () use ($model) {
                // Reload the relationships after save
                $model->reloadRelations('hero_image', 'authors');
                
                // Get the new value for hero_image (single file)
                $newHeroImage = $model->hero_image
                    ? $model->hero_image->only(['disk_name', 'file_name', 'file_size'])
                    : null;

                // Get the new values for authors (multiple entries)
                $newAuthors = $model->authors->map(function ($author) {
                    return $author->only(['id', 'title']);
                })->toArray();

                // Log the new values
                Log::info('New hero_image:', $newHeroImage);
                Log::info('New authors:', $newAuthors);

                // Compare the old and new values (from the beforeSave event)
                $originalHeroImage = $model->originalRelations['hero_image'];
                $originalAuthors = $model->originalRelations['authors'];

                // If there's a difference, update the updated_at field
                if ($originalHeroImage !== $newHeroImage || $originalAuthors !== $newAuthors) {
                    // Manually update the updated_at field
                    DB::table($model->getTable())
                        ->where('id', $model->id)
                        ->update(['updated_at' => now()]);

                    Log::info('updated_at field was set to current date/time for this video content type record.');
                }
            });
        });
}

Can you suggest some solution? Or maybe I’m overcomplicating things and there is an easier way?

Thanks in advance.