1: <?php
2: /**
3: * You may not change or alter any portion of this comment or credits
4: * of supporting developers from this source code or any supporting source code
5: * which is considered copyrighted (c) material of the original comment or credit authors.
6: * This program is distributed in the hope that it will be useful,
7: * but WITHOUT ANY WARRANTY; without even the implied warranty of
8: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9: */
10:
11: namespace Xoops\Core\Kernel;
12:
13: use Xoops\Core\Database\Connection;
14:
15: /**
16: * XOOPS Kernel Persistable Object Handler class.
17: *
18: * @category Xoops\Core\Kernel\XoopsPersistableObjectHandler
19: * @package Xoops\Core\Kernel
20: * @author Taiwen Jiang <phppp@users.sourceforge.net>
21: * @author Jan Keller Pedersen <mithrandir@xoops.org>
22: * @copyright 2000-2015 XOOPS Project (http://xoops.org)
23: * @license GNU GPL 2 or later (http://www.gnu.org/licenses/gpl-2.0.html)
24: * @link http://xoops.org
25: * @since 2.0.0
26: */
27: abstract class XoopsPersistableObjectHandler extends XoopsObjectHandler
28: {
29: /**
30: * holds reference to custom extended object handler
31: *
32: * var object
33: *
34: * @access private
35: */
36: /**
37: * static protected
38: */
39: protected $handler;
40:
41: /**
42: * holds reference to predefined extended object handlers: read, stats, joint, write, sync
43: *
44: * The handlers hold methods for different purposes, which could be all put together inside of current class.
45: * However, load codes only if they are necessary, thus they are now split out.
46: *
47: * var array of objects
48: *
49: * @access private
50: */
51: private $handlers = array('read' => null, 'stats' => null, 'joint' => null, 'write' => null, 'sync' => null);
52:
53: /**
54: * Information about the class, the handler is managing
55: *
56: * @var string
57: * @access public
58: */
59: public $table;
60:
61: /**
62: * @var string
63: */
64: public $keyName;
65:
66: /**
67: * @var string
68: */
69: public $className;
70:
71: /**
72: * @var string
73: */
74: public $table_link;
75:
76: /**
77: * @var string
78: */
79: public $identifierName;
80:
81: /**
82: * @var string
83: */
84: public $field_link;
85:
86: /**
87: * @var string
88: */
89: public $field_object;
90:
91: /**
92: * @var string
93: */
94: public $keyName_link;
95:
96: /**
97: * Constructor
98: *
99: * @param null|Connection $db database connection}
100: * @param string $table Name of database table
101: * @param string $className Name of Class, this handler is managing
102: * @param string $keyName Name of the property holding the key
103: * @param string $identifierName Name of the property holding an identifier
104: * name (title, name ...), used on getList()
105: */
106: protected function __construct(
107: Connection $db = null,
108: $table = '',
109: $className = '',
110: $keyName = '',
111: $identifierName = ''
112: ) {
113: parent::__construct($db);
114: $this->table = $this->db2->prefix($table);
115: $this->keyName = $keyName;
116: $this->className = $className;
117: if ($identifierName) {
118: $this->identifierName = $identifierName;
119: }
120: }
121:
122: /**
123: * Set custom handler
124: *
125: * @param string|object $handler handler
126: * @param array|null $args arguments
127: *
128: * @return object|null
129: */
130: public function setHandler($handler = null, $args = null)
131: {
132: $this->handler = null;
133: if (is_object($handler)) {
134: $this->handler = $handler;
135: } else {
136: if (is_string($handler)) {
137: $xmf = XoopsModelFactory::getInstance();
138: $this->handler = $xmf->loadHandler($this, $handler, $args);
139: }
140: }
141: return $this->handler;
142: }
143:
144: /**
145: * Load predefined handler
146: *
147: * @param string $name handler name
148: * @param mixed $args args
149: *
150: * @return XoopsModelAbstract handler
151: */
152: public function loadHandler($name, $args = null)
153: {
154: static $handlers;
155: if (!isset($handlers[$name])) {
156: $xmf = XoopsModelFactory::getInstance();
157: $handlers[$name] = $xmf->loadHandler($this, $name, $args);
158: }
159: /* @var $handler XoopsModelAbstract */
160: $handler = $handlers[$name];
161: $handler->setHandler($this);
162: $handler->setVars($args);
163:
164: return $handler;
165:
166: /**
167: * // Following code just kept as placeholder for PHP5
168: * if (!isset(self::$handlers[$name])) {
169: * self::$handlers[$name] = XoopsModelFactory::loadHandler($this, $name, $args);
170: * } else {
171: * self::$handlers[$name]->setHandler($this);
172: * self::$handlers[$name]->setVars($args);
173: * }
174: *
175: * return self::$handlers[$name];
176: */
177: }
178:
179: /**
180: * Magic method for overloading of delegation
181: *
182: * @param string $name method name
183: * @param array $args arguments
184: *
185: * @return mixed
186: */
187: public function __call($name, $args)
188: {
189: if (is_object($this->handler) && is_callable(array($this->handler, $name))) {
190: return call_user_func_array(array($this->handler, $name), $args);
191: }
192: foreach (array_keys($this->handlers) as $_handler) {
193: $handler = $this->loadHandler($_handler);
194: if (is_callable(array($handler, $name))) {
195: return call_user_func_array(array($handler, $name), $args);
196: }
197: }
198:
199: return null;
200: }
201:
202: /**
203: * Methods of native handler
204: */
205:
206: /**
207: * create a new object
208: *
209: * @param bool $isNew Flag the new objects as new
210: *
211: * @return XoopsObject
212: */
213: public function create($isNew = true)
214: {
215: if (empty($this->className)) {
216: return false;
217: }
218:
219: /* @var $obj XoopsObject */
220: $obj = new $this->className();
221: if ($isNew === true) {
222: $obj->setNew();
223: }
224: return $obj;
225: }
226:
227: /**
228: * Load an object from the database
229: *
230: * @param mixed $id ID
231: * @param array $fields fields to fetch
232: *
233: * @return XoopsObject|null
234: */
235: public function get($id = null, $fields = null)
236: {
237: $object = null;
238: if (empty($id)) {
239: $object = $this->create();
240: return $object;
241: }
242: $qb = $this->db2->createXoopsQueryBuilder();
243: $eb = $qb->expr();
244: if (is_array($fields) && count($fields) > 0) {
245: if (!in_array($this->keyName, $fields)) {
246: $fields[] = $this->keyName;
247: }
248: $first=true;
249: foreach ($fields as $field) {
250: if ($first) {
251: $first=false;
252: $qb->select($field);
253: } else {
254: $qb->addSelect($field);
255: }
256: }
257: } else {
258: $qb->select('*');
259: }
260: $qb->from($this->table, null)
261: ->where($eb->eq($this->keyName, ':id'))
262: ->setParameter(':id', $id, \PDO::PARAM_INT);
263: if (!$result = $qb->execute()) {
264: return $object;
265: }
266: $row = $result->fetch(\PDO::FETCH_ASSOC);
267: if (!$row) {
268: return $object;
269: }
270: $object = $this->create(false);
271: $object->assignVars($row);
272:
273: return $object;
274: }
275:
276: /**
277: * Methods of write handler
278: */
279:
280: /**
281: * insert an object into the database
282: *
283: * @param XoopsObject $object object to insert
284: * @param bool $force flag to force the query execution despite security settings
285: *
286: * @return mixed
287: */
288: public function insert(XoopsObject $object, $force = true)
289: {
290: /* @var $handler Model\Write */
291: $handler = $this->loadHandler('write');
292: return $handler->insert($object, $force);
293: }
294:
295: /**
296: * delete an object from the database
297: *
298: * @param XoopsObject $object object to delete
299: * @param bool $force force delete
300: *
301: * @return bool FALSE if failed.
302: */
303: public function delete(XoopsObject $object, $force = false)
304: {
305: /* @var $handler Model\Write */
306: $handler = $this->loadHandler('write');
307: return $handler->delete($object, $force);
308: }
309:
310: /**
311: * delete all objects matching the conditions
312: *
313: * @param CriteriaElement $criteria criteria to match
314: * @param boolean $force force to delete
315: * @param boolean $asObject delete in object way: instantiate all objects
316: * and delete one by one
317: *
318: * @return bool
319: */
320: public function deleteAll(CriteriaElement $criteria, $force = true, $asObject = false)
321: {
322: if (empty($criteria)) {
323: return false;
324: }
325:
326: /* @var $handler Model\Write */
327: $handler = $this->loadHandler('write');
328: return $handler->deleteAll($criteria, $force, $asObject);
329: }
330:
331: /**
332: * Change a field for objects with a certain criteria
333: *
334: * @param string $fieldname Name of the field
335: * @param mixed $fieldvalue Value to write
336: * @param CriteriaElement $criteria criteria to match
337: * @param boolean $force force to query
338: *
339: * @return bool
340: */
341: public function updateAll($fieldname, $fieldvalue, CriteriaElement $criteria, $force = false)
342: {
343: if (empty($criteria)) {
344: return false;
345: }
346:
347: /* @var $handler Model\Write */
348: $handler = $this->loadHandler('write');
349: return $handler->updateAll($fieldname, $fieldvalue, $criteria, $force);
350: }
351:
352: /**
353: * Methods of read handler
354: */
355:
356: /**
357: * Retrieve objects from the database
358: *
359: * @param CriteriaElement|null $criteria criteria to match
360: * @param bool $id_as_key use the ID as key for the array
361: * @param bool $as_object return an array of objects
362: *
363: * @return array
364: */
365: public function getObjects(CriteriaElement $criteria = null, $id_as_key = false, $as_object = true)
366: {
367: /* @var $handler Model\Read */
368: $handler = $this->loadHandler('read');
369: $ret = $handler->getObjects($criteria, $id_as_key, $as_object);
370: return $ret;
371: }
372:
373: /**
374: * get all objects matching a condition
375: *
376: * @param CriteriaElement|null $criteria criteria to match
377: * @param array $fields variables to fetch
378: * @param bool $asObject flag indicating as object, otherwise as array
379: * @param bool $id_as_key use the ID as key for the array
380: *
381: * @return array of objects/array as requested by $asObject
382: */
383: public function getAll(CriteriaElement $criteria = null, $fields = null, $asObject = true, $id_as_key = true)
384: {
385: /* @var $handler Model\Read */
386: $handler = $this->loadHandler('read');
387: $ret = $handler->getAll($criteria, $fields, $asObject, $id_as_key);
388: return $ret;
389: }
390:
391: /**
392: * Retrieve a list of objects data
393: *
394: * @param CriteriaElement|null $criteria criteria to match
395: * @param int $limit Max number of objects to fetch
396: * @param int $start Which record to start at
397: *
398: * @return array
399: */
400: public function getList(CriteriaElement $criteria = null, $limit = 0, $start = 0)
401: {
402: /* @var $handler Model\Read */
403: $handler = $this->loadHandler('read');
404: $ret = $handler->getList($criteria, $limit, $start);
405: return $ret;
406: }
407:
408: /**
409: * get IDs of objects matching a condition
410: *
411: * @param CriteriaElement|null $criteria criteria to match
412: *
413: * @return array of object IDs
414: */
415: public function getIds(CriteriaElement $criteria = null)
416: {
417: /* @var $handler Model\Read */
418: $handler = $this->loadHandler('read');
419: $ret = $handler->getIds($criteria);
420: return $ret;
421: }
422:
423: /**
424: * Methods of stats handler
425: */
426:
427: /**
428: * count objects matching a condition
429: *
430: * @param CriteriaElement|null $criteria criteria to match
431: *
432: * @return int count of objects
433: */
434: public function getCount(CriteriaElement $criteria = null)
435: {
436: /* @var $handler Model\Stats */
437: $handler = $this->loadHandler('stats');
438: return $handler->getCount($criteria);
439: }
440:
441: /**
442: * Get counts of objects matching a condition
443: *
444: * @param CriteriaElement|null $criteria criteria to match
445: *
446: * @return array of counts
447: */
448: public function getCounts(CriteriaElement $criteria = null)
449: {
450: /* @var $handler Model\Stats*/
451: $handler = $this->loadHandler('stats');
452: return $handler->getCounts($criteria);
453: }
454:
455: /**
456: * Methods of joint handler
457: */
458:
459: /**
460: * get a list of objects matching a condition joint with another related object
461: *
462: * @param CriteriaElement|null $criteria criteria to match
463: * @param array $fields variables to fetch
464: * @param bool $asObject flag indicating as object, otherwise as array
465: * @param string $field_link field of linked object for JOIN
466: * @param string $field_object field of current object for JOIN
467: *
468: * @return array as specified by $asObject
469: */
470: public function getByLink(
471: CriteriaElement $criteria = null,
472: $fields = null,
473: $asObject = true,
474: $field_link = null,
475: $field_object = null
476: ) {
477: /* @var $handler Model\Joint */
478: $handler = $this->loadHandler('joint');
479: $ret = $handler->getByLink($criteria, $fields, $asObject, $field_link, $field_object);
480: return $ret;
481: }
482:
483: /**
484: * Count of objects matching a condition
485: *
486: * @param CriteriaElement|null $criteria criteria to match
487: *
488: * @return int count of objects
489: */
490: public function getCountByLink(CriteriaElement $criteria = null)
491: {
492: /* @var $handler Model\Joint */
493: $handler = $this->loadHandler('joint');
494: $ret = $handler->getCountByLink($criteria);
495: return $ret;
496: }
497:
498: /**
499: * array of count of objects matching a condition of, groupby linked object keyname
500: *
501: * @param CriteriaElement|null $criteria criteria to match
502: *
503: * @return int count of objects
504: */
505: public function getCountsByLink(CriteriaElement $criteria = null)
506: {
507: /* @var $handler Model\Joint */
508: $handler = $this->loadHandler('joint');
509: $ret = $handler->getCountsByLink($criteria);
510: return $ret;
511: }
512:
513: /**
514: * update objects matching a condition against linked objects
515: *
516: * @param array $data array of key => value
517: * @param CriteriaElement|null $criteria criteria to match
518: *
519: * @return int count of objects
520: */
521: public function updateByLink($data, CriteriaElement $criteria = null)
522: {
523: /* @var $handler Model\Joint */
524: $handler = $this->loadHandler('joint');
525: $ret = $handler->updateByLink($data, $criteria);
526: return $ret;
527: }
528:
529: /**
530: * Delete objects matching a condition against linked objects
531: *
532: * @param CriteriaElement|null $criteria criteria to match
533: *
534: * @return int count of objects
535: */
536: public function deleteByLink(CriteriaElement $criteria = null)
537: {
538: /* @var $handler Model\Joint */
539: $handler = $this->loadHandler('joint');
540: $ret = $handler->deleteByLink($criteria);
541: return $ret;
542: }
543:
544: /**
545: * Methods of sync handler
546: */
547:
548: /**
549: * Clean orphan objects against linked objects
550: *
551: * @param string $table_link table of linked object for JOIN
552: * @param string $field_link field of linked object for JOIN
553: * @param string $field_object field of current object for JOIN
554: *
555: * @return bool true on success
556: */
557: public function cleanOrphan($table_link = '', $field_link = '', $field_object = '')
558: {
559: /* @var $handler Model\Sync */
560: $handler = $this->loadHandler('sync');
561: $ret = $handler->cleanOrphan($table_link, $field_link, $field_object);
562: return $ret;
563: }
564:
565: /**
566: * Synchronizing objects
567: *
568: * @param string $table_link parent table
569: * @param string $field_link primary key (parent table)
570: * @param string $field_object foreign key (child table)
571: *
572: * @return bool true on success
573: */
574: public function synchronization($table_link = '', $field_link = '', $field_object = '')
575: {
576: $retval = $this->cleanOrphan($table_link, $field_link, $field_object);
577: return $retval;
578: }
579: }
580: