* * 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 * @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('/(?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); } } } }