GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Issues (910)

framework/widgets/DetailView.php (2 issues)

Labels
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\widgets;
9
10
use Yii;
11
use yii\base\Arrayable;
12
use yii\base\InvalidConfigException;
13
use yii\base\Model;
14
use yii\base\Widget;
15
use yii\helpers\ArrayHelper;
16
use yii\helpers\Html;
17
use yii\helpers\Inflector;
18
use yii\i18n\Formatter;
19
20
/**
21
 * DetailView displays the detail of a single data [[model]].
22
 *
23
 * DetailView is best used for displaying a model in a regular format (e.g. each model attribute
24
 * is displayed as a row in a table.) The model can be either an instance of [[Model]]
25
 * or an associative array.
26
 *
27
 * DetailView uses the [[attributes]] property to determines which model attributes
28
 * should be displayed and how they should be formatted.
29
 *
30
 * A typical usage of DetailView is as follows:
31
 *
32
 * ```php
33
 * echo DetailView::widget([
34
 *     'model' => $model,
35
 *     'attributes' => [
36
 *         'title',               // title attribute (in plain text)
37
 *         'description:html',    // description attribute in HTML
38
 *         [                      // the owner name of the model
39
 *             'label' => 'Owner',
40
 *             'value' => $model->owner->name,
41
 *         ],
42
 *         'created_at:datetime', // creation date formatted as datetime
43
 *     ],
44
 * ]);
45
 * ```
46
 *
47
 * For more details and usage information on DetailView, see the [guide article on data widgets](guide:output-data-widgets).
48
 *
49
 * @author Qiang Xue <[email protected]>
50
 * @since 2.0
51
 */
52
class DetailView extends Widget
53
{
54
    /**
55
     * @var array|object the data model whose details are to be displayed. This can be a [[Model]] instance,
56
     * an associative array, an object that implements [[Arrayable]] interface or simply an object with defined
57
     * public accessible non-static properties.
58
     */
59
    public $model;
60
    /**
61
     * @var array a list of attributes to be displayed in the detail view. Each array element
62
     * represents the specification for displaying one particular attribute.
63
     *
64
     * An attribute can be specified as a string in the format of `attribute`, `attribute:format` or `attribute:format:label`,
65
     * where `attribute` refers to the attribute name, and `format` represents the format of the attribute. The `format`
66
     * is passed to the [[Formatter::format()]] method to format an attribute value into a displayable text.
67
     * Please refer to [[Formatter]] for the supported types. Both `format` and `label` are optional.
68
     * They will take default values if absent.
69
     *
70
     * An attribute can also be specified in terms of an array with the following elements:
71
     *
72
     * - `attribute`: the attribute name. This is required if either `label` or `value` is not specified.
73
     * - `label`: the label associated with the attribute. If this is not specified, it will be generated from the attribute name.
74
     * - `value`: the value to be displayed. If this is not specified, it will be retrieved from [[model]] using the attribute name
75
     *   by calling [[ArrayHelper::getValue()]]. Note that this value will be formatted into a displayable text
76
     *   according to the `format` option. Since version 2.0.11 it can be defined as closure with the following
77
     *   parameters:
78
     *
79
     *   ```php
80
     *   function ($model, $widget)
81
     *   ```
82
     *
83
     *   `$model` refers to displayed model and `$widget` is an instance of `DetailView` widget.
84
     *
85
     * - `format`: the type of the value that determines how the value would be formatted into a displayable text.
86
     *   Please refer to [[Formatter]] for supported types and [[Formatter::format()]] on how to specify this value.
87
     * - `visible`: whether the attribute is visible. If set to `false`, the attribute will NOT be displayed.
88
     * - `contentOptions`: the HTML attributes to customize value tag. For example: `['class' => 'bg-red']`.
89
     *   Please refer to [[\yii\helpers\BaseHtml::renderTagAttributes()]] for the supported syntax.
90
     * - `captionOptions`: the HTML attributes to customize label tag. For example: `['class' => 'bg-red']`.
91
     *   Please refer to [[\yii\helpers\BaseHtml::renderTagAttributes()]] for the supported syntax.
92
     */
93
    public $attributes;
94
    /**
95
     * @var string|callable the template used to render a single attribute. If a string, the token `{label}`
96
     * and `{value}` will be replaced with the label and the value of the corresponding attribute.
97
     * If a callback (e.g. an anonymous function), the signature must be as follows:
98
     *
99
     * ```php
100
     * function ($attribute, $index, $widget)
101
     * ```
102
     *
103
     * where `$attribute` refer to the specification of the attribute being rendered, `$index` is the zero-based
104
     * index of the attribute in the [[attributes]] array, and `$widget` refers to this widget instance.
105
     *
106
     * Since Version 2.0.10, the tokens `{captionOptions}` and `{contentOptions}` are available, which will represent
107
     * HTML attributes of HTML container elements for the label and value.
108
     */
109
    public $template = '<tr><th{captionOptions}>{label}</th><td{contentOptions}>{value}</td></tr>';
110
    /**
111
     * @var array|null the HTML attributes for the container tag of this widget. The `tag` option specifies
112
     * what container tag should be used. It defaults to `table` if not set.
113
     * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
114
     */
115
    public $options = ['class' => 'table table-striped table-bordered detail-view'];
116
    /**
117
     * @var array|Formatter|null the formatter used to format model attribute values into displayable texts.
118
     * This can be either an instance of [[Formatter]] or an configuration array for creating the [[Formatter]]
119
     * instance. If this property is not set, the `formatter` application component will be used.
120
     */
121
    public $formatter;
122
123
124
    /**
125
     * Initializes the detail view.
126
     * This method will initialize required property values.
127
     */
128 9
    public function init()
129
    {
130 9
        parent::init();
131
132 9
        if ($this->model === null) {
133
            throw new InvalidConfigException('Please specify the "model" property.');
134
        }
135 9
        if ($this->formatter === null) {
136 9
            $this->formatter = Yii::$app->getFormatter();
137
        } elseif (is_array($this->formatter)) {
138
            $this->formatter = Yii::createObject($this->formatter);
139
        }
140 9
        if (!$this->formatter instanceof Formatter) {
141
            throw new InvalidConfigException('The "formatter" property must be either a Format object or a configuration array.');
142
        }
143 9
        $this->normalizeAttributes();
144
145 9
        if (!isset($this->options['id'])) {
146 9
            $this->options['id'] = $this->getId();
147
        }
148
    }
149
150
    /**
151
     * Renders the detail view.
152
     * This is the main entry of the whole detail view rendering.
153
     */
154
    public function run()
155
    {
156
        $rows = [];
157
        $i = 0;
158
        foreach ($this->attributes as $attribute) {
159
            $rows[] = $this->renderAttribute($attribute, $i++);
160
        }
161
162
        $options = $this->options;
163
        $tag = ArrayHelper::remove($options, 'tag', 'table');
164
        echo Html::tag($tag, implode("\n", $rows), $options);
165
    }
166
167
    /**
168
     * Renders a single attribute.
169
     * @param array $attribute the specification of the attribute to be rendered.
170
     * @param int $index the zero-based index of the attribute in the [[attributes]] array
171
     * @return string the rendering result
172
     */
173 4
    protected function renderAttribute($attribute, $index)
174
    {
175 4
        if (is_string($this->template)) {
176 4
            $captionOptions = Html::renderTagAttributes(ArrayHelper::getValue($attribute, 'captionOptions', []));
177 4
            $contentOptions = Html::renderTagAttributes(ArrayHelper::getValue($attribute, 'contentOptions', []));
178 4
            return strtr($this->template, [
179 4
                '{label}' => $attribute['label'],
180 4
                '{value}' => $this->formatter->format($attribute['value'], $attribute['format']),
0 ignored issues
show
The method format() does not exist on null. ( Ignorable by Annotation )

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

180
                '{value}' => $this->formatter->/** @scrutinizer ignore-call */ format($attribute['value'], $attribute['format']),

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
181 4
                '{captionOptions}' => $captionOptions,
182 4
                '{contentOptions}' => $contentOptions,
183 4
            ]);
184
        }
185
186
        return call_user_func($this->template, $attribute, $index, $this);
187
    }
188
189
    /**
190
     * Normalizes the attribute specifications.
191
     * @throws InvalidConfigException
192
     */
193 9
    protected function normalizeAttributes()
194
    {
195 9
        if ($this->attributes === null) {
196 4
            if ($this->model instanceof Model) {
197 2
                $this->attributes = $this->model->attributes();
198 2
            } elseif (is_object($this->model)) {
199 1
                $this->attributes = $this->model instanceof Arrayable ? array_keys($this->model->toArray()) : array_keys(get_object_vars($this->model));
200 1
            } elseif (is_array($this->model)) {
0 ignored issues
show
The condition is_array($this->model) is always true.
Loading history...
201 1
                $this->attributes = array_keys($this->model);
202
            } else {
203
                throw new InvalidConfigException('The "model" property must be either an array or an object.');
204
            }
205 4
            sort($this->attributes);
206
        }
207
208 9
        foreach ($this->attributes as $i => $attribute) {
209 9
            if (is_string($attribute)) {
210 7
                if (!preg_match('/^([^:]+)(:(\w*))?(:(.*))?$/', $attribute, $matches)) {
211
                    throw new InvalidConfigException('The attribute must be specified in the format of "attribute", "attribute:format" or "attribute:format:label"');
212
                }
213 7
                $attribute = [
214 7
                    'attribute' => $matches[1],
215 7
                    'format' => isset($matches[3]) ? $matches[3] : 'text',
216 7
                    'label' => isset($matches[5]) ? $matches[5] : null,
217 7
                ];
218
            }
219
220 9
            if (!is_array($attribute)) {
221
                throw new InvalidConfigException('The attribute configuration must be an array.');
222
            }
223
224 9
            if (isset($attribute['visible']) && !$attribute['visible']) {
225 1
                unset($this->attributes[$i]);
226 1
                continue;
227
            }
228
229 9
            if (!isset($attribute['format'])) {
230 3
                $attribute['format'] = 'text';
231
            }
232 9
            if (isset($attribute['attribute'])) {
233 9
                $attributeName = $attribute['attribute'];
234 9
                if (!isset($attribute['label'])) {
235 8
                    $attribute['label'] = $this->model instanceof Model ? $this->model->getAttributeLabel($attributeName) : Inflector::camel2words($attributeName, true);
236
                }
237 9
                if (!array_key_exists('value', $attribute)) {
238 9
                    $attribute['value'] = ArrayHelper::getValue($this->model, $attributeName);
239
                }
240
            } elseif (!isset($attribute['label']) || !array_key_exists('value', $attribute)) {
241
                throw new InvalidConfigException('The attribute configuration requires the "attribute" element to determine the value and display label.');
242
            }
243
244 9
            if ($attribute['value'] instanceof \Closure) {
245 2
                $attribute['value'] = call_user_func($attribute['value'], $this->model, $this);
246
            }
247
248 9
            $this->attributes[$i] = $attribute;
249
        }
250
    }
251
}
252