Issues (910)

framework/widgets/Breadcrumbs.php (1 issue)

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\InvalidConfigException;
12
use yii\base\Widget;
13
use yii\helpers\ArrayHelper;
14
use yii\helpers\Html;
15
16
/**
17
 * Breadcrumbs displays a list of links indicating the position of the current page in the whole site hierarchy.
18
 *
19
 * For example, breadcrumbs like "Home / Sample Post / Edit" means the user is viewing an edit page
20
 * for the "Sample Post". He can click on "Sample Post" to view that page, or he can click on "Home"
21
 * to return to the homepage.
22
 *
23
 * To use Breadcrumbs, you need to configure its [[links]] property, which specifies the links to be displayed. For example,
24
 *
25
 * ```php
26
 * // $this is the view object currently being used
27
 * echo Breadcrumbs::widget([
28
 *     'itemTemplate' => "<li><i>{link}</i></li>\n", // template for all links
29
 *     'links' => [
30
 *         [
31
 *             'label' => 'Post Category',
32
 *             'url' => ['post-category/view', 'id' => 10],
33
 *             'template' => "<li><b>{link}</b></li>\n", // template for this link only
34
 *         ],
35
 *         ['label' => 'Sample Post', 'url' => ['post/edit', 'id' => 1]],
36
 *         'Edit',
37
 *     ],
38
 * ]);
39
 * ```
40
 *
41
 * Because breadcrumbs usually appears in nearly every page of a website, you may consider placing it in a layout view.
42
 * You can use a view parameter (e.g. `$this->params['breadcrumbs']`) to configure the links in different
43
 * views. In the layout view, you assign this view parameter to the [[links]] property like the following:
44
 *
45
 * ```php
46
 * // $this is the view object currently being used
47
 * echo Breadcrumbs::widget([
48
 *     'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [],
49
 * ]);
50
 * ```
51
 *
52
 * @author Qiang Xue <[email protected]>
53
 * @since 2.0
54
 */
55
class Breadcrumbs extends Widget
56
{
57
    /**
58
     * @var string the name of the breadcrumb container tag.
59
     */
60
    public $tag = 'ul';
61
    /**
62
     * @var array the HTML attributes for the breadcrumb container tag.
63
     * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
64
     */
65
    public $options = ['class' => 'breadcrumb'];
66
    /**
67
     * @var bool whether to HTML-encode the link labels.
68
     */
69
    public $encodeLabels = true;
70
    /**
71
     * @var array|null the first hyperlink in the breadcrumbs (called home link).
72
     * Please refer to [[links]] on the format of the link.
73
     * If this property is not set, it will default to a link pointing to [[\yii\web\Application::homeUrl]]
74
     * with the label 'Home'. If this property is false, the home link will not be rendered.
75
     */
76
    public $homeLink;
77
    /**
78
     * @var array list of links to appear in the breadcrumbs. If this property is empty,
79
     * the widget will not render anything. Each array element represents a single link in the breadcrumbs
80
     * with the following structure:
81
     *
82
     * ```php
83
     * [
84
     *     'label' => 'label of the link',  // required
85
     *     'url' => 'url of the link',      // optional, will be processed by Url::to()
86
     *     'template' => 'own template of the item', // optional, if not set $this->itemTemplate will be used
87
     * ]
88
     * ```
89
     *
90
     * If a link is active, you only need to specify its "label", and instead of writing `['label' => $label]`,
91
     * you may simply use `$label`.
92
     *
93
     * Since version 2.0.1, any additional array elements for each link will be treated as the HTML attributes
94
     * for the hyperlink tag. For example, the following link specification will generate a hyperlink
95
     * with CSS class `external`:
96
     *
97
     * ```php
98
     * [
99
     *     'label' => 'demo',
100
     *     'url' => 'https://example.com',
101
     *     'class' => 'external',
102
     * ]
103
     * ```
104
     *
105
     * Since version 2.0.3 each individual link can override global [[encodeLabels]] param like the following:
106
     *
107
     * ```php
108
     * [
109
     *     'label' => '<strong>Hello!</strong>',
110
     *     'encode' => false,
111
     * ]
112
     * ```
113
     */
114
    public $links = [];
115
    /**
116
     * @var string the template used to render each inactive item in the breadcrumbs. The token `{link}`
117
     * will be replaced with the actual HTML link for each inactive item.
118
     */
119
    public $itemTemplate = "<li>{link}</li>\n";
120
    /**
121
     * @var string the template used to render each active item in the breadcrumbs. The token `{link}`
122
     * will be replaced with the actual HTML link for each active item.
123
     */
124
    public $activeItemTemplate = "<li class=\"active\">{link}</li>\n";
125
126
127
    /**
128
     * Renders the widget.
129
     */
130 5
    public function run()
131
    {
132 5
        if (empty($this->links)) {
133 1
            return;
134
        }
135 4
        $links = [];
136 4
        if ($this->homeLink === null) {
137 1
            $links[] = $this->renderItem([
138 1
                'label' => Yii::t('yii', 'Home'),
139 1
                'url' => Yii::$app->homeUrl,
0 ignored issues
show
Bug Best Practice introduced by
The property homeUrl does not exist on yii\console\Application. Since you implemented __get, consider adding a @property annotation.
Loading history...
140 1
            ], $this->itemTemplate);
141 3
        } elseif ($this->homeLink !== false) {
142 2
            $links[] = $this->renderItem($this->homeLink, $this->itemTemplate);
143
        }
144 4
        foreach ($this->links as $link) {
145 4
            if (!is_array($link)) {
146 4
                $link = ['label' => $link];
147
            }
148 4
            $links[] = $this->renderItem($link, isset($link['url']) ? $this->itemTemplate : $this->activeItemTemplate);
149
        }
150 4
        echo Html::tag($this->tag, implode('', $links), $this->options);
151
    }
152
153
    /**
154
     * Renders a single breadcrumb item.
155
     * @param array $link the link to be rendered. It must contain the "label" element. The "url" element is optional.
156
     * @param string $template the template to be used to rendered the link. The token "{link}" will be replaced by the link.
157
     * @return string the rendering result
158
     * @throws InvalidConfigException if `$link` does not have "label" element.
159
     */
160 10
    protected function renderItem($link, $template)
161
    {
162 10
        $encodeLabel = ArrayHelper::remove($link, 'encode', $this->encodeLabels);
163 10
        if (array_key_exists('label', $link)) {
164 9
            $label = $encodeLabel ? Html::encode($link['label']) : $link['label'];
165
        } else {
166 1
            throw new InvalidConfigException('The "label" element is required for each link.');
167
        }
168 9
        if (isset($link['template'])) {
169 1
            $template = $link['template'];
170
        }
171 9
        if (isset($link['url'])) {
172 4
            $options = $link;
173 4
            unset($options['template'], $options['label'], $options['url']);
174 4
            $link = Html::a($label, $link['url'], $options);
175
        } else {
176 6
            $link = $label;
177
        }
178
179 9
        return strtr($template, ['{link}' => $link]);
180
    }
181
}
182