1: <?php
2:
3: namespace PHPixie\ORM\Conditions\Builder;
4:
5: class Container extends \PHPixie\Database\Conditions\Builder\Container
6: implements \PHPixie\ORM\Conditions\Builder
7: {
8: protected $conditions;
9: protected $relationshipMap;
10: protected $modelNameStack = array();
11: protected $currentModelName;
12:
13: public function __construct($conditions, $relationshipMap, $modelName, $defaultOperator = '=')
14: {
15: $this->conditions = $conditions;
16: $this->relationshipMap = $relationshipMap;
17: parent::__construct($defaultOperator);
18: $this->pushModelNameToStack($modelName);
19: }
20:
21: public function addOperatorCondition($logic, $negate, $field, $operator, $values)
22: {
23: $relationship = null;
24:
25: if (($pos = strpos($field, '>')) !== false || ($pos = strrpos($field, '.')) !== false) {
26: $relationship = substr($field, 0, $pos);
27: $field = substr($field, $pos + 1);
28: }
29:
30: $condition = $this->buildOperatorCondition($field, $operator, $values);
31: $this->addToRelationship($logic, $negate, $condition, $relationship);
32: return $this;
33: }
34:
35: public function startRelatedToConditionGroup($relationship, $logic = 'and', $negate = false)
36: {
37: $path = explode('.', $relationship);
38: $root = null;
39: $current = null;
40:
41: $modelName = $this->currentModelName;
42:
43: foreach ($path as $key => $step) {
44: $side = $this->relationshipMap->get($modelName, $step);
45: $modelName = $side->relatedModelName();
46:
47: $group = $this->buildRelatedToGroupCondition($step);
48:
49: if ($key == 0) {
50: $root = $group;
51: }else{
52: $current->add($group);
53: }
54:
55: $current = $group;
56: }
57:
58: $this->addCondition($logic, $negate, $root);
59: $this->pushGroupToStack($current);
60: $this->pushModelNameToStack($modelName);
61: return $this;
62: }
63:
64:
65: public function addRelatedToCondition($logic, $negate, $relationship, $condition = null)
66: {
67: $this->startRelatedToConditionGroup($relationship, $logic, $negate);
68: if($condition !== null) {
69: if (!is_callable($condition)) {
70: $this->addInCondition('and', false, $condition);
71: }else {
72: call_user_func($condition, $this);
73: }
74: }
75:
76: return $this->endGroup();
77: }
78:
79: public function addInCondition($logic, $negate, $items)
80: {
81: $condition = $this->buildInCondition($items);
82: return $this->addCondition($logic, $negate, $condition);
83: }
84:
85: protected function addToRelationship($logic, $negate, $condition, $relationship)
86: {
87: if ($relationship !== null) {
88: $this->startRelatedToConditionGroup($relationship, $logic, $negate);
89: $this->addCondition('and', false, $condition);
90: $this->endGroup();
91: }else{
92: $this->addCondition($logic, $negate, $condition);
93: }
94: }
95:
96: protected function pushModelNameToStack($modelName)
97: {
98: $this->modelNameStack[] = $modelName;
99: $this->currentModelName = $modelName;
100: }
101:
102: public function endGroup()
103: {
104: $oldGroup = $this->currentGroup;
105: parent::endGroup();
106:
107: if($oldGroup instanceof \PHPixie\ORM\Conditions\Condition\Collection\RelatedTo) {
108: array_pop($this->modelNameStack);
109: $this->currentModelName = end($this->modelNameStack);
110: }
111: return $this;
112: }
113:
114:
115: protected function buildGroupCondition()
116: {
117: return $this->conditions->group();
118: }
119:
120: protected function buildOperatorCondition($field, $operator, $values)
121: {
122: return $this->conditions->operator($field, $operator, $values);
123: }
124:
125: protected function buildPlaceholderCondition($allowEmpty)
126: {
127: return $this->conditions->placeholder(
128: $this->currentModelName,
129: $this->defaultOperator,
130: $allowEmpty
131: );
132: }
133:
134: protected function buildRelatedToGroupCondition($relationshipName)
135: {
136: return $this->conditions->relatedToGroup($relationshipName);
137: }
138:
139: protected function buildInCondition($items)
140: {
141: return $this->conditions->in($this->currentModelName, $items);
142: }
143:
144: public function addWhereOperatorCondition($logic, $negate, $field, $operator, $values)
145: {
146: return $this->addOperatorCondition($logic, $negate, $field, $operator, $values);
147: }
148:
149: public function startWhereConditionGroup($logic = 'and', $negate = false)
150: {
151: return $this->startConditionGroup($logic, $negate);
152: }
153:
154: public function addWherePlaceholder($logic = 'and', $negate = false, $allowEmpty = true)
155: {
156: return $this->addPlaceholder($logic, $negate, $allowEmpty);
157: }
158:
159: public function addWhereCondition($logic, $negate, $condition)
160: {
161: return $this->addCondition($logic, $negate, $condition);
162: }
163:
164: public function buildWhereCondition($logic, $negate, $args)
165: {
166: return $this->buildCondition($logic, $negate, $args);
167: }
168:
169: public function where()
170: {
171: return $this->buildCondition('and', false, func_get_args());
172: }
173:
174: public function andWhere()
175: {
176: return $this->buildCondition('and', false, func_get_args());
177: }
178:
179: public function orWhere()
180: {
181: return $this->buildCondition('or', false, func_get_args());
182: }
183:
184: public function xorWhere()
185: {
186: return $this->buildCondition('xor', false, func_get_args());
187: }
188:
189: public function whereNot()
190: {
191: return $this->buildCondition('and', true, func_get_args());
192: }
193:
194: public function andWhereNot()
195: {
196: return $this->buildCondition('and', true, func_get_args());
197: }
198:
199: public function orWhereNot()
200: {
201: return $this->buildCondition('or', true, func_get_args());
202: }
203:
204: public function xorWhereNot()
205: {
206: return $this->buildCondition('xor', true, func_get_args());
207: }
208:
209: public function startWhereGroup()
210: {
211: return $this->startConditionGroup('and', false);
212: }
213:
214: public function startAndWhereGroup()
215: {
216: return $this->startConditionGroup('and', false);
217: }
218:
219: public function startOrWhereGroup()
220: {
221: return $this->startConditionGroup('or', false);
222: }
223:
224: public function startXorWhereGroup()
225: {
226: return $this->startConditionGroup('xor', false);
227: }
228:
229: public function startWhereNotGroup()
230: {
231: return $this->startConditionGroup('and', true);
232: }
233:
234: public function startAndWhereNotGroup()
235: {
236: return $this->startConditionGroup('and', true);
237: }
238:
239: public function startOrWhereNotGroup()
240: {
241: return $this->startConditionGroup('or', true);
242: }
243:
244: public function startXorWhereNotGroup()
245: {
246: return $this->startConditionGroup('xor', true);
247: }
248:
249: public function endWhereGroup()
250: {
251: return $this->endGroup();
252: }
253:
254: public function in($items)
255: {
256: return $this->addInCondition('and', false, $items);
257: }
258:
259: public function andIn($items)
260: {
261: return $this->addInCondition('and', false, $items);
262: }
263:
264: public function orIn($items)
265: {
266: return $this->addInCondition('or', false, $items);
267: }
268:
269: public function xorIn($items)
270: {
271: return $this->addInCondition('xor', false, $items);
272: }
273:
274: public function notIn($items)
275: {
276: return $this->addInCondition('and', true, $items);
277: }
278:
279: public function andNotIn($items)
280: {
281: return $this->addInCondition('and', true, $items);
282: }
283:
284: public function orNotIn($items)
285: {
286: return $this->addInCondition('or', true, $items);
287: }
288:
289: public function xorNotIn($items)
290: {
291: return $this->addInCondition('xor', true, $items);
292: }
293:
294:
295: public function relatedTo($relationship, $items = null)
296: {
297: return $this->addRelatedToCondition('and', false, $relationship, $items);
298: }
299:
300: public function andRelatedTo($relationship, $items = null)
301: {
302: return $this->addRelatedToCondition('and', false, $relationship, $items);
303: }
304:
305: public function orRelatedTo($relationship, $items = null)
306: {
307: return $this->addRelatedToCondition('or', false, $relationship, $items);
308: }
309:
310: public function xorRelatedTo($relationship, $items = null)
311: {
312: return $this->addRelatedToCondition('xor', false, $relationship, $items);
313: }
314:
315: public function notRelatedTo($relationship, $items = null)
316: {
317: return $this->addRelatedToCondition('and', true, $relationship, $items);
318: }
319:
320: public function andNotRelatedTo($relationship, $items = null)
321: {
322: return $this->addRelatedToCondition('and', true, $relationship, $items);
323: }
324:
325: public function orNotRelatedTo($relationship, $items = null)
326: {
327: return $this->addRelatedToCondition('or', true, $relationship, $items);
328: }
329:
330: public function xorNotrelatedTo($relationship, $items = null)
331: {
332: return $this->addRelatedToCondition('xor', true, $relationship, $items);
333: }
334:
335:
336: public function startRelatedToGroup($relationship)
337: {
338: return $this->startRelatedToConditionGroup($relationship, 'and', false);
339: }
340:
341: public function startAndRelatedToGroup($relationship)
342: {
343: return $this->startRelatedToConditionGroup($relationship, 'and', false);
344: }
345:
346: public function startOrRelatedToGroup($relationship)
347: {
348: return $this->startRelatedToConditionGroup($relationship, 'or', false);
349: }
350:
351: public function startXorRelatedToGroup($relationship)
352: {
353: return $this->startRelatedToConditionGroup($relationship, 'xor', false);
354: }
355:
356: public function startNotRelatedToGroup($relationship)
357: {
358: return $this->startRelatedToConditionGroup($relationship, 'and', true);
359: }
360:
361: public function startAndNotRelatedToGroup($relationship)
362: {
363: return $this->startRelatedToConditionGroup($relationship, 'and', true);
364: }
365:
366: public function startOrNotRelatedToGroup($relationship)
367: {
368: return $this->startRelatedToConditionGroup($relationship, 'or', true);
369: }
370:
371: public function startXorNotRelatedToGroup($relationship)
372: {
373: return $this->startRelatedToConditionGroup($relationship, 'xor', true);
374: }
375:
376: }