Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
81.82% covered (warning)
81.82%
54 / 66
90.91% covered (success)
90.91%
10 / 11
CRAP
0.00% covered (danger)
0.00%
0 / 1
Column
81.82% covered (warning)
81.82%
54 / 66
90.91% covered (success)
90.91%
10 / 11
45.23
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 new
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 bold
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 italic
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 badge
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 date
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 sort
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 sortKey
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 kind
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 get
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
7
 getValue
67.57% covered (warning)
67.57%
25 / 37
0.00% covered (danger)
0.00%
0 / 1
29.05
1<?php
2
3declare(strict_types=1);
4
5namespace Cosray;
6
7use Closure;
8use Cosray\Node\Factory;
9use Cosray\Node\Wrapper;
10
11final class Column
12{
13    private bool|Closure $bold = false;
14    private bool|Closure $italic = false;
15    private bool|Closure $badge = false;
16    private bool|Closure $date = false;
17    private ?string $sort = null;
18    private string|Closure $color = '';
19
20    public function __construct(
21        public readonly string $title,
22        public readonly string|Closure $field,
23    ) {}
24
25    public static function new(
26        string|Closure $title,
27        string|Closure $field,
28    ): self {
29        return new self($title, $field);
30    }
31
32    public function bold(bool|Closure $bold): self
33    {
34        $this->bold = $bold;
35
36        return $this;
37    }
38
39    public function italic(bool|Closure $italic): self
40    {
41        $this->italic = $italic;
42
43        return $this;
44    }
45
46    public function badge(bool|Closure $badge): self
47    {
48        $this->badge = $badge;
49
50        return $this;
51    }
52
53    public function date(bool|Closure $date): self
54    {
55        $this->date = $date;
56
57        return $this;
58    }
59
60    public function sort(?string $sort): self
61    {
62        $sort = trim((string) $sort);
63        $this->sort = $sort === '' ? null : $sort;
64
65        return $this;
66    }
67
68    public function sortKey(): ?string
69    {
70        return $this->sort;
71    }
72
73    /**
74     * What the column holds, for the listing to size its track by. A date needs
75     * room a number does not, and a badge sizes to its own text. Flags resolved
76     * per node cannot be answered for the column as a whole, so they count as
77     * text â€” the safe assumption, since text is what shrinks gracefully.
78     */
79    public function kind(): string
80    {
81        if ($this->date === true) {
82            return 'date';
83        }
84
85        if ($this->badge === true) {
86            return 'badge';
87        }
88
89        return 'text';
90    }
91
92    public function get(Wrapper $node): array
93    {
94        return [
95            'value' => is_string($this->field)
96                ? $this->getValue($node, $this->field)
97                : ($this->field)($node),
98            'bold' => is_bool($this->bold) ? $this->bold : ($this->bold)($node),
99            'italic' => is_bool($this->italic) ? $this->italic : ($this->italic)($node),
100            'badge' => is_bool($this->badge) ? $this->badge : ($this->badge)($node),
101            'date' => is_bool($this->date) ? $this->date : ($this->date)($node),
102            'color' => is_string($this->color) ? $this->color : ($this->color)($node),
103        ];
104    }
105
106    private function getValue(Wrapper $node, string $field): mixed
107    {
108        $inner = Wrapper::unwrap($node);
109
110        switch ($field) {
111            case 'title':
112                return $node->label();
113            case 'meta.name':
114                return $node->meta->name;
115            case 'meta.uid':
116            case 'meta.published':
117            case 'meta.hidden':
118            case 'meta.locked':
119            case 'meta.created':
120            case 'meta.changed':
121            case 'meta.deleted':
122            case 'meta.content':
123            case 'meta.handle':
124                $key = explode('.', $field)[1];
125
126                return $node->meta->get($key);
127            case 'meta.class':
128                return $inner::class;
129            case 'meta.classname':
130                return basename(str_replace('\\', '/', $inner::class));
131            case 'meta.editor':
132                $editorData = (array) $node->meta->get('editor_data', []);
133
134                return (
135                    escape(
136                        $editorData['name'] ?? $node->meta->get('editor_username'),
137                    ) ?? $node->meta->get('editor_email')
138                );
139            case 'meta.creator':
140                $creatorData = (array) $node->meta->get('creator_data', []);
141
142                return (
143                    escape(
144                        $creatorData['name'] ?? $node->meta->get('creator_username'),
145                    ) ?? $node->meta->get('creator_email')
146                );
147            default:
148                $fieldObj = Factory::fieldFor($inner, $field);
149                $value = $fieldObj->value();
150
151                return $value->isset() ? (string) $value : null;
152        }
153    }
154}