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,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;
}
}