Issues (902)

framework/web/ViewAction.php (4 issues)

1
<?php
2
/**
3
 * @link https://www.yiiframework.com/
4
 * @copyright Copyright (c) 2008 Yii Software LLC
5
 * @license https://www.yiiframework.com/license/
6
 */
7
8
namespace yii\web;
9
10
use Yii;
11
use yii\base\Action;
12
use yii\base\ViewNotFoundException;
13
14
/**
15
 * ViewAction represents an action that displays a view according to a user-specified parameter.
16
 *
17
 * By default, the view being displayed is specified via the `view` GET parameter.
18
 * The name of the GET parameter can be customized via [[viewParam]].
19
 *
20
 * Users specify a view in the format of `path/to/view`, which translates to the view name
21
 * `ViewPrefix/path/to/view` where `ViewPrefix` is given by [[viewPrefix]]. The view will then
22
 * be rendered by the [[\yii\base\Controller::render()|render()]] method of the currently active controller.
23
 *
24
 * Note that the user-specified view name must start with a word character and can only contain
25
 * word characters, forward slashes, dots and dashes.
26
 *
27
 * @author Alexander Makarov <[email protected]>
28
 * @author Qiang Xue <[email protected]>
29
 * @since 2.0
30
 */
31
class ViewAction extends Action
32
{
33
    /**
34
     * @var string the name of the GET parameter that contains the requested view name.
35
     */
36
    public $viewParam = 'view';
37
    /**
38
     * @var string the name of the default view when [[\yii\web\ViewAction::$viewParam]] GET parameter is not provided
39
     * by user. Defaults to 'index'. This should be in the format of 'path/to/view', similar to that given in the
40
     * GET parameter.
41
     * @see \yii\web\ViewAction::$viewPrefix
42
     */
43
    public $defaultView = 'index';
44
    /**
45
     * @var string a string to be prefixed to the user-specified view name to form a complete view name.
46
     * For example, if a user requests for `tutorial/chap1`, the corresponding view name will
47
     * be `pages/tutorial/chap1`, assuming the prefix is `pages`.
48
     * The actual view file is determined by [[\yii\base\View::findViewFile()]].
49
     * @see \yii\base\View::findViewFile()
50
     */
51
    public $viewPrefix = 'pages';
52
    /**
53
     * @var mixed the name of the layout to be applied to the requested view.
54
     * This will be assigned to [[\yii\base\Controller::$layout]] before the view is rendered.
55
     * Defaults to null, meaning the controller's layout will be used.
56
     * If false, no layout will be applied.
57
     */
58
    public $layout;
59
60
61
    /**
62
     * Runs the action.
63
     * This method displays the view requested by the user.
64
     * @throws NotFoundHttpException if the view file cannot be found
65
     */
66
    public function run()
67
    {
68
        $viewName = $this->resolveViewName();
69
        $this->controller->actionParams[$this->viewParam] = Yii::$app->request->get($this->viewParam);
0 ignored issues
show
Bug Best Practice introduced by
The property actionParams does not exist on yii\base\Controller. Since you implemented __get, consider adding a @property annotation.
Loading history...
Bug Best Practice introduced by
The property actionParams does not exist on yii\console\Controller. Since you implemented __get, consider adding a @property annotation.
Loading history...
The method get() does not exist on yii\console\Request. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

69
        /** @scrutinizer ignore-call */ 
70
        $this->controller->actionParams[$this->viewParam] = Yii::$app->request->get($this->viewParam);
Loading history...
70
71
        $controllerLayout = null;
72
        if ($this->layout !== null) {
73
            $controllerLayout = $this->controller->layout;
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->controller->layout can also be of type boolean. However, the property $layout is declared as type false|null|string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
74
            $this->controller->layout = $this->layout;
75
        }
76
77
        try {
78
            $output = $this->render($viewName);
79
80
            if ($controllerLayout) {
81
                $this->controller->layout = $controllerLayout;
82
            }
83
        } catch (ViewNotFoundException $e) {
84
            if ($controllerLayout) {
85
                $this->controller->layout = $controllerLayout;
86
            }
87
88
            if (YII_DEBUG) {
89
                throw new NotFoundHttpException($e->getMessage());
90
            }
91
92
            throw new NotFoundHttpException(
93
                Yii::t('yii', 'The requested view "{name}" was not found.', ['name' => $viewName])
94
            );
95
        }
96
97
        return $output;
98
    }
99
100
    /**
101
     * Renders a view.
102
     *
103
     * @param string $viewName view name
104
     * @return string result of the rendering
105
     */
106
    protected function render($viewName)
107
    {
108
        return $this->controller->render($viewName);
109
    }
110
111
    /**
112
     * Resolves the view name currently being requested.
113
     *
114
     * @return string the resolved view name
115
     * @throws NotFoundHttpException if the specified view name is invalid
116
     */
117
    protected function resolveViewName()
118
    {
119
        $viewName = Yii::$app->request->get($this->viewParam, $this->defaultView);
120
121
        if (!is_string($viewName) || !preg_match('~^\w(?:(?!\/\.{0,2}\/)[\w\/\-\.])*$~', $viewName)) {
122
            if (YII_DEBUG) {
123
                throw new NotFoundHttpException("The requested view \"$viewName\" must start with a word character, must not contain /../ or /./, can contain only word characters, forward slashes, dots and dashes.");
124
            }
125
126
            throw new NotFoundHttpException(Yii::t('yii', 'The requested view "{name}" was not found.', ['name' => $viewName]));
127
        }
128
129
        return empty($this->viewPrefix) ? $viewName : $this->viewPrefix . '/' . $viewName;
130
    }
131
}
132