Commit a2cde075db985ec267c8d896e5abb034a750930e
0 parents
first commit
Showing
31 changed files
with
2992 additions
and
0 deletions
Show diff stats
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 | + } | ... | ... |
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 | ... | ... |
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 | ... | ... |
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 | ... | ... |
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 | ... | ... |
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 | ... | ... |
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 | + ]; | ... | ... |
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 | + ]; | ... | ... |
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 | + ]; | ... | ... |
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 | + } | ... | ... |
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 | + } | ... | ... |
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 | ... | ... |
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 | + } | ... | ... |
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 | ... | ... |
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 | + } | ... | ... |
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 | ... | ... |
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 | ... | ... |
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); | ... | ... |
752 Bytes
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 | +*/ | ... | ... |
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 | +} | ... | ... |
2.4 KB
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 | ... | ... |
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 | ... | ... |
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 | + | ... | ... |
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 | ... | ... |
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 | ... | ... |
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 | ... | ... |
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 | ... | ... |
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 | ... | ... |