[ Index ]
 

Code source de Symfony 1.0.0

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/lib/addon/propel/ -> sfPropelData.class.php (source)

   1  <?php
   2  
   3  /*
   4   * This file is part of the symfony package.
   5   * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
   6   *
   7   * For the full copyright and license information, please view the LICENSE
   8   * file that was distributed with this source code.
   9   */
  10  
  11  /**
  12   * This class is the Propel implementation of sfData.  It interacts with the data source
  13   * and loads data.
  14   *
  15   * @package    symfony
  16   * @subpackage addon
  17   * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
  18   * @version    SVN: $Id: sfPropelData.class.php 3386 2007-02-01 09:53:58Z fabien $
  19   */
  20  class sfPropelData extends sfData
  21  {
  22    protected
  23      $maps = array();
  24  
  25    // symfony load-data (file|dir)
  26    /**
  27     * Loads data from a file or directory into a Propel data source
  28     *
  29     * @param mixed A file or directory path
  30     * @param string The Propel connection name, default 'propel'
  31     *
  32     * @throws Exception If the database throws an error, rollback transaction and rethrows exception
  33     */
  34    public function loadData($directory_or_file = null, $connectionName = 'propel')
  35    {
  36      $fixture_files = $this->getFiles($directory_or_file);
  37  
  38      // wrap all database operations in a single transaction
  39      $con = Propel::getConnection($connectionName);
  40      try
  41      {
  42        $con->begin();
  43  
  44        $this->doDeleteCurrentData($fixture_files);
  45  
  46        $this->doLoadData($fixture_files);
  47  
  48        $con->commit();
  49      }
  50      catch (Exception $e)
  51      {
  52        $con->rollback();
  53        throw $e;
  54      }
  55    }
  56  
  57    /**
  58     * Implements the abstract loadDataFromArray method and loads the data using the generated data model.
  59     *
  60     * @param array The data to be loaded into the data source
  61     *
  62     * @throws Exception If data is unnamed.
  63     * @throws sfException If an object defined in the model does not exist in the data
  64     * @throws sfException If a column that does not exist is referenced
  65     */
  66    public function loadDataFromArray($data)
  67    {
  68      if ($data === null)
  69      {
  70        // no data
  71        return;
  72      }
  73  
  74      foreach ($data as $class => $datas)
  75      {
  76        $class = trim($class);
  77  
  78        $peer_class = $class.'Peer';
  79  
  80        // load map class
  81        $this->loadMapBuilder($class);
  82  
  83        $tableMap = $this->maps[$class]->getDatabaseMap()->getTable(constant($peer_class.'::TABLE_NAME'));
  84  
  85        $column_names = call_user_func_array(array($peer_class, 'getFieldNames'), array(BasePeer::TYPE_FIELDNAME));
  86  
  87        // iterate through datas for this class
  88        // might have been empty just for force a table to be emptied on import
  89        if (!is_array($datas))
  90        {
  91          return;
  92        }
  93  
  94        foreach ($datas as $key => $data)
  95        {
  96          // create a new entry in the database
  97          $obj = new $class();
  98  
  99          if (!is_array($data))
 100          {
 101            throw new Exception('You must give a name for each fixture data entry');
 102          }
 103  
 104          foreach ($data as $name => $value)
 105          {
 106            // foreign key?
 107            try
 108            {
 109              $column = $tableMap->getColumn($name);
 110              if ($column->isForeignKey() && !is_null($value))
 111              {
 112                $relatedTable = $this->maps[$class]->getDatabaseMap()->getTable($column->getRelatedTableName());
 113                if (!isset($this->object_references[$relatedTable->getPhpName().'_'.$value]))
 114                {
 115                  $error = 'The object "%s" from class "%s" is not defined in your data file.';
 116                  $error = sprintf($error, $value, $relatedTable->getPhpName());
 117                  throw new sfException($error);
 118                }
 119                $value = $this->object_references[$relatedTable->getPhpName().'_'.$value];
 120              }
 121            }
 122            catch (PropelException $e)
 123            {
 124            }
 125  
 126            $pos = array_search($name, $column_names);
 127            $method = 'set'.sfInflector::camelize($name);
 128            if ($pos)
 129            {
 130              $obj->setByPosition($pos, $value);
 131            }
 132            else if (is_callable(array($obj, $method)))
 133            {
 134              $obj->$method($value);
 135            }
 136            else
 137            {
 138              $error = 'Column "%s" does not exist for class "%s"';
 139              $error = sprintf($error, $name, $class);
 140              throw new sfException($error);
 141            }
 142          }
 143          $obj->save();
 144  
 145          // save the id for future reference
 146          if (method_exists($obj, 'getPrimaryKey'))
 147          {
 148            $this->object_references[$class.'_'.$key] = $obj->getPrimaryKey();
 149          }
 150        }
 151      }
 152    }
 153  
 154    /**
 155     * Clears existing data from the data source by reading the fixture files
 156     * and deleting the existing data for only those classes that are mentioned
 157     * in the fixtures.
 158     *
 159     * @param array The list of YAML files.
 160     *
 161     * @throws sfException If a class mentioned in a fixture can not be found
 162     */
 163    protected function doDeleteCurrentData($fixture_files)
 164    {
 165      // delete all current datas in database
 166      if (!$this->deleteCurrentData)
 167      {
 168        return;
 169      }
 170  
 171      rsort($fixture_files);
 172      foreach ($fixture_files as $fixture_file)
 173      {
 174        $data = sfYaml::load($fixture_file);
 175  
 176        if ($data === null)
 177        {
 178          // no data
 179          continue;
 180        }
 181  
 182        $classes = array_keys($data);
 183        krsort($classes);
 184        foreach ($classes as $class)
 185        {
 186          $peer_class = trim($class.'Peer');
 187  
 188          if (!$classPath = sfCore::getClassPath($peer_class))
 189          {
 190            throw new sfException(sprintf('Unable to find path for class "%s".', $peer_class));
 191          }
 192  
 193          require_once($classPath);
 194  
 195          call_user_func(array($peer_class, 'doDeleteAll'));
 196        }
 197      }
 198    }
 199  
 200    /**
 201     * Loads the mappings for the classes
 202     *
 203     * @param string The name of a data object
 204     *
 205     * @throws sfException If the class cannot be found
 206     */
 207    protected function loadMapBuilder($class)
 208    {
 209      $class_map_builder = $class.'MapBuilder';
 210      if (!isset($this->maps[$class]))
 211      {
 212        if (!$classPath = sfCore::getClassPath($class_map_builder))
 213        {
 214          throw new sfException(sprintf('Unable to find path for class "%s".', $class_map_builder));
 215        }
 216  
 217        require_once($classPath);
 218        $this->maps[$class] = new $class_map_builder();
 219        $this->maps[$class]->doBuild();
 220      }
 221    }
 222  
 223    /**
 224     * Dumps data to fixture from 1 or more tables.
 225     *
 226     * @param string directory or file to dump to
 227     * @param mixed name or names of tables to dump
 228     * @param string connection name
 229     */
 230    public function dumpData($directory_or_file = null, $tables = 'all', $connectionName = 'propel')
 231    {
 232      $sameFile = true;
 233      if (is_dir($directory_or_file))
 234      {
 235        // multi files
 236        $sameFile = false;
 237      }
 238      else
 239      {
 240        // same file
 241        // delete file
 242      }
 243  
 244      $con = Propel::getConnection($connectionName);
 245  
 246      // get tables
 247      if ('all' === $tables || null === $tables)
 248      {
 249        $tables = sfFinder::type('file')->name('/(?<!Peer)\.php$/')->maxdepth(0)->in(sfConfig::get('sf_model_lib_dir'));
 250        foreach ($tables as &$table)
 251        {
 252          $table = basename($table, '.php');
 253        }
 254      }
 255      else if (!is_array($tables))
 256      {
 257        $tables = array($tables);
 258      }
 259  
 260      $dumpData = array();
 261  
 262      // load map classes
 263      array_walk($tables, array($this, 'loadMapBuilder'));
 264  
 265      // reordering tables to take foreign keys into account
 266      $move = true;
 267      while ($move)
 268      {
 269        foreach ($tables as $i => $tableName)
 270        {
 271          $tableMap = $this->maps[$tableName]->getDatabaseMap()->getTable(constant($tableName.'Peer::TABLE_NAME'));
 272  
 273          foreach ($tableMap->getColumns() as $column)
 274          {
 275            if ($column->isForeignKey())
 276            {
 277              $relatedTable = $this->maps[$tableName]->getDatabaseMap()->getTable($column->getRelatedTableName());
 278              if (array_search($relatedTable->getPhpName(), $tables) > $i)
 279              {
 280                unset($tables[$i]);
 281                $tables[] = $tableName;
 282                $move = true;
 283                continue 2;
 284              }
 285            }
 286          }
 287  
 288          $move = false;
 289        }
 290      }
 291  
 292      foreach ($tables as $tableName)
 293      {
 294        $tableMap = $this->maps[$tableName]->getDatabaseMap()->getTable(constant($tableName.'Peer::TABLE_NAME'));
 295  
 296        // get db info
 297        $rs = $con->executeQuery('SELECT * FROM '.constant($tableName.'Peer::TABLE_NAME'));
 298  
 299        $dumpData[$tableName] = array();
 300  
 301        while ($rs->next())
 302        {
 303          $pk = $tableName;
 304          $values = array();
 305          foreach ($tableMap->getColumns() as $column)
 306          {
 307            $col = strtolower($column->getColumnName());
 308            if ($column->isPrimaryKey())
 309            {
 310              $pk .= '_'.$rs->get($col);
 311            }
 312            else if ($column->isForeignKey())
 313            {
 314              $relatedTable = $this->maps[$tableName]->getDatabaseMap()->getTable($column->getRelatedTableName());
 315  
 316              $values[$col] = $relatedTable->getPhpName().'_'.$rs->get($col);
 317            }
 318            else
 319            {
 320              $values[$col] = $rs->get($col);
 321            }
 322          }
 323  
 324          $dumpData[$tableName][$pk] = $values;
 325        }
 326      }
 327  
 328      // save to file(s)
 329      if ($sameFile)
 330      {
 331        $yaml = Spyc::YAMLDump($dumpData);
 332        file_put_contents($directory_or_file, $yaml);
 333      }
 334      else
 335      {
 336        foreach ($dumpData as $table => $data)
 337        {
 338          $yaml = Spyc::YAMLDump($data);
 339          file_put_contents($directory_or_file."/$table.yml", $yaml);
 340        }
 341      }
 342    }
 343  }


Généré le : Fri Mar 16 22:42:14 2007 par Balluche grâce à PHPXref 0.7