Completed
Push — master ( ba64aa...13fe25 )
by Dmitrijs
02:37
created

Breadcrumbs::renderItem()   B

Complexity

Conditions 7
Paths 25

Size

Total Lines 34
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 19
dl 0
loc 34
c 0
b 0
f 0
rs 8.8333
cc 7
nc 25
nop 1
1
<?php
2
/**
3
 * @link https://github.com/DMGPage/yii2-materialize
4
 * @copyright Copyright (c) 2018 Dmitrijs Reinmanis
5
 * @license https://github.com/DMGPage/yii2-materialize/blob/master/LICENSE
6
 */
7
8
namespace dmgpage\yii2materialize\widgets;
9
10
use Yii;
11
use yii\base\InvalidConfigException;
12
use yii\base\Widget;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, dmgpage\yii2materialize\widgets\Widget. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
13
use yii\helpers\ArrayHelper;
14
use dmgpage\yii2materialize\helpers\Html;
15
use dmgpage\yii2materialize\helpers\Position;
16
use dmgpage\yii2materialize\assets\MaterializeExtraAsset;
17
18
/**
19
 * Breadcrumbs displays a list of links indicating the position of the current page in the whole site hierarchy.
20
 *
21
 * For example, breadcrumbs like "Home / Sample Post / Edit" means the user is viewing an edit page
22
 * for the "Sample Post". He can click on "Sample Post" to view that page, or he can click on "Home"
23
 * to return to the homepage.
24
 *
25
 * To use Breadcrumbs, you need to configure its [[links]] property, which specifies the links to be displayed. For example,
26
 *
27
 * ```php
28
 * echo Breadcrumbs::widget([
29
 *     'links' => [
30
 *         [
31
 *             'label' => 'Post Category',
32
 *             'url' => ['post-category/view', 'id' => 10],
33
 *             'target' => '_blank'
34
 *         ],
35
 *         [
36
 *             'label' => 'Sample Post',
37
 *             'url' => ['post/edit', 'id' => 1]
38
 *         ],
39
 *         'Edit',
40
 *     ],
41
 * ]);
42
 * ```
43
 *
44
 * Because breadcrumbs usually appears in nearly every page of a website, you may consider placing it in a layout view.
45
 * You can use a view parameter (e.g. `$this->params['breadcrumbs']`) to configure the links in different
46
 * views. In the layout view, you assign this view parameter to the [[links]] property like the following:
47
 *
48
 * ```php
49
 * // $this is the view object currently being used
50
 * echo Breadcrumbs::widget([
51
 *     'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [],
52
 * ]);
53
 * ```
54
 */
55
class Breadcrumbs extends Widget
56
{
57
    /**
58
     * @var array the HTML attributes for the breadcrumb container tag.
59
     * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
60
     */
61
    public $options = [];
62
63
    /**
64
     * @var array the HTML attributes for the breadcrumb wrapper tag.
65
     * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
66
     */
67
    public $wrapperOptions = [];
68
69
    /**
70
     * @var array the HTML attributes for the breadcrumb column tag.
71
     * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
72
     */
73
    public $columnOptions = [];
74
75
    /**
76
     * @var string the type of breadcrumb to be rendered
77
     * @see \dmgpage\yii2materialize\helpers\Type
78
     */
79
    public $type;
80
81
    /**
82
     * @var bool whether to HTML-encode the link labels.
83
     */
84
    public $encodeLabels = true;
85
86
    /**
87
     * @var array the first hyperlink in the breadcrumbs (called home link).
88
     * Please refer to [[links]] on the format of the link.
89
     * If this property is not set, it will default to a link pointing to [[\yii\web\Application::homeUrl]]
90
     * with the label 'Home'. If this property contains `['render' => false]`, the home link will not be rendered.
91
     */
92
    public $homeLink;
93
94
    /**
95
     * @var array list of links to appear in the breadcrumbs. If this property is empty,
96
     * the widget will not render anything. Each array element represents a single link in the breadcrumbs
97
     * with the following structure:
98
     *
99
     * ```php
100
     * [
101
     *     'label' => 'label of the link',  // required
102
     *     'url' => 'url of the link'      // optional, will be processed by Url::to()
103
     * ]
104
     * ```
105
     *
106
     * If a link is active, you only need to specify its "label", and instead of writing `['label' => $label]`,
107
     * you may simply use `$label`.
108
     */
109
    public $links = [];
110
111
    /**
112
     * Initialize the widget.
113
     */
114
    public function init()
115
    {
116
        if (!isset($this->wrapperOptions['class'])) {
117
            Html::addCssClass($this->wrapperOptions, 'nav-wrapper');
118
        }
119
120
        if (!isset($this->columnOptions['class'])) {
121
            Html::addCssClass($this->columnOptions, 'col s12');
122
        }
123
    }
124
125
    /**
126
     * Renders the widget.
127
     */
128
    public function run()
129
    {
130
        if (!empty($this->links)) {
131
            $links = [];
132
133
            if (empty($this->homeLink)) {
134
                $links[] = $this->renderItem(
135
                    [
136
                        'label' => Yii::t('yii', 'Home'),
137
                        'url' => Yii::$app->homeUrl
138
                    ]
139
                );
140
            } elseif (!isset($this->homeLink['render']) || $this->homeLink['render'] === true) {
141
                $links[] = $this->renderItem($this->homeLink);
142
            }
143
144
            foreach ($this->links as $link) {
145
                if (!is_array($link)) {
146
                    $link = ['label' => $link];
147
                }
148
149
                $links[] = $this->renderItem($link);
150
            }
151
152
            $column = Html::tag('div', implode('', $links), $this->columnOptions);
153
            $wraper = Html::tag('div', $column, $this->wrapperOptions);
154
155
            if (!empty($this->type)) {
156
                Html::addCssClass($this->options, $this->type);
157
                $view = $this->getView();
158
                MaterializeExtraAsset::register($view);
159
            }
160
161
            return Html::tag('nav', $wraper, $this->options);
162
        }
163
    }
164
165
    /**
166
     * Renders a single breadcrumb item.
167
     *
168
     * @param array $link the link to be rendered. It must contain the "label" element. The "url" element is optional.
169
     * @return string the rendering result
170
     * @throws InvalidConfigException if `$link` does not have "label" element.
171
     */
172
    protected function renderItem($link)
173
    {
174
        $encodeLabel = ArrayHelper::remove($link, 'encode', $this->encodeLabels);
175
176
        if (array_key_exists('label', $link)) {
177
            $label = $encodeLabel ? Html::encode($link['label']) : $link['label'];
178
        } else {
179
            throw new InvalidConfigException('The "label" element is required for each link.');
180
        }
181
182
        // Add icon to label text
183
        if (isset($link['icon'])) {
184
            $iconName = ArrayHelper::getValue($link['icon'], 'name', null);
185
            $iconOptions = ArrayHelper::getValue($link['icon'], 'options', []);
186
187
            // Default position is left, because right does not work for breadcrumb
188
            if (!isset($link['icon']['class'])) {
189
                Html::addCssClass($iconOptions, Position::LEFT);
190
            }
191
192
            $label = Html::icon($iconName, $iconOptions) . $label;
193
        }
194
195
        $options = $link;
196
        unset($options['label'], $options['url'], $options['icon']);
197
198
        if (!isset($options['class'])) {
199
            Html::addCssClass($options, 'breadcrumb');
200
        }
201
202
        if (isset($link['url'])) {
203
            return Html::a($label, $link['url'], $options);
204
        } else {
205
            return Html::tag('span', $label, $options) ;
206
        }
207
    }
208
}
209