[ Index ] |
|
Code source de Symfony 1.0.0 |
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 }
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Fri Mar 16 22:42:14 2007 | par Balluche grâce à PHPXref 0.7 |