Commit a2cde075db985ec267c8d896e5abb034a750930e

Authored by Yarik
0 parents

first commit

Module.php 0 → 100755
  1 +++ a/Module.php
  1 +<?php
  2 +
  3 + namespace artweb\artbox\comment;
  4 +
  5 + use artweb\artbox\comment\models\CommentModel;
  6 + use artweb\artbox\comment\models\RatingModel;
  7 + use Yii;
  8 + use yii\console\Application;
  9 +
  10 + /**
  11 + * Class Module
  12 + * @package artweb\artbox\comment
  13 + */
  14 + class Module extends \yii\base\Module
  15 + {
  16 +
  17 + /**
  18 + * @var string module name
  19 + */
  20 + public static $name = 'artbox-comment';
  21 +
  22 + /**
  23 + * User identity class, default to common\models\User
  24 + * @var string|null
  25 + */
  26 + public $userIdentityClass = NULL;
  27 +
  28 + /**
  29 + * Comment model class, default to common\modules\models\CommentModel
  30 + * @var string comment model class
  31 + */
  32 + public $commentModelClass = NULL;
  33 +
  34 + public $ratingModelClass = NULL;
  35 +
  36 + /**
  37 + * This namespace will be used to load controller classes by prepending it to the controller
  38 + * class name.
  39 + * @var string the namespace that controller classes are in.
  40 + */
  41 + public $controllerNamespace = 'artweb\artbox\comment\controllers';
  42 +
  43 + /**
  44 + * @var \yii\db\Connection DB connection, default to \Yii::$app->db
  45 + */
  46 + public $db = NULL;
  47 +
  48 + /**
  49 + * Key, used to encrypt and decrypt comment service data.
  50 + * @var string Encryption key
  51 + */
  52 + public static $encryptionKey = 'artbox-comment';
  53 +
  54 + /**
  55 + * Whether to enable comment rating or not.
  56 + * @var bool
  57 + */
  58 + public static $enableRating = true;
  59 +
  60 + /**
  61 + * Initializes the module.
  62 + * This method is called after the module is created and initialized with property values
  63 + * given in configuration. The default implementation will initialize
  64 + * [[controllerNamespace]] if it is not set. If you override this method, please make sure
  65 + * you call the parent implementation.
  66 + */
  67 + public function init()
  68 + {
  69 + if($this->userIdentityClass === NULL) {
  70 + $this->userIdentityClass = Yii::$app->getUser()->identityClass;
  71 + }
  72 + if($this->commentModelClass === NULL) {
  73 + $this->commentModelClass = CommentModel::className();
  74 + }
  75 + if(self::$enableRating && $this->ratingModelClass === NULL) {
  76 + $this->ratingModelClass = RatingModel::className();
  77 + }
  78 + if(\Yii::$app instanceof Application) {
  79 + $this->controllerNamespace = 'artweb\artbox\comment\commands';
  80 + }
  81 + if($this->db === NULL) {
  82 + $this->db = \Yii::$app->db;
  83 + }
  84 + Yii::setAlias('@artbox-comment', __DIR__);
  85 + parent::init();
  86 + }
  87 +
  88 + }
... ...
assets/CommentAsset.php 0 → 100755
  1 +++ a/assets/CommentAsset.php
  1 +<?php
  2 +
  3 + namespace artweb\artbox\comment\assets;
  4 +
  5 + use yii\web\AssetBundle;
  6 +
  7 + /**
  8 + * Class CommentAsset
  9 + * @package artweb\artbox\comment\assets
  10 + */
  11 + class CommentAsset extends AssetBundle
  12 + {
  13 +
  14 + /**
  15 + * @inheritdoc
  16 + */
  17 + public $sourcePath = '@artbox-comment/resources';
  18 +
  19 + /**
  20 + * @inheritdoc
  21 + */
  22 + public $js = [
  23 + 'artbox_comment.js',
  24 + 'jquery.rateit.min.js',
  25 + ];
  26 +
  27 + /**
  28 + * @inheritdoc
  29 + */
  30 + public $css = [
  31 + 'artbox_comment.css',
  32 + 'rateit.css',
  33 + ];
  34 +
  35 + /**
  36 + * @inheritdoc
  37 + */
  38 + public $depends = [
  39 + 'yii\web\JqueryAsset',
  40 + 'yii\web\YiiAsset',
  41 + ];
  42 + }
0 43 \ No newline at end of file
... ...
behaviors/ParentBehavior.php 0 → 100755
  1 +++ a/behaviors/ParentBehavior.php
  1 +<?php
  2 + namespace artweb\artbox\comment\behaviors;
  3 +
  4 + use artweb\artbox\comment\models\CommentModel;
  5 + use yii\base\Behavior;
  6 + use yii\base\Event;
  7 + use yii\db\ActiveRecord;
  8 +
  9 + class ParentBehavior extends Behavior
  10 + {
  11 +
  12 + public function events()
  13 + {
  14 + return [
  15 + ActiveRecord::EVENT_AFTER_VALIDATE => 'afterValidate',
  16 + ];
  17 + }
  18 +
  19 + /**
  20 + * @param Event $event
  21 + */
  22 + public function afterValidate($event)
  23 + {
  24 + /**
  25 + * @var CommentModel $owner
  26 + */
  27 + $owner = $this->owner;
  28 + if(!empty( $owner->artbox_comment_pid )) {
  29 + /**
  30 + * @var CommentModel $parent
  31 + */
  32 + $parent = CommentModel::find()
  33 + ->where([ 'artbox_comment_id' => $owner->artbox_comment_pid ])
  34 + ->one();
  35 + if(!empty( $parent->artbox_comment_pid )) {
  36 + $owner->related_id = $owner->artbox_comment_pid;
  37 + $owner->artbox_comment_pid = $parent->artbox_comment_pid;
  38 + }
  39 + }
  40 + }
  41 + }
0 42 \ No newline at end of file
... ...
composer.json 0 → 100644
  1 +++ a/composer.json
  1 +{
  2 + "name": "artweb/artbox-comment",
  3 + "description": "Yii2 light-weight CMS",
  4 + "license": "BSD-3-Clause",
  5 + "require": {
  6 + "php": ">=7.0",
  7 + "yiisoft/yii2": "*",
  8 + "developeruz/yii2-db-rbac": "*"
  9 + },
  10 + "autoload": {
  11 + "psr-4": {
  12 + "artweb\\artbox\\comment\\": ""
  13 + }
  14 + }
  15 +}
0 16 \ No newline at end of file
... ...
controllers/DefaultController.php 0 → 100755
  1 +++ a/controllers/DefaultController.php
  1 +<?php
  2 + namespace artweb\artbox\comment\controllers;
  3 +
  4 + use artweb\artbox\comment\models\CommentModel;
  5 + use artweb\artbox\comment\models\RatingModel;
  6 + use artweb\artbox\comment\Module;
  7 + use yii\filters\AccessControl;
  8 + use yii\filters\VerbFilter;
  9 + use yii\helpers\Json;
  10 + use yii\web\Controller;
  11 + use yii\web\NotFoundHttpException;
  12 + use yii\web\Response;
  13 +
  14 + class DefaultController extends Controller
  15 + {
  16 +
  17 + /**
  18 + * Returns a list of behaviors that this component should behave as.
  19 + * @return array
  20 + */
  21 + public function behaviors()
  22 + {
  23 + return [
  24 + 'verbs' => [
  25 + 'class' => VerbFilter::className(),
  26 + 'actions' => [
  27 + 'create' => [ 'post' ],
  28 + 'delete' => [
  29 + 'post',
  30 + 'delete',
  31 + ],
  32 + ],
  33 + ],
  34 + 'access' => [
  35 + 'class' => AccessControl::className(),
  36 + 'only' => [ 'delete' ],
  37 + 'rules' => [
  38 + [
  39 + 'allow' => true,
  40 + 'roles' => [ '@' ],
  41 + ],
  42 + ],
  43 + ],
  44 + ];
  45 + }
  46 +
  47 + /**
  48 + * Create comment.
  49 + *
  50 + * @param string $entity
  51 + *
  52 + * @return array|null|Response
  53 + */
  54 + public function actionCreate(string $entity)
  55 + {
  56 + \Yii::$app->response->format = Response::FORMAT_JSON;
  57 + /* @var $module Module */
  58 + $module = \Yii::$app->getModule(Module::$name);
  59 + $entity_data_json = \Yii::$app->getSecurity()
  60 + ->decryptByKey($entity, $module::$encryptionKey);
  61 + if($entity_data_json != false) {
  62 + $entity_data = Json::decode($entity_data_json);
  63 + $commentModelClass = $module->commentModelClass;
  64 + /**
  65 + * @var CommentModel $model
  66 + */
  67 + $model = new $commentModelClass([
  68 + 'scenario' => \Yii::$app->user->getIsGuest() ? $commentModelClass::SCENARIO_GUEST : $commentModelClass::SCENARIO_USER,
  69 + ]);
  70 + if($model->load(\Yii::$app->request->post())) {
  71 + $model->setAttributes($entity_data);
  72 + if($model->save()) {
  73 + if(empty( $model->artbox_comment_pid ) && $module::$enableRating) {
  74 + $ratingModelClass = $module->ratingModelClass;
  75 + /**
  76 + * @var RatingModel $rating
  77 + */
  78 + $rating = new $ratingModelClass([
  79 + 'model' => $model::className(),
  80 + 'model_id' => $model->primaryKey,
  81 + ]);
  82 + if($rating->load(\Yii::$app->request->post())) {
  83 + $rating->save();
  84 + }
  85 + }
  86 + \Yii::$app->session->setFlash('artbox_comment_success', \Yii::t('artbox-comment', 'Comment posted'));
  87 + return [ 'status' => 'success' ];
  88 + } else {
  89 + return [
  90 + 'status' => 'error',
  91 + 'errors' => $model->getFirstErrors(),
  92 + ];
  93 + }
  94 + }
  95 + }
  96 + return [
  97 + 'status' => 'error',
  98 + 'message' => \Yii::t('artbox-comment', 'Oops, something went wrong. Please try again later.'),
  99 + ];
  100 + }
  101 +
  102 + /**
  103 + * Delete comment.
  104 + *
  105 + * @param integer $id Comment ID
  106 + *
  107 + * @return string Comment text
  108 + */
  109 + public function actionDelete($id)
  110 + {
  111 + \Yii::$app->response->format = Response::FORMAT_JSON;
  112 + $model = $this->findModel($id);
  113 + if($model->deleteComment()) {
  114 + return [
  115 + 'status' => 'success',
  116 + 'message' => \Yii::t('yii2mod.comments', 'Comment has been deleted.'),
  117 + ];
  118 + } else {
  119 + \Yii::$app->response->setStatusCode(500);
  120 + return \Yii::t('yii2mod.comments', 'Comment has not been deleted. Please try again!');
  121 + }
  122 + }
  123 +
  124 + /**
  125 + * Find model by ID.
  126 + *
  127 + * @param integer|array $id Comment ID
  128 + *
  129 + * @return CommentModel
  130 + * @throws NotFoundHttpException
  131 + */
  132 + protected function findModel(int $id): CommentModel
  133 + {
  134 + /** @var CommentModel $model */
  135 + $commentModelClass = \Yii::$app->getModule(Module::$name)->commentModelClass;
  136 + if(( $model = $commentModelClass::findOne($id) ) !== NULL) {
  137 + return $model;
  138 + } else {
  139 + throw new NotFoundHttpException(\Yii::t('yii2mod.comments', 'The requested page does not exist.'));
  140 + }
  141 + }
  142 + }
0 143 \ No newline at end of file
... ...
controllers/ManageController.php 0 → 100755
  1 +++ a/controllers/ManageController.php
  1 +<?php
  2 +
  3 + namespace artweb\artbox\comment\controllers;
  4 +
  5 + use artweb\artbox\comment\models\CommentModel;
  6 + use artweb\artbox\comment\models\CommentModelSearch;
  7 + use artweb\artbox\comment\Module;
  8 + use Yii;
  9 + use yii\filters\VerbFilter;
  10 + use yii\web\Controller;
  11 + use yii\web\NotFoundHttpException;
  12 +
  13 + class ManageController extends Controller
  14 + {
  15 +
  16 + /**
  17 + * Returns a list of behaviors that this component should behave as.
  18 + * @return array
  19 + */
  20 + public function behaviors()
  21 + {
  22 + return [
  23 + 'verbs' => [
  24 + 'class' => VerbFilter::className(),
  25 + 'actions' => [
  26 + 'index' => [ 'get' ],
  27 + 'update' => [
  28 + 'get',
  29 + 'post',
  30 + ],
  31 + 'delete' => [ 'post' ],
  32 + ],
  33 + ],
  34 + ];
  35 + }
  36 +
  37 + /**
  38 + * Lists all comments.
  39 + * @return mixed
  40 + */
  41 + public function actionIndex()
  42 + {
  43 + $searchModel = new CommentModelSearch();
  44 + $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
  45 + $commentModel = Yii::$app->getModule(Module::$name)->commentModelClass;
  46 +
  47 + return $this->render('index', [
  48 + 'dataProvider' => $dataProvider,
  49 + 'searchModel' => $searchModel,
  50 + 'commentModel' => $commentModel,
  51 + ]);
  52 + }
  53 +
  54 + /**
  55 + * Updates an existing CommentModel model.
  56 + * If update is successful, the browser will be redirected to the 'view' page.
  57 + *
  58 + * @param integer $id
  59 + *
  60 + * @return mixed
  61 + */
  62 + public function actionUpdate($id)
  63 + {
  64 + $model = $this->findModel($id);
  65 +
  66 + if($model->load(Yii::$app->request->post()) && $model->save()) {
  67 + Yii::$app->session->setFlash('artbox_comment_success', /*Yii::t('yii2mod.comments', 'Comment has been saved.')*/
  68 + 'Comment has been saved.');
  69 + return $this->redirect([ 'index' ]);
  70 + }
  71 +
  72 + return $this->render('update', [
  73 + 'model' => $model,
  74 + ]);
  75 +
  76 + }
  77 +
  78 + /**
  79 + * Deletes an existing CommentModel model.
  80 + * If deletion is successful, the browser will be redirected to the 'index' page.
  81 + *
  82 + * @param integer $id
  83 + *
  84 + * @return mixed
  85 + */
  86 + public function actionDelete($id)
  87 + {
  88 + $this->findModel($id)
  89 + ->delete();
  90 + Yii::$app->session->setFlash('artbox_comment_success', Yii::t('artbox-comment', 'Comment has been deleted.'));
  91 + return $this->redirect([ 'index' ]);
  92 + }
  93 +
  94 + /**
  95 + * Finds the CommentModel model based on its primary key value.
  96 + * If the model is not found, a 404 HTTP exception will be thrown.
  97 + *
  98 + * @param integer $id
  99 + *
  100 + * @return CommentModel the loaded model
  101 + * @throws NotFoundHttpException if the model cannot be found
  102 + */
  103 + protected function findModel($id)
  104 + {
  105 + if(( $model = CommentModel::findOne($id) ) !== NULL) {
  106 + return $model;
  107 + } else {
  108 + throw new NotFoundHttpException(/*Yii::t('yii2mod.comments', 'The requested page does not exist.')*/
  109 + 'The requested page does not exist.');
  110 + }
  111 + }
  112 + }
0 113 \ No newline at end of file
... ...
messages/config.php 0 → 100755
  1 +++ a/messages/config.php
  1 +<?php
  2 +
  3 + return [
  4 + // string, required, root directory of all source files
  5 + 'sourcePath' => __DIR__ . DIRECTORY_SEPARATOR . '..',
  6 + // array, required, list of language codes that the extracted messages
  7 + // should be translated to. For example, ['zh-CN', 'de'].
  8 + 'languages' => [
  9 + 'en',
  10 + 'ru',
  11 + ],
  12 + // string, the name of the function for translating messages.
  13 + // Defaults to 'Yii::t'. This is used as a mark to find the messages to be
  14 + // translated. You may use a string for single function name or an array for
  15 + // multiple function names.
  16 + 'translator' => 'Yii::t',
  17 + // boolean, whether to sort messages by keys when merging new messages
  18 + // with the existing ones. Defaults to false, which means the new (untranslated)
  19 + // messages will be separated from the old (translated) ones.
  20 + 'sort' => true,
  21 + // boolean, whether to remove messages that no longer appear in the source code.
  22 + // Defaults to false, which means each of these messages will be enclosed with a pair of '@@' marks.
  23 + 'removeUnused' => false,
  24 + // array, list of patterns that specify which files (not directories) should be processed.
  25 + // If empty or not set, all files will be processed.
  26 + // Please refer to "except" for details about the patterns.
  27 + 'only' => [ '*.php' ],
  28 + // array, list of patterns that specify which files/directories should NOT be processed.
  29 + // If empty or not set, all files/directories will be processed.
  30 + // A path matches a pattern if it contains the pattern string at its end. For example,
  31 + // '/a/b' will match all files and directories ending with '/a/b';
  32 + // the '*.svn' will match all files and directories whose name ends with '.svn'.
  33 + // and the '.svn' will match all files and directories named exactly '.svn'.
  34 + // Note, the '/' characters in a pattern matches both '/' and '\'.
  35 + // See helpers/FileHelper::findFiles() description for more details on pattern matching rules.
  36 + // If a file/directory matches both a pattern in "only" and "except", it will NOT be processed.
  37 + 'except' => [
  38 + '.svn',
  39 + '.git',
  40 + '.gitignore',
  41 + '.gitkeep',
  42 + '.hgignore',
  43 + '.hgkeep',
  44 + '/messages',
  45 + '/tests',
  46 + '/runtime',
  47 + '/vendor',
  48 + ],
  49 +
  50 + // 'php' output format is for saving messages to php files.
  51 + 'format' => 'php',
  52 + // Root directory containing message translations.
  53 + 'messagePath' => __DIR__,
  54 + // boolean, whether the message file should be overwritten with the merged messages
  55 + 'overwrite' => true,
  56 +
  57 + // Message categories to ignore
  58 + 'ignoreCategories' => [
  59 + 'yii',
  60 + ],
  61 + ];
... ...
messages/en/artbox-comment.php 0 → 100755
  1 +++ a/messages/en/artbox-comment.php
  1 +<?php
  2 + /**
  3 + * Message translations.
  4 + * This file is automatically generated by 'yii message' command.
  5 + * It contains the localizable messages extracted from source code.
  6 + * You may modify this file by translating the extracted messages.
  7 + * Each array element represents the translation (value) of a message (key).
  8 + * If the value is empty, the message is considered as not translated.
  9 + * Messages that no longer need translation will have their translations
  10 + * enclosed between a pair of '@@' marks.
  11 + * Message string can be used with plural forms format. Check i18n section
  12 + * of the guide for details.
  13 + * NOTE: this file must be saved in UTF-8 encoding.
  14 + */
  15 + return [
  16 + 'ID' => 'ID',
  17 + 'Text' => 'Content',
  18 + 'Entity' => 'Entity',
  19 + 'Entity ID' => 'Entity ID',
  20 + 'Parent ID' => 'Parent ID',
  21 + 'Status' => 'Status',
  22 + 'Level' => 'Level',
  23 + 'User' => 'User',
  24 + 'Username' => 'User name',
  25 + 'Date add' => 'Date add',
  26 + 'Date update' => 'Date update',
  27 + 'Date delete' => 'Date delete',
  28 + 'Comment parent' => 'Parent comment',
  29 + 'Comment related' => 'Related comment',
  30 + 'Info' => 'Additional info',
  31 + 'Created by' => 'Created by',
  32 + 'Updated by' => 'Related to',
  33 + 'Related to' => 'Related to',
  34 + 'Created date' => 'Created date',
  35 + 'Updated date' => 'Updated date',
  36 + 'Update' => 'Update',
  37 + 'Delete' => 'Delete',
  38 + 'Reply' => 'Reply',
  39 + 'Comments ({0})' => 'Comments ({0})',
  40 + 'Comment cannot be blank.' => 'Comment cannot be blank.',
  41 + 'Comment has not been deleted. Please try again!' => 'Comment has not been deleted. Please try again!',
  42 + 'Add a comment...' => 'Add a comment...',
  43 + 'Comment' => 'Comment',
  44 + 'Oops, something went wrong. Please try again later.' => 'Oops, something went wrong. Please try again later.',
  45 + 'The requested page does not exist.' => 'The requested page does not exist.',
  46 + 'Comment has been deleted.' => 'Comment has been deleted.',
  47 + 'Comment has been saved.' => 'Comment has been saved.',
  48 + 'Click here to cancel reply.' => 'Click here to cancel reply.',
  49 + 'Comments Management' => 'Comments Management',
  50 + 'Select Status' => 'Select Status',
  51 + 'Select Author' => 'Select Author',
  52 + 'Update Comment: {0}' => 'Update Comment: {0}',
  53 + 'Active' => 'Active',
  54 + 'Deleted' => 'Deleted',
  55 + 'Comment posted' => 'Comment successfully added and will appear after moderator check.',
  56 + ];
... ...
messages/ru/artbox-comment.php 0 → 100755
  1 +++ a/messages/ru/artbox-comment.php
  1 +<?php
  2 + /**
  3 + * Message translations.
  4 + * This file is automatically generated by 'yii message' command.
  5 + * It contains the localizable messages extracted from source code.
  6 + * You may modify this file by translating the extracted messages.
  7 + * Each array element represents the translation (value) of a message (key).
  8 + * If the value is empty, the message is considered as not translated.
  9 + * Messages that no longer need translation will have their translations
  10 + * enclosed between a pair of '@@' marks.
  11 + * Message string can be used with plural forms format. Check i18n section
  12 + * of the guide for details.
  13 + * NOTE: this file must be saved in UTF-8 encoding.
  14 + */
  15 + return [
  16 + 'ID' => 'Идентификатор',
  17 + 'Text' => 'Комментарий',
  18 + 'Entity' => 'Модель',
  19 + 'Entity ID' => 'Идентификатор модели',
  20 + 'Parent ID' => 'Родитель',
  21 + 'Status' => 'Статус',
  22 + 'Level' => 'Уровень',
  23 + 'User' => 'Пользователь',
  24 + 'Username' => 'Имя',
  25 + 'Date add' => 'Дата добавления',
  26 + 'Date update' => 'Дата обновления',
  27 + 'Date delete' => 'Дата удаления',
  28 + 'Comment parent' => 'Родитель',
  29 + 'Comment related' => 'Связзанный комментарий',
  30 + 'Info' => 'Дополнительная информация',
  31 + 'Created by' => 'Создан',
  32 + 'Updated by' => 'Обновлен',
  33 + 'Related to' => 'Относится к',
  34 + 'Created date' => 'Дата создания',
  35 + 'Updated date' => 'Дата обновления',
  36 + 'Update' => 'Обновить',
  37 + 'Delete' => 'Удалить',
  38 + 'Reply' => 'Ответить',
  39 + 'Comments ({0})' => 'Комментарии ({0})',
  40 + 'Comment cannot be blank.' => 'Комментарий не может быть пустым.',
  41 + 'Comment has not been deleted. Please try again!' => 'Не удалось удалить комментарий. Попробуйте пожалуйста еще раз!',
  42 + 'Add a comment...' => 'Добавить комментарий...',
  43 + 'Comment' => 'Опубликовать комментарий',
  44 + 'Oops, something went wrong. Please try again later.' => 'Не удалось добавить комментарий. Попробуйте пожалуйста еще раз.',
  45 + 'The requested page does not exist.' => 'Ошибка 404 - страница не найдена!',
  46 + 'Comment has been deleted.' => 'Комментарий был удалён.',
  47 + 'Comment has been saved.' => 'Комментарий был сохранён.',
  48 + 'Click here to cancel reply.' => 'Нажмите здесь, чтобы отменить ответ.',
  49 + 'Comments Management' => 'Управление Комментариями',
  50 + 'Select Status' => 'Выберите Статус',
  51 + 'Select Author' => 'Выберите Автора',
  52 + 'Update Comment: {0}' => 'Обновить комментарий: {0}',
  53 + 'Active' => 'Включён',
  54 + 'Deleted' => 'Удален',
  55 + 'Comment posted' => 'Комментарий успешно добавлен и появится после проверки администрацией.',
  56 + 'Submit' => 'Добавить комментарий',
  57 + 'Cancel' => 'Отменить',
  58 + 'Guest' => 'Гость',
  59 + ];
... ...
migrations/m160724_162347_artbox_comment.php 0 → 100755
  1 +++ a/migrations/m160724_162347_artbox_comment.php
  1 +<?php
  2 +
  3 + use yii\db\Migration;
  4 +
  5 + class m160724_162347_artbox_comment extends Migration
  6 + {
  7 +
  8 + public function up()
  9 + {
  10 + $this->createTable(
  11 + '{{%artbox_comment}}',
  12 + [
  13 + 'artbox_comment_id' => $this->primaryKey(),
  14 + 'text' => $this->text()
  15 + ->notNull(),
  16 + 'user_id' => $this->integer(),
  17 + 'username' => $this->string(),
  18 + 'email' => $this->string(),
  19 + 'created_at' => $this->integer()
  20 + ->notNull(),
  21 + 'updated_at' => $this->integer()
  22 + ->notNull(),
  23 + 'deleted_at' => $this->integer(),
  24 + 'status' => $this->integer()
  25 + ->notNull()
  26 + ->defaultValue(1),
  27 + 'artbox_comment_pid' => $this->integer(),
  28 + 'related_id' => $this->integer(),
  29 + 'ip' => $this->string()
  30 + ->notNull(),
  31 + 'info' => $this->text(),
  32 + ]
  33 + );
  34 +
  35 + $this->addForeignKey(
  36 + 'user_id_user',
  37 + '{{%artbox_comment}}',
  38 + 'user_id',
  39 + 'customer',
  40 + 'id',
  41 + 'CASCADE',
  42 + 'CASCADE'
  43 + );
  44 + $this->addForeignKey(
  45 + 'artbox_comment_pid_artbox_comment',
  46 + '{{%artbox_comment}}',
  47 + 'artbox_comment_pid',
  48 + 'artbox_comment',
  49 + 'artbox_comment_id',
  50 + 'CASCADE',
  51 + 'CASCADE'
  52 + );
  53 + $this->addForeignKey(
  54 + 'related_id_artbox_comment',
  55 + '{{%artbox_comment}}',
  56 + 'related_id',
  57 + 'artbox_comment',
  58 + 'artbox_comment_id',
  59 + 'CASCADE',
  60 + 'CASCADE'
  61 + );
  62 +
  63 + $this->createTable(
  64 + '{{%artbox_like}}',
  65 + [
  66 + 'artbox_like_id' => $this->primaryKey(),
  67 + 'artbox_comment_id' => $this->integer()
  68 + ->notNull(),
  69 + 'user_id' => $this->integer(),
  70 + 'created_at' => $this->integer()
  71 + ->notNull(),
  72 + 'is_like' => $this->integer()
  73 + ->notNull()
  74 + ->defaultValue(1),
  75 + ]
  76 + );
  77 +
  78 + $this->addForeignKey(
  79 + 'artbox_comment_id_artbox_comment',
  80 + '{{%artbox_like}}',
  81 + 'artbox_comment_id',
  82 + 'artbox_comment',
  83 + 'artbox_comment_id',
  84 + 'CASCADE',
  85 + 'CASCADE'
  86 + );
  87 + $this->addForeignKey('user_id_user', '{{%artbox_like}}', 'user_id', 'customer', 'id', 'CASCADE', 'CASCADE');
  88 + $this->createIndex(
  89 + 'artbox_like_unique',
  90 + '{{%artbox_like}}',
  91 + [
  92 + 'artbox_comment_id',
  93 + 'user_id',
  94 + 'is_like',
  95 + ],
  96 + true
  97 + );
  98 +
  99 + }
  100 +
  101 + public function down()
  102 + {
  103 + $this->dropForeignKey('user_id_user', '{{%artbox_comment}}');
  104 + $this->dropForeignKey('artbox_comment_pid_artbox_comment', '{{%artbox_comment}}');
  105 + $this->dropForeignKey('related_id_artbox_comment', '{{%artbox_comment}}');
  106 + $this->dropForeignKey('artbox_comment_id_artbox_comment', '{{%artbox_like}}');
  107 + $this->dropForeignKey('user_id_user', '{{%artbox_like}}');
  108 + $this->dropIndex('artbox_like_unique', '{{%artbox_like}}');
  109 + $this->dropTable('{{%artbox_comment}}');
  110 + $this->dropTable('{{%artbox_like}}');
  111 + }
  112 + }
... ...
migrations/m160726_092634_add_entity_fields.php 0 → 100755
  1 +++ a/migrations/m160726_092634_add_entity_fields.php
  1 +<?php
  2 +
  3 + use yii\db\Migration;
  4 +
  5 + class m160726_092634_add_entity_fields extends Migration
  6 + {
  7 +
  8 + public function up()
  9 + {
  10 + $this->addColumn('{{%artbox_comment}}', 'entity', $this->string()
  11 + ->notNull()
  12 + ->defaultValue(''));
  13 + $this->addColumn('{{%artbox_comment}}', 'entity_id', $this->integer()
  14 + ->notNull()
  15 + ->defaultValue(1));
  16 + }
  17 +
  18 + public function down()
  19 + {
  20 + $this->dropColumn('{{%artbox_comment}}', 'entity');
  21 + $this->dropColumn('{{%artbox_comment}}', 'entity_id');
  22 + }
  23 + }
... ...
migrations/m160726_211227_create_artbox_comment_rating.php 0 → 100755
  1 +++ a/migrations/m160726_211227_create_artbox_comment_rating.php
  1 +<?php
  2 +
  3 + use yii\db\Migration;
  4 +
  5 + class m160726_211227_create_artbox_comment_rating extends Migration
  6 + {
  7 +
  8 + public function up()
  9 + {
  10 + $this->createTable(
  11 + '{{%artbox_comment_rating}}',
  12 + [
  13 + 'artbox_comment_rating_id' => $this->primaryKey(),
  14 + 'created_at' => $this->integer()
  15 + ->notNull(),
  16 + 'updated_at' => $this->integer()
  17 + ->notNull(),
  18 + 'user_id' => $this->integer(),
  19 + 'value' => $this->float(),
  20 + 'model' => $this->string()
  21 + ->notNull(),
  22 + 'model_id' => $this->integer()
  23 + ->notNull(),
  24 + ]
  25 + );
  26 + $this->addForeignKey(
  27 + 'user_id_user',
  28 + '{{%artbox_comment_rating}}',
  29 + 'user_id',
  30 + 'customer',
  31 + 'id',
  32 + 'CASCADE',
  33 + 'CASCADE'
  34 + );
  35 + }
  36 +
  37 + public function down()
  38 + {
  39 + $this->dropForeignKey('user_id_user', '{{%artbox_comment_rating}}');
  40 + $this->dropTable('{{%artbox_comment_rating}}');
  41 + }
  42 + }
... ...
models/CommentModel.php 0 → 100755
  1 +++ a/models/CommentModel.php
  1 +<?php
  2 + namespace artweb\artbox\comment\models;
  3 +
  4 + use common\behaviors\RatingBehavior;
  5 + use artweb\artbox\comment\behaviors\ParentBehavior;
  6 + use artweb\artbox\comment\models\interfaces\CommentInterface;
  7 + use yii\behaviors\AttributeBehavior;
  8 + use yii\behaviors\BlameableBehavior;
  9 + use yii\behaviors\TimestampBehavior;
  10 + use yii\data\ActiveDataProvider;
  11 + use yii\db\ActiveRecord;
  12 +
  13 + /**
  14 + * Class CommentModel
  15 + *
  16 + * @property int $artbox_comment_id
  17 + * @property string $text
  18 + * @property int $user_id
  19 + * @property string $username
  20 + * @property string $email
  21 + * @property int $created_at
  22 + * @property int $updated_at
  23 + * @property int $deleted_at
  24 + * @property int $status
  25 + * @property int $artbox_comment_pid
  26 + * @property int $related_id
  27 + * @property string $ip
  28 + * @property string $info
  29 + * @property string $entity
  30 + * @property int $entity_id
  31 + * @package artweb\artbox\comment\models
  32 + */
  33 + class CommentModel extends ActiveRecord implements CommentInterface
  34 + {
  35 +
  36 + const STATUS_ACTIVE = 1;
  37 + const STATUS_HIDDEN = 0;
  38 + const STATUS_DELETED = 2;
  39 +
  40 + const SCENARIO_USER = 'user';
  41 + const SCENARIO_GUEST = 'guest';
  42 +
  43 + public $encryptedEntity;
  44 +
  45 + public $entityId;
  46 +
  47 + public function scenarios()
  48 + {
  49 + $scenarios = parent::scenarios();
  50 + $scenarios[ self::SCENARIO_USER ] = [
  51 + 'text',
  52 + 'entity',
  53 + 'entity_id',
  54 + 'artbox_comment_pid',
  55 + 'status',
  56 + ];
  57 + $scenarios[ self::SCENARIO_GUEST ] = [
  58 + 'text',
  59 + 'entity',
  60 + 'entity_id',
  61 + 'username',
  62 + 'email',
  63 + 'status',
  64 + ];
  65 + return $scenarios;
  66 + }
  67 +
  68 + public static function tableName()
  69 + {
  70 + return '{{%artbox_comment}}';
  71 + }
  72 +
  73 + public function rules()
  74 + {
  75 + return [
  76 + [
  77 + [
  78 + 'text',
  79 + 'entity',
  80 + 'entity_id',
  81 + ],
  82 + 'required',
  83 + ],
  84 + [
  85 + [
  86 + 'username',
  87 + 'email',
  88 + ],
  89 + 'required',
  90 + 'on' => self::SCENARIO_GUEST,
  91 + ],
  92 + [
  93 + [
  94 + 'text',
  95 + 'entity',
  96 + 'username',
  97 + ],
  98 + 'string',
  99 + ],
  100 + [
  101 + [
  102 + 'email',
  103 + ],
  104 + 'email',
  105 + ],
  106 + [
  107 + [
  108 + 'entity_id',
  109 + 'artbox_comment_pid',
  110 + ],
  111 + 'integer',
  112 + ],
  113 + [
  114 + [ 'status' ],
  115 + 'default',
  116 + 'value' => 0,
  117 + ],
  118 + [
  119 + [ 'artbox_comment_pid' ],
  120 + 'exist',
  121 + 'targetAttribute' => 'artbox_comment_id',
  122 + 'skipOnError' => true,
  123 + ],
  124 + ];
  125 + }
  126 +
  127 + public function behaviors()
  128 + {
  129 + return [
  130 + [
  131 + 'class' => TimestampBehavior::className(),
  132 + ],
  133 + [
  134 + 'class' => BlameableBehavior::className(),
  135 + 'createdByAttribute' => 'user_id',
  136 + 'updatedByAttribute' => false,
  137 + ],
  138 + [
  139 + 'class' => AttributeBehavior::className(),
  140 + 'attributes' => [
  141 + ActiveRecord::EVENT_BEFORE_INSERT => 'ip',
  142 + ],
  143 + 'value' => function ($event) {
  144 + return \Yii::$app->request->userIP;
  145 + },
  146 + ],
  147 + [
  148 + 'class' => ParentBehavior::className(),
  149 + ],
  150 + [
  151 + 'class' => RatingBehavior::className(),
  152 + ],
  153 + /* Notification: uncomment to enable notifications.
  154 + [
  155 + 'class' => NotifyBehavior::className(),
  156 + ],
  157 + */
  158 + ];
  159 + }
  160 +
  161 + public function attributeLabels()
  162 + {
  163 + return [
  164 + 'artbox_comment_id' => \Yii::t('artbox-comment', 'ID'),
  165 + 'text' => \Yii::t('artbox-comment', 'Text'),
  166 + 'user_id' => \Yii::t('artbox-comment', 'User'),
  167 + 'username' => \Yii::t('artbox-comment', 'Username'),
  168 + 'email' => 'Email',
  169 + 'date_add' => \Yii::t('artbox-comment', 'Date add'),
  170 + 'updated_at' => \Yii::t('artbox-comment', 'Date update'),
  171 + 'deleted_at' => \Yii::t('artbox-comment', 'Date delete'),
  172 + 'status' => \Yii::t('artbox-comment', 'Status'),
  173 + 'artbox_comment_pid' => \Yii::t('artbox-comment', 'Comment parent'),
  174 + 'related_id' => \Yii::t('artbox-comment', 'Comment related'),
  175 + 'ip' => 'IP',
  176 + 'entity' => \Yii::t('artbox-comment', 'Entity'),
  177 + 'info' => \Yii::t('artbox-comment', 'Info'),
  178 + 'entity_id' => \Yii::t('artbox-comment', 'Entity ID'),
  179 + ];
  180 + }
  181 +
  182 + public function setEntity(string $entity)
  183 + {
  184 + $this->entity = $entity;
  185 + }
  186 +
  187 + public function getEntity(): string
  188 + {
  189 + return $this->entity;
  190 + }
  191 +
  192 + public static function getTree(string $entity, int $entityId): ActiveDataProvider
  193 + {
  194 + return new ActiveDataProvider(
  195 + [
  196 + 'query' => self::find()
  197 + ->with(
  198 + [
  199 + 'children',
  200 + 'user',
  201 + 'children.user',
  202 + ]
  203 + )
  204 + ->where(
  205 + [
  206 + 'entity' => $entity,
  207 + 'entity_id' => $entityId,
  208 + 'status' => 1,
  209 + 'artbox_comment_pid' => null,
  210 + ]
  211 + ),
  212 + 'pagination' => [
  213 + 'pageSize' => 20,
  214 + ],
  215 + 'sort' => [
  216 + 'defaultOrder' => [
  217 + 'created_at' => SORT_DESC,
  218 + ],
  219 + ],
  220 + ]
  221 + );
  222 + }
  223 +
  224 + public function deleteComment(): bool
  225 + {
  226 + if (\Yii::$app->user->id != null && \Yii::$app->user->id == $this->user_id) {
  227 + if ($this->delete()) {
  228 + return true;
  229 + }
  230 + }
  231 + return false;
  232 + }
  233 +
  234 + public function setEntityId(int $entityId)
  235 + {
  236 + $this->entityId = $entityId;
  237 + }
  238 +
  239 + public function getEntityId(): int
  240 + {
  241 + return $this->entityId;
  242 + }
  243 +
  244 + public function getChildren()
  245 + {
  246 + return $this->hasMany(self::className(), [ 'artbox_comment_pid' => 'artbox_comment_id' ])
  247 + ->andFilterWhere([ 'status' => self::STATUS_ACTIVE ])
  248 + ->inverseOf('parent');
  249 + }
  250 +
  251 + public function getParent()
  252 + {
  253 + return $this->hasOne(self::className(), [ 'artbox_comment_id' => 'artbox_comment_pid' ])
  254 + ->inverseOf('children');
  255 + }
  256 +
  257 + public function getUser()
  258 + {
  259 + $module = \Yii::$app->getModule('artbox-comment');
  260 + return $this->hasOne($module->userIdentityClass, [ 'id' => 'user_id' ]);
  261 + }
  262 +
  263 + public function getRating()
  264 + {
  265 + return $this->hasOne(RatingModel::className(), [ 'model_id' => 'artbox_comment_id' ])
  266 + ->andWhere(
  267 + [
  268 + 'or',
  269 + [ 'artbox_comment_rating.model' => null ],
  270 + [ 'artbox_comment_rating.model' => self::className() ],
  271 + ]
  272 + );
  273 + }
  274 + }
0 275 \ No newline at end of file
... ...
models/CommentModelSearch.php 0 → 100755
  1 +++ a/models/CommentModelSearch.php
  1 +<?php
  2 +
  3 + namespace artweb\artbox\comment\models;
  4 +
  5 + use yii\base\Model;
  6 + use yii\data\ActiveDataProvider;
  7 +
  8 + /**
  9 + * CommentModelSearch represents the model behind the search form about
  10 + * `artweb\artbox\comment\models\CommentModel`.
  11 + */
  12 + class CommentModelSearch extends CommentModel
  13 + {
  14 +
  15 + public $ratingValue;
  16 +
  17 + public $childrenCount;
  18 +
  19 + /**
  20 + * @inheritdoc
  21 + */
  22 + public function rules()
  23 + {
  24 + return [
  25 + [
  26 + [
  27 + 'artbox_comment_id',
  28 + 'created_at',
  29 + 'updated_at',
  30 + 'deleted_at',
  31 + 'status',
  32 + 'artbox_comment_pid',
  33 + 'related_id',
  34 + 'entity_id',
  35 + ],
  36 + 'integer',
  37 + ],
  38 + [
  39 + [
  40 + 'childrenCount',
  41 + ],
  42 + 'integer',
  43 + 'min' => 0,
  44 + ],
  45 + [
  46 + [
  47 + 'ratingValue',
  48 + ],
  49 + 'number',
  50 + 'min' => 1,
  51 + 'max' => 5,
  52 + ],
  53 + [
  54 + [
  55 + 'user_id',
  56 + 'text',
  57 + 'username',
  58 + 'email',
  59 + 'ip',
  60 + 'entity',
  61 + 'info',
  62 + ],
  63 + 'safe',
  64 + ],
  65 + ];
  66 + }
  67 +
  68 + public function attributeLabels()
  69 + {
  70 + return array_merge(
  71 + parent::attributeLabels(),
  72 + [
  73 + 'ratingValue' => 'Рейтинг',
  74 + 'childrenCount' => 'Количество ответов',
  75 + ]
  76 + );
  77 + }
  78 +
  79 + /**
  80 + * @inheritdoc
  81 + */
  82 + public function scenarios()
  83 + {
  84 + // bypass scenarios() implementation in the parent class
  85 + return Model::scenarios();
  86 + }
  87 +
  88 + /**
  89 + * Creates data provider instance with search query applied
  90 + *
  91 + * @param array $params
  92 + *
  93 + * @return ActiveDataProvider
  94 + */
  95 + public function search($params)
  96 + {
  97 + $query = CommentModel::find()
  98 + ->joinWith(
  99 + [
  100 + 'rating',
  101 + 'user',
  102 + ]
  103 + );
  104 +
  105 + // add conditions that should always apply here
  106 +
  107 + $dataProvider = new ActiveDataProvider(
  108 + [
  109 + 'query' => $query,
  110 + 'sort' => [
  111 + 'attributes' => [
  112 + 'ratingValue' => [
  113 + 'asc' => [ 'artbox_comment_rating.value' => SORT_ASC ],
  114 + 'desc' => [ 'artbox_comment_rating.value' => SORT_DESC ],
  115 + ],
  116 + 'artbox_comment_id',
  117 + 'date_add',
  118 + 'text',
  119 + 'user_id',
  120 + 'status',
  121 + 'entity',
  122 + 'entity_id',
  123 + ],
  124 + 'defaultOrder' => [
  125 + 'created_at' => SORT_DESC,
  126 + ],
  127 + ],
  128 + ]
  129 + );
  130 +
  131 + $this->load($params);
  132 +
  133 + if (!$this->validate()) {
  134 + // uncomment the following line if you do not want to return any records when validation fails
  135 + // $query->where('0=1');
  136 + return $dataProvider;
  137 + }
  138 +
  139 + // grid filtering conditions
  140 + $query->andFilterWhere(
  141 + [
  142 + 'artbox_comment_id' => $this->artbox_comment_id,
  143 + 'created_at' => $this->created_at,
  144 + 'updated_at' => $this->updated_at,
  145 + 'deleted_at' => $this->deleted_at,
  146 + 'artbox_comment.status' => $this->status,
  147 + 'artbox_comment_pid' => $this->artbox_comment_pid,
  148 + 'related_id' => $this->related_id,
  149 + 'entity_id' => $this->entity_id,
  150 + ]
  151 + );
  152 +
  153 + $query->andFilterWhere(
  154 + [
  155 + 'like',
  156 + 'text',
  157 + $this->text,
  158 + ]
  159 + )
  160 + ->andFilterWhere(
  161 + [
  162 + 'like',
  163 + 'username',
  164 + $this->username,
  165 + ]
  166 + )
  167 + ->andFilterWhere(
  168 + [
  169 + 'like',
  170 + 'email',
  171 + $this->email,
  172 + ]
  173 + )
  174 + ->andFilterWhere(
  175 + [
  176 + 'like',
  177 + 'ip',
  178 + $this->ip,
  179 + ]
  180 + )
  181 + ->andFilterWhere(
  182 + [
  183 + 'like',
  184 + 'entity',
  185 + $this->entity,
  186 + ]
  187 + )
  188 + ->andFilterWhere(
  189 + [
  190 + 'like',
  191 + 'info',
  192 + $this->info,
  193 + ]
  194 + )
  195 + ->andFilterWhere(
  196 + [
  197 + 'artbox_comment_rating.value' => $this->ratingValue,
  198 + ]
  199 + );
  200 +
  201 + if (!empty( $this->user_id )) {
  202 + $query->andWhere(
  203 + [
  204 + 'or',
  205 + [ 'artbox_comment.user_id' => (int) $this->user_id ],
  206 + [
  207 + 'like',
  208 + 'user.username',
  209 + $this->user_id,
  210 + ],
  211 + [
  212 + 'like',
  213 + 'artbox_comment.username',
  214 + $this->user_id,
  215 + ],
  216 + [
  217 + 'like',
  218 + 'artbox_comment.email',
  219 + $this->user_id,
  220 + ],
  221 + ]
  222 + );
  223 + }
  224 +
  225 + return $dataProvider;
  226 + }
  227 + }
... ...
models/LikeModel.php 0 → 100755
  1 +++ a/models/LikeModel.php
  1 +<?php
  2 +
  3 + namespace artweb\artbox\comment\models;
  4 +
  5 + use yii\db\ActiveRecord;
  6 +
  7 + /**
  8 + * Class LikeModel
  9 + * @package artweb\artbox\comment\models
  10 + */
  11 + class LikeModel extends ActiveRecord
  12 + {
  13 +
  14 + }
0 15 \ No newline at end of file
... ...
models/RatingModel.php 0 → 100755
  1 +++ a/models/RatingModel.php
  1 +<?php
  2 +
  3 + namespace artweb\artbox\comment\models;
  4 +
  5 + use common\models\User;
  6 + use Yii;
  7 + use yii\behaviors\BlameableBehavior;
  8 + use yii\behaviors\TimestampBehavior;
  9 + use yii\db\ActiveRecord;
  10 +
  11 + /**
  12 + * This is the model class for table "artbox_comment_rating".
  13 + *
  14 + * @property integer $artbox_comment_rating_id
  15 + * @property string $created_at
  16 + * @property string $updated_at
  17 + * @property integer $user_id
  18 + * @property integer $value
  19 + * @property string $model
  20 + * @property integer $model_id
  21 + * @property User $user
  22 + */
  23 + class RatingModel extends ActiveRecord
  24 + {
  25 +
  26 + /**
  27 + * @inheritdoc
  28 + */
  29 + public static function tableName()
  30 + {
  31 + return 'artbox_comment_rating';
  32 + }
  33 +
  34 + /**
  35 + * @inheritdoc
  36 + */
  37 + public function rules()
  38 + {
  39 + return [
  40 + [
  41 + [ 'value' ],
  42 + 'required',
  43 + ],
  44 + [
  45 + [ 'value' ],
  46 + 'number',
  47 + 'min' => 0.5,
  48 + 'max' => 5,
  49 + ],
  50 + ];
  51 + }
  52 +
  53 + public function behaviors()
  54 + {
  55 + return [
  56 + [
  57 + 'class' => TimestampBehavior::className(),
  58 + ],
  59 + [
  60 + 'class' => BlameableBehavior::className(),
  61 + 'createdByAttribute' => 'user_id',
  62 + 'updatedByAttribute' => false,
  63 + ],
  64 + ];
  65 + }
  66 +
  67 + /**
  68 + * @inheritdoc
  69 + */
  70 + public function attributeLabels()
  71 + {
  72 + return [
  73 + 'rating_id' => Yii::t('app', 'Rating ID'),
  74 + 'date_add' => Yii::t('app', 'Date Add'),
  75 + 'updated_at' => Yii::t('app', 'Date Update'),
  76 + 'user_id' => Yii::t('app', 'User ID'),
  77 + 'entity' => Yii::t('app', 'Entity'),
  78 + 'value' => Yii::t('app', 'Value'),
  79 + ];
  80 + }
  81 +
  82 + /**
  83 + * @return \yii\db\ActiveQuery
  84 + */
  85 + public function getUser()
  86 + {
  87 + return $this->hasOne(User::className(), [ 'id' => 'user_id' ]);
  88 + }
  89 +
  90 + public function getModel()
  91 + {
  92 + $model = $this->model;
  93 + return $this->hasOne($model, [ $model::primaryKey() => 'model_id' ]);
  94 + }
  95 + }
... ...
models/interfaces/CommentInterface.php 0 → 100755
  1 +++ a/models/interfaces/CommentInterface.php
  1 +<?php
  2 +
  3 + namespace artweb\artbox\comment\models\interfaces;
  4 +
  5 + use yii\data\ActiveDataProvider;
  6 +
  7 + /**
  8 + * Interface CommentInterface
  9 + * @package artweb\artbox\comment\models\interfaces
  10 + */
  11 + interface CommentInterface
  12 + {
  13 +
  14 + public function setEntity(string $entity);
  15 +
  16 + public function getEntity(): string;
  17 +
  18 + public function setEntityId(int $entityId);
  19 +
  20 + public function getEntityId(): int;
  21 +
  22 + public static function getTree(string $entity, int $entityId): ActiveDataProvider;
  23 +
  24 + }
0 25 \ No newline at end of file
... ...
resources/artbox_comment.css 0 → 100755
  1 +++ a/resources/artbox_comment.css
  1 +@import "https://fonts.googleapis.com/css?family=Roboto:400,700,500&subset=cyrillic-ext,latin,cyrillic,latin-ext";
  2 +
  3 +.input_bl, .area_bl, .form-comm-wr, .user_name, .user_txt, .comment-panel, .answer-form, .comments-start input, .comments-start textarea, .submit_btn button, .input_bl label {
  4 + box-sizing: border-box
  5 +}
  6 +
  7 +.comments-border {
  8 + width: 100%;
  9 + margin-top: 25px;
  10 + margin-bottom: 27px;
  11 + height: 1px;
  12 + background: #d2d2d2
  13 +}
  14 +
  15 +.comments-start {
  16 + width: 730px;
  17 + margin: 0 auto;
  18 + font-family: 'Roboto', sans-serif;
  19 + font-weight: 400;
  20 + color: #333
  21 +}
  22 +
  23 +.form-comm-wr {
  24 + width: 100%;
  25 + background: #f5f5f5;
  26 + padding: 20px;
  27 + float: left
  28 +}
  29 +
  30 +.input_bl {
  31 + margin-top: 15px;
  32 + float: left
  33 +}
  34 +
  35 +.area_bl, .input_bl {
  36 + position: relative
  37 +}
  38 +
  39 +.input_bl input, .input_bl textarea, .answer-form textarea {
  40 + width: 258px;
  41 + height: 30px;
  42 + border: 1px solid #d2d2d2;
  43 + background: #fff;
  44 + outline: none !important;
  45 + border-radius: 4px;
  46 + padding-left: 10px
  47 +}
  48 +
  49 +.area_bl textarea, .answer-form textarea {
  50 + resize: none !important;
  51 + height: 140px;
  52 + width: 585px;
  53 + padding-top: 7px
  54 +}
  55 +.stars-wr_ {
  56 + width: 100%;
  57 +}
  58 +.input_bl input:focus, .input_bl textarea:focus, .answer-form textarea:focus {
  59 + box-shadow: 1px 2px 2px 0 rgba(215, 215, 215, 0.75) inset;
  60 + transition: .1s;
  61 + border: 1px solid #d2d2d2 !important;
  62 +}
  63 +
  64 +.input_bl label {
  65 + font-size: 12px;
  66 + color: #7d7d7d;
  67 + font-weight: 400;
  68 + text-transform: uppercase;
  69 + position: relative;
  70 + width: 105px;
  71 + float: left;
  72 + text-align: right;
  73 + padding-right: 10px;
  74 + margin: 9px 0 0 0;
  75 +}
  76 +
  77 +.field-commentmodel-email label {
  78 + width: 69px
  79 +}
  80 +
  81 +.submit_btn {
  82 + float: right;
  83 + margin-top: 27px
  84 +}
  85 +
  86 +.submit_btn button, .answer-form button {
  87 + padding: 0 17px;
  88 + height: 32px;
  89 + font-weight: 500;
  90 + font-size: 15px;
  91 + color: #fff;
  92 + border-top: 0;
  93 + border-left: 0;
  94 + border-right: 0;
  95 + border-bottom: 2px solid #799920;
  96 + background: #95ba2f;
  97 + border-radius: 4px;
  98 + cursor: pointer;
  99 + outline: none !important
  100 +}
  101 +
  102 +.submit_btn button:hover, .answer-form button:hover {
  103 + border-bottom: 2px solid #95ba2f
  104 +}
  105 +
  106 +.submit_btn button:active, .answer-form button:active {
  107 + border-bottom: 2px solid #799920;
  108 + background: #799920
  109 +}
  110 +
  111 +.answer-form button {
  112 + float: right;
  113 + margin-top: 27px;
  114 + margin-left: 10px;
  115 +}
  116 +
  117 +.comments-wr, .comment-answer {
  118 + min-height: 64px;
  119 + position: relative;
  120 + float: left;
  121 + width: 100%
  122 +}
  123 +
  124 +.answer-form {
  125 + float: left;
  126 + width: 100%
  127 +}
  128 +
  129 +.answer-form label {
  130 + position: relative;
  131 +}
  132 +
  133 +.answer-form .required label:before {
  134 + right: -7px;
  135 +}
  136 +
  137 +.user-ico {
  138 + width: 80px;
  139 + height: 80px;
  140 + float: left;
  141 + overflow: hidden;
  142 + border-radius: 50%;
  143 + position: absolute;
  144 + top: 0;
  145 + left: 0
  146 +}
  147 +
  148 +.user-ico img {
  149 + width: 100%;
  150 + height: 100%
  151 +}
  152 +
  153 +.comments-start .user_data {
  154 + margin-top: -2px;
  155 + font-size: 12px;
  156 + color: #636363;
  157 + border-right: none;
  158 +}
  159 +
  160 +.user_name {
  161 + margin-top: 6px;
  162 + font-weight: 700;
  163 + font-size: 15px
  164 +}
  165 +
  166 +.comments-start .user_name, .comments-start .user_txt, .comments-start .comment-panel, .comments-start .user_data, .comments-start .user_rating {
  167 + width: 100%;
  168 + float: left;
  169 + padding-left: 100px
  170 +}
  171 +
  172 +.user_txt {
  173 + margin-top: 8px;
  174 + font-size: 13px;
  175 + line-height: 18px
  176 +}
  177 +
  178 +.comment-panel {
  179 + width: 100%;
  180 + float: left;
  181 + margin-top: 11px
  182 +}
  183 +
  184 +.comment-panel a:first-child {
  185 + margin-left: 0
  186 +}
  187 +
  188 +.btn-comm-answer, .btn-comm-delete {
  189 + font-size: 13px;
  190 + color: #799920;
  191 + border-bottom: 1px dotted #799920
  192 +}
  193 +
  194 +.btn-comm-answer, .btn-comm-delete, .btn-comm-like, .btn-comm-dislike {
  195 + float: left;
  196 + margin-left: 10px;
  197 + text-decoration: none;
  198 + margin-top: 11px;
  199 +}
  200 +
  201 +.btn-comm-answer, .btn-comm-delete {
  202 + height: 16px;
  203 + line-height: 16px
  204 +}
  205 +
  206 +.btn-comm-answer:hover, .btn-comm-delete:hover {
  207 + text-decoration: none;
  208 + border-bottom: 0
  209 +}
  210 +
  211 +.btn-comm-like, .btn-comm-dislike {
  212 + width: 14px;
  213 + height: 16px;
  214 + background-image: url(../images/like_dislike.png);
  215 + background-repeat: no-repeat
  216 +}
  217 +
  218 +.btn-comm-like {
  219 + background-position: 0 0
  220 +}
  221 +
  222 +.btn-comm-like:hover {
  223 + background-position: 0 -16px
  224 +}
  225 +
  226 +.btn-comm-dislike:hover {
  227 + background-position: -14px -16px
  228 +}
  229 +
  230 +.btn-comm-dislike {
  231 + background-position: -14px 0
  232 +}
  233 +
  234 +.btn-comm-like:active, .btn-comm-dislike:active {
  235 + opacity: .7
  236 +}
  237 +
  238 +.comment-answer {
  239 + margin-top: 40px
  240 +}
  241 +
  242 +.comment-answer .user-ico {
  243 + left: 100px
  244 +}
  245 +
  246 +.comment-answer .user_name, .comment-answer .user_txt, .comment-answer .comment-panel, .comment-answer .user_data {
  247 + padding-left: 200px
  248 +}
  249 +
  250 +.comments-wr {
  251 + margin-top: 40px
  252 +}
  253 +
  254 +.answer-form {
  255 + margin-top: 20px
  256 +}
  257 +
  258 +.answer-form textarea {
  259 + width: 100%;
  260 + height: 90px
  261 +}
  262 +
  263 +.input_bl.has-error input, .input_bl.has-error textarea, .answer-form .has-error textarea {
  264 + box-shadow: 1px 2px 2px 0 rgba(212, 0, 0, 0.2) inset;
  265 + border: 1px solid #d2d2d2;
  266 +}
  267 +
  268 +.required.has-error label {
  269 + color: #d40000 !important;
  270 +}
  271 +
  272 +.input_bl .help-block, .answer-form .help-block {
  273 + display: none
  274 +}
  275 +
  276 +.comments-start .required label:before {
  277 + display: block;
  278 + content: "*";
  279 + color: #d40000;
  280 + position: absolute;
  281 + top: 0;
  282 + right: 3px
  283 +}
  284 +
  285 +.comments-start ul.pagination {
  286 + list-style: none;
  287 + text-align: center;
  288 + margin-top: 40px;
  289 + width: 100%;
  290 + float: left
  291 +}
  292 +
  293 +.comments-start ul.pagination li {
  294 + display: inline
  295 +}
  296 +
  297 +.comments-start ul.pagination li.prev.disabled span {
  298 + display: none
  299 +}
  300 +
  301 +.comments-start ul.pagination li.next.disabled span {
  302 + display: none
  303 +}
  304 +
  305 +.comments-start ul.pagination li a {
  306 + padding: 3px;
  307 + color: #82a02f;
  308 + font-size: 15px;
  309 + margin: 0;
  310 + text-decoration: none;
  311 + float: none;
  312 + border: none;
  313 + backgroun-color: inherit;
  314 +}
  315 +
  316 +.comments-start ul.pagination li.active a {
  317 + color: #333;
  318 + background-color: inherit;
  319 +}
0 320 \ No newline at end of file
... ...
resources/artbox_comment.js 0 → 100755
  1 +++ a/resources/artbox_comment.js
  1 +/**
  2 + * Artbox comment plugin
  3 + *
  4 + * @todo Translate Submit and Loading texts
  5 + */
  6 +(function($)
  7 +{
  8 +
  9 + $.fn.artbox_comment = function(method)
  10 + {
  11 + if(methods[method])
  12 + {
  13 + return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
  14 + } else if(typeof method === 'object' || !method)
  15 + {
  16 + return methods.init.apply(this, arguments);
  17 + } else
  18 + {
  19 + $.error('Method ' + method + ' does not exist on jQuery.comment');
  20 + return false;
  21 + }
  22 + };
  23 +
  24 + // Default settings
  25 + var defaults = {
  26 + formContainerSelector : '.artbox_form_container',
  27 + formSelector : '#artbox-comment-form',
  28 + listContainerSelector : '.artbox_list_container',
  29 + listSelector : '#artbox-comment-list',
  30 + itemContainerSelector : '.artbox_item_container',
  31 + itemInfoSelector : '.artbox_item_info',
  32 + itemToolsSelector : '.artbox_item_tools',
  33 + itemReplySelector : '.artbox_item_reply',
  34 + childrenContainerSelector : '.artbox_children_container',
  35 + childContainerSelector : '.artbox_child_container',
  36 + childInfoSelector : '.artbox_child_info',
  37 + childToolsSelector : '.artbox_child_tools',
  38 + childReplySelector : '.artbox_child_reply',
  39 + replyContainerSelector : '.artbox_comment_reply_container',
  40 + widgetContainerSelector : '.artbox_comment_container'
  41 + };
  42 +
  43 + // Methods
  44 + var methods = {
  45 + init : function(options)
  46 + {
  47 + return this.each(
  48 + function()
  49 + {
  50 + var $commentForm = $(this);
  51 + if($commentForm.data('artbox_comment'))
  52 + {
  53 + return;
  54 + }
  55 + var settings = $.extend({}, defaults, options || {});
  56 + $commentForm.data('artbox_comment', settings);
  57 + //Add events
  58 + var eventParams = {commentForm : $commentForm};
  59 + $commentForm.on('beforeSubmit.artbox_comment', eventParams, beforeSubmitForm);
  60 + $(settings.listSelector).on('beforeSubmit.artbox_comment', settings.formSelector + '-reply', eventParams, reply);
  61 + $(settings.listSelector).on('click.artbox_comment', settings.itemToolsSelector + ' [data-action="reply"]', eventParams, replyInit);
  62 + $(settings.listSelector).on('click.artbox_comment', settings.itemToolsSelector + ' [data-action="reply-cancel"]', eventParams, replyCancel);
  63 + $(settings.listSelector).on('click.artbox_comment', settings.itemToolsSelector + ' [data-action="delete"]', eventParams, deleteComment);
  64 + $(settings.listSelector).on('click.artbox_comment', settings.itemToolsSelector + ' [data-action="like"]', eventParams, like);
  65 + $(settings.listSelector).on('click.artbox_comment', settings.itemToolsSelector + ' [data-action="dislike"]', eventParams, dislike);
  66 + $(settings.listSelector).on('click.artbox_comment', settings.childToolsSelector + ' [data-action="reply"]', eventParams, replyChildInit);
  67 + $(settings.listSelector).on('click.artbox_comment', settings.childToolsSelector + ' [data-action="reply-cancel"]', eventParams, replyCancel);
  68 + $(settings.listSelector).on('click.artbox_comment', settings.childToolsSelector + ' [data-action="delete"]', eventParams, deleteChild);
  69 + $(settings.listSelector).on('click.artbox_comment', settings.childToolsSelector + ' [data-action="like"]', eventParams, likeChild);
  70 + $(settings.listSelector).on('click.artbox_comment', settings.childToolsSelector + ' [data-action="dislike"]', eventParams, dislikeChild);
  71 + }
  72 + );
  73 + },
  74 + data : function()
  75 + {
  76 + return this.data('artbox_comment');
  77 + }
  78 + };
  79 +
  80 + /**
  81 + * Submit reply form
  82 + *
  83 + * @param event
  84 + */
  85 + function reply(event)
  86 + {
  87 + /**
  88 + * @todo Implement
  89 + */
  90 + event.preventDefault();
  91 + var $replyForm = $(this);
  92 + var $commentForm = event.data.commentForm;
  93 + settings = $commentForm.data('artbox_comment');
  94 + $replyForm.find(':submit').prop('disabled', true).text('Загрузка...');
  95 + $.post(
  96 + $replyForm.attr("action"), $replyForm.serialize(), function(data)
  97 + {
  98 + if(data.status == 'success')
  99 + {
  100 + hideForm($commentForm);
  101 + $(settings.listSelector).load(
  102 + ' ' + settings.listSelector, function(data)
  103 + {
  104 + $replyForm.find(':submit').prop('disabled', false).text('Добавить комментарий');
  105 + $replyForm.trigger("reset");
  106 + }
  107 + );
  108 + }
  109 + else
  110 + {
  111 + if(data.hasOwnProperty('errors'))
  112 + {
  113 + $replyForm.yiiActiveForm('updateMessages', data.errors, true);
  114 + } else
  115 + {
  116 + $replyForm.yiiActiveForm('updateAttribute', 'commentmodel-text-reply', [data.message]);
  117 + }
  118 + $replyForm.find(':submit').prop('disabled', false).text('Добавить комментарий');
  119 + }
  120 + }
  121 + );
  122 + return false;
  123 + }
  124 +
  125 + /**
  126 + * Submit comment form
  127 + *
  128 + * @param event
  129 + */
  130 + function beforeSubmitForm(event)
  131 + {
  132 + event.preventDefault();
  133 + var $commentForm = $(this), settings = $commentForm.data('artbox_comment');
  134 + $commentForm.find(':submit').prop('disabled', true).text('Загрузка...');
  135 + $.post(
  136 + $commentForm.attr("action"), $commentForm.serialize(), function(data)
  137 + {
  138 + if(data.status == 'success')
  139 + {
  140 + hideForm($commentForm);
  141 + $(settings.listSelector).load(
  142 + ' ' + settings.listSelector, function(data)
  143 + {
  144 + $commentForm.find(':submit').prop('disabled', false).text('Добавить комментарий');
  145 + $commentForm.trigger("reset");
  146 + }
  147 + );
  148 + }
  149 + else
  150 + {
  151 + if(data.hasOwnProperty('errors'))
  152 + {
  153 + $commentForm.yiiActiveForm('updateMessages', data.errors, true);
  154 + } else
  155 + {
  156 + $commentForm.yiiActiveForm('updateAttribute', 'commentmodel-text', [data.message]);
  157 + }
  158 + $commentForm.find(':submit').prop('disabled', false).text('Добавить комментарий');
  159 + }
  160 + }
  161 + );
  162 + return false;
  163 + }
  164 +
  165 + /**
  166 + * Init reply form
  167 + *
  168 + * @param event
  169 + */
  170 + function replyInit(event)
  171 + {
  172 + event.preventDefault();
  173 + var data = event.data.commentForm.data('artbox_comment');
  174 + var form = $(data.formSelector + '-reply');
  175 + var button = this;
  176 + var item = $(button).parents(data.itemContainerSelector);
  177 + var item_id = $(item).data('key');
  178 + $(form).find('#commentmodel-artbox_comment_pid-reply').val(item_id);
  179 + $(item).find(data.itemReplySelector).append(form);
  180 + }
  181 +
  182 + /**
  183 + * Init reply form
  184 + *
  185 + * @param event
  186 + */
  187 + function replyCancel(event)
  188 + {
  189 + event.preventDefault();
  190 + hideForm(event.data.commentForm);
  191 + }
  192 +
  193 + /**
  194 + * Init reply form
  195 + *
  196 + * @param event
  197 + */
  198 + function deleteComment(event)
  199 + {
  200 + event.preventDefault();
  201 + var data = event.data.commentForm.data('artbox_comment');
  202 + hideForm(event.data.commentForm);
  203 + var button = this;
  204 + var item = $(button).parents(data.itemContainerSelector);
  205 + $.post($(button).data('url'), function(data) {
  206 + if(data.status == 'success')
  207 + {
  208 + $(item).text(data.message);
  209 + }
  210 + else
  211 + {
  212 + console.log(data.message);
  213 + }
  214 + });
  215 + }
  216 +
  217 + /**
  218 + * Init reply form
  219 + *
  220 + * @param event
  221 + */
  222 + function like(event)
  223 + {
  224 + event.preventDefault();
  225 + /**
  226 + * @todo Implement
  227 + */
  228 + }
  229 +
  230 + /**
  231 + * Init reply form
  232 + *
  233 + * @param event
  234 + */
  235 + function dislike(event)
  236 + {
  237 + event.preventDefault();
  238 + /**
  239 + * @todo Implement
  240 + */
  241 + }
  242 +
  243 + /**
  244 + * Init reply form
  245 + *
  246 + * @param event
  247 + */
  248 + function replyChildInit(event)
  249 + {
  250 + event.preventDefault();
  251 + var data = event.data.commentForm.data('artbox_comment');
  252 + var form = $(data.formSelector + '-reply');
  253 + var button = this;
  254 + var item = $(button).parents(data.childContainerSelector);
  255 + var item_id = $(item).data('key');
  256 + $(form).find('#commentmodel-artbox_comment_pid-reply').val(item_id);
  257 + $(item).find(data.childReplySelector).append(form);
  258 + }
  259 +
  260 + /**
  261 + * Init reply form
  262 + *
  263 + * @param event
  264 + */
  265 + function deleteChild(event)
  266 + {
  267 + event.preventDefault();
  268 + var data = event.data.commentForm.data('artbox_comment');
  269 + hideForm(event.data.commentForm);
  270 + var button = this;
  271 + var item = $(button).parents(data.childContainerSelector);
  272 + $.post($(button).data('url'), function(data) {
  273 + if(data.status == 'success')
  274 + {
  275 + $(item).text(data.message);
  276 + }
  277 + else
  278 + {
  279 + console.log(data.message);
  280 + }
  281 + });
  282 + }
  283 +
  284 + /**
  285 + * Init reply form
  286 + *
  287 + * @param event
  288 + */
  289 + function likeChild(event)
  290 + {
  291 + event.preventDefault();
  292 + /**
  293 + * @todo Implement
  294 + */
  295 + }
  296 +
  297 + /**
  298 + * Init reply form
  299 + *
  300 + * @param event
  301 + */
  302 + function dislikeChild(event)
  303 + {
  304 + event.preventDefault();
  305 + /**
  306 + * @todo Implement
  307 + */
  308 + }
  309 +
  310 + function hideForm(commentForm)
  311 + {
  312 + var data = $(commentForm).data('artbox_comment');
  313 + var form = $(data.formSelector+'-reply');
  314 + $(form).parents(data.widgetContainerSelector).find(data.replyContainerSelector).append(form);
  315 + form.trigger('reset');
  316 + }
  317 +
  318 +})(window.jQuery);
... ...
resources/delete.gif 0 → 100755

752 Bytes

resources/jquery.rateit.min.js 0 → 100755
  1 +++ a/resources/jquery.rateit.min.js
  1 +/*! RateIt | v1.0.24 / 06/14/2016
  2 + https://github.com/gjunge/rateit.js | Twitter: @gjunge
  3 +*/
  4 +(function(n){function t(n){var u=n.originalEvent.changedTouches,t=u[0],i="",r;switch(n.type){case"touchmove":i="mousemove";break;case"touchend":i="mouseup";break;default:return}r=document.createEvent("MouseEvent");r.initMouseEvent(i,!0,!0,window,1,t.screenX,t.screenY,t.clientX,t.clientY,!1,!1,!1,!1,0,null);t.target.dispatchEvent(r);n.preventDefault()}n.rateit={aria:{resetLabel:"reset rating",ratingLabel:"rating"}};n.fn.rateit=function(i,r){var e=1,u={},o="init",s=function(n){return n.charAt(0).toUpperCase()+n.substr(1)},f;if(this.length===0)return this;if(f=n.type(i),f=="object"||i===undefined||i===null)u=n.extend({},n.fn.rateit.defaults,i);else{if(f=="string"&&i!=="reset"&&r===undefined)return this.data("rateit"+s(i));f=="string"&&(o="setvalue")}return this.each(function(){var c=n(this),f=function(n,t){if(t!=null){var i="aria-value"+(n=="value"?"now":n),r=c.find(".rateit-range");r.attr(i)!=undefined&&r.attr(i,t)}return arguments[0]="rateit"+s(n),c.data.apply(c,arguments)},p,w,v,h,b,g,nt,l,y,k,a;if(i=="reset"){p=f("init");for(w in p)c.data(w,p[w]);f("backingfld")&&(h=n(f("backingfld")),h.val(f("value")),h.trigger("change"),h[0].min&&(h[0].min=f("min")),h[0].max&&(h[0].max=f("max")),h[0].step&&(h[0].step=f("step")));c.trigger("reset")}if(c.hasClass("rateit")||c.addClass("rateit"),v=c.css("direction")!="rtl",o=="setvalue"){if(!f("init"))throw"Can't set value before init";i!="readonly"||r!=!0||f("readonly")||(c.find(".rateit-range").unbind(),f("wired",!1));i=="value"&&(r=r==null?f("min"):Math.max(f("min"),Math.min(f("max"),r)));f("backingfld")&&(h=n(f("backingfld")),i=="value"&&h.val(r),i=="min"&&h[0].min&&(h[0].min=r),i=="max"&&h[0].max&&(h[0].max=r),i=="step"&&h[0].step&&(h[0].step=r));f(i,r)}f("init")||(f("min",isNaN(f("min"))?u.min:f("min")),f("max",isNaN(f("max"))?u.max:f("max")),f("step",f("step")||u.step),f("readonly",f("readonly")!==undefined?f("readonly"):u.readonly),f("resetable",f("resetable")!==undefined?f("resetable"):u.resetable),f("backingfld",f("backingfld")||u.backingfld),f("starwidth",f("starwidth")||u.starwidth),f("starheight",f("starheight")||u.starheight),f("value",Math.max(f("min"),Math.min(f("max"),isNaN(f("value"))?isNaN(u.value)?u.min:u.value:f("value")))),f("ispreset",f("ispreset")!==undefined?f("ispreset"):u.ispreset),f("backingfld")&&(h=n(f("backingfld")).hide(),(h.attr("disabled")||h.attr("readonly"))&&f("readonly",!0),h[0].nodeName=="INPUT"&&(h[0].type=="range"||h[0].type=="text")&&(f("min",parseInt(h.attr("min"))||f("min")),f("max",parseInt(h.attr("max"))||f("max")),f("step",parseInt(h.attr("step"))||f("step"))),h[0].nodeName=="SELECT"&&h[0].options.length>1?(f("min",isNaN(f("min"))?Number(h[0].options[0].value):f("min")),f("max",Number(h[0].options[h[0].length-1].value)),f("step",Number(h[0].options[1].value)-Number(h[0].options[0].value)),b=h.find("option[selected]"),b.length==1&&f("value",b.val())):f("value",h.val())),g=c[0].nodeName=="DIV"?"div":"span",e++,nt='<button id="rateit-reset-{{index}}" type="button" data-role="none" class="rateit-reset" aria-label="'+n.rateit.aria.resetLabel+'" aria-controls="rateit-range-{{index}}"><\/button><{{element}} id="rateit-range-{{index}}" class="rateit-range" tabindex="0" role="slider" aria-label="'+n.rateit.aria.ratingLabel+'" aria-owns="rateit-reset-{{index}}" aria-valuemin="'+f("min")+'" aria-valuemax="'+f("max")+'" aria-valuenow="'+f("value")+'"><{{element}} class="rateit-selected" style="height:'+f("starheight")+'px"><\/{{element}}><{{element}} class="rateit-hover" style="height:'+f("starheight")+'px"><\/{{element}}><\/{{element}}>',c.append(nt.replace(/{{index}}/gi,e).replace(/{{element}}/gi,g)),v||(c.find(".rateit-reset").css("float","right"),c.find(".rateit-selected").addClass("rateit-selected-rtl"),c.find(".rateit-hover").addClass("rateit-hover-rtl")),f("init",JSON.parse(JSON.stringify(c.data()))));c.find(".rateit-selected, .rateit-hover").height(f("starheight"));l=c.find(".rateit-range");l.width(f("starwidth")*(f("max")-f("min"))).height(f("starheight"));y="rateit-preset"+(v?"":"-rtl");f("ispreset")?c.find(".rateit-selected").addClass(y):c.find(".rateit-selected").removeClass(y);f("value")!=null&&(k=(f("value")-f("min"))*f("starwidth"),c.find(".rateit-selected").width(k));a=c.find(".rateit-reset");a.data("wired")!==!0&&a.bind("click",function(t){t.preventDefault();a.blur();var i=n.Event("beforereset");if(c.trigger(i),i.isDefaultPrevented())return!1;c.rateit("value",null);c.trigger("reset")}).data("wired",!0);var tt=function(t,i){var u=i.changedTouches?i.changedTouches[0].pageX:i.pageX,r=u-n(t).offset().left;return v||(r=l.width()-r),r>l.width()&&(r=l.width()),r<0&&(r=0),k=Math.ceil(r/f("starwidth")*(1/f("step")))},it=function(n){var t=n*f("starwidth")*f("step"),r=l.find(".rateit-hover"),i;r.data("width")!=t&&(l.find(".rateit-selected").hide(),r.width(t).show().data("width",t),i=[n*f("step")+f("min")],c.trigger("hover",i).trigger("over",i))},d=function(t){var i=n.Event("beforerated");return(c.trigger(i,[t]),i.isDefaultPrevented())?!1:(f("value",t),f("backingfld")&&n(f("backingfld")).val(t).trigger("change"),f("ispreset")&&(l.find(".rateit-selected").removeClass(y),f("ispreset",!1)),l.find(".rateit-hover").hide(),l.find(".rateit-selected").width(t*f("starwidth")-f("min")*f("starwidth")).show(),c.trigger("hover",[null]).trigger("over",[null]).trigger("rated",[t]),!0)};f("readonly")?a.hide():(f("resetable")||a.hide(),f("wired")||(l.bind("touchmove touchend",t),l.mousemove(function(n){var t=tt(this,n);it(t)}),l.mouseleave(function(){l.find(".rateit-hover").hide().width(0).data("width","");c.trigger("hover",[null]).trigger("over",[null]);l.find(".rateit-selected").show()}),l.mouseup(function(n){var t=tt(this,n),i=t*f("step")+f("min");d(i);l.blur()}),l.keyup(function(n){(n.which==38||n.which==(v?39:37))&&d(Math.min(f("value")+f("step"),f("max")));(n.which==40||n.which==(v?37:39))&&d(Math.max(f("value")-f("step"),f("min")))}),f("wired",!0)),f("resetable")&&a.show());l.attr("aria-readonly",f("readonly"))})};n.fn.rateit.defaults={min:0,max:5,step:.5,starwidth:16,starheight:16,readonly:!1,resetable:!0,ispreset:!1};n(function(){n("div.rateit, span.rateit").rateit()})})(jQuery);
  5 +/*
  6 +//# sourceMappingURL=jquery.rateit.min.js.map
  7 +*/
... ...
resources/rateit.css 0 → 100755
  1 +++ a/resources/rateit.css
  1 +.rateit {
  2 + display: -moz-inline-box;
  3 + display: inline-block;
  4 + position: relative;
  5 + -webkit-user-select: none;
  6 + -khtml-user-select: none;
  7 + -moz-user-select: none;
  8 + -o-user-select: none;
  9 + -ms-user-select: none;
  10 + user-select: none;
  11 + -webkit-touch-callout: none;
  12 +}
  13 +
  14 +.rateit .rateit-range
  15 +{
  16 + position: relative;
  17 + display: -moz-inline-box;
  18 + display: inline-block;
  19 + background: url(star.gif);
  20 + height: 16px;
  21 + outline: none;
  22 +}
  23 +
  24 +.rateit .rateit-range * {
  25 + display:block;
  26 +}
  27 +
  28 +/* for IE 6 */
  29 +* html .rateit, * html .rateit .rateit-range
  30 +{
  31 + display: inline;
  32 +}
  33 +
  34 +/* for IE 7 */
  35 +* + html .rateit, * + html .rateit .rateit-range
  36 +{
  37 + display: inline;
  38 +}
  39 +
  40 +.rateit .rateit-hover, .rateit .rateit-selected
  41 +{
  42 + position: absolute;
  43 + left: 0px;
  44 +}
  45 +
  46 +.rateit .rateit-hover-rtl, .rateit .rateit-selected-rtl
  47 +{
  48 + left: auto;
  49 + right: 0px;
  50 +}
  51 +
  52 +.rateit .rateit-hover
  53 +{
  54 + background: url(star.gif) left -32px;
  55 +}
  56 +
  57 +.rateit .rateit-hover-rtl
  58 +{
  59 + background-position: right -32px;
  60 +}
  61 +
  62 +.rateit .rateit-selected
  63 +{
  64 + background: url(star.gif) left -16px;
  65 +}
  66 +
  67 +.rateit .rateit-selected-rtl
  68 +{
  69 + background-position: right -16px;
  70 +}
  71 +
  72 +.rateit .rateit-preset
  73 +{
  74 + background: url(star.gif) left -48px;
  75 +}
  76 +
  77 +.rateit .rateit-preset-rtl
  78 +{
  79 + background: url(star.gif) left -48px;
  80 +}
  81 +
  82 +.rateit button.rateit-reset
  83 +{
  84 + background: url(delete.gif) 0 0;
  85 + width: 16px;
  86 + height: 16px;
  87 + display: -moz-inline-box;
  88 + display: inline-block;
  89 + float: left;
  90 + outline: none;
  91 + border:none;
  92 + padding: 0;
  93 +}
  94 +
  95 +.rateit button.rateit-reset:hover, .rateit button.rateit-reset:focus
  96 +{
  97 + background-position: 0 -16px;
  98 +}
... ...
resources/star.gif 0 → 100755

2.4 KB

todo 0 → 100755
  1 +++ a/todo
  1 +Сделать:
  2 +1. Реализовать действия.
  3 +2. Добавить RBAC.
  4 +3. Добавить рейтинг.
  5 +4. Добавить модерацию.
  6 +5. Добавить соц сети.
  7 +6. Добавить "пожаловаться".
  8 +7. Добавить установщик.
  9 +8. Добавить PJAX.
  10 +9. Добавить приколы.
  11 +10. Добавить возможность бана.
  12 +11. Предусмотреть удаление пользователя (что делать с его комментариями).
  13 +12. Добавить базовую верстку bootstrap / nonbootstrap.
  14 +13. Добавить возможность использования кастомной модели комментариев.
  15 +14. Реализовать мультиязычность.
  16 +15. Добавить возможность изменения макета (layout) функцией (Вместо "{form}{list}" добавить возможность function($parts, $view ...)).
  17 +16. Добавить сортировку.
  18 +17. Сделать навигацию по ссылкам related как на Youtube.
  19 +
  20 +Действия:
  21 +1. Добавить
  22 +2. Редактировать
  23 +3. Ответить
  24 +4. Like / dislike
  25 +5. Удалить
  26 +
  27 +Таблица (artbox_comment):
  28 +artbox_comment_id primary_key
  29 +text text
  30 +user_id int foreign key
  31 +username string
  32 +email string
  33 +created_at int notNull
  34 +updated_at int notNull
  35 +deleted_at int notNull
  36 +status int notNull default(1)
  37 +comment_pid int foreign_key
  38 +related_id int foreign key
  39 +ip string notNull
  40 +info text
  41 +
  42 +Таблица (artbox_comment_like):
  43 +artbox_comment_like_id primary_key
  44 +artbox_comment_id int foreign key
  45 +user_id int foreign key
  46 +created_at int notNull
  47 +is_like int notNull default(1)
  48 +
  49 +Приколы:
  50 +1. Рандомная генерация изображений
  51 +2. Смайлы
0 52 \ No newline at end of file
... ...
views/artbox_comment_form.php 0 → 100755
  1 +++ a/views/artbox_comment_form.php
  1 +<?php
  2 + use artweb\artbox\comment\models\CommentModel;
  3 + use artweb\artbox\comment\models\RatingModel;
  4 + use yii\base\Model;
  5 + use yii\helpers\Html;
  6 + use yii\helpers\Url;
  7 + use yii\web\View;
  8 + use yii\widgets\ActiveForm;
  9 +
  10 + /**
  11 + * @var CommentModel $comment_model
  12 + * @var array $form_params
  13 + * @var Model $model
  14 + * @var string $formId
  15 + * @var View $this
  16 + * @var RatingModel|NULL $rating_model
  17 + */
  18 + $form = ActiveForm::begin([
  19 + 'id' => $formId,
  20 + 'action' => Url::to([
  21 + 'artbox-comment/default/create',
  22 + 'entity' => $comment_model->encryptedEntity,
  23 + ]),
  24 + ]);
  25 +?>
  26 + <div class="form-comm-wr">
  27 + <?php
  28 + if(!empty( $rating_model )) {
  29 + ?>
  30 + <div class="input_bl stars-wr_">
  31 + <?php
  32 + echo $form->field($rating_model, 'value', [ 'enableClientValidation' => false ])
  33 + ->hiddenInput()
  34 + ->label(false);
  35 + echo Html::tag('div', '', [
  36 + 'class' => 'rateit',
  37 + 'data-rateit-backingfld' => '#' . Html::getInputId($rating_model, 'value'),
  38 + ]);
  39 + ?>
  40 + </div>
  41 + <?php
  42 + }
  43 + if(\Yii::$app->user->isGuest) {
  44 + echo $form->field($comment_model, 'username', [ 'options' => [ 'class' => 'form-group input_bl' ] ])
  45 + ->textInput();
  46 + echo $form->field($comment_model, 'email', [ 'options' => [ 'class' => 'form-group input_bl' ] ])
  47 + ->textInput();
  48 + }
  49 + echo $form->field($comment_model, 'text', [ 'options' => [ 'class' => 'form-group input_bl area_bl' ] ])
  50 + ->textarea();
  51 + echo Html::tag('div', Html::submitButton(Yii::t('artbox-comment', 'Submit')), [ 'class' => 'input_bl submit_btn' ]);
  52 + ?>
  53 + </div>
  54 +<?php
  55 + ActiveForm::end();
  56 +?>
0 57 \ No newline at end of file
... ...
views/artbox_comment_item.php 0 → 100755
  1 +++ a/views/artbox_comment_item.php
  1 +<?php
  2 + use artweb\artbox\comment\models\CommentModel;
  3 + use yii\helpers\Html;
  4 + use yii\helpers\Url;
  5 + use yii\widgets\ListView;
  6 +
  7 + /**
  8 + * @var CommentModel $model
  9 + * @var mixed $key
  10 + * @var int $index
  11 + * @var ListView $widget
  12 + */
  13 +?>
  14 +<div class="comments-wr">
  15 + <div class="artbox_item_info">
  16 + <div class="user-ico">
  17 + <?php
  18 + echo Html::img('/img/user-noimage.png');
  19 + ?>
  20 + </div>
  21 + <div class="user_data" itemprop="datePublished">
  22 + <?php
  23 + echo date('d.m.Y', $model->created_at);
  24 + ?>
  25 + </div>
  26 + <div class="user_name" itemprop="author">
  27 + <?php
  28 + if(!empty( $model->user )) {
  29 + echo $model->user->username;
  30 + } else {
  31 + echo $model->username . ' (' . Yii::t('artbox-comment', 'Guest') . ')';
  32 + }
  33 + ?>
  34 + </div>
  35 + <?php
  36 + if(!empty( $model->rating )) {
  37 + ?>
  38 + <div class="user_rating" itemprop="reviewRating" itemscope itemtype="http://schema.org/Rating">
  39 + <span itemprop="worstRating" style="display: none">1</span>
  40 + <span itemprop="ratingValue" style="display: none"><?php echo $model->rating->value; ?></span>
  41 + <span itemprop="bestRating" style="display: none">5</span>
  42 + <div class="rateit" data-rateit-value="<?php echo $model->rating->value; ?>" data-rateit-ispreset="true" data-rateit-readonly="true"></div>
  43 + </div>
  44 + <?php
  45 + }
  46 + ?>
  47 + <div class="user_txt" itemprop="description">
  48 + <?php
  49 + echo $model->text;
  50 + ?>
  51 + </div>
  52 + </div>
  53 + <div class="artbox_item_tools comment-panel">
  54 + <?php
  55 + if(!\Yii::$app->user->isGuest) {
  56 + ?>
  57 + <a href="" class="btn-comm-answer" data-action="reply">Ответить</a>
  58 + <?php
  59 + }
  60 + if(!\Yii::$app->user->isGuest && \Yii::$app->user->id == $model->user_id) {
  61 + ?>
  62 + <a href="" class="btn-comm-delete" data-action="delete" data-url="<?php echo Url::to([
  63 + 'artbox-comment/default/delete',
  64 + 'id' => $model->artbox_comment_id,
  65 + ]); ?>">Удалить</a>
  66 + <?php
  67 + }
  68 + // Like / dislike to be done
  69 + /*
  70 + ?>
  71 + <a href="" class="btn-comm-like" data-action="like" data-url="<?php echo Url::to([
  72 + 'artbox-comment/default/like',
  73 + 'id' => $model->artbox_comment_id,
  74 + ]); ?>">Like</a>
  75 + <a href="" class="btn-comm-dislike" data-action="dislike" data-url="<?php echo Url::to([
  76 + 'artbox-comment/default/dislike',
  77 + 'id' => $model->artbox_comment_id,
  78 + ]); ?>">Dislike</a>
  79 + <?php
  80 + */
  81 + ?>
  82 + <div class="artbox_item_reply"></div>
  83 + </div>
  84 +</div>
  85 +<div class="artbox_children_container">
  86 + <?php
  87 + if(!empty( $model->children )) {
  88 + foreach($model->children as $index => $child) {
  89 + ?>
  90 + <div class="artbox_child_container comment-answer">
  91 + <div class="artbox_child_info">
  92 + <div class="user-ico">
  93 + <?php
  94 + echo Html::img('/img/user-noimage.png');
  95 + ?>
  96 + </div>
  97 + <div class="user_data">
  98 + <?php
  99 + echo date('d.m.Y', $child->created_at);
  100 + ?>
  101 + </div>
  102 + <div class="user_name">
  103 + <?php
  104 + if(!empty( $child->user )) {
  105 + echo $child->user->username;
  106 + } else {
  107 + echo $child->username . ' (' . Yii::t('artbox-comment', 'Guest') . ')';
  108 + }
  109 + ?>
  110 + </div>
  111 + <div class="user_txt">
  112 + <?php
  113 + echo $child->text;
  114 + ?>
  115 + </div>
  116 + </div>
  117 + <div class="artbox_child_tools comment-panel">
  118 + <?php
  119 + if(!\Yii::$app->user->isGuest) {
  120 + ?>
  121 + <a href="" class="btn-comm-answer" data-action="reply">Ответить</a>
  122 + <?php
  123 + }
  124 + if(!\Yii::$app->user->isGuest && \Yii::$app->user->id == $child->user_id) {
  125 + ?>
  126 + <a href="" class="btn-comm-delete" data-action="delete" data-url="<?php echo Url::to([
  127 + 'artbox-comment/default/delete',
  128 + 'id' => $child->artbox_comment_id,
  129 + ]); ?>">Удалить</a>
  130 + <?php
  131 + }
  132 + /* Like /dislike to be done
  133 + ?>
  134 + <a href="" class="btn-comm-like" data-action="like" data-url="<?php echo Url::to([
  135 + 'artbox-comment/default/like',
  136 + 'id' => $child->artbox_comment_id,
  137 + ]); ?>">Like</a>
  138 + <a href="" class="btn-comm-dislike" data-action="dislike" data-url="<?php echo Url::to([
  139 + 'artbox-comment/default/dislike',
  140 + 'id' => $child->artbox_comment_id,
  141 + ]); ?>">Dislike</a>
  142 + <?php
  143 + */
  144 + ?>
  145 + <div class="artbox_child_reply"></div>
  146 + </div>
  147 + </div>
  148 + <?php
  149 + }
  150 + }
  151 + ?>
  152 +</div>
  153 +
... ...
views/artbox_comment_list.php 0 → 100755
  1 +++ a/views/artbox_comment_list.php
  1 +<?php
  2 + use artweb\artbox\comment\models\CommentModel;
  3 + use yii\base\Model;
  4 + use yii\data\ActiveDataProvider;
  5 + use yii\helpers\Html;
  6 + use yii\web\View;
  7 + use yii\widgets\ListView;
  8 + use yii\widgets\Pjax;
  9 +
  10 + /**
  11 + * @var CommentModel $comment_model
  12 + * @var array $list_params
  13 + * @var array $item_options
  14 + * @var string $item_view
  15 + * @var Model $model
  16 + * @var ActiveDataProvider $comments
  17 + * @var View $this
  18 + */
  19 + Pjax::begin();
  20 + if(( $success = \Yii::$app->session->getFlash('artbox_comment_success') ) != NULL) {
  21 + echo Html::tag('p', $success);
  22 + }
  23 + echo ListView::widget([
  24 + 'dataProvider' => $comments,
  25 + 'itemOptions' => $item_options,
  26 + 'itemView' => $item_view,
  27 + 'summary' => '',
  28 + ]);
  29 + Pjax::end();
  30 +
0 31 \ No newline at end of file
... ...
views/artbox_comment_reply.php 0 → 100755
  1 +++ a/views/artbox_comment_reply.php
  1 +<?php
  2 + use artweb\artbox\comment\models\CommentModel;
  3 + use yii\base\Model;
  4 + use yii\helpers\Html;
  5 + use yii\helpers\Url;
  6 + use yii\web\View;
  7 + use yii\widgets\ActiveForm;
  8 +
  9 + /**
  10 + * @var CommentModel $comment_model
  11 + * @var array $form_params
  12 + * @var Model $model
  13 + * @var string $formId
  14 + * @var View $this
  15 + */
  16 + $text_input_id = Html::getInputId($comment_model, 'text') . '-reply';
  17 + $artbox_comment_pid_input_id = Html::getInputId($comment_model, 'artbox_comment_pid') . '-reply';
  18 + $text_input_selectors = [
  19 + 'container' => '.field-' . $text_input_id,
  20 + 'input' => '#' . $text_input_id,
  21 + ];
  22 + $artbox_comment_pid_input_selectors = [
  23 + 'container' => '.field-' . $artbox_comment_pid_input_id,
  24 + 'input' => '#' . $artbox_comment_pid_input_id,
  25 + ];
  26 + $form = ActiveForm::begin([
  27 + 'id' => $formId . '-reply',
  28 + 'action' => Url::to([
  29 + 'artbox-comment/default/create',
  30 + 'entity' => $comment_model->encryptedEntity,
  31 + ]),
  32 + ]);
  33 +?>
  34 + <div class="answer-form">
  35 + <?php
  36 + echo $form->field($comment_model, 'artbox_comment_pid', [
  37 + 'selectors' => $artbox_comment_pid_input_selectors,
  38 + 'inputOptions' => [
  39 + 'id' => $artbox_comment_pid_input_id,
  40 + 'class' => 'form-control',
  41 + ],
  42 + ])
  43 + ->hiddenInput()
  44 + ->label(false);
  45 + echo $form->field($comment_model, 'text', [
  46 + 'selectors' => $text_input_selectors,
  47 + 'inputOptions' => [
  48 + 'id' => $text_input_id,
  49 + 'class' => 'form-control',
  50 + 'cols' => 30,
  51 + 'rows' => 10,
  52 + ],
  53 + ])
  54 + ->textarea();
  55 + echo Html::submitButton(Yii::t('artbox-comment', 'Submit'));
  56 + echo Html::button(Yii::t('artbox-comment', 'Cancel'), [ 'data-action' => 'reply-cancel' ]);
  57 + ?>
  58 + </div>
  59 +<?php
  60 + ActiveForm::end();
  61 +?>
0 62 \ No newline at end of file
... ...
views/manage/index.php 0 → 100755
  1 +++ a/views/manage/index.php
  1 +<?php
  2 + use artweb\artbox\comment\models\CommentModelSearch;
  3 + use yii\data\ActiveDataProvider;
  4 + use yii\grid\GridView;
  5 + use yii\helpers\Html;
  6 + use yii\widgets\Pjax;
  7 +
  8 + /**
  9 + * @var ActiveDataProvider $dataProvider
  10 + * @var CommentModelSearch $searchModel
  11 + * @var string $commentModel
  12 + */
  13 + $statuses = [
  14 + $searchModel::STATUS_ACTIVE => 'Активный',
  15 + $searchModel::STATUS_HIDDEN => 'Скрытый',
  16 + $searchModel::STATUS_DELETED => 'Удаленный',
  17 + ];
  18 + Pjax::begin();
  19 + if(( $success = \Yii::$app->session->getFlash('artbox_comment_success') ) != NULL) {
  20 + echo Html::tag('p', $success);
  21 + }
  22 + echo GridView::widget([
  23 + 'dataProvider' => $dataProvider,
  24 + 'filterModel' => $searchModel,
  25 + 'columns' => [
  26 + [
  27 + 'class' => 'yii\grid\ActionColumn',
  28 + 'template' => '{update} {delete}',
  29 + ],
  30 + [
  31 + 'attribute' => 'artbox_comment_id',
  32 + 'label' => 'Идентификатор',
  33 + ],
  34 + [
  35 + 'attribute' => 'created_at',
  36 + 'format' => [
  37 + 'date',
  38 + 'php:d.m.Y',
  39 + ],
  40 + 'filter' => false,
  41 + ],
  42 + 'text:text',
  43 + [
  44 + 'attribute' => 'user_id',
  45 + 'value' => function($model) {
  46 + if(!empty( $model->user_id )) {
  47 + return $model->user->username . ' (id:' . $model->user->id . ')';
  48 + } else {
  49 + return $model->username . ' ' . $model->email . ' (Гость)';
  50 + }
  51 + },
  52 + ],
  53 + [
  54 + 'attribute' => 'status',
  55 + 'filter' => $statuses,
  56 + 'value' => function($model) use ($statuses) {
  57 + return $statuses[ $model->status ];
  58 + },
  59 + ],
  60 + [
  61 + 'attribute' => 'ratingValue',
  62 + 'value' => function($model) {
  63 + if(!empty( $model->rating )) {
  64 + return $model->rating->value;
  65 + }
  66 + return NULL;
  67 + },
  68 + ],
  69 + 'entity',
  70 + 'entity_id',
  71 + [
  72 + 'attribute' => 'childrenCount',
  73 + 'value' => function($model) {
  74 + return count($model->children);
  75 + },
  76 + ],
  77 + ],
  78 + ]);
  79 + Pjax::end();
0 80 \ No newline at end of file
... ...
views/manage/update.php 0 → 100755
  1 +++ a/views/manage/update.php
  1 +<?php
  2 + use artweb\artbox\comment\models\CommentModel;
  3 + use yii\helpers\Html;
  4 + use yii\widgets\ActiveForm;
  5 +
  6 + /**
  7 + * @var CommentModel $model
  8 + */
  9 + $statuses = [
  10 + $model::STATUS_ACTIVE => 'Активный',
  11 + $model::STATUS_HIDDEN => 'Скрытый',
  12 + $model::STATUS_DELETED => 'Удаленный',
  13 + ];
  14 + $form = ActiveForm::begin();
  15 + echo $form->field($model, 'text')
  16 + ->textarea();
  17 + echo $form->field($model, 'status')
  18 + ->dropDownList($statuses);
  19 + echo Html::submitButton('Обновить');
  20 + $form->end();
0 21 \ No newline at end of file
... ...
widgets/CommentWidget.php 0 → 100755
  1 +++ a/widgets/CommentWidget.php
  1 +<?php
  2 +
  3 + namespace artweb\artbox\comment\widgets;
  4 +
  5 + use artweb\artbox\comment\assets\CommentAsset;
  6 + use artweb\artbox\comment\models\interfaces\CommentInterface;
  7 + use artweb\artbox\comment\models\RatingModel;
  8 + use artweb\artbox\comment\Module;
  9 + use Yii;
  10 + use yii\base\InvalidConfigException;
  11 + use yii\base\Model;
  12 + use yii\base\Widget;
  13 + use yii\data\ActiveDataProvider;
  14 + use yii\db\ActiveRecord;
  15 + use yii\helpers\ArrayHelper;
  16 + use yii\helpers\Html;
  17 + use yii\helpers\Json;
  18 +
  19 + /**
  20 + * Class CommentWidget
  21 + * @property Model $model Model, to which comment attached
  22 + * @package artweb\artbox\comment\widgets
  23 + */
  24 + class CommentWidget extends Widget
  25 + {
  26 +
  27 + /**
  28 + * Model, to which comment attached
  29 + * @var Model Model
  30 + */
  31 + //public $model;
  32 +
  33 + /**
  34 + * Options
  35 + * @var array
  36 + */
  37 + public $options = [
  38 + 'class' => 'artbox_comment_container comments-start',
  39 + 'id' => 'artbox-comment',
  40 + ];
  41 +
  42 + /**
  43 + * @var string the view file that will render comment form.
  44 + */
  45 + public $formView = '@artbox-comment/views/artbox_comment_form';
  46 +
  47 + /**
  48 + * Form options
  49 + * @var array
  50 + */
  51 + public $formOptions = [
  52 + 'class' => 'artbox_form_container',
  53 + ];
  54 +
  55 + /**
  56 + * Params to be passed to form
  57 + * @var array
  58 + */
  59 + public $formParams = [];
  60 +
  61 + /**
  62 + * @var string the view file that will render comments list.
  63 + */
  64 + public $listView = '@artbox-comment/views/artbox_comment_list';
  65 +
  66 + /**
  67 + * List options
  68 + * @var array
  69 + */
  70 + public $listOptions = [
  71 + 'class' => 'artbox_list_container',
  72 + ];
  73 +
  74 + /**
  75 + * List params
  76 + * @var array
  77 + */
  78 + public $listParams = [];
  79 +
  80 + /**
  81 + * Reply options
  82 + * @var array
  83 + */
  84 + public $replyOptions = [
  85 + 'style' => 'display: none;',
  86 + 'class' => 'artbox_comment_reply_container',
  87 + ];
  88 +
  89 + /**
  90 + * Reply view
  91 + * @var string
  92 + */
  93 + public $replyView = '@artbox-comment/views/artbox_comment_reply';
  94 +
  95 + /**
  96 + * Comment form ID. If you have multiple forms on the same page, please use unique IDs.
  97 + * @var string Form ID
  98 + */
  99 + public $formId = 'artbox-comment-form';
  100 +
  101 + /**
  102 + * Comment list ID. If you have multiple forms on the same page, please use unique IDs.
  103 + * @var string List ID
  104 + */
  105 + public $listId = 'artbox-comment-list';
  106 +
  107 + /**
  108 + * Item view
  109 + * @var string
  110 + */
  111 + public $itemView = '@artbox-comment/views/artbox_comment_item';
  112 +
  113 + /**
  114 + * Item options
  115 + * @var array
  116 + */
  117 + public $itemOptions = [
  118 + 'class' => 'artbox_item_container',
  119 + 'itemprop' => 'review',
  120 + 'itemscope' => 'itemscope',
  121 + 'itemtype' => 'http://schema.org/Review',
  122 + ];
  123 +
  124 + /**
  125 + * Entity ID attribute, default to primaryKey() if ActiveRecord and throws exception if not
  126 + * set
  127 + * @var string entity id attribute
  128 + */
  129 + public $entityIdAttribute;
  130 +
  131 + /**
  132 + * Info to be passed to Comment Model
  133 + * @var string $info Additional info
  134 + */
  135 + public $info = NULL;
  136 +
  137 + /**
  138 + * Client options to be passed to JS
  139 + * @var array comment widget client options
  140 + */
  141 + public $clientOptions = [];
  142 +
  143 + /**
  144 + * @todo Check if needed
  145 + * @var string pjax container id
  146 + */
  147 + public $pjaxContainerId;
  148 +
  149 + public $layout = "<div class='comments-border'></div>{form} {reply_form} {list}";
  150 +
  151 + /**
  152 + * Model fully namespaced classname
  153 + * @var string Model namespace
  154 + */
  155 + protected $entity;
  156 +
  157 + /**
  158 + * Entity ID for attached model
  159 + * @var integer Entity ID
  160 + */
  161 + protected $entityId;
  162 +
  163 + /**
  164 + * Encrypted data to be passed to Controller. Consist of:
  165 + * * Model::className()
  166 + * * entityId
  167 + * * info (optional)
  168 + * @var string encrypted entity key
  169 + */
  170 + protected $encryptedEntityKey;
  171 +
  172 + /**
  173 + * Parts for widget
  174 + * @var array $parts
  175 + */
  176 + protected $parts;
  177 +
  178 + /**
  179 + * Initializes the widget params.
  180 + */
  181 + public function init()
  182 + {
  183 + // Module init
  184 + Yii::$app->getModule(Module::$name);
  185 + // Model init
  186 + $model = $this->getModel();
  187 +
  188 + /**
  189 + * @todo Check if needed
  190 + */
  191 + if(empty( $this->pjaxContainerId )) {
  192 + $this->pjaxContainerId = 'comment-pjax-container-' . $this->getId();
  193 + }
  194 +
  195 + $this->entity = $model::className();
  196 + // Entity ID init
  197 + if(!empty( $this->entityIdAttribute ) && $this->model->hasProperty($this->entityIdAttribute)) {
  198 + $this->entityId = $this->model->{$this->entityIdAttribute};
  199 + } else {
  200 + if($this->model instanceof ActiveRecord && !empty( $this->model->getPrimaryKey() )) {
  201 + $this->entityId = (int) $this->model->getPrimaryKey();
  202 + } else {
  203 + throw new InvalidConfigException(/*Yii::t('artbox-comment', 'The "entityIdAttribute" value for widget model cannot be empty.')*/);
  204 + }
  205 + }
  206 +
  207 + // Generate encryptedEntityKey
  208 + $this->encryptedEntityKey = $this->generateEntityKey();
  209 +
  210 + $this->registerAssets();
  211 + }
  212 +
  213 + /**
  214 + * Executes the widget.
  215 + * @return string the result of widget execution to be outputted.
  216 + */
  217 + public function run()
  218 + {
  219 + /* @var Module $module */
  220 + $module = Yii::$app->getModule(Module::$name);
  221 + $commentModelClass = $module->commentModelClass;
  222 + $commentModel = $this->createModel($commentModelClass, [
  223 + 'entity' => $this->entity,
  224 + 'entityId' => $this->entityId,
  225 + 'encryptedEntity' => $this->encryptedEntityKey,
  226 + 'scenario' => \Yii::$app->user->getIsGuest() ? $commentModelClass::SCENARIO_GUEST : $commentModelClass::SCENARIO_USER,
  227 + ]);
  228 + if($module::$enableRating) {
  229 + $ratingModelClass = $module->ratingModelClass;
  230 + $ratingModel = $this->createRating($ratingModelClass);
  231 + } else {
  232 + $ratingModel = NULL;
  233 + }
  234 +
  235 + $comments = $commentModelClass::getTree($this->entity, $this->entityId);
  236 +
  237 + $this->buildParts($commentModel, $comments, $ratingModel);
  238 +
  239 + return $this->renderWidget();
  240 + }
  241 +
  242 + /**
  243 + * Register assets.
  244 + */
  245 + protected function registerAssets()
  246 + {
  247 + $this->clientOptions[ 'formSelector' ] = '#' . $this->formId;
  248 + $this->clientOptions[ 'listSelector' ] = '#' . $this->listId;
  249 + $options = Json::encode($this->clientOptions);
  250 + $view = $this->getView();
  251 + CommentAsset::register($view);
  252 + $view->registerJs("jQuery('#{$this->formId}').artbox_comment({$options});");
  253 + }
  254 +
  255 + /**
  256 + * Get encrypted entity key
  257 + * @return string
  258 + */
  259 + protected function generateEntityKey()
  260 + {
  261 + return Yii::$app->getSecurity()
  262 + ->encryptByKey(Json::encode([
  263 + 'entity' => $this->entity,
  264 + 'entity_id' => $this->entityId,
  265 + 'info' => $this->info,
  266 + ]), Module::$encryptionKey);
  267 + }
  268 +
  269 + /**
  270 + * Create comment model
  271 + *
  272 + * @param string $className Full namespaced model
  273 + * @param array $config Init config
  274 + *
  275 + * @return CommentInterface Comment model
  276 + * @throws InvalidConfigException If object not instance of \yii\base\Model
  277 + */
  278 + protected function createModel(string $className, array $config = []): CommentInterface
  279 + {
  280 + $options = array_merge($config, [ 'class' => $className ]);
  281 + $object = Yii::createObject($options);
  282 + if($object instanceof CommentInterface) {
  283 + return $object;
  284 + }
  285 + throw new InvalidConfigException(/*Yii::t(\'artbox-comment\', \'Comment model must be instance of CommentInterface.\')*/);
  286 + }
  287 +
  288 + /**
  289 + * Create rating model
  290 + *
  291 + * @param string $className Full namespaced model
  292 + * @param array $config Init config
  293 + *
  294 + * @return CommentInterface|RatingModel Comment model
  295 + * @throws InvalidConfigException If object not instance of \yii\base\Model
  296 + */
  297 + protected function createRating(string $className, array $config = []): RatingModel
  298 + {
  299 + $options = array_merge($config, [ 'class' => $className ]);
  300 + $object = Yii::createObject($options);
  301 + if($object instanceof RatingModel) {
  302 + return $object;
  303 + }
  304 + throw new InvalidConfigException(Yii::t('artbox-comment', 'Comment model must be instance of RatingModel.'));
  305 + }
  306 +
  307 + /**
  308 + * Build parts for rendering widget
  309 + *
  310 + * @param CommentInterface $commentModel
  311 + * @param ActiveDataProvider $comments
  312 + * @param null|RatingModel $ratingModel
  313 + */
  314 + protected function buildParts(CommentInterface $commentModel, ActiveDataProvider $comments, $ratingModel = NULL)
  315 + {
  316 + $form_options = $this->formOptions;
  317 + $this->parts[ 'form' ] = Html::tag(ArrayHelper::remove($form_options, 'tag', 'div'), $this->render($this->formView, [
  318 + 'comment_model' => $commentModel,
  319 + 'form_params' => $this->formParams,
  320 + 'model' => $this->getModel(),
  321 + 'formId' => $this->formId,
  322 + 'rating_model' => $ratingModel,
  323 + ]), $form_options);
  324 +
  325 + if(!\Yii::$app->user->isGuest) {
  326 + $reply_options = $this->replyOptions;
  327 + $this->parts[ 'reply_form' ] = Html::tag(ArrayHelper::remove($reply_options, 'tag', 'div'), $this->render($this->replyView, [
  328 + 'comment_model' => $commentModel,
  329 + 'form_params' => $this->formParams,
  330 + 'model' => $this->getModel(),
  331 + 'formId' => $this->formId,
  332 + ]), $reply_options);
  333 + }
  334 +
  335 + $list_options = array_merge($this->listOptions, [ 'id' => $this->listId ]);
  336 + $this->parts[ 'list' ] = Html::tag(ArrayHelper::remove($list_options, 'tag', 'div'), $this->render($this->listView, [
  337 + 'comment_model' => $commentModel,
  338 + 'list_params' => $this->listParams,
  339 + 'model' => $this->getModel(),
  340 + 'comments' => $comments,
  341 + 'item_options' => $this->itemOptions,
  342 + 'item_view' => $this->itemView,
  343 + ]), $list_options);
  344 + }
  345 +
  346 + /**
  347 + * @return string
  348 + */
  349 + protected function renderWidget(): string
  350 + {
  351 + $layout = $this->layout;
  352 + $parts = $this->parts;
  353 + $options = $this->options;
  354 + $layout = preg_replace('/{list}/', ArrayHelper::getValue($parts, 'list', ''), $layout);
  355 + $layout = preg_replace('/{form}/', ArrayHelper::getValue($parts, 'form', ''), $layout);
  356 + $layout = preg_replace('/{reply_form}/', ArrayHelper::getValue($parts, 'reply_form', ''), $layout);
  357 + $tag = ArrayHelper::remove($options, 'tag', 'div');
  358 + return Html::tag($tag, $layout, $options);
  359 + }
  360 +
  361 + public function setModel(Model $model)
  362 + {
  363 + $this->model = $model;
  364 + }
  365 +
  366 + public function getModel(): Model
  367 + {
  368 + if(!empty( $this->model )) {
  369 + return $this->model;
  370 + }
  371 + throw new InvalidConfigException(/*Yii::t(\'artbox-comment\', \'The "model" property must be set.\')*/);
  372 + }
  373 + }
0 374 \ No newline at end of file
... ...