Overview

Packages

  • CONTENIDO
  • Core
    • Authentication
    • Backend
    • Cache
    • CEC
    • Chain
    • ContentType
    • Database
    • Debug
    • Exception
    • Frontend
      • Search
      • URI
      • Util
    • GenericDB
      • Model
    • GUI
      • HTML
    • I18N
    • LayoutHandler
    • Log
    • Security
    • Session
    • Util
    • Validation
    • Versioning
    • XML
  • Module
    • ContentRssCreator
    • ContentSitemapHtml
    • ContentSitemapXml
    • ContentUserForum
    • NavigationTop
    • ScriptCookieDirective
  • 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: /**
   4:  * This file contains the generic db item collection class.
   5:  *
   6:  * @package Core
   7:  * @subpackage GenericDB
   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 ItemCollection
  21:  * Abstract class for database based item collections.
  22:  *
  23:  * @package Core
  24:  * @subpackage GenericDB
  25:  */
  26: abstract class ItemCollection extends cItemBaseAbstract {
  27: 
  28:     /**
  29:      * Storage of all result items.
  30:      * Contains all result items.
  31:      *
  32:      * @var string
  33:      */
  34:     protected $objects;
  35: 
  36:     /**
  37:      * GenericDB driver object
  38:      *
  39:      * @var cGenericDbDriver
  40:      */
  41:     protected $_driver;
  42: 
  43:     /**
  44:      * List of instances of ItemCollection implementations
  45:      *
  46:      * @var array
  47:      */
  48:     protected $_collectionCache = array();
  49: 
  50:     /**
  51:      * Single item class
  52:      *
  53:      * @var string
  54:      */
  55:     protected $_itemClass;
  56: 
  57:     /**
  58:      * Iterator object for the next() method
  59:      *
  60:      * @var object
  61:      */
  62:     protected $_iteratorItem;
  63: 
  64:     /**
  65:      * Reverse join partners for this data object
  66:      *
  67:      * @var array
  68:      */
  69:     protected $_JoinPartners = array();
  70: 
  71:     /**
  72:      * Forward join partners for this data object
  73:      *
  74:      * @var array
  75:      */
  76:     protected $_forwardJoinPartners;
  77: 
  78:     /**
  79:      * Where restrictions for the query
  80:      *
  81:      * @var array
  82:      */
  83:     protected $_whereRestriction;
  84: 
  85:     /**
  86:      * Inner group conditions
  87:      *
  88:      * @var array
  89:      */
  90:     protected $_innerGroupConditions = array();
  91: 
  92:     /**
  93:      * Group conditions
  94:      *
  95:      * @var array
  96:      */
  97:     protected $_groupConditions;
  98: 
  99:     /**
 100:      * Result fields for the query
 101:      *
 102:      * @var array
 103:      */
 104:     protected $_resultFields = array();
 105: 
 106:     /**
 107:      * Encoding
 108:      *
 109:      * @var string
 110:      */
 111:     protected $_encoding;
 112: 
 113:     /**
 114:      * Item class instance
 115:      *
 116:      * @var object
 117:      */
 118:     protected $_itemClassInstance;
 119: 
 120:     /**
 121:      * Stores all operators which are supported by GenericDB
 122:      * Unsupported operators are passed trough as-is.
 123:      *
 124:      * @var array
 125:      */
 126:     protected $_aOperators;
 127: 
 128:     /**
 129:      * Flag to select all fields in a query.
 130:      * Reduces the number of queries send to the database.
 131:      *
 132:      * @var bool
 133:      */
 134:     protected $_bAllMode = false;
 135: 
 136:     /**
 137:      * Array with where conditions
 138:      *
 139:      * @var array
 140:      */
 141:     protected $_where;
 142: 
 143:     /**
 144:      * Order mode with direction
 145:      *
 146:      * @var string
 147:      */
 148:     protected $_order;
 149: 
 150:     /**
 151:      * Starting limit
 152:      *
 153:      * @var int
 154:      */
 155:     protected $_limitStart;
 156: 
 157:     /**
 158:      * Amount of items for limit
 159:      *
 160:      * @var int
 161:      */
 162:     protected $_limitCount;
 163: 
 164:     /**
 165:      * Last SQL statement
 166:      *
 167:      * @var string
 168:      */
 169:     protected $_lastSQL;
 170: 
 171:     /**
 172:      * Array with linked tables
 173:      *
 174:      * @var array
 175:      */
 176:     protected $_links;
 177: 
 178:     /**
 179:      * Constructor to create an instance of this class.
 180:      *
 181:      * @param string $sTable
 182:      *         The table to use as information source
 183:      * @param string $sPrimaryKey
 184:      *         The primary key to use
 185:      */
 186:     public function __construct($sTable, $sPrimaryKey) {
 187:         parent::__construct($sTable, $sPrimaryKey, get_parent_class($this));
 188: 
 189:         $this->resetQuery();
 190: 
 191:         // Try to load driver
 192:         $this->_initializeDriver();
 193: 
 194:         // Try to find out the current encoding
 195:         if (isset($GLOBALS['lang']) && isset($GLOBALS['aLanguageEncodings'])) {
 196:             $this->setEncoding($GLOBALS['aLanguageEncodings'][$GLOBALS['lang']]);
 197:         }
 198: 
 199:         $this->_aOperators = array(
 200:             '=',
 201:             '!=',
 202:             '<>',
 203:             '<',
 204:             '>',
 205:             '<=',
 206:             '>=',
 207:             'LIKE',
 208:             'DIACRITICS'
 209:         );
 210:     }
 211: 
 212:     /**
 213:      * Defines the reverse links for this table.
 214:      *
 215:      * Important: The class specified by $sForeignCollectionClass needs to be a
 216:      * collection class and has to exist.
 217:      * Define all links in the constructor of your object.
 218:      *
 219:      * @param string $sForeignCollectionClass
 220:      *         Specifies the foreign class to use
 221:      * @throws cInvalidArgumentException
 222:      *         if the given foreign class can not be instantiated
 223:      */
 224:     protected function _setJoinPartner($sForeignCollectionClass) {
 225:         if (class_exists($sForeignCollectionClass)) {
 226:             // Add class
 227:             if (!in_array($sForeignCollectionClass, $this->_JoinPartners)) {
 228:                 $this->_JoinPartners[] = strtolower($sForeignCollectionClass);
 229:             }
 230:         } else {
 231:             $msg = "Could not instantiate class [$sForeignCollectionClass] for use " . "with _setJoinPartner in class " . get_class($this);
 232:             throw new cInvalidArgumentException($msg);
 233:         }
 234:     }
 235: 
 236:     /**
 237:      * Method to set the accompanying item object.
 238:      *
 239:      * @param string $sClassName
 240:      *         Specifies the classname of item
 241:      * @throws cInvalidArgumentException
 242:      *         if the given class can not be instantiated
 243:      */
 244:     protected function _setItemClass($sClassName) {
 245:         if (class_exists($sClassName)) {
 246:             $this->_itemClass = $sClassName;
 247:             $this->_itemClassInstance = new $sClassName();
 248: 
 249:             // Initialize driver in case the developer does a setItemClass-Call
 250:             // before calling the parent constructor
 251:             $this->_initializeDriver();
 252:             $this->_driver->setItemClassInstance($this->_itemClassInstance);
 253:         } else {
 254:             $msg = "Could not instantiate class [$sClassName] for use with " . "_setItemClass in class " . get_class($this);
 255:             throw new cInvalidArgumentException($msg);
 256:         }
 257:     }
 258: 
 259:     /**
 260:      * Initializes the driver to use with GenericDB.
 261:      *
 262:      * @param bool $bForceInit [optional]
 263:      *         If true, forces the driver to initialize, even if it already exists.
 264:      */
 265:     protected function _initializeDriver($bForceInit = false) {
 266:         if (!is_object($this->_driver) || $bForceInit == true) {
 267:             $this->_driver = new cGenericDbDriverMysql();
 268:         }
 269:     }
 270: 
 271:     /**
 272:      * Sets the encoding.
 273:      *
 274:      * @param string $sEncoding
 275:      */
 276:     public function setEncoding($sEncoding) {
 277:         $this->_encoding = $sEncoding;
 278:         $this->_driver->setEncoding($sEncoding);
 279:     }
 280: 
 281:     /**
 282:      * Sets the query to use foreign tables in the resultset
 283:      *
 284:      * @param string $sForeignClass
 285:      *         The class of foreign table to use
 286:      * @throws cInvalidArgumentException
 287:      *         if the given foreign class does not exist
 288:      */
 289:     public function link($sForeignClass) {
 290:         if (class_exists($sForeignClass)) {
 291:             $this->_links[$sForeignClass] = new $sForeignClass();
 292:         } else {
 293:             $msg = "Could not find class [$sForeignClass] for use with link in class " . get_class($this);
 294:             throw new cInvalidArgumentException($msg);
 295:         }
 296:     }
 297: 
 298:     /**
 299:      * Sets the limit for results
 300:      *
 301:      * @param int $iRowStart
 302:      * @param int $iRowCount
 303:      */
 304:     public function setLimit($iRowStart, $iRowCount) {
 305:         $this->_limitStart = $iRowStart;
 306:         $this->_limitCount = $iRowCount;
 307:     }
 308: 
 309:     /**
 310:      * Restricts a query with a where clause
 311:      *
 312:      * @param string $sField
 313:      * @param mixed $mRestriction
 314:      * @param string $sOperator [optional]
 315:      */
 316:     public function setWhere($sField, $mRestriction, $sOperator = '=') {
 317:         $sField = strtolower($sField);
 318:         $this->_where['global'][$sField]['operator'] = $sOperator;
 319:         $this->_where['global'][$sField]['restriction'] = $mRestriction;
 320:     }
 321: 
 322:     /**
 323:      * Removes a previous set where clause (@see ItemCollection::setWhere).
 324:      *
 325:      * @param string $sField
 326:      * @param mixed $mRestriction
 327:      * @param string $sOperator [optional]
 328:      */
 329:     public function deleteWhere($sField, $mRestriction, $sOperator = '=') {
 330:         $sField = strtolower($sField);
 331:         if (isset($this->_where['global'][$sField]) && is_array($this->_where['global'][$sField])) {
 332:             if ($this->_where['global'][$sField]['operator'] == $sOperator && $this->_where['global'][$sField]['restriction'] == $mRestriction) {
 333:                 unset($this->_where['global'][$sField]);
 334:             }
 335:         }
 336:     }
 337: 
 338:     /**
 339:      * Restricts a query with a where clause, groupable
 340:      *
 341:      * @param string $sGroup
 342:      * @param string $sField
 343:      * @param mixed $mRestriction
 344:      * @param string $sOperator [optional]
 345:      */
 346:     public function setWhereGroup($sGroup, $sField, $mRestriction, $sOperator = '=') {
 347:         $sField = strtolower($sField);
 348:         $this->_where['groups'][$sGroup][$sField]['operator'] = $sOperator;
 349:         $this->_where['groups'][$sGroup][$sField]['restriction'] = $mRestriction;
 350:     }
 351: 
 352:     /**
 353:      * Removes a previous set groupable where clause (@see
 354:      * ItemCollection::setWhereGroup).
 355:      *
 356:      * @param string $sGroup
 357:      * @param string $sField
 358:      * @param mixed $mRestriction
 359:      * @param string $sOperator [optional]
 360:      */
 361:     public function deleteWhereGroup($sGroup, $sField, $mRestriction, $sOperator = '=') {
 362:         $sField = strtolower($sField);
 363:         if (is_array($this->_where['groups'][$sGroup]) && isset($this->_where['groups'][$sGroup][$sField]) && is_array($this->_where['groups'][$sGroup][$sField])) {
 364:             if ($this->_where['groups'][$sGroup][$sField]['operator'] == $sOperator && $this->_where['groups'][$sGroup][$sField]['restriction'] == $mRestriction) {
 365:                 unset($this->_where['groups'][$sGroup][$sField]);
 366:             }
 367:         }
 368:     }
 369: 
 370:     /**
 371:      * Defines how relations in one group are linked each together
 372:      *
 373:      * @param string $sGroup
 374:      * @param string $sCondition [optional]
 375:      */
 376:     public function setInnerGroupCondition($sGroup, $sCondition = 'AND') {
 377:         $this->_innerGroupConditions[$sGroup] = $sCondition;
 378:     }
 379: 
 380:     /**
 381:      * Defines how groups are linked to each other
 382:      *
 383:      * @param string $sGroup1
 384:      * @param string $sGroup2
 385:      * @param string $sCondition [optional]
 386:      */
 387:     public function setGroupCondition($sGroup1, $sGroup2, $sCondition = 'AND') {
 388:         $this->_groupConditions[$sGroup1][$sGroup2] = $sCondition;
 389:     }
 390: 
 391:     /**
 392:      * Builds a where statement out of the setGroupWhere calls
 393:      *
 394:      * @return array
 395:      *         With all where statements
 396:      */
 397:     protected function _buildGroupWhereStatements() {
 398:         $aWheres = array();
 399:         $aGroupWhere = array();
 400: 
 401:         $mLastGroup = false;
 402:         $sGroupWhereStatement = '';
 403: 
 404:         // Find out if there are any defined groups
 405:         if (count($this->_where['groups']) > 0) {
 406:             // Step trough all groups
 407:             foreach ($this->_where['groups'] as $groupname => $group) {
 408:                 $aWheres = array();
 409: 
 410:                 // Fetch restriction, fields and operators and build single
 411:                 // group
 412:                 // where statements
 413:                 foreach ($group as $field => $item) {
 414:                     $aWheres[] = $this->_driver->buildOperator($field, $item['operator'], $item['restriction']);
 415:                 }
 416: 
 417:                 // Add completed substatements
 418:                 $sOperator = 'AND';
 419:                 if (isset($this->_innerGroupConditions[$groupname])) {
 420:                     $sOperator = $this->_innerGroupConditions[$groupname];
 421:                 }
 422: 
 423:                 $aGroupWhere[$groupname] = implode(' ' . $sOperator . ' ', $aWheres);
 424:             }
 425:         }
 426: 
 427:         // Combine groups
 428:         foreach ($aGroupWhere as $groupname => $group) {
 429:             if ($mLastGroup != false) {
 430:                 $sOperator = 'AND';
 431:                 // Check if there's a group condition
 432:                 if (isset($this->_groupConditions[$groupname])) {
 433:                     if (isset($this->_groupConditions[$groupname][$mLastGroup])) {
 434:                         $sOperator = $this->_groupConditions[$groupname][$mLastGroup];
 435:                     }
 436:                 }
 437: 
 438:                 // Reverse check
 439:                 if (isset($this->_groupConditions[$mLastGroup])) {
 440:                     if (isset($this->_groupConditions[$mLastGroup][$groupname])) {
 441:                         $sOperator = $this->_groupConditions[$mLastGroup][$groupname];
 442:                     }
 443:                 }
 444: 
 445:                 $sGroupWhereStatement .= ' ' . $sOperator . ' (' . $group . ')';
 446:             } else {
 447:                 $sGroupWhereStatement .= '(' . $group . ')';
 448:             }
 449: 
 450:             $mLastGroup = $groupname;
 451:         }
 452: 
 453:         return $sGroupWhereStatement;
 454:     }
 455: 
 456:     /**
 457:      * Builds a where statement out of the setWhere calls
 458:      *
 459:      * @return array
 460:      *         With all where statements
 461:      */
 462:     protected function _buildWhereStatements() {
 463:         $aWheres = array();
 464: 
 465:         // Build global where condition
 466:         foreach ($this->_where['global'] as $field => $item) {
 467:             $aWheres[] = $this->_driver->buildOperator($field, $item['operator'], $item['restriction']);
 468:         }
 469: 
 470:         return implode(' AND ', $aWheres);
 471:     }
 472: 
 473:     /**
 474:      * Fetches all tables which will be joined later on.
 475:      *
 476:      * The returned array has the following format:
 477:      * <pre>
 478:      * array(
 479:      * array(fields),
 480:      * array(tables),
 481:      * array(joins),
 482:      * array(wheres)
 483:      * );
 484:      * </pre>
 485:      *
 486:      * Notes:
 487:      * The table is the table name which needs to be added to the FROM clause
 488:      * The join statement which is inserted after the master table
 489:      * The where statement is combined with all other where statements
 490:      * The fields to select from
 491:      *
 492:      * @throws cException
 493:      *         if no join partner could be found
 494:      * @return array
 495:      *         Array structure, see above
 496:      */
 497:     protected function _fetchJoinTables() {
 498:         $aParameters = array();
 499:         $aFields = array();
 500:         $aTables = array();
 501:         $aJoins = array();
 502:         $aWheres = array();
 503: 
 504:         // Fetch linked tables
 505:         foreach ($this->_links as $link => $object) {
 506:             $matches = $this->_findReverseJoinPartner(strtolower(get_class($this)), $link);
 507:             if ($matches !== false) {
 508:                 if (isset($matches['desttable'])) {
 509:                     // Driver function: Build query parts
 510:                     $aParameters[] = $this->_driver->buildJoinQuery($matches['desttable'], strtolower($matches['destclass']), $matches['key'], strtolower($matches['sourceclass']), $matches['key']);
 511:                 } else {
 512:                     foreach ($matches as $match) {
 513:                         $aParameters[] = $this->_driver->buildJoinQuery($match['desttable'], strtolower($match['destclass']), $match['key'], strtolower($match['sourceclass']), $match['key']);
 514:                     }
 515:                 }
 516:             } else {
 517:                 throw new cUnexpectedValueException("The join partner '" . get_class($this) . "' is not registered and can not be used with link().");
 518:             }
 519:         }
 520: 
 521:         // Add this class
 522:         $aFields[] = strtolower(strtolower(get_class($this))) . '.' . $this->getPrimaryKeyName();
 523: 
 524:         // Make the parameters unique
 525:         foreach ($aParameters as $parameter) {
 526:             array_unshift($aFields, $parameter['field']);
 527:             array_unshift($aTables, $parameter['table']);
 528:             array_unshift($aJoins, $parameter['join']);
 529:             array_unshift($aWheres, $parameter['where']);
 530:         }
 531: 
 532:         $aFields = array_filter(array_unique($aFields));
 533:         $aTables = array_filter(array_unique($aTables));
 534:         $aJoins = array_filter(array_unique($aJoins));
 535:         $aWheres = array_filter(array_unique($aWheres));
 536: 
 537:         return array(
 538:             'fields' => $aFields,
 539:             'tables' => $aTables,
 540:             'joins' => $aJoins,
 541:             'wheres' => $aWheres
 542:         );
 543:     }
 544: 
 545:     /**
 546:      * Resolves links (class names of joined partners)
 547:      *
 548:      * @return array
 549:      */
 550:     protected function _resolveLinks() {
 551:         $aResolvedLinks = array();
 552:         $aResolvedLinks[] = strtolower(get_class($this));
 553: 
 554:         foreach ($this->_JoinPartners as $link) {
 555:             $class = new $link();
 556:             $aResolvedLinks = array_merge($class->_resolveLinks(), $aResolvedLinks);
 557:         }
 558:         return $aResolvedLinks;
 559:     }
 560: 
 561:     /**
 562:      * Resets the properties
 563:      */
 564:     public function resetQuery() {
 565:         $this->setLimit(0, 0);
 566:         $this->_forwardJoinPartners = array();
 567:         $this->_links = array();
 568:         $this->_where['global'] = array();
 569:         $this->_where['groups'] = array();
 570:         $this->_groupConditions = array();
 571:         $this->_resultFields = array();
 572:     }
 573: 
 574:     /**
 575:      * Builds and runs the query
 576:      *
 577:      * @throws cException
 578:      *         if no item class has been set
 579:      * @return bool
 580:      */
 581:     public function query() {
 582:         if (!isset($this->_itemClassInstance)) {
 583:             throw new cException('GenericDB can\'t use query() if no item class is set via setItemClass');
 584:         }
 585: 
 586:         $aGroupWhereStatements = $this->_buildGroupWhereStatements();
 587:         $sWhereStatements = $this->_buildWhereStatements();
 588:         $aParameters = $this->_fetchJoinTables();
 589: 
 590:         $aStatement = array(
 591:             'SELECT',
 592:             implode(', ', (array_merge($aParameters['fields'], $this->_resultFields))),
 593:             'FROM',
 594:             '`' . $this->table . '` AS ' . strtolower(get_class($this))
 595:         );
 596: 
 597:         if (count($aParameters['tables']) > 0) {
 598:             $aStatement[] = implode(', ', $aParameters['tables']);
 599:         }
 600: 
 601:         if (count($aParameters['joins']) > 0) {
 602:             $aStatement[] = implode(' ', $aParameters['joins']);
 603:         }
 604: 
 605:         $aWheres = array();
 606: 
 607:         if (count($aParameters['wheres']) > 0) {
 608:             $aWheres[] = implode(', ', $aParameters['wheres']);
 609:         }
 610: 
 611:         if ($aGroupWhereStatements != '') {
 612:             $aWheres[] = $aGroupWhereStatements;
 613:         }
 614: 
 615:         if ($sWhereStatements != '') {
 616:             $aWheres[] = $sWhereStatements;
 617:         }
 618: 
 619:         if (count($aWheres) > 0) {
 620:             $aStatement[] = 'WHERE ' . implode(' AND ', $aWheres);
 621:         }
 622: 
 623:         if ($this->_order != '') {
 624:             $aStatement[] = 'ORDER BY ' . $this->_order;
 625:         }
 626: 
 627:         if ($this->_limitStart > 0 || $this->_limitCount > 0) {
 628:             $iRowStart = intval($this->_limitStart);
 629:             $iRowCount = intval($this->_limitCount);
 630:             $aStatement[] = "LIMIT $iRowStart, $iRowCount";
 631:         }
 632: 
 633:         $sql = implode(' ', $aStatement);
 634: 
 635:         $result = $this->db->query($sql);
 636:         $this->_lastSQL = $sql;
 637:         // @todo disable all mode in this method for the moment. It has to be
 638:         // verified,
 639:         // if enabling will result in negative side effects.
 640:         $this->_bAllMode = false;
 641:         return ($result) ? true : false;
 642:     }
 643: 
 644:     /**
 645:      * Sets the result order part of the query
 646:      * (e.
 647:      * g. "fieldname", "fieldname DESC", "fieldname DESC, field2name ASC")
 648:      *
 649:      * @param string $order
 650:      */
 651:     public function setOrder($order) {
 652:         $this->_order = strtolower($order);
 653:     }
 654: 
 655:     /**
 656:      * Adds a result field
 657:      *
 658:      * @param string $sField
 659:      */
 660:     public function addResultField($sField) {
 661:         $sField = strtolower($sField);
 662:         if (!in_array($sField, $this->_resultFields)) {
 663:             $this->_resultFields[] = $sField;
 664:         }
 665:     }
 666: 
 667:     /**
 668:      * Removes existing result field
 669:      *
 670:      * @param string $sField
 671:      */
 672:     public function removeResultField($sField) {
 673:         $sField = strtolower($sField);
 674:         $key = array_search($sField, $this->_resultFields);
 675:         if ($key !== false) {
 676:             unset($this->_resultFields[$key]);
 677:         }
 678:     }
 679: 
 680:     /**
 681:      * Returns reverse join partner.
 682:      *
 683:      * @param string $sParentClass
 684:      * @param string $sClassName
 685:      * @return array|bool
 686:      */
 687:     protected function _findReverseJoinPartner($sParentClass, $sClassName) {
 688:         // Make the parameters lowercase, as get_class is buggy
 689:         $sClassName = strtolower($sClassName);
 690:         $sParentClass = strtolower($sParentClass);
 691: 
 692:         // Check if we found a direct link
 693:         if (in_array($sClassName, $this->_JoinPartners)) {
 694:             $obj = new $sClassName();
 695:             return array(
 696:                 'desttable' => $obj->table,
 697:                 'destclass' => $sClassName,
 698:                 'sourceclass' => $sParentClass,
 699:                 'key' => $obj->getPrimaryKeyName()
 700:             );
 701:         } else {
 702:             // Recurse all items
 703:             foreach ($this->_JoinPartners as $join => $tmpClassname) {
 704:                 $obj = new $tmpClassname();
 705:                 $status = $obj->_findReverseJoinPartner($tmpClassname, $sClassName);
 706: 
 707:                 if (is_array($status)) {
 708:                     $returns = array();
 709: 
 710:                     if (!isset($status['desttable'])) {
 711:                         foreach ($status as $subitem) {
 712:                             $returns[] = $subitem;
 713:                         }
 714:                     } else {
 715:                         $returns[] = $status;
 716:                     }
 717: 
 718:                     $returns[] = array(
 719:                         'desttable' => $obj->table,
 720:                         'destclass' => $tmpClassname,
 721:                         'sourceclass' => $sParentClass,
 722:                         'key' => $obj->getPrimaryKeyName()
 723:                     );
 724:                     return $returns;
 725:                 }
 726:             }
 727:         }
 728:         return false;
 729:     }
 730: 
 731:     /**
 732:      * Selects all entries from the database.
 733:      * Objects are loaded using their primary key.
 734:      *
 735:      * @param string $sWhere [optional]
 736:      *         Specifies the where clause.
 737:      * @param string $sGroupBy [optional]
 738:      *         Specifies the group by clause.
 739:      * @param string $sOrderBy [optional]
 740:      *         Specifies the order by clause.
 741:      * @param string $sLimit [optional]
 742:      *         Specifies the limit by clause.
 743:      * @return bool
 744:      *         True on success, otherwise false
 745:      */
 746:     public function select($sWhere = '', $sGroupBy = '', $sOrderBy = '', $sLimit = '') {
 747:         unset($this->objects);
 748: 
 749:         if ($sWhere == '') {
 750:             $sWhere = '';
 751:         } else {
 752:             $sWhere = ' WHERE ' . $sWhere;
 753:         }
 754: 
 755:         if ($sGroupBy != '') {
 756:             $sGroupBy = ' GROUP BY ' . $sGroupBy;
 757:         }
 758: 
 759:         if ($sOrderBy != '') {
 760:             $sOrderBy = ' ORDER BY ' . $sOrderBy;
 761:         }
 762: 
 763:         if ($sLimit != '') {
 764:             $sLimit = ' LIMIT ' . $sLimit;
 765:         }
 766: 
 767:         $sFields = ($this->_settings['select_all_mode']) ? '*' : $this->getPrimaryKeyName();
 768:         $sql = 'SELECT ' . $sFields . ' FROM `' . $this->table . '`' . $sWhere . $sGroupBy . $sOrderBy . $sLimit;
 769:         $this->db->query($sql);
 770:         $this->_lastSQL = $sql;
 771:         $this->_bAllMode = $this->_settings['select_all_mode'];
 772: 
 773:         if ($this->db->numRows() == 0) {
 774:             return false;
 775:         } else {
 776:             return true;
 777:         }
 778:     }
 779: 
 780:     /**
 781:      * Selects all entries from the database.
 782:      * Objects are loaded using their primary key.
 783:      *
 784:      * @param string $sDistinct [optional]
 785:      *         Specifies if distinct will be added to the SQL statement
 786:      *         ($sDistinct !== '' -> DISTINCT)
 787:      * @param string $sFrom [optional]
 788:      *         Specifies the additional from clause (e.g.
 789:      *         'con_news_groups AS groups, con_news_groupmembers AS groupmembers').
 790:      * @param string $sWhere [optional]
 791:      *         Specifies the where clause.
 792:      * @param string $sGroupBy [optional]
 793:      *         Specifies the group by clause.
 794:      * @param string $sOrderBy [optional]
 795:      *         Specifies the order by clause.
 796:      * @param string $sLimit [optional]
 797:      *         Specifies the limit by clause.
 798:      * @return bool
 799:      *         True on success, otherwise false
 800:      */
 801:     public function flexSelect($sDistinct = '', $sFrom = '', $sWhere = '', $sGroupBy = '', $sOrderBy = '', $sLimit = '') {
 802:         unset($this->objects);
 803: 
 804:         if ($sDistinct != '') {
 805:             $sDistinct = 'DISTINCT ';
 806:         }
 807: 
 808:         if ($sFrom != '') {
 809:             $sFrom = ', ' . $sFrom;
 810:         }
 811: 
 812:         if ($sWhere != '') {
 813:             $sWhere = ' WHERE ' . $sWhere;
 814:         }
 815: 
 816:         if ($sGroupBy != '') {
 817:             $sGroupBy = ' GROUP BY ' . $sGroupBy;
 818:         }
 819: 
 820:         if ($sOrderBy != '') {
 821:             $sOrderBy = ' ORDER BY ' . $sOrderBy;
 822:         }
 823: 
 824:         if ($sLimit != '') {
 825:             $sLimit = ' LIMIT ' . $sLimit;
 826:         }
 827: 
 828:         $sql = 'SELECT ' . $sDistinct . strtolower(get_class($this)) . '.' . $this->getPrimaryKeyName() . ' AS ' . $this->getPrimaryKeyName() . ' FROM `' . $this->table . '` AS ' . strtolower(get_class($this)) . $sFrom . $sWhere . $sGroupBy . $sOrderBy . $sLimit;
 829: 
 830:         $this->db->query($sql);
 831:         $this->_lastSQL = $sql;
 832:         // @todo disable all mode in this method
 833:         $this->_bAllMode = false;
 834: 
 835:         if ($this->db->numRows() == 0) {
 836:             return false;
 837:         } else {
 838:             return true;
 839:         }
 840:     }
 841: 
 842:     /**
 843:      * Checks if a specific entry exists.
 844:      *
 845:      * @param mixed $mId
 846:      *         The id to check for (could be numeric or string)
 847:      * @return bool
 848:      *         True if object exists, false if not
 849:      */
 850:     public function exists($mId) {
 851:         $oDb = $this->_getSecondDBInstance();
 852:         $sql = "SELECT `%s` FROM %s WHERE %s='%s'";
 853:         $oDb->query($sql, $this->getPrimaryKeyName(), $this->table, $this->getPrimaryKeyName(), $mId);
 854:         return ($oDb->nextRecord()) ? true : false;
 855:     }
 856: 
 857:     /**
 858:      * Advances to the next item in the database.
 859:      *
 860:      * @return Item|bool
 861:      *         next object, or false if no more objects
 862:      */
 863:     public function next() {
 864:         $ret = false;
 865:         while ($this->db->nextRecord()) {
 866:             if ($this->_bAllMode) {
 867:                 $aRs = $this->db->toArray(cDb::FETCH_BOTH);
 868:                 $ret = $this->loadItem($aRs);
 869:             } else {
 870:                 $ret = $this->loadItem($this->db->f($this->getPrimaryKeyName()));
 871:             }
 872: 
 873:             if ($ret->get($this->getPrimaryKeyName()) == "") {
 874:                 continue;
 875:             } else {
 876:                 break;
 877:             }
 878:         }
 879:         return $ret;
 880:     }
 881: 
 882:     /**
 883:      * Fetches the resultset related to current loaded primary key as an object.
 884:      *
 885:      * @param string $sClassName
 886:      * @return Item
 887:      */
 888:     public function fetchObject($sClassName) {
 889:         $sKey = strtolower($sClassName);
 890: 
 891:         if (!is_object($this->_collectionCache[$sKey])) {
 892:             $this->_collectionCache[$sKey] = new $sClassName();
 893:         }
 894:         /* @var $obj ItemCollection */
 895:         $obj = $this->_collectionCache[$sKey];
 896:         return $obj->loadItem($this->db->f($obj->getPrimaryKeyName()));
 897:     }
 898: 
 899:     /**
 900:      * Notes:
 901:      * If the array contains keys, the key will be used as alias for the field.
 902:      * Example: array('id' => 'idcat') will put 'idcat' into field 'id'
 903:      * $aObjects = array with the objects to fetch. Notes: If the array contains
 904:      * keys, the key will be used as alias for the object. If you specify more
 905:      * than one object with the same key, the array will be multi-dimensional.
 906:      *
 907:      * @param array $aFields [optional]
 908:      *         array with the fields to fetch
 909:      * @param array $aObjects [optional]
 910:      * @return array
 911:      */
 912:     public function fetchTable(array $aFields = array(), array $aObjects = array()) {
 913:         $row = 1;
 914:         $aTable = array();
 915: 
 916:         if ($this->count() > 0) {
 917: 
 918:             $this->db->seek(0);
 919: 
 920:             while ($this->db->nextRecord()) {
 921:                 foreach ($aFields as $alias => $field) {
 922:                     if ($alias != '') {
 923:                         $aTable[$row][$alias] = $this->db->f($field);
 924:                     } else {
 925:                         $aTable[$row][$field] = $this->db->f($field);
 926:                     }
 927:                 }
 928: 
 929:                 // Fetch objects
 930:                 foreach ($aObjects as $alias => $object) {
 931:                     if ($alias != '') {
 932:                         if (isset($aTable[$row][$alias])) {
 933:                             // Is set, check for array. If no array, create one
 934:                             if (is_array($aTable[$row][$alias])) {
 935:                                 $aTable[$row][$alias][] = $this->fetchObject($object);
 936:                             } else {
 937:                                 // $tmpObj = $aTable[$row][$alias];
 938:                                 $aTable[$row][$alias] = array();
 939:                                 $aTable[$row][$alias][] = $this->fetchObject($object);
 940:                             }
 941:                         } else {
 942:                             $aTable[$row][$alias] = $this->fetchObject($object);
 943:                         }
 944:                     } else {
 945:                         $aTable[$row][$object] = $this->fetchObject($object);
 946:                     }
 947:                 }
 948:                 $row++;
 949:             }
 950: 
 951:             $this->db->seek(0);
 952: 
 953:         }
 954: 
 955:         return $aTable;
 956:     }
 957: 
 958:     /**
 959:      * Returns an array of arrays
 960:      *
 961:      * @param array $aObjects
 962:      *         With the correct order of the objects
 963:      * @return array
 964:      *         Result
 965:      */
 966:     public function queryAndFetchStructured(array $aObjects) {
 967:         $aOrder = array();
 968:         $aFetchObjects = array();
 969:         $aResult = array();
 970: 
 971:         foreach ($aObjects as $object) {
 972:             $x = new $object();
 973:             $object = strtolower($object);
 974:             $aOrder[] = $object . '.' . $x->getPrimaryKeyName() . ' ASC';
 975:             $aFetchObjects[] = $x;
 976:         }
 977: 
 978:         $this->setOrder(implode(', ', $aOrder));
 979:         $this->query();
 980: 
 981:         $this->db->seek(0);
 982: 
 983:         while ($this->db->nextRecord()) {
 984:             $aResult = $this->_recursiveStructuredFetch($aFetchObjects, $aResult);
 985:         }
 986: 
 987:         return $aResult;
 988:     }
 989: 
 990:     /**
 991:      *
 992:      * @param array $aObjects
 993:      * @param array $aResult
 994:      * @return array
 995:      */
 996:     protected function _recursiveStructuredFetch(array $aObjects, array $aResult) {
 997:         $i = array_shift($aObjects);
 998: 
 999:         $value = $this->db->f($i->getPrimaryKeyName());
1000: 
1001:         if (!is_null($value)) {
1002:             $aResult[$value]['class'] = strtolower(get_class($i));
1003:             $aResult[$value]['object'] = $i->loadItem($value);
1004: 
1005:             if (count($aObjects) > 0) {
1006:                 $aResult[$value]['items'] = $this->_recursiveStructuredFetch($aObjects, $aResult[$value]['items']);
1007:             }
1008:         }
1009: 
1010:         return $aResult;
1011:     }
1012: 
1013:     /**
1014:      * Returns the amount of returned items
1015:      *
1016:      * @return int
1017:      *         Number of rows
1018:      */
1019:     public function count() {
1020:         return $this->db->numRows();
1021:     }
1022: 
1023:     /**
1024:      * Loads a single entry by it's id.
1025:      *
1026:      * @param string|int $id
1027:      *         The primary key of the item to load.
1028:      * @return Item
1029:      *         The loaded item
1030:      */
1031:     public function fetchById($id) {
1032:         if (is_numeric($id)) {
1033:             $id = (int) $id;
1034:         } elseif (is_string($id)) {
1035:             $id = $this->escape($id);
1036:         }
1037:         return $this->loadItem($id);
1038:     }
1039: 
1040:     /**
1041:      * Loads a single object from the database.
1042:      *
1043:      * @param mixed $mItem
1044:      *         The primary key of the item to load or a recordset with itemdata
1045:      *         (array) to inject to the item object.
1046:      * @throws cException
1047:      *         If item class is not set
1048:      * @return Item
1049:      *         The newly created object
1050:      */
1051:     public function loadItem($mItem) {
1052:         if (empty($this->_itemClass)) {
1053:             $sMsg = "ItemClass has to be set in the constructor of class " . get_class($this) . ")";
1054:             throw new cException($sMsg);
1055:         }
1056: 
1057:         if (!is_object($this->_iteratorItem)) {
1058:             $this->_iteratorItem = new $this->_itemClass();
1059:         }
1060:         $obj = clone $this->_iteratorItem;
1061: 
1062:         if (is_array($mItem)) {
1063:             $obj->loadByRecordSet($mItem);
1064:         } else {
1065:             $obj->loadByPrimaryKey($mItem);
1066:         }
1067: 
1068:         return $obj;
1069:     }
1070: 
1071:     /**
1072:      * Creates a new item in the table and loads it afterwards.
1073:      *
1074:      * @param string|array $data [optional]
1075:      *         optional parameter for direct input of primary key value
1076:      *         (string) or multiple column name - value pairs
1077:      * @return Item
1078:      *         The newly created object
1079:      */
1080:     public function createNewItem($data = NULL) {
1081:         $this->_executeCallbacks(self::CREATE_BEFORE, get_class($this), array());
1082: 
1083:         $db = $this->_getSecondDBInstance();
1084: 
1085:         $primaryKeyValue = NULL;
1086:         // prepare the primary key value and the data depending on the type of
1087:         // $data
1088:         if (is_array($data)) {
1089:             if (array_key_exists($this->getPrimaryKeyName(), $data)) {
1090:                 $primaryKeyValue = $data[$this->getPrimaryKeyName()];
1091:             }
1092:         } else {
1093:             // data is the primary key
1094:             $primaryKeyValue = $data;
1095:             $data = array(
1096:                 $this->getPrimaryKeyName() => $data
1097:             );
1098:         }
1099: 
1100:         // build the insert statement and execute it
1101:         $sql = $db->buildInsert($this->table, $data);
1102: 
1103:         $db->query($sql);
1104: 
1105:         if ($primaryKeyValue === NULL) {
1106:             $primaryKeyValue = $db->getLastInsertedId();
1107:         }
1108: 
1109:         if ($db->affectedRows() == 0) {
1110:             $this->_executeCallbacks(self::CREATE_FAILURE, $this->_itemClass, array());
1111:         } else {
1112:             $this->_executeCallbacks(self::CREATE_SUCCESS, $this->_itemClass, array(
1113:                 $primaryKeyValue
1114:             ));
1115:         }
1116: 
1117:         return $this->loadItem($primaryKeyValue);
1118:     }
1119: 
1120:     /**
1121:      * Inserts a new item entry by using a existing item entry.
1122:      *
1123:      * @param object $srcItem
1124:      *         Source Item instance to copy
1125:      * @param array $fieldsToOverwrite [optional]
1126:      *         Assoziative list of fields to overwrite.
1127:      * @throws cInvalidArgumentException
1128:      *         If Item class doesn't match the defined _itemClass property
1129:      *         or passed Item instance has no loaded recordset
1130:      * @return Item|NULL
1131:      */
1132:     public function copyItem($srcItem, array $fieldsToOverwrite = array()) {
1133:         if (get_class($srcItem) !== $this->_itemClass) {
1134:             throw new cInvalidArgumentException("Item class doesn't match");
1135:         } elseif (!$srcItem->isLoaded()) {
1136:             throw new cInvalidArgumentException("Item instance has no loaded recordset");
1137:         }
1138: 
1139:         $destItem = self::createNewItem();
1140:         if (!is_object($destItem)) {
1141:             return NULL;
1142:         }
1143: 
1144:         $rs = $srcItem->toArray();
1145: 
1146:         foreach ($rs as $field => $value) {
1147:             if (is_numeric($field)) {
1148:                 // Skip index based field
1149:                 continue;
1150:             } elseif ($field == $this->getPrimaryKeyName()) {
1151:                 // Skip primary key
1152:                 continue;
1153:             }
1154: 
1155:             if (isset($fieldsToOverwrite[$field])) {
1156:                 $value = $fieldsToOverwrite[$field];
1157:             }
1158: 
1159:             $destItem->set($field, $value);
1160:         }
1161: 
1162:         $destItem->store();
1163:         return $destItem;
1164:     }
1165: 
1166:     /**
1167:      * Returns all ids of recordsets in the table matching the rules in the
1168:      * passed where clause.
1169:      *
1170:      * @param string $sWhere
1171:      *         The where clause of the SQL statement
1172:      * @return array
1173:      *         List of ids
1174:      */
1175:     public function getIdsByWhereClause($sWhere) {
1176:         $oDb = $this->_getSecondDBInstance();
1177: 
1178:         $aIds = array();
1179: 
1180:         // Get all ids
1181:         $sql = 'SELECT ' . $this->getPrimaryKeyName() . ' AS pk FROM `' . $this->table . '` WHERE ' . $sWhere;
1182:         $oDb->query($sql);
1183:         while ($oDb->nextRecord()) {
1184:             $aIds[] = $oDb->f('pk');
1185:         }
1186: 
1187:         return $aIds;
1188:     }
1189: 
1190:     /**
1191:      * Returns all specified fields of recordsets in the table matching the
1192:      * rules in the passed where clause.
1193:      *
1194:      * @param array $aFields
1195:      *         List of fields to get
1196:      * @param string $sWhere
1197:      *         The where clause of the SQL statement
1198:      * @return array
1199:      *         List of entries with specified fields
1200:      */
1201:     public function getFieldsByWhereClause(array $aFields, $sWhere) {
1202:         $oDb = $this->_getSecondDBInstance();
1203: 
1204:         $aEntries = array();
1205: 
1206:         if (count($aFields) == 0) {
1207:             return $aEntries;
1208:         }
1209: 
1210:         // Delete multiple db entries at once
1211:         $aEscapedFields = array_map(array(
1212:             $oDb,
1213:             'escape'
1214:         ), $aFields);
1215: 
1216:         $fields = implode(', ', $aEscapedFields);
1217: 
1218:         // Get all fields
1219:         $sql = 'SELECT ' . $fields . ' FROM `' . $this->table . '` WHERE ' . $sWhere;
1220:         $oDb->query($sql);
1221:         while ($oDb->nextRecord()) {
1222:             $data = array();
1223:             foreach ($aFields as $field) {
1224:                 $data[$field] = $oDb->f($field);
1225:             }
1226:             $aEntries[] = $data;
1227:         }
1228: 
1229:         return $aEntries;
1230:     }
1231: 
1232:     /**
1233:      * Returns all ids of recordsets in the table.
1234:      *
1235:      * @return array
1236:      *         List of ids
1237:      */
1238:     public function getAllIds() {
1239:         $oDb = $this->_getSecondDBInstance();
1240: 
1241:         $aIds = array();
1242: 
1243:         // Get all ids
1244:         $sql = 'SELECT ' . $this->getPrimaryKeyName() . ' AS pk FROM `' . $this->table . '`';
1245:         $oDb->query($sql);
1246:         while ($oDb->nextRecord()) {
1247:             $aIds[] = $oDb->f('pk');
1248:         }
1249: 
1250:         return $aIds;
1251:     }
1252: 
1253:     /**
1254:      * Deletes an item in the table.
1255:      * Deletes also cached e entry and any existing properties.
1256:      *
1257:      * @param mixed $mId
1258:      *         Id of entry to delete
1259:      * @return bool
1260:      */
1261:     public function delete($mId) {
1262:         $result = $this->_delete($mId);
1263:         return $result;
1264:     }
1265: 
1266:     /**
1267:      * Deletes all found items in the table matching the rules in the passed
1268:      * where clause.
1269:      * Deletes also cached e entries and any existing properties.
1270:      *
1271:      * @param string $sWhere
1272:      *         The where clause of the SQL statement
1273:      * @return int
1274:      *         Number of deleted entries
1275:      */
1276:     public function deleteByWhereClause($sWhere) {
1277:         // Get all ids and delete related entries
1278:         $aIds = $this->getIdsByWhereClause($sWhere);
1279: 
1280:         if (!is_array($aIds) || 0 >= count($aIds)) {
1281:             return 0;
1282:         }
1283: 
1284:         $numDeleted = $this->_deleteMultiple($aIds);
1285:         return $numDeleted;
1286:     }
1287: 
1288:     /**
1289:      * Deletes all found items in the table matching the passed field and it's
1290:      * value.
1291:      * Deletes also cached e entries and any existing properties.
1292:      *
1293:      * @param string $sField
1294:      *         The field name
1295:      * @param mixed $mValue
1296:      *         The value of the field
1297:      * @return int
1298:      *         Number of deleted entries
1299:      */
1300:     public function deleteBy($sField, $mValue) {
1301:         $where = (is_string($mValue)) ? "`%s` = '%s'" : "`%s` = %d";
1302:         $where = $this->db->prepare($where, $sField, $mValue);
1303: 
1304:         return $this->deleteByWhereClause($where);
1305:     }
1306: 
1307:     /**
1308:      * Deletes an item in the table, deletes also existing cache entries and
1309:      * properties of the item.
1310:      *
1311:      * @param mixed $mId
1312:      *         Id of entry to delete
1313:      * @return bool
1314:      */
1315:     protected function _delete($mId) {
1316:         $this->_executeCallbacks(self::DELETE_BEFORE, $this->_itemClass, array(
1317:             $mId
1318:         ));
1319: 
1320:         $oDb = $this->_getSecondDBInstance();
1321: 
1322:         // delete db entry
1323:         $sql = "DELETE FROM `%s` WHERE %s = '%s'";
1324:         $oDb->query($sql, $this->table, $this->getPrimaryKeyName(), $mId);
1325:         $success = $oDb->affectedRows();
1326: 
1327:         // delete cache entry
1328:         $this->_oCache->removeItem($mId);
1329: 
1330:         // delete the property values
1331:         $oProperties = $this->_getPropertiesCollectionInstance();
1332:         $oProperties->deleteProperties($this->getPrimaryKeyName(), $mId);
1333: 
1334:         if ($success == 0) {
1335:             $this->_executeCallbacks(self::DELETE_FAILURE, $this->_itemClass, array(
1336:                 $mId
1337:             ));
1338:             return false;
1339:         } else {
1340:             $this->_executeCallbacks(self::DELETE_SUCCESS, $this->_itemClass, array(
1341:                 $mId
1342:             ));
1343:             return true;
1344:         }
1345:     }
1346: 
1347:     /**
1348:      * Deletes all items in the table, deletes also existing cache entries and
1349:      * properties of the item.
1350:      *
1351:      * @param array $aIds
1352:      *         Id of entries to delete (has to be called w/ an array!)
1353:      * @return int
1354:      *         Number of affected records
1355:      */
1356:     protected function _deleteMultiple(array $aIds) {
1357:         foreach ($aIds as $mId) {
1358:             $this->_executeCallbacks(self::DELETE_BEFORE, $this->_itemClass, array(
1359:                 $mId
1360:             ));
1361:         }
1362: 
1363:         $oDb = $this->_getSecondDBInstance();
1364: 
1365:         // Delete multiple db entries at once
1366:         $aEscapedIds = array_map(array(
1367:             $oDb,
1368:             'escape'
1369:         ), $aIds);
1370:         $in = "'" . implode("', '", $aEscapedIds) . "'";
1371:         $sql = "DELETE FROM `%s` WHERE %s IN (" . $in . ")";
1372:         $oDb->query($sql, $this->table, $this->getPrimaryKeyName());
1373:         $numAffected = $oDb->affectedRows();
1374: 
1375:         // Delete cache entries
1376:         $this->_oCache->removeItems($aIds);
1377: 
1378:         // Delete the property values
1379:         $oProperties = $this->_getPropertiesCollectionInstance();
1380:         $oProperties->deletePropertiesMultiple($this->getPrimaryKeyName(), $aIds);
1381: 
1382:         // NOTE: Deleteing multiple entries at once has a drawback. There is no
1383:         // way to detect faulty ids, if one or more entries couldn't deleted.
1384:         if ($numAffected == 0) {
1385:             foreach ($aIds as $mId) {
1386:                 $this->_executeCallbacks(self::DELETE_FAILURE, $this->_itemClass, array(
1387:                     $mId
1388:                 ));
1389:             }
1390:         } else {
1391:             foreach ($aIds as $mId) {
1392:                 $this->_executeCallbacks(self::DELETE_SUCCESS, $this->_itemClass, array(
1393:                     $mId
1394:                 ));
1395:             }
1396:         }
1397:         return $numAffected;
1398:     }
1399: 
1400:     /**
1401:      * Fetches an array of fields from the database.
1402:      *
1403:      * Example:
1404:      * $i = $object->fetchArray('idartlang', array('idlang', 'name'));
1405:      *
1406:      * could result in:
1407:      * $i[5] = array('idlang' => 5, 'name' => 'My Article');
1408:      *
1409:      * Important: If you don't pass an array for fields, the function
1410:      * doesn't create an array.
1411:      *
1412:      * @param string $sKey
1413:      *         Name of the field to use for the key
1414:      * @param mixed $mFields
1415:      *         String or array
1416:      * @return array
1417:      *         Resulting array
1418:      */
1419:     public function fetchArray($sKey, $mFields) {
1420:         $aResult = array();
1421: 
1422:         while (($item = $this->next()) !== false) {
1423:             if (is_array($mFields)) {
1424:                 foreach ($mFields as $value) {
1425:                     $aResult[$item->get($sKey)][$value] = $item->get($value);
1426:                 }
1427:             } else {
1428:                 $aResult[$item->get($sKey)] = $item->get($mFields);
1429:             }
1430:         }
1431: 
1432:         return $aResult;
1433:     }
1434: }
1435: 
CMS CONTENIDO 4.9.11 API documentation generated by ApiGen 2.8.0