1: <?php
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: class Whups_Query
27: {
28:
29:
30: const TYPE_AND = 1;
31: const TYPE_OR = 2;
32: const TYPE_NOT = 3;
33: const TYPE_CRITERION = 4;
34:
35:
36: const CRITERION_ID = 1;
37: const CRITERION_QUEUE = 2;
38: const CRITERION_TYPE = 3;
39: const CRITERION_STATE = 4;
40: const CRITERION_PRIORITY = 5;
41: const CRITERION_OWNERS = 7;
42: const CRITERION_REQUESTER = 8;
43: const CRITERION_GROUPS = 9;
44: const = 11;
45: const = 12;
46: const CRITERION_SUMMARY = 13;
47: const CRITERION_ATTRIBUTE = 14;
48: const CRITERION_VERSION = 15;
49: const CRITERION_TIMESTAMP = 16;
50: const CRITERION_UPDATED = 17;
51: const CRITERION_RESOLVED = 18;
52: const CRITERION_ASSIGNED = 19;
53: const CRITERION_DUE = 20;
54:
55:
56: const OPERATOR_GREATER = 1;
57: const OPERATOR_LESS = 2;
58: const OPERATOR_EQUAL = 3;
59:
60:
61: const OPERATOR_CI_SUBSTRING = 4;
62: const OPERATOR_CS_SUBSTRING = 5;
63: const OPERATOR_WORD = 6;
64: const OPERATOR_PATTERN = 7;
65:
66: 67: 68:
69: protected $_qManager;
70:
71: 72: 73: 74: 75:
76: public $id;
77:
78: 79: 80: 81: 82:
83: public $name;
84:
85: 86: 87: 88: 89:
90: public $slug;
91:
92: 93: 94:
95: public $query = array(
96: 'type' => Whups_Query::TYPE_AND,
97: 'children' => array());
98:
99: 100: 101:
102: public $parameters = array();
103:
104: 105: 106: 107: 108: 109:
110: function __construct(Whups_Query_Manager &$qManager, array $qDetails = array())
111: {
112: $this->_qManager = &$qManager;
113: if (isset($qDetails['query_id'])) {
114: $this->id = $qDetails['query_id'];
115: }
116: if (isset($qDetails['query_name'])) {
117: $this->name = $qDetails['query_name'];
118: }
119: if (isset($qDetails['query_slug'])) {
120: $this->slug = $qDetails['query_slug'];
121: }
122: if (isset($qDetails['query_object'])) {
123: $this->query = @unserialize($qDetails['query_object']);
124: }
125: if (isset($qDetails['query_parameters'])) {
126: $this->parameters = @unserialize($qDetails['query_parameters']);
127: }
128: }
129:
130: 131: 132:
133: public static function pathToString(&$path)
134: {
135: return implode(',', $path);
136: }
137:
138: 139: 140:
141: public static function stringToPath($pathstring)
142: {
143: if (!strlen($pathstring)) {
144: return array();
145: }
146:
147: return explode(',', $pathstring);
148: }
149:
150: 151: 152: 153: 154: 155: 156:
157: public static function textOperators()
158: {
159: return array(
160: Whups_Query::OPERATOR_EQUAL => _("Exact Match"),
161: Whups_Query::OPERATOR_CI_SUBSTRING => _("Case Insensitive Substring"),
162: Whups_Query::OPERATOR_CS_SUBSTRING => _("Case Sensitive Substring"),
163: Whups_Query::OPERATOR_WORD => _("Match Word"),
164: Whups_Query::OPERATOR_PATTERN => _("Match Pattern"));
165: }
166:
167: 168: 169: 170: 171: 172: 173: 174: 175:
176: public function hasPermission($userid, $permission, $creator = null)
177: {
178: return $this->_qManager->hasPermission($this->id, $userid, $permission, $creator);
179: }
180:
181: 182: 183: 184: 185:
186: public function save()
187: {
188: $this->_qManager->save($this);
189: }
190:
191: 192: 193: 194:
195: public function delete()
196: {
197: $this->_qManager->delete($this);
198: }
199:
200: 201: 202: 203: 204:
205: public function feedLink()
206: {
207: return '<link rel="alternate" type="application/rss+xml" title="' . htmlspecialchars($this->name) . '" href="' . Whups::urlFor('query_rss', empty($this->slug) ? array('id' => $this->id) : array('slug' => $this->slug), true, -1) . '" />';
208: }
209:
210: 211: 212: 213: 214:
215: public function getTabs(Horde_Variables $vars)
216: {
217:
218: $queryurl = Horde::url('query/index.php');
219: $edit = $this->hasPermission($GLOBALS['registry']->getAuth(), Horde_Perms::EDIT);
220: $delete = $this->hasPermission($GLOBALS['registry']->getAuth(), Horde_Perms::DELETE);
221:
222: $tabs = new Horde_Core_Ui_Tabs('action', $vars);
223: $tabs->addTab(_("Ne_w Query"), $queryurl, 'new');
224: if (!$this->id || $edit) {
225: $tabs->addTab(_("_Edit Query"), $queryurl, 'edit');
226: }
227: if ($this->id && $edit && empty($GLOBALS['conf']['share']['no_sharing'])) {
228: Horde::addScriptFile('popup.js', 'horde', true);
229:
230: $permsurl = $GLOBALS['registry']->get('webroot', 'horde') . '/services/shares/edit.php';
231: $permsurl = Horde_Util::addParameter(
232: $permsurl,
233: array(
234: 'app' => 'whups',
235: 'cid' => $this->id));
236: $tabs->addTab(
237: _("Edit _Permissions"),
238: $permsurl,
239: array(
240: 'tabname' => 'perms',
241: 'onclick' => 'popup(\'' . $permsurl . '\'); return false;',
242: 'target' => '_blank'));
243: }
244: $tabs->addTab(_("E_xecute Query"), Horde::url('query/run.php'), 'run');
245: $tabs->addTab(_("_Load Query"), $queryurl, 'load');
246: if ((!$this->id && $GLOBALS['registry']->getAuth()) ||
247: ($this->id && $edit)) {
248: $tabs->addTab(_("Sa_ve Query"), $queryurl, 'save');
249: }
250: if ($this->id && $delete) {
251: $tabs->addTab(_("_Delete Query"), $queryurl, 'delete');
252: }
253:
254: return $tabs;
255: }
256:
257: 258: 259: 260: 261: 262: 263: 264:
265: public function pathToForm(&$vars)
266: {
267: $path = Whups_Query::stringToPath($vars->get('path'));
268: $parent = null;
269: $qobj = $this->query;
270:
271: for ($i = 0, $c = count($path); $i < $c; $i++) {
272: $parent = $qobj;
273: $qobj = $qobj['children'][$path[$i]];
274: }
275:
276: if ($qobj['type'] != Whups_Query::TYPE_CRITERION) {
277:
278:
279: switch ($qobj['type']) {
280: case Whups_Query::TYPE_OR:
281:
282: $criteria = array();
283: foreach ($qobj['children'] as $child) {
284: if ($child['type'] != Whups_Query::TYPE_CRITERION ||
285: $child['criterion'] != Whups_Query::CRITERION_ID) {
286: $criteria = false;
287: break;
288: }
289: $criteria[] = $child['value'];
290: }
291: if ($criteria) {
292: $vars->set('id', implode(',', $criteria));
293: return 'props';
294: }
295:
296:
297: $criteria = array();
298: $operator = $value = null;
299: foreach ($qobj['children'] as $child) {
300: if ($child['type'] != Whups_Query::TYPE_CRITERION ||
301: ($child['criterion'] != Whups_Query::CRITERION_OWNERS &&
302: $child['criterion'] != Whups_Query::CRITERION_REQUESTER &&
303: $child['criterion'] != Whups_Query::CRITERION_ADDED_COMMENT) ||
304: (isset($operator) && $operator != $child['operator']) ||
305: (isset($value) && $value != $child['value'])) {
306: $criteria = false;
307: break;
308: }
309: $criteria[] = $child['criterion'];
310: $operator = $child['operator'];
311: $value = $child['value'];
312: }
313: if ($criteria) {
314: $vars->set('user', $value);
315: $vars->set('operator', $operator);
316: foreach ($criteria as $criterion) {
317: switch ($criterion) {
318: case Whups_Query::CRITERION_OWNERS:
319: $vars->set('owners', true);
320: break;
321: case Whups_Query::CRITERION_REQUESTER:
322: $vars->set('requester', true);
323: break;
324: case Whups_Query::CRITERION_ADDED_COMMENT:
325: $vars->set('comments', true);
326: break;
327: }
328: }
329: return 'user';
330: }
331:
332:
333: $criteria = array();
334: $operator = $value = null;
335: foreach ($qobj['children'] as $child) {
336: if ($child['type'] != Whups_Query::TYPE_CRITERION ||
337: ($child['criterion'] != Whups_Query::CRITERION_COMMENT &&
338: $child['criterion'] != Whups_Query::CRITERION_SUMMARY) ||
339: (isset($operator) && $operator != $child['operator']) ||
340: (isset($value) && $value != $child['value'])) {
341: $criteria = false;
342: break;
343: }
344: $criteria[] = $child['criterion'];
345: $operator = $child['operator'];
346: $value = $child['value'];
347: }
348: if ($criteria) {
349: $vars->set('text', $value);
350: $vars->set('operator', $operator);
351: foreach ($criteria as $criterion) {
352: if ($criterion == Whups_Query::CRITERION_COMMENT) {
353: $vars->set('comments', true);
354: } elseif ($criterion == Whups_Query::CRITERION_SUMMARY) {
355: $vars->set('summary', true);
356: }
357: }
358: return 'text';
359: }
360:
361:
362: $attribs = array_keys($GLOBALS['whups_driver']->getAttributesForType());
363: $criteria = array();
364: $operator = $value = null;
365: foreach ($qobj['children'] as $child) {
366: if ($child['type'] != Whups_Query::TYPE_CRITERION ||
367: $child['criterion'] != Whups_Query::CRITERION_ATTRIBUTE ||
368: (isset($operator) && $operator != $child['operator']) ||
369: (isset($value) && $value != $child['value']) ||
370: !in_array($child['cvalue'], $attribs)) {
371: $criteria = false;
372: break;
373: }
374: $criteria[] = $child['cvalue'];
375: $operator = $child['operator'];
376: $value = $child['value'];
377: }
378: if ($criteria) {
379: $vars->set('text', $value);
380: $vars->set('operator', $operator);
381: foreach ($criteria as $criterion) {
382: $vars->set('a' . $criterion, true);
383: }
384: return 'attribs';
385: }
386: break;
387:
388: case Whups_Query::TYPE_AND:
389:
390: $criteria = false;
391: foreach ($qobj['children'] as $child) {
392: if ($child['type'] != Whups_Query::TYPE_CRITERION ||
393: ($child['criterion'] != Whups_Query::CRITERION_TIMESTAMP &&
394: $child['criterion'] != Whups_Query::CRITERION_UPDATED &&
395: $child['criterion'] != Whups_Query::CRITERION_RESOLVED &&
396: $child['criterion'] != Whups_Query::CRITERION_ASSIGNED &&
397: $child['criterion'] != Whups_Query::CRITERION_DUE)) {
398: $criteria = false;
399: break;
400: }
401: $criteria = true;
402: }
403: if ($criteria) {
404: foreach ($qobj['children'] as $child) {
405: switch ($child['criterion'] . $child['operator']) {
406: case Whups_Query::CRITERION_TIMESTAMP . Whups_Query::OPERATOR_GREATER:
407: $vars->set('ticket_timestamp[from]', $child['value']);
408: break;
409: case Whups_Query::CRITERION_TIMESTAMP . Whups_Query::OPERATOR_LESS:
410: $vars->set('ticket_timestamp[to]', $child['value']);
411: break;
412: case Whups_Query::CRITERION_UPDATED . Whups_Query::OPERATOR_GREATER:
413: $vars->set('date_updated[from]', $child['value']);
414: break;
415: case Whups_Query::CRITERION_UPDATED . Whups_Query::OPERATOR_LESS:
416: $vars->set('date_updated[to]', $child['value']);
417: break;
418: case Whups_Query::CRITERION_RESOLVED . Whups_Query::OPERATOR_GREATER:
419: $vars->set('date_resolved[from]', $child['value']);
420: break;
421: case Whups_Query::CRITERION_RESOLVED . Whups_Query::OPERATOR_LESS:
422: $vars->set('date_resolved[to]', $child['value']);
423: break;
424: case Whups_Query::CRITERION_ASSIGNED . Whups_Query::OPERATOR_GREATER:
425: $vars->set('date_assigned[from]', $child['value']);
426: break;
427: case Whups_Query::CRITERION_ASSIGNED . Whups_Query::OPERATOR_LESS:
428: $vars->set('date_assigned[to]', $child['value']);
429: break;
430: case Whups_Query::CRITERION_DUE . Whups_Query::OPERATOR_GREATER:
431: $vars->set('ticket_due[from]', $child['value']);
432: break;
433: case Whups_Query::CRITERION_DUE . Whups_Query::OPERATOR_LESS:
434: $vars->set('ticket_due[to]', $child['value']);
435: break;
436: }
437: }
438: return 'date';
439: }
440:
441:
442: if (count($qobj['children']) == 2 &&
443: $qobj['children'][0]['type'] == Whups_Query::TYPE_CRITERION &&
444: $qobj['children'][0]['criterion'] == Whups_Query::CRITERION_QUEUE &&
445: $qobj['children'][1]['type'] == Whups_Query::TYPE_CRITERION &&
446: $qobj['children'][1]['criterion'] == Whups_Query::CRITERION_VERSION) {
447: $vars->set('queue', $qobj['children'][0]['value']);
448: $vars->set('version', $qobj['children'][1]['value']);
449: return 'props';
450: }
451: break;
452: }
453: throw new Whups_Exception(_("This query element cannot be edited."));
454: }
455:
456: switch ($qobj['criterion']) {
457: case Whups_Query::CRITERION_ID:
458: $multiple = false;
459: if ($parent && $parent['type'] == Whups_Query::TYPE_OR) {
460: $multiple = array();
461: foreach ($parent['children'] as $child) {
462: if ($child['type'] != Whups_Query::TYPE_CRITERION ||
463: $child['criterion'] != Whups_Query::CRITERION_ID) {
464: $multiple = false;
465: break;
466: }
467: $multiple[] = $child['value'];
468: }
469: }
470: if ($multiple) {
471: array_pop($path);
472: $vars->set('path', Whups_Query::pathToString($path));
473: $vars->set('id', implode(',', $multiple));
474: } else {
475: $vars->set('id', $qobj['value']);
476: }
477: return 'props';
478:
479: case Whups_Query::CRITERION_QUEUE:
480: if ($parent && $parent['type'] == Whups_Query::TYPE_AND &&
481: count($parent['children']) == 2 &&
482: $parent['children'][1]['type'] == Whups_Query::TYPE_CRITERION &&
483: $parent['children'][1]['criterion'] == Whups_Query::CRITERION_VERSION) {
484: array_pop($path);
485: $vars->set('path', Whups_Query::pathToString($path));
486: $vars->set('version', $parent['children'][1]['value']);
487: }
488: $vars->set('queue', $qobj['value']);
489: return 'props';
490:
491: case Whups_Query::CRITERION_VERSION:
492: array_pop($path);
493: $vars->set('path', Whups_Query::pathToString($path));
494: $vars->set('queue', $parent['children'][0]['value']);
495: $vars->set('version', $qobj['value']);
496: return 'props';
497:
498: case Whups_Query::CRITERION_TYPE:
499: $vars->set('ttype', $qobj['value']);
500: return 'props';
501:
502: case Whups_Query::CRITERION_STATE:
503: $vars->set('state', $qobj['value']);
504: return 'props';
505:
506: case Whups_Query::CRITERION_PRIORITY:
507: $vars->set('priority', $qobj['value']);
508: return 'props';
509:
510: case Whups_Query::CRITERION_TIMESTAMP:
511: case Whups_Query::CRITERION_UPDATED:
512: case Whups_Query::CRITERION_RESOLVED:
513: case Whups_Query::CRITERION_ASSIGNED:
514: case Whups_Query::CRITERION_DUE:
515: $criteria = false;
516: if ($parent && $parent['type'] == Whups_Query::TYPE_AND) {
517: foreach ($parent['children'] as $child) {
518: if ($child['type'] != Whups_Query::TYPE_CRITERION ||
519: ($child['criterion'] != Whups_Query::CRITERION_TIMESTAMP &&
520: $child['criterion'] != Whups_Query::CRITERION_UPDATED &&
521: $child['criterion'] != Whups_Query::CRITERION_RESOLVED &&
522: $child['criterion'] != Whups_Query::CRITERION_ASSIGNED &&
523: $child['criterion'] != Whups_Query::CRITERION_DUE)) {
524: $criteria = false;
525: break;
526: }
527: $criteria = true;
528: }
529: }
530: if ($criteria) {
531: array_pop($path);
532: $vars->set('path', Whups_Query::pathToString($path));
533: foreach ($parent['children'] as $child) {
534: switch ($child['criterion'] . $child['operator']) {
535: case Whups_Query::CRITERION_TIMESTAMP . Whups_Query::OPERATOR_GREATER:
536: $vars->set('ticket_timestamp[from]', $child['value']);
537: break;
538: case Whups_Query::CRITERION_TIMESTAMP . Whups_Query::OPERATOR_LESS:
539: $vars->set('ticket_timestamp[to]', $child['value']);
540: break;
541: case Whups_Query::CRITERION_UPDATED . Whups_Query::OPERATOR_GREATER:
542: $vars->set('date_updated[from]', $child['value']);
543: break;
544: case Whups_Query::CRITERION_UPDATED . Whups_Query::OPERATOR_LESS:
545: $vars->set('date_updated[to]', $child['value']);
546: break;
547: case Whups_Query::CRITERION_RESOLVED . Whups_Query::OPERATOR_GREATER:
548: $vars->set('date_resolved[from]', $child['value']);
549: break;
550: case Whups_Query::CRITERION_RESOLVED . Whups_Query::OPERATOR_LESS:
551: $vars->set('date_resolved[to]', $child['value']);
552: break;
553: case Whups_Query::CRITERION_ASSIGNED . Whups_Query::OPERATOR_GREATER:
554: $vars->set('date_assigned[from]', $child['value']);
555: break;
556: case Whups_Query::CRITERION_ASSIGNED . Whups_Query::OPERATOR_LESS:
557: $vars->set('date_assigned[to]', $child['value']);
558: break;
559: case Whups_Query::CRITERION_DUE . Whups_Query::OPERATOR_GREATER:
560: $vars->set('ticket_due[from]', $child['value']);
561: break;
562: case Whups_Query::CRITERION_DUE . Whups_Query::OPERATOR_LESS:
563: $vars->set('ticket_due[to]', $child['value']);
564: break;
565: }
566: }
567: }
568: return 'date';
569:
570: case Whups_Query::CRITERION_OWNERS:
571: case Whups_Query::CRITERION_REQUESTER:
572: case Whups_Query::CRITERION_ADDED_COMMENT:
573: $criteria = false;
574: if ($parent && $parent['type'] == Whups_Query::TYPE_OR) {
575: $criteria = array();
576: foreach ($parent['children'] as $child) {
577: if ($child['type'] != Whups_Query::TYPE_CRITERION ||
578: !in_array($child['criterion'], array(Whups_Query::CRITERION_OWNERS, Whups_Query::CRITERION_REQUESTER, Whups_Query::CRITERION_ADDED_COMMENT))) {
579: $criteria = false;
580: break;
581: }
582: $criteria[] = $child['criterion'];
583: }
584: if ($criteria) {
585: array_pop($path);
586: $vars->set('path', Whups_Query::pathToString($path));
587: }
588: }
589: if (!$criteria) {
590: $criteria = array($qobj['criterion']);
591: }
592: $vars->set('user', $qobj['value']);
593: $vars->set('operator', $qobj['operator']);
594: foreach ($criteria as $criterion) {
595: switch ($criterion) {
596: case Whups_Query::CRITERION_OWNERS:
597: $vars->set('owners', true);
598: break;
599: case Whups_Query::CRITERION_REQUESTER:
600: $vars->set('requester', true);
601: break;
602: case Whups_Query::CRITERION_ADDED_COMMENT:
603: $vars->set('comments', true);
604: break;
605: }
606: }
607: return 'user';
608:
609: case Whups_Query::CRITERION_GROUPS:
610: $vars->set('groups', $qobj['value']);
611: return 'group';
612:
613: case Whups_Query::CRITERION_COMMENT:
614: case Whups_Query::CRITERION_SUMMARY:
615: $criteria = false;
616: if ($parent && $parent['type'] == Whups_Query::TYPE_OR) {
617: $criteria = array();
618: $operator = $value = null;
619: foreach ($parent['children'] as $child) {
620: if ($child['type'] != Whups_Query::TYPE_CRITERION ||
621: ($child['criterion'] != Whups_Query::CRITERION_COMMENT &&
622: $child['criterion'] != Whups_Query::CRITERION_SUMMARY) ||
623: (isset($operator) && $operator != $child['operator']) ||
624: (isset($value) && $value != $child['value'])) {
625: $criteria = false;
626: break;
627: }
628: $criteria[] = $child['criterion'];
629: $operator = $child['operator'];
630: $value = $child['value'];
631: }
632: if ($criteria) {
633: array_pop($path);
634: $vars->set('path', Whups_Query::pathToString($path));
635: }
636: } else {
637: $operator = $qobj['operator'];
638: $value = $qobj['value'];
639: }
640: if (!$criteria) {
641: $criteria = array($qobj['criterion']);
642: }
643: $vars->set('text', $value);
644: $vars->set('operator', $operator);
645: foreach ($criteria as $criterion) {
646: if ($criterion == Whups_Query::CRITERION_COMMENT) {
647: $vars->set('comments', true);
648: } elseif ($criterion == Whups_Query::CRITERION_SUMMARY) {
649: $vars->set('summary', true);
650: }
651: }
652: return 'text';
653:
654: case Whups_Query::CRITERION_ATTRIBUTE:
655: $attribs = array_keys($GLOBALS['whups_driver']->getAttributesForType());
656: $criteria = false;
657: if ($parent && $parent['type'] == Whups_Query::TYPE_OR) {
658: $criteria = array();
659: $operator = $value = null;
660: foreach ($parent['children'] as $child) {
661: if ($child['type'] != Whups_Query::TYPE_CRITERION ||
662: $child['criterion'] != Whups_Query::CRITERION_ATTRIBUTE ||
663: (isset($operator) && $operator != $child['operator']) ||
664: (isset($value) && $value != $child['value']) ||
665: !in_array($child['cvalue'], $attribs)) {
666: $criteria = false;
667: break;
668: }
669: $criteria[] = $child['cvalue'];
670: $operator = $child['operator'];
671: $value = $child['value'];
672: }
673: if ($criteria) {
674: array_pop($path);
675: $vars->set('path', Whups_Query::pathToString($path));
676: }
677: } else {
678: $operator = $qobj['operator'];
679: $value = $qobj['value'];
680: }
681: if (!$criteria) {
682: $criteria = array($qobj['cvalue']);
683: }
684: $vars->set('text', $value);
685: $vars->set('operator', $operator);
686: foreach ($criteria as $criterion) {
687: $vars->set('a' . $criterion, true);
688: }
689: return 'attribs';
690: }
691:
692: throw new Whups_Exception(_("This query element cannot be edited."));
693: }
694:
695: public function deleteNode($pathstring)
696: {
697: $path = Whups_Query::stringToPath($pathstring);
698: $qobj = &$this->query;
699:
700: if (!strlen($pathstring)) {
701:
702: $GLOBALS['notification']->push(_("Choose New Query instead of deleting the root node."), 'horde.warning');
703: return false;
704: } else {
705: $count = count($path) - 1;
706: for ($i = 0; $i < $count; $i++) {
707: $qobj = &$qobj['children'][$path[$i]];
708: }
709:
710: if (!empty($qobj['children'][$path[$count]]['value']) &&
711: $this->_getParameterName($qobj['children'][$path[$count]]['value']) !== null) {
712: unset($this->parameters[array_search($pn, $this->parameters)]);
713: }
714:
715: array_splice($qobj['children'], $path[$count], 1);
716: }
717: }
718:
719: public function hoist($pathstring)
720: {
721: $path = Whups_Query::stringToPath($pathstring);
722: $qobj = &$this->query;
723:
724: if (!strlen($pathstring)) {
725:
726: } else {
727: $count = count($path) - 1;
728:
729: for ($i = 0; $i < $count; $i++) {
730: $qobj = &$qobj['children'][$path[$i]];
731: }
732:
733: $cobj = &$qobj['children'][$path[$count]];
734:
735:
736: array_splice($qobj['children'], $path[$count], 0, $cobj['children']);
737: array_splice($cobj['children'], 0, count($cobj['children']));
738: }
739: }
740:
741: public function insertBranch($pathstring, $type)
742: {
743: $path = Whups_Query::stringToPath($pathstring);
744: $qobj = &$this->query;
745:
746: $newbranch = array(
747: 'type' => $type,
748: 'children' => array());
749:
750: $count = count($path);
751:
752: for ($i = 0; $i < $count; $i++) {
753: $qobj = &$qobj['children'][$path[$i]];
754: }
755:
756: if (!isset($qobj['children']) ||
757: !is_array($qobj['children'])) {
758: $qobj['children'] = array();
759: }
760:
761: $qobj['children'][] = $newbranch;
762: $path[] = count($qobj['children']) - 1;
763:
764: return Whups_Query::pathToString($path);
765: }
766:
767: public function insertCriterion($pathstring, $criterion, $cvalue, $operator, $value)
768: {
769: $path = Whups_Query::stringToPath($pathstring);
770: $qobj = &$this->query;
771:
772: $value = trim($value);
773: if ($value[0] == '"') {
774:
775: $value = substr($value, 1, -1);
776: } else {
777: $pn = $this->_getParameterName($value);
778: if ($pn !== null) {
779: $this->parameters[] = $pn;
780: }
781: }
782:
783: $newbranch = array(
784: 'type' => Whups_Query::TYPE_CRITERION,
785: 'criterion' => $criterion,
786: 'cvalue' => $cvalue,
787: 'operator' => $operator,
788: 'value' => $value);
789:
790: $count = count($path);
791: for ($i = 0; $i < $count; $i++) {
792: $qobj = &$qobj['children'][$path[$i]];
793: }
794:
795: $qobj['children'][] = $newbranch;
796: }
797:
798: 799: 800:
801: public function walk(&$obj, $method)
802: {
803: $path = array();
804: $more = array();
805: $this->_walk($this->query, $more, $path, $obj, $method);
806: }
807:
808: 809: 810:
811: protected function _walk(&$node, &$more, &$path, &$obj, $method)
812: {
813: if ($node['type'] == Whups_Query::TYPE_CRITERION) {
814: $obj->$method($more, $path, Whups_Query::TYPE_CRITERION, $node['criterion'],
815: $node['cvalue'], $node['operator'], $node['value']);
816: } else {
817: $obj->$method($more, $path, $node['type'], null, null, null, null);
818: }
819:
820: if (isset($node['children'])) {
821: $count = count($node['children']);
822:
823: for ($i = 0; $i < $count; $i++) {
824: $path[] = $i;
825: $more[] = ($i < $count - 1);
826: $this->_walk($node['children'][$i], $more, $path, $obj, $method);
827: array_pop($more);
828: array_pop($path);
829: }
830: }
831: }
832:
833: 834: 835:
836: public function reduce($method, &$vars)
837: {
838: return $this->_reduce($this->query, $method, $vars);
839: }
840:
841: 842: 843:
844: protected function _reduce(&$node, $method, &$vars)
845: {
846: $args = array();
847:
848: if (isset($node['children'])) {
849: $count = count($node['children']);
850:
851: for ($i = 0; $i < $count; $i++) {
852: $result = $this->_reduce($node['children'][$i], $method, $vars);
853: $args[] = $result;
854: }
855: }
856:
857: if ($node['type'] == Whups_Query::TYPE_CRITERION) {
858: $value = $node['value'];
859:
860: $pn = $this->_getParameterName($value);
861: if ($pn !== null) {
862: $value = $vars->get($pn);
863: }
864:
865: return call_user_func(
866: $method, $args, Whups_Query::TYPE_CRITERION, $node['criterion'],
867: $node['cvalue'], $node['operator'], $value);
868: }
869:
870: return call_user_func($method, $args, $node['type'], null, null, null, null);
871: }
872:
873: 874: 875:
876: protected function _getParameterName($value)
877: {
878: if (strcmp(substr($value, 0, 2), '${'))
879: return null;
880:
881: $pn = substr($value, 2, -1);
882: if (!is_string($pn))
883: $pn = null;
884:
885: return $pn;
886: }
887:
888: }
889: