Skip to content

Commit ea7fbe9

Browse files
authored
Merge pull request #16728 from raicabogdan/5.0.x-breadcrumbs
Add new Breadcrumbs helper component
2 parents acd51de + 5dfb939 commit ea7fbe9

File tree

9 files changed

+803
-0
lines changed

9 files changed

+803
-0
lines changed

CHANGELOG-5.0.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
### Added
1010

11+
- Added `Phalcon\Html\Helper\Breadcrumbs` component to replace the old `Phalcon\Html\Breadcrumbs` component. [#16727](https://github.com/phalcon/cphalcon/issues/16727)
12+
1113
### Fixed
1214

1315
- Fixed `Phalcon\Mvc\Micro\LazyLoader::callMethod` to prevent `Unknown named parameter` error [#16724](https://github.com/phalcon/cphalcon/issues/16724)

phalcon/Html/Breadcrumbs.zep

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ use Phalcon\Di\DiInterface;
1818
* This component offers an easy way to create breadcrumbs for your application.
1919
* The resulting HTML when calling `render()` will have each breadcrumb enclosed
2020
* in `<dt>` tags, while the whole string is enclosed in `<dl>` tags.
21+
*
22+
* @deprecated Will be removed in future version
23+
* Use {@see Phalcon\Html\Helper\Breadcrumbs} instead.
2124
*/
2225
class Breadcrumbs
2326
{

phalcon/Html/Helper/Breadcrumbs.zep

Lines changed: 325 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,325 @@
1+
2+
/**
3+
* This file is part of the Phalcon Framework.
4+
*
5+
* (c) Phalcon Team <team@phalcon.io>
6+
*
7+
* For the full copyright and license information, please view the LICENSE.txt
8+
* file that was distributed with this source code.
9+
*/
10+
11+
namespace Phalcon\Html\Helper;
12+
13+
use Phalcon\Support\Helper\Str\Interpolate;
14+
use Phalcon\Html\Escaper\EscaperInterface;
15+
16+
/**
17+
* This component offers an easy way to create breadcrumbs for your application.
18+
* The resulting HTML when calling `render()` will have each breadcrumb enclosed
19+
* in `<li>` tags, while the whole string is enclosed in `<nav>` and `<ol>` tags.
20+
*
21+
* @phpstan-type TTemplate = array{
22+
* main: string,
23+
* line: string,
24+
* last: string,
25+
* }
26+
* @phpstan-type TElement = array{
27+
* attributes: array<string, string>,
28+
* icon: string,
29+
* link: string,
30+
* text: string,
31+
* }
32+
*/
33+
class Breadcrumbs extends AbstractHelper
34+
{
35+
/**
36+
* @var array<string, string>
37+
*/
38+
private attributes = [];
39+
/**
40+
* Keeps all the breadcrumbs.
41+
*
42+
* @var array<int, TElement>
43+
*/
44+
private data = [];
45+
/**
46+
* Crumb separator.
47+
*
48+
* @var string
49+
*/
50+
private separator = "<li>/</li>";
51+
/**
52+
* The HTML template to use to render the breadcrumbs.
53+
*
54+
* @var TTemplate
55+
*/
56+
private template = [
57+
"main": "
58+
<nav%attributes%>
59+
<ol>
60+
%items%
61+
</ol>
62+
</nav>",
63+
"line": "<li%attributes%><a href=\"%link%\">%icon%%text%</a></li>",
64+
"last": "<li><span%attributes%>%text%</span></li>"
65+
];
66+
67+
/**
68+
* The HTML template to use to render the breadcrumbs.
69+
*
70+
* @var Interpolate
71+
*/
72+
private interpolator;
73+
74+
/**
75+
* AbstractHelper constructor.
76+
*
77+
* @param EscaperInterface $escaper
78+
* @param string $indent = ""
79+
* @param string|null $delimiter = null
80+
*/
81+
public function __construct(<EscaperInterface> escaper) {
82+
parent::__construct(escaper);
83+
84+
let this->interpolator = new Interpolate();
85+
}
86+
87+
/**
88+
* Sets the indent and delimiter and returns the object back.
89+
*/
90+
public function __invoke(
91+
string indent = " ",
92+
string delimiter = null
93+
) -> <Breadcrumbs> {
94+
let this->delimiter = delimiter === null ? PHP_EOL : delimiter,
95+
this->indent = indent;
96+
97+
return this;
98+
}
99+
100+
/**
101+
* Adds a new crumb.
102+
*
103+
* ```php
104+
* // Adding a crumb with a link
105+
* $breadcrumbs->add("Home", "/");
106+
*
107+
* // Adding a crumb with added attributes
108+
* $breadcrumbs->add("Home", "/", ["class" => "main"]);
109+
*
110+
* // Adding a crumb without a link (normally the last one)
111+
* $breadcrumbs->add("Users");
112+
* ```
113+
*/
114+
public function add(
115+
string text,
116+
string link = "",
117+
string icon = "",
118+
array attributes = []
119+
) -> <Breadcrumbs> {
120+
var count;
121+
122+
let count = count(this->data) + 1;
123+
let this->data[count] = [
124+
"attributes": attributes,
125+
"icon" : icon,
126+
"link" : link,
127+
"text" : text
128+
];
129+
130+
return this;
131+
}
132+
133+
/**
134+
* Clears the crumbs.
135+
*
136+
* ```php
137+
* $breadcrumbs->clear()
138+
* ```
139+
*/
140+
public function clear() -> void
141+
{
142+
let this->data = [];
143+
}
144+
145+
/**
146+
* Clear the attributes of the parent element.
147+
*/
148+
public function clearAttributes() -> <Breadcrumbs>
149+
{
150+
let this->attributes = [];
151+
152+
return this;
153+
}
154+
155+
/**
156+
* Get the attributes of the parent element.
157+
*
158+
* @return array<string, string>
159+
*/
160+
public function getAttributes() -> array
161+
{
162+
return this->attributes;
163+
}
164+
165+
/**
166+
* Returns the separator.
167+
*/
168+
public function getSeparator() -> string
169+
{
170+
return this->separator;
171+
}
172+
173+
/**
174+
* Return the current template.
175+
*
176+
* @return TTemplate
177+
*/
178+
public function getTemplate() -> array
179+
{
180+
return this->template;
181+
}
182+
183+
/**
184+
* Removes crumb by url.
185+
*
186+
* ```php
187+
* // Remove the second element
188+
* $breadcrumbs->remove(2);
189+
* ```
190+
*/
191+
public function remove(int index) -> void
192+
{
193+
var elements;
194+
195+
let elements = this->data;
196+
unset elements[index];
197+
198+
let this->data = elements;
199+
}
200+
/**
201+
* Renders and outputs breadcrumbs based on previously set template.
202+
*
203+
* ```php
204+
* echo $breadcrumbs->render();
205+
* ```
206+
*/
207+
public function render() -> string
208+
{
209+
var lastUrl, lastElement, element;
210+
array output;
211+
/*
212+
* Early exit for empty data
213+
*/
214+
if empty this->data {
215+
return "";
216+
}
217+
218+
let output = [];
219+
let lastUrl = array_key_last(this->data);
220+
let lastElement = this->data[lastUrl];
221+
222+
unset this->data[lastUrl];
223+
224+
for element in this->data {
225+
let output[] = this->getLink(this->template["line"], element);
226+
}
227+
228+
/*
229+
* Last element
230+
*/
231+
let output[] = this->getLink(this->template["last"], lastElement);
232+
233+
return this->interpolator->__invoke(
234+
this->template["main"],
235+
[
236+
"attributes" : this->processAttributes(this->attributes),
237+
"delimiter" : this->delimiter,
238+
"indent" : this->indent,
239+
"items" : implode(
240+
this->indent . this->separator . this->delimiter,
241+
output
242+
)
243+
]
244+
);
245+
}
246+
247+
/**
248+
* Set the attributes for the parent element.
249+
*/
250+
public function setAttributes(array attributes) -> <Breadcrumbs>
251+
{
252+
let this->attributes = attributes;
253+
254+
return this;
255+
}
256+
257+
/**
258+
* Set the separator.
259+
*/
260+
public function setSeparator(string separator) -> <Breadcrumbs>
261+
{
262+
let this->separator = separator;
263+
264+
return this;
265+
}
266+
267+
/**
268+
* Set the HTML template.
269+
*/
270+
public function setTemplate(
271+
string main,
272+
string line,
273+
string last
274+
) -> <Breadcrumbs> {
275+
let this->template = [
276+
"main": main,
277+
"line": line,
278+
"last": last
279+
];
280+
281+
return this;
282+
}
283+
284+
/**
285+
* Returns the internal breadcrumbs array.
286+
*
287+
* @return array<int, TElement>
288+
*/
289+
public function toArray() -> array
290+
{
291+
return this->data;
292+
}
293+
294+
/**
295+
* @param TElement $element
296+
*/
297+
private function getLink(
298+
string template,
299+
array element
300+
) -> string {
301+
return this->indent
302+
.this->interpolator->__invoke(
303+
template,
304+
[
305+
"attributes" : this->processAttributes(element["attributes"]),
306+
"icon" : element["icon"],
307+
"text" : this->escaper->html(element["text"]),
308+
"link" : element["link"]
309+
]
310+
)
311+
.this->delimiter;
312+
}
313+
314+
/**
315+
* Processes attributes
316+
*/
317+
private function processAttributes(array attributes) -> string
318+
{
319+
var attributesRendered;
320+
321+
let attributesRendered = this->renderAttributes(attributes);
322+
323+
return rtrim(!empty(attributesRendered) ? " " . attributesRendered : "");
324+
}
325+
}

phalcon/Html/TagFactory.zep

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ namespace Phalcon\Html;
1212

1313
use Phalcon\Factory\AbstractFactory;
1414
use Phalcon\Html\Escaper\EscaperInterface;
15+
use Phalcon\Html\Helper\Breadcrumbs;
1516
use Phalcon\Html\Helper\Doctype;
1617
use Phalcon\Html\Helper\Input\Checkbox;
1718
use Phalcon\Html\Helper\Input\Color;
@@ -59,6 +60,7 @@ use Phalcon\Html\Link\Link;
5960
*
6061
* @method string a(string $href, string $text, array $attributes = [], bool $raw = false)
6162
* @method string base(string $href, array $attributes = [])
63+
* @method Breadcrumbs breadcrumbs(string $indent = ' ', string $delimiter = "\n")
6264
* @method string body(array $attributes = [])
6365
* @method string button(string $text, array $attributes = [], bool $raw = false)
6466
* @method string close(string $tag, bool $raw = false)
@@ -204,6 +206,7 @@ class TagFactory extends AbstractFactory
204206
return [
205207
"a" : "Phalcon\\Html\\Helper\\Anchor",
206208
"base" : "Phalcon\\Html\\Helper\\Base",
209+
"breadcrumbs" : "Phalcon\\Html\\Helper\\Breadcrumbs",
207210
"body" : "Phalcon\\Html\\Helper\\Body",
208211
"button" : "Phalcon\\Html\\Helper\\Button",
209212
"close" : "Phalcon\\Html\\Helper\\Close",

0 commit comments

Comments
 (0)