1: <?php
2:
3: namespace PHPixie\Database\Driver\Mongo\Parser\Conditions;
4:
5: class ExpandedGroup extends \PHPixie\Database\Conditions\Condition\Implementation
6: {
7: protected $groups = array();
8:
9: public function __construct($condition = null)
10: {
11: if ($condition !== null)
12: $this->add($condition);
13: }
14:
15: protected function addAnd($condition)
16: {
17: $newGroups = array();
18: if($condition instanceof ExpandedGroup) {
19: $groups = $condition->groups();
20:
21: if(empty($groups))
22: return;
23:
24: foreach ($this->groups as $group) {
25: foreach($groups as $conditionGroup) {
26: $newGroup = array();
27: foreach(array_merge($group, $conditionGroup) as $cond) {
28: $newGroup[] = clone $cond;
29: }
30: $newGroups[] = $newGroup;
31: }
32: }
33:
34: }else{
35: foreach ($this->groups as $group) {
36: $group[] = $condition;
37: $newGroups[] = $group;
38: }
39: }
40: $this->groups = $newGroups;
41: }
42:
43: protected function addOr($condition)
44: {
45: if ($condition instanceof ExpandedGroup) {
46: $this->groups = array_merge($this->groups, $condition->groups());
47: } else {
48: $this->groups[] = array($condition);
49: }
50: }
51:
52: public function add($condition, $logic = 'and')
53: {
54: $isExpandedGroup = $condition instanceof ExpandedGroup;
55: if(!$isExpandedGroup && !(($condition instanceof \PHPixie\Database\Conditions\Condition\Field\Operator))) {
56: throw new \PHPixie\Database\Exception\Parser("You can only add ExpandedGroup and Operator conditions");
57: }
58:
59: $condition = clone $condition;
60: if (empty($this->groups)) {
61:
62: if ($isExpandedGroup) {
63: $this->groups = $condition->groups();
64: } else {
65: $this->groups[] = array($condition);
66: }
67:
68: } elseif ($logic == 'and') {
69: $this->addAnd($condition);
70: } elseif ($logic == 'or') {
71: $this->addOr($condition);
72: } else {
73: throw new \PHPixie\Database\Exception\Parser("You can only use 'and' and 'or' logic");
74: }
75:
76: return $this;
77: }
78:
79: public function negate()
80: {
81: $groups = array(array());
82: $count = count($this->groups);
83: $negated = array();
84:
85: for ($i = $count - 1; $i >= 0; $i--) {
86:
87: $group = $this->groups[$i];
88: $merged = array();
89:
90: foreach ($group as $operator) {
91: if (!in_array($operator, $negated, true)) {
92: $operator = clone $operator;
93: $operator->negate();
94: $negated[] = $operator;
95: }
96:
97: foreach ($groups as $oldMerged) {
98: if (!$this->conditionInArray($operator, $oldMerged)) {
99: array_unshift($oldMerged, clone $operator);
100: }
101: $merged[] = $oldMerged;
102:
103: }
104: }
105:
106: $groups = $this->optimize($merged);
107: }
108: $this->groups = $groups;
109:
110: return $this;
111: }
112:
113: protected function optimize($groups)
114: {
115: $count = count($groups);
116: $remove = array();
117: for ($i = 0; $i < $count; $i++) {
118: for ($j = 0; $j < $count; $j++) {
119:
120: if ($i === $j)
121: continue;
122:
123: if ($this->isSubset($groups[$i], $groups[$j])) {
124: $remove[] = $j;
125: }
126:
127: }
128: }
129:
130: foreach($remove as $i)
131: unset($groups[$i]);
132:
133: return array_values($groups);
134: }
135:
136: protected function isSubset(&$subset, &$set)
137: {
138: foreach($subset as $item) {
139: if(!$this->conditionInArray($item, $set))
140: return false;
141: }
142:
143: return true;
144: }
145:
146: public function groups()
147: {
148: return $this->groups;
149: }
150:
151: public function __clone()
152: {
153: foreach ($this->groups as $key=>$group) {
154: foreach ($group as $itemKey => $item) {
155: $this->groups[$key][$itemKey] = clone $item;
156: }
157: }
158: }
159:
160: protected function conditionInArray($condition, $set)
161: {
162: foreach($set as $setCondition) {
163: if(
164: $condition->field() === $setCondition->field() &&
165: $condition->operator() === $setCondition->operator() &&
166: $condition->values() === $setCondition->values() &&
167: $condition->isNegated() === $setCondition->isNegated()
168: )
169: return true;
170: }
171:
172: return false;
173: }
174:
175: public function operatorConditions()
176: {
177: $conditions = array();
178: foreach ($this->groups as $group) {
179: foreach ($group as $item) {
180: $conditions[] = $item;
181: }
182: }
183: return $conditions;
184: }
185: }
186: