Extend User Model, adding a trait

Hi,

I’m looking to extend and add a trait (Revisionable) to \RainLab\User\Models\User;

I tried this in my boot() method :

\RainLab\User\Models\User::extend(function($model) {

      $model->morphMany['revision_history'] = [
          \System\Models\Revision::class, 'name' => 'revisionable'
      ];

      $model->revisionable = [
          'name',
          'surname'
      ];

      $model->implement[] = '\October\Rain\Database\Traits\Revisionable';

});

But this is giving an error :

Cannot instantiate trait October\Rain\Database\Traits\Revisionable

How can we extend a plugin and add any trait to it ?

Thank you.

Tried this GitHub - CptMeatball/notifiable-user: Adds the Notifiable trait as a behavior to the user model

<?php namespace Larnet\Osm\Behaviors;

use \October\Rain\Database\Traits\Revisionable as RevisionableTrait;

class Revisionable extends \October\Rain\Database\ModelBehavior
{
    use RevisionableTrait;

    public function __call($name, $params = null)
    {
        if (!method_exists($this, $name) || !is_callable($this, $name)) {
            return call_user_func_array([$this->model, $name], $params);
        }
    }
}

I added this to my boot function :

\RainLab\User\Models\User::extend(function ($model) {
  $model->morphMany['revision_history'] = [
                  \System\Models\Revision::class, 'name' => 'revisionable'
              ];
  
  $model->revisionable = ['name', 'surname', 'email'];
  
  $model->implement[] = 'Larnet.Osm.Behaviors.Revisionable';
});

but it’s not working.

Hi @apinard

You’re close.

We don’t support this because maintaining it is extremely difficult. You can write your own implementation; you should do it to make things predictable and the code robust.

Don’t be afraid to duplicate code and ship it with your plugin to gain the flexibility benefits. Something like this:

<?php namespace Acme\MyPlugin\Behaviors;

use System\Classes\ModelBehavior;

/**
 * RevisionableModel implementation of \October\Rain\Database\Traits\Revisionable
 *
 * Usage:
 *
 * In the model class definition:
 *
 *   public $implement = [\Acme\MyPlugin\Behaviors\RevisionableModel::class];
 *
 */
class RevisionableModel extends ModelBehavior
{
    use \October\Rain\Database\Traits\Revisionable;

    /**
     * __construct the behavior
     */
    public function __construct($model)
    {
        parent::__construct($model);

        if (!is_array($this->model->revisionable)) {
            throw new Exception(sprintf(
                'The $revisionable property in %s must be an array to use the Revisionable behavior.',
                get_class($this->model)
            ));
        }

        $this->model->bindEvent('model.afterUpdate', function () {
            $this->revisionableAfterUpdate();
        });

        $this->model->bindEvent('model.afterDelete', function () {
            $this->revisionableAfterDelete();
        });
    }

    /**
     * revisionableAfterUpdate event
     */
    public function revisionableAfterUpdate()
    {
        // every time $this is mentioned, use $this->model
    }
}
1 Like