vistart/yii2-models

View on GitHub
traits/MessageTrait.php

Summary

Maintainability
A
25 mins
Test Coverage
<?php

/**
 *  _   __ __ _____ _____ ___  ____  _____
 * | | / // // ___//_  _//   ||  __||_   _|
 * | |/ // /(__  )  / / / /| || |     | |
 * |___//_//____/  /_/ /_/ |_||_|     |_|
 * @link https://vistart.name/
 * @copyright Copyright (c) 2016 vistart
 * @license https://vistart.name/license/
 */

namespace vistart\Models\traits;

use yii\base\ModelEvent;
use yii\db\AfterSaveEvent;

/**
 * This trait should be used in models extended from models used BlameableTrait.
 * Notice: The models used BlameableTrait are also models used EntityTrait.
 *
 * @property $recipient
 * @version 2.0
 * @author vistart <i@vistart.name>
 */
trait MessageTrait
{
    use MutualTrait;

    public $attachmentAttribute = 'attachment';
    public $receivedAtAttribute = 'received_at';
    public $readAtAttribute = 'read_at';
    public static $eventMessageReceived = 'messageReceived';
    public static $eventMessageRead = 'messageRead';
    public $permitChangeContent = false;
    public $permitChangeReceivedAt = false;
    public $permitChangeReadAt = false;

    public function hasBeenReceived()
    {
        return is_string($this->receivedAtAttribute) ? !$this->isInitDatetime($this->getReceivedAt()) : false;
    }

    public function hasBeenRead()
    {
        return is_string($this->readAtAttribute) ? !$this->isInitDatetime($this->getReadAt()) : false;
    }

    public function touchReceived()
    {
        return $this->setReceivedAt(static::currentDatetime());
    }

    public function touchRead()
    {
        return $this->setReadAt(static::currentDatetime());
    }

    public function getReceivedAt()
    {
        if (is_string($this->receivedAtAttribute)) {
            $raAttribute = $this->receivedAtAttribute;
            return $this->$raAttribute;
        }
        return null;
    }

    public function setReceivedAt($receivedAt)
    {
        if (is_string($this->receivedAtAttribute)) {
            $raAttribute = $this->receivedAtAttribute;
            return $this->$raAttribute = $receivedAt;
        }
        return null;
    }

    public function getReadAt()
    {
        if (is_string($this->readAtAttribute)) {
            $raAttribute = $this->readAtAttribute;
            return $this->$raAttribute;
        }
        return null;
    }

    public function setReadAt($readAt)
    {
        if (is_string($this->readAtAttribute)) {
            $raAttribute = $this->readAtAttribute;
            return $this->$raAttribute = $readAt;
        }
        return null;
    }

    /**
     * @param ModelEvent $event
     */
    public function onInitReceivedAtAttribute($event)
    {
        $sender = $event->sender;
        /* @var $sender static */
        $sender->setReceivedAt(static::getInitDatetime($event));
    }

    /**
     * @param ModelEvent $event
     */
    public function onInitReadAtAttribute($event)
    {
        $sender = $event->sender;
        /* @var $sender static */
        $sender->setReadAt(static::getInitDatetime($event));
    }

    /**
     * We consider you have received the message if you read it.
     * @param ModelEvent $event
     */
    public function onReadAtChanged($event)
    {
        $sender = $event->sender;
        $raAttribute = $sender->readAtAttribute;
        if (!is_string($raAttribute)) {
            return;
        }
        $reaAttribute = $sender->receivedAtAttribute;
        if (is_string($reaAttribute) && !$sender->isInitDatetime($sender->$raAttribute) && $sender->isInitDatetime($sender->$reaAttribute)) {
            $sender->$reaAttribute = $sender->currentDatetime();
        }
        if ($sender->permitChangeReadAt) {
            return;
        }
        $oldRa = $sender->getOldAttribute($raAttribute);
        if ($oldRa != null && !$sender->isInitDatetime($oldRa) && $sender->$raAttribute != $oldRa) {
            $sender->$raAttribute = $oldRa;
            return;
        }
    }

    /**
     * You are not allowed to change receive time if you have received it.
     * @param ModelEvent $event
     */
    public function onReceivedAtChanged($event)
    {
        $sender = $event->sender;
        $raAttribute = $sender->receivedAtAttribute;
        if (!is_string($raAttribute)) {
            return;
        }
        if ($sender->permitChangeReceivedAt) {
            return;
        }
        $oldRa = $sender->getOldAttribute($raAttribute);
        if ($oldRa != null && !$sender->isInitDatetime($oldRa) && $sender->$raAttribute != $oldRa) {
            $sender->$raAttribute = $oldRa;
            return;
        }
    }

    /**
     * You are not allowed to change the content if it is not new message.
     * @param ModelEvent $event
     */
    public function onContentChanged($event)
    {
        $sender = $event->sender;
        if ($sender->permitChangeContent) {
            return;
        }
        $cAttribute = $sender->contentAttribute;
        $oldContent = $sender->getOldAttribute($cAttribute);
        if ($oldContent != $sender->$cAttribute) {
            $sender->$cAttribute = $oldContent;
        }
    }

    /**
     * Trigger message received or read events.
     * @param AfterSaveEvent $event
     */
    public function onMessageUpdated($event)
    {
        $sender = $event->sender;
        $reaAttribute = $sender->receivedAtAttribute;
        if (isset($event->changedAttributes[$reaAttribute]) && $event->changedAttributes[$reaAttribute] != $sender->$reaAttribute) {
            $sender->trigger(static::$eventMessageReceived);
        }
        $raAttribute = $sender->readAtAttribute;
        if (isset($event->changedAttributes[$raAttribute]) && $event->changedAttributes[$raAttribute] != $sender->$raAttribute) {
            $sender->trigger(static::$eventMessageRead);
        }
    }

    public function initMessageEvents()
    {
        $this->on(static::EVENT_BEFORE_INSERT, [$this, 'onInitReceivedAtAttribute']);
        $this->on(static::EVENT_BEFORE_INSERT, [$this, 'onInitReadAtAttribute']);
        $this->on(static::EVENT_BEFORE_UPDATE, [$this, 'onReceivedAtChanged']);
        $this->on(static::EVENT_BEFORE_UPDATE, [$this, 'onReadAtChanged']);
        $this->on(static::EVENT_BEFORE_UPDATE, [$this, 'onContentChanged']);
        $this->on(static::EVENT_AFTER_UPDATE, [$this, 'onMessageUpdated']);
    }

    public function getMessageRules()
    {
        $rules = [];
        $rules = array_merge($rules, $this->getMutualRules());
        if (is_string($this->attachmentAttribute)) {
            $rules[] = [$this->attachmentAttribute, 'safe'];
        }
        if (is_string($this->receivedAtAttribute)) {
            $rules[] = [$this->receivedAtAttribute, 'safe'];
        }
        if (is_string($this->readAtAttribute)) {
            $rules[] = [$this->readAtAttribute, 'safe'];
        }
        return $rules;
    }

    public function rules()
    {
        return array_merge(parent::rules(), $this->getMessageRules());
    }

    public function enabledFields()
    {
        $fields = parent::enabledFields();
        if (is_string($this->otherGuidAttribute)) {
            $fields[] = $this->otherGuidAttribute;
        }
        if (is_string($this->attachmentAttribute)) {
            $fields[] = $this->attachmentAttribute;
        }
        if (is_string($this->receivedAtAttribute)) {
            $fields[] = $this->receivedAtAttribute;
        }
        if (is_string($this->readAtAttribute)) {
            $fields[] = $this->readAtAttribute;
        }
        return $fields;
    }
}