Skip to content

Commit 311689c

Browse files
committed
[Map] Refactor and simplify the way to create a custom Icon
1 parent 73151f6 commit 311689c

File tree

11 files changed

+265
-105
lines changed

11 files changed

+265
-105
lines changed

src/Map/doc/index.rst

+14-9
Original file line numberDiff line numberDiff line change
@@ -137,19 +137,24 @@ Add Marker icons
137137

138138
.. versionadded:: 2.24
139139

140-
``Marker`` icon customizatisation is available since UX Map 2.24.
141-
When returning a Map, it's quite common to want to customize ``Marker`` icon. It is possible thanks to ``icon`` parameter and ``Icon`` class::
142-
143-
// It can be a UX Icon (requires `symfony/ux-icons`)
144-
$icon = Icon::fromUxIcon('fa:map-marker');
140+
``Marker`` icon customization is available since UX Map 2.24.
141+
142+
A ``Marker`` can be customized with an ``Icon`` instance, which can either be an UX Icon, an URL, or a SVG content::
143+
144+
// It can be a UX Icon (requires `symfony/ux-icons` package)
145+
$icon = Icon::ux('fa:map-marker');
145146
// Or an URL pointing to an image
146-
$icon = Icon::fromUrl('https://example.com/marker.png');
147+
$icon = Icon::url('https://example.com/marker.png');
147148
// Or a plain SVG content
148-
$icon = Icon::fromInlineSVG('<svg>(...)</svg>');
149-
new Marker(
149+
$icon = Icon::svg('<svg>(...)</svg>');
150+
151+
// Configure the icon size with the `width()` and `height()` methods
152+
$icon = Icon::ux('fa:map-marker')->width(48)->height(48);
153+
154+
$map->addMarker(new Marker(
150155
// ...
151156
icon: $icon
152-
))
157+
));
153158

154159
Remove elements from Map
155160
~~~~~~~~~~~~~~~~~~~~~~~~

src/Map/src/Bridge/Google/tests/GoogleRendererTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public function provideTestRenderMap(): iterable
3131
->center(new Point(48.8566, 2.3522))
3232
->zoom(12);
3333
$marker1 = new Marker(position: new Point(48.8566, 2.3522), title: 'Paris', id: 'marker1');
34-
$marker2 = new Marker(position: new Point(48.8566, 2.3522), title: 'Lyon', infoWindow: new InfoWindow(content: 'Lyon'), id: 'marker2', icon: Icon::fromInlineSVG(html: '<svg></svg>'));
34+
$marker2 = new Marker(position: new Point(48.8566, 2.3522), title: 'Lyon', infoWindow: new InfoWindow(content: 'Lyon'), id: 'marker2', icon: Icon::svg(html: '<svg></svg>'));
3535
$marker3 = new Marker(position: new Point(45.8566, 2.3522), title: 'Dijon', id: 'marker3');
3636

3737
yield 'simple map, with minimum options' => [

src/Map/src/Bridge/Leaflet/tests/LeafletRendererTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public function provideTestRenderMap(): iterable
3131
->zoom(12);
3232

3333
$marker1 = new Marker(position: new Point(48.8566, 2.3522), title: 'Paris', id: 'marker1');
34-
$marker2 = new Marker(position: new Point(48.8566, 2.3522), title: 'Lyon', infoWindow: new InfoWindow(content: 'Lyon'), id: 'marker2', icon: Icon::fromInlineSVG(html: '<svg></svg>'));
34+
$marker2 = new Marker(position: new Point(48.8566, 2.3522), title: 'Lyon', infoWindow: new InfoWindow(content: 'Lyon'), id: 'marker2', icon: Icon::svg(html: '<svg></svg>'));
3535
$marker3 = new Marker(position: new Point(45.8566, 2.3522), title: 'Dijon', id: 'marker3');
3636

3737
yield 'simple map' => [

src/Map/src/Icon/Icon.php

+63-47
Original file line numberDiff line numberDiff line change
@@ -17,77 +17,93 @@
1717
* Represents an icon that can be displayed on a map marker.
1818
*
1919
* @author Sylvain Blondeau <[email protected]>
20+
* @author Hugo Alliaume <[email protected]>
2021
*/
21-
class Icon
22+
abstract class Icon
2223
{
23-
public const TYPE_URL = 'url';
24-
public const TYPE_INLINE_SVG = 'inline-svg';
25-
public const TYPE_UX_ICON = 'ux-icon';
24+
/**
25+
* @param non-empty-string $url
26+
*/
27+
public static function url(string $url): UrlIcon
28+
{
29+
return new UrlIcon($url);
30+
}
2631

27-
private function __construct(
28-
public string $content,
29-
public string $type,
30-
public int $width = 24,
31-
public int $height = 24,
32-
) {
32+
/**
33+
* @param non-empty-string $html
34+
*/
35+
public static function svg(string $html): SvgIcon
36+
{
37+
return new SvgIcon($html);
3338
}
3439

35-
public function toArray(): array
40+
/**
41+
* @param non-empty-string $name
42+
*/
43+
public static function ux(string $name): UxIcon
3644
{
37-
return [
38-
'content' => $this->content,
39-
'type' => $this->type,
40-
'width' => $this->width,
41-
'height' => $this->height,
42-
];
45+
return new UxIcon($name);
46+
}
47+
48+
/**
49+
* @param positive-int $width
50+
* @param positive-int $height
51+
*/
52+
protected function __construct(
53+
protected IconType $type,
54+
protected int $width = 24,
55+
protected int $height = 24,
56+
) {
4357
}
4458

45-
public static function fromUrl(string $url, int $width = 24, int $height = 24): Url
59+
public function width(int $width): static
4660
{
47-
return new Url(
48-
content: $url,
49-
type: self::TYPE_URL,
50-
width: $width,
51-
height: $height
52-
);
61+
if ($width <= 0) {
62+
throw new InvalidArgumentException('Width must be greater than 0.');
63+
}
64+
65+
$this->width = $width;
66+
67+
return $this;
5368
}
5469

55-
public static function fromInlineSVG(string $html, int $width = 24, int $height = 24): InlineSvg
70+
public function height(int $height): static
5671
{
57-
return new InlineSvg(
58-
content: $html,
59-
type: self::TYPE_INLINE_SVG,
60-
width: $width,
61-
height: $height
62-
);
72+
if ($height <= 0) {
73+
throw new InvalidArgumentException('Height must be greater than 0.');
74+
}
75+
76+
$this->height = $height;
77+
78+
return $this;
6379
}
6480

65-
public static function fromUxIcon(string $name, int $width = 24, int $height = 24): UxIcon
81+
/**
82+
* @internal
83+
*/
84+
public function toArray(): array
6685
{
67-
return new UxIcon(
68-
content: $name,
69-
type: self::TYPE_UX_ICON,
70-
width: $width,
71-
height: $height
72-
);
86+
return [
87+
'type' => $this->type->value,
88+
'width' => $this->width,
89+
'height' => $this->height,
90+
];
7391
}
7492

7593
/**
76-
* @param array{
77-
* content: string,
78-
* type: string,
79-
* width: int,
80-
* height: int,
81-
* } $data
94+
* @param array{ type: value-of<IconType>, width: positive-int, height: positive-int }
95+
* &(array{ url: non-empty-string }
96+
* |array{ html: non-empty-string }
97+
* |array{ name: non-empty-string }) $data
8298
*
8399
* @internal
84100
*/
85101
public static function fromArray(array $data): static
86102
{
87103
return match ($data['type']) {
88-
'url' => self::fromUrl($data['content'], (int) $data['width'], (int) $data['height']),
89-
'inline-svg' => self::fromInlineSvg($data['content'], (int) $data['width'], (int) $data['height']),
90-
'ux-icon' => self::fromUxIcon($data['content'], (int) $data['width'], (int) $data['height']),
104+
IconType::Url->value => UrlIcon::fromArray($data),
105+
IconType::Svg->value => SvgIcon::fromArray($data),
106+
IconType::UxIcon->value => UxIcon::fromArray($data),
91107
default => throw new InvalidArgumentException(\sprintf('Invalid icon type %s.', $data['type'])),
92108
};
93109
}

src/Map/src/Icon/InlineSvg.php renamed to src/Map/src/Icon/IconType.php

+5-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,11 @@
1414
/**
1515
* Represents an inline SVG icon.
1616
*
17-
* @author Sylvain Blondeau <[email protected]>
17+
* @author Hugo Alliaume <[email protected]>
1818
*/
19-
class InlineSvg extends Icon
19+
enum IconType: string
2020
{
21+
case Url = 'url';
22+
case Svg = 'svg';
23+
case UxIcon = 'ux-icon';
2124
}

src/Map/src/Icon/SvgIcon.php

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\UX\Map\Icon;
13+
14+
/**
15+
* Represents an inline SVG icon.
16+
*
17+
* @author Sylvain Blondeau <[email protected]>
18+
* @author Hugo Alliaume <[email protected]>
19+
*
20+
* @internal
21+
*/
22+
class SvgIcon extends Icon
23+
{
24+
/**
25+
* @param non-empty-string $html
26+
* @param positive-int $width
27+
* @param positive-int $height
28+
*/
29+
protected function __construct(
30+
protected string $html,
31+
int $width = 24,
32+
int $height = 24,
33+
) {
34+
parent::__construct(IconType::Svg, $width, $height);
35+
}
36+
37+
/**
38+
* @param array{ html: string, width: positive-int, height: positive-int } $data
39+
*/
40+
public static function fromArray(array $data): static
41+
{
42+
return new self(
43+
html: $data['html'],
44+
width: $data['width'],
45+
height: $data['height'],
46+
);
47+
}
48+
49+
public function toArray(): array
50+
{
51+
return [
52+
...parent::toArray(),
53+
'html' => $this->html,
54+
];
55+
}
56+
}

src/Map/src/Icon/Url.php

-21
This file was deleted.

src/Map/src/Icon/UrlIcon.php

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\UX\Map\Icon;
13+
14+
/**
15+
* Represents an URL icon.
16+
*
17+
* @author Sylvain Blondeau <[email protected]>
18+
* @author Hugo Alliaume <[email protected]>
19+
*
20+
* @internal
21+
*/
22+
class UrlIcon extends Icon
23+
{
24+
/**
25+
* @param non-empty-string $url
26+
* @param positive-int $width
27+
* @param positive-int $height
28+
*/
29+
protected function __construct(
30+
protected string $url,
31+
int $width = 24,
32+
int $height = 24,
33+
) {
34+
parent::__construct(IconType::Url, $width, $height);
35+
}
36+
37+
public static function fromArray(array $data): static
38+
{
39+
return new self(
40+
url: $data['url'],
41+
width: $data['width'],
42+
height: $data['height'],
43+
);
44+
}
45+
46+
public function toArray(): array
47+
{
48+
return [
49+
...parent::toArray(),
50+
'url' => $this->url,
51+
];
52+
}
53+
}

src/Map/src/Icon/UxIcon.php

+33-1
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,42 @@
1212
namespace Symfony\UX\Map\Icon;
1313

1414
/**
15-
* Represents an ux icon.
15+
* Represents an UX icon.
1616
*
1717
* @author Sylvain Blondeau <[email protected]>
18+
* @author Hugo Alliaume <[email protected]>
19+
*
20+
* @internal
1821
*/
1922
class UxIcon extends Icon
2023
{
24+
/**
25+
* @param non-empty-string $name
26+
* @param positive-int $width
27+
* @param positive-int $height
28+
*/
29+
protected function __construct(
30+
protected string $name,
31+
int $width = 24,
32+
int $height = 24,
33+
) {
34+
parent::__construct(IconType::UxIcon, $width, $height);
35+
}
36+
37+
public static function fromArray(array $data): static
38+
{
39+
return new self(
40+
name: $data['name'],
41+
width: $data['width'],
42+
height: $data['height'],
43+
);
44+
}
45+
46+
public function toArray(): array
47+
{
48+
return [
49+
...parent::toArray(),
50+
'name' => $this->name,
51+
];
52+
}
2153
}

0 commit comments

Comments
 (0)