1
0
mirror of synced 2024-12-14 15:16:04 +03:00
doctrine2/website/plugins/sfDoctrinePlugin/lib/sfDoctrineData.class.php
2007-08-31 23:41:48 +00:00

362 lines
8.9 KiB
PHP

<?php
/*
* This file is part of the sfDoctrine package.
* (c) 2006 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 sfDoctrinePlugin
* @subpackage sfDoctrineData
* @author Olivier Verdier <Olivier.Verdier@gmail.com>
* @version SVN: $Id: sfDoctrineData.class.php 4493 2007-06-30 00:47:02Z Jonathan.Wage $
*/
class sfDoctrineData extends sfData
{
/**
* connectionName
*
* @var mixed
* @access protected
*/
protected $connectionName = null;
/**
* loadData
*
* @param mixed $directory_or_file
* @param mixed $connectionName
* @access public
* @return void
*/
public function loadData($directory_or_file = null, $connectionName = null)
{
$this->connectionName = $connectionName;
$fixture_files = $this->getFiles($directory_or_file);
// wrap all database operations in a single transaction
$con = sfDoctrine::connection($connectionName);
try
{
$con->beginTransaction();
$this->doLoadData($fixture_files);
$con->commit();
}
catch (Exception $e)
{
$con->rollback();
throw $e;
}
}
/**
* loadDataFromArray
*
* @param mixed $data
* @access public
* @return void
*/
public function loadDataFromArray($data)
{
$pendingRelations = array();
if ($data === null)
{
// no data
return;
}
// only for pake_echo_action
require_once(sfConfig::get('sf_symfony_lib_dir').'/vendor/pake/pakeFunction.php');
foreach ($data as $class => $entries)
{
pake_echo_action('Filling', sprintf('class "%s"', $class)."\t");
// fetch a table object
$table = sfDoctrine::getTable($class, $this->connectionName);
$colNames = array_keys($table->getColumns());
$tableName = $table->getTableName();
// relation fields
$relations = $table->getRelations();
//echo "Class $class: ".implode(', ', array_keys($relations))."\n";
if ($this->deleteCurrentData)
{
$q = new Doctrine_Query();
$q->delete()->from($class);
$q->execute();
}
// iterate through entries for this class
// might have been empty just for force a table to be emptied on import
if (is_array($entries))
{
foreach ($entries as $key => $columnAssignments)
{
// create a new entry in the database
$obj = $table->create();
$now = date("Y-m-d H:i:s", time());
if($obj->getTable()->hasColumn('created_at'))
{
$obj->set('created_at', $now);
}
if (!is_array($columnAssignments))
{
throw new Exception('You must give a name for each fixture data entry');
}
foreach ($columnAssignments as $name => $value)
{
$isRelation = isset($relations[$name]);
// foreign key?
if ($isRelation)
{
$rel = $relations[$name];
// $relatedTable = $rel->getTable()->getTableName();
$localKey = $rel->getLocal();
$foreignKey = $rel->getForeign();
$pendingRelations[] = array($obj, $localKey, $foreignKey, $value);
}
else
{
// first check that the column exists
if (!in_array($name, $colNames))
{
$error = 'Column "%s" does not exist for class "%s"';
$error = sprintf($error, $name, $class);
throw new sfException($error);
}
$obj->rawSet($name, $value);
}
}
$obj->save();
// For progress meter
echo '.';
// save the id for future reference
$pk = $obj->obtainIdentifier();
if (isset($this->object_references[$key]))
{
throw new sfException(sprintf('The key "%s" is not unique', $key));
}
$this->object_references[$key] = $pk;
}
}
echo "\n";
}
// now we take care of the pending relations
foreach ($pendingRelations as $pending)
{
list($obj, $localKey, $foreignKey, $key) = $pending;
if (!isset($this->object_references[$key]))
{
$error = 'No object with key "%s" is defined in your data file';
$error = sprintf($error, $key);
throw new sfException($error);
}
$foreignId = $this->object_references[$key][$foreignKey];
$obj->rawSet($localKey, $foreignId);
$obj->save();
}
}
/**
* loadMapBuilder
*
* @param mixed $class
* @access protected
* @return void
*/
protected function loadMapBuilder($class)
{
$class_map_builder = $class.'MapBuilder';
if (!isset($this->maps[$class]))
{
if (!$classPath = sfCore::getClassPath($class_map_builder))
{
throw new sfException(sprintf('Unable to find path for class "%s".', $class_map_builder));
}
require_once($classPath);
$this->maps[$class] = new $class_map_builder();
$this->maps[$class]->doBuild();
}
}
/**
* dumpData
*
* @param mixed $directory_or_file
* @param string $tables
* @param string $connectionName
* @access public
* @return void
*/
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
}
$manager = Doctrine_Manager::getInstance();
$con = $manager->getCurrentConnection();
// get tables
if ('all' === $tables || null === $tables)
{
$modelDirectories = array();
$modelDirectories[] = sfConfig::get('sf_model_lib_dir').'/doctrine';
$directories = sfFinder::type('dir')->maxdepth(0)->in(sfConfig::get('sf_model_lib_dir').'/doctrine');
foreach($directories AS $directory)
{
if( strstr($directory, 'generated') )
{
continue;
}
$modelDirectories[] = $directory;
}
$tables = array();
foreach($modelDirectories AS $directory)
{
$dirTables = sfFinder::type('file')->name('/(?<!Table)\.class.php$/')->maxdepth(0)->in($directory);
foreach ($dirTables AS $key => $table)
{
$table = basename($table, '.class.php');
$tables[] = $table;
}
}
}
else if (!is_array($tables))
{
$tables = array($tables);
}
$dumpData = array();
foreach ($tables as $modelName)
{
$table = sfDoctrine::getTable($modelName, $this->connectionName);
// get table name
$tableName = $table->getTableName();
$relations = $table->getRelations();
// get columns
$columns = $con->fetchAll('DESCRIBE '.$tableName);
// get records
//$records = $con->fetchAll('SELECT * FROM '.$tableName);
$query = new Doctrine_Query();
$query->from($modelName);
$records = $query->execute();
$dumpData[$modelName] = array();
foreach($records AS $record)
{
$pk = $modelName;
$values = array();
foreach($columns AS $column)
{
$col = strtolower($column['Field']);
try {
$initialValue = $record[$col];
} catch(Exception $e) {
continue;
}
if( !$initialValue )
{
continue;
}
if ($column['Key'] == 'PRI')
{
$pk .= '_'.$initialValue;
}
else
{
$isForeignKey = false;
foreach($relations AS $relation)
{
if( $relation->getLocal() == $col )
{
$isForeignKey = true;
break;
}
}
if( $isForeignKey )
{
$array = $relation->toArray();
$values[$relation->getAlias()] = $array['class'].'_'.$initialValue;
} else {
$value = $initialValue;
// Needed to maintain bool values
if( is_bool($value) )
{
$value = $value ? 1:0;
}
$values[$col] = $value;
}
}
}
$dumpData[$modelName][$pk] = $values;
}
}
// save to file(s)
if ($sameFile)
{
$yaml = Spyc::YAMLDump($dumpData);
file_put_contents($directory_or_file, $yaml);
}
else
{
foreach ($dumpData as $table => $data)
{
$yaml = Spyc::YAMLDump($data);
file_put_contents($directory_or_file."/$table.yml", $yaml);
}
}
}
}