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