Files
grzanieplus.pl/plugins/stInstallerPlugin/lib/stPropelDataLoader.php
2025-03-12 17:06:23 +01:00

325 lines
8.2 KiB
PHP

<?php
/**
* This class 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 662 2009-09-21 12:14:20Z marcin $
*/
class stPropelDataLoader
{
protected $data = array();
protected $fixtureMap = array();
protected $moduleIndex = array();
protected $maps = array();
protected $processed = array();
protected $deletedClasses = array();
protected $objectReferences = array();
public function loadData($fixture_dir_or_file, $delay = 0)
{
$fixture_files = $this->getFixtureFiles($fixture_dir_or_file);
foreach ($fixture_files as $fixture_file)
{
$this->doLoadData($fixture_file, $delay);
}
return $fixture_files;
}
protected function doLoadData($fixture_file, $delay = 0)
{
if (!isset($this->processed[$fixture_file]))
{
$this->doDeleteCurrentData($fixture_file);
$data = $this->loadFixtureFromFile($fixture_file);
$this->processed[$fixture_file] = true;
$this->loadDataFromArray($data, $delay);
}
}
public function loadDataFromArray($data, $delay = 0)
{
if ($data === null)
{
return;
}
foreach ($data as $class => $datas)
{
$class = trim($class);
$peer_class = $class.'Peer';
$this->loadMapBuilder($class);
$tableMap = $this->maps[$class]->getDatabaseMap()->getTable(constant($peer_class.'::TABLE_NAME'));
$column_names = array_flip(call_user_func_array(array($peer_class, 'getFieldNames'), array(BasePeer::TYPE_FIELDNAME)));
if (!is_array($datas))
{
continue;
}
if (!is_subclass_of($class, 'BaseObject'))
{
throw new Exception(sprintf('The class "%s" is not a Propel class. This probably means there is already a class named "%s" somewhere in symfony or in your project.', $class, $class));
}
foreach ($datas as $key => $data)
{
$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)
{
$isARealColumn = true;
try
{
$column = $tableMap->getColumn($name);
}
catch (PropelException $e)
{
$isARealColumn = false;
}
// foreign key?
if ($isARealColumn)
{
if ($column->isForeignKey() && !is_null($value))
{
list($relatedObjectName) = explode("_", $value);
if (!isset($this->objectReferences[$value]))
{
if (!$this->loadFixturesFromClassName($relatedObjectName))
{
throw new sfException(sprintf('Failed when trying to locate the object "%s" from class "%2$s" or "%2$s.yml" fixture file', $value, $relatedObjectName));
}
if (!isset($this->objectReferences[$value]))
{
if (in_array($value, array('Countries_39', 'Currency_5', 'Countries_6')))
{
continue 2;
}
throw new sfException(sprintf('The object "%s" from class "%s" is not defined in your data file.', $value, $relatedObjectName));
}
}
$value = $this->objectReferences[$value];
}
}
if (isset($column_names[$name]))
{
$obj->setByPosition($column_names[$name], $value);
}
else if (is_callable(array($obj, $method = 'set'.sfInflector::camelize($name))))
{
$obj->$method($value);
}
else
{
$error = 'Column "%s" does not exist for class "%s"';
$error = sprintf($error, $name, $class);
throw new sfException($error);
}
}
$obj->save();
if (method_exists($obj, 'getPrimaryKey'))
{
$this->objectReferences[$key] = $obj->getPrimaryKey();
}
$this->delay($delay);
}
}
}
protected function doDeleteCurrentData($fixture_file)
{
$data = $this->loadFixtureFromFile($fixture_file);
if ($data === null)
{
return;
}
$classes = array_keys($data);
krsort($classes);
foreach ($classes as $class)
{
$class = trim($class);
if (isset($this->deletedClasses[$class]))
{
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->deletedClasses[$class] = true;
}
}
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();
}
}
public function indexFixturesFiles($fixtures_dirs = array(), $delay = 0)
{
foreach ($fixtures_dirs as $dir)
{
$files = $this->getFiles($dir);
sort($files);
$this->fixtureMap[$dir] = $files;
foreach ($files as $file)
{
$this->indexFixtureFile($file);
}
$this->delay($delay);
}
}
protected function delay($ms = 0)
{
if ($ms)
{
usleep($ms * 1000);
}
}
protected function indexFixtureFile($file)
{
$data = sfYaml::load($file);
$model_classes = array_keys($data);
foreach ($model_classes as $model_class)
{
if (!isset($this->modelIndex[$model_class]))
{
$this->modelIndex[$model_class] = array();
}
$this->modelIndex[$model_class][] = $file;
}
$this->data[$file] = $data;
unset($data);
}
protected function loadFixtureFromFile($fixture_file)
{
if (!isset($this->data[$fixture_file]))
{
$this->indexFixtureFile($fixture_file);
}
return $this->data[$fixture_file];
}
protected function loadFixturesFromClassName($classname)
{
if (isset($this->modelIndex[$classname]))
{
foreach ($this->modelIndex[$classname] as $file)
{
$this->doLoadData($file);
}
}
else
{
return false;
}
return true;
}
protected function getFixtureFiles($dir_or_file)
{
if (isset($this->fixtureMap[$dir_or_file]))
{
return $this->fixtureMap[$dir_or_file];
}
return array($dir_or_file);
}
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')->ignore_version_control()->maxdepth(0)->name('*.yml')->in($directory_or_file);
}
else
{
throw new sfInitializationException('You must give a directory or a file.');
}
return $fixture_files;
}
}