CommentModel.php 12.2 KB
<?php
    
    namespace artbox\webcomment\models;
    
    use artbox\webcomment\behaviors\ParentBehavior;
    use artbox\webcomment\models\interfaces\CommentInterface;
    use yii\behaviors\AttributeBehavior;
    use yii\behaviors\BlameableBehavior;
    use yii\behaviors\TimestampBehavior;
    use yii\data\ActiveDataProvider;
    use yii\db\ActiveRecord;
    
    /**
     * Class CommentModel
     *
     * @property int                                      $id
     * @property string                                   $text
     * @property int                                      $customer_id
     * @property string                                   $username
     * @property string                                   $email
     * @property int                                      $created_at
     * @property int                                      $updated_at
     * @property int                                      $deleted_at
     * @property int                                      $status
     * @property int                                      $parent_id
     * @property int                                      $related_id
     * @property string                                   $ip
     * @property string                                   $info
     * @property string                                   $entity
     * @property int                                      $entity_id
     * @property ActiveRecord                             $entityModel
     * @property string                                   $link
     * @property \artbox\webcomment\models\CommentModel[] $children
     * @property \artbox\order\models\Customer            $customer
     */
    class CommentModel extends ActiveRecord implements CommentInterface
    {
        
        const STATUS_ACTIVE = 1;
        const STATUS_HIDDEN = 0;
        const STATUS_DELETED = 2;
        
        const SCENARIO_USER = 'user';
        const SCENARIO_GUEST = 'guest';
        const SCENARIO_ADMIN = 'admin';
        const SCENARIO_ADMIN_ANSWER = 'admin';
        
        public $encryptedEntity;
        
        public $entityId;
    
        /**
         * @inheritdoc
         */
        public function scenarios()
        {
            $scenarios = parent::scenarios();
            $scenarios[ self::SCENARIO_USER ] = [
                'text',
                'entity',
                'entity_id',
                'parent_id',
                'status',
            ];
            $scenarios[ self::SCENARIO_GUEST ] = [
                'text',
                'entity',
                'entity_id',
                'username',
                'email',
                'status',
            ];
            $scenarios[ self::SCENARIO_ADMIN ] = [
                'text',
                'status',
            ];
            $scenarios[ self::SCENARIO_ADMIN_ANSWER ] = [
                'text',
                'parent_id',
                'customer_id',
                'entity',
                'entity_id',
                'status',
            ];
            return $scenarios;
        }
    
        /**
         * @inheritdoc
         */
        public static function tableName()
        {
            return '{{%artbox_comment}}';
        }
    
        /**
         * @inheritdoc
         */
        public function rules()
        {
            return [
                [
                    [
                        'text',
                        'entity',
                        'entity_id',
                        'username',
                        'email',
                    ],
                    'required',
                ],
                [
                    [
                        'text',
                        'entity',
                        'username',
                    ],
                    'string',
                ],
                [
                    [
                        'email',
                    ],
                    'email',
                ],
                [
                    [
                        'entity_id',
                        'parent_id',
                    ],
                    'integer',
                ],
                [
                    [ 'status' ],
                    'default',
                    'value' => 0,
                ],
                [
                    [ 'parent_id' ],
                    'exist',
                    'targetAttribute' => 'id',
                    'skipOnError'     => true,
                ],
            ];
        }
    
        /**
         * @inheritdoc
         */
        public function behaviors()
        {
            return [
                [
                    'class' => TimestampBehavior::className(),
                ],
                [
                    'class'              => BlameableBehavior::className(),
                    'createdByAttribute' => 'customer_id',
                    'updatedByAttribute' => false,
                ],
                [
                    'class'      => AttributeBehavior::className(),
                    'attributes' => [
                        ActiveRecord::EVENT_BEFORE_INSERT => 'ip',
                    ],
                    'value'      => function () {
                        return \Yii::$app->request->userIP;
                    },
                ],
                [
                    'class' => ParentBehavior::className(),
                ],
            ];
        }
    
        /**
         * @inheritdoc
         */
        public function attributeLabels()
        {
            return [
                'id'          => \Yii::t('artbox-comment', 'ID'),
                'text'        => \Yii::t('artbox-comment', 'Text'),
                'customer_id' => \Yii::t('artbox-comment', 'User'),
                'username'    => \Yii::t('artbox-comment', 'Username'),
                'email'       => 'Email',
                'created_at'  => \Yii::t('artbox-comment', 'Date add'),
                'updated_at'  => \Yii::t('artbox-comment', 'Date update'),
                'deleted_at'  => \Yii::t('artbox-comment', 'Date delete'),
                'status'      => \Yii::t('artbox-comment', 'Status'),
                'parent_id'   => \Yii::t('artbox-comment', 'Comment parent'),
                'related_id'  => \Yii::t('artbox-comment', 'Comment related'),
                'ip'          => 'IP',
                'entity'      => \Yii::t('artbox-comment', 'Entity'),
                'info'        => \Yii::t('artbox-comment', 'Info'),
                'entity_id'   => \Yii::t('artbox-comment', 'Entity ID'),
            ];
        }
    
        /**
         * Set Entity of Comment model
         *
         * @param string $entity
         */
        public function setEntity(string $entity)
        {
            $this->entity = $entity;
        }
    
        /**
         * Get Entity of Comment model
         *
         * @return string
         */
        public function getEntity(): string
        {
            return $this->entity;
        }
    
        /**
         * Get ActiveDataProvider of comments for particular Entity according to its EntityId
         *
         * @param string $entity   Entity name
         * @param int    $entityId Entity Id
         *
         * @return \yii\data\ActiveDataProvider
         */
        public static function getTree(string $entity, int $entityId): ActiveDataProvider
        {
            $query = self::find()
                         ->with(
                             [
                                 'children' => function ($query) {
                                     /**
                                      * @var \yii\db\ActiveQuery $query
                                      */
                                     if (class_exists(self::getCustomerClass())) {
                                         $query->with('customer');
                                     }
                                 },
                             ]
                         )
                         ->where(
                             [
                                 'entity'    => $entity,
                                 'entity_id' => $entityId,
                                 'status'    => self::STATUS_ACTIVE,
                                 'parent_id' => null,
                             ]
                         );
            if (class_exists(self::getCustomerClass())) {
                $query->with('customer');
            }
            return new ActiveDataProvider(
                [
                    'query'      => $query,
                    'pagination' => [
                        'pageSize' => 20,
                    ],
                    'sort'       => [
                        'defaultOrder' => [
                            'created_at' => SORT_DESC,
                        ],
                    ],
                ]
            );
        }
    
        /**
         * Delete comment
         *
         * @return bool
         */
        public function deleteComment(): bool
        {
            if (!\Yii::$app->user->isGuest && \Yii::$app->user->id == $this->customer_id) {
                if ($this->delete()) {
                    return true;
                }
            }
            return false;
        }
    
        /**
         * Set EntityId of Comment model
         *
         * @param int $entityId
         */
        public function setEntityId(int $entityId)
        {
            $this->entityId = $entityId;
        }
    
        /**
         * Get EntityId of Comment model
         *
         * @return int
         */
        public function getEntityId(): int
        {
            return $this->entityId;
        }
    
        /**
         * Get children relation for current comment
         *
         * @return \yii\db\ActiveQuery
         */
        public function getChildren()
        {
            return $this->hasMany(self::className(), [ 'parent_id' => 'id' ])
                        ->andFilterWhere([ 'status' => self::STATUS_ACTIVE ])
                        ->inverseOf('parent');
        }
    
        /**
         * Get parent relation for current comment
         *
         * @return \yii\db\ActiveQuery
         */
        public function getParent()
        {
            return $this->hasOne(self::className(), [ 'id' => 'parent_id' ])
                        ->inverseOf('children');
        }
    
        /**
         * Get customer relation for current comment
         *
         * @return \yii\db\ActiveQuery
         */
        public function getCustomer()
        {
            return $this->hasOne(self::getCustomerClass(), [ 'id' => 'customer_id' ]);
        }
    
        /**
         * Get rating relation for current model
         *
         * @return \yii\db\ActiveQuery
         */
        public function getRating()
        {
            return $this->hasOne(RatingModel::className(), [ 'model_id' => 'id' ])
                        ->andWhere(
                            [
                                'or',
                                [ 'artbox_comment_rating.model' => null ],
                                [ 'artbox_comment_rating.model' => self::className() ],
                            ]
                        );
        }
    
        /**
         * Get entity model for current comment or false if not ActiveRecord
         *
         * @return ActiveRecord|false
         */
        public function getEntityModel()
        {
            if (method_exists($this->entity, 'findOne')) {
                $model = call_user_func_array(
                    [
                        $this->entity,
                        'findOne',
                    ],
                    [ $this->entity_id ]
                );
                return $model;
            } else {
                return false;
            }
        }
    
        /**
         * Get Customer model name
         *
         * @return string
         */
        protected static function getCustomerClass()
        {
            /**
             * @var \artbox\webcomment\Module $module
             */
            $module = \Yii::$app->getModule('artbox-comment');
            if ($module) {
                return $module->userIdentityClass;
            } else {
                return 'artbox\order\models\Customer';
            }
        }
    }