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.
Completed
Push — master ( ecd2dc...aafa57 )
by Robert
18:49
created

DetailView::normalizeAttributes()   F

Complexity

Conditions 22
Paths 811

Size

Total Lines 58
Code Lines 37

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 41
CRAP Score 22.34

Importance

Changes 0
Metric Value
dl 0
loc 58
ccs 41
cts 45
cp 0.9111
rs 3.4482
c 0
b 0
f 0
cc 22
eloc 37
nc 811
nop 0
crap 22.34

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @link http://www.yiiframework.com/
4
 * @copyright Copyright (c) 2008 Yii Software LLC
5
 * @license http://www.yiiframework.com/license/
6
 */
7
8
namespace yii\widgets;
9
10
use Yii;
11
use yii\base\Arrayable;
12
use yii\i18n\Formatter;
13
use yii\base\InvalidConfigException;
14
use yii\base\Model;
15
use yii\base\Widget;
16
use yii\helpers\ArrayHelper;
17
use yii\helpers\Html;
18
use yii\helpers\Inflector;
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.
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 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 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 8
    public function init()
129
    {
130 8
        if ($this->model === null) {
131
            throw new InvalidConfigException('Please specify the "model" property.');
132
        }
133 8
        if ($this->formatter === null) {
134 8
            $this->formatter = Yii::$app->getFormatter();
135 8
        } elseif (is_array($this->formatter)) {
136
            $this->formatter = Yii::createObject($this->formatter);
137
        }
138 8
        if (!$this->formatter instanceof Formatter) {
139
            throw new InvalidConfigException('The "formatter" property must be either a Format object or a configuration array.');
140
        }
141 8
        $this->normalizeAttributes();
142
143 8
        if (!isset($this->options['id'])) {
144 8
            $this->options['id'] = $this->getId();
145 8
        }
146 8
    }
147
148
    /**
149
     * Renders the detail view.
150
     * This is the main entry of the whole detail view rendering.
151
     */
152
    public function run()
153
    {
154
        $rows = [];
155
        $i = 0;
156
        foreach ($this->attributes as $attribute) {
157
            $rows[] = $this->renderAttribute($attribute, $i++);
158
        }
159
160
        $options = $this->options;
161
        $tag = ArrayHelper::remove($options, 'tag', 'table');
162
        echo Html::tag($tag, implode("\n", $rows), $options);
163
    }
164
165
    /**
166
     * Renders a single attribute.
167
     * @param array $attribute the specification of the attribute to be rendered.
168
     * @param int $index the zero-based index of the attribute in the [[attributes]] array
169
     * @return string the rendering result
170
     */
171 4
    protected function renderAttribute($attribute, $index)
172
    {
173 4
        if (is_string($this->template)) {
174 4
            $captionOptions = Html::renderTagAttributes(ArrayHelper::getValue($attribute, 'captionOptions', []));
175 4
            $contentOptions = Html::renderTagAttributes(ArrayHelper::getValue($attribute, 'contentOptions', []));
176 4
            return strtr($this->template, [
177 4
                '{label}' => $attribute['label'],
178 4
                '{value}' => $this->formatter->format($attribute['value'], $attribute['format']),
179 4
                '{captionOptions}' => $captionOptions,
180 4
                '{contentOptions}' =>  $contentOptions,
181 4
            ]);
182
        } else {
183
            return call_user_func($this->template, $attribute, $index, $this);
184
        }
185
    }
186
187
    /**
188
     * Normalizes the attribute specifications.
189
     * @throws InvalidConfigException
190
     */
191 8
    protected function normalizeAttributes()
192
    {
193 8
        if ($this->attributes === null) {
194 3
            if ($this->model instanceof Model) {
195 1
                $this->attributes = $this->model->attributes();
196 3
            } elseif (is_object($this->model)) {
197 1
                $this->attributes = $this->model instanceof Arrayable ? array_keys($this->model->toArray()) : array_keys(get_object_vars($this->model));
198 2
            } elseif (is_array($this->model)) {
199 1
                $this->attributes = array_keys($this->model);
200 1
            } else {
201
                throw new InvalidConfigException('The "model" property must be either an array or an object.');
202
            }
203 3
            sort($this->attributes);
204 3
        }
205
206 8
        foreach ($this->attributes as $i => $attribute) {
207 8
            if (is_string($attribute)) {
208 6
                if (!preg_match('/^([^:]+)(:(\w*))?(:(.*))?$/', $attribute, $matches)) {
209
                    throw new InvalidConfigException('The attribute must be specified in the format of "attribute", "attribute:format" or "attribute:format:label"');
210
                }
211
                $attribute = [
212 6
                    'attribute' => $matches[1],
213 6
                    'format' => isset($matches[3]) ? $matches[3] : 'text',
214 6
                    'label' => isset($matches[5]) ? $matches[5] : null,
215 6
                ];
216 6
            }
217
218 8
            if (!is_array($attribute)) {
219
                throw new InvalidConfigException('The attribute configuration must be an array.');
220
            }
221
222 8
            if (isset($attribute['visible']) && !$attribute['visible']) {
223 1
                unset($this->attributes[$i]);
224 1
                continue;
225
            }
226
227 8
            if (!isset($attribute['format'])) {
228 3
                $attribute['format'] = 'text';
229 3
            }
230 8
            if (isset($attribute['attribute'])) {
231 8
                $attributeName = $attribute['attribute'];
232 8
                if (!isset($attribute['label'])) {
233 7
                    $attribute['label'] = $this->model instanceof Model ? $this->model->getAttributeLabel($attributeName) : Inflector::camel2words($attributeName, true);
234 7
                }
235 8
                if (!array_key_exists('value', $attribute)) {
236 7
                    $attribute['value'] = ArrayHelper::getValue($this->model, $attributeName);
237 7
                }
238 8
            } elseif (!isset($attribute['label']) || !array_key_exists('value', $attribute)) {
239
                throw new InvalidConfigException('The attribute configuration requires the "attribute" element to determine the value and display label.');
240
            }
241
242 8
            if ($attribute['value'] instanceof \Closure) {
243 2
                $attribute['value'] = call_user_func($attribute['value'], $this->model, $this);
244 2
            }
245
246 8
            $this->attributes[$i] = $attribute;
247 8
        }
248 8
    }
249
}
250