adding zend project folders into old campcaster.

This commit is contained in:
naomiaro 2010-12-07 14:19:27 -05:00
parent 56abfaf28e
commit 7ef0c18b26
4045 changed files with 1054952 additions and 0 deletions

View file

@ -0,0 +1,916 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* Propel's main resource pool and initialization & configuration class.
*
* This static class is used to handle Propel initialization and to maintain all of the
* open database connections and instantiated database maps.
*
* @author Hans Lellelid <hans@xmpl.rg> (Propel)
* @author Daniel Rall <dlr@finemaltcoding.com> (Torque)
* @author Magnús Þór Torfason <magnus@handtolvur.is> (Torque)
* @author Jason van Zyl <jvanzyl@apache.org> (Torque)
* @author Rafal Krzewski <Rafal.Krzewski@e-point.pl> (Torque)
* @author Martin Poeschl <mpoeschl@marmot.at> (Torque)
* @author Henning P. Schmiedehausen <hps@intermeta.de> (Torque)
* @author Kurt Schrader <kschrader@karmalab.org> (Torque)
* @version $Revision: 1811 $
* @package propel.runtime
*/
class Propel
{
/**
* The Propel version.
*/
const VERSION = '1.5.2';
/**
* A constant for <code>default</code>.
*/
const DEFAULT_NAME = "default";
/**
* A constant defining 'System is unusuable' logging level
*/
const LOG_EMERG = 0;
/**
* A constant defining 'Immediate action required' logging level
*/
const LOG_ALERT = 1;
/**
* A constant defining 'Critical conditions' logging level
*/
const LOG_CRIT = 2;
/**
* A constant defining 'Error conditions' logging level
*/
const LOG_ERR = 3;
/**
* A constant defining 'Warning conditions' logging level
*/
const LOG_WARNING = 4;
/**
* A constant defining 'Normal but significant' logging level
*/
const LOG_NOTICE = 5;
/**
* A constant defining 'Informational' logging level
*/
const LOG_INFO = 6;
/**
* A constant defining 'Debug-level messages' logging level
*/
const LOG_DEBUG = 7;
/**
* The class name for a PDO object.
*/
const CLASS_PDO = 'PDO';
/**
* The class name for a PropelPDO object.
*/
const CLASS_PROPEL_PDO = 'PropelPDO';
/**
* The class name for a DebugPDO object.
*/
const CLASS_DEBUG_PDO = 'DebugPDO';
/**
* Constant used to request a READ connection (applies to replication).
*/
const CONNECTION_READ = 'read';
/**
* Constant used to request a WRITE connection (applies to replication).
*/
const CONNECTION_WRITE = 'write';
/**
* @var string The db name that is specified as the default in the property file
*/
private static $defaultDBName;
/**
* @var array The global cache of database maps
*/
private static $dbMaps = array();
/**
* @var array The cache of DB adapter keys
*/
private static $adapterMap = array();
/**
* @var array Cache of established connections (to eliminate overhead).
*/
private static $connectionMap = array();
/**
* @var PropelConfiguration Propel-specific configuration.
*/
private static $configuration;
/**
* @var bool flag to set to true once this class has been initialized
*/
private static $isInit = false;
/**
* @var Log optional logger
*/
private static $logger = null;
/**
* @var string The name of the database mapper class
*/
private static $databaseMapClass = 'DatabaseMap';
/**
* @var bool Whether the object instance pooling is enabled
*/
private static $instancePoolingEnabled = true;
/**
* @var bool For replication, whether to force the use of master connection.
*/
private static $forceMasterConnection = false;
/**
* @var string Base directory to use for autoloading. Initialized in self::initBaseDir()
*/
protected static $baseDir;
/**
* @var array A map of class names and their file paths for autoloading
*/
protected static $autoloadMap = array(
'DBAdapter' => 'adapter/DBAdapter.php',
'DBMSSQL' => 'adapter/DBMSSQL.php',
'MssqlPropelPDO' => 'adapter/MSSQL/MssqlPropelPDO.php',
'MssqlDebugPDO' => 'adapter/MSSQL/MssqlDebugPDO.php',
'MssqlDateTime' => 'adapter/MSSQL/MssqlDateTime.class.php',
'DBMySQL' => 'adapter/DBMySQL.php',
'DBMySQLi' => 'adapter/DBMySQLi.php',
'DBNone' => 'adapter/DBNone.php',
'DBOracle' => 'adapter/DBOracle.php',
'DBPostgres' => 'adapter/DBPostgres.php',
'DBSQLite' => 'adapter/DBSQLite.php',
'DBSybase' => 'adapter/DBSybase.php',
'PropelArrayCollection' => 'collection/PropelArrayCollection.php',
'PropelCollection' => 'collection/PropelCollection.php',
'PropelObjectCollection' => 'collection/PropelObjectCollection.php',
'PropelOnDemandCollection' => 'collection/PropelOnDemandCollection.php',
'PropelOnDemandIterator' => 'collection/PropelOnDemandIterator.php',
'PropelConfiguration' => 'config/PropelConfiguration.php',
'PropelConfigurationIterator' => 'config/PropelConfigurationIterator.php',
'PropelPDO' => 'connection/PropelPDO.php',
'DebugPDO' => 'connection/DebugPDO.php',
'DebugPDOStatement' => 'connection/DebugPDOStatement.php',
'PropelException' => 'exception/PropelException.php',
'ModelWith' => 'formatter/ModelWith.php',
'PropelArrayFormatter' => 'formatter/PropelArrayFormatter.php',
'PropelFormatter' => 'formatter/PropelFormatter.php',
'PropelObjectFormatter' => 'formatter/PropelObjectFormatter.php',
'PropelOnDemandFormatter' => 'formatter/PropelOnDemandFormatter.php',
'PropelStatementFormatter' => 'formatter/PropelStatementFormatter.php',
'BasicLogger' => 'logger/BasicLogger.php',
'MojaviLogAdapter' => 'logger/MojaviLogAdapter.php',
'ColumnMap' => 'map/ColumnMap.php',
'DatabaseMap' => 'map/DatabaseMap.php',
'TableMap' => 'map/TableMap.php',
'RelationMap' => 'map/RelationMap.php',
'ValidatorMap' => 'map/ValidatorMap.php',
'BaseObject' => 'om/BaseObject.php',
'NodeObject' => 'om/NodeObject.php',
'Persistent' => 'om/Persistent.php',
'PreOrderNodeIterator' => 'om/PreOrderNodeIterator.php',
'NestedSetPreOrderNodeIterator' => 'om/NestedSetPreOrderNodeIterator.php',
'NestedSetRecursiveIterator' => 'om/NestedSetRecursiveIterator.php',
'Criteria' => 'query/Criteria.php',
'Criterion' => 'query/Criterion.php',
'CriterionIterator' => 'query/CriterionIterator.php',
'Join' => 'query/Join.php',
'ModelCriteria' => 'query/ModelCriteria.php',
'ModelCriterion' => 'query/ModelCriterion.php',
'ModelJoin' => 'query/ModelJoin.php',
'PropelQuery' => 'query/PropelQuery.php',
'BasePeer' => 'util/BasePeer.php',
'NodePeer' => 'util/NodePeer.php',
'PeerInfo' => 'util/PeerInfo.php',
'PropelAutoloader' => 'util/PropelAutoloader.php',
'PropelColumnTypes' => 'util/PropelColumnTypes.php',
'PropelConditionalProxy' => 'util/PropelConditionalProxy.php',
'PropelModelPager' => 'util/PropelModelPager.php',
'PropelPager' => 'util/PropelPager.php',
'PropelDateTime' => 'util/PropelDateTime.php',
'BasicValidator' => 'validator/BasicValidator.php',
'MatchValidator' => 'validator/MatchValidator.php',
'MaxLengthValidator' => 'validator/MaxLengthValidator.php',
'MaxValueValidator' => 'validator/MaxValueValidator.php',
'MinLengthValidator' => 'validator/MinLengthValidator.php',
'MinValueValidator' => 'validator/MinValueValidator.php',
'NotMatchValidator' => 'validator/NotMatchValidator.php',
'RequiredValidator' => 'validator/RequiredValidator.php',
'UniqueValidator' => 'validator/UniqueValidator.php',
'ValidValuesValidator' => 'validator/ValidValuesValidator.php',
'ValidationFailed' => 'validator/ValidationFailed.php',
);
/**
* Initializes Propel
*
* @throws PropelException Any exceptions caught during processing will be
* rethrown wrapped into a PropelException.
*/
public static function initialize()
{
if (self::$configuration === null) {
throw new PropelException("Propel cannot be initialized without a valid configuration. Please check the log files for further details.");
}
self::configureLogging();
// reset the connection map (this should enable runtime changes of connection params)
self::$connectionMap = array();
if (isset(self::$configuration['classmap']) && is_array(self::$configuration['classmap'])) {
PropelAutoloader::getInstance()->addClassPaths(self::$configuration['classmap']);
PropelAutoloader::getInstance()->register();
}
self::$isInit = true;
}
/**
* Configure Propel a PHP (array) config file.
*
* @param string Path (absolute or relative to include_path) to config file.
*
* @throws PropelException If configuration file cannot be opened.
* (E_WARNING probably will also be raised by PHP)
*/
public static function configure($configFile)
{
$configuration = include($configFile);
if ($configuration === false) {
throw new PropelException("Unable to open configuration file: " . var_export($configFile, true));
}
self::setConfiguration($configuration);
}
/**
* Configure the logging system, if config is specified in the runtime configuration.
*/
protected static function configureLogging()
{
if (self::$logger === null) {
if (isset(self::$configuration['log']) && is_array(self::$configuration['log']) && count(self::$configuration['log'])) {
include_once 'Log.php'; // PEAR Log class
$c = self::$configuration['log'];
$type = isset($c['type']) ? $c['type'] : 'file';
$name = isset($c['name']) ? $c['name'] : './propel.log';
$ident = isset($c['ident']) ? $c['ident'] : 'propel';
$conf = isset($c['conf']) ? $c['conf'] : array();
$level = isset($c['level']) ? $c['level'] : PEAR_LOG_DEBUG;
self::$logger = Log::singleton($type, $name, $ident, $conf, $level);
} // if isset()
}
}
/**
* Initialization of Propel a PHP (array) configuration file.
*
* @param string $c The Propel configuration file path.
*
* @throws PropelException Any exceptions caught during processing will be
* rethrown wrapped into a PropelException.
*/
public static function init($c)
{
self::configure($c);
self::initialize();
}
/**
* Determine whether Propel has already been initialized.
*
* @return bool True if Propel is already initialized.
*/
public static function isInit()
{
return self::$isInit;
}
/**
* Sets the configuration for Propel and all dependencies.
*
* @param mixed The Configuration (array or PropelConfiguration)
*/
public static function setConfiguration($c)
{
if (is_array($c)) {
if (isset($c['propel']) && is_array($c['propel'])) {
$c = $c['propel'];
}
$c = new PropelConfiguration($c);
}
self::$configuration = $c;
}
/**
* Get the configuration for this component.
*
* @param int - PropelConfiguration::TYPE_ARRAY: return the configuration as an array
* (for backward compatibility this is the default)
* - PropelConfiguration::TYPE_ARRAY_FLAT: return the configuration as a flat array
* ($config['name.space.item'])
* - PropelConfiguration::TYPE_OBJECT: return the configuration as a PropelConfiguration instance
* @return mixed The Configuration (array or PropelConfiguration)
*/
public static function getConfiguration($type = PropelConfiguration::TYPE_ARRAY)
{
return self::$configuration->getParameters($type);
}
/**
* Override the configured logger.
*
* This is primarily for things like unit tests / debugging where
* you want to change the logger without altering the configuration file.
*
* You can use any logger class that implements the propel.logger.BasicLogger
* interface. This interface is based on PEAR::Log, so you can also simply pass
* a PEAR::Log object to this method.
*
* @param object The new logger to use. ([PEAR] Log or BasicLogger)
*/
public static function setLogger($logger)
{
self::$logger = $logger;
}
/**
* Returns true if a logger, for example PEAR::Log, has been configured,
* otherwise false.
*
* @return bool True if Propel uses logging
*/
public static function hasLogger()
{
return (self::$logger !== null);
}
/**
* Get the configured logger.
*
* @return object Configured log class ([PEAR] Log or BasicLogger).
*/
public static function logger()
{
return self::$logger;
}
/**
* Logs a message
* If a logger has been configured, the logger will be used, otherwrise the
* logging message will be discarded without any further action
*
* @param string The message that will be logged.
* @param string The logging level.
*
* @return bool True if the message was logged successfully or no logger was used.
*/
public static function log($message, $level = self::LOG_DEBUG)
{
if (self::hasLogger()) {
$logger = self::logger();
switch ($level) {
case self::LOG_EMERG:
return $logger->log($message, $level);
case self::LOG_ALERT:
return $logger->alert($message);
case self::LOG_CRIT:
return $logger->crit($message);
case self::LOG_ERR:
return $logger->err($message);
case self::LOG_WARNING:
return $logger->warning($message);
case self::LOG_NOTICE:
return $logger->notice($message);
case self::LOG_INFO:
return $logger->info($message);
default:
return $logger->debug($message);
}
}
return true;
}
/**
* Returns the database map information. Name relates to the name
* of the connection pool to associate with the map.
*
* The database maps are "registered" by the generated map builder classes.
*
* @param string The name of the database corresponding to the DatabaseMap to retrieve.
*
* @return DatabaseMap The named <code>DatabaseMap</code>.
*
* @throws PropelException - if database map is null or propel was not initialized properly.
*/
public static function getDatabaseMap($name = null)
{
if ($name === null) {
$name = self::getDefaultDB();
if ($name === null) {
throw new PropelException("DatabaseMap name is null!");
}
}
if (!isset(self::$dbMaps[$name])) {
$clazz = self::$databaseMapClass;
self::$dbMaps[$name] = new $clazz($name);
}
return self::$dbMaps[$name];
}
/**
* Sets the database map object to use for specified datasource.
*
* @param string $name The datasource name.
* @param DatabaseMap $map The database map object to use for specified datasource.
*/
public static function setDatabaseMap($name, DatabaseMap $map)
{
if ($name === null) {
$name = self::getDefaultDB();
}
self::$dbMaps[$name] = $map;
}
/**
* For replication, set whether to always force the use of a master connection.
*
* @param boolean $bit True or False
*/
public static function setForceMasterConnection($bit)
{
self::$forceMasterConnection = (bool) $bit;
}
/**
* For replication, whether to always force the use of a master connection.
*
* @return boolean
*/
public static function getForceMasterConnection()
{
return self::$forceMasterConnection;
}
/**
* Sets a Connection for specified datasource name.
*
* @param string $name The datasource name for the connection being set.
* @param PropelPDO $con The PDO connection.
* @param string $mode Whether this is a READ or WRITE connection (Propel::CONNECTION_READ, Propel::CONNECTION_WRITE)
*/
public static function setConnection($name, PropelPDO $con, $mode = Propel::CONNECTION_WRITE)
{
if ($name === null) {
$name = self::getDefaultDB();
}
if ($mode == Propel::CONNECTION_READ) {
self::$connectionMap[$name]['slave'] = $con;
} else {
self::$connectionMap[$name]['master'] = $con;
}
}
/**
* Gets an already-opened PDO connection or opens a new one for passed-in db name.
*
* @param string $name The datasource name that is used to look up the DSN from the runtime configuation file.
* @param string $mode The connection mode (this applies to replication systems).
*
* @return PDO A database connection
*
* @throws PropelException - if connection cannot be configured or initialized.
*/
public static function getConnection($name = null, $mode = Propel::CONNECTION_WRITE)
{
if ($name === null) {
$name = self::getDefaultDB();
}
// IF a WRITE-mode connection was requested
// or Propel is configured to always use the master connection
// THEN return the master connection.
if ($mode != Propel::CONNECTION_READ || self::$forceMasterConnection) {
return self::getMasterConnection($name);
} else {
return self::getSlaveConnection($name);
}
}
/**
* Gets an already-opened write PDO connection or opens a new one for passed-in db name.
*
* @param string $name The datasource name that is used to look up the DSN
* from the runtime configuation file. Empty name not allowed.
*
* @return PDO A database connection
*
* @throws PropelException - if connection cannot be configured or initialized.
*/
public static function getMasterConnection($name)
{
if (!isset(self::$connectionMap[$name]['master'])) {
// load connection parameter for master connection
$conparams = isset(self::$configuration['datasources'][$name]['connection']) ? self::$configuration['datasources'][$name]['connection'] : null;
if (empty($conparams)) {
throw new PropelException('No connection information in your runtime configuration file for datasource ['.$name.']');
}
// initialize master connection
$con = Propel::initConnection($conparams, $name);
self::$connectionMap[$name]['master'] = $con;
}
return self::$connectionMap[$name]['master'];
}
/**
* Gets an already-opened read PDO connection or opens a new one for passed-in db name.
*
* @param string $name The datasource name that is used to look up the DSN
* from the runtime configuation file. Empty name not allowed.
*
* @return PDO A database connection
*
* @throws PropelException - if connection cannot be configured or initialized.
*/
public static function getSlaveConnection($name)
{
if (!isset(self::$connectionMap[$name]['slave'])) {
$slaveconfigs = isset(self::$configuration['datasources'][$name]['slaves']) ? self::$configuration['datasources'][$name]['slaves'] : null;
if (empty($slaveconfigs)) {
// no slaves configured for this datasource
// fallback to the master connection
self::$connectionMap[$name]['slave'] = self::getMasterConnection($name);
} else {
// Initialize a new slave
if (isset($slaveconfigs['connection']['dsn'])) {
// only one slave connection configured
$conparams = $slaveconfigs['connection'];
} else {
// more than one sleve connection configured
// pickup a random one
$randkey = array_rand($slaveconfigs['connection']);
$conparams = $slaveconfigs['connection'][$randkey];
if (empty($conparams)) {
throw new PropelException('No connection information in your runtime configuration file for SLAVE ['.$randkey.'] to datasource ['.$name.']');
}
}
// initialize slave connection
$con = Propel::initConnection($conparams, $name);
self::$connectionMap[$name]['slave'] = $con;
}
} // if datasource slave not set
return self::$connectionMap[$name]['slave'];
}
/**
* Opens a new PDO connection for passed-in db name.
*
* @param array $conparams Connection paramters.
* @param string $name Datasource name.
* @param string $defaultClass The PDO subclass to instantiate if there is no explicit classname
* specified in the connection params (default is Propel::CLASS_PROPEL_PDO)
*
* @return PDO A database connection of the given class (PDO, PropelPDO, SlavePDO or user-defined)
*
* @throws PropelException - if lower-level exception caught when trying to connect.
*/
public static function initConnection($conparams, $name, $defaultClass = Propel::CLASS_PROPEL_PDO)
{
$dsn = $conparams['dsn'];
if ($dsn === null) {
throw new PropelException('No dsn specified in your connection parameters for datasource ['.$name.']');
}
if (isset($conparams['classname']) && !empty($conparams['classname'])) {
$classname = $conparams['classname'];
if (!class_exists($classname)) {
throw new PropelException('Unable to load specified PDO subclass: ' . $classname);
}
} else {
$classname = $defaultClass;
}
$user = isset($conparams['user']) ? $conparams['user'] : null;
$password = isset($conparams['password']) ? $conparams['password'] : null;
// load any driver options from the config file
// driver options are those PDO settings that have to be passed during the connection construction
$driver_options = array();
if ( isset($conparams['options']) && is_array($conparams['options']) ) {
try {
self::processDriverOptions( $conparams['options'], $driver_options );
} catch (PropelException $e) {
throw new PropelException('Error processing driver options for datasource ['.$name.']', $e);
}
}
try {
$con = new $classname($dsn, $user, $password, $driver_options);
$con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
if (Propel::getConfiguration(PropelConfiguration::TYPE_OBJECT)->getParameter('debugpdo.logging.enabled', false)) {
$con->useLogging(true);
}
} catch (PDOException $e) {
throw new PropelException("Unable to open PDO connection", $e);
}
// load any connection options from the config file
// connection attributes are those PDO flags that have to be set on the initialized connection
if (isset($conparams['attributes']) && is_array($conparams['attributes'])) {
$attributes = array();
try {
self::processDriverOptions( $conparams['attributes'], $attributes );
} catch (PropelException $e) {
throw new PropelException('Error processing connection attributes for datasource ['.$name.']', $e);
}
foreach ($attributes as $key => $value) {
$con->setAttribute($key, $value);
}
}
// initialize the connection using the settings provided in the config file. this could be a "SET NAMES <charset>" query for MySQL, for instance
$adapter = self::getDB($name);
$adapter->initConnection($con, isset($conparams['settings']) && is_array($conparams['settings']) ? $conparams['settings'] : array());
return $con;
}
/**
* Internal function to handle driver options or conneciton attributes in PDO.
*
* Process the INI file flags to be passed to each connection.
*
* @param array Where to find the list of constant flags and their new setting.
* @param array Put the data into here
*
* @throws PropelException If invalid options were specified.
*/
private static function processDriverOptions($source, &$write_to)
{
foreach ($source as $option => $optiondata) {
if (is_string($option) && strpos($option, '::') !== false) {
$key = $option;
} elseif (is_string($option)) {
$key = 'PropelPDO::' . $option;
}
if (!defined($key)) {
throw new PropelException("Invalid PDO option/attribute name specified: ".$key);
}
$key = constant($key);
$value = $optiondata['value'];
if (is_string($value) && strpos($value, '::') !== false) {
if (!defined($value)) {
throw new PropelException("Invalid PDO option/attribute value specified: ".$value);
}
$value = constant($value);
}
$write_to[$key] = $value;
}
}
/**
* Returns database adapter for a specific datasource.
*
* @param string The datasource name.
*
* @return DBAdapter The corresponding database adapter.
*
* @throws PropelException If unable to find DBdapter for specified db.
*/
public static function getDB($name = null)
{
if ($name === null) {
$name = self::getDefaultDB();
}
if (!isset(self::$adapterMap[$name])) {
if (!isset(self::$configuration['datasources'][$name]['adapter'])) {
throw new PropelException("Unable to find adapter for datasource [" . $name . "].");
}
$db = DBAdapter::factory(self::$configuration['datasources'][$name]['adapter']);
// register the adapter for this name
self::$adapterMap[$name] = $db;
}
return self::$adapterMap[$name];
}
/**
* Sets a database adapter for specified datasource.
*
* @param string $name The datasource name.
* @param DBAdapter $adapter The DBAdapter implementation to use.
*/
public static function setDB($name, DBAdapter $adapter)
{
if ($name === null) {
$name = self::getDefaultDB();
}
self::$adapterMap[$name] = $adapter;
}
/**
* Returns the name of the default database.
*
* @return string Name of the default DB
*/
public static function getDefaultDB()
{
if (self::$defaultDBName === null) {
// Determine default database name.
self::$defaultDBName = isset(self::$configuration['datasources']['default']) ? self::$configuration['datasources']['default'] : self::DEFAULT_NAME;
}
return self::$defaultDBName;
}
/**
* Closes any associated resource handles.
*
* This method frees any database connection handles that have been
* opened by the getConnection() method.
*/
public static function close()
{
foreach (self::$connectionMap as $idx => $cons) {
// Propel::log("Closing connections for " . $idx, Propel::LOG_DEBUG);
unset(self::$connectionMap[$idx]);
}
}
/**
* Autoload function for loading propel dependencies.
*
* @param string The class name needing loading.
*
* @return boolean TRUE if the class was loaded, false otherwise.
*/
public static function autoload($className)
{
if (isset(self::$autoloadMap[$className])) {
require self::$baseDir . self::$autoloadMap[$className];
return true;
}
return false;
}
/**
* Initialize the base directory for the autoloader.
* Avoids a call to dirname(__FILE__) each time self::autoload() is called.
* FIXME put in the constructor if the Propel class ever becomes a singleton
*/
public static function initBaseDir()
{
self::$baseDir = dirname(__FILE__) . '/';
}
/**
* Include once a file specified in DOT notation and return unqualified classname.
*
* Typically, Propel uses autoload is used to load classes and expects that all classes
* referenced within Propel are included in Propel's autoload map. This method is only
* called when a specific non-Propel classname was specified -- for example, the
* classname of a validator in the schema.xml. This method will attempt to include that
* class via autoload and then relative to a location on the include_path.
*
* @param string $class dot-path to clas (e.g. path.to.my.ClassName).
* @return string unqualified classname
*/
public static function importClass($path) {
// extract classname
if (($pos = strrpos($path, '.')) === false) {
$class = $path;
} else {
$class = substr($path, $pos + 1);
}
// check if class exists, using autoloader to attempt to load it.
if (class_exists($class, $useAutoload=true)) {
return $class;
}
// turn to filesystem path
$path = strtr($path, '.', DIRECTORY_SEPARATOR) . '.php';
// include class
$ret = include_once($path);
if ($ret === false) {
throw new PropelException("Unable to import class: " . $class . " from " . $path);
}
// return qualified name
return $class;
}
/**
* Set your own class-name for Database-Mapping. Then
* you can change the whole TableMap-Model, but keep its
* functionality for Criteria.
*
* @param string The name of the class.
*/
public static function setDatabaseMapClass($name)
{
self::$databaseMapClass = $name;
}
/**
* Disable instance pooling.
*
* @return boolean true if the method changed the instance pooling state,
* false if it was already disabled
*/
public static function disableInstancePooling()
{
if (!self::$instancePoolingEnabled) {
return false;
}
self::$instancePoolingEnabled = false;
return true;
}
/**
* Enable instance pooling (enabled by default).
*
* @return boolean true if the method changed the instance pooling state,
* false if it was already enabled
*/
public static function enableInstancePooling()
{
if (self::$instancePoolingEnabled) {
return false;
}
self::$instancePoolingEnabled = true;
return true;
}
/**
* the instance pooling behaviour. True by default.
*
* @return boolean Whether the pooling is enabled or not.
*/
public static function isInstancePoolingEnabled()
{
return self::$instancePoolingEnabled;
}
}
// Since the Propel class is not a true singleton, this code cannot go into the __construct()
Propel::initBaseDir();
spl_autoload_register(array('Propel', 'autoload'));

View file

@ -0,0 +1,297 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* DBAdapter</code> defines the interface for a Propel database adapter.
*
* <p>Support for new databases is added by subclassing
* <code>DBAdapter</code> and implementing its abstract interface, and by
* registering the new database adapter and corresponding Propel
* driver in the private adapters map (array) in this class.</p>
*
* <p>The Propel database adapters exist to present a uniform
* interface to database access across all available databases. Once
* the necessary adapters have been written and configured,
* transparent swapping of databases is theoretically supported with
* <i>zero code change</i> and minimal configuration file
* modifications.</p>
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Jon S. Stevens <jon@latchkey.com> (Torque)
* @author Brett McLaughlin <bmclaugh@algx.net> (Torque)
* @author Daniel Rall <dlr@finemaltcoding.com> (Torque)
* @version $Revision: 1612 $
* @package propel.runtime.adapter
*/
abstract class DBAdapter
{
const ID_METHOD_NONE = 0;
const ID_METHOD_AUTOINCREMENT = 1;
const ID_METHOD_SEQUENCE = 2;
/**
* Propel driver to Propel adapter map.
* @var array
*/
private static $adapters = array(
'mysql' => 'DBMySQL',
'mysqli' => 'DBMySQLi',
'mssql' => 'DBMSSQL',
'dblib' => 'DBMSSQL',
'sybase' => 'DBSybase',
'oracle' => 'DBOracle',
'oci' => 'DBOracle',
'pgsql' => 'DBPostgres',
'sqlite' => 'DBSQLite',
'' => 'DBNone',
);
/**
* Creates a new instance of the database adapter associated
* with the specified Propel driver.
*
* @param string $driver The name of the Propel driver to
* create a new adapter instance for or a shorter form adapter key.
* @return DBAdapter An instance of a Propel database adapter.
* @throws PropelException if the adapter could not be instantiated.
*/
public static function factory($driver) {
$adapterClass = isset(self::$adapters[$driver]) ? self::$adapters[$driver] : null;
if ($adapterClass !== null) {
$a = new $adapterClass();
return $a;
} else {
throw new PropelException("Unsupported Propel driver: " . $driver . ": Check your configuration file");
}
}
/**
* This method is called after a connection was created to run necessary
* post-initialization queries or code.
*
* If a charset was specified, this will be set before any other queries
* are executed.
*
* This base method runs queries specified using the "query" setting.
*
* @param PDO A PDO connection instance.
* @param array An array of settings.
* @see setCharset()
*/
public function initConnection(PDO $con, array $settings)
{
if (isset($settings['charset']['value'])) {
$this->setCharset($con, $settings['charset']['value']);
}
if (isset($settings['queries']) && is_array($settings['queries'])) {
foreach ($settings['queries'] as $queries) {
foreach ((array)$queries as $query) {
$con->exec($query);
}
}
}
}
/**
* Sets the character encoding using SQL standard SET NAMES statement.
*
* This method is invoked from the default initConnection() method and must
* be overridden for an RDMBS which does _not_ support this SQL standard.
*
* @param PDO A PDO connection instance.
* @param string The charset encoding.
* @see initConnection()
*/
public function setCharset(PDO $con, $charset)
{
$con->exec("SET NAMES '" . $charset . "'");
}
/**
* This method is used to ignore case.
*
* @param string The string to transform to upper case.
* @return string The upper case string.
*/
public abstract function toUpperCase($in);
/**
* Returns the character used to indicate the beginning and end of
* a piece of text used in a SQL statement (generally a single
* quote).
*
* @return string The text delimeter.
*/
public function getStringDelimiter()
{
return '\'';
}
/**
* This method is used to ignore case.
*
* @param string $in The string whose case to ignore.
* @return string The string in a case that can be ignored.
*/
public abstract function ignoreCase($in);
/**
* This method is used to ignore case in an ORDER BY clause.
* Usually it is the same as ignoreCase, but some databases
* (Interbase for example) does not use the same SQL in ORDER BY
* and other clauses.
*
* @param string $in The string whose case to ignore.
* @return string The string in a case that can be ignored.
*/
public function ignoreCaseInOrderBy($in)
{
return $this->ignoreCase($in);
}
/**
* Returns SQL which concatenates the second string to the first.
*
* @param string String to concatenate.
* @param string String to append.
* @return string
*/
public abstract function concatString($s1, $s2);
/**
* Returns SQL which extracts a substring.
*
* @param string String to extract from.
* @param int Offset to start from.
* @param int Number of characters to extract.
* @return string
*/
public abstract function subString($s, $pos, $len);
/**
* Returns SQL which calculates the length (in chars) of a string.
*
* @param string String to calculate length of.
* @return string
*/
public abstract function strLength($s);
/**
* Quotes database objec identifiers (table names, col names, sequences, etc.).
* @param string $text The identifier to quote.
* @return string The quoted identifier.
*/
public function quoteIdentifier($text)
{
return '"' . $text . '"';
}
/**
* Quotes a database table which could have space seperating it from an alias, both should be identified seperately
* @param string $table The table name to quo
* @return string The quoted table name
**/
public function quoteIdentifierTable($table) {
return implode(" ", array_map(array($this, "quoteIdentifier"), explode(" ", $table) ) );
}
/**
* Returns the native ID method for this RDBMS.
* @return int one of DBAdapter:ID_METHOD_SEQUENCE, DBAdapter::ID_METHOD_AUTOINCREMENT.
*/
protected function getIdMethod()
{
return DBAdapter::ID_METHOD_AUTOINCREMENT;
}
/**
* Whether this adapter uses an ID generation system that requires getting ID _before_ performing INSERT.
* @return boolean
*/
public function isGetIdBeforeInsert()
{
return ($this->getIdMethod() === DBAdapter::ID_METHOD_SEQUENCE);
}
/**
* Whether this adapter uses an ID generation system that requires getting ID _before_ performing INSERT.
* @return boolean
*/
public function isGetIdAfterInsert()
{
return ($this->getIdMethod() === DBAdapter::ID_METHOD_AUTOINCREMENT);
}
/**
* Gets the generated ID (either last ID for autoincrement or next sequence ID).
* @return mixed
*/
public function getId(PDO $con, $name = null)
{
return $con->lastInsertId($name);
}
/**
* Returns timestamp formatter string for use in date() function.
* @return string
*/
public function getTimestampFormatter()
{
return "Y-m-d H:i:s";
}
/**
* Returns date formatter string for use in date() function.
* @return string
*/
public function getDateFormatter()
{
return "Y-m-d";
}
/**
* Returns time formatter string for use in date() function.
* @return string
*/
public function getTimeFormatter()
{
return "H:i:s";
}
/**
* Should Column-Names get identifiers for inserts or updates.
* By default false is returned -> backwards compability.
*
* it`s a workaround...!!!
*
* @todo should be abstract
* @return boolean
* @deprecated
*/
public function useQuoteIdentifier()
{
return false;
}
/**
* Modifies the passed-in SQL to add LIMIT and/or OFFSET.
*/
public abstract function applyLimit(&$sql, $offset, $limit);
/**
* Gets the SQL string that this adapter uses for getting a random number.
*
* @param mixed $seed (optional) seed value for databases that support this
*/
public abstract function random($seed = null);
}

View file

@ -0,0 +1,215 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* This is used to connect to a MSSQL database.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @version $Revision: 1700 $
* @package propel.runtime.adapter
*/
class DBMSSQL extends DBAdapter
{
/**
* This method is used to ignore case.
*
* @param in The string to transform to upper case.
* @return The upper case string.
*/
public function toUpperCase($in)
{
return $this->ignoreCase($in);
}
/**
* This method is used to ignore case.
*
* @param in The string whose case to ignore.
* @return The string in a case that can be ignored.
*/
public function ignoreCase($in)
{
return 'UPPER(' . $in . ')';
}
/**
* Returns SQL which concatenates the second string to the first.
*
* @param string String to concatenate.
* @param string String to append.
* @return string
*/
public function concatString($s1, $s2)
{
return '(' . $s1 . ' + ' . $s2 . ')';
}
/**
* Returns SQL which extracts a substring.
*
* @param string String to extract from.
* @param int Offset to start from.
* @param int Number of characters to extract.
* @return string
*/
public function subString($s, $pos, $len)
{
return 'SUBSTRING(' . $s . ', ' . $pos . ', ' . $len . ')';
}
/**
* Returns SQL which calculates the length (in chars) of a string.
*
* @param string String to calculate length of.
* @return string
*/
public function strLength($s)
{
return 'LEN(' . $s . ')';
}
/**
* @see DBAdapter::quoteIdentifier()
*/
public function quoteIdentifier($text)
{
return '[' . $text . ']';
}
/**
* @see DBAdapter::random()
*/
public function random($seed = null)
{
return 'RAND(' . ((int)$seed) . ')';
}
/**
* Simulated Limit/Offset
* This rewrites the $sql query to apply the offset and limit.
* some of the ORDER BY logic borrowed from Doctrine MsSqlPlatform
* @see DBAdapter::applyLimit()
* @author Benjamin Runnels <kraven@kraven.org>
*/
public function applyLimit(&$sql, $offset, $limit)
{
// make sure offset and limit are numeric
if(! is_numeric($offset) || ! is_numeric($limit))
{
throw new PropelException('DBMSSQL::applyLimit() expects a number for argument 2 and 3');
}
//split the select and from clauses out of the original query
$selectSegment = array();
$selectText = 'SELECT ';
if (preg_match('/\Aselect(\s+)distinct/i', $sql)) {
$selectText .= 'DISTINCT ';
}
preg_match('/\Aselect(.*)from(.*)/si', $sql, $selectSegment);
if(count($selectSegment) == 3) {
$selectStatement = trim($selectSegment[1]);
$fromStatement = trim($selectSegment[2]);
} else {
throw new Exception('DBMSSQL::applyLimit() could not locate the select statement at the start of the query.');
}
// if we're starting at offset 0 then theres no need to simulate limit,
// just grab the top $limit number of rows
if($offset == 0) {
$sql = $selectText . 'TOP ' . $limit . ' ' . $selectStatement . ' FROM ' . $fromStatement;
return;
}
//get the ORDER BY clause if present
$orderStatement = stristr($fromStatement, 'ORDER BY');
$orders = '';
if($orderStatement !== false) {
//remove order statement from the from statement
$fromStatement = trim(str_replace($orderStatement, '', $fromStatement));
$order = str_ireplace('ORDER BY', '', $orderStatement);
$orders = explode(',', $order);
for($i = 0; $i < count($orders); $i ++) {
$orderArr[trim(preg_replace('/\s+(ASC|DESC)$/i', '', $orders[$i]))] = array(
'sort' => (stripos($orders[$i], ' DESC') !== false) ? 'DESC' : 'ASC',
'key' => $i
);
}
}
//setup inner and outer select selects
$innerSelect = '';
$outerSelect = '';
foreach(explode(', ', $selectStatement) as $selCol) {
$selColArr = explode(' ', $selCol);
$selColCount = count($selColArr) - 1;
//make sure the current column isn't * or an aggregate
if($selColArr[0] != '*' && ! strstr($selColArr[0], '(')) {
if(isset($orderArr[$selColArr[0]])) {
$orders[$orderArr[$selColArr[0]]['key']] = $selColArr[0] . ' ' . $orderArr[$selColArr[0]]['sort'];
}
//use the alias if one was present otherwise use the column name
$alias = (! stristr($selCol, ' AS ')) ? $this->quoteIdentifier($selColArr[0]) : $this->quoteIdentifier($selColArr[$selColCount]);
//save the first non-aggregate column for use in ROW_NUMBER() if required
if(! isset($firstColumnOrderStatement)) {
$firstColumnOrderStatement = 'ORDER BY ' . $selColArr[0];
}
//add an alias to the inner select so all columns will be unique
$innerSelect .= $selColArr[0] . ' AS ' . $alias . ', ';
$outerSelect .= $alias . ', ';
} else {
//agregate columns must always have an alias clause
if(! stristr($selCol, ' AS ')) {
throw new Exception('DBMSSQL::applyLimit() requires aggregate columns to have an Alias clause');
}
//aggregate column alias can't be used as the count column you must use the entire aggregate statement
if(isset($orderArr[$selColArr[$selColCount]])) {
$orders[$orderArr[$selColArr[$selColCount]]['key']] = str_replace($selColArr[$selColCount - 1] . ' ' . $selColArr[$selColCount], '', $selCol) . $orderArr[$selColArr[$selColCount]]['sort'];
}
//quote the alias
$alias = $this->quoteIdentifier($selColArr[$selColCount]);
$innerSelect .= str_replace($selColArr[$selColCount], $alias, $selCol) . ', ';
$outerSelect .= $alias . ', ';
}
}
if(is_array($orders)) {
$orderStatement = 'ORDER BY ' . implode(', ', $orders);
} else {
//use the first non aggregate column in our select statement if no ORDER BY clause present
if(isset($firstColumnOrderStatement)) {
$orderStatement = $firstColumnOrderStatement;
} else {
throw new Exception('DBMSSQL::applyLimit() unable to find column to use with ROW_NUMBER()');
}
}
//substring the select strings to get rid of the last comma and add our FROM and SELECT clauses
$innerSelect = $selectText . 'ROW_NUMBER() OVER(' . $orderStatement . ') AS RowNumber, ' . substr($innerSelect, 0, - 2) . ' FROM';
//outer select can't use * because of the RowNumber column
$outerSelect = 'SELECT ' . substr($outerSelect, 0, - 2) . ' FROM';
//ROW_NUMBER() starts at 1 not 0
$sql = $outerSelect . ' (' . $innerSelect . ' ' . $fromStatement . ') AS derivedb WHERE RowNumber BETWEEN ' . ($offset + 1) . ' AND ' . ($limit + $offset);
return;
}
}

View file

@ -0,0 +1,145 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* This is used in order to connect to a MySQL database.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Jon S. Stevens <jon@clearink.com> (Torque)
* @author Brett McLaughlin <bmclaugh@algx.net> (Torque)
* @author Daniel Rall <dlr@finemaltcoding.com> (Torque)
* @version $Revision: 1612 $
* @package propel.runtime.adapter
*/
class DBMySQL extends DBAdapter
{
/**
* This method is used to ignore case.
*
* @param in The string to transform to upper case.
* @return The upper case string.
*/
public function toUpperCase($in)
{
return "UPPER(" . $in . ")";
}
/**
* This method is used to ignore case.
*
* @param in The string whose case to ignore.
* @return The string in a case that can be ignored.
*/
public function ignoreCase($in)
{
return "UPPER(" . $in . ")";
}
/**
* Returns SQL which concatenates the second string to the first.
*
* @param string String to concatenate.
* @param string String to append.
* @return string
*/
public function concatString($s1, $s2)
{
return "CONCAT($s1, $s2)";
}
/**
* Returns SQL which extracts a substring.
*
* @param string String to extract from.
* @param int Offset to start from.
* @param int Number of characters to extract.
* @return string
*/
public function subString($s, $pos, $len)
{
return "SUBSTRING($s, $pos, $len)";
}
/**
* Returns SQL which calculates the length (in chars) of a string.
*
* @param string String to calculate length of.
* @return string
*/
public function strLength($s)
{
return "CHAR_LENGTH($s)";
}
/**
* Locks the specified table.
*
* @param Connection $con The Propel connection to use.
* @param string $table The name of the table to lock.
* @throws PDOException No Statement could be created or
* executed.
*/
public function lockTable(PDO $con, $table)
{
$con->exec("LOCK TABLE " . $table . " WRITE");
}
/**
* Unlocks the specified table.
*
* @param PDO $con The PDO connection to use.
* @param string $table The name of the table to unlock.
* @throws PDOException No Statement could be created or
* executed.
*/
public function unlockTable(PDO $con, $table)
{
$statement = $con->exec("UNLOCK TABLES");
}
/**
* @see DBAdapter::quoteIdentifier()
*/
public function quoteIdentifier($text)
{
return '`' . $text . '`';
}
/**
* @see DBAdapter::useQuoteIdentifier()
*/
public function useQuoteIdentifier()
{
return true;
}
/**
* @see DBAdapter::applyLimit()
*/
public function applyLimit(&$sql, $offset, $limit)
{
if ( $limit > 0 ) {
$sql .= " LIMIT " . ($offset > 0 ? $offset . ", " : "") . $limit;
} else if ( $offset > 0 ) {
$sql .= " LIMIT " . $offset . ", 18446744073709551615";
}
}
/**
* @see DBAdapter::random()
*/
public function random($seed = null)
{
return 'rand('.((int) $seed).')';
}
}

View file

@ -0,0 +1,104 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* This adapter is used when you do not have a database installed.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Jon S. Stevens <jon@clearink.com> (Torque)
* @author Brett McLaughlin <bmclaugh@algx.net> (Torque)
* @version $Revision: 1612 $
* @package propel.runtime.adapter
*/
class DBNone extends DBAdapter
{
/**
* @see DBAdapter::initConnection()
*/
public function initConnection(PDO $con, array $settings)
{
}
/**
* This method is used to ignore case.
*
* @param in The string to transform to upper case.
* @return The upper case string.
*/
public function toUpperCase($in)
{
return $in;
}
/**
* This method is used to ignore case.
*
* @param in The string whose case to ignore.
* @return The string in a case that can be ignored.
*/
public function ignoreCase($in)
{
return $in;
}
/**
* Returns SQL which concatenates the second string to the first.
*
* @param string String to concatenate.
* @param string String to append.
* @return string
*/
public function concatString($s1, $s2)
{
return ($s1 . $s2);
}
/**
* Returns SQL which extracts a substring.
*
* @param string String to extract from.
* @param int Offset to start from.
* @param int Number of characters to extract.
* @return string
*/
public function subString($s, $pos, $len)
{
return substr($s, $pos, $len);
}
/**
* Returns SQL which calculates the length (in chars) of a string.
*
* @param string String to calculate length of.
* @return string
*/
public function strLength($s)
{
return strlen($s);
}
/**
* Modifies the passed-in SQL to add LIMIT and/or OFFSET.
*/
public function applyLimit(&$sql, $offset, $limit)
{
}
/**
* Gets the SQL string that this adapter uses for getting a random number.
*
* @param mixed $seed (optional) seed value for databases that support this
*/
public function random($seed = null)
{
}
}

View file

@ -0,0 +1,150 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* Oracle adapter.
*
* @author David Giffin <david@giffin.org> (Propel)
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Jon S. Stevens <jon@clearink.com> (Torque)
* @author Brett McLaughlin <bmclaugh@algx.net> (Torque)
* @author Bill Schneider <bschneider@vecna.com> (Torque)
* @author Daniel Rall <dlr@finemaltcoding.com> (Torque)
* @version $Revision: 1669 $
* @package propel.runtime.adapter
*/
class DBOracle extends DBAdapter
{
/**
* This method is called after a connection was created to run necessary
* post-initialization queries or code.
* Removes the charset query and adds the date queries
*
* @param PDO A PDO connection instance.
* @see parent::initConnection()
*/
public function initConnection(PDO $con, array $settings)
{
$con->exec("ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD'");
$con->exec("ALTER SESSION SET NLS_TIMESTAMP_FORMAT='YYYY-MM-DD HH24:MI:SS'");
if (isset($settings['queries']) && is_array($settings['queries'])) {
foreach ($settings['queries'] as $queries) {
foreach ((array)$queries as $query) {
$con->exec($query);
}
}
}
}
/**
* This method is used to ignore case.
*
* @param string $in The string to transform to upper case.
* @return string The upper case string.
*/
public function toUpperCase($in)
{
return "UPPER(" . $in . ")";
}
/**
* This method is used to ignore case.
*
* @param string $in The string whose case to ignore.
* @return string The string in a case that can be ignored.
*/
public function ignoreCase($in)
{
return "UPPER(" . $in . ")";
}
/**
* Returns SQL which concatenates the second string to the first.
*
* @param string String to concatenate.
* @param string String to append.
* @return string
*/
public function concatString($s1, $s2)
{
return "CONCAT($s1, $s2)";
}
/**
* Returns SQL which extracts a substring.
*
* @param string String to extract from.
* @param int Offset to start from.
* @param int Number of characters to extract.
* @return string
*/
public function subString($s, $pos, $len)
{
return "SUBSTR($s, $pos, $len)";
}
/**
* Returns SQL which calculates the length (in chars) of a string.
*
* @param string String to calculate length of.
* @return string
*/
public function strLength($s)
{
return "LENGTH($s)";
}
/**
* @see DBAdapter::applyLimit()
*/
public function applyLimit(&$sql, $offset, $limit, $criteria = null)
{
if (BasePeer::needsSelectAliases($criteria)) {
$selectSql = BasePeer::createSelectSqlPart($criteria, $params, true);
$sql = $selectSql . substr($sql, strpos('FROM', $sql));
}
$sql = 'SELECT B.* FROM ('
. 'SELECT A.*, rownum AS PROPEL_ROWNUM FROM (' . $sql . ') A '
. ') B WHERE ';
if ( $offset > 0 ) {
$sql .= ' B.PROPEL_ROWNUM > ' . $offset;
if ( $limit > 0 ) {
$sql .= ' AND B.PROPEL_ROWNUM <= ' . ( $offset + $limit );
}
} else {
$sql .= ' B.PROPEL_ROWNUM <= ' . $limit;
}
}
protected function getIdMethod()
{
return DBAdapter::ID_METHOD_SEQUENCE;
}
public function getId(PDO $con, $name = null)
{
if ($name === null) {
throw new PropelException("Unable to fetch next sequence ID without sequence name.");
}
$stmt = $con->query("SELECT " . $name . ".nextval FROM dual");
$row = $stmt->fetch(PDO::FETCH_NUM);
return $row[0];
}
public function random($seed=NULL)
{
return 'dbms_random.value';
}
}

View file

@ -0,0 +1,141 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* This is used to connect to PostgresQL databases.
*
* <a href="http://www.pgsql.org">http://www.pgsql.org</a>
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Hakan Tandogan <hakan42@gmx.de> (Torque)
* @version $Revision: 1612 $
* @package propel.runtime.adapter
*/
class DBPostgres extends DBAdapter
{
/**
* This method is used to ignore case.
*
* @param string $in The string to transform to upper case.
* @return string The upper case string.
*/
public function toUpperCase($in)
{
return "UPPER(" . $in . ")";
}
/**
* This method is used to ignore case.
*
* @param in The string whose case to ignore.
* @return The string in a case that can be ignored.
*/
public function ignoreCase($in)
{
return "UPPER(" . $in . ")";
}
/**
* Returns SQL which concatenates the second string to the first.
*
* @param string String to concatenate.
* @param string String to append.
* @return string
*/
public function concatString($s1, $s2)
{
return "($s1 || $s2)";
}
/**
* Returns SQL which extracts a substring.
*
* @param string String to extract from.
* @param int Offset to start from.
* @param int Number of characters to extract.
* @return string
*/
public function subString($s, $pos, $len)
{
return "substring($s from $pos" . ($len > -1 ? "for $len" : "") . ")";
}
/**
* Returns SQL which calculates the length (in chars) of a string.
*
* @param string String to calculate length of.
* @return string
*/
public function strLength($s)
{
return "char_length($s)";
}
/**
* @see DBAdapter::getIdMethod()
*/
protected function getIdMethod()
{
return DBAdapter::ID_METHOD_SEQUENCE;
}
/**
* Gets ID for specified sequence name.
*/
public function getId(PDO $con, $name = null)
{
if ($name === null) {
throw new PropelException("Unable to fetch next sequence ID without sequence name.");
}
$stmt = $con->query("SELECT nextval(".$con->quote($name).")");
$row = $stmt->fetch(PDO::FETCH_NUM);
return $row[0];
}
/**
* Returns timestamp formatter string for use in date() function.
* @return string
*/
public function getTimestampFormatter()
{
return "Y-m-d H:i:s O";
}
/**
* Returns timestamp formatter string for use in date() function.
* @return string
*/
public function getTimeFormatter()
{
return "H:i:s O";
}
/**
* @see DBAdapter::applyLimit()
*/
public function applyLimit(&$sql, $offset, $limit)
{
if ( $limit > 0 ) {
$sql .= " LIMIT ".$limit;
}
if ( $offset > 0 ) {
$sql .= " OFFSET ".$offset;
}
}
/**
* @see DBAdapter::random()
*/
public function random($seed=NULL)
{
return 'random()';
}
}

View file

@ -0,0 +1,116 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* This is used in order to connect to a SQLite database.
*
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 1612 $
* @package propel.runtime.adapter
*/
class DBSQLite extends DBAdapter
{
/**
* For SQLite this method has no effect, since SQLite doesn't support specifying a character
* set (or, another way to look at it, it doesn't require a single character set per DB).
*
* @param PDO A PDO connection instance.
* @param string The charset encoding.
* @throws PropelException If the specified charset doesn't match sqlite_libencoding()
*/
public function setCharset(PDO $con, $charset)
{
}
/**
* This method is used to ignore case.
*
* @param in The string to transform to upper case.
* @return The upper case string.
*/
public function toUpperCase($in)
{
return 'UPPER(' . $in . ')';
}
/**
* This method is used to ignore case.
*
* @param in The string whose case to ignore.
* @return The string in a case that can be ignored.
*/
public function ignoreCase($in)
{
return 'UPPER(' . $in . ')';
}
/**
* Returns SQL which concatenates the second string to the first.
*
* @param string String to concatenate.
* @param string String to append.
* @return string
*/
public function concatString($s1, $s2)
{
return "($s1 || $s2)";
}
/**
* Returns SQL which extracts a substring.
*
* @param string String to extract from.
* @param int Offset to start from.
* @param int Number of characters to extract.
* @return string
*/
public function subString($s, $pos, $len)
{
return "substr($s, $pos, $len)";
}
/**
* Returns SQL which calculates the length (in chars) of a string.
*
* @param string String to calculate length of.
* @return string
*/
public function strLength($s)
{
return "length($s)";
}
/**
* @see DBAdapter::quoteIdentifier()
*/
public function quoteIdentifier($text)
{
return '[' . $text . ']';
}
/**
* @see DBAdapter::applyLimit()
*/
public function applyLimit(&$sql, $offset, $limit)
{
if ( $limit > 0 ) {
$sql .= " LIMIT " . $limit . ($offset > 0 ? " OFFSET " . $offset : "");
} elseif ( $offset > 0 ) {
$sql .= " LIMIT -1 OFFSET " . $offset;
}
}
public function random($seed=NULL)
{
return 'random()';
}
}

View file

@ -0,0 +1,35 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* MSSQL Server returns datetimes in a format that strtotime doesn't handle so we need to extend DateTime
*
* @package propel.runtime.adapter.MSSQL
*/
class MssqlDateTime extends DateTime
{
public function __construct($datetime='now', DateTimeZone $tz = null)
{
//if the date is bad account for Mssql datetime format
if ($datetime != 'now' && strtotime($datetime) === false)
{
$datetime = substr($datetime,0, -6).substr($datetime,-2);
}
if($tz instanceof DateTimeZone)
{
parent::__construct($datetime,$tz);
}
else
{
parent::__construct($datetime);
}
}
}

View file

@ -0,0 +1,19 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* dblib doesn't support transactions so we need to add a workaround for transactions, last insert ID, and quoting
*
* @package propel.runtime.adapter.MSSQL
*/
class MssqlDebugPDO extends MssqlPropelPDO
{
public $useDebug = true;
}

View file

@ -0,0 +1,132 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* dblib doesn't support transactions so we need to add a workaround for transactions, last insert ID, and quoting
*
* @package propel.runtime.adapter.MSSQL
*/
class MssqlPropelPDO extends PropelPDO
{
/**
* Begin a transaction.
*
* It is necessary to override the abstract PDO transaction functions here, as
* the PDO driver for MSSQL does not support transactions.
*/
public function beginTransaction()
{
$return = true;
$opcount = $this->getNestedTransactionCount();
if ( $opcount === 0 ) {
$return = self::exec('BEGIN TRANSACTION');
if ($this->useDebug) {
$this->log('Begin transaction', null, __METHOD__);
}
$this->isUncommitable = false;
}
$this->nestedTransactionCount++;
return $return;
}
/**
* Commit a transaction.
*
* It is necessary to override the abstract PDO transaction functions here, as
* the PDO driver for MSSQL does not support transactions.
*/
public function commit()
{
$return = true;
$opcount = $this->getNestedTransactionCount();
if ($opcount > 0) {
if ($opcount === 1) {
if ($this->isUncommitable) {
throw new PropelException('Cannot commit because a nested transaction was rolled back');
} else {
$return = self::exec('COMMIT TRANSACTION');
if ($this->useDebug) {
$this->log('Commit transaction', null, __METHOD__);
}
}
}
$this->nestedTransactionCount--;
}
return $return;
}
/**
* Roll-back a transaction.
*
* It is necessary to override the abstract PDO transaction functions here, as
* the PDO driver for MSSQL does not support transactions.
*/
public function rollBack()
{
$return = true;
$opcount = $this->getNestedTransactionCount();
if ($opcount > 0) {
if ($opcount === 1) {
$return = self::exec('ROLLBACK TRANSACTION');
if ($this->useDebug) {
$this->log('Rollback transaction', null, __METHOD__);
}
} else {
$this->isUncommitable = true;
}
$this->nestedTransactionCount--;
}
return $return;
}
/**
* Rollback the whole transaction, even if this is a nested rollback
* and reset the nested transaction count to 0.
*
* It is necessary to override the abstract PDO transaction functions here, as
* the PDO driver for MSSQL does not support transactions.
*/
public function forceRollBack()
{
$return = true;
$opcount = $this->getNestedTransactionCount();
if ($opcount > 0) {
// If we're in a transaction, always roll it back
// regardless of nesting level.
$return = self::exec('ROLLBACK TRANSACTION');
// reset nested transaction count to 0 so that we don't
// try to commit (or rollback) the transaction outside this scope.
$this->nestedTransactionCount = 0;
if ($this->useDebug) {
$this->log('Rollback transaction', null, __METHOD__);
}
}
return $return;
}
public function lastInsertId($seqname = null)
{
$result = self::query('SELECT SCOPE_IDENTITY()');
return (int) $result->fetchColumn();
}
public function quoteIdentifier($text)
{
return '[' . $text . ']';
}
public function useQuoteIdentifier()
{
return true;
}
}

View file

@ -0,0 +1,188 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* Class for iterating over a list of Propel objects stored as arrays
*
* @author Francois Zaninotto
* @package propel.runtime.collection
*/
class PropelArrayCollection extends PropelCollection
{
protected $workerObject;
/**
* Save all the elements in the collection
*/
public function save($con = null)
{
if (null === $con) {
$con = $this->getConnection(Propel::CONNECTION_WRITE);
}
$con->beginTransaction();
try {
$obj = $this->getWorkerObject();
foreach ($this as $element) {
$obj->clear();
$obj->fromArray($element);
$obj->setNew($obj->isPrimaryKeyNull());
$obj->save($con);
}
$con->commit();
} catch (PropelException $e) {
$con->rollback();
}
}
/**
* Delete all the elements in the collection
*/
public function delete($con = null)
{
if (null === $con) {
$con = $this->getConnection(Propel::CONNECTION_WRITE);
}
$con->beginTransaction();
try {
foreach ($this as $element) {
$obj = $this->getWorkerObject();
$obj->setDeleted(false);
$obj->fromArray($element);
$obj->delete($con);
}
$con->commit();
} catch (PropelException $e) {
$con->rollback();
throw $e;
}
}
/**
* Get an array of the primary keys of all the objects in the collection
*
* @return array The list of the primary keys of the collection
*/
public function getPrimaryKeys($usePrefix = true)
{
$callable = array($this->getPeerClass(), 'getPrimaryKeyFromRow');
$ret = array();
foreach ($this as $key => $element) {
$key = $usePrefix ? ($this->getModel() . '_' . $key) : $key;
$ret[$key]= call_user_func($callable, array_values($element));
}
return $ret;
}
/**
* Populates the collection from an array
* Uses the object model to force the column types
* Does not empty the collection before adding the data from the array
*
* @param array $arr
*/
public function fromArray($arr)
{
$obj = $this->getWorkerObject();
foreach ($arr as $element) {
$obj->clear();
$obj->fromArray($element);
$this->append($obj->toArray());
}
}
/**
* Get an array representation of the collection
* This is not an alias for getData(), since it returns a copy of the data
*
* @param string $keyColumn If null, the returned array uses an incremental index.
* Otherwise, the array is indexed using the specified column
* @param boolean $usePrefix If true, the returned array prefixes keys
* with the model class name ('Article_0', 'Article_1', etc).
*
* <code>
* $bookCollection->toArray();
* array(
* 0 => array('Id' => 123, 'Title' => 'War And Peace'),
* 1 => array('Id' => 456, 'Title' => 'Don Juan'),
* )
* $bookCollection->toArray('Id');
* array(
* 123 => array('Id' => 123, 'Title' => 'War And Peace'),
* 456 => array('Id' => 456, 'Title' => 'Don Juan'),
* )
* $bookCollection->toArray(null, true);
* array(
* 'Book_0' => array('Id' => 123, 'Title' => 'War And Peace'),
* 'Book_1' => array('Id' => 456, 'Title' => 'Don Juan'),
* )
* </code>
* @return array
*/
public function toArray($keyColumn = null, $usePrefix = false)
{
$ret = array();
foreach ($this as $key => $element) {
$key = null === $keyColumn ? $key : $element[$keyColumn];
$key = $usePrefix ? ($this->getModel() . '_' . $key) : $key;
$ret[$key] = $element;
}
return $ret;
}
/**
* Synonym for toArray(), to provide a similar interface to PopelObjectCollection
*/
public function getArrayCopy($keyColumn = null, $usePrefix = false)
{
if (null === $keyColumn && false === $usePrefix) {
return parent::getArrayCopy();
} else {
return $this->toArray($keyColumn, $usePrefix);
}
}
/**
* Get an associative array representation of the collection
* The first parameter specifies the column to be used for the key,
* And the seconf for the value.
* <code>
* $res = $coll->toKeyValue('Id', 'Name');
* </code>
*
* @return array
*/
public function toKeyValue($keyColumn, $valueColumn)
{
$ret = array();
foreach ($this as $obj) {
$ret[$obj[$keyColumn]] = $obj[$valueColumn];
}
return $ret;
}
protected function getWorkerObject()
{
if (null === $this->workerObject) {
if ($this->model == '') {
throw new PropelException('You must set the collection model before interacting with it');
}
$class = $this->getModel();
$this->workerObject = new $class();
}
return $this->workerObject;
}
}
?>

View file

@ -0,0 +1,409 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* Class for iterating over a list of Propel elements
* The collection keys must be integers - no associative array accepted
*
* @author Francois Zaninotto
* @package propel.runtime.collection
*/
class PropelCollection extends ArrayObject implements Serializable
{
protected $model = '';
protected $iterator;
protected $formatter;
// Generic Collection methods
/**
* Get the data in the collection
*
* @return array
*/
public function getData()
{
return $this->getArrayCopy();
}
/**
* Set the data in the collection
*
* @param array $data
*/
public function setData($data)
{
$this->exchangeArray($data);
}
/**
* Gets the position of the internal pointer
* This position can be later used in seek()
*
* @return int
*/
public function getPosition()
{
return (int) $this->getInternalIterator()->key();
}
/**
* Move the internal pointer to the beginning of the list
* And get the first element in the collection
*
* @return mixed
*/
public function getFirst()
{
$this->getInternalIterator()->rewind();
return $this->getCurrent();
}
/**
* Check whether the internal pointer is at the beginning of the list
*
* @return boolean
*/
public function isFirst()
{
return $this->getPosition() == 0;
}
/**
* Move the internal pointer backward
* And get the previous element in the collection
*
* @return mixed
*/
public function getPrevious()
{
$pos = $this->getPosition();
if ($pos == 0) {
return null;
} else {
$this->getInternalIterator()->seek($pos - 1);
return $this->getCurrent();
}
}
/**
* Get the current element in the collection
*
* @return mixed
*/
public function getCurrent()
{
return $this->getInternalIterator()->current();
}
/**
* Move the internal pointer forward
* And get the next element in the collection
*
* @return mixed
*/
public function getNext()
{
$this->getInternalIterator()->next();
return $this->getCurrent();
}
/**
* Move the internal pointer to the end of the list
* And get the last element in the collection
*
* @return mixed
*/
public function getLast()
{
$count = $this->count();
if ($count == 0) {
return null;
} else {
$this->getInternalIterator()->seek($count - 1);
return $this->getCurrent();
}
}
/**
* Check whether the internal pointer is at the end of the list
*
* @return boolean
*/
public function isLast()
{
$count = $this->count();
if ($count == 0) {
// empty list... so yes, this is the last
return true;
} else {
return $this->getPosition() == $count - 1;
}
}
/**
* Check if the collection is empty
*
* @return boolean
*/
public function isEmpty()
{
return $this->count() == 0;
}
/**
* Check if the current index is an odd integer
*
* @return boolean
*/
public function isOdd()
{
return (boolean) ($this->getInternalIterator()->key() % 2);
}
/**
* Check if the current index is an even integer
*
* @return boolean
*/
public function isEven()
{
return !$this->isOdd();
}
/**
* Get an element from its key
* Alias for ArrayObject::offsetGet()
*
* @param mixed $key
*
* @return mixed The element
*/
public function get($key)
{
if (!$this->offsetExists($key)) {
throw new PropelException('Unknown key ' . $key);
}
return $this->offsetGet($key);
}
/**
* Pops an element off the end of the collection
*
* @return mixed The popped element
*/
public function pop()
{
if ($this->count() == 0) {
return null;
}
$ret = $this->getLast();
$lastKey = $this->getInternalIterator()->key();
$this->offsetUnset((string) $lastKey);
return $ret;
}
/**
* Pops an element off the beginning of the collection
*
* @return mixed The popped element
*/
public function shift()
{
// the reindexing is complicated to deal with through the iterator
// so let's use the simple solution
$arr = $this->getArrayCopy();
$ret = array_shift($arr);
$this->exchangeArray($arr);
return $ret;
}
/**
* Prepend one or more elements to the beginning of the collection
*
* @param mixed $value the element to prepend
*
* @return int The number of new elements in the array
*/
public function prepend($value)
{
// the reindexing is complicated to deal with through the iterator
// so let's use the simple solution
$arr = $this->getArrayCopy();
$ret = array_unshift($arr, $value);
$this->exchangeArray($arr);
return $ret;
}
/**
* Add an element to the collection with the given key
* Alias for ArrayObject::offsetSet()
*
* @param mixed $key
* @param mixed $value
*/
public function set($key, $value)
{
return $this->offsetSet($key, $value);
}
/**
* Removes a specified collection element
* Alias for ArrayObject::offsetUnset()
*
* @param mixed $key
*
* @return mixed The removed element
*/
public function remove($key)
{
if (!$this->offsetExists($key)) {
throw new PropelException('Unknown key ' . $key);
}
return $this->offsetUnset($key);
}
/**
* Clears the collection
*
* @return array The previous collection
*/
public function clear()
{
return $this->exchangeArray(array());
}
/**
* Whether or not this collection contains a specified element
*
* @param mixed $element the element
*
* @return boolean
*/
public function contains($element)
{
return in_array($element, $this->getArrayCopy(), true);
}
/**
* Search an element in the collection
*
* @param mixed $element
*
* @return mixed Returns the key for the element if it is found in the collection, FALSE otherwise
*/
public function search($element)
{
return array_search($element, $this->getArrayCopy(), true);
}
// Serializable interface
public function serialize()
{
$repr = array(
'data' => $this->getArrayCopy(),
'model' => $this->model,
);
return serialize($repr);
}
public function unserialize($data)
{
$repr = unserialize($data);
$this->exchangeArray($repr['data']);
$this->model = $repr['model'];
}
// IteratorAggregate method
/**
* Overrides ArrayObject::getIterator() to save the iterator object
* for internal use e.g. getNext(), isOdd(), etc.
*/
public function getIterator()
{
$this->iterator = new ArrayIterator($this);
return $this->iterator;
}
public function getInternalIterator()
{
if (null === $this->iterator) {
return $this->getIterator();
}
return $this->iterator;
}
// Propel collection methods
/**
* Set the model of the elements in the collection
*
* @param string $model Name of the Propel object classes stored in the collection
*/
public function setModel($model)
{
$this->model = $model;
}
/**
* Get the model of the elements in the collection
*
* @return string Name of the Propel object class stored in the collection
*/
public function getModel()
{
return $this->model;
}
/**
* Get the peer class of the elements in the collection
*
* @return string Name of the Propel peer class stored in the collection
*/
public function getPeerClass()
{
if ($this->model == '') {
throw new PropelException('You must set the collection model before interacting with it');
}
return constant($this->getModel() . '::PEER');
}
public function setFormatter(PropelFormatter $formatter)
{
$this->formatter = $formatter;
}
public function getFormatter()
{
return $this->formatter;
}
/**
* Get a connection object for the database containing the elements of the collection
*
* @param string $type The connection type (Propel::CONNECTION_READ by default; can be Propel::connection_WRITE)
*
* @return PropelPDO a connection object
*/
public function getConnection($type = Propel::CONNECTION_READ)
{
$databaseName = constant($this->getPeerClass() . '::DATABASE_NAME');
return Propel::getConnection($databaseName, $type);
}
}
?>

View file

@ -0,0 +1,249 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* Class for iterating over a list of Propel objects
*
* @author Francois Zaninotto
* @package propel.runtime.collection
*/
class PropelObjectCollection extends PropelCollection
{
/**
* Save all the elements in the collection
*/
public function save($con = null)
{
if (null === $con) {
$con = $this->getConnection(Propel::CONNECTION_WRITE);
}
$con->beginTransaction();
try {
foreach ($this as $element) {
$element->save($con);
}
$con->commit();
} catch (PropelException $e) {
$con->rollback();
throw $e;
}
}
/**
* Delete all the elements in the collection
*/
public function delete($con = null)
{
if (null === $con) {
$con = $this->getConnection(Propel::CONNECTION_WRITE);
}
$con->beginTransaction();
try {
foreach ($this as $element) {
$element->delete($con);
}
$con->commit();
} catch (PropelException $e) {
$con->rollback();
throw $e;
}
}
/**
* Get an array of the primary keys of all the objects in the collection
*
* @return array The list of the primary keys of the collection
*/
public function getPrimaryKeys($usePrefix = true)
{
$ret = array();
foreach ($this as $key => $obj) {
$key = $usePrefix ? ($this->getModel() . '_' . $key) : $key;
$ret[$key]= $obj->getPrimaryKey();
}
return $ret;
}
/**
* Populates the collection from an array
* Each object is populated from an array and the result is stored
* Does not empty the collection before adding the data from the array
*
* @param array $arr
*/
public function fromArray($arr)
{
$class = $this->getModel();
foreach ($arr as $element) {
$obj = new $class();
$obj->fromArray($element);
$this->append($obj);
}
}
/**
* Get an array representation of the collection
* Each object is turned into an array and the result is returned
*
* @param string $keyColumn If null, the returned array uses an incremental index.
* Otherwise, the array is indexed using the specified column
* @param boolean $usePrefix If true, the returned array prefixes keys
* with the model class name ('Article_0', 'Article_1', etc).
*
* <code>
* $bookCollection->toArray();
* array(
* 0 => array('Id' => 123, 'Title' => 'War And Peace'),
* 1 => array('Id' => 456, 'Title' => 'Don Juan'),
* )
* $bookCollection->toArray('Id');
* array(
* 123 => array('Id' => 123, 'Title' => 'War And Peace'),
* 456 => array('Id' => 456, 'Title' => 'Don Juan'),
* )
* $bookCollection->toArray(null, true);
* array(
* 'Book_0' => array('Id' => 123, 'Title' => 'War And Peace'),
* 'Book_1' => array('Id' => 456, 'Title' => 'Don Juan'),
* )
* </code>
* @return array
*/
public function toArray($keyColumn = null, $usePrefix = false)
{
$ret = array();
$keyGetterMethod = 'get' . $keyColumn;
foreach ($this as $key => $obj) {
$key = null === $keyColumn ? $key : $obj->$keyGetterMethod();
$key = $usePrefix ? ($this->getModel() . '_' . $key) : $key;
$ret[$key] = $obj->toArray();
}
return $ret;
}
/**
* Get an array representation of the collection
*
* @param string $keyColumn If null, the returned array uses an incremental index.
* Otherwise, the array is indexed using the specified column
* @param boolean $usePrefix If true, the returned array prefixes keys
* with the model class name ('Article_0', 'Article_1', etc).
*
* <code>
* $bookCollection->getArrayCopy();
* array(
* 0 => $book0,
* 1 => $book1,
* )
* $bookCollection->getArrayCopy('Id');
* array(
* 123 => $book0,
* 456 => $book1,
* )
* $bookCollection->getArrayCopy(null, true);
* array(
* 'Book_0' => $book0,
* 'Book_1' => $book1,
* )
* </code>
* @return array
*/
public function getArrayCopy($keyColumn = null, $usePrefix = false)
{
if (null === $keyColumn && false === $usePrefix) {
return parent::getArrayCopy();
}
$ret = array();
$keyGetterMethod = 'get' . $keyColumn;
foreach ($this as $key => $obj) {
$key = null === $keyColumn ? $key : $obj->$keyGetterMethod();
$key = $usePrefix ? ($this->getModel() . '_' . $key) : $key;
$ret[$key] = $obj;
}
return $ret;
}
/**
* Get an associative array representation of the collection
* The first parameter specifies the column to be used for the key,
* And the seconf for the value.
* <code>
* $res = $coll->toKeyValue('Id', 'Name');
* </code>
*
* @return array
*/
public function toKeyValue($keyColumn = 'PrimaryKey', $valueColumn = null)
{
$ret = array();
$keyGetterMethod = 'get' . $keyColumn;
$valueGetterMethod = (null === $valueColumn) ? '__toString' : ('get' . $valueColumn);
foreach ($this as $obj) {
$ret[$obj->$keyGetterMethod()] = $obj->$valueGetterMethod();
}
return $ret;
}
/**
* Makes an additional query to populate the objects related to the collection objects
* by a certain relation
*
* @param string $relation Relation name (e.g. 'Book')
* @param Criteria $criteria Optional Criteria object to filter the related object collection
* @param PropelPDO $con Optional connection object
*
* @return PropelObjectCollection the list of related objects
*/
public function populateRelation($relation, $criteria = null, $con = null)
{
if (!Propel::isInstancePoolingEnabled()) {
throw new PropelException('populateRelation() needs instance pooling to be enabled prior to populating the collection');
}
$relationMap = $this->getFormatter()->getTableMap()->getRelation($relation);
$symRelationMap = $relationMap->getSymmetricalRelation();
// query the db for the related objects
$useMethod = 'use' . $symRelationMap->getName() . 'Query';
$query = PropelQuery::from($relationMap->getRightTable()->getPhpName());
if (null !== $criteria) {
$query->mergeWith($criteria);
}
$relatedObjects = $query
->$useMethod()
->filterByPrimaryKeys($this->getPrimaryKeys())
->endUse()
->find($con);
// associate the related objects to the main objects
if ($relationMap->getType() == RelationMap::ONE_TO_MANY) {
$getMethod = 'get' . $symRelationMap->getName();
$addMethod = 'add' . $relationMap->getName();
foreach ($relatedObjects as $object) {
$mainObj = $object->$getMethod(); // instance pool is used here to avoid a query
$mainObj->$addMethod($object);
}
} elseif ($relationMap->getType() == RelationMap::MANY_TO_ONE) {
// nothing to do; the instance pool will catch all calls to getRelatedObject()
// and return the object in memory
} else {
throw new PropelException('populateRelation() does not support this relation type');
}
return $relatedObjects;
}
}
?>

View file

@ -0,0 +1,151 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* Class for iterating over a statement and returning one Propel object at a time
*
* @author Francois Zaninotto
* @package propel.runtime.collection
*/
class PropelOnDemandCollection extends PropelCollection
{
protected
$iterator,
$currentRow,
$currentKey = -1,
$isValid = null;
public function initIterator(PropelFormatter $formatter, PDOStatement $stmt)
{
$this->iterator = new PropelOnDemandIterator($formatter, $stmt);
}
// IteratorAggregate Interface
public function getIterator()
{
return $this->iterator;
}
// ArrayAccess Interface
public function offsetExists($offset)
{
if ($offset == $this->currentKey) {
return true;
}
throw new PropelException('The On Demand Collection does not allow acces by offset');
}
public function offsetGet($offset)
{
if ($offset == $this->currentKey) {
return $this->currentRow;
}
throw new PropelException('The On Demand Collection does not allow acces by offset');
}
public function offsetSet($offset, $value)
{
throw new PropelException('The On Demand Collection is read only');
}
public function offsetUnset($offset)
{
throw new PropelException('The On Demand Collection is read only');
}
// Serializable Interface
public function serialize()
{
throw new PropelException('The On Demand Collection cannot be serialized');
}
public function unserialize($data)
{
throw new PropelException('The On Demand Collection cannot be serialized');
}
// Countable Interface
/**
* Returns the number of rows in the resultset
* Warning: this number is inaccurate for most databases. Do not rely on it for a portable application.
*
* @return int number of results
*/
public function count()
{
return $this->iterator->count();
}
// ArrayObject methods
public function append($value)
{
throw new PropelException('The On Demand Collection is read only');
}
public function prepend($value)
{
throw new PropelException('The On Demand Collection is read only');
}
public function asort()
{
throw new PropelException('The On Demand Collection is read only');
}
public function exchangeArray($input)
{
throw new PropelException('The On Demand Collection is read only');
}
public function getArrayCopy()
{
throw new PropelException('The On Demand Collection does not allow acces by offset');
}
public function getFlags()
{
throw new PropelException('The On Demand Collection does not allow acces by offset');
}
public function ksort()
{
throw new PropelException('The On Demand Collection is read only');
}
public function natcasesort()
{
throw new PropelException('The On Demand Collection is read only');
}
public function natsort()
{
throw new PropelException('The On Demand Collection is read only');
}
public function setFlags($flags)
{
throw new PropelException('The On Demand Collection does not allow acces by offset');
}
public function uasort($cmp_function)
{
throw new PropelException('The On Demand Collection is read only');
}
public function uksort($cmp_function)
{
throw new PropelException('The On Demand Collection is read only');
}
}

View file

@ -0,0 +1,118 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* Class for iterating over a statement and returning one Propel object at a time
*
* @author Francois Zaninotto
* @package propel.runtime.collection
*/
class PropelOnDemandIterator implements Iterator
{
protected
$formatter,
$stmt,
$currentRow,
$currentKey = -1,
$isValid = null,
$enableInstancePoolingOnFinish = false;
public function __construct(PropelFormatter $formatter, PDOStatement $stmt)
{
$this->formatter = $formatter;
$this->stmt = $stmt;
$this->enableInstancePoolingOnFinish = Propel::disableInstancePooling();
}
public function closeCursor()
{
$this->stmt->closeCursor();
}
/**
* Returns the number of rows in the resultset
* Warning: this number is inaccurate for most databases. Do not rely on it for a portable application.
*
* @return int number of results
*/
public function count()
{
return $this->stmt->rowCount();
}
// Iterator Interface
/**
* Gets the current Model object in the collection
* This is where the hydration takes place.
*
* @see PropelObjectFormatter::getAllObjectsFromRow()
*
* @return BaseObject
*/
public function current()
{
return $this->formatter->getAllObjectsFromRow($this->currentRow);
}
/**
* Gets the current key in the iterator
*
* @return string
*/
public function key()
{
return $this->currentKey;
}
/**
* Advances the curesor in the statement
* Closes the cursor if the end of the statement is reached
*/
public function next()
{
$this->currentRow = $this->stmt->fetch(PDO::FETCH_NUM);
$this->currentKey++;
$this->isValid = (boolean) $this->currentRow;
if (!$this->isValid) {
$this->closeCursor();
if ($this->enableInstancePoolingOnFinish) {
Propel::enableInstancePooling();
}
}
}
/**
* Initializes the iterator by advancing to the first position
* This method can only be called once (this is a NoRewindIterator)
*/
public function rewind()
{
// check that the hydration can begin
if (null === $this->formatter) {
throw new PropelException('The On Demand collection requires a formatter. Add it by calling setFormatter()');
}
if (null === $this->stmt) {
throw new PropelException('The On Demand collection requires a statement. Add it by calling setStatement()');
}
if (null !== $this->isValid) {
throw new PropelException('The On Demand collection can only be iterated once');
}
// initialize the current row and key
$this->next();
}
public function valid()
{
return $this->isValid;
}
}

View file

@ -0,0 +1,159 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* PropelConfiguration is a container for all Propel's configuration data.
*
* PropelConfiguration implements ArrayAccess interface so the configuration
* can be accessed as an array or using a simple getter and setter. The whole
* configuration can also be retrieved as a nested arrays, flat array or as a
* PropelConfiguration instance.
*
* @author Veikko Mäkinen <veikko@veikko.fi>
* @version $Revision: 1612 $
* @package propel.runtime.config
*/
class PropelConfiguration implements ArrayAccess
{
const TYPE_ARRAY = 1;
const TYPE_ARRAY_FLAT = 2;
const TYPE_OBJECT = 3;
/**
* @var array An array of parameters
*/
protected $parameters = array();
/**
* Construct a new configuration container
*
* @param array $parameters
*/
public function __construct(array $parameters = array())
{
$this->parameters = $parameters;
}
/**
* @see http://www.php.net/ArrayAccess
*/
public function offsetExists($offset)
{
return array_key_exists($offset, $this->parameters);
}
/**
* @see http://www.php.net/ArrayAccess
*/
public function offsetSet($offset, $value)
{
$this->parameter[$offset] = $value;
}
/**
* @see http://www.php.net/ArrayAccess
*/
public function offsetGet($offset)
{
return $this->parameters[$offset];
}
/**
* @see http://www.php.net/ArrayAccess
*/
public function offsetUnset($offset)
{
unset($this->parameters[$offset]);
}
/**
* Get parameter value from the container
*
* @param string $name Parameter name
* @param mixed $default Default value to be used if the
* requested value is not found
* @return mixed Parameter value or the default
*/
public function getParameter($name, $default = null)
{
$ret = $this->parameters;
$parts = explode('.', $name); //name.space.name
while ($part = array_shift($parts)) {
if (isset($ret[$part])) {
$ret = $ret[$part];
} else {
return $default;
}
}
return $ret;
}
/**
* Store a value to the container
*
* @param string $name Configuration item name (name.space.name)
* @param mixed $value Value to be stored
*/
public function setParameter($name, $value)
{
$param = &$this->parameters;
$parts = explode('.', $name); //name.space.name
while ($part = array_shift($parts)) {
$param = &$param[$part];
}
$param = $value;
}
/**
*
*
* @param int $type
* @return mixed
*/
public function getParameters($type = PropelConfiguration::TYPE_ARRAY)
{
switch ($type) {
case PropelConfiguration::TYPE_ARRAY:
return $this->parameters;
case PropelConfiguration::TYPE_ARRAY_FLAT:
return $this->toFlatArray();
case PropelConfiguration::TYPE_OBJECT:
return $this;
default:
throw new PropelException('Unknown configuration type: '. var_export($type, true));
}
}
/**
* Get the configuration as a flat array. ($array['name.space.item'] = 'value')
*
* @return array
*/
protected function toFlatArray()
{
$result = array();
$it = new PropelConfigurationIterator(new RecursiveArrayIterator($this->parameters), RecursiveIteratorIterator::SELF_FIRST);
foreach($it as $key => $value) {
$ns = $it->getDepth() ? $it->getNamespace() . '.'. $key : $key;
if ($it->getNodeType() == PropelConfigurationIterator::NODE_ITEM) {
$result[$ns] = $value;
}
}
return $result;
}
}
?>

View file

@ -0,0 +1,103 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* PropelConfigurationIterator is used internally by PropelConfiguration to
* build a flat array from nesting configuration arrays.
*
* @author Veikko Mäkinen <veikko@veikko.fi>
* @version $Revision: 1612 $
* @package propel.runtime.config
*/
class PropelConfigurationIterator extends RecursiveIteratorIterator
{
/**
* Node is a parent node
*/
const NODE_PARENT = 0;
/**
* Node is an actual configuration item
*/
const NODE_ITEM = 1;
/**
* Namespace stack when recursively iterating the configuration tree
*
* @var array
*/
protected $namespaceStack = array();
/**
* Current node type. Possible values: null (undefined), self::NODE_PARENT or self::NODE_ITEM
*
* @var int
*/
protected $nodeType = null;
/**
* Get current namespace
*
* @return string
*/
public function getNamespace()
{
return implode('.', $this->namespaceStack);
}
/**
* Get current node type.
*
* @see http://www.php.net/RecursiveIteratorIterator
* @return int
* - null (undefined)
* - self::NODE_PARENT
* - self::NODE_ITEM
*/
public function getNodeType()
{
return $this->nodeType;
}
/**
* Get the current element
*
* @see http://www.php.net/RecursiveIteratorIterator
* @return mixed
*/
public function current()
{
$current = parent::current();
if (is_array($current)) {
$this->namespaceStack[] = $this->key();
$this->nodeType = self::NODE_PARENT;
}
else {
$this->nodeType = self::NODE_ITEM;
}
return $current;
}
/**
* Called after current child iterator is invalid and right before it gets destructed.
*
* @see http://www.php.net/RecursiveIteratorIterator
*/
public function endChildren()
{
if ($this->namespaceStack) {
array_pop($this->namespaceStack);
}
}
}
?>

View file

@ -0,0 +1,111 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* PDO connection subclass that provides some basic support for query counting and logging.
*
* This class is ONLY intended for development use. This class is also a work in-progress
* and, as such, it should be expected that this class' API may change.
*
* The following runtime configuration items affect the behaviour of this class:
*
* - debugpdo.logging.enabled (default: true)
* Should any logging take place
*
* - debugpdo.logging.innerglue (default: ": ")
* String to use for combining the title of a detail and its value
*
* - debugpdo.logging.outerglue (default: " | ")
* String to use for combining details together on a log line
*
* - debugpdo.logging.realmemoryusage (default: false)
* Parameter to memory_get_usage() and memory_get_peak_usage() calls
*
* - debugpdo.logging.methods (default: DebugPDO::$defaultLogMethods)
* An array of method names ("Class::method") to be included in method call logging
*
* - debugpdo.logging.onlyslow (default: false)
* Suppress logging of non-slow queries.
*
* - debugpdo.logging.details.slow.enabled (default: false)
* Enables flagging of slow method calls
*
* - debugpdo.logging.details.slow.threshold (default: 0.1)
* Method calls taking more seconds than this threshold are considered slow
*
* - debugpdo.logging.details.time.enabled (default: false)
* Enables logging of method execution times
*
* - debugpdo.logging.details.time.precision (default: 3)
* Determines the precision of the execution time logging
*
* - debugpdo.logging.details.time.pad (default: 10)
* How much horizontal space to reserve for the execution time on a log line
*
* - debugpdo.logging.details.mem.enabled (default: false)
* Enables logging of the instantaneous PHP memory consumption
*
* - debugpdo.logging.details.mem.precision (default: 1)
* Determines the precision of the memory consumption logging
*
* - debugpdo.logging.details.mem.pad (default: 9)
* How much horizontal space to reserve for the memory consumption on a log line
*
* - debugpdo.logging.details.memdelta.enabled (default: false)
* Enables logging differences in memory consumption before and after the method call
*
* - debugpdo.logging.details.memdelta.precision (default: 1)
* Determines the precision of the memory difference logging
*
* - debugpdo.logging.details.memdelta.pad (default: 10)
* How much horizontal space to reserve for the memory difference on a log line
*
* - debugpdo.logging.details.mempeak.enabled (default: false)
* Enables logging the peak memory consumption thus far by the currently executing PHP script
*
* - debugpdo.logging.details.mempeak.precision (default: 1)
* Determines the precision of the memory peak logging
*
* - debugpdo.logging.details.mempeak.pad (default: 9)
* How much horizontal space to reserve for the memory peak on a log line
*
* - debugpdo.logging.details.querycount.enabled (default: false)
* Enables logging of the number of queries performed by the DebugPDO instance thus far
*
* - debugpdo.logging.details.querycount.pad (default: 2)
* How much horizontal space to reserve for the query count on a log line
*
* - debugpdo.logging.details.method.enabled (default: false)
* Enables logging of the name of the method call
*
* - debugpdo.logging.details.method.pad (default: 28)
* How much horizontal space to reserve for the method name on a log line
*
* The order in which the logging details are enabled is significant, since it determines the order in
* which they will appear in the log file.
*
* @example // Enable simple query profiling, flagging calls taking over 1.5 seconds as slow:
* $config = Propel::getConfiguration(PropelConfiguration::TYPE_OBJECT);
* $config->setParameter('debugpdo.logging.details.slow.enabled', true);
* $config->setParameter('debugpdo.logging.details.slow.threshold', 1.5);
* $config->setParameter('debugpdo.logging.details.time.enabled', true);
*
* @author Francois Zaninotto
* @author Cameron Brunner <cameron.brunner@gmail.com>
* @author Hans Lellelid <hans@xmpl.org>
* @author Christian Abegg <abegg.ch@gmail.com>
* @author Jarno Rantanen <jarno.rantanen@tkk.fi>
* @since 2006-09-22
* @package propel.runtime.connection
*/
class DebugPDO extends PropelPDO
{
public $useDebug = true;
}

View file

@ -0,0 +1,122 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* PDOStatement that provides some enhanced functionality needed by Propel.
*
* Simply adds the ability to count the number of queries executed and log the queries/method calls.
*
* @author Oliver Schonrock <oliver@realtsp.com>
* @author Jarno Rantanen <jarno.rantanen@tkk.fi>
* @since 2007-07-12
* @package propel.runtime.connection
*/
class DebugPDOStatement extends PDOStatement
{
/**
* The PDO connection from which this instance was created.
*
* @var PropelPDO
*/
protected $pdo;
/**
* Hashmap for resolving the PDO::PARAM_* class constants to their human-readable names.
*
* This is only used in logging the binding of variables.
*
* @see self::bindValue()
* @var array
*/
protected static $typeMap = array(
PDO::PARAM_BOOL => "PDO::PARAM_BOOL",
PDO::PARAM_INT => "PDO::PARAM_INT",
PDO::PARAM_STR => "PDO::PARAM_STR",
PDO::PARAM_LOB => "PDO::PARAM_LOB",
PDO::PARAM_NULL => "PDO::PARAM_NULL",
);
/**
* @var array The values that have been bound
*/
protected $boundValues = array();
/**
* Construct a new statement class with reference to main DebugPDO object from
* which this instance was created.
*
* @param DebugPDO $pdo Reference to the parent PDO instance.
*/
protected function __construct(PropelPDO $pdo)
{
$this->pdo = $pdo;
}
public function getExecutedQueryString()
{
$sql = $this->queryString;
$matches = array();
if (preg_match_all('/(:p[0-9]+\b)/', $sql, $matches)) {
$size = count($matches[1]);
for ($i = $size-1; $i >= 0; $i--) {
$pos = $matches[1][$i];
$sql = str_replace($pos, $this->boundValues[$pos], $sql);
}
}
return $sql;
}
/**
* Executes a prepared statement. Returns a boolean value indicating success.
*
* Overridden for query counting and logging.
*
* @return bool
*/
public function execute($input_parameters = null)
{
$debug = $this->pdo->getDebugSnapshot();
$return = parent::execute($input_parameters);
$sql = $this->getExecutedQueryString();
$this->pdo->log($sql, null, __METHOD__, $debug);
$this->pdo->setLastExecutedQuery($sql);
$this->pdo->incrementQueryCount();
return $return;
}
/**
* Binds a value to a corresponding named or question mark placeholder in the SQL statement
* that was use to prepare the statement. Returns a boolean value indicating success.
*
* @param int $pos Parameter identifier (for determining what to replace in the query).
* @param mixed $value The value to bind to the parameter.
* @param int $type Explicit data type for the parameter using the PDO::PARAM_* constants. Defaults to PDO::PARAM_STR.
* @return boolean
*/
public function bindValue($pos, $value, $type = PDO::PARAM_STR)
{
$debug = $this->pdo->getDebugSnapshot();
$typestr = isset(self::$typeMap[$type]) ? self::$typeMap[$type] : '(default)';
$return = parent::bindValue($pos, $value, $type);
$valuestr = $type == PDO::PARAM_LOB ? '[LOB value]' : var_export($value, true);
$msg = "Binding $valuestr at position $pos w/ PDO type $typestr";
$this->boundValues[$pos] = $valuestr;
$this->pdo->log($msg, null, __METHOD__, $debug);
return $return;
}
}

View file

@ -0,0 +1,716 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* PDO connection subclass that provides the basic fixes to PDO that are required by Propel.
*
* This class was designed to work around the limitation in PDO where attempting to begin
* a transaction when one has already been begun will trigger a PDOException. Propel
* relies on the ability to create nested transactions, even if the underlying layer
* simply ignores these (because it doesn't support nested transactions).
*
* The changes that this class makes to the underlying API include the addition of the
* getNestedTransactionDepth() and isInTransaction() and the fact that beginTransaction()
* will no longer throw a PDOException (or trigger an error) if a transaction is already
* in-progress.
*
* @author Cameron Brunner <cameron.brunner@gmail.com>
* @author Hans Lellelid <hans@xmpl.org>
* @author Christian Abegg <abegg.ch@gmail.com>
* @since 2006-09-22
* @package propel.runtime.connection
*/
class PropelPDO extends PDO
{
/**
* Attribute to use to set whether to cache prepared statements.
*/
const PROPEL_ATTR_CACHE_PREPARES = -1;
const DEFAULT_SLOW_THRESHOLD = 0.1;
const DEFAULT_ONLYSLOW_ENABLED = false;
/**
* The current transaction depth.
* @var int
*/
protected $nestedTransactionCount = 0;
/**
* Cache of prepared statements (PDOStatement) keyed by md5 of SQL.
*
* @var array [md5(sql) => PDOStatement]
*/
protected $preparedStatements = array();
/**
* Whether to cache prepared statements.
*
* @var boolean
*/
protected $cachePreparedStatements = false;
/**
* Whether the final commit is possible
* Is false if a nested transaction is rolled back
*/
protected $isUncommitable = false;
/**
* Count of queries performed.
*
* @var int
*/
protected $queryCount = 0;
/**
* SQL code of the latest performed query.
*
* @var string
*/
protected $lastExecutedQuery;
/**
* Whether or not the debug is enabled
*
* @var boolean
*/
public $useDebug = false;
/**
* Configured BasicLogger (or compatible) logger.
*
* @var BasicLogger
*/
protected $logger;
/**
* The log level to use for logging.
*
* @var int
*/
private $logLevel = Propel::LOG_DEBUG;
/**
* The default value for runtime config item "debugpdo.logging.methods".
*
* @var array
*/
protected static $defaultLogMethods = array(
'PropelPDO::exec',
'PropelPDO::query',
'DebugPDOStatement::execute',
);
/**
* Creates a PropelPDO instance representing a connection to a database.
*.
* If so configured, specifies a custom PDOStatement class and makes an entry
* to the log with the state of this object just after its initialization.
* Add PropelPDO::__construct to $defaultLogMethods to see this message
*
* @param string $dsn Connection DSN.
* @param string $username (optional) The user name for the DSN string.
* @param string $password (optional) The password for the DSN string.
* @param array $driver_options (optional) A key=>value array of driver-specific connection options.
* @throws PDOException if there is an error during connection initialization.
*/
public function __construct($dsn, $username = null, $password = null, $driver_options = array())
{
if ($this->useDebug) {
$debug = $this->getDebugSnapshot();
}
parent::__construct($dsn, $username, $password, $driver_options);
if ($this->useDebug) {
$this->configureStatementClass('DebugPDOStatement', $suppress = true);
$this->log('Opening connection', null, __METHOD__, $debug);
}
}
/**
* Gets the current transaction depth.
* @return int
*/
public function getNestedTransactionCount()
{
return $this->nestedTransactionCount;
}
/**
* Set the current transaction depth.
* @param int $v The new depth.
*/
protected function setNestedTransactionCount($v)
{
$this->nestedTransactionCount = $v;
}
/**
* Is this PDO connection currently in-transaction?
* This is equivalent to asking whether the current nested transaction count
* is greater than 0.
* @return boolean
*/
public function isInTransaction()
{
return ($this->getNestedTransactionCount() > 0);
}
/**
* Check whether the connection contains a transaction that can be committed.
* To be used in an evironment where Propelexceptions are caught.
*
* @return boolean True if the connection is in a committable transaction
*/
public function isCommitable()
{
return $this->isInTransaction() && !$this->isUncommitable;
}
/**
* Overrides PDO::beginTransaction() to prevent errors due to already-in-progress transaction.
*/
public function beginTransaction()
{
$return = true;
if (!$this->nestedTransactionCount) {
$return = parent::beginTransaction();
if ($this->useDebug) {
$this->log('Begin transaction', null, __METHOD__);
}
$this->isUncommitable = false;
}
$this->nestedTransactionCount++;
return $return;
}
/**
* Overrides PDO::commit() to only commit the transaction if we are in the outermost
* transaction nesting level.
*/
public function commit()
{
$return = true;
$opcount = $this->nestedTransactionCount;
if ($opcount > 0) {
if ($opcount === 1) {
if ($this->isUncommitable) {
throw new PropelException('Cannot commit because a nested transaction was rolled back');
} else {
$return = parent::commit();
if ($this->useDebug) {
$this->log('Commit transaction', null, __METHOD__);
}
}
}
$this->nestedTransactionCount--;
}
return $return;
}
/**
* Overrides PDO::rollBack() to only rollback the transaction if we are in the outermost
* transaction nesting level
* @return boolean Whether operation was successful.
*/
public function rollBack()
{
$return = true;
$opcount = $this->nestedTransactionCount;
if ($opcount > 0) {
if ($opcount === 1) {
$return = parent::rollBack();
if ($this->useDebug) {
$this->log('Rollback transaction', null, __METHOD__);
}
} else {
$this->isUncommitable = true;
}
$this->nestedTransactionCount--;
}
return $return;
}
/**
* Rollback the whole transaction, even if this is a nested rollback
* and reset the nested transaction count to 0.
* @return boolean Whether operation was successful.
*/
public function forceRollBack()
{
$return = true;
if ($this->nestedTransactionCount) {
// If we're in a transaction, always roll it back
// regardless of nesting level.
$return = parent::rollBack();
// reset nested transaction count to 0 so that we don't
// try to commit (or rollback) the transaction outside this scope.
$this->nestedTransactionCount = 0;
if ($this->useDebug) {
$this->log('Rollback transaction', null, __METHOD__);
}
}
return $return;
}
/**
* Sets a connection attribute.
*
* This is overridden here to provide support for setting Propel-specific attributes
* too.
*
* @param int $attribute The attribute to set (e.g. PropelPDO::PROPEL_ATTR_CACHE_PREPARES).
* @param mixed $value The attribute value.
*/
public function setAttribute($attribute, $value)
{
switch($attribute) {
case self::PROPEL_ATTR_CACHE_PREPARES:
$this->cachePreparedStatements = $value;
break;
default:
parent::setAttribute($attribute, $value);
}
}
/**
* Gets a connection attribute.
*
* This is overridden here to provide support for setting Propel-specific attributes
* too.
*
* @param int $attribute The attribute to get (e.g. PropelPDO::PROPEL_ATTR_CACHE_PREPARES).
*/
public function getAttribute($attribute)
{
switch($attribute) {
case self::PROPEL_ATTR_CACHE_PREPARES:
return $this->cachePreparedStatements;
break;
default:
return parent::getAttribute($attribute);
}
}
/**
* Prepares a statement for execution and returns a statement object.
*
* Overrides PDO::prepare() in order to:
* - Add logging and query counting if logging is true.
* - Add query caching support if the PropelPDO::PROPEL_ATTR_CACHE_PREPARES was set to true.
*
* @param string $sql This must be a valid SQL statement for the target database server.
* @param array One or more key => value pairs to set attribute values
* for the PDOStatement object that this method returns.
* @return PDOStatement
*/
public function prepare($sql, $driver_options = array())
{
if ($this->useDebug) {
$debug = $this->getDebugSnapshot();
}
if ($this->cachePreparedStatements) {
if (!isset($this->preparedStatements[$sql])) {
$return = parent::prepare($sql, $driver_options);
$this->preparedStatements[$sql] = $return;
} else {
$return = $this->preparedStatements[$sql];
}
} else {
$return = parent::prepare($sql, $driver_options);
}
if ($this->useDebug) {
$this->log($sql, null, __METHOD__, $debug);
}
return $return;
}
/**
* Execute an SQL statement and return the number of affected rows.
*
* Overrides PDO::exec() to log queries when required
*
* @return int
*/
public function exec($sql)
{
if ($this->useDebug) {
$debug = $this->getDebugSnapshot();
}
$return = parent::exec($sql);
if ($this->useDebug) {
$this->log($sql, null, __METHOD__, $debug);
$this->setLastExecutedQuery($sql);
$this->incrementQueryCount();
}
return $return;
}
/**
* Executes an SQL statement, returning a result set as a PDOStatement object.
* Despite its signature here, this method takes a variety of parameters.
*
* Overrides PDO::query() to log queries when required
*
* @see http://php.net/manual/en/pdo.query.php for a description of the possible parameters.
* @return PDOStatement
*/
public function query()
{
if ($this->useDebug) {
$debug = $this->getDebugSnapshot();
}
$args = func_get_args();
if (version_compare(PHP_VERSION, '5.3', '<')) {
$return = call_user_func_array(array($this, 'parent::query'), $args);
} else {
$return = call_user_func_array('parent::query', $args);
}
if ($this->useDebug) {
$sql = $args[0];
$this->log($sql, null, __METHOD__, $debug);
$this->setLastExecutedQuery($sql);
$this->incrementQueryCount();
}
return $return;
}
/**
* Clears any stored prepared statements for this connection.
*/
public function clearStatementCache()
{
$this->preparedStatements = array();
}
/**
* Configures the PDOStatement class for this connection.
*
* @param boolean $suppressError Whether to suppress an exception if the statement class cannot be set.
* @throws PropelException if the statement class cannot be set (and $suppressError is false).
*/
protected function configureStatementClass($class = 'PDOStatement', $suppressError = true)
{
// extending PDOStatement is only supported with non-persistent connections
if (!$this->getAttribute(PDO::ATTR_PERSISTENT)) {
$this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array($class, array($this)));
} elseif (!$suppressError) {
throw new PropelException('Extending PDOStatement is not supported with persistent connections.');
}
}
/**
* Returns the number of queries this DebugPDO instance has performed on the database connection.
*
* When using DebugPDOStatement as the statement class, any queries by DebugPDOStatement instances
* are counted as well.
*
* @return int
* @throws PropelException if persistent connection is used (since unable to override PDOStatement in that case).
*/
public function getQueryCount()
{
// extending PDOStatement is not supported with persistent connections
if ($this->getAttribute(PDO::ATTR_PERSISTENT)) {
throw new PropelException('Extending PDOStatement is not supported with persistent connections. Count would be inaccurate, because we cannot count the PDOStatment::execute() calls. Either don\'t use persistent connections or don\'t call PropelPDO::getQueryCount()');
}
return $this->queryCount;
}
/**
* Increments the number of queries performed by this DebugPDO instance.
*
* Returns the original number of queries (ie the value of $this->queryCount before calling this method).
*
* @return int
*/
public function incrementQueryCount()
{
$this->queryCount++;
}
/**
* Get the SQL code for the latest query executed by Propel
*
* @return string Executable SQL code
*/
public function getLastExecutedQuery()
{
return $this->lastExecutedQuery;
}
/**
* Set the SQL code for the latest query executed by Propel
*
* @param string $query Executable SQL code
*/
public function setLastExecutedQuery($query)
{
$this->lastExecutedQuery = $query;
}
/**
* Enable or disable the query debug features
*
* @var boolean $value True to enable debug (default), false to disable it
*/
public function useDebug($value = true)
{
if ($value) {
$this->configureStatementClass('DebugPDOStatement', $suppress = true);
} else {
// reset query logging
$this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('PDOStatement'));
$this->setLastExecutedQuery('');
$this->queryCount = 0;
}
$this->clearStatementCache();
$this->useDebug = $value;
}
/**
* Sets the logging level to use for logging method calls and SQL statements.
*
* @param int $level Value of one of the Propel::LOG_* class constants.
*/
public function setLogLevel($level)
{
$this->logLevel = $level;
}
/**
* Sets a logger to use.
*
* The logger will be used by this class to log various method calls and their properties.
*
* @param BasicLogger $logger A Logger with an API compatible with BasicLogger (or PEAR Log).
*/
public function setLogger($logger)
{
$this->logger = $logger;
}
/**
* Gets the logger in use.
*
* @return BasicLogger $logger A Logger with an API compatible with BasicLogger (or PEAR Log).
*/
public function getLogger()
{
return $this->logger;
}
/**
* Logs the method call or SQL using the Propel::log() method or a registered logger class.
*
* @uses self::getLogPrefix()
* @see self::setLogger()
*
* @param string $msg Message to log.
* @param int $level (optional) Log level to use; will use self::setLogLevel() specified level by default.
* @param string $methodName (optional) Name of the method whose execution is being logged.
* @param array $debugSnapshot (optional) Previous return value from self::getDebugSnapshot().
*/
public function log($msg, $level = null, $methodName = null, array $debugSnapshot = null)
{
// If logging has been specifically disabled, this method won't do anything
if (!$this->getLoggingConfig('enabled', true)) {
return;
}
// If the method being logged isn't one of the ones to be logged, bail
if (!in_array($methodName, $this->getLoggingConfig('methods', self::$defaultLogMethods))) {
return;
}
// If a logging level wasn't provided, use the default one
if ($level === null) {
$level = $this->logLevel;
}
// Determine if this query is slow enough to warrant logging
if ($this->getLoggingConfig("onlyslow", self::DEFAULT_ONLYSLOW_ENABLED)) {
$now = $this->getDebugSnapshot();
if ($now['microtime'] - $debugSnapshot['microtime'] < $this->getLoggingConfig("details.slow.threshold", self::DEFAULT_SLOW_THRESHOLD)) return;
}
// If the necessary additional parameters were given, get the debug log prefix for the log line
if ($methodName && $debugSnapshot) {
$msg = $this->getLogPrefix($methodName, $debugSnapshot) . $msg;
}
// We won't log empty messages
if (!$msg) {
return;
}
// Delegate the actual logging forward
if ($this->logger) {
$this->logger->log($msg, $level);
} else {
Propel::log($msg, $level);
}
}
/**
* Returns a snapshot of the current values of some functions useful in debugging.
*
* @return array
*/
public function getDebugSnapshot()
{
if ($this->useDebug) {
return array(
'microtime' => microtime(true),
'memory_get_usage' => memory_get_usage($this->getLoggingConfig('realmemoryusage', false)),
'memory_get_peak_usage' => memory_get_peak_usage($this->getLoggingConfig('realmemoryusage', false)),
);
} else {
throw new PropelException('Should not get debug snapshot when not debugging');
}
}
/**
* Returns a named configuration item from the Propel runtime configuration, from under the
* 'debugpdo.logging' prefix. If such a configuration setting hasn't been set, the given default
* value will be returned.
*
* @param string $key Key for which to return the value.
* @param mixed $defaultValue Default value to apply if config item hasn't been set.
* @return mixed
*/
protected function getLoggingConfig($key, $defaultValue)
{
return Propel::getConfiguration(PropelConfiguration::TYPE_OBJECT)->getParameter("debugpdo.logging.$key", $defaultValue);
}
/**
* Returns a prefix that may be prepended to a log line, containing debug information according
* to the current configuration.
*
* Uses a given $debugSnapshot to calculate how much time has passed since the call to self::getDebugSnapshot(),
* how much the memory consumption by PHP has changed etc.
*
* @see self::getDebugSnapshot()
*
* @param string $methodName Name of the method whose execution is being logged.
* @param array $debugSnapshot A previous return value from self::getDebugSnapshot().
* @return string
*/
protected function getLogPrefix($methodName, $debugSnapshot)
{
$prefix = '';
$now = $this->getDebugSnapshot();
$logDetails = array_keys($this->getLoggingConfig('details', array()));
$innerGlue = $this->getLoggingConfig('innerglue', ': ');
$outerGlue = $this->getLoggingConfig('outerglue', ' | ');
// Iterate through each detail that has been configured to be enabled
foreach ($logDetails as $detailName) {
if (!$this->getLoggingConfig("details.$detailName.enabled", false))
continue;
switch ($detailName) {
case 'slow';
$value = $now['microtime'] - $debugSnapshot['microtime'] >= $this->getLoggingConfig("details.$detailName.threshold", self::DEFAULT_SLOW_THRESHOLD) ? 'YES' : ' NO';
break;
case 'time':
$value = number_format($now['microtime'] - $debugSnapshot['microtime'], $this->getLoggingConfig("details.$detailName.precision", 3)) . ' sec';
$value = str_pad($value, $this->getLoggingConfig("details.$detailName.pad", 10), ' ', STR_PAD_LEFT);
break;
case 'mem':
$value = self::getReadableBytes($now['memory_get_usage'], $this->getLoggingConfig("details.$detailName.precision", 1));
$value = str_pad($value, $this->getLoggingConfig("details.$detailName.pad", 9), ' ', STR_PAD_LEFT);
break;
case 'memdelta':
$value = $now['memory_get_usage'] - $debugSnapshot['memory_get_usage'];
$value = ($value > 0 ? '+' : '') . self::getReadableBytes($value, $this->getLoggingConfig("details.$detailName.precision", 1));
$value = str_pad($value, $this->getLoggingConfig("details.$detailName.pad", 10), ' ', STR_PAD_LEFT);
break;
case 'mempeak':
$value = self::getReadableBytes($now['memory_get_peak_usage'], $this->getLoggingConfig("details.$detailName.precision", 1));
$value = str_pad($value, $this->getLoggingConfig("details.$detailName.pad", 9), ' ', STR_PAD_LEFT);
break;
case 'querycount':
$value = $this->getQueryCount();
$value = str_pad($value, $this->getLoggingConfig("details.$detailName.pad", 2), ' ', STR_PAD_LEFT);
break;
case 'method':
$value = $methodName;
$value = str_pad($value, $this->getLoggingConfig("details.$detailName.pad", 28), ' ', STR_PAD_RIGHT);
break;
default:
$value = 'n/a';
break;
}
$prefix .= $detailName . $innerGlue . $value . $outerGlue;
}
return $prefix;
}
/**
* Returns a human-readable representation of the given byte count.
*
* @param int $bytes Byte count to convert.
* @param int $precision How many decimals to include.
* @return string
*/
protected function getReadableBytes($bytes, $precision)
{
$suffix = array('B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
$total = count($suffix);
for ($i = 0; $bytes > 1024 && $i < $total; $i++)
$bytes /= 1024;
return number_format($bytes, $precision) . ' ' . $suffix[$i];
}
/**
* If so configured, makes an entry to the log of the state of this object just prior to its destruction.
* Add PropelPDO::__destruct to $defaultLogMethods to see this message
*
* @see self::log()
*/
public function __destruct()
{
if ($this->useDebug) {
$this->log('Closing connection', null, __METHOD__, $this->getDebugSnapshot());
}
}
}

View file

@ -0,0 +1,50 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* The base class of all exceptions thrown by Propel.
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 1612 $
* @package propel.runtime.exception
*/
class PropelException extends Exception {
/** The nested "cause" exception. */
protected $cause;
function __construct($p1, $p2 = null) {
$cause = null;
if ($p2 !== null) {
$msg = $p1;
$cause = $p2;
} else {
if ($p1 instanceof Exception) {
$msg = "";
$cause = $p1;
} else {
$msg = $p1;
}
}
parent::__construct($msg);
if ($cause !== null) {
$this->cause = $cause;
$this->message .= " [wrapped: " . $cause->getMessage() ."]";
}
}
function getCause() {
return $this->cause;
}
}

View file

@ -0,0 +1,144 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* Data object to describe a joined hydration in a Model Query
* ModelWith objects are used by formatters to hydrate related objects
*
* @author Francois Zaninotto (Propel)
* @package propel.runtime.query
*/
class ModelWith
{
protected $modelName = '';
protected $modelPeerName = '';
protected $isSingleTableInheritance = false;
protected $isAdd = false;
protected $relationName = '';
protected $relationMethod = '';
protected $relatedClass;
public function __construct(ModelJoin $join = null)
{
if (null !== $join) {
$this->init($join);
}
}
/**
* Define the joined hydration schema based on a join object.
* Fills the ModelWith properties using a ModelJoin as source
*
* @param ModelJoin $join
*/
public function init(ModelJoin $join)
{
$tableMap = $join->getTableMap();
$this->modelName = $tableMap->getClassname();
$this->modelPeerName = $tableMap->getPeerClassname();
$this->isSingleTableInheritance = $tableMap->isSingleTableInheritance();
$relation = $join->getRelationMap();
if ($relation->getType() == RelationMap::ONE_TO_MANY) {
$this->isAdd = true;
$this->relationName = $relation->getName() . 's';
$this->relationMethod = 'add' . $relation->getName();
} else {
$this->relationName = $relation->getName();
$this->relationMethod = 'set' . $relation->getName();
}
if (!$join->isPrimary()) {
$this->relatedClass = $join->hasLeftTableAlias() ? $join->getLeftTableAlias() : $relation->getLeftTable()->getPhpName();
}
}
// DataObject getters & setters
public function setModelName($modelName)
{
$this->modelName = $modelName;
}
public function getModelName()
{
return $this->modelName;
}
public function setModelPeerName($modelPeerName)
{
$this->modelPeerName = $modelPeerName;
}
public function getModelPeerName()
{
return $this->modelPeerName;
}
public function setIsSingleTableInheritance($isSingleTableInheritance)
{
$this->isSingleTableInheritance = $isSingleTableInheritance;
}
public function isSingleTableInheritance()
{
return $this->isSingleTableInheritance;
}
public function setIsAdd($isAdd)
{
$this->isAdd = $isAdd;;
}
public function isAdd()
{
return $this->isAdd;
}
public function setRelationName($relationName)
{
$this->relationName = $relationName;
}
public function getRelationName()
{
return $this->relationName;
}
public function setRelationMethod($relationMethod)
{
$this->relationMethod = $relationMethod;
}
public function getRelationMethod()
{
return $this->relationMethod;
}
public function setRelatedClass($relatedClass)
{
$this->relatedClass = $relatedClass;
}
public function getRelatedClass()
{
return $this->relatedClass;
}
// Utility methods
public function isPrimary()
{
return null === $this->relatedClass;
}
public function __toString()
{
return sprintf("modelName: %s, relationName: %s, relationMethod: %s, relatedClass: %s", $this->modelName, $this->relationName, $this->relationMethod, $this->relatedClass);
}
}

View file

@ -0,0 +1,170 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* Array formatter for Propel query
* format() returns a PropelArrayCollection of associative arrays
*
* @author Francois Zaninotto
* @version $Revision: 1796 $
* @package propel.runtime.formatter
*/
class PropelArrayFormatter extends PropelFormatter
{
protected $collectionName = 'PropelArrayCollection';
protected $alreadyHydratedObjects = array();
protected $emptyVariable;
public function format(PDOStatement $stmt)
{
$this->checkInit();
if($class = $this->collectionName) {
$collection = new $class();
$collection->setModel($this->class);
$collection->setFormatter($this);
} else {
$collection = array();
}
if ($this->isWithOneToMany() && $this->hasLimit) {
throw new PropelException('Cannot use limit() in conjunction with with() on a one-to-many relationship. Please remove the with() call, or the limit() call.');
}
while ($row = $stmt->fetch(PDO::FETCH_NUM)) {
if ($object = &$this->getStructuredArrayFromRow($row)) {
$collection[] = $object;
}
}
$this->currentObjects = array();
$this->alreadyHydratedObjects = array();
$stmt->closeCursor();
return $collection;
}
public function formatOne(PDOStatement $stmt)
{
$this->checkInit();
$result = null;
while ($row = $stmt->fetch(PDO::FETCH_NUM)) {
if ($object = &$this->getStructuredArrayFromRow($row)) {
$result = &$object;
}
}
$this->currentObjects = array();
$this->alreadyHydratedObjects = array();
$stmt->closeCursor();
return $result;
}
/**
* Formats an ActiveRecord object
*
* @param BaseObject $record the object to format
*
* @return array The original record turned into an array
*/
public function formatRecord($record = null)
{
return $record ? $record->toArray() : array();
}
public function isObjectFormatter()
{
return false;
}
/**
* Hydrates a series of objects from a result row
* The first object to hydrate is the model of the Criteria
* The following objects (the ones added by way of ModelCriteria::with()) are linked to the first one
*
* @param array $row associative array indexed by column number,
* as returned by PDOStatement::fetch(PDO::FETCH_NUM)
*
* @return Array
*/
public function &getStructuredArrayFromRow($row)
{
$col = 0;
// hydrate main object or take it from registry
$mainObjectIsNew = false;
$mainKey = call_user_func(array($this->peer, 'getPrimaryKeyHashFromRow'), $row);
// we hydrate the main object even in case of a one-to-many relationship
// in order to get the $col variable increased anyway
$obj = $this->getSingleObjectFromRow($row, $this->class, $col);
if (!isset($this->alreadyHydratedObjects[$this->class][$mainKey])) {
$this->alreadyHydratedObjects[$this->class][$mainKey] = $obj->toArray();
$mainObjectIsNew = true;
}
$hydrationChain = array();
// related objects added using with()
foreach ($this->getWith() as $relAlias => $modelWith) {
// determine class to use
if ($modelWith->isSingleTableInheritance()) {
$class = call_user_func(array($modelWith->getModelPeerName(), 'getOMClass'), $row, $col, false);
$refl = new ReflectionClass($class);
if ($refl->isAbstract()) {
$col += constant($class . 'Peer::NUM_COLUMNS');
continue;
}
} else {
$class = $modelWith->getModelName();
}
// hydrate related object or take it from registry
$key = call_user_func(array($modelWith->getModelPeerName(), 'getPrimaryKeyHashFromRow'), $row, $col);
// we hydrate the main object even in case of a one-to-many relationship
// in order to get the $col variable increased anyway
$secondaryObject = $this->getSingleObjectFromRow($row, $class, $col);
if (!isset($this->alreadyHydratedObjects[$relAlias][$key])) {
if ($secondaryObject->isPrimaryKeyNull()) {
$this->alreadyHydratedObjects[$relAlias][$key] = array();
} else {
$this->alreadyHydratedObjects[$relAlias][$key] = $secondaryObject->toArray();
}
}
if ($modelWith->isPrimary()) {
$arrayToAugment = &$this->alreadyHydratedObjects[$this->class][$mainKey];
} else {
$arrayToAugment = &$hydrationChain[$modelWith->getRelatedClass()];
}
if ($modelWith->isAdd()) {
if (!isset($arrayToAugment[$modelWith->getRelationName()]) || !in_array($this->alreadyHydratedObjects[$relAlias][$key], $arrayToAugment[$modelWith->getRelationName()])) {
$arrayToAugment[$modelWith->getRelationName()][] = &$this->alreadyHydratedObjects[$relAlias][$key];
}
} else {
$arrayToAugment[$modelWith->getRelationName()] = &$this->alreadyHydratedObjects[$relAlias][$key];
}
$hydrationChain[$relAlias] = &$this->alreadyHydratedObjects[$relAlias][$key];
}
// columns added using withColumn()
foreach ($this->getAsColumns() as $alias => $clause) {
$this->alreadyHydratedObjects[$this->class][$mainKey][$alias] = $row[$col];
$col++;
}
if ($mainObjectIsNew) {
return $this->alreadyHydratedObjects[$this->class][$mainKey];
} else {
// we still need to return a reference to something to avoid a warning
return $emptyVariable;
}
}
}

View file

@ -0,0 +1,202 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* Abstract class for query formatter
*
* @author Francois Zaninotto
* @version $Revision: 1796 $
* @package propel.runtime.formatter
*/
abstract class PropelFormatter
{
protected
$dbName,
$class,
$peer,
$with = array(),
$asColumns = array(),
$hasLimit = false,
$currentObjects = array();
public function __construct(ModelCriteria $criteria = null)
{
if (null !== $criteria) {
$this->init($criteria);
}
}
/**
* Define the hydration schema based on a query object.
* Fills the Formatter's properties using a Criteria as source
*
* @param ModelCriteria $criteria
*
* @return PropelFormatter The current formatter object
*/
public function init(ModelCriteria $criteria)
{
$this->dbName = $criteria->getDbName();
$this->class = $criteria->getModelName();
$this->peer = $criteria->getModelPeerName();
$this->setWith($criteria->getWith());
$this->asColumns = $criteria->getAsColumns();
$this->hasLimit = $criteria->getLimit() != 0;
return $this;
}
// DataObject getters & setters
public function setDbName($dbName)
{
$this->dbName = $dbName;
}
public function getDbName()
{
return $this->dbName;
}
public function setClass($class)
{
$this->class = $class;
}
public function getClass()
{
return $this->class;
}
public function setPeer($peer)
{
$this->peer = $peer;
}
public function getPeer()
{
return $this->peer;
}
public function setWith($withs = array())
{
$this->with = array();
foreach ($withs as $relation => $join) {
$this->with[$relation] = new ModelWith($join);
}
}
public function getWith()
{
return $this->with;
}
public function setAsColumns($asColumns = array())
{
$this->asColumns = $asColumns;
}
public function getAsColumns()
{
return $this->asColumns;
}
public function setHasLimit($hasLimit = false)
{
$this->hasLimit = $hasLimit;
}
public function hasLimit()
{
return $this->hasLimit;
}
/**
* Formats an ActiveRecord object
*
* @param BaseObject $record the object to format
*
* @return BaseObject The original record
*/
public function formatRecord($record = null)
{
return $record;
}
abstract public function format(PDOStatement $stmt);
abstract public function formatOne(PDOStatement $stmt);
abstract public function isObjectFormatter();
public function checkInit()
{
if (null === $this->peer) {
throw new PropelException('You must initialize a formatter object before calling format() or formatOne()');
}
}
public function getTableMap()
{
return Propel::getDatabaseMap($this->dbName)->getTableByPhpName($this->class);
}
protected function isWithOneToMany()
{
foreach ($this->with as $modelWith) {
if ($modelWith->isAdd()) {
return true;
}
}
return false;
}
/**
* Gets the worker object for the class.
* To save memory, we don't create a new object for each row,
* But we keep hydrating a single object per class.
* The column offset in the row is used to index the array of classes
* As there may be more than one object of the same class in the chain
*
* @param int $col Offset of the object in the list of objects to hydrate
* @param string $class Propel model object class
*
* @return BaseObject
*/
protected function getWorkerObject($col, $class)
{
if(isset($this->currentObjects[$col])) {
$this->currentObjects[$col]->clear();
} else {
$this->currentObjects[$col] = new $class();
}
return $this->currentObjects[$col];
}
/**
* Gets a Propel object hydrated from a selection of columns in statement row
*
* @param array $row associative array indexed by column number,
* as returned by PDOStatement::fetch(PDO::FETCH_NUM)
* @param string $class The classname of the object to create
* @param int $col The start column for the hydration (modified)
*
* @return BaseObject
*/
public function getSingleObjectFromRow($row, $class, &$col = 0)
{
$obj = $this->getWorkerObject($col, $class);
$col = $obj->hydrate($row, $col);
return $obj;
}
}

View file

@ -0,0 +1,112 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* Object formatter for Propel query
* format() returns a PropelObjectCollection of Propel model objects
*
* @author Francois Zaninotto
* @version $Revision: 1733 $
* @package propel.runtime.formatter
*/
class PropelObjectFormatter extends PropelFormatter
{
protected $collectionName = 'PropelObjectCollection';
public function format(PDOStatement $stmt)
{
$this->checkInit();
if($class = $this->collectionName) {
$collection = new $class();
$collection->setModel($this->class);
$collection->setFormatter($this);
} else {
$collection = array();
}
if ($this->isWithOneToMany()) {
if ($this->hasLimit) {
throw new PropelException('Cannot use limit() in conjunction with with() on a one-to-many relationship. Please remove the with() call, or the limit() call.');
}
$pks = array();
while ($row = $stmt->fetch(PDO::FETCH_NUM)) {
$object = $this->getAllObjectsFromRow($row);
$pk = $object->getPrimaryKey();
if (!in_array($pk, $pks)) {
$collection[] = $object;
$pks[] = $pk;
}
}
} else {
// only many-to-one relationships
while ($row = $stmt->fetch(PDO::FETCH_NUM)) {
$collection[] = $this->getAllObjectsFromRow($row);
}
}
$stmt->closeCursor();
return $collection;
}
public function formatOne(PDOStatement $stmt)
{
$this->checkInit();
$result = null;
while ($row = $stmt->fetch(PDO::FETCH_NUM)) {
$result = $this->getAllObjectsFromRow($row);
}
$stmt->closeCursor();
return $result;
}
public function isObjectFormatter()
{
return true;
}
/**
* Hydrates a series of objects from a result row
* The first object to hydrate is the model of the Criteria
* The following objects (the ones added by way of ModelCriteria::with()) are linked to the first one
*
* @param array $row associative array indexed by column number,
* as returned by PDOStatement::fetch(PDO::FETCH_NUM)
*
* @return BaseObject
*/
public function getAllObjectsFromRow($row)
{
// main object
list($obj, $col) = call_user_func(array($this->peer, 'populateObject'), $row);
// related objects added using with()
foreach ($this->getWith() as $class => $modelWith) {
list($endObject, $col) = call_user_func(array($modelWith->getModelPeerName(), 'populateObject'), $row, $col);
// as we may be in a left join, the endObject may be empty
// in which case it should not be related to the previous object
if (null === $endObject || $endObject->isPrimaryKeyNull()) {
continue;
}
if (isset($hydrationChain)) {
$hydrationChain[$class] = $endObject;
} else {
$hydrationChain = array($class => $endObject);
}
$startObject = $modelWith->isPrimary() ? $obj : $hydrationChain[$modelWith->getRelatedClass()];
call_user_func(array($startObject, $modelWith->getRelationMethod()), $endObject);
}
// columns added using withColumn()
foreach ($this->getAsColumns() as $alias => $clause) {
$obj->setVirtualColumn($alias, $row[$col]);
$col++;
}
return $obj;
}
}

View file

@ -0,0 +1,96 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* Object formatter for Propel query
* format() returns a PropelOnDemandCollection that hydrates objects as the use iterates on the collection
* This formatter consumes less memory than the PropelObjectFormatter, but doesn't use Instance Pool
*
* @author Francois Zaninotto
* @version $Revision: 1733 $
* @package propel.runtime.formatter
*/
class PropelOnDemandFormatter extends PropelObjectFormatter
{
protected $collectionName = 'PropelOnDemandCollection';
protected $isSingleTableInheritance = false;
public function init(ModelCriteria $criteria)
{
parent::init($criteria);
$this->isSingleTableInheritance = $criteria->getTableMap()->isSingleTableInheritance();
return $this;
}
public function format(PDOStatement $stmt)
{
$this->checkInit();
if ($this->isWithOneToMany()) {
throw new PropelException('PropelOnDemandFormatter cannot hydrate related objects using a one-to-many relationship. Try removing with() from your query.');
}
$class = $this->collectionName;
$collection = new $class();
$collection->setModel($this->class);
$collection->initIterator($this, $stmt);
return $collection;
}
/**
* Hydrates a series of objects from a result row
* The first object to hydrate is the model of the Criteria
* The following objects (the ones added by way of ModelCriteria::with()) are linked to the first one
*
* @param array $row associative array indexed by column number,
* as returned by PDOStatement::fetch(PDO::FETCH_NUM)
*
* @return BaseObject
*/
public function getAllObjectsFromRow($row)
{
$col = 0;
// main object
$class = $this->isSingleTableInheritance ? call_user_func(array($his->peer, 'getOMClass'), $row, $col, false) : $this->class;
$obj = $this->getSingleObjectFromRow($row, $class, $col);
// related objects using 'with'
foreach ($this->getWith() as $modelWith) {
if ($modelWith->isSingleTableInheritance()) {
$class = call_user_func(array($modelWith->getModelPeerName(), 'getOMClass'), $row, $col, false);
$refl = new ReflectionClass($class);
if ($refl->isAbstract()) {
$col += constant($class . 'Peer::NUM_COLUMNS');
continue;
}
} else {
$class = $modelWith->getModelName();
}
$endObject = $this->getSingleObjectFromRow($row, $class, $col);
// as we may be in a left join, the endObject may be empty
// in which case it should not be related to the previous object
if (null === $endObject || $endObject->isPrimaryKeyNull()) {
continue;
}
if (isset($hydrationChain)) {
$hydrationChain[$class] = $endObject;
} else {
$hydrationChain = array($class => $endObject);
}
$startObject = $modelWith->isPrimary() ? $obj : $hydrationChain[$modelWith->getRelatedClass()];
call_user_func(array($startObject, $modelWith->getRelationMethod()), $endObject);
}
foreach ($this->getAsColumns() as $alias => $clause) {
$obj->setVirtualColumn($alias, $row[$col]);
$col++;
}
return $obj;
}
}

View file

@ -0,0 +1,45 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* statement formatter for Propel query
* format() returns a PDO statement
*
* @author Francois Zaninotto
* @version $Revision: 1796 $
* @package propel.runtime.formatter
*/
class PropelStatementFormatter extends PropelFormatter
{
public function format(PDOStatement $stmt)
{
return $stmt;
}
public function formatOne(PDOStatement $stmt)
{
if ($stmt->rowCount() == 0) {
return null;
} else {
return $stmt;
}
}
public function formatRecord($record = null)
{
throw new PropelException('The Statement formatter cannot transform a record into a statement');
}
public function isObjectFormatter()
{
return false;
}
}

View file

@ -0,0 +1,91 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* This is a minimalistic interface that any logging class must implement for Propel.
*
* The API for this interface is based on the PEAR::Log interface. It provides a simple
* API that can be used by Propel independently of Log backend.
*
* PEAR::Log and perhaps the Log API was developed by Chuck Hagenbuch <chuck@horde.org>
* and Jon Parise <jon@php.net>.
*
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 1612 $
* @package propel.runtime.logger
*/
interface BasicLogger
{
/**
* A convenience function for logging an alert event.
*
* @param mixed $message String or Exception object containing the message
* to log.
*/
public function alert($message);
/**
* A convenience function for logging a critical event.
*
* @param mixed $message String or Exception object containing the message
* to log.
*/
public function crit($message);
/**
* A convenience function for logging an error event.
*
* @param mixed $message String or Exception object containing the message
* to log.
*/
public function err($message);
/**
* A convenience function for logging a warning event.
*
* @param mixed $message String or Exception object containing the message
* to log.
*/
public function warning($message);
/**
* A convenience function for logging an critical event.
*
* @param mixed $message String or Exception object containing the message
* to log.
*/
public function notice($message);
/**
* A convenience function for logging an critical event.
*
* @param mixed $message String or Exception object containing the message
* to log.
*/
public function info($message);
/**
* A convenience function for logging a debug event.
*
* @param mixed $message String or Exception object containing the message
* to log.
*/
public function debug($message);
/**
* Primary method to handle logging.
*
* @param mixed $message String or Exception object containing the message
* to log.
* @param int $severity The numeric severity. Defaults to null so that no
* assumptions are made about the logging backend.
*/
public function log($message, $severity = null);
}

View file

@ -0,0 +1,160 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* Mojavi logging adapter for propel
*
* @author Brandon Keepers <brandon@opensoul.org>
* @version $Revision: 1612 $
* @package propel.runtime.logger
*/
class MojaviLogAdapter implements BasicLogger
{
/**
* Instance of mojavi logger
*/
private $logger = null;
/**
* constructor for setting up Mojavi log adapter
*
* @param ErrorLog $logger instance of Mojavi error log obtained by
* calling LogManager::getLogger();
*/
public function __construct($logger = null)
{
$this->logger = $logger;
}
/**
* A convenience function for logging an alert event.
*
* @param mixed $message String or Exception object containing the message
* to log.
*/
public function alert($message)
{
$this->log($message, 'alert');
}
/**
* A convenience function for logging a critical event.
*
* @param mixed $message String or Exception object containing the message
* to log.
*/
public function crit($message)
{
$this->log($message, 'crit');
}
/**
* A convenience function for logging an error event.
*
* @param mixed $message String or Exception object containing the message
* to log.
*/
public function err($message)
{
$this->log($message, 'err');
}
/**
* A convenience function for logging a warning event.
*
* @param mixed $message String or Exception object containing the message
* to log.
*/
public function warning($message)
{
$this->log($message, 'warning');
}
/**
* A convenience function for logging an critical event.
*
* @param mixed $message String or Exception object containing the message
* to log.
*/
public function notice($message)
{
$this->log($message, 'notice');
}
/**
* A convenience function for logging an critical event.
*
* @param mixed $message String or Exception object containing the message
* to log.
*/
public function info($message)
{
$this->log($message, 'info');
}
/**
* A convenience function for logging a debug event.
*
* @param mixed $message String or Exception object containing the message
* to log.
*/
public function debug($message)
{
$this->log($message, 'debug');
}
/**
* Primary method to handle logging.
*
* @param mixed $message String or Exception object containing the message
* to log.
* @param int $severity The numeric severity. Defaults to null so that no
* assumptions are made about the logging backend.
*/
public function log($message, $severity = null)
{
if (is_null($this->logger))
$this->logger = LogManager::getLogger('propel');
switch($severity)
{
case 'crit':
$method = 'fatal';
break;
case 'err':
$method = 'error';
break;
case 'alert':
case 'warning':
$method = 'warning';
break;
case 'notice':
case 'info':
$method = 'info';
break;
case 'debug':
default:
$method = 'debug';
}
// get a backtrace to pass class, function, file, & line to Mojavi logger
$trace = debug_backtrace();
// call the appropriate Mojavi logger method
$this->logger->{$method} (
$message,
$trace[2]['class'],
$trace[2]['function'],
$trace[1]['file'],
$trace[1]['line']
);
}
}

View file

@ -0,0 +1,464 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* ColumnMap is used to model a column of a table in a database.
*
* GENERAL NOTE
* ------------
* The propel.map classes are abstract building-block classes for modeling
* the database at runtime. These classes are similar (a lite version) to the
* propel.engine.database.model classes, which are build-time modeling classes.
* These classes in themselves do not do any database metadata lookups.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author John D. McNally <jmcnally@collab.net> (Torque)
* @version $Revision: 1612 $
* @package propel.runtime.map
*/
class ColumnMap
{
// Propel type of the column
protected $type;
// Size of the column
protected $size = 0;
// Is it a primary key?
protected $pk = false;
// Is null value allowed?
protected $notNull = false;
// The default value for this column
protected $defaultValue;
// Name of the table that this column is related to
protected $relatedTableName = "";
// Name of the column that this column is related to
protected $relatedColumnName = "";
// The TableMap for this column
protected $table;
// The name of the column
protected $columnName;
// The php name of the column
protected $phpName;
// The validators for this column
protected $validators = array();
/**
* Constructor.
*
* @param string $name The name of the column.
* @param TableMap containingTable TableMap of the table this column is in.
*/
public function __construct($name, TableMap $containingTable)
{
$this->columnName = $name;
$this->table = $containingTable;
}
/**
* Get the name of a column.
*
* @return string A String with the column name.
*/
public function getName()
{
return $this->columnName;
}
/**
* Get the table map this column belongs to.
* @return TableMap
*/
public function getTable()
{
return $this->table;
}
/**
* Get the name of the table this column is in.
*
* @return string A String with the table name.
*/
public function getTableName()
{
return $this->table->getName();
}
/**
* Get the table name + column name.
*
* @return string A String with the full column name.
*/
public function getFullyQualifiedName()
{
return $this->getTableName() . "." . $this->columnName;
}
/**
* Set the php anme of this column.
*
* @param string $phpName A string representing the PHP name.
* @return void
*/
public function setPhpName($phpName)
{
$this->phpName = $phpName;
}
/**
* Get the name of a column.
*
* @return string A String with the column name.
*/
public function getPhpName()
{
return $this->phpName;
}
/**
* Set the Propel type of this column.
*
* @param string $type A string representing the Propel type (e.g. PropelColumnTypes::DATE).
* @return void
*/
public function setType($type)
{
$this->type = $type;
}
/**
* Get the Propel type of this column.
*
* @return string A string representing the Propel type (e.g. PropelColumnTypes::DATE).
*/
public function getType()
{
return $this->type;
}
/**
* Get the PDO type of this column.
*
* @return int The PDO::PARMA_* value
*/
public function getPdoType()
{
return PropelColumnTypes::getPdoType($this->type);
}
/**
* Whether this is a BLOB, LONGVARBINARY, or VARBINARY.
* @return boolean
*/
public function isLob()
{
return ($this->type == PropelColumnTypes::BLOB || $this->type == PropelColumnTypes::VARBINARY || $this->type == PropelColumnTypes::LONGVARBINARY);
}
/**
* Whether this is a DATE/TIME/TIMESTAMP column.
*
* @return boolean
* @since 1.3
*/
public function isTemporal()
{
return ($this->type == PropelColumnTypes::TIMESTAMP || $this->type == PropelColumnTypes::DATE || $this->type == PropelColumnTypes::TIME || $this->type == PropelColumnTypes::BU_DATE || $this->type == PropelColumnTypes::BU_TIMESTAMP);
}
/**
* Whether this is a DATE/TIME/TIMESTAMP column that is post-epoch (1970).
*
* PHP cannot handle pre-epoch timestamps well -- hence the need to differentiate
* between epoch and pre-epoch timestamps.
*
* @return boolean
* @deprecated Propel supports non-epoch dates
*/
public function isEpochTemporal()
{
return ($this->type == PropelColumnTypes::TIMESTAMP || $this->type == PropelColumnTypes::DATE || $this->type == PropelColumnTypes::TIME);
}
/**
* Whether this column is numeric (int, decimal, bigint etc).
* @return boolean
*/
public function isNumeric()
{
return ($this->type == PropelColumnTypes::NUMERIC || $this->type == PropelColumnTypes::DECIMAL || $this->type == PropelColumnTypes::TINYINT || $this->type == PropelColumnTypes::SMALLINT || $this->type == PropelColumnTypes::INTEGER || $this->type == PropelColumnTypes::BIGINT || $this->type == PropelColumnTypes::REAL || $this->type == PropelColumnTypes::FLOAT || $this->type == PropelColumnTypes::DOUBLE);
}
/**
* Whether this column is a text column (varchar, char, longvarchar).
* @return boolean
*/
public function isText()
{
return ($this->type == PropelColumnTypes::VARCHAR || $this->type == PropelColumnTypes::LONGVARCHAR || $this->type == PropelColumnTypes::CHAR);
}
/**
* Set the size of this column.
*
* @param int $size An int specifying the size.
* @return void
*/
public function setSize($size)
{
$this->size = $size;
}
/**
* Get the size of this column.
*
* @return int An int specifying the size.
*/
public function getSize()
{
return $this->size;
}
/**
* Set if this column is a primary key or not.
*
* @param boolean $pk True if column is a primary key.
* @return void
*/
public function setPrimaryKey($pk)
{
$this->pk = $pk;
}
/**
* Is this column a primary key?
*
* @return boolean True if column is a primary key.
*/
public function isPrimaryKey()
{
return $this->pk;
}
/**
* Set if this column may be null.
*
* @param boolean nn True if column may be null.
* @return void
*/
public function setNotNull($nn)
{
$this->notNull = $nn;
}
/**
* Is null value allowed ?
*
* @return boolean True if column may not be null.
*/
public function isNotNull()
{
return ($this->notNull || $this->isPrimaryKey());
}
/**
* Sets the default value for this column.
* @param mixed $defaultValue the default value for the column
* @return void
*/
public function setDefaultValue($defaultValue)
{
$this->defaultValue = $defaultValue;
}
/**
* Gets the default value for this column.
* @return mixed String or NULL
*/
public function getDefaultValue()
{
return $this->defaultValue;
}
/**
* Set the foreign key for this column.
*
* @param string tableName The name of the table that is foreign.
* @param string columnName The name of the column that is foreign.
* @return void
*/
public function setForeignKey($tableName, $columnName)
{
if ($tableName && $columnName) {
$this->relatedTableName = $tableName;
$this->relatedColumnName = $columnName;
} else {
$this->relatedTableName = "";
$this->relatedColumnName = "";
}
}
/**
* Is this column a foreign key?
*
* @return boolean True if column is a foreign key.
*/
public function isForeignKey()
{
if ($this->relatedTableName) {
return true;
} else {
return false;
}
}
/**
* Get the RelationMap object for this foreign key
*/
public function getRelation()
{
if(!$this->relatedTableName) return null;
foreach ($this->getTable()->getRelations() as $name => $relation)
{
if($relation->getType() == RelationMap::MANY_TO_ONE)
{
if ($relation->getForeignTable()->getName() == $this->getRelatedTableName()
&& array_key_exists($this->getFullyQualifiedName(), $relation->getColumnMappings()))
{
return $relation;
}
}
}
}
/**
* Get the table.column that this column is related to.
*
* @return string A String with the full name for the related column.
*/
public function getRelatedName()
{
return $this->relatedTableName . "." . $this->relatedColumnName;
}
/**
* Get the table name that this column is related to.
*
* @return string A String with the name for the related table.
*/
public function getRelatedTableName()
{
return $this->relatedTableName;
}
/**
* Get the column name that this column is related to.
*
* @return string A String with the name for the related column.
*/
public function getRelatedColumnName()
{
return $this->relatedColumnName;
}
/**
* Get the TableMap object that this column is related to.
*
* @return TableMap The related TableMap object
* @throws PropelException when called on a column with no foreign key
*/
public function getRelatedTable()
{
if ($this->relatedTableName) {
return $this->table->getDatabaseMap()->getTable($this->relatedTableName);
} else {
throw new PropelException("Cannot fetch RelatedTable for column with no foreign key: " . $this->columnName);
}
}
/**
* Get the TableMap object that this column is related to.
*
* @return ColumnMap The related ColumnMap object
* @throws PropelException when called on a column with no foreign key
*/
public function getRelatedColumn()
{
return $this->getRelatedTable()->getColumn($this->relatedColumnName);
}
public function addValidator($validator)
{
$this->validators[] = $validator;
}
public function hasValidators()
{
return count($this->validators) > 0;
}
public function getValidators()
{
return $this->validators;
}
/**
* Performs DB-specific ignore case, but only if the column type necessitates it.
* @param string $str The expression we want to apply the ignore case formatting to (e.g. the column name).
* @param DBAdapter $db
*/
public function ignoreCase($str, DBAdapter $db)
{
if ($this->isText()) {
return $db->ignoreCase($str);
} else {
return $str;
}
}
/**
* Normalizes the column name, removing table prefix and uppercasing.
*
* article.first_name becomes FIRST_NAME
*
* @param string $name
* @return string Normalized column name.
*/
public static function normalizeName($name)
{
if (false !== ($pos = strpos($name, '.'))) {
$name = substr($name, $pos + 1);
}
$name = strtoupper($name);
return $name;
}
// deprecated methods
/**
* Gets column name
* @deprecated Use getName() instead
* @return string
* @deprecated Use getName() instead.
*/
public function getColumnName()
{
return $this->getName();
}
}

View file

@ -0,0 +1,191 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* DatabaseMap is used to model a database.
*
* GENERAL NOTE
* ------------
* The propel.map classes are abstract building-block classes for modeling
* the database at runtime. These classes are similar (a lite version) to the
* propel.engine.database.model classes, which are build-time modeling classes.
* These classes in themselves do not do any database metadata lookups.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author John D. McNally <jmcnally@collab.net> (Torque)
* @author Daniel Rall <dlr@collab.net> (Torque)
* @version $Revision: 1802 $
* @package propel.runtime.map
*/
class DatabaseMap
{
/** @var string Name of the database. */
protected $name;
/** @var array TableMap[] Tables in the database, using table name as key */
protected $tables = array();
/** @var array TableMap[] Tables in the database, using table phpName as key */
protected $tablesByPhpName = array();
/**
* Constructor.
*
* @param string $name Name of the database.
*/
public function __construct($name)
{
$this->name = $name;
}
/**
* Get the name of this database.
*
* @return string The name of the database.
*/
public function getName()
{
return $this->name;
}
/**
* Add a new table to the database by name.
*
* @param string $tableName The name of the table.
* @return TableMap The newly created TableMap.
*/
public function addTable($tableName)
{
$this->tables[$tableName] = new TableMap($tableName, $this);
return $this->tables[$tableName];
}
/**
* Add a new table object to the database.
*
* @param TableMap $table The table to add
*/
public function addTableObject(TableMap $table)
{
$table->setDatabaseMap($this);
$this->tables[$table->getName()] = $table;
$this->tablesByPhpName[$table->getClassname()] = $table;
}
/**
* Add a new table to the database, using the tablemap class name.
*
* @param string $tableMapClass The name of the table map to add
* @return TableMap The TableMap object
*/
public function addTableFromMapClass($tableMapClass)
{
$table = new $tableMapClass();
if(!$this->hasTable($table->getName())) {
$this->addTableObject($table);
return $table;
} else {
return $this->getTable($table->getName());
}
}
/**
* Does this database contain this specific table?
*
* @param string $name The String representation of the table.
* @return boolean True if the database contains the table.
*/
public function hasTable($name)
{
if ( strpos($name, '.') > 0) {
$name = substr($name, 0, strpos($name, '.'));
}
return array_key_exists($name, $this->tables);
}
/**
* Get a TableMap for the table by name.
*
* @param string $name Name of the table.
* @return TableMap A TableMap
* @throws PropelException if the table is undefined
*/
public function getTable($name)
{
if (!isset($this->tables[$name])) {
throw new PropelException("Cannot fetch TableMap for undefined table: " . $name );
}
return $this->tables[$name];
}
/**
* Get a TableMap[] of all of the tables in the database.
*
* @return array A TableMap[].
*/
public function getTables()
{
return $this->tables;
}
/**
* Get a ColumnMap for the column by name.
* Name must be fully qualified, e.g. book.AUTHOR_ID
*
* @param $qualifiedColumnName Name of the column.
* @return ColumnMap A TableMap
* @throws PropelException if the table is undefined, or if the table is undefined
*/
public function getColumn($qualifiedColumnName)
{
list($tableName, $columnName) = explode('.', $qualifiedColumnName);
return $this->getTable($tableName)->getColumn($columnName, false);
}
// deprecated methods
/**
* Does this database contain this specific table?
*
* @deprecated Use hasTable() instead
* @param string $name The String representation of the table.
* @return boolean True if the database contains the table.
*/
public function containsTable($name)
{
return $this->hasTable($name);
}
public function getTableByPhpName($phpName)
{
if (array_key_exists($phpName, $this->tablesByPhpName)) {
return $this->tablesByPhpName[$phpName];
} else if (class_exists($tmClass = $phpName . 'TableMap')) {
$this->addTableFromMapClass($tmClass);
return $this->tablesByPhpName[$phpName];
} else if (class_exists($tmClass = substr_replace($phpName, '\\map\\', strrpos($phpName, '\\'), 1) . 'TableMap')) {
$this->addTableFromMapClass($tmClass);
return $this->tablesByPhpName[$phpName];
} else {
throw new PropelException("Cannot fetch TableMap for undefined table phpName: " . $phpName);
}
}
/**
* Convenience method to get the DBAdapter registered with Propel for this database.
* @return DBAdapter
* @see Propel::getDB(string)
*/
public function getDBAdapter()
{
return Propel::getDB($this->name);
}
}

View file

@ -0,0 +1,299 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* RelationMap is used to model a database relationship.
*
* GENERAL NOTE
* ------------
* The propel.map classes are abstract building-block classes for modeling
* the database at runtime. These classes are similar (a lite version) to the
* propel.engine.database.model classes, which are build-time modeling classes.
* These classes in themselves do not do any database metadata lookups.
*
* @author Francois Zaninotto
* @version $Revision: 1728 $
* @package propel.runtime.map
*/
class RelationMap
{
const
// types
MANY_TO_ONE = 1,
ONE_TO_MANY = 2,
ONE_TO_ONE = 3,
MANY_TO_MANY = 4,
// representations
LOCAL_TO_FOREIGN = 0,
LEFT_TO_RIGHT = 1;
protected
$name,
$type,
$localTable,
$foreignTable,
$localColumns = array(),
$foreignColumns = array(),
$onUpdate, $onDelete;
/**
* Constructor.
*
* @param string $name Name of the relation.
*/
public function __construct($name)
{
$this->name = $name;
}
/**
* Get the name of this relation.
*
* @return string The name of the relation.
*/
public function getName()
{
return $this->name;
}
/**
* Set the type
*
* @param integer $type The relation type (either self::MANY_TO_ONE, self::ONE_TO_MANY, or self::ONE_TO_ONE)
*/
public function setType($type)
{
$this->type = $type;
}
/**
* Get the type
*
* @return integer the relation type
*/
public function getType()
{
return $this->type;
}
/**
* Set the local table
*
* @param TableMap $table The local table for this relationship
*/
public function setLocalTable($table)
{
$this->localTable = $table;
}
/**
* Get the local table
*
* @return TableMap The local table for this relationship
*/
public function getLocalTable()
{
return $this->localTable;
}
/**
* Set the foreign table
*
* @param TableMap $table The foreign table for this relationship
*/
public function setForeignTable($table)
{
$this->foreignTable = $table;
}
/**
* Get the foreign table
*
* @return TableMap The foreign table for this relationship
*/
public function getForeignTable()
{
return $this->foreignTable;
}
/**
* Get the left table of the relation
*
* @return TableMap The left table for this relationship
*/
public function getLeftTable()
{
return ($this->getType() == RelationMap::MANY_TO_ONE) ? $this->getLocalTable() : $this->getForeignTable();
}
/**
* Get the right table of the relation
*
* @return TableMap The right table for this relationship
*/
public function getRightTable()
{
return ($this->getType() == RelationMap::MANY_TO_ONE) ? $this->getForeignTable() : $this->getLocalTable();
}
/**
* Add a column mapping
*
* @param ColumnMap $local The local column
* @param ColumnMap $foreign The foreign column
*/
public function addColumnMapping(ColumnMap $local, ColumnMap $foreign)
{
$this->localColumns[] = $local;
$this->foreignColumns[] = $foreign;
}
/**
* Get an associative array mapping local column names to foreign column names
* The arrangement of the returned array depends on the $direction parameter:
* - If the value is RelationMap::LOCAL_TO_FOREIGN, then the returned array is local => foreign
* - If the value is RelationMap::LEFT_TO_RIGHT, then the returned array is left => right
*
* @param int $direction How the associative array must return columns
* @return Array Associative array (local => foreign) of fully qualified column names
*/
public function getColumnMappings($direction = RelationMap::LOCAL_TO_FOREIGN)
{
$h = array();
if ($direction == RelationMap::LEFT_TO_RIGHT && $this->getType() == RelationMap::MANY_TO_ONE) {
$direction = RelationMap::LOCAL_TO_FOREIGN;
}
for ($i=0, $size=count($this->localColumns); $i < $size; $i++) {
if ($direction == RelationMap::LOCAL_TO_FOREIGN) {
$h[$this->localColumns[$i]->getFullyQualifiedName()] = $this->foreignColumns[$i]->getFullyQualifiedName();
} else {
$h[$this->foreignColumns[$i]->getFullyQualifiedName()] = $this->localColumns[$i]->getFullyQualifiedName();
}
}
return $h;
}
/**
* Returns true if the relation has more than one column mapping
*
* @return boolean
*/
public function isComposite()
{
return $this->countColumnMappings() > 1;
}
/**
* Return the number of column mappings
*
* @return int
*/
public function countColumnMappings()
{
return count($this->localColumns);
}
/**
* Get the local columns
*
* @return Array list of ColumnMap objects
*/
public function getLocalColumns()
{
return $this->localColumns;
}
/**
* Get the foreign columns
*
* @return Array list of ColumnMap objects
*/
public function getForeignColumns()
{
return $this->foreignColumns;
}
/**
* Get the left columns of the relation
*
* @return array of ColumnMap objects
*/
public function getLeftColumns()
{
return ($this->getType() == RelationMap::MANY_TO_ONE) ? $this->getLocalColumns() : $this->getForeignColumns();
}
/**
* Get the right columns of the relation
*
* @return array of ColumnMap objects
*/
public function getRightColumns()
{
return ($this->getType() == RelationMap::MANY_TO_ONE) ? $this->getForeignColumns() : $this->getLocalColumns();
}
/**
* Set the onUpdate behavior
*
* @param string $onUpdate
*/
public function setOnUpdate($onUpdate)
{
$this->onUpdate = $onUpdate;
}
/**
* Get the onUpdate behavior
*
* @return integer the relation type
*/
public function getOnUpdate()
{
return $this->onUpdate;
}
/**
* Set the onDelete behavior
*
* @param string $onDelete
*/
public function setOnDelete($onDelete)
{
$this->onDelete = $onDelete;
}
/**
* Get the onDelete behavior
*
* @return integer the relation type
*/
public function getOnDelete()
{
return $this->onDelete;
}
/**
* Gets the symmetrical relation
*
* @return RelationMap
*/
public function getSymmetricalRelation()
{
$localMapping = array($this->getLeftColumns(), $this->getRightColumns());
foreach ($this->getRightTable()->getRelations() as $relation) {
if ($localMapping == array($relation->getRightColumns(), $relation->getLeftColumns())) {
return $relation;
}
}
}
}

View file

@ -0,0 +1,712 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* TableMap is used to model a table in a database.
*
* GENERAL NOTE
* ------------
* The propel.map classes are abstract building-block classes for modeling
* the database at runtime. These classes are similar (a lite version) to the
* propel.engine.database.model classes, which are build-time modeling classes.
* These classes in themselves do not do any database metadata lookups.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author John D. McNally <jmcnally@collab.net> (Torque)
* @author Daniel Rall <dlr@finemaltcoding.com> (Torque)
* @version $Revision: 1612 $
* @package propel.runtime.map
*/
class TableMap
{
/**
* Columns in the table
* @var array TableMap[]
*/
protected $columns = array();
/**
* Columns in the table, using table phpName as key
* @var array TableMap[]
*/
protected $columnsByPhpName = array();
// The database this table belongs to
protected $dbMap;
// The name of the table
protected $tableName;
// The PHP name of the table
protected $phpName;
// The Classname for this table
protected $classname;
// The Package for this table
protected $package;
// Whether to use an id generator for pkey
protected $useIdGenerator;
// Whether the table uses single table inheritance
protected $isSingleTableInheritance = false;
// The primary key columns in the table
protected $primaryKeys = array();
// The foreign key columns in the table
protected $foreignKeys = array();
// The relationships in the table
protected $relations = array();
// Relations are lazy loaded. This property tells if the relations are loaded or not
protected $relationsBuilt = false;
// Object to store information that is needed if the for generating primary keys
protected $pkInfo;
/**
* Construct a new TableMap.
*
*/
public function __construct($name = null, $dbMap = null)
{
if (null !== $name) {
$this->setName($name);
}
if (null !== $dbMap) {
$this->setDatabaseMap($dbMap);
}
$this->initialize();
}
/**
* Initialize the TableMap to build columns, relations, etc
* This method should be overridden by descendents
*/
public function initialize()
{
}
/**
* Set the DatabaseMap containing this TableMap.
*
* @param DatabaseMap $dbMap A DatabaseMap.
*/
public function setDatabaseMap(DatabaseMap $dbMap)
{
$this->dbMap = $dbMap;
}
/**
* Get the DatabaseMap containing this TableMap.
*
* @return DatabaseMap A DatabaseMap.
*/
public function getDatabaseMap()
{
return $this->dbMap;
}
/**
* Set the name of the Table.
*
* @param string $name The name of the table.
*/
public function setName($name)
{
$this->tableName = $name;
}
/**
* Get the name of the Table.
*
* @return string A String with the name of the table.
*/
public function getName()
{
return $this->tableName;
}
/**
* Set the PHP name of the Table.
*
* @param string $phpName The PHP Name for this table
*/
public function setPhpName($phpName)
{
$this->phpName = $phpName;
}
/**
* Get the PHP name of the Table.
*
* @return string A String with the name of the table.
*/
public function getPhpName()
{
return $this->phpName;
}
/**
* Set the Classname of the Table. Could be useful for calling
* Peer and Object methods dynamically.
* @param string $classname The Classname
*/
public function setClassname($classname)
{
$this->classname = $classname;
}
/**
* Get the Classname of the Propel Class belonging to this table.
* @return string
*/
public function getClassname()
{
return $this->classname;
}
/**
* Get the Peer Classname of the Propel Class belonging to this table.
* @return string
*/
public function getPeerClassname()
{
return constant($this->classname . '::PEER');
}
/**
* Set the Package of the Table
*
* @param string $package The Package
*/
public function setPackage($package)
{
$this->package = $package;
}
/**
* Get the Package of the table.
* @return string
*/
public function getPackage()
{
return $this->package;
}
/**
* Set whether or not to use Id generator for primary key.
* @param boolean $bit
*/
public function setUseIdGenerator($bit)
{
$this->useIdGenerator = $bit;
}
/**
* Whether to use Id generator for primary key.
* @return boolean
*/
public function isUseIdGenerator()
{
return $this->useIdGenerator;
}
/**
* Set whether or not to this table uses single table inheritance
* @param boolean $bit
*/
public function setSingleTableInheritance($bit)
{
$this->isSingleTableInheritance = $bit;
}
/**
* Whether this table uses single table inheritance
* @return boolean
*/
public function isSingleTableInheritance()
{
return $this->isSingleTableInheritance;
}
/**
* Sets the pk information needed to generate a key
*
* @param $pkInfo information needed to generate a key
*/
public function setPrimaryKeyMethodInfo($pkInfo)
{
$this->pkInfo = $pkInfo;
}
/**
* Get the information used to generate a primary key
*
* @return An Object.
*/
public function getPrimaryKeyMethodInfo()
{
return $this->pkInfo;
}
/**
* Add a column to the table.
*
* @param string name A String with the column name.
* @param string $type A string specifying the Propel type.
* @param boolean $isNotNull Whether column does not allow NULL values.
* @param int $size An int specifying the size.
* @param boolean $pk True if column is a primary key.
* @param string $fkTable A String with the foreign key table name.
* @param $fkColumn A String with the foreign key column name.
* @param string $defaultValue The default value for this column.
* @return ColumnMap The newly created column.
*/
public function addColumn($name, $phpName, $type, $isNotNull = false, $size = null, $defaultValue = null, $pk = false, $fkTable = null, $fkColumn = null)
{
$col = new ColumnMap($name, $this);
$col->setType($type);
$col->setSize($size);
$col->setPhpName($phpName);
$col->setNotNull($isNotNull);
$col->setDefaultValue($defaultValue);
if ($pk) {
$col->setPrimaryKey(true);
$this->primaryKeys[$name] = $col;
}
if ($fkTable && $fkColumn) {
$col->setForeignKey($fkTable, $fkColumn);
$this->foreignKeys[$name] = $col;
}
$this->columns[$name] = $col;
$this->columnsByPhpName[$phpName] = $col;
return $col;
}
/**
* Add a pre-created column to this table. It will replace any
* existing column.
*
* @param ColumnMap $cmap A ColumnMap.
* @return ColumnMap The added column map.
*/
public function addConfiguredColumn($cmap)
{
$this->columns[ $cmap->getColumnName() ] = $cmap;
return $cmap;
}
/**
* Does this table contain the specified column?
*
* @param mixed $name name of the column or ColumnMap instance
* @param boolean $normalize Normalize the column name (if column name not like FIRST_NAME)
* @return boolean True if the table contains the column.
*/
public function hasColumn($name, $normalize = true)
{
if ($name instanceof ColumnMap) {
$name = $name->getColumnName();
} else if($normalize) {
$name = ColumnMap::normalizeName($name);
}
return isset($this->columns[$name]);
}
/**
* Get a ColumnMap for the table.
*
* @param string $name A String with the name of the table.
* @param boolean $normalize Normalize the column name (if column name not like FIRST_NAME)
* @return ColumnMap A ColumnMap.
* @throws PropelException if the column is undefined
*/
public function getColumn($name, $normalize = true)
{
if ($normalize) {
$name = ColumnMap::normalizeName($name);
}
if (!$this->hasColumn($name, false)) {
throw new PropelException("Cannot fetch ColumnMap for undefined column: " . $name);
}
return $this->columns[$name];
}
/**
* Does this table contain the specified column?
*
* @param mixed $phpName name of the column
* @return boolean True if the table contains the column.
*/
public function hasColumnByPhpName($phpName)
{
return isset($this->columnsByPhpName[$phpName]);
}
/**
* Get a ColumnMap for the table.
*
* @param string $phpName A String with the name of the table.
* @return ColumnMap A ColumnMap.
* @throws PropelException if the column is undefined
*/
public function getColumnByPhpName($phpName)
{
if (!isset($this->columnsByPhpName[$phpName])) {
throw new PropelException("Cannot fetch ColumnMap for undefined column phpName: " . $phpName);
}
return $this->columnsByPhpName[$phpName];
}
/**
* Get a ColumnMap[] of the columns in this table.
*
* @return array A ColumnMap[].
*/
public function getColumns()
{
return $this->columns;
}
/**
* Add a primary key column to this Table.
*
* @param string $columnName A String with the column name.
* @param string $type A string specifying the Propel type.
* @param boolean $isNotNull Whether column does not allow NULL values.
* @param $size An int specifying the size.
* @return ColumnMap Newly added PrimaryKey column.
*/
public function addPrimaryKey($columnName, $phpName, $type, $isNotNull = false, $size = null, $defaultValue = null)
{
return $this->addColumn($columnName, $phpName, $type, $isNotNull, $size, $defaultValue, true, null, null);
}
/**
* Add a foreign key column to the table.
*
* @param string $columnName A String with the column name.
* @param string $type A string specifying the Propel type.
* @param string $fkTable A String with the foreign key table name.
* @param string $fkColumn A String with the foreign key column name.
* @param boolean $isNotNull Whether column does not allow NULL values.
* @param int $size An int specifying the size.
* @param string $defaultValue The default value for this column.
* @return ColumnMap Newly added ForeignKey column.
*/
public function addForeignKey($columnName, $phpName, $type, $fkTable, $fkColumn, $isNotNull = false, $size = 0, $defaultValue = null)
{
return $this->addColumn($columnName, $phpName, $type, $isNotNull, $size, $defaultValue, false, $fkTable, $fkColumn);
}
/**
* Add a foreign primary key column to the table.
*
* @param string $columnName A String with the column name.
* @param string $type A string specifying the Propel type.
* @param string $fkTable A String with the foreign key table name.
* @param string $fkColumn A String with the foreign key column name.
* @param boolean $isNotNull Whether column does not allow NULL values.
* @param int $size An int specifying the size.
* @param string $defaultValue The default value for this column.
* @return ColumnMap Newly created foreign pkey column.
*/
public function addForeignPrimaryKey($columnName, $phpName, $type, $fkTable, $fkColumn, $isNotNull = false, $size = 0, $defaultValue = null)
{
return $this->addColumn($columnName, $phpName, $type, $isNotNull, $size, $defaultValue, true, $fkTable, $fkColumn);
}
/**
* Returns array of ColumnMap objects that make up the primary key for this table
*
* @return array ColumnMap[]
*/
public function getPrimaryKeys()
{
return $this->primaryKeys;
}
/**
* Returns array of ColumnMap objects that are foreign keys for this table
*
* @return array ColumnMap[]
*/
public function getForeignKeys()
{
return $this->foreignKeys;
}
/**
* Add a validator to a table's column
*
* @param string $columnName The name of the validator's column
* @param string $name The rule name of this validator
* @param string $classname The dot-path name of class to use (e.g. myapp.propel.MyValidator)
* @param string $value
* @param string $message The error message which is returned on invalid values
* @return void
*/
public function addValidator($columnName, $name, $classname, $value, $message)
{
if (false !== ($pos = strpos($columnName, '.'))) {
$columnName = substr($columnName, $pos + 1);
}
$col = $this->getColumn($columnName);
if ($col !== null) {
$validator = new ValidatorMap($col);
$validator->setName($name);
$validator->setClass($classname);
$validator->setValue($value);
$validator->setMessage($message);
$col->addValidator($validator);
}
}
/**
* Build relations
* Relations are lazy loaded for performance reasons
* This method should be overridden by descendents
*/
public function buildRelations()
{
}
/**
* Adds a RelationMap to the table
*
* @param string $name The relation name
* @param string $tablePhpName The related table name
* @param integer $type The relation type (either RelationMap::MANY_TO_ONE, RelationMap::ONE_TO_MANY, or RelationMAp::ONE_TO_ONE)
* @param array $columnMapping An associative array mapping column names (local => foreign)
* @return RelationMap the built RelationMap object
*/
public function addRelation($name, $tablePhpName, $type, $columnMapping = array(), $onDelete = null, $onUpdate = null)
{
// note: using phpName for the second table allows the use of DatabaseMap::getTableByPhpName()
// and this method autoloads the TableMap if the table isn't loaded yet
$relation = new RelationMap($name);
$relation->setType($type);
$relation->setOnUpdate($onUpdate);
$relation->setOnDelete($onDelete);
// set tables
if ($type == RelationMap::MANY_TO_ONE) {
$relation->setLocalTable($this);
$relation->setForeignTable($this->dbMap->getTableByPhpName($tablePhpName));
} else {
$relation->setLocalTable($this->dbMap->getTableByPhpName($tablePhpName));
$relation->setForeignTable($this);
$columnMapping = array_flip($columnMapping);
}
// set columns
foreach ($columnMapping as $local => $foreign) {
$relation->addColumnMapping(
$relation->getLocalTable()->getColumn($local),
$relation->getForeignTable()->getColumn($foreign)
);
}
$this->relations[$name] = $relation;
return $relation;
}
/**
* Gets a RelationMap of the table by relation name
* This method will build the relations if they are not built yet
*
* @param String $name The relation name
* @return boolean true if the relation exists
*/
public function hasRelation($name)
{
return array_key_exists($name, $this->getRelations());
}
/**
* Gets a RelationMap of the table by relation name
* This method will build the relations if they are not built yet
*
* @param String $name The relation name
* @return RelationMap The relation object
* @throws PropelException When called on an inexistent relation
*/
public function getRelation($name)
{
if (!array_key_exists($name, $this->getRelations()))
{
throw new PropelException('Calling getRelation() on an unknown relation, ' . $name);
}
return $this->relations[$name];
}
/**
* Gets the RelationMap objects of the table
* This method will build the relations if they are not built yet
*
* @return Array list of RelationMap objects
*/
public function getRelations()
{
if(!$this->relationsBuilt)
{
$this->buildRelations();
$this->relationsBuilt = true;
}
return $this->relations;
}
/**
*
* Gets the list of behaviors registered for this table
*
* @return array
*/
public function getBehaviors()
{
return array();
}
// Deprecated methods and attributres, to be removed
/**
* Does this table contain the specified column?
*
* @deprecated Use hasColumn instead
* @param mixed $name name of the column or ColumnMap instance
* @param boolean $normalize Normalize the column name (if column name not like FIRST_NAME)
* @return boolean True if the table contains the column.
*/
public function containsColumn($name, $normalize = true)
{
return $this->hasColumn($name, $normalize);
}
/**
* Normalizes the column name, removing table prefix and uppercasing.
* article.first_name becomes FIRST_NAME
*
* @deprecated Use ColumnMap::normalizeColumName() instead
* @param string $name
* @return string Normalized column name.
*/
protected function normalizeColName($name)
{
return ColumnMap::normalizeName($name);
}
/**
* Returns array of ColumnMap objects that make up the primary key for this table.
*
* @deprecated Use getPrimaryKeys instead
* @return array ColumnMap[]
*/
public function getPrimaryKeyColumns()
{
return array_values($this->primaryKeys);
}
//---Utility methods for doing intelligent lookup of table names
/**
* The prefix on the table name.
* @deprecated Not used anywhere in Propel
*/
private $prefix;
/**
* Get table prefix name.
*
* @deprecated Not used anywhere in Propel
* @return string A String with the prefix.
*/
public function getPrefix()
{
return $this->prefix;
}
/**
* Set table prefix name.
*
* @deprecated Not used anywhere in Propel
* @param string $prefix The prefix for the table name (ie: SCARAB for
* SCARAB_PROJECT).
* @return void
*/
public function setPrefix($prefix)
{
$this->prefix = $prefix;
}
/**
* Tell me if i have PREFIX in my string.
*
* @deprecated Not used anywhere in Propel
* @param data A String.
* @return boolean True if prefix is contained in data.
*/
protected function hasPrefix($data)
{
return (strpos($data, $this->prefix) === 0);
}
/**
* Removes the PREFIX if found
*
* @deprecated Not used anywhere in Propel
* @param string $data A String.
* @return string A String with data, but with prefix removed.
*/
protected function removePrefix($data)
{
return $this->hasPrefix($data) ? substr($data, strlen($this->prefix)) : $data;
}
/**
* Removes the PREFIX, removes the underscores and makes
* first letter caps.
*
* SCARAB_FOO_BAR becomes FooBar.
*
* @deprecated Not used anywhere in Propel. At buildtime, use Column::generatePhpName() for that purpose
* @param data A String.
* @return string A String with data processed.
*/
public final function removeUnderScores($data)
{
$out = '';
$tmp = $this->removePrefix($data);
$tok = strtok($tmp, '_');
while ($tok) {
$out .= ucfirst($tok);
$tok = strtok('_');
}
return $out;
}
/**
* Makes the first letter caps and the rest lowercase.
*
* @deprecated Not used anywhere in Propel.
* @param string $data A String.
* @return string A String with data processed.
*/
private function firstLetterCaps($data)
{
return(ucfirst(strtolower($data)));
}
}

View file

@ -0,0 +1,92 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* ValidatorMap is used to model a column validator.
*
* GENERAL NOTE
* ------------
* The propel.map classes are abstract building-block classes for modeling
* the database at runtime. These classes are similar (a lite version) to the
* propel.engine.database.model classes, which are build-time modeling classes.
* These classes in themselves do not do any database metadata lookups.
*
* @author Michael Aichler <aichler@mediacluster.de>
* @version $Revision: 1612 $
* @package propel.runtime.map
*/
class ValidatorMap
{
/** rule name of this validator */
private $name;
/** the dot-path to class to use for validator */
private $classname;
/** value to check against */
private $value;
/** execption message thrown on invalid input */
private $message;
/** related column */
private $column;
public function __construct($containingColumn)
{
$this->column = $containingColumn;
}
public function getColumn()
{
return $this->column;
}
public function getColumnName()
{
return $this->column->getColumnName();
}
public function setName($name)
{
$this->name = $name;
}
public function setClass($classname)
{
$this->classname = $classname;
}
public function setValue($value)
{
$this->value = $value;
}
public function setMessage($message)
{
$this->message = $message;
}
public function getName()
{
return $this->name;
}
public function getClass()
{
return $this->classname;
}
public function getValue()
{
return $this->value;
}
public function getMessage()
{
return $this->message;
}
}

View file

@ -0,0 +1,319 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* This class contains attributes and methods that are used by all
* business objects within the system.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Frank Y. Kim <frank.kim@clearink.com> (Torque)
* @author John D. McNally <jmcnally@collab.net> (Torque)
* @version $Revision: 1673 $
* @package propel.runtime.om
*/
abstract class BaseObject
{
/**
* attribute to determine if this object has previously been saved.
* @var boolean
*/
protected $_new = true;
/**
* attribute to determine whether this object has been deleted.
* @var boolean
*/
protected $_deleted = false;
/**
* The columns that have been modified in current object.
* Tracking modified columns allows us to only update modified columns.
* @var array
*/
protected $modifiedColumns = array();
/**
* The (virtual) columns that are added at runtime
* The formatters can add supplementary columns based on a resultset
* @var array
*/
protected $virtualColumns = array();
/**
* Empty constructor (this allows people with their own BaseObject implementation to use its constructor)
*/
public function __construct() {
}
/**
* Returns whether the object has been modified.
*
* @return boolean True if the object has been modified.
*/
public function isModified()
{
return !empty($this->modifiedColumns);
}
/**
* Has specified column been modified?
*
* @param string $col column fully qualified name (BasePeer::TYPE_COLNAME), e.g. Book::AUTHOR_ID
* @return boolean True if $col has been modified.
*/
public function isColumnModified($col)
{
return in_array($col, $this->modifiedColumns);
}
/**
* Get the columns that have been modified in this object.
* @return array A unique list of the modified column names for this object.
*/
public function getModifiedColumns()
{
return array_unique($this->modifiedColumns);
}
/**
* Returns whether the object has ever been saved. This will
* be false, if the object was retrieved from storage or was created
* and then saved.
*
* @return true, if the object has never been persisted.
*/
public function isNew()
{
return $this->_new;
}
/**
* Setter for the isNew attribute. This method will be called
* by Propel-generated children and Peers.
*
* @param boolean $b the state of the object.
*/
public function setNew($b)
{
$this->_new = (boolean) $b;
}
/**
* Whether this object has been deleted.
* @return boolean The deleted state of this object.
*/
public function isDeleted()
{
return $this->_deleted;
}
/**
* Specify whether this object has been deleted.
* @param boolean $b The deleted state of this object.
* @return void
*/
public function setDeleted($b)
{
$this->_deleted = (boolean) $b;
}
/**
* Code to be run before persisting the object
* @param PropelPDO $con
* @return bloolean
*/
public function preSave(PropelPDO $con = null)
{
return true;
}
/**
* Code to be run after persisting the object
* @param PropelPDO $con
*/
public function postSave(PropelPDO $con = null) { }
/**
* Code to be run before inserting to database
* @param PropelPDO $con
* @return boolean
*/
public function preInsert(PropelPDO $con = null)
{
return true;
}
/**
* Code to be run after inserting to database
* @param PropelPDO $con
*/
public function postInsert(PropelPDO $con = null) { }
/**
* Code to be run before updating the object in database
* @param PropelPDO $con
* @return boolean
*/
public function preUpdate(PropelPDO $con = null)
{
return true;
}
/**
* Code to be run after updating the object in database
* @param PropelPDO $con
*/
public function postUpdate(PropelPDO $con = null) { }
/**
* Code to be run before deleting the object in database
* @param PropelPDO $con
* @return boolean
*/
public function preDelete(PropelPDO $con = null)
{
return true;
}
/**
* Code to be run after deleting the object in database
* @param PropelPDO $con
*/
public function postDelete(PropelPDO $con = null) { }
/**
* Sets the modified state for the object to be false.
* @param string $col If supplied, only the specified column is reset.
* @return void
*/
public function resetModified($col = null)
{
if ($col !== null) {
while (($offset = array_search($col, $this->modifiedColumns)) !== false) {
array_splice($this->modifiedColumns, $offset, 1);
}
} else {
$this->modifiedColumns = array();
}
}
/**
* Compares this with another <code>BaseObject</code> instance. If
* <code>obj</code> is an instance of <code>BaseObject</code>, delegates to
* <code>equals(BaseObject)</code>. Otherwise, returns <code>false</code>.
*
* @param obj The object to compare to.
* @return Whether equal to the object specified.
*/
public function equals($obj)
{
$thisclazz = get_class($this);
if (is_object($obj) && $obj instanceof $thisclazz) {
if ($this === $obj) {
return true;
} elseif ($this->getPrimaryKey() === null || $obj->getPrimaryKey() === null) {
return false;
} else {
return ($this->getPrimaryKey() === $obj->getPrimaryKey());
}
} else {
return false;
}
}
/**
* If the primary key is not <code>null</code>, return the hashcode of the
* primary key. Otherwise calls <code>Object.hashCode()</code>.
*
* @return int Hashcode
*/
public function hashCode()
{
$ok = $this->getPrimaryKey();
if ($ok === null) {
return crc32(serialize($this));
}
return crc32(serialize($ok)); // serialize because it could be an array ("ComboKey")
}
/**
* Get the associative array of the virtual columns in this object
*
* @param string $name The virtual column name
*
* @return array
*/
public function getVirtualColumns()
{
return $this->virtualColumns;
}
/**
* Checks the existence of a virtual column in this object
*
* @return boolean
*/
public function hasVirtualColumn($name)
{
return array_key_exists($name, $this->virtualColumns);
}
/**
* Get the value of a virtual column in this object
*
* @return mixed
*/
public function getVirtualColumn($name)
{
if (!$this->hasVirtualColumn($name)) {
throw new PropelException('Cannot get value of inexistent virtual column ' . $name);
}
return $this->virtualColumns[$name];
}
/**
* Get the value of a virtual column in this object
*
* @param string $name The virtual column name
* @param mixed $value The value to give to the virtual column
*
* @return BaseObject The current object, for fluid interface
*/
public function setVirtualColumn($name, $value)
{
$this->virtualColumns[$name] = $value;
return $this;
}
/**
* Logs a message using Propel::log().
*
* @param string $msg
* @param int $priority One of the Propel::LOG_* logging levels
* @return boolean
*/
protected function log($msg, $priority = Propel::LOG_INFO)
{
return Propel::log(get_class($this) . ': ' . $msg, $priority);
}
/**
* Clean up internal collections prior to serializing
* Avoids recursive loops that turn into segmentation faults when serializing
*/
public function __sleep()
{
$this->clearAllReferences();
return array_keys(get_object_vars($this));
}
}

View file

@ -0,0 +1,86 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* Pre-order node iterator for Node objects.
*
* @author Heltem <heltem@o2php.com>
* @version $Revision: 1612 $
* @package propel.runtime.om
*/
class NestedSetRecursiveIterator implements RecursiveIterator
{
protected $topNode = null;
protected $curNode = null;
public function __construct($node)
{
$this->topNode = $node;
$this->curNode = $node;
}
public function rewind()
{
$this->curNode = $this->topNode;
}
public function valid()
{
return ($this->curNode !== null);
}
public function current()
{
return $this->curNode;
}
public function key()
{
$method = method_exists($this->curNode, 'getPath') ? 'getPath' : 'getAncestors';
$key = array();
foreach ($this->curNode->$method() as $node) {
$key[] = $node->getPrimaryKey();
}
return implode('.', $key);
}
public function next()
{
$nextNode = null;
$method = method_exists($this->curNode, 'retrieveNextSibling') ? 'retrieveNextSibling' : 'getNextSibling';
if ($this->valid()) {
while (null === $nextNode) {
if (null === $this->curNode) {
break;
}
if ($this->curNode->hasNextSibling()) {
$nextNode = $this->curNode->$method();
} else {
break;
}
}
$this->curNode = $nextNode;
}
return $this->curNode;
}
public function hasChildren()
{
return $this->curNode->hasChildren();
}
public function getChildren()
{
$method = method_exists($this->curNode, 'retrieveFirstChild') ? 'retrieveFirstChild' : 'getFirstChild';
return new NestedSetRecursiveIterator($this->curNode->$method());
}
}

View file

@ -0,0 +1,324 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* This interface defines methods that must be implemented by all
* business objects within the system to handle Node object.
*
* @author Heltem <heltem@o2php.com> (Propel)
* @version $Revision: 1612 $
* @package propel.runtime.om
*/
interface NodeObject extends IteratorAggregate
{
/**
* If object is saved without left/right values, set them as undefined (0)
*
* @param PropelPDO $con Connection to use.
* @return void
* @throws PropelException
*/
public function save(PropelPDO $con = null);
/**
* Delete node and descendants
*
* @param PropelPDO $con Connection to use.
* @return void
* @throws PropelException
*/
public function delete(PropelPDO $con = null);
/**
* Sets node properties to make it a root node.
*
* @return object The current object (for fluent API support)
* @throws PropelException
*/
public function makeRoot();
/**
* Gets the level if set, otherwise calculates this and returns it
*
* @param PropelPDO $con Connection to use.
* @return int
*/
public function getLevel(PropelPDO $con = null);
/**
* Get the path to the node in the tree
*
* @param PropelPDO $con Connection to use.
* @return array
*/
public function getPath(PropelPDO $con = null);
/**
* Gets the number of children for the node (direct descendants)
*
* @param PropelPDO $con Connection to use.
* @return int
*/
public function getNumberOfChildren(PropelPDO $con = null);
/**
* Gets the total number of desceandants for the node
*
* @param PropelPDO $con Connection to use.
* @return int
*/
public function getNumberOfDescendants(PropelPDO $con = null);
/**
* Gets the children for the node
*
* @param PropelPDO $con Connection to use.
* @return array
*/
public function getChildren(PropelPDO $con = null);
/**
* Gets the descendants for the node
*
* @param PropelPDO $con Connection to use.
* @return array
*/
public function getDescendants(PropelPDO $con = null);
/**
* Sets the level of the node in the tree
*
* @param int $v new value
* @return object The current object (for fluent API support)
*/
public function setLevel($level);
/**
* Sets the children array of the node in the tree
*
* @param array of Node $children array of Propel node object
* @return object The current object (for fluent API support)
*/
public function setChildren(array $children);
/**
* Sets the parentNode of the node in the tree
*
* @param Node $parent Propel node object
* @return object The current object (for fluent API support)
*/
public function setParentNode(NodeObject $parent = null);
/**
* Sets the previous sibling of the node in the tree
*
* @param Node $node Propel node object
* @return object The current object (for fluent API support)
*/
public function setPrevSibling(NodeObject $node = null);
/**
* Sets the next sibling of the node in the tree
*
* @param Node $node Propel node object
* @return object The current object (for fluent API support)
*/
public function setNextSibling(NodeObject $node = null);
/**
* Determines if the node is the root node
*
* @return bool
*/
public function isRoot();
/**
* Determines if the node is a leaf node
*
* @return bool
*/
public function isLeaf();
/**
* Tests if object is equal to $node
*
* @param object $node Propel object for node to compare to
* @return bool
*/
public function isEqualTo(NodeObject $node);
/**
* Tests if object has an ancestor
*
* @param PropelPDO $con Connection to use.
* @return bool
*/
public function hasParent(PropelPDO $con = null);
/**
* Determines if the node has children / descendants
*
* @return bool
*/
public function hasChildren();
/**
* Determines if the node has previous sibling
*
* @param PropelPDO $con Connection to use.
* @return bool
*/
public function hasPrevSibling(PropelPDO $con = null);
/**
* Determines if the node has next sibling
*
* @param PropelPDO $con Connection to use.
* @return bool
*/
public function hasNextSibling(PropelPDO $con = null);
/**
* Gets ancestor for the given node if it exists
*
* @param PropelPDO $con Connection to use.
* @return mixed Propel object if exists else false
*/
public function retrieveParent(PropelPDO $con = null);
/**
* Gets first child if it exists
*
* @param PropelPDO $con Connection to use.
* @return mixed Propel object if exists else false
*/
public function retrieveFirstChild(PropelPDO $con = null);
/**
* Gets last child if it exists
*
* @param PropelPDO $con Connection to use.
* @return mixed Propel object if exists else false
*/
public function retrieveLastChild(PropelPDO $con = null);
/**
* Gets prev sibling for the given node if it exists
*
* @param PropelPDO $con Connection to use.
* @return mixed Propel object if exists else false
*/
public function retrievePrevSibling(PropelPDO $con = null);
/**
* Gets next sibling for the given node if it exists
*
* @param PropelPDO $con Connection to use.
* @return mixed Propel object if exists else false
*/
public function retrieveNextSibling(PropelPDO $con = null);
/**
* Inserts as first child of destination node $parent
*
* @param object $parent Propel object for given destination node
* @param PropelPDO $con Connection to use.
* @return object The current object (for fluent API support)
*/
public function insertAsFirstChildOf(NodeObject $parent, PropelPDO $con = null);
/**
* Inserts as last child of destination node $parent
*
* @param object $parent Propel object for given destination node
* @param PropelPDO $con Connection to use.
* @return object The current object (for fluent API support)
*/
public function insertAsLastChildOf(NodeObject $parent, PropelPDO $con = null);
/**
* Inserts node as previous sibling to destination node $dest
*
* @param object $dest Propel object for given destination node
* @param PropelPDO $con Connection to use.
* @return object The current object (for fluent API support)
*/
public function insertAsPrevSiblingOf(NodeObject $dest, PropelPDO $con = null);
/**
* Inserts node as next sibling to destination node $dest
*
* @param object $dest Propel object for given destination node
* @param PropelPDO $con Connection to use.
* @return object The current object (for fluent API support)
*/
public function insertAsNextSiblingOf(NodeObject $dest, PropelPDO $con = null);
/**
* Moves node to be first child of $parent
*
* @param object $parent Propel object for destination node
* @param PropelPDO $con Connection to use.
* @return void
*/
public function moveToFirstChildOf(NodeObject $parent, PropelPDO $con = null);
/**
* Moves node to be last child of $parent
*
* @param object $parent Propel object for destination node
* @param PropelPDO $con Connection to use.
* @return void
*/
public function moveToLastChildOf(NodeObject $parent, PropelPDO $con = null);
/**
* Moves node to be prev sibling to $dest
*
* @param object $dest Propel object for destination node
* @param PropelPDO $con Connection to use.
* @return void
*/
public function moveToPrevSiblingOf(NodeObject $dest, PropelPDO $con = null);
/**
* Moves node to be next sibling to $dest
*
* @param object $dest Propel object for destination node
* @param PropelPDO $con Connection to use.
* @return void
*/
public function moveToNextSiblingOf(NodeObject $dest, PropelPDO $con = null);
/**
* Inserts node as parent of given node.
*
* @param object $node Propel object for given destination node
* @param PropelPDO $con Connection to use.
* @return void
* @throws Exception When trying to insert node as parent of a root node
*/
public function insertAsParentOf(NodeObject $node, PropelPDO $con = null);
/**
* Wraps the getter for the scope value
*
* @return int
*/
public function getScopeIdValue();
/**
* Set the value of scope column
*
* @param int $v new value
* @return object The current object (for fluent API support)
*/
public function setScopeIdValue($v);
} // NodeObject

View file

@ -0,0 +1,108 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* This interface defines methods related to saving an object
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author John D. McNally <jmcnally@collab.net> (Torque)
* @author Fedor K. <fedor@apache.org> (Torque)
* @version $Revision: 1612 $
* @package propel.runtime.om
*/
interface Persistent
{
/**
* getter for the object primaryKey.
*
* @return ObjectKey the object primaryKey as an Object
*/
public function getPrimaryKey();
/**
* Sets the PrimaryKey for the object.
*
* @param mixed $primaryKey The new PrimaryKey object or string (result of PrimaryKey.toString()).
* @return void
* @throws Exception, This method might throw an exceptions
*/
public function setPrimaryKey($primaryKey);
/**
* Returns whether the object has been modified, since it was
* last retrieved from storage.
*
* @return boolean True if the object has been modified.
*/
public function isModified();
/**
* Has specified column been modified?
*
* @param string $col
* @return boolean True if $col has been modified.
*/
public function isColumnModified($col);
/**
* Returns whether the object has ever been saved. This will
* be false, if the object was retrieved from storage or was created
* and then saved.
*
* @return boolean True, if the object has never been persisted.
*/
public function isNew();
/**
* Setter for the isNew attribute. This method will be called
* by Propel-generated children and Peers.
*
* @param boolean $b the state of the object.
*/
public function setNew($b);
/**
* Resets (to false) the "modified" state for this object.
*
* @return void
*/
public function resetModified();
/**
* Whether this object has been deleted.
* @return boolean The deleted state of this object.
*/
public function isDeleted();
/**
* Specify whether this object has been deleted.
* @param boolean $b The deleted state of this object.
* @return void
*/
public function setDeleted($b);
/**
* Deletes the object.
* @param PropelPDO $con
* @return void
* @throws Exception
*/
public function delete(PropelPDO $con = null);
/**
* Saves the object.
* @param PropelPDO $con
* @return void
* @throws Exception
*/
public function save(PropelPDO $con = null);
}

View file

@ -0,0 +1,78 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* Pre-order node iterator for Node objects.
*
* @author Dave Lawson <dlawson@masterytech.com>
* @version $Revision: 1612 $
* @package propel.runtime.om
*/
class PreOrderNodeIterator implements Iterator
{
private $topNode = null;
private $curNode = null;
private $querydb = false;
private $con = null;
public function __construct($node, $opts) {
$this->topNode = $node;
$this->curNode = $node;
if (isset($opts['con']))
$this->con = $opts['con'];
if (isset($opts['querydb']))
$this->querydb = $opts['querydb'];
}
public function rewind() {
$this->curNode = $this->topNode;
}
public function valid() {
return ($this->curNode !== null);
}
public function current() {
return $this->curNode;
}
public function key() {
return $this->curNode->getNodePath();
}
public function next() {
if ($this->valid())
{
$nextNode = $this->curNode->getFirstChildNode($this->querydb, $this->con);
while ($nextNode === null)
{
if ($this->curNode === null || $this->curNode->equals($this->topNode))
break;
$nextNode = $this->curNode->getSiblingNode(false, $this->querydb, $this->con);
if ($nextNode === null)
$this->curNode = $this->curNode->getParentNode($this->querydb, $this->con);
}
$this->curNode = $nextNode;
}
return $this->curNode;
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,543 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* This is an "inner" class that describes an object in the criteria.
*
* In Torque this is an inner class of the Criteria class.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @version $Revision: 1740 $
* @package propel.runtime.query
*/
class Criterion
{
const UND = " AND ";
const ODER = " OR ";
/** Value of the CO. */
protected $value;
/** Comparison value.
* @var SqlEnum
*/
protected $comparison;
/** Table name. */
protected $table;
/** Real table name */
protected $realtable;
/** Column name. */
protected $column;
/** flag to ignore case in comparison */
protected $ignoreStringCase = false;
/**
* The DBAdaptor which might be used to get db specific
* variations of sql.
*/
protected $db;
/**
* other connected criteria and their conjunctions.
*/
protected $clauses = array();
protected $conjunctions = array();
/** "Parent" Criteria class */
protected $parent;
/**
* Create a new instance.
*
* @param Criteria $parent The outer class (this is an "inner" class).
* @param string $column TABLE.COLUMN format.
* @param mixed $value
* @param string $comparison
*/
public function __construct(Criteria $outer, $column, $value, $comparison = null)
{
$this->value = $value;
$dotPos = strrpos($column, '.');
if ($dotPos === false) {
// no dot => aliased column
$this->table = null;
$this->column = $column;
} else {
$this->table = substr($column, 0, $dotPos);
$this->column = substr($column, $dotPos + 1);
}
$this->comparison = ($comparison === null) ? Criteria::EQUAL : $comparison;
$this->init($outer);
}
/**
* Init some properties with the help of outer class
* @param Criteria $criteria The outer class
*/
public function init(Criteria $criteria)
{
// init $this->db
try {
$db = Propel::getDB($criteria->getDbName());
$this->setDB($db);
} catch (Exception $e) {
// we are only doing this to allow easier debugging, so
// no need to throw up the exception, just make note of it.
Propel::log("Could not get a DBAdapter, sql may be wrong", Propel::LOG_ERR);
}
// init $this->realtable
$realtable = $criteria->getTableForAlias($this->table);
$this->realtable = $realtable ? $realtable : $this->table;
}
/**
* Get the column name.
*
* @return string A String with the column name.
*/
public function getColumn()
{
return $this->column;
}
/**
* Set the table name.
*
* @param name A String with the table name.
* @return void
*/
public function setTable($name)
{
$this->table = $name;
}
/**
* Get the table name.
*
* @return string A String with the table name.
*/
public function getTable()
{
return $this->table;
}
/**
* Get the comparison.
*
* @return string A String with the comparison.
*/
public function getComparison()
{
return $this->comparison;
}
/**
* Get the value.
*
* @return mixed An Object with the value.
*/
public function getValue()
{
return $this->value;
}
/**
* Get the value of db.
* The DBAdapter which might be used to get db specific
* variations of sql.
* @return DBAdapter value of db.
*/
public function getDB()
{
return $this->db;
}
/**
* Set the value of db.
* The DBAdapter might be used to get db specific variations of sql.
* @param DBAdapter $v Value to assign to db.
* @return void
*/
public function setDB(DBAdapter $v)
{
$this->db = $v;
foreach ( $this->clauses as $clause ) {
$clause->setDB($v);
}
}
/**
* Sets ignore case.
*
* @param boolean $b True if case should be ignored.
* @return Criterion A modified Criterion object.
*/
public function setIgnoreCase($b)
{
$this->ignoreStringCase = (boolean) $b;
return $this;
}
/**
* Is ignore case on or off?
*
* @return boolean True if case is ignored.
*/
public function isIgnoreCase()
{
return $this->ignoreStringCase;
}
/**
* Get the list of clauses in this Criterion.
* @return array
*/
private function getClauses()
{
return $this->clauses;
}
/**
* Get the list of conjunctions in this Criterion
* @return array
*/
public function getConjunctions()
{
return $this->conjunctions;
}
/**
* Append an AND Criterion onto this Criterion's list.
*/
public function addAnd(Criterion $criterion)
{
$this->clauses[] = $criterion;
$this->conjunctions[] = self::UND;
return $this;
}
/**
* Append an OR Criterion onto this Criterion's list.
* @return Criterion
*/
public function addOr(Criterion $criterion)
{
$this->clauses[] = $criterion;
$this->conjunctions[] = self::ODER;
return $this;
}
/**
* Appends a Prepared Statement representation of the Criterion
* onto the buffer.
*
* @param string &$sb The string that will receive the Prepared Statement
* @param array $params A list to which Prepared Statement parameters will be appended
* @return void
* @throws PropelException - if the expression builder cannot figure out how to turn a specified
* expression into proper SQL.
*/
public function appendPsTo(&$sb, array &$params)
{
$sb .= str_repeat ( '(', count($this->clauses) );
$this->dispatchPsHandling($sb, $params);
foreach ($this->clauses as $key => $clause) {
$sb .= $this->conjunctions[$key];
$clause->appendPsTo($sb, $params);
$sb .= ')';
}
}
/**
* Figure out which Criterion method to use
* to build the prepared statement and parameters using to the Criterion comparison
* and call it to append the prepared statement and the parameters of the current clause
*
* @param string &$sb The string that will receive the Prepared Statement
* @param array $params A list to which Prepared Statement parameters will be appended
*/
protected function dispatchPsHandling(&$sb, array &$params)
{
switch ($this->comparison) {
case Criteria::CUSTOM:
// custom expression with no parameter binding
$this->appendCustomToPs($sb, $params);
break;
case Criteria::IN:
case Criteria::NOT_IN:
// table.column IN (?, ?) or table.column NOT IN (?, ?)
$this->appendInToPs($sb, $params);
break;
case Criteria::LIKE:
case Criteria::NOT_LIKE:
case Criteria::ILIKE:
case Criteria::NOT_ILIKE:
// table.column LIKE ? or table.column NOT LIKE ? (or ILIKE for Postgres)
$this->appendLikeToPs($sb, $params);
break;
default:
// table.column = ? or table.column >= ? etc. (traditional expressions, the default)
$this->appendBasicToPs($sb, $params);
}
}
/**
* Appends a Prepared Statement representation of the Criterion onto the buffer
* For custom expressions with no binding, e.g. 'NOW() = 1'
*
* @param string &$sb The string that will receive the Prepared Statement
* @param array $params A list to which Prepared Statement parameters will be appended
*/
protected function appendCustomToPs(&$sb, array &$params)
{
if ($this->value !== "") {
$sb .= (string) $this->value;
}
}
/**
* Appends a Prepared Statement representation of the Criterion onto the buffer
* For IN expressions, e.g. table.column IN (?, ?) or table.column NOT IN (?, ?)
*
* @param string &$sb The string that will receive the Prepared Statement
* @param array $params A list to which Prepared Statement parameters will be appended
*/
protected function appendInToPs(&$sb, array &$params)
{
if ($this->value !== "") {
$bindParams = array();
$index = count($params); // to avoid counting the number of parameters for each element in the array
foreach ((array) $this->value as $value) {
$params[] = array('table' => $this->realtable, 'column' => $this->column, 'value' => $value);
$index++; // increment this first to correct for wanting bind params to start with :p1
$bindParams[] = ':p' . $index;
}
if (count($bindParams)) {
$field = ($this->table === null) ? $this->column : $this->table . '.' . $this->column;
$sb .= $field . $this->comparison . '(' . implode(',', $bindParams) . ')';
} else {
$sb .= ($this->comparison === Criteria::IN) ? "1<>1" : "1=1";
}
}
}
/**
* Appends a Prepared Statement representation of the Criterion onto the buffer
* For LIKE expressions, e.g. table.column LIKE ? or table.column NOT LIKE ? (or ILIKE for Postgres)
*
* @param string &$sb The string that will receive the Prepared Statement
* @param array $params A list to which Prepared Statement parameters will be appended
*/
protected function appendLikeToPs(&$sb, array &$params)
{
$field = ($this->table === null) ? $this->column : $this->table . '.' . $this->column;
$db = $this->getDb();
// If selection is case insensitive use ILIKE for PostgreSQL or SQL
// UPPER() function on column name for other databases.
if ($this->ignoreStringCase) {
if ($db instanceof DBPostgres) {
if ($this->comparison === Criteria::LIKE) {
$this->comparison = Criteria::ILIKE;
} elseif ($this->comparison === Criteria::NOT_LIKE) {
$this->comparison = Criteria::NOT_ILIKE;
}
} else {
$field = $db->ignoreCase($field);
}
}
$params[] = array('table' => $this->realtable, 'column' => $this->column, 'value' => $this->value);
$sb .= $field . $this->comparison;
// If selection is case insensitive use SQL UPPER() function
// on criteria or, if Postgres we are using ILIKE, so not necessary.
if ($this->ignoreStringCase && !($db instanceof DBPostgres)) {
$sb .= $db->ignoreCase(':p'.count($params));
} else {
$sb .= ':p'.count($params);
}
}
/**
* Appends a Prepared Statement representation of the Criterion onto the buffer
* For traditional expressions, e.g. table.column = ? or table.column >= ? etc.
*
* @param string &$sb The string that will receive the Prepared Statement
* @param array $params A list to which Prepared Statement parameters will be appended
*/
protected function appendBasicToPs(&$sb, array &$params)
{
$field = ($this->table === null) ? $this->column : $this->table . '.' . $this->column;
// NULL VALUES need special treatment because the SQL syntax is different
// i.e. table.column IS NULL rather than table.column = null
if ($this->value !== null) {
// ANSI SQL functions get inserted right into SQL (not escaped, etc.)
if ($this->value === Criteria::CURRENT_DATE || $this->value === Criteria::CURRENT_TIME || $this->value === Criteria::CURRENT_TIMESTAMP) {
$sb .= $field . $this->comparison . $this->value;
} else {
$params[] = array('table' => $this->realtable, 'column' => $this->column, 'value' => $this->value);
// default case, it is a normal col = value expression; value
// will be replaced w/ '?' and will be inserted later using PDO bindValue()
if ($this->ignoreStringCase) {
$sb .= $this->getDb()->ignoreCase($field) . $this->comparison . $this->getDb()->ignoreCase(':p'.count($params));
} else {
$sb .= $field . $this->comparison . ':p'.count($params);
}
}
} else {
// value is null, which means it was either not specified or specifically
// set to null.
if ($this->comparison === Criteria::EQUAL || $this->comparison === Criteria::ISNULL) {
$sb .= $field . Criteria::ISNULL;
} elseif ($this->comparison === Criteria::NOT_EQUAL || $this->comparison === Criteria::ISNOTNULL) {
$sb .= $field . Criteria::ISNOTNULL;
} else {
// for now throw an exception, because not sure how to interpret this
throw new PropelException("Could not build SQL for expression: $field " . $this->comparison . " NULL");
}
}
}
/**
* This method checks another Criteria to see if they contain
* the same attributes and hashtable entries.
* @return boolean
*/
public function equals($obj)
{
// TODO: optimize me with early outs
if ($this === $obj) {
return true;
}
if (($obj === null) || !($obj instanceof Criterion)) {
return false;
}
$crit = $obj;
$isEquiv = ( ( ($this->table === null && $crit->getTable() === null)
|| ( $this->table !== null && $this->table === $crit->getTable() )
)
&& $this->column === $crit->getColumn()
&& $this->comparison === $crit->getComparison());
// check chained criterion
$clausesLength = count($this->clauses);
$isEquiv &= (count($crit->getClauses()) == $clausesLength);
$critConjunctions = $crit->getConjunctions();
$critClauses = $crit->getClauses();
for ($i=0; $i < $clausesLength && $isEquiv; $i++) {
$isEquiv &= ($this->conjunctions[$i] === $critConjunctions[$i]);
$isEquiv &= ($this->clauses[$i] === $critClauses[$i]);
}
if ($isEquiv) {
$isEquiv &= $this->value === $crit->getValue();
}
return $isEquiv;
}
/**
* Returns a hash code value for the object.
*/
public function hashCode()
{
$h = crc32(serialize($this->value)) ^ crc32($this->comparison);
if ($this->table !== null) {
$h ^= crc32($this->table);
}
if ($this->column !== null) {
$h ^= crc32($this->column);
}
foreach ( $this->clauses as $clause ) {
// TODO: i KNOW there is a php incompatibility with the following line
// but i dont remember what it is, someone care to look it up and
// replace it if it doesnt bother us?
// $clause->appendPsTo($sb='',$params=array());
$sb = '';
$params = array();
$clause->appendPsTo($sb,$params);
$h ^= crc32(serialize(array($sb,$params)));
unset ( $sb, $params );
}
return $h;
}
/**
* Get all tables from nested criterion objects
* @return array
*/
public function getAllTables()
{
$tables = array();
$this->addCriterionTable($this, $tables);
return $tables;
}
/**
* method supporting recursion through all criterions to give
* us a string array of tables from each criterion
* @return void
*/
private function addCriterionTable(Criterion $c, array &$s)
{
$s[] = $c->getTable();
foreach ( $c->getClauses() as $clause ) {
$this->addCriterionTable($clause, $s);
}
}
/**
* get an array of all criterion attached to this
* recursing through all sub criterion
* @return array Criterion[]
*/
public function getAttachedCriterion()
{
$criterions = array($this);
foreach ($this->getClauses() as $criterion) {
$criterions = array_merge($criterions, $criterion->getAttachedCriterion());
}
return $criterions;
}
/**
* Ensures deep cloning of attached objects
*/
public function __clone()
{
foreach ($this->clauses as $key => $criterion) {
$this->clauses[$key] = clone $criterion;
}
}
}

View file

@ -0,0 +1,54 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* Class that implements SPL Iterator interface. This allows foreach () to
* be used w/ Criteria objects. Probably there is no performance advantage
* to doing it this way, but it makes sense -- and simpler code.
*
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 1612 $
* @package propel.runtime.query
*/
class CriterionIterator implements Iterator
{
private $idx = 0;
private $criteria;
private $criteriaKeys;
private $criteriaSize;
public function __construct(Criteria $criteria) {
$this->criteria = $criteria;
$this->criteriaKeys = $criteria->keys();
$this->criteriaSize = count($this->criteriaKeys);
}
public function rewind() {
$this->idx = 0;
}
public function valid() {
return $this->idx < $this->criteriaSize;
}
public function key() {
return $this->criteriaKeys[$this->idx];
}
public function current() {
return $this->criteria->getCriterion($this->criteriaKeys[$this->idx]);
}
public function next() {
$this->idx++;
}
}

View file

@ -0,0 +1,250 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* Data object to describe a join between two tables, for example
* <pre>
* table_a LEFT JOIN table_b ON table_a.id = table_b.a_id
* </pre>
*
* @author Francois Zaninotto (Propel)
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @author Kaspars Jaudzems <kaspars.jaudzems@inbox.lv> (Propel)
* @author Frank Y. Kim <frank.kim@clearink.com> (Torque)
* @author John D. McNally <jmcnally@collab.net> (Torque)
* @author Brett McLaughlin <bmclaugh@algx.net> (Torque)
* @author Eric Dobbs <eric@dobbse.net> (Torque)
* @author Henning P. Schmiedehausen <hps@intermeta.de> (Torque)
* @author Sam Joseph <sam@neurogrid.com> (Torque)
* @package propel.runtime.query
*/
class Join
{
// default comparison type
const EQUAL = "=";
// the left parts of the join condition
protected $left = array();
// the right parts of the join condition
protected $right = array();
// the comparison operators for each pair of columns in the join condition
protected $operator = array();
// the type of the join (LEFT JOIN, ...), or null for an implicit join
protected $joinType = null;
// the number of conditions in the join
protected $count = 0;
/**
* Constructor
* Use it preferably with no arguments, and then use addCondition() and setJoinType()
* Syntax with arguments used mainly for backwards compatibility
*
* @param string $leftColumn The left column of the join condition
* (may contain an alias name)
* @param string $rightColumn The right column of the join condition
* (may contain an alias name)
* @param string $joinType The type of the join. Valid join types are null (implicit join),
* Criteria::LEFT_JOIN, Criteria::RIGHT_JOIN, and Criteria::INNER_JOIN
*/
public function __construct($leftColumn = null, $rightColumn = null, $joinType = null)
{
if(!is_null($leftColumn)) {
if (!is_array($leftColumn)) {
// simple join
$this->addCondition($leftColumn, $rightColumn);
} else {
// join with multiple conditions
if (count($leftColumn) != count($rightColumn) ) {
throw new PropelException("Unable to create join because the left column count isn't equal to the right column count");
}
foreach ($leftColumn as $key => $value)
{
$this->addCondition($value, $rightColumn[$key]);
}
}
$this->setJoinType($joinType);
}
}
/**
* Join condition definition
*
* @param string $left The left column of the join condition
* (may contain an alias name)
* @param string $right The right column of the join condition
* (may contain an alias name)
* @param string $operator The comparison operator of the join condition, default Join::EQUAL
*/
public function addCondition($left, $right, $operator = self::EQUAL)
{
$this->left[] = $left;
$this->right[] = $right;
$this->operator[] = $operator;
$this->count++;
}
/**
* Retrieve the number of conditions in the join
*
* @return integer The number of conditions in the join
*/
public function countConditions()
{
return $this->count;
}
/**
* Return an array of the join conditions
*
* @return array An array of arrays representing (left, comparison, right) for each condition
*/
public function getConditions()
{
$conditions = array();
for ($i=0; $i < $this->count; $i++) {
$conditions[] = array(
'left' => $this->getLeftColumn($i),
'operator' => $this->getOperator($i),
'right' => $this->getRightColumn($i)
);
}
return $conditions;
}
/**
* @return the comparison operator for the join condition
*/
public function getOperator($index = 0)
{
return $this->operator[$index];
}
public function getOperators()
{
return $this->operator;
}
/**
* Set the join type
*
* @param string $joinType The type of the join. Valid join types are
* null (adding the join condition to the where clause),
* Criteria::LEFT_JOIN(), Criteria::RIGHT_JOIN(), and Criteria::INNER_JOIN()
*/
public function setJoinType($joinType = null)
{
$this->joinType = $joinType;
}
/**
* Get the join type
*
* @return string The type of the join, i.e. Criteria::LEFT_JOIN(), ...,
* or null for adding the join condition to the where Clause
*/
public function getJoinType()
{
return $this->joinType;
}
/**
* @return the left column of the join condition
*/
public function getLeftColumn($index = 0)
{
return $this->left[$index];
}
/**
* @return all right columns of the join condition
*/
public function getLeftColumns()
{
return $this->left;
}
public function getLeftColumnName($index = 0)
{
return substr($this->left[$index], strrpos($this->left[$index], '.') + 1);
}
public function getLeftTableName($index = 0)
{
return substr($this->left[$index], 0, strrpos($this->left[$index], '.'));
}
/**
* @return the right column of the join condition
*/
public function getRightColumn($index = 0)
{
return $this->right[$index];
}
/**
* @return all right columns of the join condition
*/
public function getRightColumns()
{
return $this->right;
}
public function getRightColumnName($index = 0)
{
return substr($this->right[$index], strrpos($this->right[$index], '.') + 1);
}
public function getRightTableName($index = 0)
{
return substr($this->right[$index], 0, strrpos($this->right[$index], '.'));
}
public function equals($join)
{
return $join !== null
&& $join instanceof Join
&& $this->joinType == $join->getJoinType()
&& $this->getConditions() == $join->getConditions();
}
/**
* returns a String representation of the class,
* mainly for debugging purposes
*
* @return string A String representation of the class
*/
public function toString()
{
$result = '';
if ($this->joinType !== null) {
$result .= $this->joinType . ' : ';
}
foreach ($this->getConditions() as $index => $condition) {
$result .= implode($condition);
if ($index + 1 < $this->count) {
$result .= ' AND ';
}
}
$result .= '(ignoreCase not considered)';
return $result;
}
public function __toString()
{
return $this->toString();
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,283 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* This is an "inner" class that describes an object in the criteria.
*
* @author Francois
* @version $Revision: 1630 $
* @package propel.runtime.query
*/
class ModelCriterion extends Criterion
{
protected $clause = '';
/**
* Create a new instance.
*
* @param Criteria $parent The outer class (this is an "inner" class).
* @param ColumnMap $column A Column object to help escaping the value
* @param mixed $value
* @param string $comparison, among ModelCriteria::MODEL_CLAUSE
* @param string $clause A simple pseudo-SQL clause, e.g. 'foo.BAR LIKE ?'
*/
public function __construct(Criteria $outer, $column, $value = null, $comparison = ModelCriteria::MODEL_CLAUSE, $clause)
{
$this->value = $value;
if ($column instanceof ColumnMap) {
$this->column = $column->getName();
$this->table = $column->getTable()->getName();
} else {
$dotPos = strrpos($column,'.');
if ($dotPos === false) {
// no dot => aliased column
$this->table = null;
$this->column = $column;
} else {
$this->table = substr($column, 0, $dotPos);
$this->column = substr($column, $dotPos+1, strlen($column));
}
}
$this->comparison = ($comparison === null ? Criteria::EQUAL : $comparison);
$this->clause = $clause;
$this->init($outer);
}
public function getClause()
{
return $this->clause;
}
/**
* Figure out which MocelCriterion method to use
* to build the prepared statement and parameters using to the Criterion comparison
* and call it to append the prepared statement and the parameters of the current clause.
* For performance reasons, this method tests the cases of parent::dispatchPsHandling()
* first, and that is not possible through inheritance ; that's why the parent
* code is duplicated here.
*
* @param string &$sb The string that will receive the Prepared Statement
* @param array $params A list to which Prepared Statement parameters will be appended
*/
protected function dispatchPsHandling(&$sb, array &$params)
{
switch ($this->comparison) {
case Criteria::CUSTOM:
// custom expression with no parameter binding
$this->appendCustomToPs($sb, $params);
break;
case Criteria::IN:
case Criteria::NOT_IN:
// table.column IN (?, ?) or table.column NOT IN (?, ?)
$this->appendInToPs($sb, $params);
break;
case Criteria::LIKE:
case Criteria::NOT_LIKE:
case Criteria::ILIKE:
case Criteria::NOT_ILIKE:
// table.column LIKE ? or table.column NOT LIKE ? (or ILIKE for Postgres)
$this->appendLikeToPs($sb, $params);
break;
case ModelCriteria::MODEL_CLAUSE:
// regular model clause, e.g. 'book.TITLE = ?'
$this->appendModelClauseToPs($sb, $params);
break;
case ModelCriteria::MODEL_CLAUSE_LIKE:
// regular model clause, e.g. 'book.TITLE = ?'
$this->appendModelClauseLikeToPs($sb, $params);
break;
case ModelCriteria::MODEL_CLAUSE_SEVERAL:
// Ternary model clause, e.G 'book.ID BETWEEN ? AND ?'
$this->appendModelClauseSeveralToPs($sb, $params);
break;
case ModelCriteria::MODEL_CLAUSE_ARRAY:
// IN or NOT IN model clause, e.g. 'book.TITLE NOT IN ?'
$this->appendModelClauseArrayToPs($sb, $params);
break;
default:
// table.column = ? or table.column >= ? etc. (traditional expressions, the default)
$this->appendBasicToPs($sb, $params);
}
}
/**
* Appends a Prepared Statement representation of the ModelCriterion onto the buffer
* For regular model clauses, e.g. 'book.TITLE = ?'
*
* @param string &$sb The string that will receive the Prepared Statement
* @param array $params A list to which Prepared Statement parameters will be appended
*/
public function appendModelClauseToPs(&$sb, array &$params)
{
if ($this->value !== null) {
$params[] = array('table' => $this->realtable, 'column' => $this->column, 'value' => $this->value);
$sb .= str_replace('?', ':p'.count($params), $this->clause);
} else {
$sb .= $this->clause;
}
}
/**
* Appends a Prepared Statement representation of the ModelCriterion onto the buffer
* For LIKE model clauses, e.g. 'book.TITLE LIKE ?'
* Handles case insensitivity for VARCHAR columns
*
* @param string &$sb The string that will receive the Prepared Statement
* @param array $params A list to which Prepared Statement parameters will be appended
*/
public function appendModelClauseLikeToPs(&$sb, array &$params)
{
// LIKE is case insensitive in mySQL and SQLite, but not in PostGres
// If the column is case insensitive, use ILIKE / NOT ILIKE instead of LIKE / NOT LIKE
if ($this->ignoreStringCase && $this->getDb() instanceof DBPostgres) {
$this->clause = preg_replace('/LIKE \?$/i', 'ILIKE ?', $this->clause);
}
$this->appendModelClauseToPs($sb, $params);
}
/**
* Appends a Prepared Statement representation of the ModelCriterion onto the buffer
* For ternary model clauses, e.G 'book.ID BETWEEN ? AND ?'
*
* @param string &$sb The string that will receive the Prepared Statement
* @param array $params A list to which Prepared Statement parameters will be appended
*/
public function appendModelClauseSeveralToPs(&$sb, array &$params)
{
$clause = $this->clause;
foreach ((array) $this->value as $value) {
if ($value === null) {
// FIXME we eventually need to translate a BETWEEN to
// something like WHERE (col < :p1 OR :p1 IS NULL) AND (col < :p2 OR :p2 IS NULL)
// in order to support null values
throw new PropelException('Null values are not supported inside BETWEEN clauses');
}
$params[] = array('table' => $this->realtable, 'column' => $this->column, 'value' => $value);
$clause = self::strReplaceOnce('?', ':p'.count($params), $clause);
}
$sb .= $clause;
}
/**
* Appends a Prepared Statement representation of the ModelCriterion onto the buffer
* For IN or NOT IN model clauses, e.g. 'book.TITLE NOT IN ?'
*
* @param string &$sb The string that will receive the Prepared Statement
* @param array $params A list to which Prepared Statement parameters will be appended
*/
public function appendModelClauseArrayToPs(&$sb, array &$params)
{
$_bindParams = array(); // the param names used in query building
$_idxstart = count($params);
$valuesLength = 0;
foreach ( (array) $this->value as $value ) {
$valuesLength++; // increment this first to correct for wanting bind params to start with :p1
$params[] = array('table' => $this->realtable, 'column' => $this->column, 'value' => $value);
$_bindParams[] = ':p'.($_idxstart + $valuesLength);
}
if ($valuesLength !== 0) {
$sb .= str_replace('?', '(' . implode(',', $_bindParams) . ')', $this->clause);
} else {
$sb .= (stripos($this->clause, ' NOT IN ') === false) ? "1<>1" : "1=1";
}
unset ( $value, $valuesLength );
}
/**
* This method checks another Criteria to see if they contain
* the same attributes and hashtable entries.
* @return boolean
*/
public function equals($obj)
{
// TODO: optimize me with early outs
if ($this === $obj) {
return true;
}
if (($obj === null) || !($obj instanceof ModelCriterion)) {
return false;
}
$crit = $obj;
$isEquiv = ( ( ($this->table === null && $crit->getTable() === null)
|| ( $this->table !== null && $this->table === $crit->getTable() )
)
&& $this->clause === $crit->getClause()
&& $this->column === $crit->getColumn()
&& $this->comparison === $crit->getComparison());
// check chained criterion
$clausesLength = count($this->clauses);
$isEquiv &= (count($crit->getClauses()) == $clausesLength);
$critConjunctions = $crit->getConjunctions();
$critClauses = $crit->getClauses();
for ($i=0; $i < $clausesLength && $isEquiv; $i++) {
$isEquiv &= ($this->conjunctions[$i] === $critConjunctions[$i]);
$isEquiv &= ($this->clauses[$i] === $critClauses[$i]);
}
if ($isEquiv) {
$isEquiv &= $this->value === $crit->getValue();
}
return $isEquiv;
}
/**
* Returns a hash code value for the object.
*/
public function hashCode()
{
$h = crc32(serialize($this->value)) ^ crc32($this->comparison) ^ crc32($this->clause);
if ($this->table !== null) {
$h ^= crc32($this->table);
}
if ($this->column !== null) {
$h ^= crc32($this->column);
}
foreach ( $this->clauses as $clause ) {
// TODO: i KNOW there is a php incompatibility with the following line
// but i dont remember what it is, someone care to look it up and
// replace it if it doesnt bother us?
// $clause->appendPsTo($sb='',$params=array());
$sb = '';
$params = array();
$clause->appendPsTo($sb,$params);
$h ^= crc32(serialize(array($sb,$params)));
unset ( $sb, $params );
}
return $h;
}
/**
* Replace only once
* taken from http://www.php.net/manual/en/function.str-replace.php
*
*/
protected static function strReplaceOnce($search, $replace, $subject)
{
$firstChar = strpos($subject, $search);
if($firstChar !== false) {
$beforeStr = substr($subject,0,$firstChar);
$afterStr = substr($subject, $firstChar + strlen($search));
return $beforeStr.$replace.$afterStr;
} else {
return $subject;
}
}
}

View file

@ -0,0 +1,166 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* A ModelJoin is a Join object tied to a RelationMap object
*
* @author Francois Zaninotto (Propel)
* @package propel.runtime.query
*/
class ModelJoin extends Join
{
protected $relationMap;
protected $tableMap;
protected $leftTableAlias;
protected $relationAlias;
protected $previousJoin;
public function setRelationMap(RelationMap $relationMap, $leftTableAlias = null, $relationAlias = null)
{
$leftCols = $relationMap->getLeftColumns();
$rightCols = $relationMap->getRightColumns();
$nbColumns = $relationMap->countColumnMappings();
for ($i=0; $i < $nbColumns; $i++) {
$leftColName = ($leftTableAlias ? $leftTableAlias : $leftCols[$i]->getTableName()) . '.' . $leftCols[$i]->getName();
$rightColName = ($relationAlias ? $relationAlias : $rightCols[$i]->getTableName()) . '.' . $rightCols[$i]->getName();
$this->addCondition($leftColName, $rightColName, Criteria::EQUAL);
}
$this->relationMap = $relationMap;
$this->leftTableAlias = $leftTableAlias;
$this->relationAlias = $relationAlias;
return $this;
}
public function getRelationMap()
{
return $this->relationMap;
}
/**
* Sets the right tableMap for this join
*
* @param TableMap $tableMap The table map to use
*
* @return ModelJoin The current join object, for fluid interface
*/
public function setTableMap(TableMap $tableMap)
{
$this->tableMap = $tableMap;
return $this;
}
/**
* Gets the right tableMap for this join
*
* @return TableMap The table map
*/
public function getTableMap()
{
if (null === $this->tableMap && null !== $this->relationMap)
{
$this->tableMap = $this->relationMap->getRightTable();
}
return $this->tableMap;
}
public function setPreviousJoin(ModelJoin $join)
{
$this->previousJoin = $join;
return $this;
}
public function getPreviousJoin()
{
return $this->previousJoin;
}
public function isPrimary()
{
return null === $this->previousJoin;
}
public function setLeftTableAlias($leftTableAlias)
{
$this->leftTableAlias = $leftTableAlias;
return $this;
}
public function getLeftTableAlias()
{
return $this->leftTableAlias;
}
public function hasLeftTableAlias()
{
return null !== $this->leftTableAlias;
}
public function setRelationAlias($relationAlias)
{
$this->relationAlias = $relationAlias;
return $this;
}
public function getRelationAlias()
{
return $this->relationAlias;
}
public function hasRelationAlias()
{
return null !== $this->relationAlias;
}
/**
* This method returns the last related, but already hydrated object up until this join
* Starting from $startObject and continuously calling the getters to get
* to the base object for the current join.
*
* This method only works if PreviousJoin has been defined,
* which only happens when you provide dotted relations when calling join
*
* @param Object $startObject the start object all joins originate from and which has already hydrated
* @return Object the base Object of this join
*/
public function getObjectToRelate($startObject)
{
if($this->isPrimary()) {
return $startObject;
} else {
$previousJoin = $this->getPreviousJoin();
$previousObject = $previousJoin->getObjectToRelate($startObject);
$method = 'get' . $previousJoin->getRelationMap()->getName();
return $previousObject->$method();
}
}
public function equals($join)
{
return parent::equals($join)
&& $this->relationMap == $join->getRelationMap()
&& $this->previousJoin == $join->getPreviousJoin()
&& $this->relationAlias == $join->getRelationAlias();
}
public function __toString()
{
return parent::toString()
. ' tableMap: ' . ($this->tableMap ? get_class($this->tableMap) : 'null')
. ' relationMap: ' . $this->relationMap->getName()
. ' previousJoin: ' . ($this->previousJoin ? '(' . $this->previousJoin . ')' : 'null')
. ' relationAlias: ' . $this->relationAlias;
}
}

View file

@ -0,0 +1,33 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* Factory for model queries
*
* @author François Zaninotto
* @version $Revision: 1612 $
* @package propel.runtime.query
*/
class PropelQuery
{
public static function from($queryClassAndAlias)
{
list($class, $alias) = ModelCriteria::getClassAndAlias($queryClassAndAlias);
$queryClass = $class . 'Query';
if (!class_exists($queryClass)) {
throw new PropelException('Cannot find a query class for ' . $class);
}
$query = new $queryClass();
if ($alias !== null) {
$query->setModelAlias($alias);
}
return $query;
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,369 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* This is a utility interface for all generated NodePeer classes in the system.
*
* @author Heltem <heltem@o2php.com> (Propel)
* @version $Revision: 1612 $
* @package propel.runtime.util
*/
interface NodePeer
{
/**
* Creates the supplied node as the root node.
*
* @param object $node Propel object for model
* @return object Inserted propel object for model
*/
public static function createRoot(NodeObject $node);
/**
* Returns the root node for a given scope id
*
* @param int $scopeId Scope id to determine which root node to return
* @param PropelPDO $con Connection to use.
* @return object Propel object for root node
*/
public static function retrieveRoot($scopeId = 1, PropelPDO $con = null);
/**
* Inserts $child as first child of destination node $parent
*
* @param object $child Propel object for child node
* @param object $parent Propel object for parent node
* @param PropelPDO $con Connection to use.
* @return void
*/
public static function insertAsFirstChildOf(NodeObject $child, NodeObject $parent, PropelPDO $con = null);
/**
* Inserts $child as last child of destination node $parent
*
* @param object $child Propel object for child node
* @param object $parent Propel object for parent node
* @param PropelPDO $con Connection to use.
* @return void
*/
public static function insertAsLastChildOf(NodeObject $child, NodeObject $parent, PropelPDO $con = null);
/**
* Inserts $sibling as previous sibling to destination node $node
*
* @param object $node Propel object for destination node
* @param object $sibling Propel object for source node
* @param PropelPDO $con Connection to use.
* @return void
*/
public static function insertAsPrevSiblingOf(NodeObject $node, NodeObject $sibling, PropelPDO $con = null);
/**
* Inserts $sibling as next sibling to destination node $node
*
* @param object $node Propel object for destination node
* @param object $sibling Propel object for source node
* @param PropelPDO $con Connection to use.
* @return void
*/
public static function insertAsNextSiblingOf(NodeObject $node, NodeObject $sibling, PropelPDO $con = null);
/**
* Inserts $parent as parent of given $node.
*
* @param object $parent Propel object for given parent node
* @param object $node Propel object for given destination node
* @param PropelPDO $con Connection to use.
* @return void
* @throws Exception When trying to insert node as parent of a root node
*/
public static function insertAsParentOf(NodeObject $parent, NodeObject $node, PropelPDO $con = null);
/**
* Inserts $node as root node
*
* @param object $node Propel object as root node
* @param PropelPDO $con Connection to use.
* @return void
*/
public static function insertRoot(NodeObject $node, PropelPDO $con = null);
/**
* Delete root node
*
* @param int $scopeId Scope id to determine which root node to delete
* @param PropelPDO $con Connection to use.
* @return boolean Deletion status
*/
public static function deleteRoot($scopeId = 1, PropelPDO $con = null);
/**
* Delete $dest node
*
* @param object $dest Propel object node to delete
* @param PropelPDO $con Connection to use.
* @return boolean Deletion status
*/
public static function deleteNode(NodeObject $dest, PropelPDO $con = null);
/**
* Moves $child to be first child of $parent
*
* @param object $parent Propel object for parent node
* @param object $child Propel object for child node
* @param PropelPDO $con Connection to use.
* @return void
*/
public static function moveToFirstChildOf(NodeObject $parent, NodeObject $child, PropelPDO $con = null);
/**
* Moves $node to be last child of $dest
*
* @param object $dest Propel object for destination node
* @param object $node Propel object for source node
* @param PropelPDO $con Connection to use.
* @return void
*/
public static function moveToLastChildOf(NodeObject $dest, NodeObject $node, PropelPDO $con = null);
/**
* Moves $node to be prev sibling to $dest
*
* @param object $dest Propel object for destination node
* @param object $node Propel object for source node
* @param PropelPDO $con Connection to use.
* @return void
*/
public static function moveToPrevSiblingOf(NodeObject $dest, NodeObject $node, PropelPDO $con = null);
/**
* Moves $node to be next sibling to $dest
*
* @param object $dest Propel object for destination node
* @param object $node Propel object for source node
* @param PropelPDO $con Connection to use.
* @return void
*/
public static function moveToNextSiblingOf(NodeObject $dest, NodeObject $node, PropelPDO $con = null);
/**
* Gets first child for the given node if it exists
*
* @param object $node Propel object for src node
* @param PropelPDO $con Connection to use.
* @return mixed Propel object if exists else false
*/
public static function retrieveFirstChild(NodeObject $node, PropelPDO $con = null);
/**
* Gets last child for the given node if it exists
*
* @param object $node Propel object for src node
* @param PropelPDO $con Connection to use.
* @return mixed Propel object if exists else false
*/
public static function retrieveLastChild(NodeObject $node, PropelPDO $con = null);
/**
* Gets prev sibling for the given node if it exists
*
* @param object $node Propel object for src node
* @param PropelPDO $con Connection to use.
* @return mixed Propel object if exists else false
*/
public static function retrievePrevSibling(NodeObject $node, PropelPDO $con = null);
/**
* Gets next sibling for the given node if it exists
*
* @param object $node Propel object for src node
* @param PropelPDO $con Connection to use.
* @return mixed Propel object if exists else false
*/
public static function retrieveNextSibling(NodeObject $node, PropelPDO $con = null);
/**
* Retrieves the entire tree from root
*
* @param int $scopeId Scope id to determine which scope tree to return
* @param PropelPDO $con Connection to use.
*/
public static function retrieveTree($scopeId = 1, PropelPDO $con = null);
/**
* Retrieves the entire tree from parent $node
*
* @param PropelPDO $con Connection to use.
*/
public static function retrieveBranch(NodeObject $node, PropelPDO $con = null);
/**
* Gets direct children for the node
*
* @param object $node Propel object for parent node
* @param PropelPDO $con Connection to use.
*/
public static function retrieveChildren(NodeObject $node, PropelPDO $con = null);
/**
* Gets all descendants for the node
*
* @param object $node Propel object for parent node
* @param PropelPDO $con Connection to use.
*/
public static function retrieveDescendants(NodeObject $node, PropelPDO $con = null);
/**
* Gets all siblings for the node
*
* @param object $node Propel object for src node
* @param PropelPDO $con Connection to use.
*/
public static function retrieveSiblings(NodeObject $node, PropelPDO $con = null);
/**
* Gets ancestor for the given node if it exists
*
* @param object $node Propel object for src node
* @param PropelPDO $con Connection to use.
* @return mixed Propel object if exists else false
*/
public static function retrieveParent(NodeObject $node, PropelPDO $con = null);
/**
* Gets level for the given node
*
* @param object $node Propel object for src node
* @param PropelPDO $con Connection to use.
* @return int Level for the given node
*/
public static function getLevel(NodeObject $node, PropelPDO $con = null);
/**
* Gets number of direct children for given node
*
* @param object $node Propel object for src node
* @param PropelPDO $con Connection to use.
* @return int Level for the given node
*/
public static function getNumberOfChildren(NodeObject $node, PropelPDO $con = null);
/**
* Gets number of descendants for given node
*
* @param object $node Propel object for src node
* @param PropelPDO $con Connection to use.
* @return int Level for the given node
*/
public static function getNumberOfDescendants(NodeObject $node, PropelPDO $con = null);
/**
* Returns path to a specific node as an array, useful to create breadcrumbs
*
* @param object $node Propel object of node to create path to
* @param PropelPDO $con Connection to use.
* @return array Array in order of heirarchy
*/
public static function getPath(NodeObject $node, PropelPDO $con = null);
/**
* Tests if node is valid
*
* @param object $node Propel object for src node
* @return bool
*/
public static function isValid(NodeObject $node = null);
/**
* Tests if node is a root
*
* @param object $node Propel object for src node
* @return bool
*/
public static function isRoot(NodeObject $node);
/**
* Tests if node is a leaf
*
* @param object $node Propel object for src node
* @return bool
*/
public static function isLeaf(NodeObject $node);
/**
* Tests if $child is a child of $parent
*
* @param object $child Propel object for node
* @param object $parent Propel object for node
* @return bool
*/
public static function isChildOf(NodeObject $child, NodeObject $parent);
/**
* Tests if $node1 is equal to $node2
*
* @param object $node1 Propel object for node
* @param object $node2 Propel object for node
* @return bool
*/
public static function isEqualTo(NodeObject $node1, NodeObject $node2);
/**
* Tests if $node has an ancestor
*
* @param object $node Propel object for node
* @param PropelPDO $con Connection to use.
* @return bool
*/
public static function hasParent(NodeObject $node, PropelPDO $con = null);
/**
* Tests if $node has prev sibling
*
* @param object $node Propel object for node
* @param PropelPDO $con Connection to use.
* @return bool
*/
public static function hasPrevSibling(NodeObject $node, PropelPDO $con = null);
/**
* Tests if $node has next sibling
*
* @param object $node Propel object for node
* @param PropelPDO $con Connection to use.
* @return bool
*/
public static function hasNextSibling(NodeObject $node, PropelPDO $con = null);
/**
* Tests if $node has children
*
* @param object $node Propel object for node
* @return bool
*/
public static function hasChildren(NodeObject $node);
/**
* Deletes $node and all of its descendants
*
* @param object $node Propel object for source node
* @param PropelPDO $con Connection to use.
*/
public static function deleteDescendants(NodeObject $node, PropelPDO $con = null);
/**
* Returns a node given its primary key or the node itself
*
* @param int/object $node Primary key/instance of required node
* @param PropelPDO $con Connection to use.
* @return object Propel object for model
*/
public static function getNode($node, PropelPDO $con = null);
} // NodePeer

View file

@ -0,0 +1,113 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* Simple autoloader for Propel generated model classes.
* This class implements the singleton pattern.
*
* @author Prancois Zaninotto
* @author Fabien Potencier
* @version $Revision: 1773 $
* @package propel.util
*/
class PropelAutoloader
{
static protected $instance = null;
protected $classes = array();
/**
* Retrieves the singleton instance of this class.
*
* @return PropelAutoloader A PropelAutoloader instance.
*/
static public function getInstance()
{
if (!isset(self::$instance)) {
self::$instance = new PropelAutoloader();
}
return self::$instance;
}
/**
* Register PropelAutoloader in spl autoloader.
*
* @return void
*/
static public function register()
{
ini_set('unserialize_callback_func', 'spl_autoload_call');
if (false === spl_autoload_register(array(self::getInstance(), 'autoload'))) {
throw new Exception(sprintf('Unable to register %s::autoload as an autoloading method.', get_class(self::getInstance())));
}
}
/**
* Unregister PropelAutoloader from spl autoloader.
*
* @return void
*/
static public function unregister()
{
spl_autoload_unregister(array(self::getInstance(), 'autoload'));
}
/**
* Sets the path for a list of classes.
*
* @param array $classMap An associative array $className => $classPath
*/
public function addClassPaths($classMap)
{
$this->classes = array_merge($this->classes, $classMap);
}
/**
* Sets the path for a particular class.
*
* @param string $class A PHP class name
* @param string $path A path (absolute or relative to the include path)
*/
public function addClassPath($class, $path)
{
$this->classes[$class] = $path;
}
/**
* Returns the path where a particular class can be found.
*
* @param string $class A PHP class name
*
* @return string|null A path (absolute or relative to the include path)
*/
public function getClassPath($class)
{
return isset($this->classes[$class]) ? $this->classes[$class] : null;
}
/**
* Handles autoloading of classes that have been registered in this instance
*
* @param string $class A class name.
*
* @return boolean Returns true if the class has been loaded
*/
public function autoload($class)
{
if (isset($this->classes[$class])) {
require $this->classes[$class];
return true;
}
return false;
}
}

View file

@ -0,0 +1,88 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* Enumeration of Propel types.
*
* THIS CLASS MUST BE KEPT UP-TO-DATE WITH THE MORE EXTENSIVE GENERATOR VERSION OF THIS CLASS.
*
* @author Hans Lellelid <hans@xmpl.org> (Propel)
* @version $Revision: 1612 $
* @package propel.runtime.util
*/
class PropelColumnTypes
{
const
CHAR = "CHAR",
VARCHAR = "VARCHAR",
LONGVARCHAR = "LONGVARCHAR",
CLOB = "CLOB",
CLOB_EMU = "CLOB_EMU",
NUMERIC = "NUMERIC",
DECIMAL = "DECIMAL",
TINYINT = "TINYINT",
SMALLINT = "SMALLINT",
INTEGER = "INTEGER",
BIGINT = "BIGINT",
REAL = "REAL",
FLOAT = "FLOAT",
DOUBLE = "DOUBLE",
BINARY = "BINARY",
VARBINARY = "VARBINARY",
LONGVARBINARY = "LONGVARBINARY",
BLOB = "BLOB",
DATE = "DATE",
TIME = "TIME",
TIMESTAMP = "TIMESTAMP",
BU_DATE = "BU_DATE",
BU_TIMESTAMP = "BU_TIMESTAMP",
BOOLEAN = "BOOLEAN",
BOOLEAN_EMU = "BOOLEAN_EMU";
private static $propelToPdoMap = array(
self::CHAR => PDO::PARAM_STR,
self::VARCHAR => PDO::PARAM_STR,
self::LONGVARCHAR => PDO::PARAM_STR,
self::CLOB => PDO::PARAM_LOB,
self::CLOB_EMU => PDO::PARAM_STR,
self::NUMERIC => PDO::PARAM_STR,
self::DECIMAL => PDO::PARAM_STR,
self::TINYINT => PDO::PARAM_INT,
self::SMALLINT => PDO::PARAM_INT,
self::INTEGER => PDO::PARAM_INT,
self::BIGINT => PDO::PARAM_STR,
self::REAL => PDO::PARAM_STR,
self::FLOAT => PDO::PARAM_STR,
self::DOUBLE => PDO::PARAM_STR,
self::BINARY => PDO::PARAM_STR,
self::VARBINARY => PDO::PARAM_STR,
self::LONGVARBINARY => PDO::PARAM_STR,
self::BLOB => PDO::PARAM_LOB,
self::DATE => PDO::PARAM_STR,
self::TIME => PDO::PARAM_STR,
self::TIMESTAMP => PDO::PARAM_STR,
self::BU_DATE => PDO::PARAM_STR,
self::BU_TIMESTAMP => PDO::PARAM_STR,
self::BOOLEAN => PDO::PARAM_BOOL,
self::BOOLEAN_EMU => PDO::PARAM_INT,
);
/**
* Resturns the PDO type (PDO::PARAM_* constant) value for the Propel type provided.
* @param string $propelType
* @return int
*/
public static function getPdoType($propelType)
{
return self::$propelToPdoMap[$propelType];
}
}

View file

@ -0,0 +1,71 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* Proxy for conditional statements in a fluid interface.
* This class replaces another class for wrong statements,
* and silently catches all calls to non-conditional method calls
*
* @example
* <code>
* $c->_if(true) // returns $c
* ->doStuff() // executed
* ->_else() // returns a PropelConditionalProxy instance
* ->doOtherStuff() // not executed
* ->_endif(); // returns $c
* $c->_if(false) // returns a PropelConditionalProxy instance
* ->doStuff() // not executed
* ->_else() // returns $c
* ->doOtherStuff() // executed
* ->_endif(); // returns $c
* @see Criteria
*
* @author Francois Zaninotto
* @version $Revision: 1612 $
* @package propel.runtime.util
*/
class PropelConditionalProxy
{
protected $mainObject;
public function __construct($mainObject)
{
$this->mainObject = $mainObject;
}
public function _if()
{
throw new PropelException('_if() statements cannot be nested');
}
public function _elseif($cond)
{
if($cond) {
return $this->mainObject;
} else {
return $this;
}
}
public function _else()
{
return $this->mainObject;
}
public function _endif()
{
return $this->mainObject;
}
public function __call($name, $arguments)
{
return $this;
}
}

View file

@ -0,0 +1,76 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* DateTime subclass which supports serialization.
*
* Currently Propel is not using this for storing date/time objects
* within model objeects; however, we are keeping it in the repository
* because it is useful if you want to store a DateTime object in a session.
*
* @author Alan Pinstein
* @author Soenke Ruempler
* @author Hans Lellelid
* @package propel.runtime.util
*/
class PropelDateTime extends DateTime
{
/**
* A string representation of the date, for serialization.
* @var string
*/
private $dateString;
/**
* A string representation of the time zone, for serialization.
* @var string
*/
private $tzString;
/**
* Convenience method to enable a more fluent API.
* @param string $date Date/time value.
* @param DateTimeZone $tz (optional) timezone
*/
public static function newInstance($date, DateTimeZone $tz = null)
{
if ($tz) {
return new DateTime($date, $tz);
} else {
return new DateTime($date);
}
}
/**
* PHP "magic" function called when object is serialized.
* Sets an internal property with the date string and returns properties
* of class that should be serialized.
* @return array string[]
*/
function __sleep()
{
// We need to use a string without a time zone, due to
// PHP bug: http://bugs.php.net/bug.php?id=40743
$this->dateString = $this->format('Y-m-d H:i:s');
$this->tzString = $this->getTimeZone()->getName();
return array('dateString', 'tzString');
}
/**
* PHP "magic" function called when object is restored from serialized state.
* Calls DateTime constructor with previously stored string value of date.
*/
function __wakeup()
{
parent::__construct($this->dateString, new DateTimeZone($this->tzString));
}
}

View file

@ -0,0 +1,349 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* Implements a pager based on a ModelCriteria
* The code from this class heavily borrows from symfony's sfPager class
*
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @author François Zaninotto
* @version $Revision: 1665 $
* @package propel.runtime.query
*/
class PropelModelPager implements IteratorAggregate, Countable
{
protected
$query = null,
$page = 1,
$maxPerPage = 10,
$lastPage = 1,
$nbResults = 0,
$objects = null,
$parameters = array(),
$currentMaxLink = 1,
$parameterHolder = null,
$maxRecordLimit = false,
$results = null,
$resultsCounter = 0;
public function __construct(Criteria $query, $maxPerPage = 10)
{
$this->setQuery($query);
$this->setMaxPerPage($maxPerPage);
}
public function setQuery(Criteria $query)
{
$this->query = $query;
}
public function getQuery()
{
return $this->query;
}
public function init()
{
$hasMaxRecordLimit = ($this->getMaxRecordLimit() !== false);
$maxRecordLimit = $this->getMaxRecordLimit();
$qForCount = clone $this->getQuery();
$count = $qForCount
->offset(0)
->limit(0)
->count();
$this->setNbResults($hasMaxRecordLimit ? min($count, $maxRecordLimit) : $count);
$q = $this->getQuery()
->offset(0)
->limit(0);
if (($this->getPage() == 0 || $this->getMaxPerPage() == 0)) {
$this->setLastPage(0);
} else {
$this->setLastPage(ceil($this->getNbResults() / $this->getMaxPerPage()));
$offset = ($this->getPage() - 1) * $this->getMaxPerPage();
$q->offset($offset);
if ($hasMaxRecordLimit) {
$maxRecordLimit = $maxRecordLimit - $offset;
if ($maxRecordLimit > $this->getMaxPerPage()) {
$q->limit($this->getMaxPerPage());
} else {
$q->limit($maxRecordLimit);
}
} else {
$q->limit($this->getMaxPerPage());
}
}
}
/**
* Get the collection of results in the page
*
* @return PropelObjectCollection A collection of results
*/
public function getResults()
{
if (null === $this->results) {
$this->results = $this->getQuery()
->setFormatter(ModelCriteria::FORMAT_OBJECT)
->find();
}
return $this->results;
}
public function getCurrentMaxLink()
{
return $this->currentMaxLink;
}
public function getMaxRecordLimit()
{
return $this->maxRecordLimit;
}
public function setMaxRecordLimit($limit)
{
$this->maxRecordLimit = $limit;
}
public function getLinks($nb_links = 5)
{
$links = array();
$tmp = $this->page - floor($nb_links / 2);
$check = $this->lastPage - $nb_links + 1;
$limit = ($check > 0) ? $check : 1;
$begin = ($tmp > 0) ? (($tmp > $limit) ? $limit : $tmp) : 1;
$i = (int) $begin;
while (($i < $begin + $nb_links) && ($i <= $this->lastPage)) {
$links[] = $i++;
}
$this->currentMaxLink = count($links) ? $links[count($links) - 1] : 1;
return $links;
}
/**
* Test whether the number of results exceeds the max number of results per page
*
* @return boolean true if the pager displays only a subset of the results
*/
public function haveToPaginate()
{
return (($this->getMaxPerPage() != 0) && ($this->getNbResults() > $this->getMaxPerPage()));
}
/**
* Get the index of the first element in the page
* Returns 1 on the first page, $maxPerPage +1 on the second page, etc
*
* @return int
*/
public function getFirstIndex()
{
if ($this->page == 0) {
return 1;
} else {
return ($this->page - 1) * $this->maxPerPage + 1;
}
}
/**
* Get the index of the last element in the page
* Always less than or eaqual to $maxPerPage
*
* @return int
*/
public function getLastIndex()
{
if ($this->page == 0) {
return $this->nbResults;
} else {
if (($this->page * $this->maxPerPage) >= $this->nbResults) {
return $this->nbResults;
} else {
return ($this->page * $this->maxPerPage);
}
}
}
/**
* Get the total number of results of the query
* This can be greater than $maxPerPage
*
* @return int
*/
public function getNbResults()
{
return $this->nbResults;
}
/**
* Set the total number of results of the query
*
* @param int $nb
*/
protected function setNbResults($nb)
{
$this->nbResults = $nb;
}
/**
* Check whether the current page is the first page
*
* @return boolean true if the current page is the first page
*/
public function isFirstPage()
{
return $this->getPage() == $this->getFirstPage();
}
/**
* Get the number of the first page
*
* @return int Always 1
*/
public function getFirstPage()
{
return 1;
}
/**
* Check whether the current page is the last page
*
* @return boolean true if the current page is the last page
*/
public function isLastPage()
{
return $this->getPage() == $this->getLastPage();
}
/**
* Get the number of the last page
*
* @return int
*/
public function getLastPage()
{
return $this->lastPage;
}
/**
* Set the number of the first page
*
* @param int $page
*/
protected function setLastPage($page)
{
$this->lastPage = $page;
if ($this->getPage() > $page) {
$this->setPage($page);
}
}
/**
* Get the number of the current page
*
* @return int
*/
public function getPage()
{
return $this->page;
}
/**
* Set the number of the current page
*
* @param int $page
*/
public function setPage($page)
{
$this->page = intval($page);
if ($this->page <= 0) {
// set first page, which depends on a maximum set
$this->page = $this->getMaxPerPage() ? 1 : 0;
}
}
/**
* Get the number of the next page
*
* @return int
*/
public function getNextPage()
{
return min($this->getPage() + 1, $this->getLastPage());
}
/**
* Get the number of the previous page
*
* @return int
*/
public function getPreviousPage()
{
return max($this->getPage() - 1, $this->getFirstPage());
}
/**
* Get the maximum number results per page
*
* @return int
*/
public function getMaxPerPage()
{
return $this->maxPerPage;
}
/**
* Set the maximum number results per page
*
* @param int $max
*/
public function setMaxPerPage($max)
{
if ($max > 0) {
$this->maxPerPage = $max;
if ($this->page == 0) {
$this->page = 1;
}
} else if ($max == 0) {
$this->maxPerPage = 0;
$this->page = 0;
} else {
$this->maxPerPage = 1;
if ($this->page == 0) {
$this->page = 1;
}
}
}
public function getIterator()
{
return $this->getResults()->getIterator();
}
/**
* Returns the total number of results.
*
* @see Countable
* @return int
*/
public function count()
{
return $this->getNbResults();
}
}

View file

@ -0,0 +1,597 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* PropelPager
*
* Example Usage:
*
* require_once 'propel/util/PropelPager.php';
* require_once 'PEACH/Propel/Poem/poemPeer.php';
*
* $c = new Criteria();
* $c->addDescendingOrderByColumn(poemPeer::SID);
*
* // with join
* $pager = new PropelPager($c, 'poemPeer', 'doSelectJoinPoemUsers', 1, 50);
*
* // without Join
*
* $pager = new PropelPager($c, 'poemPeer', 'doSelect', 1, 50);
*
* Some template:
*
* <p>
* Total Pages: <?=$pager->getTotalPages()?> Total Records: <?=$pager->getTotalRecordCount()?>
* </p>
* <table>
* <tr>
* <td>
* <?if ($link = $pager->getFirstPage):?>
* <a href="somescript?page=<?=$link?>"><?=$link?></a>|
* <?endif?>
* </td>
* <td>
* <?if ($link = $pager->getPrev()):?>
* <a href="somescript?page=<?=$link?>">Previous</a>|
* <?endif?>
* </td>
* <td>
* <?foreach ($pager->getPrevLinks() as $link):?>
* <a href="somescript?page=<?=$link?>"><?=$link?></a>|
* <?endforeach?>
* </td>
* <td><?=$pager->getPage()?></td>
* <td>
* <?foreach ($pager->getNextLinks() as $link):?>
* | <a href="somescript?page=<?=$link?>"><?=$link?></a>
* <?endforeach?>
* </td>
* <td>
* <?if ($link = $pager->getNext()):?>
* <a href="somescript?page=<?=$link?>">Last</a>|
* <?endif?>
* </td>
* <td>
* <?if ($link = $pager->getLastPage()):?>
* <a href="somescript?page=<?=$link?>"><?=$link?></a>|
* <?endif?>
* </td>
* </tr>
* </table>
* <table id="latestPoems">
* <tr>
* <th>Title</th>
* <th>Auteur</th>
* <th>Date</th>
* <th>comments</th>
* </tr>
* <?foreach ($pager->getResult() as $poem):?>
* <tr>
* <td><?=$poem->getTitle()?></td>
* <td><?=$poem->getPoemUsers()->getUname()?></td>
* <td><?=$poem->getTime()?></td>
* <td><?=$poem->getComments()?></td>
* </tr>
* <?endforeach?>
* </table>
*
*
* @author Rob Halff <info@rhalff.com>
* @author Niklas Närhinen <niklas@narhinen.net>
* @version $Revision: 1612 $
* @copyright Copyright (c) 2004 Rob Halff: LGPL - See LICENCE
* @package propel.runtime.util
*/
class PropelPager implements Countable, Iterator
{
private $recordCount;
private $pages;
private $peerClass;
private $peerSelectMethod;
private $peerCountMethod;
private $criteria;
private $countCriteria;
private $page;
private $rs = null;
//Iterator vars
private $currentKey = 0;
/** @var int Start row (offset) */
protected $start = 0;
/** @var int Max rows to return (0 means all) */
protected $max = 0;
/**
* Create a new Propel Pager.
* @param Criteria $c
* @param string $peerClass The name of the static Peer class.
* @param string $peerSelectMethod The name of the static method for selecting content from the Peer class.
* @param int $page The current page (1-based).
* @param int $rowsPerPage The number of rows that should be displayed per page.
*/
public function __construct($c = null, $peerClass = null, $peerSelectMethod = null, $page = 1, $rowsPerPage = 25)
{
if (!isset($c)) {
$c = new Criteria();
}
$this->setCriteria($c);
$this->setPeerClass($peerClass);
$this->setPeerSelectMethod($peerSelectMethod);
$this->guessPeerCountMethod();
$this->setPage($page);
$this->setRowsPerPage($rowsPerPage);
}
/**
* Set the criteria for this pager.
* @param Criteria $c
* @return void
*/
public function setCriteria(Criteria $c)
{
$this->criteria = $c;
}
/**
* Return the Criteria object for this pager.
* @return Criteria
*/
public function getCriteria()
{
return $this->criteria;
}
/**
* Set the Peer Classname
*
* @param string $class
* @return void
*/
public function setPeerClass($class)
{
$this->peerClass = $class;
}
/**
* Return the Peer Classname.
* @return string
*/
public function getPeerClass()
{
return $this->peerClass;
}
/**
* Set the Peer select method.
* This exists for legacy support, please use setPeerSelectMethod().
* @param string $method The name of the static method to call on the Peer class.
* @return void
* @see setPeerSelectMethod()
* @deprecated
*/
public function setPeerMethod($method)
{
$this->setPeerSelectMethod($method);
}
/**
* Return the Peer select method.
* This exists for legacy support, please use getPeerSelectMethod().
* @return string
* @see getPeerSelectMethod()
* @deprecated
*/
public function getPeerMethod()
{
return $this->getPeerSelectMethod();
}
/**
* Set the Peer select method.
*
* @param string $method The name of the static method to call on the Peer class.
* @return void
*/
public function setPeerSelectMethod($method)
{
$this->peerSelectMethod = $method;
}
/**
* Return the Peer select method.
* @return string
*/
public function getPeerSelectMethod()
{
return $this->peerSelectMethod;
}
/**
* Sets the Count method.
* This is set based on the Peer method, for example if Peer method is doSelectJoin*() then the
* count method will be doCountJoin*().
* @param string $method The name of the static method to call on the Peer class.
*/
public function setPeerCountMethod($method)
{
$this->peerCountMethod = $method;
}
/**
* Return the Peer count method.
*/
public function getPeerCountMethod()
{
return $this->peerCountMethod;
}
/**
* Guesses the Peer count method based on the select method.
*/
private function guessPeerCountMethod()
{
$selectMethod = $this->getPeerSelectMethod();
if ($selectMethod == 'doSelect') {
$countMethod = 'doCount';
} elseif ( ($pos = stripos($selectMethod, 'doSelectJoin')) === 0) {
$countMethod = 'doCount' . substr($selectMethod, strlen('doSelect'));
} else {
// we will fall back to doCount() if we don't understand the join
// method; however, it probably won't be accurate. Maybe triggering an error would
// be appropriate ...
$countMethod = 'doCount';
}
$this->setPeerCountMethod($countMethod);
}
/**
* Get the paged resultset
*
* @return mixed $rs
*/
public function getResult()
{
if (!isset($this->rs)) {
$this->doRs();
}
return $this->rs;
}
/**
* Get the paged resultset
*
* Main method which creates a paged result set based on the criteria
* and the requested peer select method.
*
*/
private function doRs()
{
$this->criteria->setOffset($this->start);
$this->criteria->setLimit($this->max);
$this->rs = call_user_func(array($this->getPeerClass(), $this->getPeerSelectMethod()), $this->criteria);
}
/**
* Get the first page
*
* For now I can only think of returning 1 always.
* It should probably return 0 if there are no pages
*
* @return int 1
*/
public function getFirstPage()
{
return '1';
}
/**
* Convenience method to indicate whether current page is the first page.
*
* @return boolean
*/
public function atFirstPage()
{
return $this->getPage() == $this->getFirstPage();
}
/**
* Get last page
*
* @return int $lastPage
*/
public function getLastPage()
{
$totalPages = $this->getTotalPages();
if ($totalPages == 0) {
return 1;
} else {
return $totalPages;
}
}
/**
* Convenience method to indicate whether current page is the last page.
*
* @return boolean
*/
public function atLastPage()
{
return $this->getPage() == $this->getLastPage();
}
/**
* get total pages
*
* @return int $this->pages
*/
public function getTotalPages() {
if (!isset($this->pages)) {
$recordCount = $this->getTotalRecordCount();
if ($this->max > 0) {
$this->pages = ceil($recordCount/$this->max);
} else {
$this->pages = 0;
}
}
return $this->pages;
}
/**
* get an array of previous id's
*
* @param int $range
* @return array $links
*/
public function getPrevLinks($range = 5)
{
$total = $this->getTotalPages();
$start = $this->getPage() - 1;
$end = $this->getPage() - $range;
$first = $this->getFirstPage();
$links = array();
for ($i=$start; $i>$end; $i--) {
if ($i < $first) {
break;
}
$links[] = $i;
}
return array_reverse($links);
}
/**
* get an array of next id's
*
* @param int $range
* @return array $links
*/
public function getNextLinks($range = 5)
{
$total = $this->getTotalPages();
$start = $this->getPage() + 1;
$end = $this->getPage() + $range;
$last = $this->getLastPage();
$links = array();
for ($i=$start; $i<$end; $i++) {
if ($i > $last) {
break;
}
$links[] = $i;
}
return $links;
}
/**
* Returns whether last page is complete
*
* @return bool Last page complete or not
*/
public function isLastPageComplete()
{
return !($this->getTotalRecordCount() % $this->max);
}
/**
* get previous id
*
* @return mixed $prev
*/
public function getPrev() {
if ($this->getPage() != $this->getFirstPage()) {
$prev = $this->getPage() - 1;
} else {
$prev = false;
}
return $prev;
}
/**
* get next id
*
* @return mixed $next
*/
public function getNext() {
if ($this->getPage() != $this->getLastPage()) {
$next = $this->getPage() + 1;
} else {
$next = false;
}
return $next;
}
/**
* Set the current page number (First page is 1).
* @param int $page
* @return void
*/
public function setPage($page)
{
$this->page = $page;
// (re-)calculate start rec
$this->calculateStart();
}
/**
* Get current page.
* @return int
*/
public function getPage()
{
return $this->page;
}
/**
* Set the number of rows per page.
* @param int $r
*/
public function setRowsPerPage($r)
{
$this->max = $r;
// (re-)calculate start rec
$this->calculateStart();
}
/**
* Get number of rows per page.
* @return int
*/
public function getRowsPerPage()
{
return $this->max;
}
/**
* Calculate startrow / max rows based on current page and rows-per-page.
* @return void
*/
private function calculateStart()
{
$this->start = ( ($this->page - 1) * $this->max );
}
/**
* Gets the total number of (un-LIMITed) records.
*
* This method will perform a query that executes un-LIMITed query.
*
* @return int Total number of records - disregarding page, maxrows, etc.
*/
public function getTotalRecordCount()
{
if (!isset($this->rs)) {
$this->doRs();
}
if (empty($this->recordCount)) {
$this->countCriteria = clone $this->criteria;
$this->countCriteria->setLimit(0);
$this->countCriteria->setOffset(0);
$this->recordCount = call_user_func(
array(
$this->getPeerClass(),
$this->getPeerCountMethod()
),
$this->countCriteria
);
}
return $this->recordCount;
}
/**
* Sets the start row or offset.
* @param int $v
*/
public function setStart($v)
{
$this->start = $v;
}
/**
* Sets max rows (limit).
* @param int $v
* @return void
*/
public function setMax($v)
{
$this->max = $v;
}
/**
* Returns the count of the current page's records
* @return int
*/
public function count()
{
return count($this->getResult());
}
/**
* Returns the current element of the iterator
* @return mixed
*/
public function current()
{
if (!isset($this->rs)) {
$this->doRs();
}
return $this->rs[$this->currentKey];
}
/**
* Returns the current key of the iterator
* @return int
*/
public function key()
{
return $this->currentKey;
}
/**
* Advances the iterator to the next element
* @return void
*/
public function next()
{
$this->currentKey++;
}
/**
* Resets the iterator to the first element
* @return void
*/
public function rewind()
{
$this->currentKey = 0;
}
/**
* Checks if the current key exists in the container
* @return boolean
*/
public function valid()
{
if (!isset($this->rs)) {
$this->doRs();
}
return in_array($this->currentKey, array_keys($this->rs));
}
}

View file

@ -0,0 +1,35 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* Basic Validator interface.
*
* BasicValidator objects perform validation without any knowledge of column/table
* context. They are simply given an input and some value and asked whether the input
* is valid.
*
* @author Michael Aichler <aichler@mediacluster.de>
* @version $Revision: 1612 $
* @package propel.runtime.validator
*/
interface BasicValidator
{
/**
* Determine whether a value meets the criteria specified
*
* @param ValidatorMap $map A column map object for the column to be validated.
* @param string $str a <code>String</code> to be tested
*
* @return mixed TRUE if valid, error message otherwise
*/
public function isValid(ValidatorMap $map, $str);
}

View file

@ -0,0 +1,68 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* A validator for regular expressions.
*
* This validator will return true, when the passed value *matches* the
* regular expression.
*
* ## This class replaces the former class MaskValidator ##
*
* If you do want to test if the value does *not* match an expression,
* you can use the MatchValidator class instead.
*
* Below is an example usage for your Propel xml schema file.
*
* <code>
* <column name="email" type="VARCHAR" size="128" required="true" />
* <validator column="username">
* <!-- allow strings that match the email adress pattern -->
* <rule
* name="match"
* value="/^([a-zA-Z0-9])+([\.a-zA-Z0-9_-])*@([a-zA-Z0-9])+(\.[a-zA-Z0-9_-]+)+$/"
* message="Please enter a valid email address." />
* </validator>
* </code>
*
* @author Michael Aichler <aichler@mediacluster.de>
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 1612 $
* @package propel.runtime.validator
*/
class MatchValidator implements BasicValidator
{
/**
* Prepares the regular expression entered in the XML
* for use with preg_match().
* @param string $exp
* @return string Prepared regular expession.
*/
private function prepareRegexp($exp)
{
// remove surrounding '/' marks so that they don't get escaped in next step
if ($exp{0} !== '/' || $exp{strlen($exp)-1} !== '/' ) {
$exp = '/' . $exp . '/';
}
// if they did not escape / chars; we do that for them
$exp = preg_replace('/([^\\\])\/([^$])/', '$1\/$2', $exp);
return $exp;
}
/**
* Whether the passed string matches regular expression.
*/
public function isValid (ValidatorMap $map, $str)
{
return (preg_match($this->prepareRegexp($map->getValue()), $str) != 0);
}
}

View file

@ -0,0 +1,39 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* A validator for maximum string length.
*
* Below is an example usage for your Propel xml schema file.
*
* Note that if you have specified the size attribute in the column tag
* you do not have to specify it as value in the validator rule again as
* this is done automatically.
*
* <code>
* <column name="username" type="VARCHAR" size="25" required="true" />
*
* <validator column="username">
* <rule name="maxLength" message="Passwort must be at least ${value} characters !" />
* </validator>
* </code>
*
* @author Michael Aichler <aichler@mediacluster.de>
* @version $Revision: 1612 $
* @package propel.runtime.validator
*/
class MaxLengthValidator implements BasicValidator
{
public function isValid (ValidatorMap $map, $str)
{
return strlen($str) <= intval($map->getValue());
}
}

View file

@ -0,0 +1,43 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* A validator for maximum values.
*
* Below is an example usage for your Propel xml schema file.
*
* <code>
* <column name="articles" type="INTEGER" required="true" />
*
* <validator column="articles">
* <rule name="minValue" value="1" message="Minimum value for selected articles is ${value} !" />
* <rule name="maxValue" value="10" message="Maximum value for selected articles is ${value} !" />
* </validator>
* </code>
*
* @author Michael Aichler <aichler@mediacluster.de>
* @version $Revision: 1612 $
* @package propel.runtime.validator
*/
class MaxValueValidator implements BasicValidator
{
/**
* @see BasicValidator::isValid()
*/
public function isValid (ValidatorMap $map, $value)
{
if (is_null($value) == false && is_numeric($value) == true) {
return intval($value) <= intval($map->getValue());
}
return false;
}
}

View file

@ -0,0 +1,36 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* A validator for minimum string length.
*
* <code>
* <column name="password" type="VARCHAR" size="34" required="true" />
*
* <validator column="password">
* <rule name="minLength" value="5" message="Passwort must be at least ${value} characters !" />
* </validator>
* </code>
*
* @author Michael Aichler <aichler@mediacluster.de>
* @version $Revision: 1612 $
* @package propel.runtime.validator
*/
class MinLengthValidator implements BasicValidator
{
/**
* @see BasicValidator::isValid()
*/
public function isValid (ValidatorMap $map, $str)
{
return strlen($str) >= intval($map->getValue());
}
}

View file

@ -0,0 +1,43 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* A validator for minimum values.
*
* Below is an example usage for your Propel xml schema file.
*
* <code>
* <column name="articles" type="INTEGER" required="true" />
*
* <validator column="articles">
* <rule name="minValue" value="1" message="Minimum value for selected articles is ${value} !" />
* <rule name="maxValue" value="10" message="Maximum value for selected articles is ${value} !" />
* </validator>
* </code>
*
* @author Michael Aichler <aichler@mediacluster.de>
* @version $Revision: 1612 $
* @package propel.runtime.validator
*/
class MinValueValidator implements BasicValidator
{
/**
* @see BasicValidator::isValid()
*/
public function isValid (ValidatorMap $map, $value)
{
if (is_null($value) == false && is_numeric($value)) {
return intval($value) >= intval($map->getValue());
}
return false;
}
}

View file

@ -0,0 +1,66 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* A validator for regular expressions.
*
* This validator will return true, when the passed value does *not* match
* the regular expression.
*
* If you do want to test if the value *matches* an expression, you can use
* the MatchValidator class instead.
*
* Below is an example usage for your Propel xml schema file.
*
* <code>
* <column name="ISBN" type="VARCHAR" size="20" required="true" />
* <validator column="username">
* <!-- disallow everything that's not a digit or minus -->
* <rule
* name="notMatch"
* value="/[^\d-]+/"
* message="Please enter a valid email adress." />
* </validator>
* </code>
*
* @author Michael Aichler <aichler@mediacluster.de>
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 1612 $
* @package propel.runtime.validator
*/
class NotMatchValidator implements BasicValidator
{
/**
* Prepares the regular expression entered in the XML
* for use with preg_match().
* @param string $exp
* @return string Prepared regular expession.
*/
private function prepareRegexp($exp)
{
// remove surrounding '/' marks so that they don't get escaped in next step
if ($exp{0} !== '/' || $exp{strlen($exp)-1} !== '/' ) {
$exp = '/' . $exp . '/';
}
// if they did not escape / chars; we do that for them
$exp = preg_replace('/([^\\\])\/([^$])/', '$1\/$2', $exp);
return $exp;
}
/**
* Whether the passed string matches regular expression.
*/
public function isValid (ValidatorMap $map, $str)
{
return (preg_match($this->prepareRegexp($map->getValue()), $str) == 0);
}
}

View file

@ -0,0 +1,38 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* A validator for required fields.
*
* Below is an example usage for your Propel xml schema file.
*
* <code>
* <column name="username" type="VARCHAR" size="25" required="true" />
*
* <validator column="username">
* <rule name="required" message="Username is required." />
* </validator>
* </code>
*
* @author Michael Aichler <aichler@mediacluster.de>
* @version $Revision: 1612 $
* @package propel.runtime.validator
*/
class RequiredValidator implements BasicValidator
{
/**
* @see BasicValidator::isValid()
*/
public function isValid (ValidatorMap $map, $str)
{
return ($str !== null && $str !== "");
}
}

View file

@ -0,0 +1,68 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* A validator for validating the (PHP) type of the value submitted.
*
* <code>
* <column name="some_int" type="INTEGER" required="true"/>
*
* <validator column="some_int">
* <rule name="type" value="integer" message="Please specify an integer value for some_int column." />
* </validator>
* </code>
*
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 1612 $
* @package propel.runtime.validator
*/
class TypeValidator implements BasicValidator
{
public function isValid(ValidatorMap $map, $value)
{
switch ($map->getValue()) {
case 'array':
return is_array($value);
break;
case 'bool':
case 'boolean':
return is_bool($value);
break;
case 'float':
return is_float($value);
break;
case 'int':
case 'integer':
return is_int($value);
break;
case 'numeric':
return is_numeric($value);
break;
case 'object':
return is_object($value);
break;
case 'resource':
return is_resource($value);
break;
case 'scalar':
return is_scalar($value);
break;
case 'string':
return is_string($value);
break;
case 'function':
return function_exists($value);
break;
default:
throw new PropelException('Unkonwn type ' . $map->getValue());
break;
}
}
}

View file

@ -0,0 +1,48 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* A validator for unique column names.
*
* <code>
* <column name="username" type="VARCHAR" size="25" required="true" />
*
* <validator column="username">
* <rule name="unique" message="Username already exists !" />
* </validator>
* </code>
*
* @author Michael Aichler <aichler@mediacluster.de>
* @version $Revision: 1612 $
* @package propel.runtime.validator
*/
class UniqueValidator implements BasicValidator
{
/**
* @see BasicValidator::isValid()
*/
public function isValid (ValidatorMap $map, $str)
{
$column = $map->getColumn();
$c = new Criteria();
$c->add($column->getFullyQualifiedName(), $str, Criteria::EQUAL);
$table = $column->getTable()->getClassName();
$clazz = $table . 'Peer';
$count = call_user_func(array($clazz, 'doCount'), $c);
$isValid = ($count === 0);
return $isValid;
}
}

View file

@ -0,0 +1,33 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* A validator for valid values (e.g. for enum fields)
*
* <code>
* <column name="address_type" type="VARCHAR" required="true" default="delivery" />
*
* <validator column="address_type">
* <rule name="validValues" value="account|delivery" message="Please select a valid address type." />
* </validator>
* </code>
*
* @author Michael Aichler <aichler@mediacluster.de>
* @version $Revision: 1612 $
* @package propel.runtime.validator
*/
class ValidValuesValidator implements BasicValidator
{
public function isValid (ValidatorMap $map, $str)
{
return in_array($str, preg_split("/[|,]/", $map->getValue()));
}
}

View file

@ -0,0 +1,115 @@
<?php
/**
* This file is part of the Propel package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
/**
* Simple class that serves as a container for any information about a failed validation.
*
* Currently this class stores the qualified column name (e.g. tablename.COLUMN_NAME) and
* the message that should be displayed to the user.
*
* An array of these objects will be returned by BasePeer::doValidate() if validation
* failed.
*
* @author Hans Lellelid <hans@xmpl.org>
* @version $Revision: 1612 $
* @package propel.runtime.validator
* @see BasePeer::doValidate()
*/
class ValidationFailed {
/** Column name in tablename.COLUMN_NAME format */
private $colname;
/** Message to display to user. */
private $message;
/** Validator object that caused this to fail. */
private $validator;
/**
* Construct a new ValidationFailed object.
* @param string $colname Column name.
* @param string $message Message to display to user.
* @param object $validator The Validator that caused this column to fail.
*/
public function __construct($colname, $message, $validator = null)
{
$this->colname = $colname;
$this->message = $message;
$this->validator = $validator;
}
/**
* Set the column name.
* @param string $v
*/
public function setColumn($v)
{
$this->colname = $v;
}
/**
* Gets the column name.
* @return string Qualified column name (tablename.COLUMN_NAME)
*/
public function getColumn()
{
return $this->colname;
}
/**
* Set the message for the validation failure.
* @param string $v
*/
public function setMessage($v)
{
$this->message = $v;
}
/**
* Gets the message for the validation failure.
* @return string
*/
public function getMessage()
{
return $this->message;
}
/**
* Set the validator object that caused this to fail.
* @param object $v
*/
public function setValidator($v)
{
$this->validator = $v;
}
/**
* Gets the validator object that caused this to fail.
* @return object
*/
public function getValidator()
{
return $this->validator;
}
/**
* "magic" method to get string represenation of object.
* Maybe someday PHP5 will support the invoking this method automatically
* on (string) cast. Until then it's pretty useless.
* @return string
*/
public function __toString()
{
return $this->getMessage();
}
}