-
Notifications
You must be signed in to change notification settings - Fork 1
/
TimesheetWalker.php
120 lines (94 loc) · 3.48 KB
/
TimesheetWalker.php
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
<?php
namespace Phpactor\Extension\Timekeeper\Adapter\Hoa;
use DateTimeImmutable;
use Hoa\Compiler\Llk\TreeNode;
use Phpactor\Extension\Timekeeper\Domain\Date;
use Phpactor\Extension\Timekeeper\Domain\Builder\DateBuilder;
use Phpactor\Extension\Timekeeper\Domain\Builder\EntryBuilder;
use Phpactor\Extension\Timekeeper\Domain\Builder\TimesheetBuilder;
use Phpactor\Extension\Timekeeper\Domain\Entry;
use Phpactor\Extension\Timekeeper\Domain\Exception\DefectException;
class TimesheetWalker
{
const NODE_CATEGORY = '#category';
const NODE_DATE = '#date';
const NODE_ENTRY = '#entry';
const NODE_ENTRY_LINE = '#entryline';
const NODE_TAG = '#tag';
const TOKEN_DATE = 'date';
const TOKEN_TEXT = 'text';
const TOKEN_TIME = 'time';
public function walk(TreeNode $node)
{
$builder = new TimesheetBuilder();
foreach ($node->getChildren() as $childNode) {
assert($childNode instanceof TreeNode);
if ($childNode->getId() === self::NODE_DATE) {
$builder->addDate($this->walkDate($childNode));
}
}
return $builder->build();
}
private function walkDate(TreeNode $node): Date
{
$date = $node->getValue();
$builder = new DateBuilder();
foreach ($node->getChildren() as $childNode) {
assert($childNode instanceof TreeNode);
if ($childNode->getValueToken() === self::TOKEN_DATE) {
$builder->date(new DateTimeImmutable($childNode->getValueValue()));
continue;
}
if ($childNode->getId() == self::NODE_ENTRY) {
$builder->addEntry($this->walkEntry($childNode));
continue;
}
}
return $builder->build();
}
private function walkEntry(TreeNode $childNode): Entry
{
$builder = new EntryBuilder();
foreach ($childNode->getChildren() as $childNode) {
assert($childNode instanceof TreeNode);
if ($childNode->getValueToken() === self::TOKEN_TIME) {
[ $hour, $minutes ] = explode(':', $childNode->getValueValue());
$builder->time($hour, $minutes);
continue;
}
if ($childNode->getValueToken() === self::TOKEN_TEXT) {
$builder->comment(trim($childNode->getValueValue()));
continue;
}
if ($childNode->getId() === self::NODE_CATEGORY) {
$builder->category($this->walkCategory($childNode));
continue;
}
if ($childNode->getId() === self::NODE_TAG) {
$builder->addTag($this->walkTag($childNode));
continue;
}
}
return $builder->build();
}
private function walkCategory(TreeNode $node): string
{
foreach ($node->getChildren() as $childNode) {
assert($childNode instanceof TreeNode);
if ($childNode->getValueToken() === 'name') {
return $childNode->getValueValue();
}
}
throw new DefectException('Category has no name');
}
private function walkTag(TreeNode $node)
{
foreach ($node->getChildren() as $childNode) {
assert($childNode instanceof TreeNode);
if ($childNode->getValueToken() === 'tag') {
return ltrim($childNode->getValueValue(), '@');
}
}
throw new DefectException('Tag has no name');
}
}