1: <?php
2:
3: namespace PHPixie\ORM\Models\Type\Database\Implementation;
4:
5: class Query extends \PHPixie\ORM\Conditions\Builder\Proxy
6: implements \PHPixie\ORM\Models\Type\Database\Query
7: {
8: 9: 10:
11: protected $values;
12: 13: 14:
15: protected $queryMapper;
16: 17: 18:
19: protected $queryPropertyMap;
20: 21: 22:
23: protected $container;
24: protected $config;
25:
26: protected $relationshipProperties;
27:
28: protected $limit;
29: protected $offset;
30:
31: protected $orderBy = array();
32:
33: public function __construct($values, $queryMapper, $queryPropertyMap, $container, $config)
34: {
35: parent::__construct($container);
36:
37: $this->container = $container;
38: $this->values = $values;
39: $this->queryMapper = $queryMapper;
40: $this->queryPropertyMap = $queryPropertyMap;
41: $this->config = $config;
42: }
43:
44: public function modelName()
45: {
46: return $this->config->model;
47: }
48:
49: public function limit($limit)
50: {
51: if (!is_numeric($limit))
52: throw new \PHPixie\ORM\Exception\Query("Limit must be a number");
53:
54: $this->limit = $limit;
55: return $this;
56: }
57:
58: public function getLimit()
59: {
60: return $this->limit;
61: }
62:
63: public function clearLimit()
64: {
65: $this->limit = null;
66: return $this;
67: }
68:
69: public function offset($offset)
70: {
71: if (!is_numeric($offset))
72: throw new \PHPixie\ORM\Exception\Query("Offset must be a number");
73:
74: $this->offset = $offset;
75: return $this;
76: }
77:
78: public function getOffset()
79: {
80: return $this->offset;
81: }
82:
83: public function clearOffset()
84: {
85: $this->offset = null;
86: return $this;
87: }
88:
89: public function orderAscendingBy($field)
90: {
91: $this->orderBy[] = $this->values->orderBy($field, 'asc');
92: return $this;
93: }
94:
95: public function orderDescendingBy($field)
96: {
97: $this->orderBy[] = $this->values->orderBy($field, 'desc');
98: return $this;
99: }
100:
101: public function getOrderBy()
102: {
103: return $this->orderBy;
104: }
105:
106: public function clearOrderBy()
107: {
108: $this->orderBy = array();
109: return $this;
110: }
111:
112: public function getConditions()
113: {
114: return $this->container->getConditions();
115: }
116:
117: public function find($preload = array())
118: {
119: return $this->planFind($preload)->execute();
120: }
121:
122: 123: 124: 125: 126:
127: public function findOne($preload = array())
128: {
129: $oldLimit = $this->getLimit();
130: $this->limit(1);
131:
132: $loader = $this->find($preload);
133:
134: if($oldLimit !== null)
135: {
136: $this->limit($oldLimit);
137: }else{
138: $this->clearLimit();
139: }
140:
141: if(!$loader->offsetExists(0))
142: return null;
143:
144: return $loader->getByOffset(0);
145: }
146:
147: public function planFind($preload = array())
148: {
149: $preloads = $this->values->preload();
150:
151: foreach($preload as $item) {
152: $preloads->add($item);
153: }
154:
155: return $this->queryMapper->mapFind($this, $preloads);
156: }
157:
158:
159:
160: public function update($updates)
161: {
162: $this->planUpdate($updates)->execute();
163: return $this;
164: }
165:
166: public function planUpdate($updates)
167: {
168: $update = $this->values->update($this);
169:
170: foreach($updates as $key => $value) {
171: $update->set($key, $value);
172: }
173:
174: return $this->planUpdateValue($update);
175: }
176:
177: public function delete()
178: {
179: $this->planDelete()->execute();
180: return $this;
181: }
182:
183: public function planDelete()
184: {
185: return $this->queryMapper->mapDelete($this);
186: }
187:
188: public function count()
189: {
190: return $this->planCount()->execute();
191: }
192:
193: public function planCount()
194: {
195: return $this->queryMapper->mapCount($this);
196: }
197:
198: public function getUpdateBuilder()
199: {
200: return $this->values->updateBuilder($this);
201: }
202:
203: public function planUpdateValue($update){
204: return $this->queryMapper->mapUpdate($this, $update);
205: }
206:
207: public function getRelationshipProperty($name)
208: {
209: $this->requirePropertyNames();
210:
211: if (!array_key_exists($name, $this->relationshipProperties)) {
212: throw new \PHPixie\ORM\Exception\Relationship("Relationship property '$name' is not defined for '{$this->modelName()}'");
213: }
214:
215: return $this->relationshipProperty($name);
216: }
217:
218: protected function relationshipProperty($name)
219: {
220: $property = $this->relationshipProperties[$name];
221:
222: if($property === null) {
223: $property = $this->queryPropertyMap->property($this, $name);
224: $this->relationshipProperties[$name] = $property;
225: }
226:
227: return $this->relationshipProperties[$name];
228: }
229:
230: public function __get($name)
231: {
232: return $this->getRelationshipProperty($name);
233: }
234:
235: public function __call($name, $params)
236: {
237: $this->requirePropertyNames();
238:
239: if (array_key_exists($name, $this->relationshipProperties)) {
240: $property = $this->relationshipProperty($name);
241: return call_user_func_array($property, $params);
242: }
243:
244: return parent::__call($name, $params);
245: }
246:
247: protected function requirePropertyNames()
248: {
249: if ($this->relationshipProperties === null) {
250: $propertyNames = $this->queryPropertyMap->getPropertyNames($this->modelName());
251: $this->relationshipProperties = array_fill_keys($propertyNames, null);
252: }
253: }
254: }
255: