Overview

Packages

  • Core
    • Authentication
    • Backend
    • Cache
    • CEC
    • Chain
    • ContentType
    • Database
    • Datatype
    • Debug
    • Exception
    • Frontend
      • Search
      • URI
      • Util
    • GenericDB
      • Model
    • GUI
      • HTML
    • I18N
    • LayoutHandler
    • Log
    • Security
    • Session
    • Util
    • Validation
    • Versioning
    • XML
  • Module
    • ContentSitemapHtml
    • ContentSitemapXml
    • ContentUserForum
    • NavigationTop
  • mpAutoloaderClassMap
  • None
  • Plugin
    • ContentAllocation
    • CronjobOverview
    • FormAssistant
    • FrontendLogic
    • FrontendUsers
    • Linkchecker
    • ModRewrite
    • Newsletter
    • Repository
      • FrontendNavigation
      • KeywordDensity
    • SearchSolr
    • SmartyWrapper
    • UrlShortener
    • UserForum
    • Workflow
  • PluginManager
  • Setup
    • Form
    • GUI
    • Helper
      • Environment
      • Filesystem
      • MySQL
      • PHP
    • UpgradeJob

Classes

  • ArticleForum
  • cApiShortUrl
  • cGenericDb
  • cGenericDbDriver
  • cGenericDbDriverMysql
  • cItemBaseAbstract
  • cItemCache
  • Item
  • ItemCollection
  • Overview
  • Package
  • Class
  • Tree
  • Deprecated
  • Todo
  1: <?php
  2: /**
  3:  * This file contains the generic db item class.
  4:  *
  5:  * @package Core
  6:  * @subpackage GenericDB
  7:  * @version SVN Revision $Rev:$
  8:  *
  9:  * @author Timo Hummel
 10:  * @author Murat Purc <murat@purc.de>
 11:  * @copyright four for business AG <www.4fb.de>
 12:  * @license http://www.contenido.org/license/LIZENZ.txt
 13:  * @link http://www.4fb.de
 14:  * @link http://www.contenido.org
 15:  */
 16: 
 17: defined('CON_FRAMEWORK') || die('Illegal call: Missing framework initialization - request aborted.');
 18: 
 19: /**
 20:  * Class Item
 21:  * Abstract class for database based items.
 22:  *
 23:  * @package Core
 24:  * @subpackage GenericDB
 25:  */
 26: abstract class Item extends cItemBaseAbstract {
 27: 
 28:     /**
 29:      * Storage of the source table to use for the user informations
 30:      *
 31:      * @var array
 32:      */
 33:     public $values;
 34: 
 35:     /**
 36:      * Storage of the fields which were modified, where the keys are the
 37:      * fieldnames and the values just simple booleans.
 38:      *
 39:      * @var array
 40:      */
 41:     protected $modifiedValues;
 42: 
 43:     /**
 44:      * Stores the old primary key, just in case somebody wants to change it
 45:      *
 46:      * @var string
 47:      */
 48:     protected $oldPrimaryKey;
 49: 
 50:     /**
 51:      * List of funcion names of the filters used when data is stored to the db.
 52:      *
 53:      * @var array
 54:      */
 55:     protected $_arrInFilters = array(
 56:         'htmlspecialchars',
 57:         'addslashes'
 58:     );
 59: 
 60:     /**
 61:      * List of funcion names of the filtersused when data is retrieved from the
 62:      * db
 63:      *
 64:      * @var array
 65:      */
 66:     protected $_arrOutFilters = array(
 67:         'stripslashes',
 68:         'htmldecode'
 69:     );
 70: 
 71:     /**
 72:      * Class name of meta object
 73:      *
 74:      * @var string
 75:      */
 76:     protected $_metaObject;
 77: 
 78:     /**
 79:      * Last executed SQL statement
 80:      *
 81:      * @var string
 82:      */
 83:     protected $_lastSQL;
 84: 
 85:     /**
 86:      * Constructor function
 87:      *
 88:      * @param string $sTable The table to use as information source
 89:      * @param string $sPrimaryKey The primary key to use
 90:      * @param int $iLifetime
 91:      */
 92:     public function __construct($sTable, $sPrimaryKey) {
 93:         parent::__construct($sTable, $sPrimaryKey, get_parent_class($this));
 94:     }
 95: 
 96:     /**
 97:      * Loads an item by colum/field from the database.
 98:      *
 99:      * @param string $sField Specifies the field
100:      * @param mixed $mValue Specifies the value
101:      * @param bool $bSafe Use inFilter or not
102:      * @throws cException if more than one item has been found matching the
103:      *         given arguments
104:      * @return bool True if the load was successful
105:      */
106:     public function loadBy($sField, $mValue, $bSafe = true) {
107:         if ($bSafe) {
108:             $mValue = $this->_inFilter($mValue);
109:         }
110: 
111:         // check, if cache contains a matching entry
112:         $aRecordSet = NULL;
113:         if ($sField === $this->primaryKey) {
114:             $aRecordSet = $this->_oCache->getItem($mValue);
115:         } else {
116:             $aRecordSet = $this->_oCache->getItemByProperty($sField, $mValue);
117:         }
118: 
119:         if ($aRecordSet) {
120:             // entry in cache found, load entry from cache
121:             $this->loadByRecordSet($aRecordSet);
122:             return true;
123:         }
124: 
125:         // SQL-Statement to select by field
126:         $sql = "SELECT * FROM `%s` WHERE %s = '%s'";
127:         $sql = $this->db->prepare($sql, $this->table, $sField, $mValue);
128: 
129:         // Query the database
130:         $this->db->query($sql);
131: 
132:         $this->_lastSQL = $sql;
133: 
134:         if ($this->db->numRows() > 1) {
135:             $msg = "Tried to load a single line with field $sField and value $mValue from " . $this->table . " but found more than one row";
136:             throw new cException($msg);
137:         }
138: 
139:         // Advance to the next record, return false if nothing found
140:         if (!$this->db->nextRecord()) {
141:             return false;
142:         }
143: 
144:         $this->loadByRecordSet($this->db->toArray());
145:         return true;
146:     }
147: 
148:     /**
149:      * Loads an item by colums/fields from the database.
150:      *
151:      * @param array $aAttributes associative array with field / value pairs
152:      * @param bool $bSafe Use inFilter or not
153:      * @throws cException if more than one item could be found matching the
154:      *         given arguments
155:      * @return bool True if the load was successful
156:      */
157:     public function loadByMany(array $aAttributes, $bSafe = true) {
158:         if ($bSafe) {
159:             $aAttributes = $this->_inFilter($aAttributes);
160:         }
161: 
162:         // check, if cache contains a matching entry
163:         $aRecordSet = NULL;
164:         if (count($aAttributes) == 1 && isset($aAttributes[$this->primaryKey])) {
165:             $aRecordSet = $this->_oCache->getItem($aAttributes[$this->primaryKey]);
166:         } else {
167:             $aRecordSet = $this->_oCache->getItemByProperties($aAttributes);
168:         }
169: 
170:         if ($aRecordSet) {
171:             // entry in cache found, load entry from cache
172:             $this->loadByRecordSet($aRecordSet);
173:             return true;
174:         }
175: 
176:         // SQL-Statement to select by fields
177:         $sql = 'SELECT * FROM `:mytab` WHERE';
178:         foreach (array_keys($aAttributes) as $sKey) {
179:             // add quotes if key is a string
180:             if (is_string($sKey)) {
181:                 $sql .= " $sKey = ':$sKey' AND";
182:             } else {
183:                 $sql .= " $sKey = :$sKey AND";
184:             }
185:         }
186:         // strip the last " AND" token
187:         $sql = substr($sql, 0, strlen($sql) - 4);
188:         $sql = $this->db->prepare($sql, array_merge(array(
189:             'mytab' => $this->table
190:         ), $aAttributes));
191: 
192:         // Query the database
193:         $this->db->query($sql);
194: 
195:         $this->_lastSQL = $sql;
196: 
197:         if ($this->db->numRows() > 1) {
198:             $msg = 'Tried to load a single line with fields ' . print_r(array_keys($aAttributes), true) . ' and values ' . print_r(array_values($aAttributes), true) . ' from ' . $this->table . ' but found more than one row';
199:             throw new cException($msg);
200:         }
201: 
202:         // Advance to the next record, return false if nothing found
203:         if (!$this->db->nextRecord()) {
204:             return false;
205:         }
206: 
207:         $this->loadByRecordSet($this->db->toArray());
208:         return true;
209:     }
210: 
211:     /**
212:      * Loads an item by passed where clause from the database.
213:      * This function is expensive, since it executes allways a query to the
214:      * database
215:      * to retrieve the primary key, even if the record set is aleady cached.
216:      * NOTE: Passed value has to be escaped before. This will not be done by
217:      * this function.
218:      *
219:      * @param string $sWhere The where clause like 'idart = 123 AND idlang = 1'
220:      * @throws cException if more than one item could be found matching the
221:      *         given where clause
222:      * @return bool True if the load was successful
223:      */
224:     protected function _loadByWhereClause($sWhere) {
225:         // SQL-Statement to select by whee clause
226:         $sql = "SELECT %s AS pk FROM `%s` WHERE " . (string) $sWhere;
227:         $sql = $this->db->prepare($sql, $this->primaryKey, $this->table);
228: 
229:         // Query the database
230:         $this->db->query($sql);
231: 
232:         $this->_lastSQL = $sql;
233: 
234:         if ($this->db->numRows() > 1) {
235:             $msg = "Tried to load a single line with where clause '" . $sWhere . "' from " . $this->table . " but found more than one row";
236:             throw new cException($msg);
237:         }
238: 
239:         // Advance to the next record, return false if nothing found
240:         if (!$this->db->nextRecord()) {
241:             return false;
242:         }
243: 
244:         $id = $this->db->f('pk');
245:         return $this->loadByPrimaryKey($id);
246:     }
247: 
248:     /**
249:      * Loads an item by ID from the database.
250:      *
251:      * @param string $mValue Specifies the primary key value
252:      * @return bool True if the load was successful
253:      */
254:     public function loadByPrimaryKey($mValue) {
255:         $bSuccess = $this->loadBy($this->primaryKey, $mValue);
256: 
257:         if ($bSuccess == true && method_exists($this, '_onLoad')) {
258:             $this->_onLoad();
259:         }
260: 
261:         return $bSuccess;
262:     }
263: 
264:     /**
265:      * Loads an item by it's recordset.
266:      *
267:      * @param array $aRecordSet The recordset of the item
268:      */
269:     public function loadByRecordSet(array $aRecordSet) {
270:         $this->values = $aRecordSet;
271:         $this->oldPrimaryKey = $this->values[$this->primaryKey];
272:         $this->virgin = false;
273:         $this->_oCache->addItem($this->oldPrimaryKey, $this->values);
274: 
275:         if (method_exists($this, '_onLoad')) {
276:             $this->_onLoad();
277:         }
278:     }
279: 
280:     /**
281:      * Checks if a the item is already loaded.
282:      *
283:      * @return bool
284:      */
285:     public function isLoaded() {
286:         return !$this->virgin;
287:     }
288: 
289:     /**
290:      * Function which is called whenever an item is loaded.
291:      * Inherited classes should override this function if desired.
292:      *
293:      * @return void
294:      */
295:     protected function _onLoad() {
296:     }
297: 
298:     /**
299:      * Gets the value of a specific field.
300:      *
301:      * @param string $sField Specifies the field to retrieve
302:      * @return mixed Value of the field
303:      */
304:     public function getField($sField) {
305:         if ($this->virgin == true) {
306:             $this->lasterror = 'No item loaded';
307:             return false;
308:         }
309:         return $this->_outFilter($this->values[$sField]);
310:     }
311: 
312:     /**
313:      * Wrapper for getField (less to type).
314:      *
315:      * @param string $sField Specifies the field to retrieve
316:      * @return mixed Value of the field
317:      */
318:     public function get($sField) {
319:         return $this->getField($sField);
320:     }
321: 
322:     /**
323:      * Sets the value of a specific field.
324:      *
325:      * @param string $sField Field name
326:      * @param string $mValue Value to set
327:      * @param bool $bSafe Flag to run defined inFilter on passed value
328:      * @return bool
329:      */
330:     public function setField($sField, $mValue, $bSafe = true) {
331:         if ($this->virgin == true) {
332:             $this->lasterror = 'No item loaded';
333:             return false;
334:         }
335: 
336:         if ($sField == $this->primaryKey) {
337:             $this->oldPrimaryKey = $this->values[$sField];
338:         }
339: 
340:         // apply filter on value
341:         if (true == $bSafe) {
342:             $mValue = $this->_inFilter($mValue);
343:         }
344: 
345:         // flag as modified
346:         if ($this->values[$sField] != $mValue) {
347:             $this->modifiedValues[$sField] = true;
348:         }
349: 
350:         // set new value
351:         $this->values[$sField] = $mValue;
352: 
353:         return true;
354:     }
355: 
356:     /**
357:      * Shortcut to setField.
358:      *
359:      * @param string $sField Field name
360:      * @param string $mValue Value to set
361:      * @param bool $bSafe Flag to run defined inFilter on passed value
362:      */
363:     public function set($sField, $mValue, $bSafe = true) {
364:         return $this->setField($sField, $mValue, $bSafe);
365:     }
366: 
367:     /**
368:      * Stores the loaded and modified item to the database.
369:      *
370:      * @return bool
371:      */
372:     public function store() {
373:         $this->_executeCallbacks(self::STORE_BEFORE, get_class($this), array(
374:             $this
375:         ));
376: 
377:         if ($this->virgin == true) {
378:             $this->lasterror = 'No item loaded';
379:             $this->_executeCallbacks(self::STORE_FAILURE, get_class($this), array(
380:                 $this
381:             ));
382:             return false;
383:         }
384: 
385:         $sql = 'UPDATE `' . $this->table . '` SET ';
386:         $first = true;
387: 
388:         if (!is_array($this->modifiedValues)) {
389:             $this->_executeCallbacks(self::STORE_SUCCESS, get_class($this), array(
390:                 $this
391:             ));
392:             return true;
393:         }
394: 
395:         foreach ($this->modifiedValues as $key => $bValue) {
396:             $value = $this->values[$key];
397:             if (is_string($value)) {
398:                 $value = $this->db->escape($value);
399:             }
400: 
401:             if ($first == true) {
402:                 $sql .= "`$key` = '" . $value . "'";
403:                 $first = false;
404:             } else {
405:                 $sql .= ", `$key` = '" . $value . "'";
406:             }
407:         }
408: 
409:         $sql .= " WHERE " . $this->primaryKey . " = '" . $this->oldPrimaryKey . "'";
410: 
411:         $this->db->query($sql);
412: 
413:         $this->_lastSQL = $sql;
414: 
415:         if ($this->db->affectedRows() > 0) {
416:             $this->_oCache->addItem($this->oldPrimaryKey, $this->values);
417:             $this->_executeCallbacks(self::STORE_SUCCESS, get_class($this), array(
418:                 $this
419:             ));
420:             return true;
421:         }
422: 
423:         $this->_executeCallbacks(self::STORE_FAILURE, get_class($this), array(
424:             $this
425:         ));
426:         return false;
427:     }
428: 
429:     /**
430:      * Returns current item data as an assoziative array.
431:      *
432:      * @return array false
433:      */
434:     public function toArray() {
435:         if ($this->virgin == true) {
436:             $this->lasterror = 'No item loaded';
437:             return false;
438:         }
439: 
440:         $aReturn = array();
441:         foreach ($this->values as $field => $value) {
442:             $aReturn[$field] = $this->getField($field);
443:         }
444:         return $aReturn;
445:     }
446: 
447:     /**
448:      * Returns current item data as an object.
449:      *
450:      * @return stdClass false
451:      */
452:     public function toObject() {
453:         $return = $this->toArray();
454:         return (false !== $return) ? (object) $return : $return;
455:     }
456: 
457:     /**
458:      * Sets a custom property.
459:      *
460:      * @param string $sType Specifies the type
461:      * @param string $sName Specifies the name
462:      * @param mixed $mValue Specifies the value
463:      * @param int $iClient Id of client to set property for
464:      * @return bool
465:      */
466:     public function setProperty($sType, $sName, $mValue, $iClient = 0) {
467:         // If this object wasn't loaded before, return false
468:         if ($this->virgin == true) {
469:             $this->lasterror = 'No item loaded';
470:             return false;
471:         }
472: 
473:         // Set the value
474:         $oProperties = $this->_getPropertiesCollectionInstance($iClient);
475:         $bResult = $oProperties->setValue($this->primaryKey, $this->get($this->primaryKey), $sType, $sName, $mValue);
476:         return $bResult;
477:     }
478: 
479:     /**
480:      * Returns a custom property.
481:      *
482:      * @param string $sType Specifies the type
483:      * @param string $sName Specifies the name
484:      * @param int $iClient Id of client to set property for
485:      * @return mixed Value of the given property or false
486:      */
487:     public function getProperty($sType, $sName, $iClient = 0) {
488:         // If this object wasn't loaded before, return false
489:         if ($this->virgin == true) {
490:             $this->lasterror = 'No item loaded';
491:             return false;
492:         }
493: 
494:         // Return the value
495:         $oProperties = $this->_getPropertiesCollectionInstance($iClient);
496:         $mValue = $oProperties->getValue($this->primaryKey, $this->get($this->primaryKey), $sType, $sName);
497:         return $mValue;
498:     }
499: 
500:     /**
501:      * Deletes a custom property.
502:      *
503:      * @param string $sType Specifies the type
504:      * @param string $sName Specifies the name
505:      * @param int $iClient Id of client to delete properties
506:      * @return bool
507:      */
508:     public function deleteProperty($sType, $sName, $iClient = 0) {
509:         // If this object wasn't loaded before, return false
510:         if ($this->virgin == true) {
511:             $this->lasterror = 'No item loaded';
512:             return false;
513:         }
514: 
515:         // Delete the value
516:         $oProperties = $this->_getPropertiesCollectionInstance($iClient);
517:         $bResult = $oProperties->deleteValue($this->primaryKey, $this->get($this->primaryKey), $sType, $sName);
518:         return $bResult;
519:     }
520: 
521:     /**
522:      * Deletes a custom property by its id.
523:      *
524:      * @param int $idprop Id of property
525:      * @return bool
526:      */
527:     public function deletePropertyById($idprop) {
528:         $oProperties = $this->_getPropertiesCollectionInstance();
529:         return $oProperties->delete($idprop);
530:     }
531: 
532:     /**
533:      * Deletes the current item
534:      *
535:      * @return void
536:      */
537:     // Method doesn't work, remove in future versions
538:     // function delete()
539:     // {
540:     // $this->_collectionInstance->delete($item->get($this->primaryKey));
541:     // }
542: 
543:     /**
544:      * Define the filter functions used when data is being stored or retrieved
545:      * from the database.
546:      *
547:      * Examples:
548:      * <pre>
549:      * $obj->setFilters(array('addslashes'), array('stripslashes'));
550:      * $obj->setFilters(array('htmlencode', 'addslashes'), array('stripslashes',
551:      * 'htmlencode'));
552:      * </pre>
553:      *
554:      * @param array $aInFilters Array with function names
555:      * @param array $aOutFilters Array with function names
556:      */
557:     public function setFilters($aInFilters = array(), $aOutFilters = array()) {
558:         $this->_arrInFilters = $aInFilters;
559:         $this->_arrOutFilters = $aOutFilters;
560:     }
561: 
562:     /**
563:      * Filters the passed data using the functions defines in the _arrInFilters
564:      * array.
565:      *
566:      * @param mixed $mData Data to filter
567:      * @return mixed Filtered data
568:      * @todo This method is used from public scope, but it should be protected
569:      * @see setFilters()
570:      */
571:     public function _inFilter($mData) {
572:         foreach ($this->_arrInFilters as $_function) {
573:             if (function_exists($_function)) {
574:                 if (is_array($mData)) {
575:                     foreach ($mData as $key => $value) {
576:                         $mData[$key] = $_function($value);
577:                     }
578:                 } else {
579:                     $mData = $_function($mData);
580:                 }
581:             }
582:         }
583:         return $mData;
584:     }
585: 
586:     /**
587:      * Filters the passed data using the functions defines in the _arrOutFilters
588:      * array.
589:      *
590:      *
591:      * @param mixed $mData Data to filter
592:      * @return mixed Filtered data
593:      * @see setFilters()
594:      */
595:     protected function _outFilter($mData) {
596:         foreach ($this->_arrOutFilters as $_function) {
597:             if (function_exists($_function)) {
598:                 if (is_array($mData)) {
599:                     foreach ($mData as $key => $value) {
600:                         $mData[$key] = $_function($value);
601:                     }
602:                 } else {
603:                     $mData = $_function($mData);
604:                 }
605:             }
606:         }
607:         return $mData;
608:     }
609: 
610:     /**
611:      * Set meta object class name.
612:      *
613:      * @param string $metaObject
614:      */
615:     protected function _setMetaObject($metaObject) {
616:         $this->_metaObject = $metaObject;
617:     }
618: 
619:     /**
620:      * Return meta object instance.
621:      * This object might be retrieved from a global cache ($_metaObjectCache).
622:      *
623:      * @return object
624:      */
625:     public function getMetaObject() {
626:         global $_metaObjectCache;
627: 
628:         if (!is_array($_metaObjectCache)) {
629:             $_metaObjectCache = array();
630:         }
631: 
632:         $sClassName = $this->_metaObject;
633:         $qclassname = strtolower($sClassName);
634: 
635:         if (array_key_exists($qclassname, $_metaObjectCache)) {
636:             if (is_object($_metaObjectCache[$qclassname])) {
637:                 if (strtolower(get_class($_metaObjectCache[$qclassname])) == $qclassname) {
638:                     $_metaObjectCache[$qclassname]->setPayloadObject($this);
639:                     return $_metaObjectCache[$qclassname];
640:                 }
641:             }
642:         }
643: 
644:         if (class_exists($sClassName)) {
645:             $_metaObjectCache[$qclassname] = new $sClassName($this);
646:             return $_metaObjectCache[$qclassname];
647:         }
648:     }
649: }
650: 
CMS CONTENIDO 4.9.1 API documentation generated by ApiGen 2.8.0