Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
19 / 19
100.00% covered (success)
100.00%
7 / 7
CRAP
100.00% covered (success)
100.00%
1 / 1
Dashboard
100.00% covered (success)
100.00%
19 / 19
100.00% covered (success)
100.00%
7 / 7
11
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 withDefaults
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 add
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 replace
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 cards
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 validated
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 validate
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
5
1<?php
2
3declare(strict_types=1);
4
5namespace Cosray\Panel;
6
7use Cosray\Contract\DashboardCard;
8use Cosray\Exception\RuntimeException;
9use Cosray\Panel\Dashboard\Drafts;
10use Cosray\Panel\Dashboard\Entries;
11use Cosray\Panel\Dashboard\Media;
12use ReflectionClass;
13
14final class Dashboard
15{
16    /** @var list<class-string<DashboardCard>|DashboardCard> */
17    private array $cards;
18
19    /** @param list<class-string<DashboardCard>|DashboardCard> $cards */
20    public function __construct(array $cards = [])
21    {
22        $this->cards = $this->validated($cards);
23    }
24
25    public static function withDefaults(): self
26    {
27        return new self([
28            Entries::class,
29            Drafts::class,
30            Media::class,
31        ]);
32    }
33
34    /** @param class-string<DashboardCard>|DashboardCard $card */
35    public function add(string|DashboardCard $card): self
36    {
37        $this->cards[] = $this->validate($card);
38
39        return $this;
40    }
41
42    /** @param class-string<DashboardCard>|DashboardCard ...$cards */
43    public function replace(string|DashboardCard ...$cards): self
44    {
45        $this->cards = $this->validated($cards);
46
47        return $this;
48    }
49
50    /** @return list<class-string<DashboardCard>|DashboardCard> */
51    public function cards(): array
52    {
53        return $this->cards;
54    }
55
56    /**
57     * @param list<class-string<DashboardCard>|DashboardCard> $cards
58     * @return list<class-string<DashboardCard>|DashboardCard>
59     */
60    private function validated(array $cards): array
61    {
62        return array_values(array_map($this->validate(...), $cards));
63    }
64
65    /**
66     * @param class-string<DashboardCard>|DashboardCard $card
67     * @return class-string<DashboardCard>|DashboardCard
68     */
69    private function validate(string|DashboardCard $card): string|DashboardCard
70    {
71        if ($card instanceof DashboardCard) {
72            return $card;
73        }
74
75        if (!class_exists($card) || !is_a($card, DashboardCard::class, true)) {
76            throw new RuntimeException('Dashboard cards must implement ' . DashboardCard::class . "{$card}");
77        }
78
79        if (!new ReflectionClass($card)->isInstantiable()) {
80            throw new RuntimeException("Dashboard card {$card} must be instantiable");
81        }
82
83        return $card;
84    }
85}