Added support of sub comments

This commit is contained in:
Lucas Bartholemy 2020-06-29 22:09:24 +02:00
parent 2d88d5d3b1
commit 05892a7a95
12 changed files with 162 additions and 81 deletions

View File

@ -30,7 +30,7 @@ class Helpers
*/
public static function truncateText($text, $length)
{
$length = abs((int) $length);
$length = abs((int)$length);
if (strlen($text) > $length) {
$text = preg_replace("/^(.{1,$length})(\s.*|$)/s", '\\1...', $text);
}
@ -42,7 +42,7 @@ class Helpers
public static function trimText($text, $length)
{
$length = abs((int) $length);
$length = abs((int)$length);
$textlength = mb_strlen($text);
if ($textlength > $length) {
$text = self::substru($text, 0, $textlength - ($textlength - $length));
@ -160,10 +160,17 @@ class Helpers
}
switch (substr($valueString, -1)) {
case 'M': case 'm': return (int) $valueString * 1048576;
case 'K': case 'k': return (int) $valueString * 1024;
case 'G': case 'g': return (int) $valueString * 1073741824;
default: return (int) $valueString;
case 'M':
case 'm':
return (int)$valueString * 1048576;
case 'K':
case 'k':
return (int)$valueString * 1024;
case 'G':
case 'g':
return (int)$valueString * 1073741824;
default:
return (int)$valueString;
}
}
@ -190,12 +197,12 @@ class Helpers
if (is_array($type)) {
foreach ($type as $t) {
if (class_exists($className) && is_subclass_of($className, $t)) {
if (class_exists($className) && (is_subclass_of($className, $t) || $className === $t)) {
return true;
}
}
} else {
if (class_exists($className) && is_subclass_of($className, $type)) {
if (class_exists($className) && (is_subclass_of($className, $type) || $className === $type)) {
return true;
}
}
@ -250,8 +257,8 @@ class Helpers
*
* This is mainly required for grouped notifications.
*
* @since 1.2.1
* @param $event
* @since 1.2.1
*/
public static function SqlMode($event)
{
@ -260,7 +267,7 @@ class Helpers
try {
$event->sender->createCommand('SET SESSION sql_mode=""; SET SESSION sql_mode="NO_ENGINE_SUBSTITUTION"')->execute();
} catch (\Exception $ex) {
Yii::error('Could not switch SQL mode: '. $ex->getMessage());
Yii::error('Could not switch SQL mode: ' . $ex->getMessage());
}
}
}

View File

@ -8,10 +8,14 @@
namespace humhub\modules\comment\controllers;
use humhub\components\Controller;
use humhub\libs\Helpers;
use humhub\modules\comment\Module;
use humhub\modules\content\components\ContentActiveRecord;
use humhub\modules\content\models\Content;
use Yii;
use yii\data\Pagination;
use yii\web\HttpException;
use humhub\modules\content\components\ContentAddonController;
use humhub\components\behaviors\AccessControl;
use humhub\modules\comment\models\Comment;
use humhub\modules\comment\widgets\Comment as CommentWidget;
@ -23,9 +27,10 @@ use yii\web\ForbiddenHttpException;
* CommentController provides all comment related actions.
*
* @package humhub.modules_core.comment.controllers
* @property Module $module
* @since 0.5
*/
class CommentController extends ContentAddonController
class CommentController extends Controller
{
/**
@ -47,35 +52,68 @@ class CommentController extends ContentAddonController
];
}
/**
* @var Comment|ContentActiveRecord The model to comment
*/
public $target;
/**
* @var Content
*/
public $content;
/**
* @inheritDoc
*/
public function beforeAction($action)
{
$modelClass = Yii::$app->request->get('object_model', Yii::$app->request->post('object_model'));
$modelPk = (int)Yii::$app->request->get('object_id', Yii::$app->request->post('object_id'));
Helpers::CheckClassType($modelClass, [Comment::class, ContentActiveRecord::class]);
$this->target = $modelClass::findOne(['id' => $modelPk]);
if ($this->target === null) {
throw new HttpException(500, 'Could not find underlying content or content addon record!');
}
$this->content = $this->target->content;
if (!$this->content->canView()) {
throw new HttpException(403, 'Access denied!');
}
return parent::beforeAction($action); // TODO: Change the autogenerated stub
}
/**
* Returns a List of all Comments belong to this Model
*/
public function actionShow()
{
$content = $this->parentContent;
$query = Comment::find();
$query->orderBy('created_at DESC');
$query->where([
'object_model' => $content->className(),
'object_id' => $content->getPrimaryKey(),
]);
$query->where(['object_model' => $this->target->className(), 'object_id' => $this->target->getPrimaryKey()]);
$pagination = new Pagination([
'totalCount' => Comment::GetCommentCount($content->className(), $content->getPrimaryKey()),
'totalCount' => Comment::GetCommentCount($this->target->className(), $this->target->getPrimaryKey()),
'pageSize' => $this->module->commentsBlockLoadSize
]);
$query->offset($pagination->offset)->limit($pagination->limit);
$comments = array_reverse($query->all());
$output = ShowMore::widget(['pagination' => $pagination, 'object' => $content]);
$output = ShowMore::widget(['pagination' => $pagination, 'object' => $this->target]);
foreach ($comments as $comment) {
$output .= CommentWidget::widget(['comment' => $comment]);
}
if (Yii::$app->request->get('mode') == 'popup') {
return $this->renderAjax('showPopup', ['object' => $content, 'output' => $output, 'id' => $content->getUniqueId()]);
return $this->renderAjax('showPopup', ['object' => $this->target, 'output' => $output, 'id' => $this->content->getUniqueId()]);
} else {
return $this->renderAjaxContent($output);
}
@ -86,13 +124,10 @@ class CommentController extends ContentAddonController
*/
public function actionPost()
{
if (Yii::$app->user->isGuest || !Yii::$app->getModule('comment')->canComment($this->parentContent->content)) {
throw new ForbiddenHttpException(Yii::t('CommentModule.base',
'You are not allowed to comment.')
);
if (Yii::$app->user->isGuest || !$this->module->canComment($this->content)) {
throw new ForbiddenHttpException(Yii::t('CommentModule.base', 'You are not allowed to comment.'));
}
return Comment::getDb()->transaction(function ($db) {
$message = Yii::$app->request->post('message');
$files = Yii::$app->request->post('fileList');
@ -102,7 +137,7 @@ class CommentController extends ContentAddonController
}
$comment = new Comment(['message' => $message]);
$comment->setPolyMorphicRelation($this->parentContent);
$comment->setPolyMorphicRelation($this->target);
$comment->save();
$comment->fileManager->attach($files);
@ -131,7 +166,7 @@ class CommentController extends ContentAddonController
'comment' => $this->contentAddon,
'justEdited' => true
]));
} else if(Yii::$app->request->post()) {
} else if (Yii::$app->request->post()) {
Yii::$app->response->statusCode = 400;
}

View File

@ -37,10 +37,6 @@ use humhub\modules\user\models\User;
* @property string $updated_at
* @property integer $updated_by
*
* The followings are the available model relations:
* @property Post[] $posts
*
* @package humhub.modules_core.comment.models
* @since 0.5
*/
class Comment extends ContentAddonActiveRecord implements ContentOwner
@ -87,6 +83,13 @@ class Comment extends ContentAddonActiveRecord implements ContentOwner
{
$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();
}
@ -130,7 +133,7 @@ class Comment extends ContentAddonActiveRecord implements ContentOwner
{
$this->flushCache();
if($insert) {
if ($insert) {
NewComment::instance()->about($this)->create();
}

View File

@ -1,19 +1,22 @@
<?php
use humhub\libs\Html;
use humhub\libs\Html;
use humhub\widgets\ModalDialog;
?>
<?php \humhub\widgets\ModalDialog::begin(['header' => Yii::t('CommentModule.base', 'Comments')]) ?>
<div class="modal-body comment-container comment-modal-body" style="margin-top:0px">
<div id="userlist-content">
<div class="well well-small" id="comment_<?= $id; ?>">
<div class="comment" id="comments_area_<?= $id; ?>">
<?= $output; ?>
</div>
<?= humhub\modules\comment\widgets\Form::widget(['object' => $object]); ?>
<?php ModalDialog::begin(['header' => Yii::t('CommentModule.base', 'Comments')]) ?>
<div class="modal-body comment-container comment-modal-body" style="margin-top:0px">
<div id="userlist-content">
<div class="well well-small" id="comment_<?= $id; ?>">
<div class="comment" id="comments_area_<?= $id; ?>">
<?= $output; ?>
</div>
<?= humhub\modules\comment\widgets\Form::widget(['object' => $object]); ?>
</div>
</div>
<?php \humhub\widgets\ModalDialog::end() ?>
</div>
<?php ModalDialog::end() ?>
<script <?= Html::nonce() ?>>
// scroll to top of list

View File

@ -58,11 +58,23 @@ class CommentLink extends Widget
return '';
}
$objectModel = $this->object->content->object_model;
$objectId = $this->object->content->object_id;
if ($this->object instanceof CommentModel) {
$objectModel = CommentModel::class;
$objectId = $this->object->id;
if ($this->object->getSource() instanceof CommentModel) {
// Dont allow comments of comments
return '';
}
}
return $this->render('link', [
'id' => $this->object->getUniqueId(),
'mode' => $this->mode,
'objectModel' => $this->object->content->object_model,
'objectId' => $this->object->content->object_id,
'objectModel' => $objectModel,
'objectId' => $objectId,
]);
}

View File

@ -2,6 +2,8 @@
namespace humhub\modules\comment\widgets;
use humhub\modules\comment\models\Comment as CommentModel;
/**
* This widget is used include the comments functionality to a wall entry.
*
@ -28,8 +30,8 @@ class Comments extends \yii\base\Widget
$modelId = $this->object->content->object_id;
// Count all Comments
$commentCount = \humhub\modules\comment\models\Comment::GetCommentCount($modelName, $modelId);
$comments = \humhub\modules\comment\models\Comment::GetCommentsLimited($modelName, $modelId, 2);
$commentCount = CommentModel::GetCommentCount($modelName, $modelId);
$comments = CommentModel::GetCommentsLimited($modelName, $modelId, 2);
$isLimited = ($commentCount > 2);

View File

@ -9,6 +9,7 @@
namespace humhub\modules\comment\widgets;
use Yii;
use humhub\modules\comment\models\Comment as CommentModel;
/**
* This widget is used include the comments functionality to a wall entry.
@ -33,19 +34,23 @@ class Form extends \yii\base\Widget
{
if (Yii::$app->user->isGuest) {
return;
return '';
}
if (!Yii::$app->getModule('comment')->canComment($this->object->content)) {
return;
return '';
}
$objectModel = $this->object->content->object_model;
$objectId = $this->object->content->object_id;
if ($this->object instanceof CommentModel) {
$objectModel = CommentModel::class;
$objectId = $this->object->id;
}
$modelName = $this->object->content->object_model;
$modelId = $this->object->content->object_id;
return $this->render('form', [
'modelName' => $modelName,
'modelId' => $modelId,
'modelName' => $objectModel,
'modelId' => $objectId,
'id' => $this->object->getUniqueId(),
]);
}

View File

@ -1,12 +1,17 @@
<?php
use humhub\modules\comment\widgets\Form;
use humhub\modules\comment\widgets\Comment;
use yii\helpers\Url;
use humhub\libs\Html;
?>
<div class="well well-small comment-container" style="display:none;" id="comment_<?= $id; ?>">
<div class="comment <?php if (Yii::$app->user->isGuest): ?>guest-mode<?php endif; ?>" id="comments_area_<?= $id; ?>">
<div class="comment <?php if (Yii::$app->user->isGuest): ?>guest-mode<?php endif; ?>"
id="comments_area_<?= $id; ?>">
<?php if ($isLimited): ?>
<a href="#" class="show show-all-link" data-ui-loader data-action-click="comment.showAll" data-action-url="<?= Url::to(['/comment/comment/show', 'contentModel' => $modelName, 'contentId' => $modelId]) ?>">
<a href="#" class="show show-all-link" data-ui-loader data-action-click="comment.showAll"
data-action-url="<?= Url::to(['/comment/comment/show', 'contentModel' => $modelName, 'contentId' => $modelId]) ?>">
<?= Yii::t('CommentModule.base', 'Show all {total} comments.', ['{total}' => $total]) ?>
</a>
<hr>
@ -14,20 +19,19 @@ use humhub\libs\Html;
?>
<?php foreach ($comments as $comment) : ?>
<?= \humhub\modules\comment\widgets\Comment::widget(['comment' => $comment]); ?>
<?= Comment::widget(['comment' => $comment]); ?>
<?php endforeach; ?>
</div>
<?= \humhub\modules\comment\widgets\Form::widget(['object' => $object]); ?>
<?= Form::widget(['object' => $object]); ?>
</div>
<?php /* END: Comment Create Form */ ?>
<script <?= Html::nonce() ?>>
<?php if (count($comments) != 0) { ?>
<?php if (count($comments) != 0) { ?>
// make comments visible at this point to fixing autoresizing issue for textareas in Firefox
$('#comment_<?php echo $id; ?>').show();
<?php } ?>
<?php } ?>
</script>
</script>

View File

@ -17,8 +17,8 @@ $submitUrl = Url::to(['/comment/comment/post']);
<div id="comment_create_form_<?= $id; ?>" class="comment_create" data-ui-widget="comment.Form">
<?= Html::beginForm('#'); ?>
<?= Html::hiddenInput('contentModel', $modelName); ?>
<?= Html::hiddenInput('contentId', $modelId); ?>
<?= Html::hiddenInput('object_model', $modelName); ?>
<?= Html::hiddenInput('object_id', $modelId); ?>
<div class="comment-create-input-group">
<?= RichTextField::widget([
@ -58,4 +58,4 @@ $submitUrl = Url::to(['/comment/comment/post']);
]); ?>
<?= Html::endForm(); ?>
</div>
</div>

View File

@ -1,12 +1,13 @@
<?php
use humhub\modules\comment\widgets\CommentLink;
use humhub\widgets\Button;
use yii\helpers\Html;
use yii\helpers\Url;
$commentCount = $this->context->getCommentsCount();
$hasComments = ($commentCount > 0);
$commentCountSpan = Html::tag('span', ' ('.$commentCount.')', [
$commentCountSpan = Html::tag('span', ' (' . $commentCount . ')', [
'class' => 'comment-count',
'data-count' => $commentCount,
'style' => ($hasComments) ? null : 'display:none'
@ -14,13 +15,13 @@ $commentCountSpan = Html::tag('span', ' ('.$commentCount.')', [
?>
<?php if ($mode == \humhub\modules\comment\widgets\CommentLink::MODE_POPUP): ?>
<?php $url = Url::to(['/comment/comment/show', 'contentModel' => $objectModel, 'contentId' => $objectId, 'mode' => 'popup']); ?>
<?php if ($mode == CommentLink::MODE_POPUP): ?>
<?php $url = Url::to(['/comment/comment/show', 'object_model' => $objectModel, 'object_id' => $objectId, 'mode' => 'popup']); ?>
<a href="#" data-action-click="ui.modal.load" data-action-url="<?= $url ?>">
<?= Yii::t('CommentModule.base', "Comment").'('.$this->context->getCommentsCount().')' ?>
<?= Yii::t('CommentModule.base', "Comment") . ' (' . $this->context->getCommentsCount() . ')' ?>
</a>
<?php elseif(Yii::$app->user->isGuest): ?>
<?= Html::a(Yii::t('CommentModule.base', "Comment").$commentCountSpan, Yii::$app->user->loginUrl, ['data-target' => '#globalModal']) ?>
<?php elseif (Yii::$app->user->isGuest): ?>
<?= Html::a(Yii::t('CommentModule.base', "Comment") . $commentCountSpan, Yii::$app->user->loginUrl, ['data-target' => '#globalModal']) ?>
<?php else : ?>
<?= Button::asLink(Yii::t('CommentModule.base', "Comment").$commentCountSpan)->action('comment.toggleComment', null, '#comment_' . $id)?>
<?php endif; ?>
<?= Button::asLink(Yii::t('CommentModule.base', "Comment") . $commentCountSpan)->action('comment.toggleComment', null, '#comment_' . $id) ?>
<?php endif; ?>

View File

@ -6,7 +6,9 @@ use humhub\modules\content\widgets\richtext\RichText;
use humhub\modules\user\widgets\Image as UserImage;
use humhub\modules\file\widgets\ShowFiles;
use humhub\modules\like\widgets\LikeLink;
use humhub\modules\comment\widgets\CommentLink;
/* @var $comment \humhub\modules\comment\models\Comment */
/* @var $deleteUrl string */
/* @var $editUrl string */
/* @var $loadUrl string */
@ -20,21 +22,24 @@ use humhub\modules\like\widgets\LikeLink;
<div class="media" id="comment_<?= $comment->id; ?>"
data-action-component="comment.Comment"
data-content-delete-url="<?= $deleteUrl ?>">
<?php if ($canEdit || $canDelete) : ?>
<?php if ($canEdit || $canDelete) : ?>
<div class="comment-entry-loader pull-right"></div>
<ul class="nav nav-pills preferences">
<li class="dropdown ">
<a class="dropdown-toggle" data-toggle="dropdown" href="#" aria-label="<?= Yii::t('base', 'Toggle comment menu'); ?>" aria-haspopup="true">
<a class="dropdown-toggle" data-toggle="dropdown" href="#"
aria-label="<?= Yii::t('base', 'Toggle comment menu'); ?>" aria-haspopup="true">
<i class="fa fa-angle-down"></i>
</a>
<ul class="dropdown-menu pull-right">
<?php if ($canEdit): ?>
<li>
<a href="#" class="comment-edit-link" data-action-click="edit" data-action-url="<?= $editUrl ?>">
<a href="#" class="comment-edit-link" data-action-click="edit"
data-action-url="<?= $editUrl ?>">
<i class="fa fa-pencil"></i> <?= Yii::t('CommentModule.base', 'Edit') ?>
</a>
<a href="#" class="comment-cancel-edit-link" data-action-click="cancelEdit" data-action-url="<?= $loadUrl ?>" style="display:none;">
<a href="#" class="comment-cancel-edit-link" data-action-click="cancelEdit"
data-action-url="<?= $loadUrl ?>" style="display:none;">
<i class="fa fa-pencil"></i> <?= Yii::t('CommentModule.base', 'Cancel Edit') ?>
</a>
</li>
@ -43,7 +48,7 @@ use humhub\modules\like\widgets\LikeLink;
<?php if ($canDelete): ?>
<li>
<a href="#" data-action-click="delete">
<i class="fa fa-trash-o"></i> <?= Yii::t('CommentModule.base', 'Delete') ?>
<i class="fa fa-trash-o"></i> <?= Yii::t('CommentModule.base', 'Delete') ?>
</a>
</li>
<?php endif; ?>
@ -57,14 +62,16 @@ use humhub\modules\like\widgets\LikeLink;
<h4 class="media-heading"><?= Html::containerLink($user); ?>
<small><?= TimeAgo::widget(['timestamp' => $createdAt]); ?>
<?php if ($updatedAt !== null): ?>
&middot; <span class="tt" title="<?= Yii::$app->formatter->asDateTime($updatedAt); ?>"><?= Yii::t('ContentModule.base', 'Updated'); ?></span>
&middot; <span class="tt"
title="<?= Yii::$app->formatter->asDateTime($updatedAt); ?>"><?= Yii::t('ContentModule.base', 'Updated'); ?></span>
<?php endif; ?>
</small>
</h4>
</div>
<!-- class comment_edit_content required since v1.2 -->
<div class="content comment_edit_content" id="comment_editarea_<?= $comment->id; ?>">
<div id="comment-message-<?= $comment->id; ?>" class="comment-message" data-ui-markdown data-ui-show-more data-read-more-text="<?= Yii::t('CommentModule.base', 'Read full comment...') ?>">
<div id="comment-message-<?= $comment->id; ?>" class="comment-message" data-ui-markdown data-ui-show-more
data-read-more-text="<?= Yii::t('CommentModule.base', 'Read full comment...') ?>">
<?= RichText::output($comment->message, ['record' => $comment]); ?>
</div>
<?= ShowFiles::widget(['object' => $comment]); ?>
@ -72,6 +79,8 @@ use humhub\modules\like\widgets\LikeLink;
<div class="wall-entry-controls">
<?= LikeLink::widget(['object' => $comment]); ?>
&middot;
<?= CommentLink::widget(['object' => $comment, 'mode' => CommentLink::MODE_POPUP]); ?>
</div>
</div>
<hr>

View File

@ -141,8 +141,8 @@ class ContentAddonActiveRecord extends ActiveRecord implements ContentOwner
/**
* Checks if this content addon can be changed
*
* @deprecated since 1.4
* @return boolean
* @deprecated since 1.4
*/
public function canWrite()
{