rootlocal/yii2-crud

View on GitHub
src/actions/IndexAction.php

Summary

Maintainability
A
1 hr
Test Coverage
A
100%
<?php

namespace rootlocal\crud\actions;

use Closure;
use rootlocal\crud\components\Action;
use rootlocal\crud\components\SearchModelInterface;
use Yii;
use yii\base\ErrorException;
use yii\base\InvalidConfigException;
use yii\data\ActiveDataProvider;
use yii\web\Response;

/**
 * Class IndexAction
 * Lists all SearchModelInterface models.
 *
 * examples:
 *
 * ```php
 * // lambda function:
 * public function actions()
 * {
 *      'index' => [
 *          'class' => IndexAction::class,
 *          'searchModel' => function () {
 *              return new BookSearch();
 *          },
 *          'dataProvider' => function ($model, $queryParams) {
 *              $model->query = $model::find()->active();
 *              return $model->search($queryParams);
 *          }
 *      ]
 * }
 *
 * // string:
 * public function actions()
 * {
 *      'index' => [
 *          'class' => IndexAction::class,
 *          'searchModel' => BookSearch::class
 *      ]
 * }
 *
 * // ActiveRecord:
 * public function actions()
 * {
 *      'index' => [
 *          'class' => IndexAction::class,
 *          'model' => new BookSearch()
 *      ]
 * }
 * ```
 * @property Closure|null $dataProvider implements a data provider (instanceof [[Closure]])
 * @property string|SearchModelInterface|Closure $searchModel ActiveRecord searchModel
 * @property SearchModelInterface $model Readonly ActiveRecord object instanceof [[SearchModelInterface]]
 * @property-read array $queryParams The request GET parameter values.
 *
 * @author Alexander Zakharov <sys@eml.ru>
 * @package rootlocal\crud\actions
 */
class IndexAction extends Action
{
    /**
     * @var string|SearchModelInterface|Closure
     */
    private $_searchModel;
    /**
     * @var SearchModelInterface
     */
    private $_model;
    /**
     * @var ActiveDataProvider
     */
    private $_dataProvider;
    /**
     * @var array $queryParams The request GET parameter values.
     */
    private array $_queryParams = [];


    /**
     * Runs the action.
     *
     * @return string
     */
    public function run()
    {
        $request = Yii::$app->getRequest();

        if ($request->isAjax || $request->isPjax) {
            Yii::$app->response->format = Response::FORMAT_JSON;
            return $this->controller->renderAjax($this->getViewName(), [
                'searchModel' => $this->getModel(),
                'dataProvider' => $this->getDataProvider(),
            ]);
        }

        return $this->controller->render($this->getViewName(), [
            'searchModel' => $this->getModel(),
            'dataProvider' => $this->getDataProvider(),
        ]);
    }

    /**
     * Get ActiveRecord searchModel
     *
     * @return Closure|string|SearchModelInterface|array ActiveRecord searchModel
     * @throws ErrorException if Model not specified (not set)
     */
    public function getSearchModel()
    {
        if (empty($this->_searchModel)) {
            throw new ErrorException(Yii::t('rootlocal/crud', 'No search model specified'));
        }

        return $this->_searchModel;
    }

    /**
     * Set ActiveRecord searchModel
     *
     * @param Closure|string|SearchModelInterface|array $searchModel ActiveRecord searchModel
     */
    public function setSearchModel($searchModel): void
    {
        $this->_searchModel = $searchModel;
    }

    /**
     * Get ActiveRecord searchModel
     *
     * @return SearchModelInterface ActiveRecord searchModel object instanceof [[SearchModelInterface]]
     * @throws ErrorException if searchModel not instanceof [[SearchModelInterface]]
     * @throws InvalidConfigException if the configuration is invalid
     */
    public function getModel(): SearchModelInterface
    {
        if ($this->_model === null) {

            if (is_string($this->getSearchModel())) {
                $this->_model = Yii::createObject(['class' => $this->getSearchModel()]);
            }

            if ($this->getSearchModel() instanceof Closure || is_array($this->getSearchModel())) {
                $this->_model = call_user_func($this->getSearchModel());
            }

            if ($this->getSearchModel() instanceof SearchModelInterface) {
                $this->_model = $this->getSearchModel();
            }
        }

        if ($this->_model instanceof SearchModelInterface) {

            if ($this->checkAccess && ($this->checkAccess instanceof Closure || is_array($this->checkAccess))) {
                call_user_func($this->checkAccess, $this->id, $this->_model);
            }

            return $this->_model;
        }

        throw new ErrorException('searchModel not instanceof ' . SearchModelInterface::class);
    }

    /**
     * Get The request GET parameter values.
     *
     * @return array The request GET parameter values.
     */
    public function getQueryParams()
    {
        if (empty($this->_queryParams)) {

            $queryParams = Yii::$app->getRequest()->getQueryParams();

            if (empty($queryParams)) {
                $queryParams = Yii::$app->getRequest()->getBodyParams();
            }

            $this->_queryParams = $queryParams;
        }

        return $this->_queryParams;
    }

    /**
     * Get DataProvider object
     *
     * @return ActiveDataProvider ActiveDataProvider object
     * @throws InvalidConfigException if dataProvider not instanceof [[ActiveDataProvider]]
     */
    public function getDataProvider(): ActiveDataProvider
    {
        if ($this->_dataProvider === null) {
            $this->_dataProvider = $this->getModel()->search($this->getQueryParams());
        }

        if (!($this->_dataProvider instanceof ActiveDataProvider))
            throw new InvalidConfigException('dataProvider not instanceof ' . ActiveDataProvider::class);

        return $this->_dataProvider;
    }

    /**
     * Get DataProvider
     *
     * @param Closure $dataProvider anonymous function for [[ActiveDataProvider]]
     */
    public function setDataProvider($dataProvider): void
    {
        if ($dataProvider instanceof Closure || is_array($dataProvider)) {
            $this->_dataProvider = call_user_func($dataProvider, $this->getModel(), $this->getQueryParams());
        }
    }
}