CommentWidget.php 5.71 KB
<?php
    namespace common\modules\comment\widgets;

    use \yii\helpers\ArrayHelper;
    use \yii\helpers\Html;

    class CommentWidget extends \yii\base\Widget
    {

        /**
         * @var array Parts of widgets that can be rendered
         */
        public $parts = [];

        /**
         * @var string|\common\modules\comment\models\Comment
         */
        public $comment_class;

        /**
         * @var array
         */
        public $class_options = [];

        /**
         * @var bool Wheather to display comment list
         */
        public $display_comment_list = true;

        /**
         * @var bool Wheather to display comment form
         */
        public $display_comment_form = true;

        public $display_comment_success = true;

        public $allow_multiple = true;

        public $success_text = "Comment posted successfully";

        public $list_options = [
            'tag' => 'div',
            'view' => 'list-comment',
            'class' => 'test-class',
        ];

        public $success_options = [
            'tag' => 'div',
            'content' => null,
            'class' => 'test-class-success',
        ];

        public $form_options = [
            'tag' => 'div',
            'view' => 'form-comment',
            'class' => 'test-class-form',
        ];

        protected $isSuccess = false;

        public $entity;

        public $template = "{success}\n{form}\n{list}";

        public $options = [];

        /**
         * @var \yii\data\DataProviderInterface
         */
        public $dataProvider;

        /**
         * @inheritdoc
         */
        public function init()
        {
            parent::init();
            if(is_string($this->comment_class)) {
                $this->comment_class = new $this->comment_class($this->class_options);
            } elseif(!is_object($this->comment_class)) {
                throw new \yii\base\InvalidConfigException(__CLASS__.'->comment_class must be defined as string or object.');
            }
            $this->comment_class->entity = $this->entity;
            $this->createDataProvider();
            if($this->comment_class->checkCreate($this->entity)) {
                $this->handleCreate();
            }
            ob_start();
        }

        /**
         * @inheritdoc
         * @return string
         */
        public function run()
        {
            $content = ob_get_clean();
            $this->createParts();
            return $this->renderWidget();
        }

        public function createParts() {
            if($this->display_comment_success && $this->isSuccess) {
                $tag = ArrayHelper::remove($this->success_options, 'tag', 'div');
                if(is_callable($this->success_options['content'])) {
                    $result = call_user_func(ArrayHelper::remove($this->success_options, 'content'), $this->success_text);
                } elseif($this->success_options['content'] != NULL) {
                    $result = Html::encode(ArrayHelper::remove($this->success_options, 'content', $this->success_text));
                } else {
                    $result = Html::encode($this->success_text);
                }
                $this->parts['success'] = Html::tag($tag, $result, $this->success_options);
                unset($tag, $result);
            }

            if($this->display_comment_list) {
                $tag = ArrayHelper::remove($this->list_options, 'tag', 'div');
                $view = ArrayHelper::remove($this->list_options, 'view');
                $this->parts['list'] = Html::tag($tag, $this->renderItems($view), $this->list_options);
            }

            if($this->display_comment_form) {
                $tag = ArrayHelper::remove($this->form_options, 'tag', 'div');
                $view = ArrayHelper::remove($this->form_options, 'view');
                $this->parts['form'] = Html::tag($tag, $this->renderForm($view), $this->list_options);
            }
        }

        public function createDataProvider()
        {
            $this->dataProvider = new \yii\data\ActiveDataProvider([
                'query' => $this->comment_class->getComments($this->entity),
                'pagination' => [
                    'pageSize' => 10,
                ],
            ]);
        }

        public function renderItems($view) {
            if(empty($view)) {
                throw new \yii\base\InvalidConfigException("list_options[view] must be set");
            }
            return $this->render($view, ['dataProvider' => $this->dataProvider]);
        }

        public function renderForm($view) {
            if(empty($view)) {
                throw new \yii\base\InvalidConfigException("form_options[view] must be set");
            }
            return $this->render($view, [
                'model' => $this->comment_class,
                'user' => \Yii::$app->user->identity,
                'dataProvider' => $this->dataProvider,
            ]);
        }

        public function renderWidget() {
            $template = $this->template;
            $parts = $this->parts;
            $options = $this->options;
            $template = preg_replace('/{success}/', ArrayHelper::remove($parts, 'success', ''), $template);
            $template = preg_replace('/{list}/', ArrayHelper::remove($parts, 'list', ''), $template);
            $template = preg_replace('/{form}/', ArrayHelper::remove($parts, 'form', ''), $template);
            $tag = ArrayHelper::remove($options, 'tag', 'div');
            return Html::tag($tag, $template, $options);
        }

        public function handleCreate()
        {
            $data = \Yii::$app->request->post();
            if($this->comment_class->postComment($data)) {
                $this->isSuccess = true;
            };
        }
    }