1 | <?php |
||
15 | class SetOperatorNodeSimplifier implements NodeSimplifier { |
||
16 | |||
17 | /** |
||
18 | * @see NodeSimplifier::isSimplifierFor |
||
19 | */ |
||
20 | 3 | public function isSimplifierFor(AbstractNode $node) { |
|
23 | |||
24 | /** |
||
25 | * @see NodeSimplifier::simplify |
||
26 | */ |
||
27 | 13 | public function simplify(AbstractNode $node) { |
|
28 | 13 | if($node instanceof UnionNode) { |
|
29 | 5 | return $this->simplifyUnionNode($node); |
|
30 | 8 | } elseif($node instanceof IntersectionNode) { |
|
31 | 7 | return $this->simplifyIntersectionNode($node); |
|
32 | } else { |
||
33 | 1 | throw new InvalidArgumentException('SetOperatorNodeSimplifier can only simplify UnionNode and IntersectionNode'); |
|
34 | } |
||
35 | } |
||
36 | |||
37 | 8 | private function simplifyUnionNode(UnionNode $node) { |
|
38 | 8 | $simplifiedOperands = $this->simplifyUnionOperands($this->getUnionOperands($node)); |
|
39 | |||
40 | 8 | switch(count($simplifiedOperands)) { |
|
41 | 8 | case 0: |
|
42 | 1 | return new ResourceListNode(); |
|
43 | 7 | case 1: |
|
44 | 4 | return reset($simplifiedOperands); |
|
45 | 4 | default: |
|
46 | 4 | return new UnionNode($simplifiedOperands); |
|
47 | 4 | } |
|
48 | } |
||
49 | |||
50 | 8 | private function getUnionOperands(UnionNode $node) { |
|
51 | 8 | $operands = array(); |
|
52 | |||
53 | 8 | foreach($node->getOperands() as $operand) { |
|
54 | 7 | if($operand instanceof IntersectionNode) { |
|
55 | $operand = $this->simplifyIntersectionNode($operand); |
||
56 | } |
||
57 | |||
58 | 7 | if($operand instanceof UnionNode) { |
|
59 | 1 | $operands = array_merge($operands, $this->getUnionOperands($operand)); |
|
60 | 1 | } else { |
|
61 | 7 | $operands[] = $operand; |
|
62 | } |
||
63 | 8 | } |
|
64 | |||
65 | 8 | return $operands; |
|
66 | } |
||
67 | |||
68 | 8 | private function simplifyUnionOperands(array $operands) { |
|
69 | 8 | list($resourceLists, $otherOperands) = $this->filterOperandsByType($operands, 'list'); |
|
70 | |||
71 | 8 | if(!empty($resourceLists)) { |
|
72 | 5 | $otherOperands[] = new ResourceListNode($resourceLists); |
|
73 | 5 | } |
|
74 | |||
75 | 8 | return $otherOperands; |
|
76 | } |
||
77 | |||
78 | 12 | private function filterOperandsByType(array $operands, $type) { |
|
79 | 12 | $filteredOperands = array(); |
|
80 | 12 | $otherOperands = array(); |
|
81 | |||
82 | /** @var AbstractNode $operand */ |
||
83 | 12 | foreach($operands as $operand) { |
|
84 | 10 | if($operand->getType() === $type) { |
|
85 | 9 | $filteredOperands[] = $operand; |
|
86 | 9 | } else { |
|
87 | 5 | $otherOperands[] = $operand; |
|
88 | } |
||
89 | 12 | } |
|
90 | |||
91 | 12 | return array($filteredOperands, $otherOperands); |
|
92 | } |
||
93 | |||
94 | 7 | private function simplifyIntersectionNode(IntersectionNode $node) { |
|
95 | 7 | $node = $this->simplifyLazilyIntersectionNode($node); |
|
96 | |||
97 | 7 | if($node instanceof IntersectionNode) { |
|
98 | 4 | return $this->moveUnionUnderIntersection($node); |
|
99 | } else { |
||
100 | 3 | return $node; |
|
101 | } |
||
102 | } |
||
103 | |||
104 | 7 | private function simplifyLazilyIntersectionNode(IntersectionNode $node) { |
|
105 | 7 | $simplifiedOperands = $this->simplifyIntersectionOperands($this->getIntersectionOperands($node)); |
|
106 | |||
107 | 7 | if(count($simplifiedOperands) === 1) { |
|
108 | 3 | return reset($simplifiedOperands); |
|
109 | } |
||
110 | |||
111 | 4 | return new IntersectionNode($simplifiedOperands); |
|
112 | } |
||
113 | |||
114 | 7 | private function getIntersectionOperands(IntersectionNode $node) { |
|
131 | |||
132 | 7 | private function simplifyIntersectionOperands(array $operands) { |
|
133 | 7 | list($resourceLists, $otherOperands) = $this->filterOperandsByType($operands, 'list'); |
|
134 | |||
135 | 7 | if(!empty($resourceLists)) { |
|
136 | 6 | $otherOperands[] = $this->doIntersection($resourceLists); |
|
137 | 6 | } |
|
138 | |||
141 | |||
142 | 6 | private function doIntersection(array $lists) { |
|
150 | |||
151 | 6 | private function intersect(array $list1, ResourceListNode $list2) { |
|
162 | |||
163 | 4 | private function moveUnionUnderIntersection(IntersectionNode $intersectionNode) { |
|
190 | } |
||
191 |