PageRenderTime 30ms CodeModel.GetById 0ms RepoModel.GetById 1ms app.codeStats 0ms

/generator/lib/model/Database.php

https://github.com/1989gaurav/Propel
PHP | 656 lines | 357 code | 68 blank | 231 comment | 32 complexity | 099e616b54a754950286a51dde8f7ddd MD5 | raw file
  1. <?php
  2. /**
  3. * This file is part of the Propel package.
  4. * For the full copyright and license information, please view the LICENSE
  5. * file that was distributed with this source code.
  6. *
  7. * @license MIT License
  8. */
  9. require_once dirname(__FILE__) . '/ScopedElement.php';
  10. require_once dirname(__FILE__) . '/IDMethod.php';
  11. require_once dirname(__FILE__) . '/NameGenerator.php';
  12. require_once dirname(__FILE__) . '/Table.php';
  13. require_once dirname(__FILE__) . '/Behavior.php';
  14. /**
  15. * A class for holding application data structures.
  16. *
  17. * @author Hans Lellelid <hans@xmpl.org> (Propel)
  18. * @author Leon Messerschmidt <leon@opticode.co.za> (Torque)
  19. * @author John McNally<jmcnally@collab.net> (Torque)
  20. * @author Martin Poeschl<mpoeschl@marmot.at> (Torque)
  21. * @author Daniel Rall<dlr@collab.net> (Torque)
  22. * @author Byron Foster <byron_foster@yahoo.com> (Torque)
  23. * @version $Revision$
  24. * @package propel.generator.model
  25. */
  26. class Database extends ScopedElement
  27. {
  28. private $platform;
  29. private $tableList = array();
  30. private $curColumn;
  31. private $name;
  32. private $baseClass;
  33. private $basePeer;
  34. private $defaultIdMethod;
  35. private $defaultPhpNamingMethod;
  36. private $defaultTranslateMethod;
  37. private $dbParent;
  38. private $tablesByName = array();
  39. private $tablesByLowercaseName = array();
  40. private $tablesByPhpName = array();
  41. private $heavyIndexing;
  42. protected $tablePrefix = '';
  43. /**
  44. * The default string format for objects based on this database
  45. * (e.g. 'XML', 'YAML', 'CSV', 'JSON')
  46. *
  47. * @var string
  48. */
  49. protected $defaultStringFormat;
  50. private $domainMap = array();
  51. /**
  52. * List of behaviors registered for this table
  53. *
  54. * @var array
  55. */
  56. protected $behaviors = array();
  57. /**
  58. * Constructs a new Database object.
  59. *
  60. * @param string $name
  61. */
  62. public function __construct($name = null)
  63. {
  64. $this->name = $name;
  65. }
  66. /**
  67. * Sets up the Database object based on the attributes that were passed to loadFromXML().
  68. * @see parent::loadFromXML()
  69. */
  70. protected function setupObject()
  71. {
  72. parent::setupObject();
  73. $this->name = $this->getAttribute("name");
  74. $this->baseClass = $this->getAttribute("baseClass");
  75. $this->basePeer = $this->getAttribute("basePeer");
  76. $this->defaultIdMethod = $this->getAttribute("defaultIdMethod", IDMethod::NATIVE);
  77. $this->defaultPhpNamingMethod = $this->getAttribute("defaultPhpNamingMethod", NameGenerator::CONV_METHOD_UNDERSCORE);
  78. $this->defaultTranslateMethod = $this->getAttribute("defaultTranslateMethod", Validator::TRANSLATE_NONE);
  79. $this->heavyIndexing = $this->booleanValue($this->getAttribute("heavyIndexing"));
  80. $this->tablePrefix = $this->getAttribute('tablePrefix', $this->getBuildProperty('tablePrefix'));
  81. $this->defaultStringFormat = $this->getAttribute('defaultStringFormat', 'YAML');
  82. }
  83. /**
  84. * Returns the PropelPlatformInterface implementation for this database.
  85. *
  86. * @return PropelPlatformInterface a Platform implementation
  87. */
  88. public function getPlatform()
  89. {
  90. return $this->platform;
  91. }
  92. /**
  93. * Sets the PropelPlatformInterface implementation for this database.
  94. *
  95. * @param PropelPlatformInterface $platform A Platform implementation
  96. */
  97. public function setPlatform($platform)
  98. {
  99. $this->platform = $platform;
  100. }
  101. /**
  102. * Get the name of the Database
  103. */
  104. public function getName()
  105. {
  106. return $this->name;
  107. }
  108. /**
  109. * Set the name of the Database
  110. */
  111. public function setName($name)
  112. {
  113. $this->name = $name;
  114. }
  115. /**
  116. * Get the value of baseClass.
  117. * @return value of baseClass.
  118. */
  119. public function getBaseClass()
  120. {
  121. return $this->baseClass;
  122. }
  123. /**
  124. * Set the value of baseClass.
  125. * @param v Value to assign to baseClass.
  126. */
  127. public function setBaseClass($v)
  128. {
  129. $this->baseClass = $v;
  130. }
  131. /**
  132. * Get the value of basePeer.
  133. * @return value of basePeer.
  134. */
  135. public function getBasePeer()
  136. {
  137. return $this->basePeer;
  138. }
  139. /**
  140. * Set the value of basePeer.
  141. * @param v Value to assign to basePeer.
  142. */
  143. public function setBasePeer($v)
  144. {
  145. $this->basePeer = $v;
  146. }
  147. /**
  148. * Get the value of defaultIdMethod.
  149. * @return value of defaultIdMethod.
  150. */
  151. public function getDefaultIdMethod()
  152. {
  153. return $this->defaultIdMethod;
  154. }
  155. /**
  156. * Set the value of defaultIdMethod.
  157. * @param v Value to assign to defaultIdMethod.
  158. */
  159. public function setDefaultIdMethod($v)
  160. {
  161. $this->defaultIdMethod = $v;
  162. }
  163. /**
  164. * Get the value of defaultPHPNamingMethod which specifies the
  165. * method for converting schema names for table and column to PHP names.
  166. * @return string The default naming conversion used by this database.
  167. */
  168. public function getDefaultPhpNamingMethod()
  169. {
  170. return $this->defaultPhpNamingMethod;
  171. }
  172. /**
  173. * Set the value of defaultPHPNamingMethod.
  174. * @param string $v The default naming conversion for this database to use.
  175. */
  176. public function setDefaultPhpNamingMethod($v)
  177. {
  178. $this->defaultPhpNamingMethod = $v;
  179. }
  180. /**
  181. * Get the value of defaultTranslateMethod which specifies the
  182. * method for translate validator error messages.
  183. * @return string The default translate method.
  184. */
  185. public function getDefaultTranslateMethod()
  186. {
  187. return $this->defaultTranslateMethod;
  188. }
  189. /**
  190. * Set the default string format for ActiveRecord objects in this Db.
  191. *
  192. * @param string $defaultStringFormat Any of 'XML', 'YAML', 'JSON', or 'CSV'
  193. */
  194. public function setDefaultStringFormat($defaultStringFormat)
  195. {
  196. $this->defaultStringFormat = $defaultStringFormat;
  197. }
  198. /**
  199. * Get the default string format for ActiveRecord objects in this Db.
  200. *
  201. * @return string The default string format
  202. */
  203. public function getDefaultStringFormat()
  204. {
  205. return $this->defaultStringFormat;
  206. }
  207. /**
  208. * Set the value of defaultTranslateMethod.
  209. * @param string $v The default translate method to use.
  210. */
  211. public function setDefaultTranslateMethod($v)
  212. {
  213. $this->defaultTranslateMethod = $v;
  214. }
  215. /**
  216. * Get the value of heavyIndexing.
  217. *
  218. * This is a synonym for getHeavyIndexing().
  219. *
  220. * @return boolean Value of heavyIndexing.
  221. * @see getHeavyIndexing()
  222. */
  223. public function isHeavyIndexing()
  224. {
  225. return $this->getHeavyIndexing();
  226. }
  227. /**
  228. * Get the value of heavyIndexing.
  229. *
  230. * @return boolean Value of heavyIndexing.
  231. */
  232. public function getHeavyIndexing()
  233. {
  234. return $this->heavyIndexing;
  235. }
  236. /**
  237. * Set the value of heavyIndexing.
  238. * @param boolean $v Value to assign to heavyIndexing.
  239. */
  240. public function setHeavyIndexing($v)
  241. {
  242. $this->heavyIndexing = (boolean) $v;
  243. }
  244. /**
  245. * Return the list of all tables
  246. * @return array
  247. */
  248. public function getTables()
  249. {
  250. return $this->tableList;
  251. }
  252. /**
  253. * Return the number of tables in the database
  254. * @return integer
  255. */
  256. public function countTables()
  257. {
  258. $count = 0;
  259. foreach ($this->tableList as $table) {
  260. if (!$table->isReadOnly()) {
  261. $count++;
  262. }
  263. }
  264. return $count;
  265. }
  266. /**
  267. * Return the list of all tables that have a SQL representation
  268. * @return array
  269. */
  270. public function getTablesForSql()
  271. {
  272. $tables = array();
  273. foreach ($this->tableList as $table) {
  274. if (!$table->isSkipSql()) {
  275. $tables []= $table;
  276. }
  277. }
  278. return $tables;
  279. }
  280. /**
  281. * Check whether the database has a table.
  282. * @param string $name the name of the table (e.g. 'my_table')
  283. * @param boolean $caseInsensitive Whether the check is case insensitive. False by default.
  284. *
  285. * @return boolean
  286. */
  287. public function hasTable($name, $caseInsensitive = false)
  288. {
  289. if ($caseInsensitive) {
  290. return array_key_exists(strtolower($name), $this->tablesByLowercaseName);
  291. } else {
  292. return array_key_exists($name, $this->tablesByName);
  293. }
  294. }
  295. /**
  296. * Return the table with the specified name.
  297. * @param string $name The name of the table (e.g. 'my_table')
  298. * @param boolean $caseInsensitive Whether the check is case insensitive. False by default.
  299. *
  300. * @return Table a Table object or null if it doesn't exist
  301. */
  302. public function getTable($name, $caseInsensitive = false)
  303. {
  304. if ($this->hasTable($name, $caseInsensitive)) {
  305. if ($caseInsensitive) {
  306. return $this->tablesByLowercaseName[strtolower($name)];
  307. } else {
  308. return $this->tablesByName[$name];
  309. }
  310. }
  311. return null; // just to be explicit
  312. }
  313. /**
  314. * Check whether the database has a table.
  315. * @param string $phpName the PHP Name of the table (e.g. 'MyTable')
  316. * @return boolean
  317. */
  318. public function hasTableByPhpName($phpName)
  319. {
  320. return array_key_exists($phpName, $this->tablesByPhpName);
  321. }
  322. /**
  323. * Return the table with the specified phpName.
  324. * @param string $phpName the PHP Name of the table (e.g. 'MyTable')
  325. * @return Table a Table object or null if it doesn't exist
  326. */
  327. public function getTableByPhpName($phpName)
  328. {
  329. if (isset($this->tablesByPhpName[$phpName])) {
  330. return $this->tablesByPhpName[$phpName];
  331. }
  332. return null; // just to be explicit
  333. }
  334. /**
  335. * An utility method to add a new table from an xml attribute.
  336. */
  337. public function addTable($data)
  338. {
  339. if ($data instanceof Table) {
  340. $tbl = $data; // alias
  341. $tbl->setDatabase($this);
  342. if ($tbl->getSchema() === null) $tbl->setSchema($this->getSchema());
  343. if (isset($this->tablesByName[$tbl->getName()])) {
  344. throw new EngineException("Duplicate table declared: " . $tbl->getName());
  345. }
  346. $this->tableList[] = $tbl;
  347. $this->tablesByName[$tbl->getName()] = $tbl;
  348. $this->tablesByLowercaseName[strtolower($tbl->getName())] = $tbl;
  349. $this->tablesByPhpName[ $tbl->getPhpName() ] = $tbl;
  350. if (strpos($tbl->getNamespace(), '\\') === 0) {
  351. $tbl->setNamespace(substr($tbl->getNamespace(), 1));
  352. } elseif ($namespace = $this->getNamespace()) {
  353. if ($tbl->getNamespace() === null) {
  354. $tbl->setNamespace($namespace);
  355. } else {
  356. $tbl->setNamespace($namespace . '\\' . $tbl->getNamespace());
  357. }
  358. }
  359. if ($tbl->getPackage() === null) {
  360. $tbl->setPackage($this->getPackage());
  361. }
  362. return $tbl;
  363. } else {
  364. $tbl = new Table();
  365. $tbl->setDatabase($this);
  366. $tbl->setSchema($this->getSchema());
  367. $tbl->loadFromXML($data);
  368. return $this->addTable($tbl); // call self w/ different param
  369. }
  370. }
  371. /**
  372. * Set the parent of the database
  373. */
  374. public function setAppData(AppData $parent)
  375. {
  376. $this->dbParent = $parent;
  377. }
  378. /**
  379. * Get the parent of the table
  380. */
  381. public function getAppData()
  382. {
  383. return $this->dbParent;
  384. }
  385. /**
  386. * Adds Domain object from <domain> tag.
  387. * @param mixed XML attributes (array) or Domain object.
  388. */
  389. public function addDomain($data) {
  390. if ($data instanceof Domain) {
  391. $domain = $data; // alias
  392. $domain->setDatabase($this);
  393. $this->domainMap[ $domain->getName() ] = $domain;
  394. return $domain;
  395. } else {
  396. $domain = new Domain();
  397. $domain->setDatabase($this);
  398. $domain->loadFromXML($data);
  399. return $this->addDomain($domain); // call self w/ different param
  400. }
  401. }
  402. /**
  403. * Get already configured Domain object by name.
  404. * @return Domain
  405. */
  406. public function getDomain($domainName)
  407. {
  408. if (isset($this->domainMap[$domainName])) {
  409. return $this->domainMap[$domainName];
  410. }
  411. return null; // just to be explicit
  412. }
  413. public function getGeneratorConfig()
  414. {
  415. if ($this->getAppData()) {
  416. return $this->getAppData()->getGeneratorConfig();
  417. } else {
  418. return null;
  419. }
  420. }
  421. public function getBuildProperty($key)
  422. {
  423. if($config = $this->getGeneratorConfig()) {
  424. return $config->getBuildProperty($key);
  425. } else {
  426. return '';
  427. }
  428. }
  429. /**
  430. * Adds a new Behavior to the database
  431. * @return Behavior A behavior instance
  432. */
  433. public function addBehavior($bdata)
  434. {
  435. if ($bdata instanceof Behavior) {
  436. $behavior = $bdata;
  437. $behavior->setDatabase($this);
  438. $this->behaviors[$behavior->getName()] = $behavior;
  439. return $behavior;
  440. } else {
  441. $class = $this->getConfiguredBehavior($bdata['name']);
  442. $behavior = new $class();
  443. $behavior->loadFromXML($bdata);
  444. return $this->addBehavior($behavior);
  445. }
  446. }
  447. /**
  448. * Get the database behaviors
  449. * @return Array of Behavior objects
  450. */
  451. public function getBehaviors()
  452. {
  453. return $this->behaviors;
  454. }
  455. /**
  456. * check if the database has a behavior by name
  457. *
  458. * @param string $name the behavior name
  459. * @return boolean True if the behavior exists
  460. */
  461. public function hasBehavior($name)
  462. {
  463. return array_key_exists($name, $this->behaviors);
  464. }
  465. /**
  466. * Get one database behavior by name
  467. * @param string $name the behavior name
  468. * @return Behavior a behavior object
  469. */
  470. public function getBehavior($name)
  471. {
  472. return $this->behaviors[$name];
  473. }
  474. /**
  475. * Get the table prefix for this database
  476. *
  477. * @return string the table prefix
  478. */
  479. public function getTablePrefix()
  480. {
  481. return $this->tablePrefix;
  482. }
  483. /**
  484. * Get the next behavior on all tables, ordered by behavior priority,
  485. * and skipping the ones that were already executed,
  486. *
  487. * @return Behavior
  488. */
  489. public function getNextTableBehavior()
  490. {
  491. // order the behaviors according to Behavior::$tableModificationOrder
  492. $behaviors = array();
  493. foreach ($this->getTables() as $table) {
  494. foreach ($table->getBehaviors() as $behavior) {
  495. if (!$behavior->isTableModified()) {
  496. $behaviors[$behavior->getTableModificationOrder()][] = $behavior;
  497. }
  498. }
  499. }
  500. ksort($behaviors);
  501. foreach ($behaviors as $behaviorList) {
  502. foreach ($behaviorList as $behavior) {
  503. return $behavior;
  504. }
  505. }
  506. }
  507. public function doFinalInitialization()
  508. {
  509. // add the referrers for the foreign keys
  510. $this->setupTableReferrers();
  511. // add default behaviors to database
  512. if($defaultBehaviors = $this->getBuildProperty('behaviorDefault')) {
  513. // add generic behaviors from build.properties
  514. $defaultBehaviors = explode(',', $defaultBehaviors);
  515. foreach ($defaultBehaviors as $behavior) {
  516. $this->addBehavior(array('name' => trim($behavior)));
  517. }
  518. }
  519. // execute database behaviors
  520. foreach ($this->getBehaviors() as $behavior) {
  521. $behavior->modifyDatabase();
  522. }
  523. // execute table behaviors (may add new tables and new behaviors)
  524. while ($behavior = $this->getNextTableBehavior()) {
  525. $behavior->getTableModifier()->modifyTable();
  526. $behavior->setTableModified(true);
  527. }
  528. // do naming and heavy indexing
  529. foreach ($this->getTables() as $table) {
  530. $table->doFinalInitialization();
  531. // setup referrers again, since final initialization may have added columns
  532. $table->setupReferrers(true);
  533. }
  534. }
  535. /**
  536. * Can be called several times
  537. */
  538. protected function setupTableReferrers()
  539. {
  540. foreach ($this->getTables() as $table) {
  541. $table->doNaming();
  542. $table->setupReferrers();
  543. }
  544. }
  545. /**
  546. * @see XMLElement::appendXml(DOMNode)
  547. */
  548. public function appendXml(DOMNode $node)
  549. {
  550. $doc = ($node instanceof DOMDocument) ? $node : $node->ownerDocument;
  551. $dbNode = $node->appendChild($doc->createElement('database'));
  552. $dbNode->setAttribute('name', $this->name);
  553. if ($this->pkg) {
  554. $dbNode->setAttribute('package', $this->pkg);
  555. }
  556. if ($this->defaultIdMethod) {
  557. $dbNode->setAttribute('defaultIdMethod', $this->defaultIdMethod);
  558. }
  559. if ($this->baseClass) {
  560. $dbNode->setAttribute('baseClass', $this->baseClass);
  561. }
  562. if ($this->basePeer) {
  563. $dbNode->setAttribute('basePeer', $this->basePeer);
  564. }
  565. if ($this->defaultPhpNamingMethod) {
  566. $dbNode->setAttribute('defaultPhpNamingMethod', $this->defaultPhpNamingMethod);
  567. }
  568. if ($this->defaultTranslateMethod) {
  569. $dbNode->setAttribute('defaultTranslateMethod', $this->defaultTranslateMethod);
  570. }
  571. /*
  572. FIXME - Before we can add support for domains in the schema, we need
  573. to have a method of the Column that indicates whether the column was mapped
  574. to a SPECIFIC domain (since Column->getDomain() will always return a Domain object)
  575. foreach ($this->domainMap as $domain) {
  576. $domain->appendXml($dbNode);
  577. }
  578. */
  579. foreach ($this->vendorInfos as $vi) {
  580. $vi->appendXml($dbNode);
  581. }
  582. foreach ($this->tableList as $table) {
  583. $table->appendXml($dbNode);
  584. }
  585. }
  586. }