Blame view

widgets/CommentWidget.php 14.7 KB
a2cde075   Yarik   first commit
1
2
  <?php
      
faff2c48   Yarik   Artbox comment cr...
3
      namespace artbox\webcomment\widgets;
a2cde075   Yarik   first commit
4
      
faff2c48   Yarik   Artbox comment cr...
5
6
7
8
9
      use artbox\webcomment\assets\CommentAsset;
      use artbox\webcomment\models\CommentModel;
      use artbox\webcomment\models\interfaces\CommentInterface;
      use artbox\webcomment\models\RatingModel;
      use artbox\webcomment\Module;
a2cde075   Yarik   first commit
10
11
12
13
14
15
16
17
18
19
20
21
      use Yii;
      use yii\base\InvalidConfigException;
      use yii\base\Model;
      use yii\base\Widget;
      use yii\data\ActiveDataProvider;
      use yii\db\ActiveRecord;
      use yii\helpers\ArrayHelper;
      use yii\helpers\Html;
      use yii\helpers\Json;
      
      /**
       * Class CommentWidget
faff2c48   Yarik   Artbox comment cr...
22
       *
a2cde075   Yarik   first commit
23
       * @property Model $model Model, to which comment attached
a2cde075   Yarik   first commit
24
25
26
       */
      class CommentWidget extends Widget
      {
179a0e00   Anastasia   bug fix artbox-co...
27
28
29
30
31
32
      
          /**
           * @var bool display reply and delete links
           */
          public $reply = true;
          public $delete = true;
b5639b59   Anastasia   comment widget
33
34
35
          /**
           * @var string what field is displayed in the user name
           */
179a0e00   Anastasia   bug fix artbox-co...
36
37
          
          
b5639b59   Anastasia   comment widget
38
          public $display_name = 'username';
a2cde075   Yarik   first commit
39
40
41
          
          /**
           * Model, to which comment attached
faff2c48   Yarik   Artbox comment cr...
42
           *
a2cde075   Yarik   first commit
43
44
45
46
47
48
           * @var Model Model
           */
          //public $model;
          
          /**
           * Options
faff2c48   Yarik   Artbox comment cr...
49
           *
a2cde075   Yarik   first commit
50
51
52
53
54
55
56
57
58
59
           * @var array
           */
          public $options = [
              'class' => 'artbox_comment_container comments-start',
              'id'    => 'artbox-comment',
          ];
          
          /**
           * @var string the view file that will render comment form.
           */
faff2c48   Yarik   Artbox comment cr...
60
          public $formView = '@artbox/webcomment/views/artbox_comment_form';
a2cde075   Yarik   first commit
61
62
63
          
          /**
           * Form options
faff2c48   Yarik   Artbox comment cr...
64
           *
a2cde075   Yarik   first commit
65
66
67
68
69
70
71
72
           * @var array
           */
          public $formOptions = [
              'class' => 'artbox_form_container',
          ];
          
          /**
           * Params to be passed to form
faff2c48   Yarik   Artbox comment cr...
73
           *
a2cde075   Yarik   first commit
74
75
76
77
78
79
80
           * @var array
           */
          public $formParams = [];
          
          /**
           * @var string the view file that will render comments list.
           */
faff2c48   Yarik   Artbox comment cr...
81
          public $listView = '@artbox/webcomment/views/artbox_comment_list';
a2cde075   Yarik   first commit
82
83
84
          
          /**
           * List options
faff2c48   Yarik   Artbox comment cr...
85
           *
a2cde075   Yarik   first commit
86
87
88
89
90
91
92
93
           * @var array
           */
          public $listOptions = [
              'class' => 'artbox_list_container',
          ];
          
          /**
           * List params
faff2c48   Yarik   Artbox comment cr...
94
           *
a2cde075   Yarik   first commit
95
96
97
98
99
100
           * @var array
           */
          public $listParams = [];
          
          /**
           * Reply options
faff2c48   Yarik   Artbox comment cr...
101
           *
a2cde075   Yarik   first commit
102
103
104
105
106
107
108
109
110
           * @var array
           */
          public $replyOptions = [
              'style' => 'display: none;',
              'class' => 'artbox_comment_reply_container',
          ];
          
          /**
           * Reply view
faff2c48   Yarik   Artbox comment cr...
111
           *
a2cde075   Yarik   first commit
112
113
           * @var string
           */
faff2c48   Yarik   Artbox comment cr...
114
          public $replyView = '@artbox/webcomment/views/artbox_comment_reply';
a2cde075   Yarik   first commit
115
116
117
          
          /**
           * Comment form ID. If you have multiple forms on the same page, please use unique IDs.
faff2c48   Yarik   Artbox comment cr...
118
           *
a2cde075   Yarik   first commit
119
120
121
122
123
124
           * @var string Form ID
           */
          public $formId = 'artbox-comment-form';
          
          /**
           * Comment list ID. If you have multiple forms on the same page, please use unique IDs.
faff2c48   Yarik   Artbox comment cr...
125
           *
a2cde075   Yarik   first commit
126
127
128
129
130
131
           * @var string List ID
           */
          public $listId = 'artbox-comment-list';
          
          /**
           * Item view
faff2c48   Yarik   Artbox comment cr...
132
           *
a2cde075   Yarik   first commit
133
134
           * @var string
           */
faff2c48   Yarik   Artbox comment cr...
135
          public $itemView = '@artbox/webcomment/views/artbox_comment_item';
a2cde075   Yarik   first commit
136
137
138
          
          /**
           * Item options
faff2c48   Yarik   Artbox comment cr...
139
           *
a2cde075   Yarik   first commit
140
141
142
143
144
145
146
147
148
149
150
151
           * @var array
           */
          public $itemOptions = [
              'class'     => 'artbox_item_container',
              'itemprop'  => 'review',
              'itemscope' => 'itemscope',
              'itemtype'  => 'http://schema.org/Review',
          ];
          
          /**
           * Entity ID attribute, default to primaryKey() if ActiveRecord and throws exception if not
           * set
faff2c48   Yarik   Artbox comment cr...
152
           *
a2cde075   Yarik   first commit
153
154
155
           * @var string entity id attribute
           */
          public $entityIdAttribute;
3dc17ed6   Anastasia   hidden comment in...
156
157
158
159
160
161
162
163
      
          /**
           * show more
           */
          public $more = [
            "show_"       => false,
            'key'         => -1,
          ];
a2cde075   Yarik   first commit
164
165
          /**
           * Info to be passed to Comment Model
faff2c48   Yarik   Artbox comment cr...
166
           *
a2cde075   Yarik   first commit
167
168
           * @var string $info Additional info
           */
faff2c48   Yarik   Artbox comment cr...
169
          public $info = null;
a2cde075   Yarik   first commit
170
171
172
          
          /**
           * Client options to be passed to JS
faff2c48   Yarik   Artbox comment cr...
173
           *
a2cde075   Yarik   first commit
174
175
176
177
178
           * @var array comment widget client options
           */
          public $clientOptions = [];
          
          /**
a2cde075   Yarik   first commit
179
180
181
182
183
184
185
186
           * @var string pjax container id
           */
          public $pjaxContainerId;
          
          public $layout = "<div class='comments-border'></div>{form} {reply_form} {list}";
          
          /**
           * Model fully namespaced classname
faff2c48   Yarik   Artbox comment cr...
187
           *
a2cde075   Yarik   first commit
188
189
190
191
192
193
           * @var string Model namespace
           */
          protected $entity;
          
          /**
           * Entity ID for attached model
faff2c48   Yarik   Artbox comment cr...
194
           *
a2cde075   Yarik   first commit
195
196
197
198
199
200
201
202
203
           * @var integer Entity ID
           */
          protected $entityId;
          
          /**
           * Encrypted data to be passed to Controller. Consist of:
           * * Model::className()
           * * entityId
           * * info (optional)
faff2c48   Yarik   Artbox comment cr...
204
           *
a2cde075   Yarik   first commit
205
206
207
208
209
210
           * @var string encrypted entity key
           */
          protected $encryptedEntityKey;
          
          /**
           * Parts for widget
faff2c48   Yarik   Artbox comment cr...
211
           *
a2cde075   Yarik   first commit
212
213
214
           * @var array $parts
           */
          protected $parts;
a2cde075   Yarik   first commit
215
216
217
          /**
           * Initializes the widget params.
           */
73983f4d   Anastasia   class for comment...
218
219
220
221
222
223
      
          /**
           * Class for button
           * @var string
           */
          public $buttonClass = '';
a2cde075   Yarik   first commit
224
225
226
          public function init()
          {
              // Module init
faff2c48   Yarik   Artbox comment cr...
227
228
229
230
              $module = Yii::$app->getModule(Module::$name);
              if (!$module) {
                  Module::registerMe();
              }
a2cde075   Yarik   first commit
231
232
              // Model init
              $model = $this->getModel();
faff2c48   Yarik   Artbox comment cr...
233
234
      
              if (empty($this->pjaxContainerId)) {
a2cde075   Yarik   first commit
235
236
237
238
239
                  $this->pjaxContainerId = 'comment-pjax-container-' . $this->getId();
              }
              
              $this->entity = $model::className();
              // Entity ID init
faff2c48   Yarik   Artbox comment cr...
240
              if (!empty($this->entityIdAttribute) && $this->model->hasProperty($this->entityIdAttribute)) {
a2cde075   Yarik   first commit
241
242
                  $this->entityId = $this->model->{$this->entityIdAttribute};
              } else {
faff2c48   Yarik   Artbox comment cr...
243
                  if ($this->model instanceof ActiveRecord && !empty($this->model->getPrimaryKey())) {
a2cde075   Yarik   first commit
244
245
                      $this->entityId = (int) $this->model->getPrimaryKey();
                  } else {
faff2c48   Yarik   Artbox comment cr...
246
247
248
                      throw new InvalidConfigException(
                          Yii::t('artbox-comment', 'The "entityIdAttribute" value for widget model cannot be empty.')
                      );
a2cde075   Yarik   first commit
249
250
251
252
253
254
255
256
257
258
259
                  }
              }
              
              // Generate encryptedEntityKey
              $this->encryptedEntityKey = $this->generateEntityKey();
              
              $this->registerAssets();
          }
          
          /**
           * Executes the widget.
faff2c48   Yarik   Artbox comment cr...
260
           *
a2cde075   Yarik   first commit
261
262
263
264
265
266
           * @return string the result of widget execution to be outputted.
           */
          public function run()
          {
              /* @var Module $module */
              $module = Yii::$app->getModule(Module::$name);
faff2c48   Yarik   Artbox comment cr...
267
268
269
              if (!$module) {
                  Module::registerMe();
              }
a2cde075   Yarik   first commit
270
              $commentModelClass = $module->commentModelClass;
faff2c48   Yarik   Artbox comment cr...
271
272
273
274
275
276
277
278
279
280
              $commentModel = $this->createModel(
                  $commentModelClass,
                  [
                      'entity'          => $this->entity,
                      'entityId'        => $this->entityId,
                      'encryptedEntity' => $this->encryptedEntityKey,
                      'scenario'        => \Yii::$app->user->getIsGuest(
                      ) ? CommentModel::SCENARIO_GUEST : CommentModel::SCENARIO_USER,
                  ]
              );
fd5e93c2   Yarik   Artbox comment pr...
281
              if ($module->enableRating) {
a2cde075   Yarik   first commit
282
283
284
                  $ratingModelClass = $module->ratingModelClass;
                  $ratingModel = $this->createRating($ratingModelClass);
              } else {
faff2c48   Yarik   Artbox comment cr...
285
286
287
288
289
290
                  $ratingModel = null;
              }
              if (method_exists($commentModelClass, 'getTree')) {
                  $comments = $commentModelClass::getTree($this->entity, $this->entityId);
              } else {
                  $comments = [];
a2cde075   Yarik   first commit
291
              }
a2cde075   Yarik   first commit
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
              
              $this->buildParts($commentModel, $comments, $ratingModel);
              
              return $this->renderWidget();
          }
          
          /**
           * Register assets.
           */
          protected function registerAssets()
          {
              $this->clientOptions[ 'formSelector' ] = '#' . $this->formId;
              $this->clientOptions[ 'listSelector' ] = '#' . $this->listId;
              $options = Json::encode($this->clientOptions);
              $view = $this->getView();
              CommentAsset::register($view);
              $view->registerJs("jQuery('#{$this->formId}').artbox_comment({$options});");
          }
          
          /**
           * Get encrypted entity key
faff2c48   Yarik   Artbox comment cr...
313
           *
a2cde075   Yarik   first commit
314
315
316
317
318
           * @return string
           */
          protected function generateEntityKey()
          {
              return Yii::$app->getSecurity()
faff2c48   Yarik   Artbox comment cr...
319
320
321
322
323
324
325
326
327
328
                              ->encryptByKey(
                                  Json::encode(
                                      [
                                          'entity'    => $this->entity,
                                          'entity_id' => $this->entityId,
                                          'info'      => $this->info,
                                      ]
                                  ),
                                  Module::$encryptionKey
                              );
a2cde075   Yarik   first commit
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
          }
          
          /**
           * Create comment model
           *
           * @param string $className Full namespaced model
           * @param array  $config    Init config
           *
           * @return CommentInterface Comment model
           * @throws InvalidConfigException If object not instance of \yii\base\Model
           */
          protected function createModel(string $className, array $config = []): CommentInterface
          {
              $options = array_merge($config, [ 'class' => $className ]);
              $object = Yii::createObject($options);
faff2c48   Yarik   Artbox comment cr...
344
              if ($object instanceof CommentInterface) {
a2cde075   Yarik   first commit
345
346
                  return $object;
              }
faff2c48   Yarik   Artbox comment cr...
347
348
349
              throw new InvalidConfigException(
                  Yii::t('artbox-comment', 'Comment model must be instance of CommentInterface.')
              );
a2cde075   Yarik   first commit
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
          }
          
          /**
           * Create rating model
           *
           * @param string $className Full namespaced model
           * @param array  $config    Init config
           *
           * @return CommentInterface|RatingModel Comment model
           * @throws InvalidConfigException If object not instance of \yii\base\Model
           */
          protected function createRating(string $className, array $config = []): RatingModel
          {
              $options = array_merge($config, [ 'class' => $className ]);
              $object = Yii::createObject($options);
faff2c48   Yarik   Artbox comment cr...
365
              if ($object instanceof RatingModel) {
a2cde075   Yarik   first commit
366
367
                  return $object;
              }
faff2c48   Yarik   Artbox comment cr...
368
369
370
              throw new InvalidConfigException(
                  Yii::t('artbox-comment', 'Comment model must be instance of RatingModel.')
              );
a2cde075   Yarik   first commit
371
372
373
374
375
376
377
378
379
          }
          
          /**
           * Build parts for rendering widget
           *
           * @param CommentInterface   $commentModel
           * @param ActiveDataProvider $comments
           * @param null|RatingModel   $ratingModel
           */
faff2c48   Yarik   Artbox comment cr...
380
          protected function buildParts(CommentInterface $commentModel, ActiveDataProvider $comments, $ratingModel = null)
a2cde075   Yarik   first commit
381
382
          {
              $form_options = $this->formOptions;
faff2c48   Yarik   Artbox comment cr...
383
384
385
386
387
388
389
390
391
392
              $this->parts[ 'form' ] = Html::tag(
                  ArrayHelper::remove($form_options, 'tag', 'div'),
                  $this->render(
                      $this->formView,
                      [
                          'comment_model' => $commentModel,
                          'form_params'   => $this->formParams,
                          'model'         => $this->getModel(),
                          'formId'        => $this->formId,
                          'rating_model'  => $ratingModel,
73983f4d   Anastasia   class for comment...
393
                          'buttonClass'   => $this->buttonClass
179a0e00   Anastasia   bug fix artbox-co...
394
                          
faff2c48   Yarik   Artbox comment cr...
395
396
397
398
399
                      ]
                  ),
                  $form_options
              );
      
179a0e00   Anastasia   bug fix artbox-co...
400
              if (!\Yii::$app->user->isGuest && $this->reply) {
a2cde075   Yarik   first commit
401
                  $reply_options = $this->replyOptions;
faff2c48   Yarik   Artbox comment cr...
402
403
404
405
406
407
408
409
410
411
412
413
414
                  $this->parts[ 'reply_form' ] = Html::tag(
                      ArrayHelper::remove($reply_options, 'tag', 'div'),
                      $this->render(
                          $this->replyView,
                          [
                              'comment_model' => $commentModel,
                              'form_params'   => $this->formParams,
                              'model'         => $this->getModel(),
                              'formId'        => $this->formId,
                          ]
                      ),
                      $reply_options
                  );
a2cde075   Yarik   first commit
415
416
417
              }
              
              $list_options = array_merge($this->listOptions, [ 'id' => $this->listId ]);
faff2c48   Yarik   Artbox comment cr...
418
419
420
421
422
423
424
425
426
427
428
              $this->parts[ 'list' ] = Html::tag(
                  ArrayHelper::remove($list_options, 'tag', 'div'),
                  $this->render(
                      $this->listView,
                      [
                          'comment_model' => $commentModel,
                          'list_params'   => $this->listParams,
                          'model'         => $this->getModel(),
                          'comments'      => $comments,
                          'item_options'  => $this->itemOptions,
                          'item_view'     => $this->itemView,
b5639b59   Anastasia   comment widget
429
                          'display_name'  => $this->display_name,
179a0e00   Anastasia   bug fix artbox-co...
430
                          'reply'         => $this->reply,
3dc17ed6   Anastasia   hidden comment in...
431
432
433
                          'delete'        => $this->delete,
                          'more'          => $this->more,
                          
b5639b59   Anastasia   comment widget
434
                          
faff2c48   Yarik   Artbox comment cr...
435
436
437
438
                      ]
                  ),
                  $list_options
              );
a2cde075   Yarik   first commit
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
          }
          
          /**
           * @return string
           */
          protected function renderWidget(): string
          {
              $layout = $this->layout;
              $parts = $this->parts;
              $options = $this->options;
              $layout = preg_replace('/{list}/', ArrayHelper::getValue($parts, 'list', ''), $layout);
              $layout = preg_replace('/{form}/', ArrayHelper::getValue($parts, 'form', ''), $layout);
              $layout = preg_replace('/{reply_form}/', ArrayHelper::getValue($parts, 'reply_form', ''), $layout);
              $tag = ArrayHelper::remove($options, 'tag', 'div');
              return Html::tag($tag, $layout, $options);
          }
          
          public function setModel(Model $model)
          {
              $this->model = $model;
          }
          
          public function getModel(): Model
          {
faff2c48   Yarik   Artbox comment cr...
463
              if (!empty($this->model)) {
a2cde075   Yarik   first commit
464
465
                  return $this->model;
              }
faff2c48   Yarik   Artbox comment cr...
466
              throw new InvalidConfigException(Yii::t('artbox-comment', 'The "model" property must be set.'));
a2cde075   Yarik   first commit
467
468
          }
      }