cacheRating) { if (empty( $this->cacheModelName ) || !is_string($this->cacheModelName)) { throw new InvalidConfigException( 'To use rating cache you must set $cacheModelName where to store it' ); } $this->setCacheModel( \Yii::createObject( [ 'class' => $this->cacheModelName, ] ) ); } parent::attach($owner); } /** * Get fully-classified name of class to hold rating cache * * @return string */ public function getCacheModelName():string { return $this->cacheModelName; } /** * Set fully-classified name of class to hold rating cache * * @param string $value */ public function setCacheModelName(string $value) { $this->cacheModelName = $value; } /** * Get model to hold rating cache * * @return \artweb\artbox\comment\models\interfaces\RatingCacheInterface */ public function getCacheModel():RatingCacheInterface { return $this->cacheModel; } /** * Set model to hold cache * * @param \artweb\artbox\comment\models\interfaces\RatingCacheInterface|null $value */ private function setCacheModel(RatingCacheInterface $value = null) { $this->cacheModel = $value; } /** * Whether cache rating or not * * @return bool */ public function getCacheRating(): bool { return $this->cacheRating; } /** * Set whether to cache rating or not * * @param bool $value */ public function setCacheRating(bool $value) { $this->cacheRating = $value; } /** * Get query to get all comments for current $owner model * * @return \yii\db\ActiveQuery */ public function getComments(): ActiveQuery { /** * @var ActiveRecord $owner */ $owner = $this->owner; $pk = $owner->primaryKey()[ 0 ]; $query = $owner->hasMany(CommentModel::className(), [ 'entity_id' => $pk ]) ->where( [ 'artbox_comment.entity' => $owner::className(), 'artbox_comment.status' => CommentModel::STATUS_ACTIVE, 'artbox_comment.artbox_comment_pid' => null, ] ); return $query; } /** * Get query to get average rating for current $owner model if it cached * * @return \yii\db\ActiveQuery */ public function getAverageRating(): ActiveQuery { /** * @var ActiveRecord $owner */ $owner = $this->owner; $pk = $owner->primaryKey()[ 0 ]; $query = $owner->hasOne($this->cacheModelName, [ $this->cacheModel->getLinkAttribute() => $pk ]); return $query; } /** * Recalculate cache for current $owner model * * @return bool */ public function recalculateRating(): bool { /** * @var RatingCacheInterface $averageRating */ $average = $this->getComments() ->joinWith('rating') ->select([ 'average' => 'avg(artbox_comment_rating.value)::float' ]) ->scalar(); if (!$average) { $average = 0; } $averageRating = $this->getAverageRating() ->one(); if (!empty( $averageRating )) { $averageRating->setValue($average); } else { /** * @var ActiveRecord $owner * @var RatingCacheInterface $averageRating */ $owner = $this->owner; $pk = $owner->primaryKey()[ 0 ]; $averageRating = \Yii::createObject( [ 'class' => $this->cacheModelName, $this->cacheModel->getLinkAttribute() => $this->owner->$pk, ] ); $averageRating->setValue($average); } if ($averageRating->save()) { return true; } else { return false; } } }