%PDF- %PDF-
| Direktori : /home/vacivi36/intranet.vacivitta.com.br/protected/humhub/modules/comment/models/ |
| Current File : /home/vacivi36/intranet.vacivitta.com.br/protected/humhub/modules/comment/models/Comment.php |
<?php
/**
* @link https://www.humhub.org/
* @copyright Copyright (c) 2018 HumHub GmbH & Co. KG
* @license https://www.humhub.com/licences
*/
namespace humhub\modules\comment\models;
use humhub\components\behaviors\PolymorphicRelation;
use humhub\modules\comment\activities\NewComment;
use humhub\modules\comment\live\NewComment as NewCommentLive;
use humhub\modules\comment\Module;
use humhub\modules\comment\notifications\NewComment as NewCommentNotification;
use humhub\modules\content\components\ContentActiveRecord;
use humhub\modules\content\components\ContentAddonActiveRecord;
use humhub\modules\content\interfaces\ContentOwner;
use humhub\modules\content\widgets\richtext\RichText;
use humhub\modules\search\libs\SearchHelper;
use humhub\modules\space\models\Space;
use humhub\modules\user\models\User;
use Yii;
use yii\base\Exception;
use yii\db\ActiveRecord;
use yii\helpers\Url;
/**
* This is the model class for table "comment".
*
* @property integer $id
* @property string $message
* @property integer $object_id
* @property string $object_model
* @property string $created_at
* @property integer $created_by
* @property string $updated_at
* @property integer $updated_by
* @property-read string $url @since 1.10.2
*
* @since 0.5
*/
class Comment extends ContentAddonActiveRecord implements ContentOwner
{
const CACHE_KEY_COUNT = 'commentCount_%s_%s';
const CACHE_KEY_LIMITED = 'commentsLimited_%s_%s';
/**
* @inheritdoc
*/
public static function tableName()
{
return 'comment';
}
/**
* @return array validation rules for model attributes.
*/
public function rules()
{
return [
[['message'], 'safe'],
];
}
/**
* @inheritdoc
*/
public function behaviors()
{
return [
[
'class' => PolymorphicRelation::class,
'mustBeInstanceOf' => [
ActiveRecord::class,
]
]
];
}
/**
* @inheritdoc
*/
public function beforeDelete()
{
$this->flushCache();
// Delete sub comment (replies)
if ($this->object_model !== static::class) {
foreach (static::findAll(['object_model' => static::class, 'object_id' => $this->id]) as $comment) {
$comment->delete();
}
}
return parent::beforeDelete();
}
/**
* @inheritdoc
*/
public function afterDelete()
{
try {
$this->updateContentSearch();
} catch (Exception $ex) {
Yii::error($ex);
}
parent::afterDelete();
}
/**
* Flush comments cache
*/
public function flushCache()
{
static::flushCommentCache($this->object_model, $this->object_id);
}
public static function flushCommentCache($model, $id)
{
Yii::$app->cache->delete(sprintf(static::CACHE_KEY_COUNT, $model, $id));
Yii::$app->cache->delete(sprintf(static::CACHE_KEY_LIMITED, $model, $id));
}
/**
* After Saving of comments, fire an activity
*
* @param bool $insert
* @param array $changedAttributes
* @return bool
* @throws Exception
*/
public function afterSave($insert, $changedAttributes)
{
$this->flushCache();
if ($insert) {
NewComment::instance()->about($this)->create();
}
// Handle mentioned users
// Execute before NewCommentNotification to avoid double notification when mentioned.
$processResult = RichText::postProcess($this->message, $this, 'message');
$mentionedUsers = (isset($processResult['mentioning'])) ? $processResult['mentioning'] : [];
if ($insert) {
$followerQuery = $this->getCommentedRecord()->getFollowersWithNotificationQuery();
// Remove mentioned users from followers query to avoid double notification
if (count($mentionedUsers) !== 0) {
$followerQuery->andWhere(['NOT IN', 'user.id', array_map(function (User $user) {
return $user->id;
}, $mentionedUsers)]);
}
// Update updated_at etc..
$this->refresh();
NewCommentNotification::instance()->from($this->user)->about($this)->sendBulk($followerQuery);
if ($this->content->container) {
Yii::$app->live->send(new NewCommentLive([
'contentContainerId' => $this->content->container->id,
'visibility' => $this->content->visibility,
'contentId' => $this->content->id,
'commentId' => $this->id
]));
}
}
$this->updateContentSearch();
parent::afterSave($insert, $changedAttributes);
}
/**
* Force search update of underlying content object.
* (This has also indexed the comments.)
*/
protected function updateContentSearch()
{
/** @var ContentActiveRecord $content */
$contentRecord = $this->getCommentedRecord();
if ($contentRecord !== null) {
SearchHelper::queueUpdate($contentRecord);
}
}
/**
* Returns the commented record e.g. a Post
*
* @return \humhub\modules\content\components\ContentActiveRecord
*/
public function getCommentedRecord()
{
return $this->content->getPolymorphicRelation();
}
/**
* Returns a limited amount of comments
*
* @param string $model
* @param int $id
* @param int|null $limit when null the default limit will used
* @param int|null $currentCommentId ID of the current Comment which should be visible on the limited result
*
* @return Comment[] the comments
*/
public static function GetCommentsLimited($model, $id, $limit = null, $currentCommentId = null)
{
if ($limit === null) {
/** @var Module $module */
$module = Yii::$app->getModule('comment');
$limit = $module->commentsPreviewMax;
}
$currentCommentId = intval($currentCommentId);
$useCaching = empty($currentCommentId);// No need to cache comments for deep single comment view
$cacheID = sprintf(static::CACHE_KEY_LIMITED, $model, $id);
$comments = $useCaching ? Yii::$app->cache->get($cacheID) : [];
if (!is_array($comments)) {
$comments = [];
}
if (!isset($comments[$limit]) || !is_array($comments[$limit])) {
$objectCondition = ['object_model' => $model, 'object_id' => $id];
$query = Comment::find();
if ($currentCommentId && Comment::findOne(['id' => $currentCommentId])) {
$nearCommentIds = Comment::find()
->select('id')
->where($objectCondition)
->andWhere(['<=', 'id', $currentCommentId])
->orderBy('created_at DESC')
->limit($limit)
->column();
if (count($nearCommentIds) < $limit) {
$newerCommentIds = Comment::find()
->select('id')
->where($objectCondition)
->andWhere(['>', 'id', $currentCommentId])
->orderBy('created_at ASC')
->limit($limit - count($nearCommentIds))
->column();
$nearCommentIds = array_merge($nearCommentIds, $newerCommentIds);
}
$query->where(['IN', 'id', $nearCommentIds]);
} else {
$query->where($objectCondition);
$query->limit($limit);
}
$query->orderBy('created_at DESC, id dESC');
$comments[$limit] = array_reverse($query->all());
if ($useCaching) {
Yii::$app->cache->set($cacheID, $comments, Yii::$app->settings->get('cache.expireTime'));
}
}
return $comments[$limit];
}
/**
* Count number comments for this target object
*
* @param $model
* @param $id
*
* @return int|mixed|string
*/
public static function GetCommentCount($model, $id)
{
$cacheID = sprintf(static::CACHE_KEY_COUNT, $model, $id);
$commentCount = Yii::$app->cache->get($cacheID);
if ($commentCount === false) {
$commentCount = Comment::find()->where(['object_model' => $model, 'object_id' => $id])->count();
Yii::$app->cache->set($cacheID, $commentCount, Yii::$app->settings->get('cache.expireTime'));
}
return $commentCount;
}
/**
* @inheritdoc
*/
public function getContentName()
{
return Yii::t('CommentModule.base', 'comment');
}
/**
* @inheritdoc
*/
public function getContentDescription()
{
return $this->message;
}
public function canDelete($userId = '')
{
if ($userId == '') {
$userId = Yii::$app->user->id;
}
if ($this->created_by == $userId) {
return true;
}
if (Yii::$app->user->isAdmin()) {
return true;
}
if ($this->content->container instanceof Space && $this->content->container->isAdmin($userId)) {
return true;
}
return false;
}
/**
* TODO: Unify with Content::isUpdated() see https://github.com/humhub/humhub/pull/4380
* @returns boolean true if this comment has been updated, otherwise false
* @since 1.7
*/
public function isUpdated()
{
return $this->created_at !== $this->updated_at && !empty($this->updated_at) && is_string($this->updated_at);
}
/**
* Checks if given content object is a subcomment
*
* @param $object
* @return bool
* @since 1.8
*/
public static function isSubComment($object)
{
return $object instanceof Comment && $object->object_model === Comment::class;
}
/**
* Get comment permalink URL
*
* @param bool|string $scheme the URI scheme to use in the generated URL
* @return string
* @since 1.10.2
*/
public function getUrl($scheme = true): string
{
if ($this->isNewRecord) {
return $this->content->getUrl();
}
return Url::to(['/comment/perma', 'id' => $this->id], $scheme);
}
}