-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathConfiguredChronoEngine.php
More file actions
147 lines (129 loc) · 4.36 KB
/
Copy pathConfiguredChronoEngine.php
File metadata and controls
147 lines (129 loc) · 4.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
<?php
namespace DirectoryTree\Chrono;
readonly class ConfiguredChronoEngine implements ChronoEngine
{
/**
* Create a Chrono engine from the given configuration.
*/
public function __construct(
protected readonly Configuration $configuration,
) {}
/**
* Parse the given text into ordered Chrono results.
*
* @return array<int, ParsedResult>
*/
public function parse(string $text, Reference $reference, Options $options): array
{
$results = array_merge(...array_map(
fn (Parser $parser) => $parser->parse($text, $reference, $options),
$this->configuration->parsers(),
));
$results = $this->attachReference($results, $reference);
$results = array_map(
fn (ParsedResult $result, int $order): array => [$result, $order],
$results,
array_keys($results),
);
usort($results, fn (array $a, array $b): int => $a[0]->index <=> $b[0]->index ?: $a[1] <=> $b[1]);
$results = array_map(fn (array $result): ParsedResult => $result[0], $results);
foreach ($this->configuration->refiners() as $refiner) {
$results = $this->attachReference(
$refiner->refine($text, $results, $reference, $options),
$reference,
);
}
return array_values($this->normalizeResultIndexes($text, $results));
}
/**
* Create a shallow copy of this engine with the same parser/refiner configuration.
*/
public function clone(): self
{
return $this->newInstance(new Configuration(
parsers: [...$this->configuration->parsers()],
refiners: [...$this->configuration->refiners()],
));
}
/**
* Return an engine instance with the given parser added.
*/
public function withParser(Parser $parser, bool $prepend = false): self
{
return $this->newInstance(
$prepend
? $this->configuration->prependParser($parser)
: $this->configuration->addParser($parser),
);
}
/**
* Return an engine instance with parsers matching the given class name removed.
*
* @param class-string<Parser> $parser
*/
public function withoutParser(string $parser): self
{
return $this->newInstance($this->configuration->removeParser($parser));
}
/**
* Return an engine instance with the given refiner added.
*/
public function withRefiner(Refiner $refiner, bool $prepend = false): self
{
return $this->newInstance(
$prepend
? $this->configuration->prependRefiner($refiner)
: $this->configuration->addRefiner($refiner),
);
}
/**
* Return an engine instance with refiners matching the given class name removed.
*
* @param class-string<Refiner> $refiner
*/
public function withoutRefiner(string $refiner): self
{
return $this->newInstance($this->configuration->removeRefiner($refiner));
}
/**
* Create a new configured engine instance.
*/
protected function newInstance(Configuration $configuration): static
{
return new static($configuration);
}
/**
* Attach upstream-style reference metadata to each parsed result.
*
* @param array<int, ParsedResult> $results
* @return array<int, ParsedResult>
*/
protected function attachReference(array $results, Reference $reference): array
{
return array_map(
fn (ParsedResult $result): ParsedResult => $result->withReference($reference),
$results,
);
}
/**
* Convert internal byte offsets to upstream-style string indexes.
*
* @param array<int, ParsedResult> $results
* @return array<int, ParsedResult>
*/
protected function normalizeResultIndexes(string $text, array $results): array
{
return array_map(function (ParsedResult $result) use ($text): ParsedResult {
$index = mb_strlen(substr($text, 0, $result->index), 'UTF-8');
return new ParsedResult(
$index,
$result->text,
$result->start,
$result->end,
$result->tags(),
$result->reference,
$result->refDate,
);
}, $results);
}
}