initial commit

This commit is contained in:
Chris Sewell
2012-11-28 03:55:08 -05:00
parent 7adb399b2e
commit cf140a2e97
3247 changed files with 492437 additions and 0 deletions

View File

@ -0,0 +1,42 @@
<?php
/*
* This file is part of the symfony package.
* (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
$sf_ez_lib_dir = sfConfig::get('sf_ez_lib_dir') ? sfConfig::get('sf_ez_lib_dir').'/' : '';
if (file_exists($sf_ez_lib_dir.'Base/src/base.php'))
{
// svn installation
require_once($sf_ez_lib_dir.'Base/src/base.php');
}
elseif (file_exists($sf_ez_lib_dir.'Base/base.php'))
{
// pear installation
require_once($sf_ez_lib_dir.'Base/base.php');
}
else
{
throw new sfAutoloadException('Invalid eZ component library path.');
}
/**
* This class makes easy to use ez components classes within symfony
*
* @package symfony
* @subpackage addon
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @version SVN: $Id: sfEzComponentsBridge.class.php 5362 2007-10-04 06:40:04Z noel $
*/
class sfEzComponentsBridge
{
public static function autoload($class)
{
return ezcBase::autoload($class);
}
}

View File

@ -0,0 +1,92 @@
<?php
/*
* This file is part of the symfony package.
* (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
if (sfConfig::get('sf_zend_lib_dir'))
{
set_include_path(sfConfig::get('sf_zend_lib_dir').PATH_SEPARATOR.get_include_path());
}
sfZendFrameworkBridge::requireZendLoader();
/**
* This class makes easy to use Zend Framework classes within symfony.
*
* @package symfony
* @subpackage addon
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @version SVN: $Id: sfZendFrameworkBridge.class.php 4752 2007-07-31 08:58:33Z fabien $
*/
class sfZendFrameworkBridge
{
public static function autoload($class)
{
try
{
if (class_exists('Zend_Version'))
{
Zend_Loader::loadClass($class);
}
else
{
Zend::loadClass($class);
}
}
catch (Zend_Exception $e)
{
return false;
}
return true;
}
/**
* Detect and return the path to current Zend loader class.
*
* Starting from ZF 0.9.0 autoloading function has been moved
* from Zend.php to Zend/Version.php class.
* Starting from ZF 1.0.0 Zend.php class no longer exists.
*
* This function tries to detect whether Zend_Version exists
* and returns its path if yes.
* If the first step fails, the class will try to find Zend.php library
* available in ZF <= 0.9.0 and returns its path if its exists.
*
* If neither Zend/Version.php nor Zend.php exists,
* then this function will raise a sfAutoloadException exception.
*
* @return string Path to default Zend Loader class
* @throws sfAutoloadException
*
* @author Simone Carletti <weppos@weppos.net>
*/
public static function requireZendLoader()
{
// get base path according to sf setting
$base = sfConfig::get('sf_zend_lib_dir') ? sfConfig::get('sf_zend_lib_dir').'/' : '';
// first check whether Zend/Version.php exists
// Zend/Version.php is available starting from ZF 0.9.0
// Before ZF 0.9.0 you should call Zend.php
// Plese note that Zend.php is still available in ZF 0.9.0
// but it should not be called because deprecated
if (file_exists($base.'Zend/Version.php'))
{
require_once($base.'Zend/Version.php');
}
else if (file_exists($base.'Zend.php'))
{
require_once($base.'Zend.php');
}
else
{
throw new sfAutoloadException('Invalid Zend Framework library structure, unable to find Zend/Version.php (ZF >= 0.9.0) or Zend.php (ZF < 0.9.0) library');
}
}
}

View File

@ -0,0 +1,212 @@
<?php
/*
* This file is part of the symfony package.
* (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
* (c) 2004-2006 Sean Kerr.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* sfCreoleDatabase provides connectivity for the Creole database abstraction
* layer.
*
* <b>Optional parameters:</b>
*
* # <b>classpath</b> - [none] - An absolute filesystem path to the main
* Creole class file.
* # <b>database</b> - [none] - The database name.
* # <b>dsn</b> - [none] - The DSN formatted connection string.
* # <b>host</b> - [none] - The database host specifications.
* # <b>port</b> - [none] - The database port.
* # <b>encoding</b> - [none] - The database encoding.
* # <b>method</b> - [normal] - How to read connection parameters.
* Possible values are dsn, normal,
* server, and env. The dsn method reads
* them from the dsn parameter. The
* normal method reads them from the
* specified values. server reads them
* from $_SERVER where the keys to
* retrieve the values are what you
* specify the value as in the settings.
* env reads them from $_ENV and works
* like $_SERVER.
* # <b>no_assoc_lower</b> - [Off] - Turn off portabilty of resultset
* field names.
* # <b>password</b> - [none] - The database password.
* # <b>persistent</b> - [No] - Indicates that the connection should
* persistent.
* # <b>phptype</b> - [none] - The type of database (mysql, pgsql,
* etc).
* # <b>username</b> - [none] - The database username.
*
* @package symfony
* @subpackage database
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @author Sean Kerr <skerr@mojavi.org>
* @version SVN: $Id: sfCreoleDatabase.class.php 3329 2007-01-23 08:29:34Z fabien $
*/
class sfCreoleDatabase extends sfDatabase
{
/**
* Connect to the database.
*
* @throws <b>sfDatabaseException</b> If a connection could not be created.
*/
public function connect()
{
try
{
// determine how to get our settings
$method = $this->getParameter('method', 'normal');
switch ($method)
{
case 'normal':
// get parameters normally, and all are required
$database = $this->getParameter('database', null);
$hostspec = $this->getParameter('hostspec') ? $this->getParameter('hostspec') : ($this->getParameter('host') ? $this->getParameter('hostspec') : null);
$password = $this->getParameter('password', null);
$phptype = $this->getParameter('phptype', null);
$username = $this->getParameter('username', null);
$port = $this->getParameter('port', null);
$encoding = $this->getParameter('encoding', null);
$dsn = array('database' => $database,
'hostspec' => $hostspec,
'password' => $password,
'phptype' => $phptype,
'username' => $username,
'port' => $port,
'encoding' => $encoding);
break;
case 'dsn':
$dsn = $this->getParameter('dsn');
if ($dsn == null)
{
// missing required dsn parameter
$error = 'Database configuration specifies method "dsn", but is missing dsn parameter';
throw new sfDatabaseException($error);
}
break;
case 'server':
// construct a DSN connection string from existing $_SERVER values
$dsn =& $this->loadDSN($_SERVER);
break;
case 'env':
// construct a DSN connection string from existing $_ENV values
$dsn =& $this->loadDSN($_ENV);
break;
default:
// who knows what the user wants...
$error = 'Invalid CreoleDatabase parameter retrieval method "%s"';
$error = sprintf($error, $method);
throw new sfDatabaseException($error);
}
// get creole class path
$classPath = $this->getParameter('classpath');
// include the creole file
if ($classPath == null)
{
require_once('creole/Creole.php');
}
else
{
require_once($classPath);
}
// set our flags
$noAssocLower = $this->getParameter('no_assoc_lower', false);
$persistent = $this->getParameter('persistent', false);
$compatAssocLower = $this->getParameter('compat_assoc_lower', false);
$compatRtrimString = $this->getParameter('compat_rtrim_string', false);
$flags = 0;
$flags |= ($noAssocLower) ? Creole::NO_ASSOC_LOWER : 0;
$flags |= ($persistent) ? Creole::PERSISTENT : 0;
$flags |= ($compatAssocLower) ? Creole::COMPAT_ASSOC_LOWER : 0;
$flags |= ($compatRtrimString) ? Creole::COMPAT_RTRIM_STRING : 0;
// do the duuuurtay work, right thurr
if ($flags > 0)
{
$this->connection = Creole::getConnection($dsn, $flags);
}
else
{
$this->connection = Creole::getConnection($dsn);
}
// get our resource
$this->resource = $this->connection->getResource();
}
catch (SQLException $e)
{
// the connection's foobar'd
throw new sfDatabaseException($e->toString());
}
}
/**
* Load a DSN connection string from an existing array.
*
* @return array An associative array of connection parameters.
*/
protected function & loadDSN(&$array)
{
// determine if a dsn is set, otherwise use separate parameters
$dsn = $this->getParameter('dsn');
if ($dsn == null)
{
// list of available parameters
$available = array('database', 'hostspec', 'password', 'phptype', 'username', 'port');
$dsn = array();
// yes, i know variable variables are ugly, but let's avoid using
// an array for array's sake in this single spot in the source
foreach ($available as $parameter)
{
$$parameter = $this->getParameter($parameter);
$dsn[$parameter] = ($$parameter != null) ? $array[$$parameter] : null;
}
}
else
{
$dsn = $array[$dsn];
}
return $dsn;
}
/**
* Execute the shutdown procedure.
*
* @return void
*
* @throws <b>sfDatabaseException</b> If an error occurs while shutting down this database.
*/
public function shutdown()
{
if ($this->connection !== null)
{
@$this->connection->close();
}
}
}

View File

@ -0,0 +1,294 @@
<?php
/**
* Debug implementation of Connection.
*
* This is a Connection that implements the decorator pattern, wrapping around
* the true Connection object (stored in $childConnection). This Connection
* tracks information about queries executed and makes that information available
* for debugging purposes. The information tracked is the last query executed
* on the connection (getLastExecutedQuery()) and the total number of
* queries executed on the connection thus far (getNumQueriesExecuted()).
*
* To use this debug connection, you need to register it as a new Creole
* driver that handles all connection types. To do this, call the following
* before calling Creole::getConnection():
*
* <code>
* Creole::registerDriver('*', 'creole.drivers.debug.DebugConnection');
* </code>
*
* The next call to Creole::getConnection() will return an instance of
* DebugConnection.
*
* @author Michael Sims
* @package creole.drivers.debug
*/
class sfDebugConnection implements Connection
{
/** @var Connection */
private $childConnection = null;
/** @var int */
private $numQueriesExecuted = 0;
/** @var string */
private $lastExecutedQuery = '';
/**
* Optional PEAR Log class; if set queries will be logged at PEAR_LOG_INFO level.
* @var Log
*/
private static $logger;
/**
* Sets a Logger class (e.g. PEAR Log) to use for logging.
* The logger class must have a log() method. All messages are logged at default log level.
* @param object $logger
*/
public static function setLogger($logger)
{
self::$logger = $logger;
}
/**
* Returns the number of queries executed on this connection so far
*
* @return int
*/
public function getNumQueriesExecuted()
{
return $this->numQueriesExecuted;
}
/**
* Returns the last query executed on this connection
*
* @return string
*/
public function getLastExecutedQuery()
{
return $this->lastExecutedQuery;
}
/**
* connect()
*/
public function connect($dsninfo, $flags = 0)
{
if (!($driver = Creole::getDriver($dsninfo['phptype'])))
{
throw new SQLException("No driver has been registered to handle connection type: $type");
}
$connectionClass = Creole::import($driver);
$this->childConnection = new $connectionClass();
$this->log("{sfCreole} connect(): DSN: ". var_export($dsninfo, true) . ", FLAGS: " . var_export($flags, true));
return $this->childConnection->connect($dsninfo, $flags);
}
/**
* @see Connection::getDatabaseInfo()
*/
public function getDatabaseInfo()
{
return $this->childConnection->getDatabaseInfo();
}
/**
* @see Connection::getIdGenerator()
*/
public function getIdGenerator()
{
return $this->childConnection->getIdGenerator();
}
/**
* @see Connection::isConnected()
*/
public function isConnected()
{
return $this->childConnection->isConnected();
}
/**
* @see Connection::prepareStatement()
*/
public function prepareStatement($sql)
{
$this->log("{sfCreole} prepareStatement(): $sql");
$obj = $this->childConnection->prepareStatement($sql);
$objClass = get_class($obj);
return new $objClass($this, $sql);
}
/**
* @see Connection::createStatement()
*/
public function createStatement()
{
$obj = $this->childConnection->createStatement();
$objClass = get_class($obj);
return new $objClass($this);
}
/**
* @see Connection::applyLimit()
*/
public function applyLimit(&$sql, $offset, $limit)
{
$this->log("{sfCreole} applyLimit(): $sql, offset: $offset, limit: $limit");
return $this->childConnection->applyLimit($sql, $offset, $limit);
}
/**
* @see Connection::close()
*/
public function close()
{
$this->log("{sfCreole} close(): Closing connection.");
return $this->childConnection->close();
}
/**
* @see Connection::executeQuery()
*/
public function executeQuery($sql, $fetchmode = null)
{
$this->lastExecutedQuery = $sql;
$this->numQueriesExecuted++;
$elapsedTime = 0;
if (sfConfig::get('sf_debug') && sfConfig::get('sf_logging_enabled'))
{
$sqlTimer = sfTimerManager::getTimer('Database');
$timer = new sfTimer();
}
$retval = $this->childConnection->executeQuery($sql, $fetchmode);
if (sfConfig::get('sf_debug') && sfConfig::get('sf_logging_enabled'))
{
$sqlTimer->addTime();
$elapsedTime = $timer->getElapsedTime();
}
$this->log(sprintf("{sfCreole} executeQuery(): [%.2f ms] %s", $elapsedTime * 1000, $sql));
return $retval;
}
/**
* @see Connection::executeUpdate()
**/
public function executeUpdate($sql)
{
$this->log("{sfCreole} executeUpdate(): $sql");
$this->lastExecutedQuery = $sql;
$this->numQueriesExecuted++;
return $this->childConnection->executeUpdate($sql);
}
/**
* @see Connection::getUpdateCount()
*/
public function getUpdateCount()
{
return $this->childConnection->getUpdateCount();
}
/**
* @see Connection::prepareCall()
**/
public function prepareCall($sql)
{
$this->log("{sfCreole} prepareCall(): $sql");
return $this->childConnection->prepareCall($sql);
}
/**
* @see Connection::getResource()
*/
public function getResource()
{
return $this->childConnection->getResource();
}
/**
* @see Connection::connect()
*/
public function getDSN()
{
return $this->childConnection->getDSN();
}
/**
* @see Connection::getFlags()
*/
public function getFlags()
{
return $this->childConnection->getFlags();
}
/**
* @see Connection::begin()
*/
public function begin()
{
$this->log("{sfCreole} beginning transaction.");
return $this->childConnection->begin();
}
/**
* @see Connection::commit()
*/
public function commit()
{
$this->log("{sfCreole} committing transaction.");
return $this->childConnection->commit();
}
/**
* @see Connection::rollback()
*/
public function rollback()
{
$this->log("{sfCreole} rolling back transaction.");
return $this->childConnection->rollback();
}
/**
* @see Connection::setAutoCommit()
*/
public function setAutoCommit($bit)
{
$this->log("{sfCreole} setting autocommit to: ".var_export($bit, true));
return $this->childConnection->setAutoCommit($bit);
}
/**
* @see Connection::getAutoCommit()
*/
public function getAutoCommit()
{
return $this->childConnection->getAutoCommit();
}
/**
* Private function that logs message using specified logger (if provided).
* @param string $msg Message to log.
*/
private function log($msg)
{
if (self::$logger)
{
// message on one line
$msg = preg_replace("/\r?\n/", ' ', $msg);
self::$logger->log($msg);
}
}
public function __call($method, $arguments)
{
return $this->childConnection->$method($arguments);
}
}

View File

@ -0,0 +1,445 @@
<?php
/**
* sfMessageSource_Creole class file.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the BSD License.
*
* Copyright(c) 2004 by Qiang Xue. All rights reserved.
*
* To contact the author write to {@link mailto:qiang.xue@gmail.com Qiang Xue}
* The latest version of PRADO can be obtained from:
* {@link http://prado.sourceforge.net/}
*
* @author Wei Zhuo <weizhuo[at]gmail[dot]com>
* @version $Id: sfMessageSource_Creole.class.php 3245 2007-01-12 15:01:53Z fabien $
* @package symfony
* @subpackage i18n
*/
/*
CREATE TABLE `catalogue` (
`cat_id` int(11) NOT NULL auto_increment,
`name` varchar(100) NOT NULL default '',
`source_lang` varchar(100) NOT NULL default '',
`target_lang` varchar(100) NOT NULL default '',
`date_created` int(11) NOT NULL default '0',
`date_modified` int(11) NOT NULL default '0',
`author` varchar(255) NOT NULL default '',
PRIMARY KEY (`cat_id`)
);
CREATE TABLE `trans_unit` (
`msg_id` int(11) NOT NULL auto_increment,
`cat_id` int(11) NOT NULL default '1',
`source` text NOT NULL,
`target` text NOT NULL,
`comments` text NOT NULL,
`date_added` int(11) NOT NULL default '0',
`date_modified` int(11) NOT NULL default '0',
`author` varchar(255) NOT NULL default '',
`translated` tinyint(1) NOT NULL default '0',
PRIMARY KEY (`msg_id`)
);
*/
/**
* sfMessageSource_Creole class.
*
* Retrieve the message translation from a Creole supported database.
*
* See the MessageSource::factory() method to instantiate this class.
*
* @author RoVeRT <symfony[at]rovert[dot]net>
*/
class sfMessageSource_Creole extends sfMessageSource
{
/**
* A resource link to the database
* @var db
*/
protected $db;
/**
* Constructor.
* Create a new message source using Creole.
* @param string Creole datasource.
* @see MessageSource::factory();
*/
public function __construct($source)
{
$this->db = sfContext::getInstance()->getDatabaseConnection($source);
if ($this->db == null || !$this->db instanceof Connection)
{
$error = 'Creole dabatase connection doesn\'t exist. Unable to open session.';
throw new sfDatabaseException($error);
}
}
/**
* Destructor, close the database connection.
*/
public function __destruct()
{
}
/**
* Get the database connection.
* @return db database connection.
*/
public function connection()
{
return $this->db;
}
/**
* Get an array of messages for a particular catalogue and cultural
* variant.
* @param string the catalogue name + variant
* @return array translation messages.
*/
protected function &loadData($variant)
{
$sql = 'SELECT t.source, t.target, t.comments '.
'FROM trans_unit t, catalogue c '.
'WHERE c.cat_id = t.cat_id AND c.name = ? '.
'ORDER BY msg_id ASC';
$stmt = $this->db->prepareStatement($sql);
$rs = $stmt->executeQuery(array($variant), ResultSet::FETCHMODE_NUM);
$result = array();
$count = 0;
while ($rs->next())
{
$source = $rs->getString(1);
$result[$source][] = $rs->getString(2); //target
$result[$source][] = $count++; //id
$result[$source][] = $rs->getString(3); //comments
}
return $result;
}
/**
* Get the last modified unix-time for this particular catalogue+variant.
* We need to query the database to get the date_modified.
*
* @param string catalogue+variant
* @return int last modified in unix-time format.
*/
protected function getLastModified($source)
{
$sql = 'SELECT date_modified FROM catalogue WHERE name = ?';
$stmt = $this->db->prepareStatement($sql);
$rs = $stmt->executeQuery(array($source), ResultSet::FETCHMODE_NUM);
$result = $rs->next() ? $rs->getInt(1) : 0;
return $result;
}
/**
* Check if a particular catalogue+variant exists in the database.
*
* @param string catalogue+variant
* @return boolean true if the catalogue+variant is in the database, false otherwise.
*/
protected function isValidSource($variant)
{
$sql = 'SELECT COUNT(*) FROM catalogue WHERE name = ?';
$stmt = $this->db->prepareStatement($sql);
$rs = $stmt->executeQuery(array($variant), ResultSet::FETCHMODE_NUM);
$result = $rs->next() ? $rs->getInt(1) == 1 : false;
return $result;
}
/**
* Get all the variants of a particular catalogue.
*
* @param string catalogue name
* @return array list of all variants for this catalogue.
*/
protected function getCatalogueList($catalogue)
{
$variants = explode('_', $this->culture);
$catalogues = array($catalogue);
$variant = null;
for ($i = 0, $max = count($variants); $i < $max; $i++)
{
if (strlen($variants[$i]) > 0)
{
$variant .= ($variant) ? '_'.$variants[$i] : $variants[$i];
$catalogues[] = $catalogue.'.'.$variant;
}
}
return array_reverse($catalogues);
}
/**
* Retrieve catalogue details, array($cat_id, $variant, $count).
*
* @param string catalogue
* @return array catalogue details, array($cat_id, $variant, $count).
*/
protected function getCatalogueDetails($catalogue = 'messages')
{
if (empty($catalogue))
{
$catalogue = 'messages';
}
$variant = $catalogue.'.'.$this->culture;
$name = $this->getSource($variant);
$sql = 'SELECT cat_id FROM catalogue WHERE name = ?';
$stmt = $this->db->prepareStatement($sql);
$rs = $stmt->executeQuery(array($name), ResultSet::FETCHMODE_NUM);
if ($rs->getRecordCount() != 1)
{
return false;
}
$rs->next();
$cat_id = $rs->getInt(1);
//first get the catalogue ID
$sql = 'SELECT count(msg_id) FROM trans_unit WHERE cat_id = ?';
$stmt = $this->db->prepareStatement($sql);
$rs = $stmt->executeQuery(array($cat_id), ResultSet::FETCHMODE_NUM);
$rs->next();
$count = $rs->getInt(1);
return array($cat_id, $variant, $count);
}
/**
* Update the catalogue last modified time.
*
* @return boolean true if updated, false otherwise.
*/
protected function updateCatalogueTime($cat_id, $variant)
{
$time = time();
$sql = 'UPDATE catalogue SET date_modified = ? WHERE cat_id = ?';
$stmt = $this->db->prepareStatement($sql);
$result = $stmt->executeUpdate(array($time, $cat_id));
if (!empty($this->cache))
{
$this->cache->clean($variant, $this->culture);
}
return true;
}
/**
* Save the list of untranslated blocks to the translation source.
* If the translation was not found, you should add those
* strings to the translation source via the <b>append()</b> method.
*
* @param string the catalogue to add to
* @return boolean true if saved successfuly, false otherwise.
*/
function save($catalogue='messages')
{
$messages = $this->untranslated;
if (count($messages) <= 0)
{
return false;
}
$details = $this->getCatalogueDetails($catalogue);
if ($details)
{
list($cat_id, $variant, $count) = $details;
}
else
{
return false;
}
if ($cat_id <= 0)
{
return false;
}
$inserted = 0;
$time = time();
try
{
$sql = 'SELECT msg_id FROM trans_unit WHERE source = ?';
$stmt = $this->db->prepareStatement($sql);
foreach($messages as $key => $message)
{
$rs = $stmt->executeQuery(array($message), ResultSet::FETCHMODE_NUM);
if ($rs->next())
{
unset($messages[$key]);
}
}
}
catch (Exception $e)
{
}
try
{
$this->db->begin();
$sql = 'INSERT INTO trans_unit (cat_id, source, target, comments, date_added, date_modified) VALUES (?, ?, ?, ?, ?, ?)';
$stmt = $this->db->prepareStatement($sql);
foreach ($messages as $message)
{
$stmt->executeUpdate(array($cat_id, $message, '', '', $time, $time));
++$inserted;
}
$this->db->commit();
}
catch (Exception $e)
{
$this->db->rollback();
}
if ($inserted > 0)
{
$this->updateCatalogueTime($cat_id, $variant);
}
return $inserted > 0;
}
/**
* Delete a particular message from the specified catalogue.
*
* @param string the source message to delete.
* @param string the catalogue to delete from.
* @return boolean true if deleted, false otherwise.
*/
function delete($message, $catalogue='messages')
{
$details = $this->getCatalogueDetails($catalogue);
if ($details)
{
list($cat_id, $variant, $count) = $details;
}
else
{
return false;
}
$deleted = false;
$sql = 'DELETE FROM trans_unit WHERE cat_id = ? AND source = ?';
$stmt = $this->db->prepareStatement($sql);
$rows = $stmt->executeUpdate(array($cat_id, $message));
if ($rows == 1)
{
$deleted = $this->updateCatalogueTime($cat_id, $variant);
}
return $deleted;
}
/**
* Update the translation.
*
* @param string the source string.
* @param string the new translation string.
* @param string comments
* @param string the catalogue of the translation.
* @return boolean true if translation was updated, false otherwise.
*/
function update($text, $target, $comments, $catalogue='messages')
{
$details = $this->getCatalogueDetails($catalogue);
if ($details)
{
list($cat_id, $variant, $count) = $details;
}
else
{
return false;
}
$time = time();
$sql = 'UPDATE trans_unit SET target = ?, comments = ?, date_modified = ? WHERE cat_id = ? AND source = ?';
$updated = false;
$stmt = $this->db->prepareStatement($sql);
$rows = $stmt->executeUpdate(array($target, $comments, $time, $cat_id, $text));
if ($rows == 1)
{
$updated = $this->updateCatalogueTime($cat_id, $variant);
}
return $updated;
}
/**
* Returns a list of catalogue as key and all it variants as value.
*
* @return array list of catalogues
*/
function catalogues()
{
$sql = 'SELECT name FROM catalogue ORDER BY name';
$rs = $this->db->executeQuery($sql, ResultSet::FETCHMODE_NUM);
$result = array();
while ($rs->next())
{
$details = explode('.', $rs->getString(1));
if (!isset($details[1]))
{
$details[1] = null;
}
$result[] = $details;
}
return $result;
}
}

View File

@ -0,0 +1,307 @@
<?php
/*
* This file is part of the symfony package.
* (c) 2004, 2005 Fabien Potencier <fabien.potencier@symfony-project.com>
* (c) 2004, 2005 Sean Kerr.
*
* The original version the file is based on is licensed under the LGPL, but a special license was granted.
* Please see the licenses/LICENSE.Agavi file
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Provides support for session storage using a CreoleDb database abstraction layer.
*
* <b>Required parameters:</b>
*
* # <b>db_table</b> - [none] - The database table in which session data will be
* stored.
*
* <b>Optional parameters:</b>
*
* # <b>database</b> - [default] - The database connection to use
* (see databases.ini).
* # <b>db_id_col</b> - [sess_id] - The database column in which the
* session id will be stored.
* # <b>db_data_col</b> - [sess_data] - The database column in which the
* session data will be stored.
* # <b>db_time_col</b> - [sess_time] - The database column in which the
* session timestamp will be stored.
* # <b>session_name</b> - [Agavi] - The name of the session.
*
* @package symfony
* @subpackage storage
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @author Sean Kerr <skerr@mojavi.org>
* @author Veikko Mäkinen <mail@veikkomakinen.com>
* @version SVN: $Id: sfCreoleSessionStorage.class.php 2995 2006-12-09 18:01:32Z fabien $
*/
class sfCreoleSessionStorage extends sfSessionStorage
{
/**
* Creole Database Connection
* @var Connection
*/
protected $db;
/**
* Initialize this Storage.
*
* @param Context A Context instance.
* @param array An associative array of initialization parameters.
*
* @return bool true, if initialization completes successfully, otherwise
* false.
*
* @throws <b>InitializationException</b> If an error occurs while
* initializing this Storage.
*/
public function initialize($context, $parameters = null)
{
// disable auto_start
$parameters['auto_start'] = false;
// initialize the parent
parent::initialize($context, $parameters);
if (!$this->getParameterHolder()->has('db_table'))
{
// missing required 'db_table' parameter
$error = 'Factory configuration file is missing required "db_table" parameter for the Storage category';
throw new sfInitializationException($error);
}
// use this object as the session handler
session_set_save_handler(array($this, 'sessionOpen'),
array($this, 'sessionClose'),
array($this, 'sessionRead'),
array($this, 'sessionWrite'),
array($this, 'sessionDestroy'),
array($this, 'sessionGC'));
// start our session
session_start();
}
/**
* Close a session.
*
* @return bool true, if the session was closed, otherwise false.
*/
public function sessionClose()
{
// do nothing
return true;
}
/**
* Destroy a session.
*
* @param string A session ID.
*
* @return bool true, if the session was destroyed, otherwise an exception
* is thrown.
*
* @throws <b>DatabaseException</b> If the session cannot be destroyed.
*/
public function sessionDestroy($id)
{
// get table/column
$db_table = $this->getParameterHolder()->get('db_table');
$db_id_col = $this->getParameterHolder()->get('db_id_col', 'sess_id');
// delete the record associated with this id
$sql = 'DELETE FROM ' . $db_table . ' WHERE ' . $db_id_col . '=?';
try
{
$stmt = $this->db->prepareStatement($sql);
$stmt->setString(1, $id);
$stmt->executeUpdate();
}
catch (SQLException $e) {
$error = 'Creole SQLException was thrown when trying to manipulate session data. ';
$error .= 'Message: ' . $e->getMessage();
throw new sfDatabaseException($error);
}
}
/**
* Cleanup old sessions.
*
* @param int The lifetime of a session.
*
* @return bool true, if old sessions have been cleaned, otherwise an
* exception is thrown.
*
* @throws <b>DatabaseException</b> If any old sessions cannot be cleaned.
*/
public function sessionGC($lifetime)
{
// determine deletable session time
$time = time() - $lifetime;
// get table/column
$db_table = $this->getParameterHolder()->get('db_table');
$db_time_col = $this->getParameterHolder()->get('db_time_col', 'sess_time');
// delete the record associated with this id
$sql = 'DELETE FROM ' . $db_table . ' ' .
'WHERE ' . $db_time_col . ' < ' . $time;
try
{
$this->db->executeQuery($sql);
return true;
}
catch (SQLException $e)
{
$error = 'Creole SQLException was thrown when trying to manipulate session data. ';
$error .= 'Message: ' . $e->getMessage();
throw new sfDatabaseException($error);
}
}
/**
* Open a session.
*
* @param string
* @param string
*
* @return bool true, if the session was opened, otherwise an exception is
* thrown.
*
* @throws <b>DatabaseException</b> If a connection with the database does
* not exist or cannot be created.
*/
public function sessionOpen($path, $name)
{
// what database are we using?
$database = $this->getParameterHolder()->get('database', 'default');
// autoload propel propely if we're reusing the propel connection for session storage
if ($this->getContext()->getDatabaseManager()->getDatabase($database) instanceof sfPropelDatabase && !Propel::isInit())
{
$error = 'Creole dabatase connection is the same as the propel database connection, but could not be initialized.';
throw new sfDatabaseException($error);
}
$this->db = $this->getContext()->getDatabaseConnection($database);
if ($this->db == null || !$this->db instanceof Connection)
{
$error = 'Creole dabatase connection doesn\'t exist. Unable to open session.';
throw new sfDatabaseException($error);
}
return true;
}
/**
* Read a session.
*
* @param string A session ID.
*
* @return bool true, if the session was read, otherwise an exception is
* thrown.
*
* @throws <b>DatabaseException</b> If the session cannot be read.
*/
public function sessionRead($id)
{
// get table/columns
$db_table = $this->getParameterHolder()->get('db_table');
$db_data_col = $this->getParameterHolder()->get('db_data_col', 'sess_data');
$db_id_col = $this->getParameterHolder()->get('db_id_col', 'sess_id');
$db_time_col = $this->getParameterHolder()->get('db_time_col', 'sess_time');
try
{
$sql = 'SELECT ' . $db_data_col . ' FROM ' . $db_table . ' WHERE ' . $db_id_col . '=?';
$stmt = $this->db->prepareStatement($sql);
$stmt->setString(1, $id);
$dbRes = $stmt->executeQuery(ResultSet::FETCHMODE_NUM);
if ($dbRes->next())
{
$data = $dbRes->getString(1);
return $data;
}
else
{
// session does not exist, create it
$sql = 'INSERT INTO ' . $db_table . '('.$db_id_col.','.$db_data_col.','.$db_time_col;
$sql .= ') VALUES (?,?,?)';
$stmt = $this->db->prepareStatement($sql);
$stmt->setString(1, $id);
$stmt->setString(2, '');
$stmt->setInt(3, time());
$stmt->executeUpdate();
return '';
}
}
catch (SQLException $e)
{
$error = 'Creole SQLException was thrown when trying to manipulate session data. ';
$error .= 'Message: ' . $e->getMessage();
throw new sfDatabaseException($error);
}
}
/**
* Write session data.
*
* @param string A session ID.
* @param string A serialized chunk of session data.
*
* @return bool true, if the session was written, otherwise an exception is
* thrown.
*
* @throws <b>DatabaseException</b> If the session data cannot be written.
*/
public function sessionWrite($id, $data)
{
// get table/column
$db_table = $this->getParameterHolder()->get('db_table');
$db_data_col = $this->getParameterHolder()->get('db_data_col', 'sess_data');
$db_id_col = $this->getParameterHolder()->get('db_id_col', 'sess_id');
$db_time_col = $this->getParameterHolder()->get('db_time_col', 'sess_time');
$sql = 'UPDATE ' . $db_table . ' SET ' . $db_data_col . '=?, ' . $db_time_col . ' = ' . time() .
' WHERE ' . $db_id_col . '=?';
try
{
$stmt = $this->db->prepareStatement($sql);
$stmt->setString(1, $data);
$stmt->setString(2, $id);
$stmt->executeUpdate();
return true;
}
catch (SQLException $e)
{
$error = 'Creole SQLException was thrown when trying to manipulate session data. ';
$error .= 'Message: ' . $e->getMessage();
throw new sfDatabaseException($error);
}
return false;
}
/**
* Execute the shutdown procedure.
*
* @return void
*/
public function shutdown()
{
}
}

View File

@ -0,0 +1,61 @@
<?php
require_once 'propel/engine/builder/om/php5/PHP5ExtensionObjectBuilder.php';
/*
* This file is part of the symfony package.
* (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* @package symfony
* @subpackage addon
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @version SVN: $Id: SfExtensionObjectBuilder.php 2624 2006-11-07 09:34:59Z fabien $
*/
class SfExtensionObjectBuilder extends PHP5ExtensionObjectBuilder
{
protected function addIncludes(&$script)
{
if (!DataModelBuilder::getBuildProperty('builderAddIncludes'))
{
return;
}
parent::addIncludes($script);
}
protected function addClassOpen(&$script)
{
$table = $this->getTable();
$tableName = $table->getName();
$tableDesc = $table->getDescription();
$baseClassname = $this->getObjectBuilder()->getClassname();
$script .= "
/**
* Subclass for representing a row from the '$tableName' table.
*
* $tableDesc
*
* @package ".$this->getPackage()."
*/
class ".$this->getClassname()." extends $baseClassname
{";
}
/**
* Closes class.
* @param string &$script The script will be modified in this method.
*/
protected function addClassClose(&$script)
{
$script .= "
}
";
}
}

View File

@ -0,0 +1,65 @@
<?php
require_once 'propel/engine/builder/om/php5/PHP5ExtensionPeerBuilder.php';
/*
* This file is part of the symfony package.
* (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* @package symfony
* @subpackage addon
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @version SVN: $Id: SfExtensionPeerBuilder.php 2624 2006-11-07 09:34:59Z fabien $
*/
class SfExtensionPeerBuilder extends PHP5ExtensionPeerBuilder
{
protected function addIncludes(&$script)
{
if (!DataModelBuilder::getBuildProperty('builderAddIncludes'))
{
return;
}
parent::addIncludes($script);
}
/**
* Adds class phpdoc comment and openning of class.
* @param string &$script The script will be modified in this method.
*/
protected function addClassOpen(&$script)
{
$table = $this->getTable();
$tableName = $table->getName();
$tableDesc = $table->getDescription();
$baseClassname = $this->getPeerBuilder()->getClassname();
$script .= "
/**
* Subclass for performing query and update operations on the '$tableName' table.
*
* $tableDesc
*
* @package ".$this->getPackage()."
*/
class ".$this->getClassname()." extends $baseClassname
{";
}
/**
* Closes class.
* @param string &$script The script will be modified in this method.
*/
protected function addClassClose(&$script)
{
$script .= "
}
";
}
}

View File

@ -0,0 +1,53 @@
<?php
require_once 'propel/engine/builder/om/php5/PHP5MapBuilderBuilder.php';
/*
* This file is part of the symfony package.
* (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* @package symfony
* @subpackage addon
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @version SVN: $Id: SfMapBuilderBuilder.php 3058 2006-12-16 17:17:26Z fabien $
*/
class SfMapBuilderBuilder extends PHP5MapBuilderBuilder
{
public function build()
{
if (!DataModelBuilder::getBuildProperty('builderAddComments'))
{
return sfToolkit::stripComments(parent::build());
}
return parent::build();
}
protected function addIncludes(&$script)
{
if (!DataModelBuilder::getBuildProperty('builderAddIncludes'))
{
return;
}
parent::addIncludes($script);
}
protected function addDoBuild(&$script)
{
parent::addDoBuild($script);
// fix http://propel.phpdb.org/trac/ticket/235: Column sizes not being inserted into [table]MapBuilder->DoBuild() by PHP5MapBuilderBuilder
$sizes = array();
foreach ($this->getTable()->getColumns() as $col)
{
$sizes[$col->getPhpName()] = !$col->getSize() ? 'null' : $col->getSize();
}
$script = preg_replace("/\\\$tMap\->addColumn\('([^']+)', '([^']+)', '([^']+)', CreoleTypes\:\:VARCHAR, (false|true)\)/e", '"\\\$tMap->addColumn(\'$1\', \'$2\', \'$3\', CreoleTypes::VARCHAR, $4, {$sizes[\'$2\']})"', $script);
}
}

View File

@ -0,0 +1,30 @@
<?php
require_once 'propel/engine/builder/om/php5/PHP5MultiExtendObjectBuilder.php';
/*
* This file is part of the symfony package.
* (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* @package symfony
* @subpackage addon
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @version SVN: $Id: SfMultiExtendObjectBuilder.php 1919 2006-09-01 14:41:22Z fabien $
*/
class SfMultiExtendObjectBuilder extends PHP5MultiExtendObjectBuilder
{
protected function addIncludes(&$script)
{
if (!DataModelBuilder::getBuildProperty('builderAddIncludes'))
{
return;
}
parent::addIncludes($script);
}
}

View File

@ -0,0 +1,341 @@
<?php
require_once 'propel/engine/builder/om/php5/PHP5ComplexObjectBuilder.php';
/*
* This file is part of the symfony package.
* (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* @package symfony
* @subpackage addon
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @version SVN: $Id: SfObjectBuilder.php 3493 2007-02-18 09:23:10Z fabien $
*/
class SfObjectBuilder extends PHP5ComplexObjectBuilder
{
public function build()
{
if (!DataModelBuilder::getBuildProperty('builderAddComments'))
{
return sfToolkit::stripComments(parent::build());
}
return parent::build();
}
protected function addIncludes(&$script)
{
if (!DataModelBuilder::getBuildProperty('builderAddIncludes'))
{
return;
}
parent::addIncludes($script);
// include the i18n classes if needed
if ($this->getTable()->getAttribute('isI18N'))
{
$relatedTable = $this->getDatabase()->getTable($this->getTable()->getAttribute('i18nTable'));
$script .= '
require_once \''.$this->getFilePath($this->getStubObjectBuilder()->getPackage().'.'.$relatedTable->getPhpName().'Peer').'\';
require_once \''.$this->getFilePath($this->getStubObjectBuilder()->getPackage().'.'.$relatedTable->getPhpName()).'\';
';
}
}
protected function addClassBody(&$script)
{
parent::addClassBody($script);
if ($this->getTable()->getAttribute('isI18N'))
{
if (count($this->getTable()->getPrimaryKey()) > 1)
{
throw new Exception('i18n support only works with a single primary key');
}
$this->addCultureAccessorMethod($script);
$this->addCultureMutatorMethod($script);
$this->addI18nMethods($script);
}
if (DataModelBuilder::getBuildProperty('builderAddBehaviors'))
{
$this->addCall($script);
}
}
protected function addCall(&$script)
{
$script .= "
public function __call(\$method, \$arguments)
{
if (!\$callable = sfMixer::getCallable('{$this->getClassname()}:'.\$method))
{
throw new sfException(sprintf('Call to undefined method {$this->getClassname()}::%s', \$method));
}
array_unshift(\$arguments, \$this);
return call_user_func_array(\$callable, \$arguments);
}
";
}
protected function addAttributes(&$script)
{
parent::addAttributes($script);
if ($this->getTable()->getAttribute('isI18N'))
{
$script .= '
/**
* The value for the culture field.
* @var string
*/
protected $culture;
';
}
}
protected function addCultureAccessorMethod(&$script)
{
$script .= '
public function getCulture()
{
return $this->culture;
}
';
}
protected function addCultureMutatorMethod(&$script)
{
$script .= '
public function setCulture($culture)
{
$this->culture = $culture;
}
';
}
protected function addI18nMethods(&$script)
{
$table = $this->getTable();
$pks = $table->getPrimaryKey();
$pk = $pks[0]->getPhpName();
foreach ($table->getReferrers() as $fk)
{
$tblFK = $fk->getTable();
if ($tblFK->getName() == $table->getAttribute('i18nTable'))
{
$className = $tblFK->getPhpName();
$culture = '';
$culture_peername = '';
foreach ($tblFK->getColumns() as $col)
{
if (("true" === strtolower($col->getAttribute('isCulture'))))
{
$culture = $col->getPhpName();
$culture_peername = PeerBuilder::getColumnName($col, $className);
}
}
foreach ($tblFK->getColumns() as $col)
{
if ($col->isPrimaryKey()) continue;
$script .= '
public function get'.$col->getPhpName().'()
{
$obj = $this->getCurrent'.$className.'();
return ($obj ? $obj->get'.$col->getPhpName().'() : null);
}
public function set'.$col->getPhpName().'($value)
{
$this->getCurrent'.$className.'()->set'.$col->getPhpName().'($value);
}
';
}
$script .= '
protected $current_i18n = array();
public function getCurrent'.$className.'()
{
if (!isset($this->current_i18n[$this->culture]))
{
$obj = '.$className.'Peer::retrieveByPK($this->get'.$pk.'(), $this->culture);
if ($obj)
{
$this->set'.$className.'ForCulture($obj, $this->culture);
}
else
{
$this->set'.$className.'ForCulture(new '.$className.'(), $this->culture);
$this->current_i18n[$this->culture]->set'.$culture.'($this->culture);
}
}
return $this->current_i18n[$this->culture];
}
public function set'.$className.'ForCulture($object, $culture)
{
$this->current_i18n[$culture] = $object;
$this->add'.$className.'($object);
}
';
}
}
}
protected function addDoSave(&$script)
{
$tmp = '';
parent::addDoSave($tmp);
// add autosave to i18n object even if the base object is not changed
$tmp = preg_replace_callback('#(\$this\->(.+?)\->isModified\(\))#', array($this, 'i18nDoSaveCallback'), $tmp);
$script .= $tmp;
}
private function i18nDoSaveCallback($matches)
{
$value = $matches[1];
// get the related class to see if it is a i18n one
$table = $this->getTable();
$column = null;
foreach ($table->getForeignKeys() as $fk)
{
if ($matches[2] == $this->getFKVarName($fk))
{
$column = $fk;
break;
}
}
$foreign_table = $this->getDatabase()->getTable($fk->getForeignTableName());
if ($foreign_table->getAttribute('isI18N'))
{
$foreign_tables_i18n_table = $this->getDatabase()->getTable($foreign_table->getAttribute('i18nTable'));
$value .= ' || $this->'.$matches[2].'->getCurrent'.$foreign_tables_i18n_table->getPhpName().'()->isModified()';
}
return $value;
}
protected function addDelete(&$script)
{
$tmp = '';
parent::addDelete($tmp);
if (DataModelBuilder::getBuildProperty('builderAddBehaviors'))
{
// add sfMixer call
$pre_mixer_script = "
foreach (sfMixer::getCallables('{$this->getClassname()}:delete:pre') as \$callable)
{
\$ret = call_user_func(\$callable, \$this, \$con);
if (\$ret)
{
return;
}
}
";
$post_mixer_script = "
foreach (sfMixer::getCallables('{$this->getClassname()}:delete:post') as \$callable)
{
call_user_func(\$callable, \$this, \$con);
}
";
$tmp = preg_replace('/{/', '{'.$pre_mixer_script, $tmp, 1);
$tmp = preg_replace('/}\s*$/', $post_mixer_script.' }', $tmp);
}
// update current script
$script .= $tmp;
}
protected function addSave(&$script)
{
$tmp = '';
parent::addSave($tmp);
// add support for created_(at|on) and updated_(at|on) columns
$date_script = '';
$updated = false;
$created = false;
foreach ($this->getTable()->getColumns() as $col)
{
$clo = strtolower($col->getName());
if (!$updated && in_array($clo, array('updated_at', 'updated_on')))
{
$updated = true;
$date_script .= "
if (\$this->isModified() && !\$this->isColumnModified(".$this->getColumnConstant($col)."))
{
\$this->set".$col->getPhpName()."(time());
}
";
}
else if (!$created && in_array($clo, array('created_at', 'created_on')))
{
$created = true;
$date_script .= "
if (\$this->isNew() && !\$this->isColumnModified(".$this->getColumnConstant($col)."))
{
\$this->set".$col->getPhpName()."(time());
}
";
}
}
$tmp = preg_replace('/{/', '{'.$date_script, $tmp, 1);
if (DataModelBuilder::getBuildProperty('builderAddBehaviors'))
{
// add sfMixer call
$pre_mixer_script = "
foreach (sfMixer::getCallables('{$this->getClassname()}:save:pre') as \$callable)
{
\$affectedRows = call_user_func(\$callable, \$this, \$con);
if (is_int(\$affectedRows))
{
return \$affectedRows;
}
}
";
$post_mixer_script = <<<EOF
foreach (sfMixer::getCallables('{$this->getClassname()}:save:post') as \$callable)
{
call_user_func(\$callable, \$this, \$con, \$affectedRows);
}
EOF;
$tmp = preg_replace('/{/', '{'.$pre_mixer_script, $tmp, 1);
$tmp = preg_replace('/(\$con\->commit\(\);)/', '$1'.$post_mixer_script, $tmp);
}
// update current script
$script .= $tmp;
}
}

View File

@ -0,0 +1,274 @@
<?php
require_once 'propel/engine/builder/om/php5/PHP5ComplexPeerBuilder.php';
/*
* This file is part of the symfony package.
* (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* @package symfony
* @subpackage addon
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @version SVN: $Id: SfPeerBuilder.php 2534 2006-10-26 17:13:50Z fabien $
*/
class SfPeerBuilder extends PHP5ComplexPeerBuilder
{
public function build()
{
if (!DataModelBuilder::getBuildProperty('builderAddComments'))
{
return sfToolkit::stripComments(parent::build());
}
return parent::build();
}
protected function addIncludes(&$script)
{
if (!DataModelBuilder::getBuildProperty('builderAddIncludes'))
{
return;
}
parent::addIncludes($script);
}
protected function addSelectMethods(&$script)
{
parent::addSelectMethods($script);
if ($this->getTable()->getAttribute('isI18N'))
{
$this->addDoSelectWithI18n($script);
}
}
protected function addDoSelectWithI18n(&$script)
{
$table = $this->getTable();
$thisTableObjectBuilder = OMBuilder::getNewObjectBuilder($table);
$className = $table->getPhpName();
$pks = $table->getPrimaryKey();
$pk = PeerBuilder::getColumnName($pks[0], $className);
// get i18n table name and culture column name
foreach ($table->getReferrers() as $fk)
{
$tblFK = $fk->getTable();
if ($tblFK->getName() == $table->getAttribute('i18nTable'))
{
$i18nClassName = $tblFK->getPhpName();
// FIXME
$i18nPeerClassName = $i18nClassName.'Peer';
$i18nTable = $table->getDatabase()->getTable($tblFK->getName());
$i18nTableObjectBuilder = OMBuilder::getNewObjectBuilder($i18nTable);
$i18nTablePeerBuilder = OMBuilder::getNewPeerBuilder($i18nTable);
$i18nPks = $i18nTable->getPrimaryKey();
$i18nPk = PeerBuilder::getColumnName($i18nPks[0], $i18nClassName);
$culturePhpName = '';
$cultureColumnName = '';
foreach ($tblFK->getColumns() as $col)
{
if (("true" === strtolower($col->getAttribute('isCulture'))))
{
$culturePhpName = $col->getPhpName();
$cultureColumnName = PeerBuilder::getColumnName($col, $i18nClassName);
}
}
}
}
$script .= "
/**
* Selects a collection of $className objects pre-filled with their i18n objects.
*
* @return array Array of $className objects.
* @throws PropelException Any exceptions caught during processing will be
* rethrown wrapped into a PropelException.
*/
public static function doSelectWithI18n(Criteria \$c, \$culture = null, \$con = null)
{
if (\$culture === null)
{
\$culture = sfContext::getInstance()->getUser()->getCulture();
}
// Set the correct dbName if it has not been overridden
if (\$c->getDbName() == Propel::getDefaultDB())
{
\$c->setDbName(self::DATABASE_NAME);
}
".$this->getPeerClassname()."::addSelectColumns(\$c);
\$startcol = (".$this->getPeerClassname()."::NUM_COLUMNS - ".$this->getPeerClassname()."::NUM_LAZY_LOAD_COLUMNS) + 1;
".$i18nPeerClassName."::addSelectColumns(\$c);
\$c->addJoin(".$pk.", ".$i18nPk.");
\$c->add(".$cultureColumnName.", \$culture);
\$rs = ".$this->basePeerClassname."::doSelect(\$c, \$con);
\$results = array();
while(\$rs->next()) {
";
if ($table->getChildrenColumn()) {
$script .= "
\$omClass = ".$this->getPeerClassname()."::getOMClass(\$rs, 1);
";
} else {
$script .= "
\$omClass = ".$this->getPeerClassname()."::getOMClass();
";
}
$script .= "
\$cls = Propel::import(\$omClass);
\$obj1 = new \$cls();
\$obj1->hydrate(\$rs);
\$obj1->setCulture(\$culture);
";
// if ($i18nTable->getChildrenColumn()) {
$script .= "
\$omClass = ".$i18nTablePeerBuilder->getPeerClassname()."::getOMClass(\$rs, \$startcol);
";
// } else {
// $script .= "
// \$omClass = ".$i18nTablePeerBuilder->getPeerClassname()."::getOMClass();
//";
// }
$script .= "
\$cls = Propel::import(\$omClass);
\$obj2 = new \$cls();
\$obj2->hydrate(\$rs, \$startcol);
\$obj1->set".$i18nClassName."ForCulture(\$obj2, \$culture);
\$obj2->set".$className."(\$obj1);
\$results[] = \$obj1;
}
return \$results;
}
";
}
protected function addDoValidate(&$script)
{
$tmp = '';
parent::addDoValidate($tmp);
$script .= str_replace("return {$this->basePeerClassname}::doValidate(".$this->getPeerClassname()."::DATABASE_NAME, ".$this->getPeerClassname()."::TABLE_NAME, \$columns);\n",
"\$res = {$this->basePeerClassname}::doValidate(".$this->getPeerClassname()."::DATABASE_NAME, ".$this->getPeerClassname()."::TABLE_NAME, \$columns);\n".
" if (\$res !== true) {\n".
" \$request = sfContext::getInstance()->getRequest();\n".
" foreach (\$res as \$failed) {\n".
" \$col = ".$this->getPeerClassname()."::translateFieldname(\$failed->getColumn(), BasePeer::TYPE_COLNAME, BasePeer::TYPE_PHPNAME);\n".
" \$request->setError(\$col, \$failed->getMessage());\n".
" }\n".
" }\n\n".
" return \$res;\n", $tmp);
}
protected function addDoSelectRS(&$script)
{
$tmp = '';
parent::addDoSelectRS($tmp);
if (DataModelBuilder::getBuildProperty('builderAddBehaviors'))
{
$mixer_script = "
foreach (sfMixer::getCallables('{$this->getClassname()}:addDoSelectRS:addDoSelectRS') as \$callable)
{
call_user_func(\$callable, '{$this->getClassname()}', \$criteria, \$con);
}
";
$tmp = preg_replace('/{/', '{'.$mixer_script, $tmp, 1);
}
$script .= $tmp;
}
protected function addDoUpdate(&$script)
{
$tmp = '';
parent::addDoUpdate($tmp);
if (DataModelBuilder::getBuildProperty('builderAddBehaviors'))
{
// add sfMixer call
$pre_mixer_script = "
foreach (sfMixer::getCallables('{$this->getClassname()}:doUpdate:pre') as \$callable)
{
\$ret = call_user_func(\$callable, '{$this->getClassname()}', \$values, \$con);
if (false !== \$ret)
{
return \$ret;
}
}
";
$post_mixer_script = "
foreach (sfMixer::getCallables('{$this->getClassname()}:doUpdate:post') as \$callable)
{
call_user_func(\$callable, '{$this->getClassname()}', \$values, \$con, \$ret);
}
return \$ret;
";
$tmp = preg_replace('/{/', '{'.$pre_mixer_script, $tmp, 1);
$tmp = preg_replace("/\t\treturn ([^}]+)/", "\t\t\$ret = $1".$post_mixer_script.' ', $tmp, 1);
}
$script .= $tmp;
}
protected function addDoInsert(&$script)
{
$tmp = '';
parent::addDoInsert($tmp);
if (DataModelBuilder::getBuildProperty('builderAddBehaviors'))
{
// add sfMixer call
$pre_mixer_script = "
foreach (sfMixer::getCallables('{$this->getClassname()}:doInsert:pre') as \$callable)
{
\$ret = call_user_func(\$callable, '{$this->getClassname()}', \$values, \$con);
if (false !== \$ret)
{
return \$ret;
}
}
";
$post_mixer_script = "
foreach (sfMixer::getCallables('{$this->getClassname()}:doInsert:post') as \$callable)
{
call_user_func(\$callable, '{$this->getClassname()}', \$values, \$con, \$pk);
}
return";
$tmp = preg_replace('/{/', '{'.$pre_mixer_script, $tmp, 1);
$tmp = preg_replace("/\t\treturn/", "\t\t".$post_mixer_script, $tmp, 1);
}
$script .= $tmp;
}
}

View File

@ -0,0 +1,46 @@
<?php
/*
* This file is part of the symfony package.
* (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* sfGenerator is the abstract base class for all generators.
*
* @package symfony
* @subpackage database
* @author Olivier Verdier <Olivier.Verdier@gmail.com>
* @version SVN: $Id $
*/
class sfPropelDataRetriever
{
static public function retrieveObjects($class, $peerMethod = null)
{
if (!$classPath = sfCore::getClassPath($class.'Peer'))
{
throw new sfException(sprintf('Unable to find path for class "%s".', $class.'Peer'));
}
require_once($classPath);
if (!$peerMethod)
{
$peerMethod = 'doSelect';
}
$classPeer = $class.'Peer';
if (!is_callable(array($classPeer, $peerMethod)))
{
throw new sfException(sprintf('Peer method "%s" not found for class "%s"', $peerMethod, $classPeer));
}
$objects = call_user_func(array($classPeer, $peerMethod), new Criteria());
return $objects;
}
}

View File

@ -0,0 +1,114 @@
<?php
/*
* This file is part of the symfony package.
* (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* A symfony database driver for Propel, derived from the native Creole driver.
*
* <b>Optional parameters:</b>
*
* # <b>datasource</b> - [symfony] - datasource to use for the connection
* # <b>is_default</b> - [false] - use as default if multiple connections
* are specified. The parameters
* that has been flagged using this param
* is be used when Propel is initialized
* via sfPropelAutoload.
*
* @package symfony
* @subpackage database
*
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @version SVN: $Id: sfPropelDatabase.class.php 3493 2007-02-18 09:23:10Z fabien $
*/
class sfPropelDatabase extends sfCreoleDatabase
{
static protected
$config = array();
public function initialize($parameters = null, $name = 'propel')
{
parent::initialize($parameters);
if (!$this->hasParameter('datasource'))
{
$this->setParameter('datasource', $name);
}
$this->addConfig();
$is_default = $this->getParameter('is_default', false);
// first defined if none listed as default
if ($is_default || count(self::$config['propel']['datasources']) == 1)
{
$this->setDefaultConfig();
}
}
public function setDefaultConfig()
{
self::$config['propel']['datasources']['default'] = $this->getParameter('datasource');
}
public function addConfig()
{
if ($this->hasParameter('host'))
{
$this->setParameter('hostspec', $this->getParameter('host'));
}
if ($dsn = $this->getParameter('dsn'))
{
require_once('creole/Creole.php');
$params = Creole::parseDSN($dsn);
$options = array('phptype', 'hostspec', 'database', 'username', 'password', 'port', 'protocol', 'encoding', 'persistent');
foreach ($options as $option)
{
if (!$this->getParameter($option) && isset($params[$option]))
{
$this->setParameter($option, $params[$option]);
}
}
}
self::$config['propel']['datasources'][$this->getParameter('datasource')] =
array(
'adapter' => $this->getParameter('phptype'),
'connection' =>
array(
'phptype' => $this->getParameter('phptype'),
'hostspec' => $this->getParameter('hostspec'),
'database' => $this->getParameter('database'),
'username' => $this->getParameter('username'),
'password' => $this->getParameter('password'),
'port' => $this->getParameter('port'),
'encoding' => $this->getParameter('encoding'),
'persistent' => $this->getParameter('persistent'),
'protocol' => $this->getParameter('protocol'),
),
);
}
public static function getConfiguration()
{
return self::$config;
}
public function setConnectionParameter($key, $value)
{
if ($key == 'host')
{
$key = 'hostspec';
}
self::$config['propel']['datasources'][$this->getParameter('datasource')]['connection'][$key] = $value;
$this->setParameter($key, $value);
}
}

View File

@ -0,0 +1,72 @@
<?php
/*
* This file is part of the symfony package.
* (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Propel Admin generator.
*
* This class generates an admin module with propel.
*
* @package symfony
* @subpackage generator
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @version SVN: $Id: sfPropelAdminGenerator.class.php 3302 2007-01-18 13:42:46Z fabien $
*/
class sfPropelAdminGenerator extends sfPropelCrudGenerator
{
/**
* Initializes the current sfGenerator instance.
*
* @param sfGeneratorManager A sfGeneratorManager instance
*/
public function initialize($generatorManager)
{
parent::initialize($generatorManager);
$this->setGeneratorClass('sfPropelAdmin');
}
public function getAllColumns()
{
$phpNames = array();
foreach ($this->getTableMap()->getColumns() as $column)
{
$phpNames[] = new sfAdminColumn($column->getPhpName(), $column);
}
return $phpNames;
}
public function getAdminColumnForField($field, $flag = null)
{
$phpName = sfInflector::camelize($field);
return new sfAdminColumn($phpName, $this->getColumnForPhpName($phpName), $flag);
}
// returns a column phpName or null if none was found
public function getColumnForPhpName($phpName)
{
// search the matching column for this column name
foreach ($this->getTableMap()->getColumns() as $column)
{
if ($column->getPhpName() == $phpName)
{
$found = true;
return $column;
}
}
// not a "real" column, so we will simulate one
return null;
}
}

View File

@ -0,0 +1,144 @@
<?php
/*
* This file is part of the symfony package.
* (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Propel CRUD generator.
*
* This class generates a basic CRUD module with propel.
*
* @package symfony
* @subpackage generator
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @version SVN: $Id: sfPropelCrudGenerator.class.php 3302 2007-01-18 13:42:46Z fabien $
*/
class sfPropelCrudGenerator extends sfAdminGenerator
{
/**
* Initializes the current sfGenerator instance.
*
* @param sfGeneratorManager A sfGeneratorManager instance
*/
public function initialize($generatorManager)
{
parent::initialize($generatorManager);
$this->setGeneratorClass('sfPropelCrud');
}
/**
* Loads primary keys.
*
* This method is ORM dependant.
*
* @throws sfException
*/
protected function loadPrimaryKeys()
{
foreach ($this->tableMap->getColumns() as $column)
{
if ($column->isPrimaryKey())
{
$this->primaryKey[] = $column;
}
}
if (!count($this->primaryKey))
{
throw new sfException(sprintf('Cannot generate a module for a model without a primary key (%s)', $this->className));
}
}
/**
* Loads map builder classes.
*
* This method is ORM dependant.
*
* @throws sfException
*/
protected function loadMapBuilderClasses()
{
// we must load all map builder classes to be able to deal with foreign keys (cf. editSuccess.php template)
$classes = sfFinder::type('file')->name('*MapBuilder.php')->in(sfLoader::getModelDirs());
foreach ($classes as $class)
{
$class_map_builder = basename($class, '.php');
$maps[$class_map_builder] = new $class_map_builder();
if (!$maps[$class_map_builder]->isBuilt())
{
$maps[$class_map_builder]->doBuild();
}
if ($this->className == str_replace('MapBuilder', '', $class_map_builder))
{
$this->map = $maps[$class_map_builder];
}
}
if (!$this->map)
{
throw new sfException('The model class "'.$this->className.'" does not exist.');
}
$this->tableMap = $this->map->getDatabaseMap()->getTable(constant($this->className.'Peer::TABLE_NAME'));
}
/**
* Generates a PHP call to an object helper.
*
* @param string The helper name
* @param string The column name
* @param array An array of parameters
* @param array An array of local parameters
*
* @return string PHP code
*/
function getPHPObjectHelper($helperName, $column, $params, $localParams = array())
{
$params = $this->getObjectTagParams($params, $localParams);
return sprintf('object_%s($%s, \'%s\', %s)', $helperName, $this->getSingularName(), $this->getColumnGetter($column, false), $params);
}
/**
* Returns the getter either non-developped: 'getFoo' or developped: '$class->getFoo()'.
*
* @param string The column name
* @param boolean true if you want developped method names, false otherwise
* @param string The prefix value
*
* @return string PHP code
*/
function getColumnGetter($column, $developed = false, $prefix = '')
{
$getter = 'get'.$column->getPhpName();
if ($developed)
{
$getter = sprintf('$%s%s->%s()', $prefix, $this->getSingularName(), $getter);
}
return $getter;
}
/*
* Gets the PHP name of the related class name.
*
* Used for foreign keys only; this method should be removed when we use sfAdminColumn instead.
*
* @param string The column name
*
* @return string The PHP name of the related class name
*/
function getRelatedClassName($column)
{
$relatedTable = $this->getMap()->getDatabaseMap()->getTable($column->getRelatedTableName());
return $relatedTable->getPhpName();
}
}

View File

@ -0,0 +1,32 @@
<?php
/*
* This file is part of the symfony package.
* (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* @package symfony
* @subpackage addon
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @version SVN: $Id: sfPropelAutoload.php 2808 2006-11-25 07:22:49Z fabien $
*/
require_once 'propel/Propel.php';
if (sfConfig::get('sf_debug') && sfConfig::get('sf_logging_enabled'))
{
// register debug driver
require_once 'creole/Creole.php';
Creole::registerDriver('*', 'symfony.addon.creole.drivers.sfDebugConnection');
// register our logger
require_once(sfConfig::get('sf_symfony_lib_dir').'/addon/creole/drivers/sfDebugConnection.php');
sfDebugConnection::setLogger(sfLogger::getInstance());
}
// propel initialization
Propel::setConfiguration(sfPropelDatabase::getConfiguration());
Propel::initialize();

View File

@ -0,0 +1,89 @@
<?php
/*
* This file is part of the symfony package.
* (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* @package symfony
* @subpackage addon
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @version SVN: $Id: sfPropelBehavior.class.php 2453 2006-10-20 05:58:48Z fabien $
*/
class sfPropelBehavior
{
static protected $behaviors = array();
static public function registerMethods($name, $callables)
{
if (!isset(self::$behaviors[$name]))
{
self::$behaviors[$name] = array('methods' => array(), 'hooks' => array());
}
foreach ($callables as $callable)
{
self::$behaviors[$name]['methods'][] = $callable;
}
}
static public function registerHooks($name, $hooks)
{
if (!isset(self::$behaviors[$name]))
{
self::$behaviors[$name] = array('methods' => array(), 'hooks' => array());
}
foreach ($hooks as $hook => $callable)
{
if (!isset(self::$behaviors[$name]['hooks']))
{
self::$behaviors[$name]['hooks'][$hook] = array();
}
self::$behaviors[$name]['hooks'][$hook][] = $callable;
}
}
static public function add($class, $behaviors)
{
foreach ($behaviors as $name => $parameters)
{
if (is_int($name))
{
// no parameters
$name = $parameters;
}
else
{
// register parameters
foreach ($parameters as $key => $value)
{
sfConfig::set('propel_behavior_'.$name.'_'.$class.'_'.$key, $value);
}
}
if (!isset(self::$behaviors[$name]))
{
throw new sfConfigurationException(sprintf('Propel behavior "%s" is not registered', $name));
}
// register hooks
foreach (self::$behaviors[$name]['hooks'] as $hook => $callables)
{
foreach ($callables as $callable)
{
sfMixer::register('Base'.$class.$hook, $callable);
}
}
// register new methods
foreach (self::$behaviors[$name]['methods'] as $callable)
{
sfMixer::register('Base'.$class, $callable);
}
}
}
}

View File

@ -0,0 +1,385 @@
<?php
/*
* This file is part of the symfony package.
* (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* This class is the Propel implementation of sfData. It interacts with the data source
* and loads data.
*
* @package symfony
* @subpackage addon
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @version SVN: $Id: sfPropelData.class.php 5339 2007-10-01 07:35:33Z fabien $
*/
class sfPropelData extends sfData
{
protected
$maps = array(),
$deletedClasses = array(),
$con = null;
// symfony load-data (file|dir)
/**
* Loads data from a file or directory into a Propel data source
*
* @param mixed A file or directory path
* @param string The Propel connection name, default 'propel'
*
* @throws Exception If the database throws an error, rollback transaction and rethrows exception
*/
public function loadData($directory_or_file = null, $connectionName = 'propel')
{
$fixture_files = $this->getFiles($directory_or_file);
// wrap all database operations in a single transaction
$this->con = Propel::getConnection($connectionName);
try
{
$this->con->begin();
$this->doDeleteCurrentData($fixture_files);
$this->doLoadData($fixture_files);
$this->con->commit();
}
catch (Exception $e)
{
$this->con->rollback();
throw $e;
}
}
/**
* Implements the abstract loadDataFromArray method and loads the data using the generated data model.
*
* @param array The data to be loaded into the data source
*
* @throws Exception If data is unnamed.
* @throws sfException If an object defined in the model does not exist in the data
* @throws sfException If a column that does not exist is referenced
*/
public function loadDataFromArray($data)
{
if ($data === null)
{
// no data
return;
}
foreach ($data as $class => $datas)
{
$class = trim($class);
$peer_class = $class.'Peer';
// load map class
$this->loadMapBuilder($class);
$tableMap = $this->maps[$class]->getDatabaseMap()->getTable(constant($peer_class.'::TABLE_NAME'));
$column_names = call_user_func_array(array($peer_class, 'getFieldNames'), array(BasePeer::TYPE_FIELDNAME));
// iterate through datas for this class
// might have been empty just for force a table to be emptied on import
if (!is_array($datas))
{
continue;
}
foreach ($datas as $key => $data)
{
// create a new entry in the database
$obj = new $class();
if (!is_array($data))
{
throw new Exception(sprintf('You must give a name for each fixture data entry (class %s)'), $class);
}
foreach ($data as $name => $value)
{
// foreign key?
try
{
$column = $tableMap->getColumn($name);
if ($column->isForeignKey() && !is_null($value))
{
$relatedTable = $this->maps[$class]->getDatabaseMap()->getTable($column->getRelatedTableName());
if (!isset($this->object_references[$relatedTable->getPhpName().'_'.$value]))
{
$error = 'The object "%s" from class "%s" is not defined in your data file.';
$error = sprintf($error, $value, $relatedTable->getPhpName());
throw new sfException($error);
}
$value = $this->object_references[$relatedTable->getPhpName().'_'.$value];
}
}
catch (PropelException $e)
{
}
$pos = array_search($name, $column_names);
$method = 'set'.sfInflector::camelize($name);
if ($pos)
{
$obj->setByPosition($pos, $value);
}
else if (is_callable(array($obj, $method)))
{
$obj->$method($value);
}
else
{
$error = 'Column "%s" does not exist for class "%s"';
$error = sprintf($error, $name, $class);
throw new sfException($error);
}
}
$obj->save($this->con);
// save the id for future reference
if (method_exists($obj, 'getPrimaryKey'))
{
$this->object_references[$class.'_'.$key] = $obj->getPrimaryKey();
}
}
}
}
/**
* Clears existing data from the data source by reading the fixture files
* and deleting the existing data for only those classes that are mentioned
* in the fixtures.
*
* @param array The list of YAML files.
*
* @throws sfException If a class mentioned in a fixture can not be found
*/
protected function doDeleteCurrentData($fixture_files)
{
// delete all current datas in database
if (!$this->deleteCurrentData)
{
return;
}
rsort($fixture_files);
foreach ($fixture_files as $fixture_file)
{
$data = sfYaml::load($fixture_file);
if ($data === null)
{
// no data
continue;
}
$classes = array_keys($data);
krsort($classes);
foreach ($classes as $class)
{
$class = trim($class);
if (in_array($class, $this->deletedClasses))
{
continue;
}
$peer_class = $class.'Peer';
if (!$classPath = sfCore::getClassPath($peer_class))
{
throw new sfException(sprintf('Unable to find path for class "%s".', $peer_class));
}
require_once($classPath);
call_user_func(array($peer_class, 'doDeleteAll'), $this->con);
$this->deletedClasses[] = $class;
}
}
}
/**
* Loads the mappings for the classes
*
* @param string The model class name
*
* @throws sfException If the class cannot be found
*/
protected function loadMapBuilder($class)
{
$mapBuilderClass = $class.'MapBuilder';
if (!isset($this->maps[$class]))
{
if (!$classPath = sfCore::getClassPath($mapBuilderClass))
{
throw new sfException(sprintf('Unable to find path for class "%s".', $mapBuilderClass));
}
require_once($classPath);
$this->maps[$class] = new $mapBuilderClass();
$this->maps[$class]->doBuild();
}
}
/**
* Dumps data to fixture from one or more tables.
*
* @param string directory or file to dump to
* @param mixed name or names of tables to dump (or all to dump all tables)
* @param string connection name
*/
public function dumpData($directory_or_file = null, $tables = 'all', $connectionName = 'propel')
{
$sameFile = true;
if (is_dir($directory_or_file))
{
// multi files
$sameFile = false;
}
else
{
// same file
// delete file
}
$this->con = Propel::getConnection($connectionName);
// get tables
if ('all' === $tables || is_null($tables))
{
// load all map builder classes
$files = sfFinder::type('file')->name('*MapBuilder.php')->in(sfLoader::getModelDirs());
foreach ($files as $file)
{
$mapBuilderClass = basename($file, '.php');
$map = new $mapBuilderClass();
$map->doBuild();
}
$dbMap = Propel::getDatabaseMap($connectionName);
$tables = array();
foreach ($dbMap->getTables() as $table)
{
$tables[] = $table->getPhpName();
}
}
else if (!is_array($tables))
{
$tables = array($tables);
}
$dumpData = array();
// load map classes
array_walk($tables, array($this, 'loadMapBuilder'));
$tables = $this->fixOrderingOfForeignKeyData($tables);
foreach ($tables as $tableName)
{
$tableMap = $this->maps[$tableName]->getDatabaseMap()->getTable(constant($tableName.'Peer::TABLE_NAME'));
// get db info
$rs = $this->con->executeQuery('SELECT * FROM '.constant($tableName.'Peer::TABLE_NAME'));
while ($rs->next())
{
$pk = $tableName;
$values = array();
foreach ($tableMap->getColumns() as $column)
{
$col = strtolower($column->getColumnName());
if ($column->isPrimaryKey())
{
$pk .= '_'.$rs->get($col);
}
else if ($column->isForeignKey())
{
$relatedTable = $this->maps[$tableName]->getDatabaseMap()->getTable($column->getRelatedTableName());
$values[$col] = $relatedTable->getPhpName().'_'.$rs->get($col);
}
else
{
$values[$col] = $rs->get($col);
}
}
if (!isset($dumpData[$tableName]))
{
$dumpData[$tableName] = array();
}
$dumpData[$tableName][$pk] = $values;
}
}
// save to file(s)
if ($sameFile)
{
file_put_contents($directory_or_file, Spyc::YAMLDump($dumpData));
}
else
{
$i = 0;
foreach ($tables as $tableName)
{
if (!isset($dumpData[$tableName]))
{
continue;
}
file_put_contents(sprintf("%s/%03d-%s.yml", $directory_or_file, ++$i, $tableName), Spyc::YAMLDump(array($tableName => $dumpData[$tableName])));
}
}
}
/**
* Fixes the ordering of foreign key data, by outputting data a foreign key depends on before the table with the foreign key.
*
* @param array The array with the class names.
*/
public function fixOrderingOfForeignKeyData($classes)
{
// reordering classes to take foreign keys into account
for ($i = 0, $count = count($classes); $i < $count; $i++)
{
$class = $classes[$i];
$tableMap = $this->maps[$class]->getDatabaseMap()->getTable(constant($class.'Peer::TABLE_NAME'));
foreach ($tableMap->getColumns() as $column)
{
if ($column->isForeignKey())
{
$relatedTable = $this->maps[$class]->getDatabaseMap()->getTable($column->getRelatedTableName());
$relatedTablePos = array_search($relatedTable->getPhpName(), $classes);
// check if relatedTable is after the current table
if ($relatedTablePos > $i)
{
// move related table 1 position before current table
$classes = array_merge(
array_slice($classes, 0, $i),
array($classes[$relatedTablePos]),
array_slice($classes, $i, $relatedTablePos - $i),
array_slice($classes, $relatedTablePos + 1)
);
// we have moved a table, so let's see if we are done
return $this->fixOrderingOfForeignKeyData($classes);
}
}
}
}
return $classes;
}
}

View File

@ -0,0 +1,719 @@
<?php
/*
* This file is part of the symfony package.
* (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
*
* @package symfony
* @subpackage addon
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @author François Zaninotto <francois.zaninotto@symfony-project.com>
* @version SVN: $Id$
*/
class sfPropelDatabaseSchema
{
protected $connection_name = '';
protected $database = array();
public function asArray()
{
return array($this->connection_name => $this->database);
}
public function loadYAML($file)
{
$schema = sfYaml::load($file);
if (count($schema) > 1)
{
throw new sfException('A schema.yml must only contain 1 database entry.');
}
$tmp = array_keys($schema);
$this->connection_name = array_shift($tmp);
if ($this->connection_name)
{
$this->database = $schema[$this->connection_name];
$this->fixYAMLDatabase();
$this->fixYAMLI18n();
$this->fixYAMLColumns();
}
}
public function asXML()
{
$xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
$xml .= "<database name=\"$this->connection_name\"".$this->getAttributesFor($this->database).">\n";
// tables
foreach ($this->getChildren($this->database) as $tb_name => $table)
{
$xml .= "\n <table name=\"$tb_name\"".$this->getAttributesFor($table).">\n";
// columns
foreach ($this->getChildren($table) as $col_name => $column)
{
$xml .= " <column name=\"$col_name\"".$this->getAttributesForColumn($tb_name, $col_name, $column);
}
// indexes
if (isset($table['_indexes']))
{
foreach ($table['_indexes'] as $index_name => $index)
{
$xml .= " <index name=\"$index_name\">\n";
foreach ($index as $index_column)
{
$xml .= " <index-column name=\"$index_column\" />\n";
}
$xml .= " </index>\n";
}
}
// uniques
if (isset($table['_uniques']))
{
foreach ($table['_uniques'] as $unique_name => $index)
{
$xml .= " <unique name=\"$unique_name\">\n";
foreach ($index as $unique_column)
{
$xml .= " <unique-column name=\"$unique_column\" />\n";
}
$xml .= " </unique>\n";
}
}
// foreign-keys
if (isset($table['_foreignKeys']))
{
foreach ($table['_foreignKeys'] as $fkey_name => $fkey)
{
$xml .= " <foreign-key foreignTable=\"$fkey[foreignTable]\"";
// foreign key name
if (!is_numeric($fkey_name))
{
$xml .= " name=\"$fkey_name\"";
}
// onDelete
if (isset($fkey['onDelete']))
{
$xml .= " onDelete=\"$fkey[onDelete]\"";
}
// onUpdate
if (isset($fkey['onUpdate']))
{
$xml .= " onUpdate=\"$fkey[onUpdate]\"";
}
$xml .= ">\n";
// references
if (isset($fkey['references']))
{
foreach ($fkey['references'] as $reference)
{
$xml .= " <reference local=\"$reference[local]\" foreign=\"$reference[foreign]\" />\n";
}
}
$xml .= " </foreign-key>\n";
}
}
$xml .= " </table>\n";
}
$xml .= "\n</database>\n";
return $xml;
}
protected function fixYAMLDatabase()
{
if (!isset($this->database['_attributes']))
{
$this->database['_attributes'] = array();
}
// conventions for database attributes
$this->setIfNotSet($this->database['_attributes'], 'defaultIdMethod', 'native');
$this->setIfNotSet($this->database['_attributes'], 'noXsd', true);
$this->setIfNotSet($this->database['_attributes'], 'package', 'lib.model');
}
protected function fixYAMLI18n()
{
foreach ($this->getTables() as $i18n_table => $columns)
{
$pos = strpos($i18n_table, '_i18n');
$has_primary_key = false;
foreach ($columns as $column => $attributes)
{
if (is_array($attributes) && array_key_exists('primaryKey', $attributes))
{
$has_primary_key = true;
}
}
if ($pos > 0 && $pos == strlen($i18n_table) - 5 && !$has_primary_key)
{
// i18n table without primary key
$main_table = $this->findTable(substr($i18n_table, 0, $pos));
if ($main_table)
{
// set i18n attributes for main table
$this->setIfNotSet($this->database[$main_table]['_attributes'], 'isI18N', 1);
$this->setIfNotSet($this->database[$main_table]['_attributes'], 'i18nTable', $i18n_table);
// set id and culture columns for i18n table
$this->setIfNotSet($this->database[$i18n_table], 'id', array(
'type' => 'integer',
'required' => true,
'primaryKey' => true,
'foreignTable' => $main_table,
'foreignReference' => 'id',
'onDelete' => 'cascade'
));
$this->setIfNotSet($this->database[$i18n_table], 'culture', array(
'isCulture' => true,
'type' => 'varchar',
'size' => '7',
'required' => true,
'primaryKey' => true
));
}
else
{
throw new sfException(sprintf('Missing main table for internationalized table "%s".', $i18n_table));
}
}
}
}
protected function fixYAMLColumns()
{
foreach ($this->getTables() as $table => $columns)
{
$has_primary_key = false;
foreach ($columns as $column => $attributes)
{
if ($attributes == null)
{
// conventions for null attributes
if ($column == 'created_at' || $column == 'updated_at')
{
// timestamp convention
$this->database[$table][$column]['type']= 'timestamp';
}
if ($column == 'id')
{
// primary key convention
$this->database[$table]['id'] = array(
'type' => 'integer',
'required' => true,
'primaryKey' => true,
'autoincrement' => true
);
$has_primary_key = true;
}
$pos = strpos($column, '_id');
if ($pos > 0 && $pos == strlen($column) - 3)
{
// foreign key convention
$foreign_table = $this->findTable(substr($column, 0, $pos));
if ($foreign_table)
{
$this->database[$table][$column] = array(
'type' => 'integer',
'foreignTable' => $foreign_table,
'foreignReference' => 'id'
);
}
else
{
throw new sfException(sprintf('Unable to resolve foreign table for column "%s"', $column));
}
}
}
else
{
if (!is_array($attributes))
{
// compact type given as single attribute
$this->database[$table][$column] = $this->getAttributesFromCompactType($attributes);
}
else
{
if (isset($attributes['type']))
{
// compact type given as value of the type attribute
$this->database[$table][$column] = array_merge($this->database[$table][$column], $this->getAttributesFromCompactType($attributes['type']));
}
if (isset($attributes['primaryKey']))
{
$has_primary_key = true;
}
}
}
}
if (!$has_primary_key)
{
// convention for tables without primary key
$this->database[$table]['id'] = array(
'type' => 'integer',
'required' => true,
'primaryKey' => true,
'autoincrement' => true
);
}
}
}
protected function getAttributesFromCompactType($type)
{
preg_match('/varchar\(([\d]+)\)/', $type, $matches);
if (isset($matches[1]))
{
return array('type' => 'varchar', 'size' => $matches[1]);
}
else
{
return array('type' => $type);
}
}
protected function setIfNotSet(&$entry, $key, $value)
{
if (!isset($entry[$key]))
{
$entry[$key] = $value;
}
}
protected function findTable($table_name)
{
// find a table from a phpName or a name
$table_match = false;
foreach ($this->getTables() as $tb_name => $table)
{
if ((isset($table['_attributes']['phpName']) && $table['_attributes']['phpName'] == sfInflector::camelize($table_name)) || ($tb_name == $table_name))
{
$table_match = $tb_name;
}
}
return $table_match;
}
protected function getAttributesForColumn($tb_name, $col_name, $column)
{
$attributes_string = '';
if (is_array($column))
{
foreach ($column as $key => $value)
{
if (!in_array($key, array('foreignTable', 'foreignReference', 'onDelete', 'onUpdate', 'index', 'unique')))
{
$attributes_string .= " $key=\"".htmlspecialchars($this->getCorrectValueFor($key, $value))."\"";
}
}
$attributes_string .= " />\n";
}
else
{
throw new sfException('Incorrect settings for column '.$col_name);
}
// conventions for foreign key attributes
if (is_array($column) && isset($column['foreignTable']))
{
$attributes_string .= " <foreign-key foreignTable=\"$column[foreignTable]\"";
if (isset($column['onDelete']))
{
$attributes_string .= " onDelete=\"$column[onDelete]\"";
}
if (isset($column['onUpdate']))
{
$attributes_string .= " onUpdate=\"$column[onUpdate]\"";
}
$attributes_string .= ">\n";
$attributes_string .= " <reference local=\"$col_name\" foreign=\"$column[foreignReference]\" />\n";
$attributes_string .= " </foreign-key>\n";
}
// conventions for index and unique index attributes
if (is_array($column) && isset($column['index']))
{
if ($column['index'] === 'unique')
{
$attributes_string .= " <unique name=\"${tb_name}_${col_name}_unique\">\n";
$attributes_string .= " <unique-column name=\"$col_name\" />\n";
$attributes_string .= " </unique>\n";
}
else
{
$attributes_string .= " <index name=\"${tb_name}_${col_name}_index\">\n";
$attributes_string .= " <index-column name=\"$col_name\" />\n";
$attributes_string .= " </index>\n";
}
}
// conventions for sequence name attributes
// required for databases using sequences for auto-increment columns (e.g. PostgreSQL or Oracle)
if (is_array($column) && isset($column['sequence']))
{
$attributes_string .= " <id-method-parameter value=\"$column[sequence]\" />\n";
}
return $attributes_string;
}
protected function getAttributesFor($tag)
{
if (!isset($tag['_attributes']))
{
return '';
}
$attributes = $tag['_attributes'];
$attributes_string = '';
foreach ($attributes as $key => $value)
{
$attributes_string .= ' '.$key.'="'.htmlspecialchars($this->getCorrectValueFor($key, $value)).'"';
}
return $attributes_string;
}
protected function getCorrectValueFor($key, $value)
{
$booleans = array('required', 'primaryKey', 'autoincrement', 'autoIncrement', 'noXsd', 'isI18N', 'isCulture');
if (in_array($key, $booleans))
{
return $value == 1 ? 'true' : 'false';
}
else
{
return is_null($value) ? 'null' : $value;
}
}
public function getTables()
{
return $this->getChildren($this->database);
}
public function getChildren($hash)
{
foreach ($hash as $key => $value)
{
// ignore special children (starting with _)
if ($key[0] == '_')
{
unset($hash[$key]);
}
}
return $hash;
}
public function loadXML($file)
{
$schema = simplexml_load_file($file);
$database = array();
// database
list($database_name, $database_attributes) = $this->getNameAndAttributes($schema->attributes());
if ($database_name)
{
$this->connection_name = $database_name;
}
else
{
throw new sfException('The database tag misses a name attribute');
}
if ($database_attributes)
{
$database['_attributes'] = $database_attributes;
}
// tables
foreach ($schema as $table)
{
list($table_name, $table_attributes) = $this->getNameAndAttributes($table->attributes());
if ($table_name)
{
$database[$table_name] = array();
}
else
{
throw new sfException('A table tag misses the name attribute');
}
if ($table_attributes)
{
$database[$table_name]['_attributes'] = $table_attributes;
}
// columns
foreach ($table->xpath('column') as $column)
{
list($column_name, $column_attributes) = $this->getNameAndAttributes($column->attributes());
if ($column_name)
{
$database[$table_name][$column_name] = $column_attributes;
}
else
{
throw new sfException('A column tag misses the name attribute');
}
}
// foreign-keys
$database[$table_name]['_foreign_keys'] = array();
foreach ($table->xpath('foreign-key') as $foreign_key)
{
$foreign_key_table = array();
// foreign key attributes
if (isset($foreign_key['foreignTable']))
{
$foreign_key_table['foreign_table'] = (string) $foreign_key['foreignTable'];
}
else
{
throw new sfException('A foreign key misses the foreignTable attribute');
}
if (isset($foreign_key['onDelete']))
{
$foreign_key_table['on_delete'] = (string) $foreign_key['onDelete'];
}
if (isset($foreign_key['onUpdate']))
{
$foreign_key_table['on_update'] = (string) $foreign_key['onUpdate'];
}
// foreign key references
$foreign_key_table['references'] = array();
foreach ($foreign_key->xpath('reference') as $reference)
{
$reference_attributes = array();
foreach ($reference->attributes() as $reference_attribute_name => $reference_attribute_value)
{
$reference_attributes[$reference_attribute_name] = strval($reference_attribute_value);
}
$foreign_key_table['references'][] = $reference_attributes;
}
if (isset($foreign_key['name']))
{
$database[$table_name]['_foreign_keys'][(string)$foreign_key['name']] = $foreign_key_table;
}
else
{
$database[$table_name]['_foreign_keys'][] = $foreign_key_table;
}
}
$this->removeEmptyKey($database[$table_name], '_foreign_keys');
// indexes
$database[$table_name]['_indexes'] = array();
foreach ($table->xpath('index') as $index)
{
$index_keys = array();
foreach ($index->xpath('index-column') as $index_key)
{
$index_keys[] = strval($index_key['name']);
}
$database[$table_name]['_indexes'][strval($index['name'])] = $index_keys;
}
$this->removeEmptyKey($database[$table_name], '_indexes');
// unique indexes
$database[$table_name]['_uniques'] = array();
foreach ($table->xpath('unique') as $index)
{
$unique_keys = array();
foreach ($index->xpath('unique-column') as $unique_key)
{
$unique_keys[] = strval($unique_key['name']);
}
$database[$table_name]['_uniques'][strval($index['name'])] = $unique_keys;
}
$this->removeEmptyKey($database[$table_name], '_uniques');
}
$this->database = $database;
$this->fixXML();
}
public function fixXML()
{
$this->fixXMLForeignKeys();
$this->fixXMLIndexes();
// $this->fixXMLColumns();
}
protected function fixXMLForeignKeys()
{
foreach ($this->getTables() as $table => $columns)
{
if (isset($this->database[$table]['_foreign_keys']))
{
$foreign_keys = $this->database[$table]['_foreign_keys'];
foreach ($foreign_keys as $foreign_key_name => $foreign_key_attributes)
{
// Only single foreign keys can be simplified
if (count($foreign_key_attributes['references']) == 1)
{
$reference = $foreign_key_attributes['references'][0];
// set simple foreign key
$this->database[$table][$reference['local']]['foreignTable'] = $foreign_key_attributes['foreign_table'];
$this->database[$table][$reference['local']]['foreignReference'] = $reference['foreign'];
if (isset($foreign_key_attributes['on_delete']))
{
$this->database[$table][$reference['local']]['onDelete'] = $foreign_key_attributes['on_delete'];
}
if (isset($foreign_key_attributes['on_update']))
{
$this->database[$table][$reference['local']]['onUpdate'] = $foreign_key_attributes['on_update'];
}
// remove complex foreign key
unset($this->database[$table]['_foreign_keys'][$foreign_key_name]);
}
$this->removeEmptyKey($this->database[$table], '_foreign_keys');
}
}
}
}
protected function fixXMLIndexes()
{
foreach ($this->getTables() as $table => $columns)
{
if (isset($this->database[$table]['_indexes']))
{
$indexes = $this->database[$table]['_indexes'];
foreach ($indexes as $index => $references)
{
// Only single indexes can be simplified
if (count($references) == 1 && array_key_exists(substr($index, 0, strlen($index) - 6), $columns))
{
$reference = $references[0];
// set simple index
$this->database[$table][$reference]['index'] = 'true';
// remove complex index
unset($this->database[$table]['_indexes'][$index]);
}
$this->removeEmptyKey($this->database[$table], '_indexes');
}
}
if (isset($this->database[$table]['_uniques']))
{
$uniques = $this->database[$table]['_uniques'];
foreach ($uniques as $index => $references)
{
// Only single unique indexes can be simplified
if (count($references) == 1 && array_key_exists(substr($index, 0, strlen($index) - 7), $columns))
{
$reference = $references[0];
// set simple index
$this->database[$table][$reference]['index'] = 'unique';
// remove complex unique index
unset($this->database[$table]['_uniques'][$index]);
}
$this->removeEmptyKey($this->database[$table], '_uniques');
}
}
}
}
protected function fixXMLColumns()
{
foreach ($this->getTables() as $table => $columns)
{
foreach ($columns as $column => $attributes)
{
if ($column == 'id' && !array_diff($attributes, array('type' => 'integer', 'required' => 'true', 'primaryKey' => 'true', 'autoincrement' => 'true')))
{
// simplify primary keys
$this->database[$table]['id'] = null;
}
if (($column == 'created_at') || ($column == 'updated_at') && !array_diff($attributes, array('type' => 'timestamp')))
{
// simplify timestamps
$this->database[$table][$column] = null;
}
$pos = strpos($column, '_id');
$has_fk_name = $pos > 0 && $pos == strlen($column) - 3;
$is_foreign_key = isset($attributes['type']) && $attributes['type'] == 'integer' && isset($attributes['foreignReference']) && $attributes['foreignReference'] == 'id';
$has_foreign_table = isset($attributes['foreignTable']) && array_key_exists($attributes['foreignTable'], $this->getTables());
$has_other_attribute = isset($attributes['onDelete']);
if ($has_fk_name && $has_foreign_table && $is_foreign_key && !$has_other_attribute)
{
// simplify foreign key
$this->database[$table][$column] = null;
}
}
}
}
public function asYAML()
{
return sfYaml::dump(array($this->connection_name => $this->database));
}
protected function getNameAndAttributes($hash, $name_attribute = 'name')
{
// tag name
$name = '';
if (isset($hash[$name_attribute]))
{
$name = strval($hash[$name_attribute]);
unset($hash[$name_attribute]);
}
// tag attributes
$attributes = array();
foreach ($hash as $attribute => $value)
{
$attributes[$attribute] = strval($value);
}
return array($name, $attributes);
}
protected function removeEmptyKey(&$hash, $key)
{
if (isset($hash[$key]) && !$hash[$key])
{
unset($hash[$key]);
}
}
}

View File

@ -0,0 +1,106 @@
<?php
/*
* This file is part of the symfony package.
* (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
*
* @package symfony
* @subpackage util
* @author Nick Lane <nick.lane@internode.on.net>
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @version SVN: $Id: sfPropelManyToMany.class.php 1931 2006-09-02 17:56:18Z fabien $
*/
class sfPropelManyToMany
{
public static function getColumn($class, $middleClass)
{
// find the related class
$tableMap = call_user_func(array($middleClass.'Peer', 'getTableMap'));
$object_table_name = constant($class.'Peer::TABLE_NAME');
foreach ($tableMap->getColumns() as $column)
{
if ($column->isForeignKey() && $object_table_name == $column->getRelatedTableName())
{
return $column;
}
}
}
public static function getRelatedColumn($class, $middleClass)
{
// find the related class
$tableMap = call_user_func(array($middleClass.'Peer', 'getTableMap'));
$object_table_name = constant($class.'Peer::TABLE_NAME');
foreach ($tableMap->getColumns() as $column)
{
if ($column->isForeignKey() && $object_table_name != $column->getRelatedTableName())
{
return $column;
}
}
}
public static function getRelatedClass($class, $middleClass)
{
$column = self::getRelatedColumn($class, $middleClass);
// we must load all map builder classes
$classes = sfFinder::type('file')->name('*MapBuilder.php')->in(sfLoader::getModelDirs());
foreach ($classes as $class)
{
$class_map_builder = basename($class, '.php');
$map = new $class_map_builder();
$map->doBuild();
}
$tableMap = call_user_func(array($middleClass.'Peer', 'getTableMap'));
return $tableMap->getDatabaseMap()->getTable($column->getRelatedTableName())->getPhpName();
}
public static function getAllObjects($object, $middleClass, $criteria = null)
{
if (null === $criteria)
{
$criteria = new Criteria();
}
$relatedClass = self::getRelatedClass(get_class($object), $middleClass);
return call_user_func(array($relatedClass.'Peer', 'doSelect'), $criteria);
}
/**
* Gets objects related by a many-to-many relationship, with a middle table.
*
* @param $object The object to get related objects for.
* @param $middleClass The middle class used for the many-to-many relationship.
* @param $criteria Criteria to apply to the selection.
*/
public static function getRelatedObjects($object, $middleClass, $criteria = null)
{
if (null === $criteria)
{
$criteria = new Criteria();
}
$relatedClass = self::getRelatedClass(get_class($object), $middleClass);
$relatedObjects = array();
$objectMethod = 'get'.$middleClass.'sJoin'.$relatedClass;
$relatedMethod = 'get'.$relatedClass;
$rels = $object->$objectMethod($criteria);
foreach ($rels as $rel)
{
$relatedObjects[] = $rel->$relatedMethod();
}
return $relatedObjects;
}
}

View File

@ -0,0 +1,138 @@
<?php
/*
* This file is part of the symfony package.
* (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* @package symfony
* @subpackage addon
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @version SVN: $Id: sfPropelPager.class.php 2728 2006-11-17 09:46:01Z chtito $
*/
/**
*
* sfPropelPager class.
*
* @package symfony
* @subpackage addon
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @version SVN: $Id: sfPropelPager.class.php 2728 2006-11-17 09:46:01Z chtito $
*/
class sfPropelPager extends sfPager
{
protected
$criteria = null,
$peer_method_name = 'doSelect',
$peer_count_method_name = 'doCount';
public function __construct($class, $maxPerPage = 10)
{
parent::__construct($class, $maxPerPage);
$this->setCriteria(new Criteria());
$this->tableName = constant($class.'Peer::TABLE_NAME');
}
public function init()
{
$hasMaxRecordLimit = ($this->getMaxRecordLimit() !== false);
$maxRecordLimit = $this->getMaxRecordLimit();
$cForCount = clone $this->getCriteria();
$cForCount->setOffset(0);
$cForCount->setLimit(0);
$cForCount->clearGroupByColumns();
// require the model class (because autoloading can crash under some conditions)
if (!$classPath = sfCore::getClassPath($this->getClassPeer()))
{
throw new sfException(sprintf('Unable to find path for class "%s".', $this->getClassPeer()));
}
require_once($classPath);
$count = call_user_func(array($this->getClassPeer(), $this->getPeerCountMethod()), $cForCount);
$this->setNbResults($hasMaxRecordLimit ? min($count, $maxRecordLimit) : $count);
$c = $this->getCriteria();
$c->setOffset(0);
$c->setLimit(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();
$c->setOffset($offset);
if ($hasMaxRecordLimit)
{
$maxRecordLimit = $maxRecordLimit - $offset;
if ($maxRecordLimit > $this->getMaxPerPage())
{
$c->setLimit($this->getMaxPerPage());
}
else
{
$c->setLimit($maxRecordLimit);
}
}
else
{
$c->setLimit($this->getMaxPerPage());
}
}
}
protected function retrieveObject($offset)
{
$cForRetrieve = clone $this->getCriteria();
$cForRetrieve->setOffset($offset - 1);
$cForRetrieve->setLimit(1);
$results = call_user_func(array($this->getClassPeer(), $this->getPeerMethod()), $cForRetrieve);
return $results[0];
}
public function getResults()
{
$c = $this->getCriteria();
return call_user_func(array($this->getClassPeer(), $this->getPeerMethod()), $c);
}
public function getPeerMethod()
{
return $this->peer_method_name;
}
public function setPeerMethod($peer_method_name)
{
$this->peer_method_name = $peer_method_name;
}
public function getPeerCountMethod()
{
return $this->peer_count_method_name;
}
public function setPeerCountMethod($peer_count_method_name)
{
$this->peer_count_method_name = $peer_count_method_name;
}
public function getClassPeer()
{
return $this->class.'Peer';
}
}

View File

@ -0,0 +1,98 @@
<?php
/*
* This file is part of the symfony package.
* (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* sfPropelUniqueValidator validates that the uniqueness of a column.
* This validator only works for single column primary key.
*
* <b>Required parameters:</b>
*
* # <b>class</b> - [none] - Propel class name.
* # <b>column</b> - [none] - Propel column name.
*
* <b>Optional parameters:</b>
*
* # <b>unique_error</b> - [Uniqueness error] - An error message to use when
* the value for this column already
* exists in the database.
*
* @package symfony
* @subpackage validator
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @author Fédéric Coelho <frederic.coelho@symfony-project.com>
* @version SVN: $Id: sfPropelUniqueValidator.class.php 2995 2006-12-09 18:01:32Z fabien $
*/
class sfPropelUniqueValidator extends sfValidator
{
public function execute(&$value, &$error)
{
$className = $this->getParameter('class').'Peer';
$columnName = call_user_func(array($className, 'translateFieldName'), $this->getParameter('column'), BasePeer::TYPE_FIELDNAME, BasePeer::TYPE_COLNAME);
$c = new Criteria();
$c->add($columnName, $value);
$object = call_user_func(array($className, 'doSelectOne'), $c);
if ($object)
{
$tableMap = call_user_func(array($className, 'getTableMap'));
foreach ($tableMap->getColumns() as $column)
{
if (!$column->isPrimaryKey())
{
continue;
}
$method = 'get'.$column->getPhpName();
$primaryKey = call_user_func(array($className, 'translateFieldName'), $column->getPhpName(), BasePeer::TYPE_PHPNAME, BasePeer::TYPE_FIELDNAME);
if ($object->$method() != $this->getContext()->getRequest()->getParameter($primaryKey))
{
$error = $this->getParameter('unique_error');
return false;
}
}
}
return true;
}
/**
* Initialize this validator.
*
* @param sfContext The current application context.
* @param array An associative array of initialization parameters.
*
* @return bool true, if initialization completes successfully, otherwise false.
*/
public function initialize($context, $parameters = null)
{
// initialize parent
parent::initialize($context);
// set defaults
$this->setParameter('unique_error', 'Uniqueness error');
$this->getParameterHolder()->add($parameters);
// check parameters
if (!$this->getParameter('class'))
{
throw new sfValidatorException('The "class" parameter is mandatory for the sfPropelUniqueValidator validator.');
}
if (!$this->getParameter('column'))
{
throw new sfValidatorException('The "column" parameter is mandatory for the sfPropelUniqueValidator validator.');
}
return true;
}
}

View File

@ -0,0 +1,120 @@
<?php
/*
* This file is part of the symfony package.
* (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* This class defines the interface for interacting with data, as well
* as default implementations.
*
* @package symfony
* @subpackage addon
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @version SVN: $Id: sfData.class.php 3382 2007-02-01 07:34:56Z fabien $
*/
abstract class sfData
{
protected
$deleteCurrentData = true,
$object_references = array();
/**
* Sets a flag to indicate if the current data in the database
* should be deleted before new data is loaded.
*
* @param boolean The flag value
*/
public function setDeleteCurrentData($boolean)
{
$this->deleteCurrentData = $boolean;
}
/**
* Gets the current value of the flag that indicates whether
* current data is to be deleted or not.
*
* @returns boolean
*/
public function getDeleteCurrentData()
{
return $this->deleteCurrentData;
}
/**
* Loads data for the database from a YAML file
*
* @param string The path to the YAML file.
*/
protected function doLoadDataFromFile($fixture_file)
{
// import new datas
$data = sfYaml::load($fixture_file);
$this->loadDataFromArray($data);
}
/**
* Manages the insertion of data into the data source
*
* @param array The data to be inserted into the data source
*/
abstract public function loadDataFromArray($data);
/**
* Manages reading all of the fixture data files and
* loading them into the data source
*
* @param array The path names of the YAML data files
*/
protected function doLoadData($fixture_files)
{
$this->object_references = array();
$this->maps = array();
sort($fixture_files);
foreach ($fixture_files as $fixture_file)
{
$this->doLoadDataFromFile($fixture_file);
}
}
/**
* Gets a list of one or more *.yml files and returns the list in an array
*
* @param string A directory or file name; if null, then defaults to 'sf_data_dir'/fixtures
*
* @returns array A list of *.yml files.
*
* @throws sfInitializationException If the directory or file does not exist.
*/
protected function getFiles($directory_or_file = null)
{
// directory or file?
$fixture_files = array();
if (!$directory_or_file)
{
$directory_or_file = sfConfig::get('sf_data_dir').'/fixtures';
}
if (is_file($directory_or_file))
{
$fixture_files[] = $directory_or_file;
}
else if (is_dir($directory_or_file))
{
$fixture_files = sfFinder::type('file')->name('*.yml')->in($directory_or_file);
}
else
{
throw new sfInitializationException('You must give a directory or a file.');
}
return $fixture_files;
}
}

View File

@ -0,0 +1,406 @@
<?php
/*
* This file is part of the symfony package.
* (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
*
* sfMail class.
*
* @package symfony
* @subpackage addon
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @version SVN: $Id: sfMail.class.php 3172 2007-01-05 16:03:15Z fabien $
*/
class sfMail
{
protected $mailer;
public function __construct()
{
require_once(sfConfig::get('sf_symfony_lib_dir').'/vendor/phpmailer/class.phpmailer.php');
require_once(sfConfig::get('sf_symfony_lib_dir').'/vendor/phpmailer/class.smtp.php');
$this->mailer = new PHPMailer();
}
public function initialize()
{
}
public function setCharset($charset)
{
$this->mailer->CharSet = $charset;
}
public function getCharset()
{
return $this->mailer->CharSet;
}
public function setContentType($content_type)
{
$this->mailer->ContentType = $content_type;
}
public function getContentType()
{
return $this->mailer->ContentType;
}
public function setPriority($priority)
{
$this->mailer->Priority = $priority;
}
public function getPriority()
{
return $this->mailer->Priority;
}
public function setEncoding($encoding)
{
$this->mailer->Encoding = $encoding;
}
public function getEncoding()
{
return $this->mailer->Encoding;
}
public function setSubject($subject)
{
$this->mailer->Subject = $subject;
}
public function getSubject()
{
return $this->mailer->Subject;
}
public function setBody($body)
{
$this->mailer->Body = $body;
}
public function getBody()
{
return $this->mailer->Body;
}
public function setMailer($type = 'mail', $options = array())
{
switch ($type)
{
case 'smtp':
$this->mailer->IsSMTP();
if (isset($options['keep_alive'])) $this->mailer->SMTPKeepAlive = true;
break;
case 'sendmail':
$this->mailer->IsSendmail();
break;
default:
$this->mailer->IsMail();
break;
}
}
public function getMailer()
{
return $this->mailer->Mailer;
}
public function setSender($address, $name = null)
{
if (!$address)
{
return;
}
if ($name == null)
{
list($address, $name) = $this->splitAddress($address);
}
$this->mailer->Sender = $address;
}
public function getSender()
{
return $this->mailer->Sender;
}
public function setFrom($address, $name = null)
{
if (!$address)
{
return;
}
if ($name == null)
{
list($address, $name) = $this->splitAddress($address);
}
$this->mailer->From = $address;
$this->mailer->FromName = $name;
}
public function getFrom()
{
return $this->mailer->From;
}
/*
* $recipents:
* test@example.com
* Example email <test@example.com>
* array('test@example.com', 'test1@example.com')
* array('Example email <test@example.com>', 'test1@example.com')
*/
public function addAddresses($addresses)
{
if (!$addresses)
{
return;
}
if (is_array($addresses))
{
foreach ($addresses as $address)
{
list($address, $name) = $this->splitAddress($address);
$this->mailer->AddAddress($address, $name);
}
}
else
{
list($address, $name) = $this->splitAddress($addresses);
$this->mailer->AddAddress($address, $name);
}
}
private function splitAddress($address)
{
if (preg_match('/^(.+)\s<(.+?)>$/', $address, $matches))
{
return array($matches[2], $matches[1]);
}
else
{
return array($address, '');
}
}
public function addAddress($address, $name = null)
{
if ($name == null)
{
list($address, $name) = $this->splitAddress($address);
}
$this->mailer->AddAddress($address, $name);
}
public function addCc($address, $name = null)
{
if ($name == null)
{
list($address, $name) = $this->splitAddress($address);
}
$this->mailer->AddCc($address, $name);
}
public function addBcc($address, $name = null)
{
if ($name == null)
{
list($address, $name) = $this->splitAddress($address);
}
$this->mailer->AddBcc($address, $name);
}
public function addReplyTo($address, $name = null)
{
if (!$address)
{
return;
}
if ($name == null)
{
list($address, $name) = $this->splitAddress($address);
}
$this->mailer->AddReplyTo($address, $name);
}
public function clearAddresses()
{
$this->mailer->ClearAddresses();
}
public function clearCcs()
{
$this->mailer->ClearCcs();
}
public function clearBccs()
{
$this->mailer->ClearBccs();
}
public function clearReplyTos()
{
$this->mailer->ClearReplyTos();
}
public function clearAllRecipients()
{
$this->mailer->ClearAllRecipients();
}
public function addAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream')
{
$this->mailer->AddAttachment($path, $name, $encoding, $type);
}
public function addStringAttachment($string, $filename, $encoding = 'base64', $type = 'application/octet-stream')
{
$this->mailer->AddStringAttachment($string, $filename, $encoding, $type);
}
public function addEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = 'application/octet-stream')
{
$this->mailer->AddEmbeddedImage($path, $cid, $name, $encoding, $type);
}
public function setAttachments($attachments)
{
if ($attachments instanceof sfMailAttachments)
{
$this->mailer->setAttachments($attachments->getAttachments());
}
}
public function clearAttachments()
{
$this->mailer->ClearAttachments();
}
function addCustomHeader($name, $value)
{
$this->mailer->AddCustomHeader("$name: $value");
}
function clearCustomHeaders()
{
$this->mailer->ClearCustomHeaders();
}
public function prepare()
{
// Set whether the message is multipart/alternative
if (!empty($this->mailer->AltBody))
{
$this->mailer->ContentType = "multipart/alternative";
}
$this->mailer->SetMessageType();
}
public function send()
{
if (!$this->mailer->Send())
{
throw new sfException($this->mailer->ErrorInfo);
}
}
public function smtpClose()
{
$this->mailer->SmtpClose();
}
public function getRawHeader()
{
return $this->mailer->CreateHeader();
}
public function getRawBody()
{
return $this->mailer->CreateBody();
}
public function setDomain($hostname)
{
$this->mailer->Hostname = $hostname;
}
public function getDomain()
{
return $this->mailer->Hostname;
}
public function setHostname($hostname)
{
$this->mailer->Host = $hostname;
}
public function getHostname()
{
return $this->mailer->Host;
}
public function setPort($port)
{
$this->mailer->Port = $port;
}
public function getPort()
{
return $this->mailer->Port;
}
public function setUsername($username)
{
$this->mailer->Username = $username;
$this->mailer->SMTPAuth = $username ? true : false;
}
public function getUsername()
{
return $this->mailer->Username;
}
public function setPassword($password)
{
$this->mailer->Password = $password;
}
public function getPassword()
{
return $this->mailer->Password;
}
public function setWordWrap($wordWrap)
{
$this->mailer->WordWrap = $wordWrap;
}
public function getWordWrap()
{
return $this->mailer->WordWrap;
}
public function setAltBody($text)
{
$this->mailer->AltBody = $text;
}
public function getAltBody()
{
return $this->mailer->AltBody;
}
}

View File

@ -0,0 +1,307 @@
<?php
/*
* This file is part of the symfony package.
* (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* @package symfony
* @subpackage addon
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @version SVN: $Id: sfPager.class.php 3099 2006-12-20 08:16:15Z fabien $
*/
/**
*
* sfPager class.
*
* @package symfony
* @subpackage addon
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
* @version SVN: $Id: sfPager.class.php 3099 2006-12-20 08:16:15Z fabien $
*/
abstract class sfPager
{
protected
$page = 1,
$maxPerPage = 0,
$lastPage = 1,
$nbResults = 0,
$class = '',
$tableName = '',
$objects = null,
$cursor = 1,
$parameters = array(),
$currentMaxLink = 1,
$parameterHolder = null,
$maxRecordLimit = false;
public function __construct($class, $maxPerPage = 10)
{
$this->setClass($class);
$this->setMaxPerPage($maxPerPage);
$this->setPage(1);
$this->parameterHolder = new sfParameterHolder();
}
// function to be called after parameters have been set
abstract public function init();
// main method: returns an array of result on the given page
abstract public function getResults();
// used internally by getCurrent()
abstract protected function retrieveObject($offset);
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 = $begin;
while (($i < $begin + $nb_links) && ($i <= $this->lastPage))
{
$links[] = $i++;
}
$this->currentMaxLink = $links[count($links) - 1];
return $links;
}
public function haveToPaginate()
{
return (($this->getPage() != 0) && ($this->getNbResults() > $this->getMaxPerPage()));
}
public function getCursor()
{
return $this->cursor;
}
public function setCursor($pos)
{
if ($pos < 1)
{
$this->cursor = 1;
}
else if ($pos > $this->nbResults)
{
$this->cursor = $this->nbResults;
}
else
{
$this->cursor = $pos;
}
}
public function getObjectByCursor($pos)
{
$this->setCursor($pos);
return $this->getCurrent();
}
public function getCurrent()
{
return $this->retrieveObject($this->cursor);
}
public function getNext()
{
if (($this->cursor + 1) > $this->nbResults)
{
return null;
}
else
{
return $this->retrieveObject($this->cursor + 1);
}
}
public function getPrevious()
{
if (($this->cursor - 1) < 1)
{
return null;
}
else
{
return $this->retrieveObject($this->cursor - 1);
}
}
public function getFirstIndice()
{
if ($this->page == 0)
{
return 1;
}
else
{
return ($this->page - 1) * $this->maxPerPage + 1;
}
}
public function getLastIndice()
{
if ($this->page == 0)
{
return $this->nbResults;
}
else
{
if (($this->page * $this->maxPerPage) >= $this->nbResults)
{
return $this->nbResults;
}
else
{
return ($this->page * $this->maxPerPage);
}
}
}
public function getCriteria()
{
return $this->criteria;
}
public function setCriteria($c)
{
$this->criteria = $c;
}
public function getClass()
{
return $this->class;
}
public function setClass($class)
{
$this->class = $class;
}
public function getNbResults()
{
return $this->nbResults;
}
protected function setNbResults($nb)
{
$this->nbResults = $nb;
}
public function getFirstPage()
{
return 1;
}
public function getLastPage()
{
return $this->lastPage;
}
protected function setLastPage($page)
{
$this->lastPage = $page;
if ($this->getPage() > $page)
{
$this->setPage($page);
}
}
public function getPage()
{
return $this->page;
}
public function getNextPage()
{
return min($this->getPage() + 1, $this->getLastPage());
}
public function getPreviousPage()
{
return max($this->getPage() - 1, $this->getFirstPage());
}
public function setPage($page)
{
$page = intval($page);
$this->page = ($page <= 0) ? 1 : $page;
}
public function getMaxPerPage()
{
return $this->maxPerPage;
}
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 getParameterHolder()
{
return $this->parameterHolder;
}
public function getParameter($name, $default = null, $ns = null)
{
return $this->parameterHolder->get($name, $default, $ns);
}
public function hasParameter($name, $ns = null)
{
return $this->parameterHolder->has($name, $ns);
}
public function setParameter($name, $value, $ns = null)
{
return $this->parameterHolder->set($name, $value, $ns);
}
}