[ Index ]
 

Code source de Symfony 1.0.0

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/lib/vendor/propel/util/ -> BasePeer.php (source)

   1  <?php
   2  /*

   3   *  $Id: BasePeer.php 431 2006-08-21 14:06:10Z hans $

   4   *

   5   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

   6   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

   7   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

   8   * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

   9   * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

  10   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

  11   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

  12   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

  13   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

  14   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

  15   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

  16   *

  17   * This software consists of voluntary contributions made by many individuals

  18   * and is licensed under the LGPL. For more information please see

  19   * <http://propel.phpdb.org>.

  20   */
  21  
  22  include_once 'propel/adapter/DBAdapter.php';
  23  include_once 'propel/map/ColumnMap.php';
  24  include_once 'propel/map/DatabaseMap.php';
  25  include_once 'propel/map/MapBuilder.php';
  26  include_once 'propel/map/TableMap.php';
  27  include_once 'propel/map/ValidatorMap.php';
  28  include_once 'propel/validator/ValidationFailed.php';
  29  
  30  /**

  31   * This is a utility class for all generated Peer classes in the system.

  32   *

  33   * Peer classes are responsible for isolating all of the database access

  34   * for a specific business object.  They execute all of the SQL

  35   * against the database.  Over time this class has grown to include

  36   * utility methods which ease execution of cross-database queries and

  37   * the implementation of concrete Peers.

  38   *

  39   * @author Hans Lellelid <hans@xmpl.org> (Propel)

  40   * @author Kaspars Jaudzems <kaspars.jaudzems@inbox.lv> (Propel)

  41   * @author Frank Y. Kim <frank.kim@clearink.com> (Torque)

  42   * @author John D. McNally <jmcnally@collab.net> (Torque)

  43   * @author Brett McLaughlin <bmclaugh@algx.net> (Torque)

  44   * @author Stephen Haberman <stephenh@chase3000.com> (Torque)

  45   * @version $Revision: 431 $

  46   * @package propel.util

  47   */
  48  class BasePeer
  49  {
  50  
  51      /** Array (hash) that contains the cached mapBuilders. */

  52      private static $mapBuilders = array();
  53  
  54      /** Array (hash) that contains cached validators */

  55      private static $validatorMap = array();
  56  
  57      /**

  58       * phpname type

  59       * e.g. 'AuthorId'

  60       */
  61      const TYPE_PHPNAME = 'phpName';
  62  
  63      /**

  64       * column (peer) name type

  65       * e.g. 'book.AUTHOR_ID'

  66       */
  67      const TYPE_COLNAME = 'colName';
  68  
  69      /**

  70       * column fieldname type

  71       * e.g. 'author_id'

  72       */
  73      const TYPE_FIELDNAME = 'fieldName';
  74  
  75      /**

  76       * num type

  77       * simply the numerical array index, e.g. 4

  78       */
  79      const TYPE_NUM = 'num';
  80  
  81  	static public function getFieldnames ($classname, $type = self::TYPE_PHPNAME) {
  82  
  83          // TODO we should take care of including the peer class here

  84  
  85          $peerclass = 'Base' . $classname . 'Peer'; // TODO is this always true?

  86          $callable = array($peerclass, 'getFieldnames');
  87          $args = array($type);
  88  
  89          return call_user_func_array($callable, $args);
  90      }
  91  
  92  	static public function translateFieldname($classname, $fieldname, $fromType, $toType) {
  93  
  94          // TODO we should take care of including the peer class here

  95  
  96          $peerclass = 'Base' . $classname . 'Peer'; // TODO is this always true?

  97          $callable = array($peerclass, 'translateFieldname');
  98          $args = array($fieldname, $fromType, $toType);
  99  
 100          return call_user_func_array($callable, $args);
 101      }
 102  
 103      /**

 104       * Method to perform deletes based on values and keys in a

 105       * Criteria.

 106       *

 107       * @param Criteria $criteria The criteria to use.

 108       * @param Connection $con A Connection.

 109       * @return int    The number of rows affected by last statement execution.  For most

 110       *                 uses there is only one delete statement executed, so this number

 111       *                 will correspond to the number of rows affected by the call to this

 112       *                 method.  Note that the return value does require that this information

 113       *                 is returned (supported) by the Creole db driver.

 114       * @throws PropelException

 115       */
 116  	public static function doDelete(Criteria $criteria, Connection $con)
 117      {
 118          $db = Propel::getDB($criteria->getDbName());
 119          $dbMap = Propel::getDatabaseMap($criteria->getDbName());
 120  
 121          // Set up a list of required tables (one DELETE statement will

 122          // be executed per table)

 123  
 124          $tables_keys = array();
 125          foreach($criteria as $c) {
 126              foreach($c->getAllTables() as $tableName) {
 127                  $tableName2 = $criteria->getTableForAlias($tableName);
 128                  if ($tableName2 !== null) {
 129                      $tables_keys[$tableName2 . ' ' . $tableName] = true;
 130                  } else {
 131                      $tables_keys[$tableName] = true;
 132                  }
 133              }
 134          } // foreach criteria->keys()

 135  
 136          $affectedRows = 0; // initialize this in case the next loop has no iterations.

 137  
 138          $tables = array_keys($tables_keys);
 139  
 140          foreach($tables as $tableName) {
 141  
 142              $whereClause = array();
 143              $selectParams = array();
 144              foreach($dbMap->getTable($tableName)->getColumns() as $colMap) {
 145                  $key = $tableName . '.' . $colMap->getColumnName();
 146                  if ($criteria->containsKey($key)) {
 147                      $sb = "";
 148                      $criteria->getCriterion($key)->appendPsTo($sb, $selectParams);
 149                      $whereClause[] = $sb;
 150                  }
 151              }
 152  
 153              if (empty($whereClause)) {
 154                  throw new PropelException("Cowardly refusing to delete from table $tableName with empty WHERE clause.");
 155              }
 156  
 157              // Execute the statement.

 158              try {
 159  
 160                  $sqlSnippet = implode(" AND ", $whereClause);
 161  
 162                  if ($criteria->isSingleRecord()) {
 163                      $sql = "SELECT COUNT(*) FROM " . $tableName . " WHERE " . $sqlSnippet;
 164                      $stmt = $con->prepareStatement($sql);
 165                      self::populateStmtValues($stmt, $selectParams, $dbMap);
 166                      $rs = $stmt->executeQuery(ResultSet::FETCHMODE_NUM);
 167                      $rs->next();
 168                      if ($rs->getInt(1) > 1) {
 169                          $rs->close();
 170                          throw new PropelException("Expecting to delete 1 record, but criteria match multiple.");
 171                      }
 172                      $rs->close();
 173                  }
 174  
 175                  $sql = "DELETE FROM " . $tableName . " WHERE " .  $sqlSnippet;
 176                  Propel::log($sql, Propel::LOG_DEBUG);
 177                  $stmt = $con->prepareStatement($sql);
 178                  self::populateStmtValues($stmt, $selectParams, $dbMap);
 179                  $affectedRows = $stmt->executeUpdate();
 180              } catch (Exception $e) {
 181                  Propel::log($e->getMessage(), Propel::LOG_ERR);
 182                  throw new PropelException("Unable to execute DELETE statement.",$e);
 183              }
 184  
 185          } // for each table

 186  
 187          return $affectedRows;
 188      }
 189  
 190      /**

 191       * Method to deletes all contents of specified table.

 192       *

 193       * This method is invoked from generated Peer classes like this:

 194       * <code>

 195       * public static function doDeleteAll($con = null)

 196       * {

 197       *   if ($con === null) $con = Propel::getConnection(self::DATABASE_NAME);

 198       *   BasePeer::doDeleteAll(self::TABLE_NAME, $con);

 199       * }

 200       * </code>

 201       *

 202       * @param string $tableName The name of the table to empty.

 203       * @param Connection $con A Connection.

 204       * @return int    The number of rows affected by the statement.  Note

 205       *                 that the return value does require that this information

 206       *                 is returned (supported) by the Creole db driver.

 207       * @throws PropelException - wrapping SQLException caught from statement execution.

 208       */
 209  	public static function doDeleteAll($tableName, Connection $con)
 210      {
 211          try {
 212              $sql = "DELETE FROM " . $tableName;
 213              Propel::log($sql, Propel::LOG_DEBUG);
 214              $stmt = $con->prepareStatement($sql);
 215              return $stmt->executeUpdate();
 216          } catch (Exception $e) {
 217              Propel::log($e->getMessage(), Propel::LOG_ERR);
 218              throw new PropelException("Unable to perform DELETE ALL operation.", $e);
 219          }
 220      }
 221  
 222      /**

 223       * Method to perform inserts based on values and keys in a

 224       * Criteria.

 225       * <p>

 226       * If the primary key is auto incremented the data in Criteria

 227       * will be inserted and the auto increment value will be returned.

 228       * <p>

 229       * If the primary key is included in Criteria then that value will

 230       * be used to insert the row.

 231       * <p>

 232       * If no primary key is included in Criteria then we will try to

 233       * figure out the primary key from the database map and insert the

 234       * row with the next available id using util.db.IDBroker.

 235       * <p>

 236       * If no primary key is defined for the table the values will be

 237       * inserted as specified in Criteria and null will be returned.

 238       *

 239       * @param Criteria $criteria Object containing values to insert.

 240       * @param Connection $con A Connection.

 241       * @return mixed The primary key for the new row if (and only if!) the primary key

 242       *                is auto-generated.  Otherwise will return <code>null</code>.

 243       * @throws PropelException

 244       */
 245  	public static function doInsert(Criteria $criteria, Connection $con) {
 246  
 247          // the primary key

 248          $id = null;
 249  
 250          // Get the table name and method for determining the primary

 251          // key value.

 252          $keys = $criteria->keys();
 253          if (!empty($keys)) {
 254              $tableName = $criteria->getTableName( $keys[0] );
 255          } else {
 256              throw new PropelException("Database insert attempted without anything specified to insert");
 257          }
 258  
 259          $dbMap = Propel::getDatabaseMap($criteria->getDbName());
 260          $tableMap = $dbMap->getTable($tableName);
 261          $keyInfo = $tableMap->getPrimaryKeyMethodInfo();
 262          $useIdGen = $tableMap->isUseIdGenerator();
 263          $keyGen = $con->getIdGenerator();
 264  
 265          $pk = self::getPrimaryKey($criteria);
 266  
 267          // only get a new key value if you need to

 268          // the reason is that a primary key might be defined

 269          // but you are still going to set its value. for example:

 270          // a join table where both keys are primary and you are

 271          // setting both columns with your own values

 272  
 273          // pk will be null if there is no primary key defined for the table

 274          // we're inserting into.

 275          if ($pk !== null && $useIdGen && !$criteria->containsKey($pk->getFullyQualifiedName())) {
 276  
 277              // If the keyMethod is SEQUENCE get the id before the insert.

 278              if ($keyGen->isBeforeInsert()) {
 279                  try {
 280                      $id = $keyGen->getId($keyInfo);
 281                  } catch (Exception $e) {
 282                      throw new PropelException("Unable to get sequence id.", $e);
 283                  }
 284                  $criteria->add($pk->getFullyQualifiedName(), $id);
 285              }
 286          }
 287  
 288          try {
 289  
 290              $qualifiedCols = $criteria->keys(); // we need table.column cols when populating values

 291              $columns = array(); // but just 'column' cols for the SQL

 292              foreach($qualifiedCols as $qualifiedCol) {
 293                  $columns[] = substr($qualifiedCol, strpos($qualifiedCol, '.') + 1);
 294              }
 295  
 296              $sql = "INSERT INTO " . $tableName
 297                  . " (" . implode(",", $columns) . ")"
 298                  . " VALUES (" . substr(str_repeat("?,", count($columns)), 0, -1) . ")";
 299  
 300              Propel::log($sql, Propel::LOG_DEBUG);
 301  
 302              $stmt = $con->prepareStatement($sql);
 303              self::populateStmtValues($stmt, self::buildParams($qualifiedCols, $criteria), $dbMap);
 304              $stmt->executeUpdate();
 305  
 306          } catch (Exception $e) {
 307              Propel::log($e->getMessage(), Propel::LOG_ERR);
 308              throw new PropelException("Unable to execute INSERT statement.", $e);
 309          }
 310  
 311          // If the primary key column is auto-incremented, get the id

 312          // now.

 313          if ($pk !== null && $useIdGen && $keyGen->isAfterInsert()) {
 314              try {
 315                  $id = $keyGen->getId($keyInfo);
 316              } catch (Exception $e) {
 317                  throw new PropelException("Unable to get autoincrement id.", $e);
 318              }
 319          }
 320  
 321          return $id;
 322      }
 323  
 324      /**

 325       * Method used to update rows in the DB.  Rows are selected based

 326       * on selectCriteria and updated using values in updateValues.

 327       * <p>

 328       * Use this method for performing an update of the kind:

 329       * <p>

 330       * WHERE some_column = some value AND could_have_another_column =

 331       * another value AND so on.

 332       *

 333       * @param $selectCriteria A Criteria object containing values used in where

 334       *        clause.

 335       * @param $updateValues A Criteria object containing values used in set

 336       *        clause.

 337       * @param $con     The Connection to use.

 338       * @return int    The number of rows affected by last update statement.  For most

 339       *                 uses there is only one update statement executed, so this number

 340       *                 will correspond to the number of rows affected by the call to this

 341       *                 method.  Note that the return value does require that this information

 342       *                 is returned (supported) by the Creole db driver.

 343       * @throws PropelException

 344       */
 345  	public static function doUpdate(Criteria $selectCriteria, Criteria $updateValues, Connection $con) {
 346  
 347          $db = Propel::getDB($selectCriteria->getDbName());
 348          $dbMap = Propel::getDatabaseMap($selectCriteria->getDbName());
 349  
 350          // Get list of required tables, containing all columns

 351          $tablesColumns = $selectCriteria->getTablesColumns();
 352  
 353          // we also need the columns for the update SQL

 354          $updateTablesColumns = $updateValues->getTablesColumns();
 355  
 356          $affectedRows = 0; // initialize this in case the next loop has no iterations.

 357  
 358          foreach($tablesColumns as $tableName => $columns) {
 359  
 360              $whereClause = array();
 361  
 362              $selectParams = array();
 363              foreach($columns as $colName) {
 364                  $sb = "";
 365                  $selectCriteria->getCriterion($colName)->appendPsTo($sb, $selectParams);
 366                  $whereClause[] = $sb;
 367              }
 368  
 369              $rs = null;
 370              $stmt = null;
 371              try {
 372  
 373                  $sqlSnippet = implode(" AND ", $whereClause);
 374  
 375                  if ($selectCriteria->isSingleRecord()) {
 376                      // Get affected records.

 377                      $sql = "SELECT COUNT(*) FROM " . $tableName . " WHERE " . $sqlSnippet;
 378                      $stmt = $con->prepareStatement($sql);
 379                      self::populateStmtValues($stmt, $selectParams, $dbMap);
 380                      $rs = $stmt->executeQuery(ResultSet::FETCHMODE_NUM);
 381                      $rs->next();
 382                      if ($rs->getInt(1) > 1) {
 383                          $rs->close();
 384                          throw new PropelException("Expected to update 1 record, multiple matched.");
 385                      }
 386                      $rs->close();
 387                  }
 388  
 389                  $sql = "UPDATE " . $tableName . " SET ";
 390                  foreach($updateTablesColumns[$tableName] as $col) {
 391                      $sql .= substr($col, strpos($col, '.') + 1) . " = ?,";
 392                  }
 393  
 394                  $sql = substr($sql, 0, -1) . " WHERE " . $sqlSnippet;
 395  
 396                  Propel::log($sql, Propel::LOG_DEBUG);
 397  
 398                  $stmt = $con->prepareStatement($sql);
 399  
 400                  // Replace '?' with the actual values

 401                  self::populateStmtValues($stmt, array_merge(self::buildParams($updateTablesColumns[$tableName], $updateValues), $selectParams), $dbMap);
 402  
 403                  $affectedRows = $stmt->executeUpdate();
 404                  $stmt->close();
 405  
 406              } catch (Exception $e) {
 407                  if ($rs) $rs->close();
 408                  if ($stmt) $stmt->close();
 409                  Propel::log($e->getMessage(), Propel::LOG_ERR);
 410                  throw new PropelException("Unable to execute UPDATE statement.", $e);
 411              }
 412  
 413          } // foreach table in the criteria

 414  
 415          return $affectedRows;
 416      }
 417  
 418      /**

 419       * Executes query build by createSelectSql() and returns ResultSet.

 420       *

 421       * @param Criteria $criteria A Criteria.

 422       * @param Connection $con A connection to use.

 423       * @return ResultSet The resultset.

 424       * @throws PropelException

 425       * @see createSelectSql()

 426       */
 427  	public static function doSelect(Criteria $criteria, $con = null)
 428      {
 429          $dbMap = Propel::getDatabaseMap($criteria->getDbName());
 430  
 431          if ($con === null)
 432              $con = Propel::getConnection($criteria->getDbName());
 433  
 434          $stmt = null;
 435  
 436          try {
 437  
 438              // Transaction support exists for (only?) Postgres, which must

 439              // have SELECT statements that include bytea columns wrapped w/

 440              // transactions.

 441              if ($criteria->isUseTransaction()) $con->begin();
 442  
 443              $params = array();
 444              $sql = self::createSelectSql($criteria, $params);
 445  
 446              $stmt = $con->prepareStatement($sql);
 447              $stmt->setLimit($criteria->getLimit());
 448              $stmt->setOffset($criteria->getOffset());
 449  
 450              self::populateStmtValues($stmt, $params, $dbMap);
 451  
 452              $rs = $stmt->executeQuery(ResultSet::FETCHMODE_NUM);
 453              if ($criteria->isUseTransaction()) $con->commit();
 454          } catch (Exception $e) {
 455              if ($stmt) $stmt->close();
 456              if ($criteria->isUseTransaction()) $con->rollback();
 457              Propel::log($e->getMessage(), Propel::LOG_ERR);
 458              throw new PropelException($e);
 459          }
 460  
 461          return $rs;
 462      }
 463  
 464      /**

 465       * Applies any validators that were defined in the schema to the specified columns.

 466       *

 467       * @param string $dbName The name of the database

 468       * @param string $tableName The name of the table

 469       * @param array $columns Array of column names as key and column values as value.

 470       */
 471  	public static function doValidate($dbName, $tableName, $columns)
 472      {
 473          $dbMap = Propel::getDatabaseMap($dbName);
 474          $tableMap = $dbMap->getTable($tableName);
 475          $failureMap = array(); // map of ValidationFailed objects

 476          foreach($columns as $colName => $colValue) {
 477              if ($tableMap->containsColumn($colName)) {
 478                  $col = $tableMap->getColumn($colName);
 479                  foreach($col->getValidators() as $validatorMap) {
 480                      $validator = BasePeer::getValidator($validatorMap->getClass());
 481                      if($validator && ($col->isNotNull() || $colValue !== null) && $validator->isValid($validatorMap, $colValue) === false) {
 482                          if (!isset($failureMap[$colName])) { // for now we do one ValidationFailed per column, not per rule
 483                              $failureMap[$colName] = new ValidationFailed($colName, $validatorMap->getMessage(), $validator);
 484                          }
 485                      }
 486                  }
 487              }
 488          }
 489          return (!empty($failureMap) ? $failureMap : true);
 490      }
 491  
 492      /**

 493       * Helper method which returns the primary key contained

 494       * in the given Criteria object.

 495       *

 496       * @param Criteria $criteria A Criteria.

 497       * @return ColumnMap If the Criteria object contains a primary

 498       *          key, or null if it doesn't.

 499       * @throws PropelException

 500       */
 501  	private static function getPrimaryKey(Criteria $criteria)
 502      {
 503          // Assume all the keys are for the same table.

 504          $keys = $criteria->keys();
 505          $key = $keys[0];
 506          $table = $criteria->getTableName($key);
 507  
 508          $pk = null;
 509  
 510          if (!empty($table)) {
 511  
 512              $dbMap = Propel::getDatabaseMap($criteria->getDbName());
 513  
 514              if ($dbMap === null) {
 515                  throw new PropelException("\$dbMap is null");
 516              }
 517  
 518              if ($dbMap->getTable($table) === null) {
 519                  throw new PropelException("\$dbMap->getTable() is null");
 520              }
 521  
 522              $columns = $dbMap->getTable($table)->getColumns();
 523              foreach(array_keys($columns) as $key) {
 524                  if ($columns[$key]->isPrimaryKey()) {
 525                      $pk = $columns[$key];
 526                      break;
 527                  }
 528              }
 529          }
 530          return $pk;
 531      }
 532  
 533      /**

 534       * Method to create an SQL query based on values in a Criteria.

 535       *

 536       * This method creates only prepared statement SQL (using ? where values

 537       * will go).  The second parameter ($params) stores the values that need

 538       * to be set before the statement is executed.  The reason we do it this way

 539       * is to let the Creole layer handle all escaping & value formatting.

 540       *

 541       * @param Criteria $criteria Criteria for the SELECT query.

 542       * @param array &$params Parameters that are to be replaced in prepared statement.

 543       * @return string

 544       * @throws PropelException Trouble creating the query string.

 545       */
 546  	public static function createSelectSql(Criteria $criteria, &$params) {
 547  
 548          $db = Propel::getDB($criteria->getDbName());
 549          $dbMap = Propel::getDatabaseMap($criteria->getDbName());
 550  
 551          // redundant definition $selectModifiers = array();

 552          $selectClause = array();
 553          $fromClause = array();
 554          $joinClause = array();
 555          $joinTables = array();
 556          $whereClause = array();
 557          $orderByClause = array();
 558          // redundant definition $groupByClause = array();

 559  
 560          $orderBy = $criteria->getOrderByColumns();
 561          $groupBy = $criteria->getGroupByColumns();
 562          $ignoreCase = $criteria->isIgnoreCase();
 563          $select = $criteria->getSelectColumns();
 564          $aliases = $criteria->getAsColumns();
 565  
 566          // simple copy

 567          $selectModifiers = $criteria->getSelectModifiers();
 568  
 569          // get selected columns

 570          foreach($select as $columnName) {
 571  
 572              // expect every column to be of "table.column" formation

 573              // it could be a function:  e.g. MAX(books.price)

 574  
 575              $tableName = null;
 576  
 577              $selectClause[] = $columnName; // the full column name: e.g. MAX(books.price)

 578  
 579              $parenPos = strpos($columnName, '(');
 580              $dotPos = strpos($columnName, '.');
 581  
 582              // [HL] I think we really only want to worry about adding stuff to

 583              // the fromClause if this function has a TABLE.COLUMN in it at all.

 584              // e.g. COUNT(*) should not need this treatment -- or there needs to

 585              // be special treatment for '*'

 586              if ($dotPos !== false) {
 587  
 588                  if ($parenPos === false) { // table.column
 589                      $tableName = substr($columnName, 0, $dotPos);
 590                  } else { // FUNC(table.column)
 591                      $tableName = substr($columnName, $parenPos + 1, $dotPos - ($parenPos + 1));
 592                      // functions may contain qualifiers so only take the last

 593                      // word as the table name.

 594                      // COUNT(DISTINCT books.price)

 595                      $lastSpace = strpos($tableName, ' ');
 596                      if ($lastSpace !== false) { // COUNT(DISTINCT books.price)
 597                          $tableName = substr($tableName, $lastSpace + 1);
 598                      }
 599                  }
 600                  $tableName2 = $criteria->getTableForAlias($tableName);
 601                  if ($tableName2 !== null) {
 602                      $fromClause[] = $tableName2 . ' ' . $tableName;
 603                  } else {
 604                      $fromClause[] = $tableName;
 605                  }
 606  
 607              } // if $dotPost !== null

 608          }
 609  
 610          // set the aliases

 611          foreach($aliases as $alias => $col) {
 612              $selectClause[] = $col . " AS " . $alias;
 613          }
 614  
 615          // add the criteria to WHERE clause

 616          // this will also add the table names to the FROM clause if they are not already

 617          // invluded via a LEFT JOIN

 618          foreach($criteria->keys() as $key) {
 619  
 620              $criterion = $criteria->getCriterion($key);
 621              $someCriteria = $criterion->getAttachedCriterion();
 622              $someCriteriaLength = count($someCriteria);
 623              $table = null;
 624              for ($i=0; $i < $someCriteriaLength; $i++) {
 625                  $tableName = $someCriteria[$i]->getTable();
 626  
 627                  $table = $criteria->getTableForAlias($tableName);
 628                  if ($table !== null) {
 629                      $fromClause[] = $table . ' ' . $tableName;
 630                  } else {
 631                      $fromClause[] = $tableName;
 632                      $table = $tableName;
 633                  }
 634  
 635                  $ignoreCase =
 636                      (($criteria->isIgnoreCase()
 637                          || $someCriteria[$i]->isIgnoreCase())
 638                          && ($dbMap->getTable($table)->getColumn($someCriteria[$i]->getColumn())->getType() == "string" )
 639                           );
 640  
 641                  $someCriteria[$i]->setIgnoreCase($ignoreCase);
 642              }
 643  
 644              $criterion->setDB($db);
 645  
 646              $sb = "";
 647              $criterion->appendPsTo($sb, $params);
 648              $whereClause[] = $sb;
 649  
 650          }
 651          
 652          // handle RIGHT (straight) joins

 653          // Loop through the joins, 

 654          // joins with a null join type will be added to the FROM clause and the condition added to the WHERE clause.

 655          // joins of a specified type: the LEFT side will be added to the fromClause and the RIGHT to the joinClause 

 656          // New Code.

 657          foreach ((array) $criteria->getJoins() as $join) { // we'll only loop if there's actually something here
 658  
 659              // The join might have been established using an alias name

 660  
 661              $leftTable = $join->getLeftTableName();
 662              $leftTableAlias = '';
 663              if ($realTable = $criteria->getTableForAlias($leftTable)) {
 664                  $leftTableAlias = " $leftTable";
 665                  $leftTable = $realTable;
 666              }
 667              
 668              $rightTable = $join->getRightTableName();
 669              $rightTableAlias = '';
 670              if ($realTable = $criteria->getTableForAlias($rightTable)) {
 671                  $rightTableAlias = " $rightTable";
 672                  $rightTable = $realTable;
 673              }
 674                      
 675              // determine if casing is relevant.

 676              if ($ignoreCase = $criteria->isIgnoreCase()) {
 677                  $leftColType = $dbMap->getTable($leftTable)->getColumn($join->getLeftColumnName())->getType();
 678                  $rightColType = $dbMap->getTable($rightTable)->getColumn($join->getRightColumnName())->getType();
 679                  $ignoreCase = ($leftColType == 'string' || $rightColType == 'string');
 680              }
 681  
 682              // build the condition

 683              if ($ignoreCase) {
 684                  $condition = $db->ignoreCase($join->getLeftColumn()) . '=' . $db->ignoreCase($join->getRightColumn());
 685              } else {
 686                  $condition = $join->getLeftColumn() . '=' . $join->getRightColumn();
 687              }
 688                      
 689              // add 'em to the queues..  

 690              if ($joinType = $join->getJoinType()) { 
 691                  if (!$fromClause) {
 692                      $fromClause[] = $leftTable . $leftTableAlias;
 693                  }
 694                  $joinTables[] = $rightTable . $rightTableAlias;
 695                  $joinClause[] = $join->getJoinType() . ' ' . $rightTable . $rightTableAlias . " ON ($condition)";
 696              } else { 
 697                  $fromClause[] = $leftTable . $leftTableAlias;
 698                  $fromClause[] = $rightTable . $rightTableAlias;
 699                  $whereClause[] = $condition;
 700              }
 701          }
 702          
 703          // Unique from clause elements

 704          $fromClause = array_unique($fromClause);
 705                  
 706          // tables should not exist in both the from and join clauses

 707          if ($joinTables && $fromClause) {
 708              foreach ($fromClause as $fi => $ftable) {
 709                  if (in_array($ftable, $joinTables)) {
 710                      unset($fromClause[$fi]);
 711                  }
 712              }
 713          }
 714  /*

 715                  // Old Code.

 716                  $joins =& $criteria->getJoins();

 717                  if (!empty($joins)) {

 718                      for ($i=0, $joinSize=count($joins); $i < $joinSize; $i++) {

 719                          $join =& $joins[$i];

 720                          $join1 = $join->getLeftColumn();

 721                          $join2 = $join->getRightColumn();

 722  

 723                          $tableName = substr($join1, 0, strpos($join1, '.'));

 724                          $table = $criteria->getTableForAlias($tableName);

 725                          if ($table !== null) {

 726                              $fromClause[] = $table . ' ' . $tableName;

 727                          } else {

 728                              $fromClause[] = $tableName;

 729                          }

 730  

 731                          $dot = strpos($join2, '.');

 732                          $tableName = substr($join2, 0, $dot);

 733                          $table = $criteria->getTableForAlias($tableName);

 734                          if ($table !== null) {

 735                              $fromClause[] = $table . ' ' . $tableName;

 736                          } else {

 737                              $fromClause[] = $tableName;

 738                              $table = $tableName;

 739                          }

 740                          $ignoreCase = ($criteria->isIgnoreCase() && ($dbMap->getTable($table)->getColumn(substr($join2, $dot + 1))->getType() == "string"));

 741                          if ($ignoreCase) {

 742                              $whereClause[] = $db->ignoreCase($join1) . '=' . $db->ignoreCase($join2);

 743                          } else {

 744                              $whereClause[] = $join1 . '=' . $join2;

 745                          }

 746                      if ($join->getJoinType()) {

 747                              $leftTable = $fromClause[count($fromClause) - 2];

 748                              $rightTable = $fromClause[count($fromClause) - 1];

 749                              $onClause = $whereClause[count($whereClause) - 1];

 750                              unset($whereClause[count($whereClause) - 1]);

 751                              $fromClause [] = $leftTable . ' ' . $join->getJoinType() . ' ' . $rightTable . ' ON ' . $onClause;

 752  

 753                              // remove all references to joinTables made by selectColumns, criteriaColumns

 754                              for ($i = 0, $fromClauseSize=count($fromClause); $i < $fromClauseSize; $i++) {

 755                                  if ($fromClause[$i] == $leftTable || $fromClause[$i] == $rightTable) {

 756                                      unset($fromClause[$i]);

 757                                  }

 758                              }

 759                          } // If join type

 760                      } // Join for loop

 761                  } // If Joins

 762  */
 763          
 764          // Add the GROUP BY columns

 765          $groupByClause = $groupBy;
 766  
 767          $having = $criteria->getHaving();
 768          $havingString = null;
 769          if ($having !== null) {
 770              $sb = "";
 771              $having->appendPsTo($sb, $params);
 772              $havingString = $sb;
 773          }
 774  
 775           if (!empty($orderBy)) {
 776  
 777              foreach($orderBy as $orderByColumn) {
 778                  
 779                  // Add function expression as-is.

 780                  
 781                  if (strpos($orderByColumn, '(') !== false) {
 782                      $orderByClause[] = $orderByColumn;
 783                      continue;
 784                  }
 785                  
 786                  // Split orderByColumn (i.e. "table.column DESC")

 787  
 788                  $dotPos = strpos($orderByColumn, '.');
 789  
 790                  if ($dotPos !== false) {
 791                      $tableName = substr($orderByColumn, 0, $dotPos);
 792                      $columnName = substr($orderByColumn, $dotPos+1);
 793                  }
 794                  else {
 795                      $tableName = '';
 796                      $columnName = $orderByColumn;
 797                  }
 798  
 799                  $spacePos = strpos($columnName, ' ');
 800  
 801                  if ($spacePos !== false) {
 802                      $direction = substr($columnName, $spacePos);
 803                      $columnName = substr($columnName, 0, $spacePos);
 804                  }
 805                  else {
 806                      $direction = '';
 807                  }
 808  
 809                  $tableAlias = $tableName;
 810                  if ($aliasTableName = $criteria->getTableForAlias($tableName)) {
 811                      $tableName = $aliasTableName;
 812                  }
 813  
 814                  $columnAlias = $columnName;
 815                  if ($asColumnName = $criteria->getColumnForAs($columnName)) {
 816                      $columnName = $asColumnName;
 817                  }
 818  
 819                  $column = $tableName ? $dbMap->getTable($tableName)->getColumn($columnName) : null;
 820  
 821                  if ($column && $column->getType() == 'string') {
 822                      $orderByClause[] = $db->ignoreCaseInOrderBy("$tableAlias.$columnAlias") . $direction;
 823                      $selectClause[] = $db->ignoreCaseInOrderBy("$tableAlias.$columnAlias");
 824                  }
 825                  else {
 826                      $orderByClause[] = $orderByColumn;
 827                  }
 828              }
 829          }
 830  
 831          // Build the SQL from the arrays we compiled

 832          $sql =  "SELECT "
 833                  .($selectModifiers ? implode(" ", $selectModifiers) . " " : "")
 834                  .implode(", ", $selectClause)
 835                  ." FROM ". ( (!empty($joinClause) && count($fromClause) > 1 && (substr(get_class($db), 0, 7) == 'DBMySQL')) ? "(" . implode(", ", $fromClause) . ")" : implode(", ", $fromClause) ) 
 836                                  .($joinClause ? ' ' . implode(' ', $joinClause) : '')
 837                  .($whereClause ? " WHERE ".implode(" AND ", $whereClause) : "")
 838                  .($groupByClause ? " GROUP BY ".implode(",", $groupByClause) : "")
 839                  .($havingString ? " HAVING ".$havingString : "")
 840                  .($orderByClause ? " ORDER BY ".implode(",", $orderByClause) : "");
 841  
 842          Propel::log($sql . ' [LIMIT: ' . $criteria->getLimit() . ', OFFSET: ' . $criteria->getOffset() . ']', Propel::LOG_DEBUG);
 843  
 844          return $sql;
 845  
 846      }
 847  
 848      /**

 849       * Builds a params array, like the kind populated by Criterion::appendPsTo().

 850       * This is useful for building an array even when it is not using the appendPsTo() method.

 851       * @param array $columns

 852       * @param Criteria $values

 853       * @return array params array('column' => ..., 'table' => ..., 'value' => ...)

 854       */
 855  	private static function buildParams($columns, Criteria $values) {
 856          $params = array();
 857          foreach($columns as $key) {
 858              if ($values->containsKey($key)) {
 859                  $crit = $values->getCriterion($key);
 860                  $params[] = array('column' => $crit->getColumn(), 'table' => $crit->getTable(), 'value' => $crit->getValue());
 861              }
 862          }
 863          return $params;
 864      }
 865  
 866      /**

 867       * Populates values in a prepared statement.

 868       *

 869       * @param PreparedStatement $stmt

 870       * @param array $params array('column' => ..., 'table' => ..., 'value' => ...)

 871       * @param DatabaseMap $dbMap

 872       * @return int The number of params replaced.

 873       */
 874  	private static function populateStmtValues($stmt, $params, DatabaseMap $dbMap)
 875      {
 876          $i = 1;
 877          foreach($params as $param) {
 878              $tableName = $param['table'];
 879              $columnName = $param['column'];
 880              $value = $param['value'];
 881  
 882              if ($value === null) {
 883                  $stmt->setNull($i++);
 884              } else {
 885                  $cMap = $dbMap->getTable($tableName)->getColumn($columnName);
 886                  $setter = 'set' . CreoleTypes::getAffix($cMap->getCreoleType());
 887                  $stmt->$setter($i++, $value);
 888              }
 889          } // foreach

 890      }
 891  
 892      /**

 893      * This function searches for the given validator $name under propel/validator/$name.php,

 894      * imports and caches it.

 895      *

 896      * @param string $classname The dot-path name of class (e.g. myapp.propel.MyValidator)

 897      * @return Validator object or null if not able to instantiate validator class (and error will be logged in this case)

 898      */
 899  	public static function getValidator($classname)
 900      {
 901          try {
 902              $v = isset(self::$validatorMap[$classname]) ? self::$validatorMap[$classname] : null;
 903              if ($v === null) {
 904                  $cls = Propel::import($classname);
 905                  $v = new $cls();
 906                  self::$validatorMap[$classname] = $v;
 907              }
 908              return $v;
 909          } catch (Exception $e) {
 910              Propel::log("BasePeer::getValidator(): failed trying to instantiate " . $classname . ": ".$e->getMessage(), Propel::LOG_ERR);
 911          }
 912      }
 913  
 914      /**

 915       * This method returns the MapBuilder specified in the name

 916       * parameter.  You should pass in the full dot-path path to the class, ie:

 917       * myapp.propel.MyMapMapBuilder.  The MapBuilder instances are cached in

 918       * this class for speed.

 919       *

 920       * @param string $classname The dot-path name of class (e.g. myapp.propel.MyMapBuilder)

 921       * @return MapBuilder or null (and logs the error) if the MapBuilder was not found.

 922       * @todo -cBasePeer Consider adding app-level caching support for map builders.

 923       */
 924  	public static function getMapBuilder($classname)
 925      {
 926          try {
 927              $mb = isset(self::$mapBuilders[$classname]) ? self::$mapBuilders[$classname] : null;
 928              if ($mb === null) {
 929                  $cls = Propel::import($classname);
 930                  $mb = new $cls();
 931                  self::$mapBuilders[$classname] = $mb;
 932              }
 933              if (!$mb->isBuilt()) {
 934                  $mb->doBuild();
 935              }
 936              return $mb;
 937          } catch (Exception $e) {
 938              // Have to catch possible exceptions because method is

 939              // used in initialization of Peers.  Log the exception and

 940              // return null.

 941              Propel::log("BasePeer::getMapBuilder() failed trying to instantiate " . $classname . ": " . $e->getMessage(), Propel::LOG_ERR);
 942          }
 943      }
 944  
 945  }


Généré le : Fri Mar 16 22:42:14 2007 par Balluche grâce à PHPXref 0.7