1
0
mirror of synced 2024-12-15 07:36:03 +03:00
doctrine2/website/plugins/sfDoctrinePlugin/addon/sfDoctrineClassSchema.class.php

503 lines
12 KiB
PHP
Raw Normal View History

2007-09-01 03:41:48 +04:00
<?php
/*
* This file is part of the sfDoctrine package.
* (c) 2006-2007 Olivier Verdier <Olivier.Verdier@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* @package symfony.plugins
* @subpackage sfDoctrine
* @author Olivier Verdier <Olivier.Verdier@gmail.com>
* @version SVN: $Id: sfDoctrineClassSchema.class.php 4696 2007-07-20 17:04:44Z gnat $
*/
class sfDoctrineClassSchema
{
// the table associated to this class
protected $table;
// class name
protected $phpName;
// list of columns
protected $columns = array();
// list of relations (foreign keys) linking to this class
protected $many = array();
// inheritance description
protected $inheritance = array();
// i18n description
protected $i18n = array();
// indexes
protected $indexes = array();
// Uniques
protected $uniques = array();
// options
protected $options = array();
public function __construct($name, array $cd = array())
{
$this->setPhpName($name);
// elementary key verification
$illegalKeys = array_diff_key($cd, array_flip(array('columns', 'tableName', 'inheritance', 'i18n', 'indexes', 'uniques', 'options')));
if ($illegalKeys)
throw new sfDoctrineSchemaException(sprintf('Invalid key "%s" in description of class "%s"', array_shift(array_keys($illegalKeys)), $name));
if (isset($cd['inheritance']))
{
$this->setInheritance($cd['inheritance']);
}
// set i18n
if (isset($cd['i18n']))
$this->setI18n($cd['i18n']);
// add indexes
if (isset($cd['indexes']))
$this->addIndexes($cd['indexes']);
// add uniques
if (isset($cd['uniques']))
$this->addUniques($cd['uniques']);
// add options
if (isset($cd['options']))
$this->addOptions($cd['options']);
// add columns
if (isset($cd['columns']))
foreach ($cd['columns'] as $colName => $column)
{
$docCol = new sfDoctrineColumnSchema($colName, $column);
$this->addColumn($docCol);
}
}
// add a column if none with the same name is already there
public function addColumn($docCol)
{
if (isset($this->columns[$docCol->getName()]))
return;
// sets up the possible relation for that column
$docCol->setUpForeignRelation($this->getPhpName());
$this->columns[$docCol->getName()] = $docCol;
}
public function getColumns()
{
return $this->columns;
}
// for testing only
public function getColumn($colName)
{
if (!isset($this->columns[$colName]))
throw new sfDoctrineSchemaException(sprintf('Column "%s" is not defined', $colName));
return $this->columns[$colName];
}
public function addToMany($relation)
{
$this->many[] = $relation;
}
public function getPhpName()
{
return $this->phpName;
}
public function setPhpName($newName)
{
$this->phpName = $newName;
}
public function setTable($table)
{
$this->table = $table;
}
public function getTable()
{
if (!$this->hasTable())
throw new sfDoctrineSchemaException(sprintf('Table not defined for class "%s"', $this->getPhpName()));
return $this->table;
}
public function getTableName()
{
return $this->getTable()->getName();
}
public function hasTable()
{
return isset($this->table);
}
public function setI18n($i18n)
{
$check = array('class', 'cultureField');
foreach ($check as $key)
if (!isset($i18n[$key]))
throw new sfDoctrineSchemaException(sprintf('The key "%s" is missing from the i18n information for class "%s".', $key, $this->getPhpName()));
$this->i18n = $i18n;
}
public function hasI18n()
{
return !empty($this->i18n);
}
public function getI18n($key)
{
return $this->i18n[$key];
}
public function setInheritance($inh)
{
$check = array('extends');
if (isset($inh['keyField']) || isset($inh['keyValue']))
$check = array_merge($check, array('keyField', 'keyValue'));
elseif (isset($inh['keyFields']))
$check = array_merge($check, array('keyFields'));
foreach ($check as $key)
if (!isset($inh[$key]))
throw new sfDoctrineSchemaException(sprintf('The key "%s" is missing from the inheritance information for class "%s".', $key, $this->getPhpName()));
$this->inheritance = $inh;
}
public function getInheritance()
{
return $this->inheritance;
}
public function hasOneTableInheritance()
{
if ($inh = $this->inheritance)
if (isset($inh['keyValue']) || isset($inh['keyFields']))
return true;
return false;
}
public function getOptions()
{
return $this->options;
}
public function addOptions($options)
{
$this->options = $options;
}
public function hasOptions()
{
return count($this->options) ? true : false;
}
public function getIndexes()
{
return $this->indexes;
}
public function addIndexes($indexes)
{
$this->indexes = $indexes;
}
public function hasIndexes()
{
return count($this->indexes) ? true : false;
}
public function addUniques($uniques)
{
$this->uniques = $uniques;
}
public function hasUniques()
{
return count($this->uniques) ? true : false;
}
public function getParentClassName()
{
return $this->inheritance['extends'];
}
// generates the name of the generated class
public function basePhpName($name = null)
{
if (!$name)
$name = $this->getPhpName();
return 'Base'.$name;
}
// outputs a function in php
public static function outputFunction($functionName, $contents, $phpdoc = '')
{
if (is_array($contents))
$contents = implode("\n ", $contents);
return "
$phpdoc
public function $functionName()
{
$contents
}
";
}
// output a class in php
public static function outputClass($className, $extends, $contents, $phpdoc = '')
{
$signature = sprintf("auto-generated by the sfDoctrine plugin");
return "<?php
/*
* $phpdoc
*
* $signature
*/
class $className extends $extends
{
$contents
}
";
}
public function getRelation($columnName)
{
return $this->columns[$columnName]->getRelation();
}
// this function returns an array ('className'=><class name>, 'source'=><class file contents>, 'base'=>true/false) of PHP classes
// corresponding to this class
public function asPHP()
{
$classes = array();
// main base class
$out = array();
$tableDef = array();
$setup = array();
// if that class inherits from another we call the parent methods
if ($this->inheritance)
{
$tableDef[] = "parent::setTableDefinition();\n";
$setup[] = "parent::setUp();\n";
}
// if it is a table we define the table name
if ($this->hasTable())
{
$tableDef[] = "\$this->setTableName('{$this->getTableName()}');\n";
}
foreach ($this->columns as $column)
{
$args = array();
$tableDef[] = $column->asPhp();
}
// declare indexes if any
foreach ($this->indexes as $name => $value)
{
// only write option if value is set
if(!empty($value))
{
$valueExport = is_array($value) ? var_export($value, true) : "'$value'";
$tableDef[] = "\$this->index('$name', $valueExport);";
}
}
// declare uniques if any
foreach ($this->uniques as $name => $value)
{
// only write option if value is set
if(!empty($value))
{
$valueExport = is_array($value) ? var_export($value, true) : "'$value'";
$tableDef[] = "\$this->unique('$name', $valueExport);";
}
}
foreach ($this->options as $name => $value)
{
// only write option if value is set
if(!empty($value))
{
$valueExport = is_array($value) ? var_export($value, true) : "'$value'";
$tableDef[] = "\$this->option('$name', $valueExport);";
}
}
$out[] = self::outputFunction('setTableDefinition', $tableDef);
// has/own one
foreach($this->columns as $col)
if ($rel = $col->getRelation())
{
$setup[] = $rel->asOnePhp();
}
// has/own many
foreach($this->many as $rel)
{
$setup[] = $rel->asManyPhp();
}
// declare inheritance if needed
if ($this->hasOneTableInheritance())
{
$inh = $this->getInheritance();
if (isset($inh['keyFields']))
{
$keyFields = $inh['keyFields'];
$keyFields = is_array($keyFields) ? $keyFields : array($keyFields);
}
else
$keyFields = array($inh['keyField'] => $inh['keyValue']);
$setup[] = '$this->setInheritanceMap('.var_export($keyFields, true).');';
}
// declare i18n if any
if ($this->hasI18n())
$setup[] = "\$this->hasI18nTable('{$this->getI18n('class')}', '{$this->getI18n('cultureField')}');";
$out[] = self::outputFunction('setUp', $setup);
// the following could also be: if ($this->inheritance)
// FIXME: create a global class!
if (isset($this->inheritance['extends']))
$parentName = $this->inheritance['extends'];
else
$parentName = ($this->hasI18n() ? 'sfDoctrineRecordI18n' : 'sfDoctrineRecord');
$class = array
(
'name' => $this->getPhpName(), // name of the child class; used only internally
'className' => $this->basePHPName(),
'source' => self::outputClass($this->basePHPName(), $parentName, implode("\n", $out), 'Base class; DO NOT EDIT'),
'overwrite' => true, // carful! even this set to false will overwrite!!!
);
$classes[] = $class;
$package = $this->getTable()->getPackage();
// generate the empty user and table classes
foreach ($classes as $baseClass)
{
$name = $baseClass['name'];
$parentClass = $baseClass['className'];
$tableName = $name.'Table'; // convention imposed by Doctrine
if (isset($this->inheritance['extends']))
$parentTable = $this->inheritance['extends'].'Table';
else
$parentTable = 'Doctrine_Table';
if ($package)
{
$pluginClassName = 'Plugin'.$name;
$classes[] = array
(
'className'=> $pluginClassName,
'source' => self::outputClass($pluginClassName, $parentClass, '', 'Plugin class'),
'plugin' => true,
);
// we hook the plugin class name in
$parentClass = $pluginClassName;
// same for tables
$pluginTableName = 'Plugin'.$tableName;
$classes[] = array
(
'className' => $pluginTableName,
'source' => self::outputClass($pluginTableName, $parentTable, '', 'Plugin table'),
'plugin' => true,
);
$parentTable = $pluginTableName;
}
$classes[] = array
(
'className'=>$name,
'source'=>self::outputClass($name, $parentClass, '', 'Edit this file to customise your model class'),
);
$classes[] = array
(
'className'=>$tableName,
'source'=>self::outputClass($tableName, $parentTable, '', 'Edit this file to customise your model table'),
);
}
return $classes;
}
// outputs a nested array
public function asDoctrineYml()
{
$output = array();
if ($this->inheritance)
$output['inheritance'] = $this->inheritance;
else
$output['tableName'] = $this->getTableName();
$cols = array();
foreach ($this->columns as $col)
{
$cols[$col->getName()] = $col->asDoctrineYml();
}
$output['columns'] = $cols;
return $output;
}
// outputs the columns of that class in propel xml format
public function addPropelXmlColumns(&$table)
{
// we add the id column which is automatically created in doctrine
$this->addColumn(new sfDoctrineColumnSchema('id', array('type'=>'integer', 'size'=>10, 'primary'=>true, 'autoincrement'=>true)));
foreach($this->columns as $col)
{
$col->addPropelXml($table);
}
}
public function debug()
{
$debug = array();
$debug['inheritance'] = $this->inheritance;
$debug['many'] = $this->many;
$debug['i18n'] = $this->i18n;
foreach ($this->columns as $col)
{
$debug['columns'][$col->getName()] = $col->debug();
}
return $debug;
}
}