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
  • 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:     protected function _onLoad() {
294:     }
295: 
296:     /**
297:      * Gets the value of a specific field.
298:      *
299:      * @param string $sField Specifies the field to retrieve
300:      * @param bool $bSafe Flag to run defined outFilter on passed value
301:      * @return mixed Value of the field
302:      */
303:     public function getField($sField, $bSafe = true) {
304:         if ($this->virgin == true) {
305:             $this->lasterror = 'No item loaded';
306:             return false;
307:         }
308: 
309:         if (true == $bSafe) {
310:             return $this->_outFilter($this->values[$sField]);
311:         } else {
312:             return $this->values[$sField];
313:         }
314:     }
315: 
316:     /**
317:      * Wrapper for getField (less to type).
318:      *
319:      * @param string $sField Specifies the field to retrieve
320:      * @param bool $bSafe Flag to run defined outFilter on passed value
321:      * @return mixed Value of the field
322:      */
323:     public function get($sField, $bSafe = true) {
324:         return $this->getField($sField, $bSafe);
325:     }
326: 
327:     /**
328:      * Sets the value of a specific field.
329:      *
330:      * @param string $sField Field name
331:      * @param string $mValue Value to set
332:      * @param bool $bSafe Flag to run defined inFilter on passed value
333:      * @return bool
334:      */
335:     public function setField($sField, $mValue, $bSafe = true) {
336:         if ($this->virgin == true) {
337:             $this->lasterror = 'No item loaded';
338:             return false;
339:         }
340: 
341:         if ($sField == $this->primaryKey) {
342:             $this->oldPrimaryKey = $this->values[$sField];
343:         }
344: 
345:         // apply filter on value
346:         if (true == $bSafe) {
347:             $mValue = $this->_inFilter($mValue);
348:         }
349: 
350:         // flag as modified
351:         if ($this->values[$sField] != $mValue || strlen($this->values[$sField]) != strlen($mValue)) {
352:             $this->modifiedValues[$sField] = true;
353:         }
354: 
355:         // set new value
356:         $this->values[$sField] = $mValue;
357: 
358:         return true;
359:     }
360: 
361:     /**
362:      * Shortcut to setField.
363:      *
364:      * @param string $sField Field name
365:      * @param string $mValue Value to set
366:      * @param bool $bSafe Flag to run defined inFilter on passed value
367:      */
368:     public function set($sField, $mValue, $bSafe = true) {
369:         return $this->setField($sField, $mValue, $bSafe);
370:     }
371: 
372:     /**
373:      * Stores the loaded and modified item to the database.
374:      *
375:      * @return bool
376:      */
377:     public function store() {
378:         $this->_executeCallbacks(self::STORE_BEFORE, get_class($this), array(
379:             $this
380:         ));
381: 
382:         if ($this->virgin == true) {
383:             $this->lasterror = 'No item loaded';
384:             $this->_executeCallbacks(self::STORE_FAILURE, get_class($this), array(
385:                 $this
386:             ));
387:             return false;
388:         }
389: 
390:         $sql = 'UPDATE `' . $this->table . '` SET ';
391:         $first = true;
392: 
393:         if (!is_array($this->modifiedValues)) {
394:             $this->_executeCallbacks(self::STORE_SUCCESS, get_class($this), array(
395:                 $this
396:             ));
397:             return true;
398:         }
399: 
400:         foreach ($this->modifiedValues as $key => $bValue) {
401:             $value = $this->values[$key];
402:             if (is_string($value)) {
403:                 $value = $this->db->escape($value);
404:             }
405: 
406:             if ($first == true) {
407:                 $sql .= "`$key` = '" . $value . "'";
408:                 $first = false;
409:             } else {
410:                 $sql .= ", `$key` = '" . $value . "'";
411:             }
412:         }
413: 
414:         $sql .= " WHERE " . $this->primaryKey . " = '" . $this->oldPrimaryKey . "'";
415: 
416:         $this->db->query($sql);
417: 
418:         $this->_lastSQL = $sql;
419: 
420:         if ($this->db->affectedRows() > 0) {
421:             $this->_oCache->addItem($this->oldPrimaryKey, $this->values);
422:             $this->_executeCallbacks(self::STORE_SUCCESS, get_class($this), array(
423:                 $this
424:             ));
425:             return true;
426:         }
427: 
428:         $this->_executeCallbacks(self::STORE_FAILURE, get_class($this), array(
429:             $this
430:         ));
431:         return false;
432:     }
433: 
434:     /**
435:      * Returns current item data as an assoziative array.
436:      *
437:      * @return array false
438:      */
439:     public function toArray() {
440:         if ($this->virgin == true) {
441:             $this->lasterror = 'No item loaded';
442:             return false;
443:         }
444: 
445:         $aReturn = array();
446:         foreach ($this->values as $field => $value) {
447:             $aReturn[$field] = $this->getField($field);
448:         }
449:         return $aReturn;
450:     }
451: 
452:     /**
453:      * Returns current item data as an object.
454:      *
455:      * @return stdClass false
456:      */
457:     public function toObject() {
458:         $return = $this->toArray();
459:         return (false !== $return) ? (object) $return : $return;
460:     }
461: 
462:     /**
463:      * Sets a custom property.
464:      *
465:      * @param string $sType Specifies the type
466:      * @param string $sName Specifies the name
467:      * @param mixed $mValue Specifies the value
468:      * @param int $iClient Id of client to set property for
469:      * @return bool
470:      */
471:     public function setProperty($sType, $sName, $mValue, $iClient = 0) {
472:         // If this object wasn't loaded before, return false
473:         if ($this->virgin == true) {
474:             $this->lasterror = 'No item loaded';
475:             return false;
476:         }
477: 
478:         // Set the value
479:         $oProperties = $this->_getPropertiesCollectionInstance($iClient);
480:         $bResult = $oProperties->setValue($this->primaryKey, $this->get($this->primaryKey), $sType, $sName, $mValue);
481:         return $bResult;
482:     }
483: 
484:     /**
485:      * Returns a custom property.
486:      *
487:      * @param string $sType Specifies the type
488:      * @param string $sName Specifies the name
489:      * @param int $iClient Id of client to set property for
490:      * @return mixed Value of the given property or false
491:      */
492:     public function getProperty($sType, $sName, $iClient = 0) {
493:         // If this object wasn't loaded before, return false
494:         if ($this->virgin == true) {
495:             $this->lasterror = 'No item loaded';
496:             return false;
497:         }
498: 
499:         // Return the value
500:         $oProperties = $this->_getPropertiesCollectionInstance($iClient);
501:         $mValue = $oProperties->getValue($this->primaryKey, $this->get($this->primaryKey), $sType, $sName);
502:         return $mValue;
503:     }
504: 
505:     /**
506:      * Deletes a custom property.
507:      *
508:      * @param string $sType Specifies the type
509:      * @param string $sName Specifies the name
510:      * @param int $iClient Id of client to delete properties
511:      * @return bool
512:      */
513:     public function deleteProperty($sType, $sName, $iClient = 0) {
514:         // If this object wasn't loaded before, return false
515:         if ($this->virgin == true) {
516:             $this->lasterror = 'No item loaded';
517:             return false;
518:         }
519: 
520:         // Delete the value
521:         $oProperties = $this->_getPropertiesCollectionInstance($iClient);
522:         $bResult = $oProperties->deleteValue($this->primaryKey, $this->get($this->primaryKey), $sType, $sName);
523:         return $bResult;
524:     }
525: 
526:     /**
527:      * Deletes a custom property by its id.
528:      *
529:      * @param int $idprop Id of property
530:      * @return bool
531:      */
532:     public function deletePropertyById($idprop) {
533:         $oProperties = $this->_getPropertiesCollectionInstance();
534:         return $oProperties->delete($idprop);
535:     }
536: 
537:     ///**
538:     // * Deletes the current item
539:     // */
540:     // Method doesn't work, remove in future versions
541:     // function delete()
542:     // {
543:     // $this->_collectionInstance->delete($item->get($this->primaryKey));
544:     // }
545: 
546:     /**
547:      * Define the filter functions used when data is being stored or retrieved
548:      * from the database.
549:      *
550:      * Examples:
551:      * <pre>
552:      * $obj->setFilters(array('addslashes'), array('stripslashes'));
553:      * $obj->setFilters(array('htmlencode', 'addslashes'), array('stripslashes',
554:      * 'htmlencode'));
555:      * </pre>
556:      *
557:      * @param array $aInFilters Array with function names
558:      * @param array $aOutFilters Array with function names
559:      */
560:     public function setFilters($aInFilters = array(), $aOutFilters = array()) {
561:         $this->_arrInFilters = $aInFilters;
562:         $this->_arrOutFilters = $aOutFilters;
563:     }
564: 
565:     /**
566:      * Filters the passed data using the functions defines in the _arrInFilters
567:      * array.
568:      *
569:      * @param mixed $mData Data to filter
570:      * @return mixed Filtered data
571:      * @todo This method is used from public scope, but it should be protected
572:      * @see setFilters()
573:      */
574:     public function _inFilter($mData) {
575:         foreach ($this->_arrInFilters as $_function) {
576:             if (function_exists($_function)) {
577:                 if (is_array($mData)) {
578:                     foreach ($mData as $key => $value) {
579:                         $mData[$key] = $_function($value);
580:                     }
581:                 } else {
582:                     $mData = $_function($mData);
583:                 }
584:             }
585:         }
586:         return $mData;
587:     }
588: 
589:     /**
590:      * Filters the passed data using the functions defines in the _arrOutFilters
591:      * array.
592:      *
593:      *
594:      * @param mixed $mData Data to filter
595:      * @return mixed Filtered data
596:      * @see setFilters()
597:      */
598:     protected function _outFilter($mData) {
599:         foreach ($this->_arrOutFilters as $_function) {
600:             if (function_exists($_function)) {
601:                 if (is_array($mData)) {
602:                     foreach ($mData as $key => $value) {
603:                         $mData[$key] = $_function($value);
604:                     }
605:                 } else {
606:                     $mData = $_function($mData);
607:                 }
608:             }
609:         }
610:         return $mData;
611:     }
612: 
613:     /**
614:      * Set meta object class name.
615:      *
616:      * @param string $metaObject
617:      */
618:     protected function _setMetaObject($metaObject) {
619:         $this->_metaObject = $metaObject;
620:     }
621: 
622:     /**
623:      * Return meta object instance.
624:      * This object might be retrieved from a global cache ($_metaObjectCache).
625:      *
626:      * @return object
627:      */
628:     public function getMetaObject() {
629:         global $_metaObjectCache;
630: 
631:         if (!is_array($_metaObjectCache)) {
632:             $_metaObjectCache = array();
633:         }
634: 
635:         $sClassName = $this->_metaObject;
636:         $qclassname = strtolower($sClassName);
637: 
638:         if (array_key_exists($qclassname, $_metaObjectCache)) {
639:             if (is_object($_metaObjectCache[$qclassname])) {
640:                 if (strtolower(get_class($_metaObjectCache[$qclassname])) == $qclassname) {
641:                     $_metaObjectCache[$qclassname]->setPayloadObject($this);
642:                     return $_metaObjectCache[$qclassname];
643:                 }
644:             }
645:         }
646: 
647:         if (class_exists($sClassName)) {
648:             $_metaObjectCache[$qclassname] = new $sClassName($this);
649:             return $_metaObjectCache[$qclassname];
650:         }
651:     }
652: }
653: 
CMS CONTENIDO 4.9.4 API documentation generated by ApiGen 2.8.0