Skip to content
This repository was archived by the owner on Jul 7, 2025. It is now read-only.

Commit 914b5f8

Browse files
Merge pull request #34 from Pixelrobin/icon-objects
Icon objects
2 parents f956f32 + 7e6534d commit 914b5f8

File tree

6 files changed

+241
-100
lines changed

6 files changed

+241
-100
lines changed

src/Icon.php

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php
2+
3+
namespace Feather;
4+
5+
class Icon
6+
{
7+
use SvgAttributesTrait;
8+
9+
private $name;
10+
11+
private $content;
12+
13+
public function __construct(string $name, array $attributes, string $content)
14+
{
15+
$this->name = $name;
16+
$this->attributes = $attributes;
17+
$this->content = $content;
18+
}
19+
20+
public function getName(): string
21+
{
22+
return $this->name;
23+
}
24+
25+
public function render(): string
26+
{
27+
$attributes = $this->filterAttributes($this->attributes);
28+
29+
$svgAttributes = \array_reduce(
30+
\array_keys($attributes),
31+
function ($final, $current) use ($attributes): string {
32+
$attributeValue = $attributes[$current];
33+
34+
if (\is_bool($attributeValue)) {
35+
$attributeValue = $attributeValue ? 'true' : 'false';
36+
}
37+
38+
$attributeValue = \htmlspecialchars((string)$attributeValue, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8', false);
39+
40+
return \sprintf('%s %s="%s"', $final, $current, $attributeValue);
41+
},
42+
''
43+
);
44+
45+
return '<svg ' . $svgAttributes . '>' . $this->content . '</svg>';
46+
}
47+
48+
private function filterAttributes(array $attributes): array
49+
{
50+
$classes = [
51+
'feather',
52+
'feather-' . $this->getName(),
53+
(string)($attributes['class'] ?? ''),
54+
];
55+
56+
$attributes['class'] = \trim(\implode(' ', $classes));
57+
58+
return \array_filter(
59+
$attributes,
60+
function ($item): bool {
61+
return $item !== null;
62+
}
63+
);
64+
}
65+
66+
public function __toString(): string
67+
{
68+
return $this->render();
69+
}
70+
}

src/IconManager.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
namespace Feather;
4+
5+
use Feather\Exception\IconNotFoundException;
6+
7+
class IconManager
8+
{
9+
use SvgAttributesTrait;
10+
11+
private $icons;
12+
13+
public function __construct()
14+
{
15+
$this->attributes = require \implode(DIRECTORY_SEPARATOR, [\dirname(__FILE__), '..', 'resources', 'attributes.php']);
16+
$this->icons = require \implode(DIRECTORY_SEPARATOR, [\dirname(__FILE__), '..', 'resources', 'icons.php']);
17+
}
18+
19+
public function getIconNames(): array
20+
{
21+
return \array_keys($this->icons);
22+
}
23+
24+
public function getIcon(string $name, array $attributes = []): Icon
25+
{
26+
if (!isset($this->icons[$name])) {
27+
throw new IconNotFoundException(\sprintf('Icon `%s` not found', $name));
28+
}
29+
30+
return new Icon($name, \array_merge($this->attributes, $attributes), $this->icons[$name]);
31+
}
32+
}

src/Icons.php

Lines changed: 0 additions & 70 deletions
This file was deleted.

src/SvgAttributesTrait.php

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
<?php
2+
3+
namespace Feather;
4+
5+
trait SvgAttributesTrait
6+
{
7+
private $attributes;
8+
9+
public function setAttributes(array $attributes): self
10+
{
11+
$this->attributes = \array_merge($this->attributes, $attributes);
12+
13+
return $this;
14+
}
15+
16+
public function setAttribute(string $key, $value): self
17+
{
18+
$this->attributes[$key] = $value;
19+
20+
return $this;
21+
}
22+
23+
public function removeAttribute(string $key): self
24+
{
25+
unset($this->attributes[$key]);
26+
27+
return $this;
28+
}
29+
30+
public function getAttributes(): array
31+
{
32+
return $this->attributes;
33+
}
34+
35+
/**
36+
* @return mixed
37+
*/
38+
public function getAttribute(string $name)
39+
{
40+
return $this->attributes[$name] ?? null;
41+
}
42+
43+
public function setSize(float $width, ?float $height = null): self
44+
{
45+
$this->setAttribute('width', $width)
46+
->setAttribute('height', $height ?? $width);
47+
48+
return $this;
49+
}
50+
51+
public function getSize(): array
52+
{
53+
return ['width' => $this->getAttribute('width'), 'height' => $this->getAttribute('height')];
54+
}
55+
56+
public function getWidth(): float
57+
{
58+
return (float)$this->getAttribute('width');
59+
}
60+
61+
public function getHeight(): float
62+
{
63+
return (float)$this->getAttribute('height');
64+
}
65+
66+
public function setColor(string $color): self
67+
{
68+
$this->setAttribute('stroke', $color);
69+
70+
return $this;
71+
}
72+
73+
public function getColor(): string
74+
{
75+
return (string)$this->getAttribute('stroke');
76+
}
77+
78+
public function setWeight(float $weight): self
79+
{
80+
$this->setAttribute('stroke-width', $weight);
81+
82+
return $this;
83+
}
84+
85+
public function getWeight(): float
86+
{
87+
return (float)$this->getAttribute('stroke-width');
88+
}
89+
90+
public function setCssClass(string $class): self
91+
{
92+
$this->setAttribute('class', $class);
93+
94+
return $this;
95+
}
96+
97+
public function addCssClass(string $class): self
98+
{
99+
$this->setAttribute('class', $this->getCssClass() . ' ' . $class);
100+
101+
return $this;
102+
}
103+
104+
public function getCssClass(): string
105+
{
106+
return (string)$this->getAttribute('class');
107+
}
108+
}

tests/AttributeTestData.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"name":"feather","attributes":{"stroke-width":1,"color":"red","aria-hidden":true,"class":"classymcclassface","alt":"Test \"quotes\""},"xml":"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"feather feather-feather classymcclassface\" alt=\"Test &quot;quotes&quot;\" color=\"red\" aria-hidden=\"true\"><path d=\"M20.24 12.24a6 6 0 0 0-8.49-8.49L5 10.5V19h8.5z\"></path><line x1=\"16\" y1=\"8\" x2=\"2\" y2=\"22\"></line><line x1=\"17.5\" y1=\"15\" x2=\"9\" y2=\"15\"></line></svg>"}
1+
{"name":"feather","attributes":{"stroke-width":1,"color":"red","aria-hidden":true,"class":"classymcclassface","alt":"Test \"quotes\" &amp;"},"xml":"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"feather feather-feather classymcclassface\" alt=\"Test &quot;quotes&quot; &amp;\" color=\"red\" aria-hidden=\"true\"><path d=\"M20.24 12.24a6 6 0 0 0-8.49-8.49L5 10.5V19h8.5z\"></path><line x1=\"16\" y1=\"8\" x2=\"2\" y2=\"22\"></line><line x1=\"17.5\" y1=\"15\" x2=\"9\" y2=\"15\"></line></svg>"}

0 commit comments

Comments
 (0)