PageRenderTime 78ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/generator/lib/builder/om/PHP5ObjectBuilder.php

https://github.com/trendone/Propel
PHP | 5602 lines | 3412 code | 539 blank | 1651 comment | 403 complexity | 6079f4763fe8202bd7fb12b7504368e3 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__) . '/ObjectBuilder.php';
  10. /**
  11. * Generates a PHP5 base Object class for user object model (OM).
  12. *
  13. * This class produces the base object class (e.g. BaseMyTable) which contains all
  14. * the custom-built accessor and setter methods.
  15. *
  16. * @author Hans Lellelid <hans@xmpl.org>
  17. * @package propel.generator.builder.om
  18. */
  19. class PHP5ObjectBuilder extends ObjectBuilder
  20. {
  21. /**
  22. * Gets the package for the [base] object classes.
  23. * @return string
  24. */
  25. public function getPackage()
  26. {
  27. return parent::getPackage() . ".om";
  28. }
  29. public function getNamespace()
  30. {
  31. if ($namespace = parent::getNamespace()) {
  32. if ($this->getGeneratorConfig() && $omns = $this->getGeneratorConfig()->getBuildProperty('namespaceOm')) {
  33. return $namespace . '\\' . $omns;
  34. } else {
  35. return $namespace;
  36. }
  37. }
  38. }
  39. /**
  40. * Returns default key type. if not presented in configuration default will be 'TYPE_PHPNAME'
  41. * @return string
  42. */
  43. public function getDefaultKeyType()
  44. {
  45. $defaultKeyType = $this->getBuildProperty('defaultKeyType') ? $this->getBuildProperty('defaultKeyType') : 'phpName';
  46. return "TYPE_".strtoupper($defaultKeyType);
  47. }
  48. /**
  49. * Returns the name of the current class being built.
  50. * @return string
  51. */
  52. public function getUnprefixedClassname()
  53. {
  54. return $this->getBuildProperty('basePrefix') . $this->getStubObjectBuilder()->getUnprefixedClassname();
  55. }
  56. /**
  57. * Validates the current table to make sure that it won't
  58. * result in generated code that will not parse.
  59. *
  60. * This method may emit warnings for code which may cause problems
  61. * and will throw exceptions for errors that will definitely cause
  62. * problems.
  63. */
  64. protected function validateModel()
  65. {
  66. parent::validateModel();
  67. $table = $this->getTable();
  68. // Check to see whether any generated foreign key names
  69. // will conflict with column names.
  70. $colPhpNames = array();
  71. $fkPhpNames = array();
  72. foreach ($table->getColumns() as $col) {
  73. $colPhpNames[] = $col->getPhpName();
  74. }
  75. foreach ($table->getForeignKeys() as $fk) {
  76. $fkPhpNames[] = $this->getFKPhpNameAffix($fk, $plural = false);
  77. }
  78. $intersect = array_intersect($colPhpNames, $fkPhpNames);
  79. if (!empty($intersect)) {
  80. throw new EngineException("One or more of your column names for [" . $table->getName() . "] table conflict with foreign key names (" . implode(", ", $intersect) . ")");
  81. }
  82. // Check foreign keys to see if there are any foreign keys that
  83. // are also matched with an inversed referencing foreign key
  84. // (this is currently unsupported behavior)
  85. // see: http://propel.phpdb.org/trac/ticket/549
  86. foreach ($table->getForeignKeys() as $fk) {
  87. if ($fk->isMatchedByInverseFK()) {
  88. throw new EngineException("The 1:1 relationship expressed by foreign key " . $fk->getName() . " is defined in both directions; Propel does not currently support this (if you must have both foreign key constraints, consider adding this constraint with a custom SQL file.)" );
  89. }
  90. }
  91. }
  92. /**
  93. * Returns the appropriate formatter (from platform) for a date/time column.
  94. * @param Column $col
  95. * @return string
  96. */
  97. protected function getTemporalFormatter(Column $col)
  98. {
  99. $fmt = null;
  100. if ($col->getType() === PropelTypes::DATE) {
  101. $fmt = $this->getPlatform()->getDateFormatter();
  102. } elseif ($col->getType() === PropelTypes::TIME) {
  103. $fmt = $this->getPlatform()->getTimeFormatter();
  104. } elseif ($col->getType() === PropelTypes::TIMESTAMP) {
  105. $fmt = $this->getPlatform()->getTimestampFormatter();
  106. }
  107. return $fmt;
  108. }
  109. /**
  110. * Returns the type-casted and stringified default value for the specified Column.
  111. * This only works for scalar default values currently.
  112. * @return string The default value or 'null' if there is none.
  113. * @throws EngineException
  114. */
  115. protected function getDefaultValueString(Column $col)
  116. {
  117. $defaultValue = var_export(null, true);
  118. $val = $col->getPhpDefaultValue();
  119. if ($val === null) {
  120. return $defaultValue;
  121. }
  122. if ($col->isTemporalType()) {
  123. $fmt = $this->getTemporalFormatter($col);
  124. try {
  125. if (!($this->getPlatform() instanceof MysqlPlatform &&
  126. ($val === '0000-00-00 00:00:00' || $val === '0000-00-00'))) {
  127. // while technically this is not a default value of null,
  128. // this seems to be closest in meaning.
  129. $defDt = new DateTime($val);
  130. $defaultValue = var_export($defDt->format($fmt), true);
  131. }
  132. } catch (Exception $x) {
  133. // prevent endless loop when timezone is undefined
  134. date_default_timezone_set('America/Los_Angeles');
  135. throw new EngineException(sprintf('Unable to parse default temporal value "%s" for column "%s"', $col->getDefaultValueString(), $col->getFullyQualifiedName()), $x);
  136. }
  137. } elseif ($col->isEnumType()) {
  138. $valueSet = $col->getValueSet();
  139. if (!in_array($val, $valueSet)) {
  140. throw new EngineException(sprintf('Default Value "%s" is not among the enumerated values', $val));
  141. }
  142. $defaultValue = array_search($val, $valueSet);
  143. } elseif ($col->isPhpPrimitiveType()) {
  144. settype($val, $col->getPhpType());
  145. $defaultValue = var_export($val, true);
  146. } elseif ($col->isPhpObjectType()) {
  147. $defaultValue = 'new '.$col->getPhpType().'(' . var_export($val, true) . ')';
  148. } elseif ($col->isPhpArrayType()) {
  149. $defaultValue = var_export($val, true);
  150. } else {
  151. throw new EngineException("Cannot get default value string for " . $col->getFullyQualifiedName());
  152. }
  153. return $defaultValue;
  154. }
  155. /**
  156. * Adds the include() statements for files that this class depends on or utilizes.
  157. * @param string &$script The script will be modified in this method.
  158. */
  159. protected function addIncludes(&$script)
  160. {
  161. } // addIncludes()
  162. /**
  163. * Adds class phpdoc comment and openning of class.
  164. * @param string &$script The script will be modified in this method.
  165. */
  166. protected function addClassOpen(&$script)
  167. {
  168. $table = $this->getTable();
  169. $tableName = $table->getName();
  170. $tableDesc = $table->getDescription();
  171. $parentClass = $this->getBehaviorContent('parentClass');
  172. if (null === $parentClass) {
  173. $parentClass = ClassTools::classname($this->getBaseClass());
  174. if (false === strpos($this->getBaseClass(), '.')) {
  175. $this->declareClass($this->getBaseClass());
  176. } else {
  177. $this->declareClass($parentClass);
  178. }
  179. }
  180. if ($this->getBuildProperty('addClassLevelComment')) {
  181. $script .= "
  182. /**
  183. * Base class that represents a row from the '$tableName' table.
  184. *
  185. * $tableDesc
  186. *";
  187. if ($this->getBuildProperty('addTimeStamp')) {
  188. $now = strftime('%c');
  189. $script .= "
  190. * This class was autogenerated by Propel " . $this->getBuildProperty('version') . " on:
  191. *
  192. * $now
  193. *";
  194. }
  195. $script .= "
  196. * @package propel.generator.".$this->getPackage()."
  197. */";
  198. }
  199. $script .= "
  200. abstract class ".$this->getClassname()." extends ".$parentClass." ";
  201. if ($interface = $this->getTable()->getInterface()) {
  202. $script .= "implements " . ClassTools::classname($interface);
  203. if ($interface !== ClassTools::classname($interface)) {
  204. $this->declareClass($interface);
  205. } else {
  206. $this->declareClassFromBuilder($this->getInterfaceBuilder());
  207. }
  208. } elseif ($interface = ClassTools::getInterface($table)) {
  209. $script .= "implements " . ClassTools::classname($interface);
  210. }
  211. $script .= "
  212. {";
  213. }
  214. /**
  215. * Specifies the methods that are added as part of the basic OM class.
  216. * This can be overridden by subclasses that wish to add more methods.
  217. * @see ObjectBuilder::addClassBody()
  218. */
  219. protected function addClassBody(&$script)
  220. {
  221. $this->declareClassFromBuilder($this->getStubObjectBuilder());
  222. $this->declareClassFromBuilder($this->getStubPeerBuilder());
  223. $this->declareClassFromBuilder($this->getStubQueryBuilder());
  224. $this->declareClasses(
  225. 'Propel', 'PropelException', 'PDO', 'PropelPDO', 'PropelQuery', 'Criteria',
  226. 'Persistent', 'BasePeer', 'PropelCollection',
  227. 'PropelObjectCollection', 'Exception'
  228. );
  229. $table = $this->getTable();
  230. if (!$table->isAlias()) {
  231. $this->addConstants($script);
  232. $this->addAttributes($script);
  233. }
  234. if ($table->hasCrossForeignKeys()) {
  235. foreach ($table->getCrossFks() as $fkList) {
  236. list($refFK, $crossFK) = $fkList;
  237. $fkName = $this->getFKPhpNameAffix($crossFK, $plural = true);
  238. $this->addScheduledForDeletionAttribute($script, $fkName);
  239. }
  240. }
  241. foreach ($table->getReferrers() as $refFK) {
  242. $fkName = $this->getRefFKPhpNameAffix($refFK, $plural = true);
  243. $this->addScheduledForDeletionAttribute($script, $fkName);
  244. }
  245. if ($this->hasDefaultValues()) {
  246. $this->addApplyDefaultValues($script);
  247. $this->addConstructor($script);
  248. }
  249. $this->addColumnAccessorMethods($script);
  250. $this->addColumnMutatorMethods($script);
  251. $this->addHasOnlyDefaultValues($script);
  252. $this->addHydrate($script);
  253. $this->addEnsureConsistency($script);
  254. if (!$table->isReadOnly()) {
  255. $this->addManipulationMethods($script);
  256. }
  257. if ($this->isAddValidateMethod()) {
  258. $this->addValidationMethods($script);
  259. }
  260. if ($this->isAddGenericAccessors()) {
  261. $this->addGetByName($script);
  262. $this->addGetByPosition($script);
  263. $this->addToArray($script);
  264. }
  265. if ($this->isAddGenericMutators()) {
  266. $this->addSetByName($script);
  267. $this->addSetByPosition($script);
  268. $this->addFromArray($script);
  269. }
  270. $this->addBuildCriteria($script);
  271. $this->addBuildPkeyCriteria($script);
  272. $this->addGetPrimaryKey($script);
  273. $this->addSetPrimaryKey($script);
  274. $this->addIsPrimaryKeyNull($script);
  275. $this->addCopy($script);
  276. if (!$table->isAlias()) {
  277. $this->addGetPeer($script);
  278. }
  279. $this->addFKMethods($script);
  280. $this->addRefFKMethods($script);
  281. $this->addCrossFKMethods($script);
  282. $this->addClear($script);
  283. $this->addClearAllReferences($script);
  284. $this->addPrimaryString($script);
  285. $this->addIsAlreadyInSave($script);
  286. // apply behaviors
  287. $this->applyBehaviorModifier('objectMethods', $script, " ");
  288. $this->addMagicCall($script);
  289. }
  290. /**
  291. * Closes class.
  292. * @param string &$script The script will be modified in this method.
  293. */
  294. protected function addClassClose(&$script)
  295. {
  296. $script .= "
  297. }
  298. ";
  299. $this->applyBehaviorModifier('objectFilter', $script, "");
  300. }
  301. /**
  302. * Adds any constants to the class.
  303. * @param string &$script The script will be modified in this method.
  304. */
  305. protected function addConstants(&$script)
  306. {
  307. $script .= "
  308. /**
  309. * Peer class name
  310. */
  311. const PEER = '" . addslashes($this->getStubPeerBuilder()->getFullyQualifiedClassname()) . "';
  312. ";
  313. }
  314. /**
  315. * Adds class attributes.
  316. * @param string &$script The script will be modified in this method.
  317. */
  318. protected function addAttributes(&$script)
  319. {
  320. $table = $this->getTable();
  321. $script .= "
  322. /**
  323. * The Peer class.
  324. * Instance provides a convenient way of calling static methods on a class
  325. * that calling code may not be able to identify.
  326. * @var ".$this->getPeerClassname()."
  327. */
  328. protected static \$peer;
  329. /**
  330. * The flag var to prevent infinit loop in deep copy
  331. * @var boolean
  332. */
  333. protected \$startCopy = false;
  334. ";
  335. if (!$table->isAlias()) {
  336. $this->addColumnAttributes($script);
  337. }
  338. foreach ($table->getForeignKeys() as $fk) {
  339. $this->addFKAttributes($script, $fk);
  340. }
  341. foreach ($table->getReferrers() as $refFK) {
  342. $this->addRefFKAttributes($script, $refFK);
  343. }
  344. // many-to-many relationships
  345. foreach ($table->getCrossFks() as $fkList) {
  346. $crossFK = $fkList[1];
  347. $this->addCrossFKAttributes($script, $crossFK);
  348. }
  349. $this->addAlreadyInSaveAttribute($script);
  350. $this->addAlreadyInValidationAttribute($script);
  351. // apply behaviors
  352. $this->applyBehaviorModifier('objectAttributes', $script, " ");
  353. }
  354. /**
  355. * Adds variables that store column values.
  356. * @param string &$script The script will be modified in this method.
  357. * @see addColumnNameConstants()
  358. */
  359. protected function addColumnAttributes(&$script)
  360. {
  361. $table = $this->getTable();
  362. foreach ($table->getColumns() as $col) {
  363. $this->addColumnAttributeComment($script, $col);
  364. $this->addColumnAttributeDeclaration($script, $col);
  365. if ($col->isLazyLoad() ) {
  366. $this->addColumnAttributeLoaderComment($script, $col);
  367. $this->addColumnAttributeLoaderDeclaration($script, $col);
  368. }
  369. if ($col->getType() == PropelTypes::OBJECT || $col->getType() == PropelTypes::PHP_ARRAY) {
  370. $this->addColumnAttributeUnserializedComment($script, $col);
  371. $this->addColumnAttributeUnserializedDeclaration($script, $col);
  372. }
  373. }
  374. }
  375. /**
  376. * Add comment about the attribute (variable) that stores column values
  377. * @param string &$script The script will be modified in this method.
  378. * @param Column $col
  379. **/
  380. protected function addColumnAttributeComment(&$script, Column $col)
  381. {
  382. $cptype = $col->getPhpType();
  383. $clo = strtolower($col->getName());
  384. $script .= "
  385. /**
  386. * The value for the $clo field.";
  387. if ($col->getDefaultValue()) {
  388. if ($col->getDefaultValue()->isExpression()) {
  389. $script .= "
  390. * Note: this column has a database default value of: (expression) ".$col->getDefaultValue()->getValue();
  391. } else {
  392. $script .= "
  393. * Note: this column has a database default value of: ". $this->getDefaultValueString($col);
  394. }
  395. }
  396. $script .= "
  397. * @var $cptype
  398. */";
  399. }
  400. /**
  401. * Adds the declaration of a column value storage attribute
  402. * @param string &$script The script will be modified in this method.
  403. * @param Column $col
  404. **/
  405. protected function addColumnAttributeDeclaration(&$script, Column $col)
  406. {
  407. $clo = strtolower($col->getName());
  408. $script .= "
  409. protected \$" . $clo . ";
  410. ";
  411. }
  412. /**
  413. * Adds the comment about the attribute keeping track if an attribute value has been loaded
  414. * @param string &$script The script will be modified in this method.
  415. * @param Column $col
  416. **/
  417. protected function addColumnAttributeLoaderComment(&$script, Column $col)
  418. {
  419. $clo = strtolower($col->getName());
  420. $script .= "
  421. /**
  422. * Whether the lazy-loaded \$$clo value has been loaded from database.
  423. * This is necessary to avoid repeated lookups if \$$clo column is null in the db.
  424. * @var boolean
  425. */";
  426. }
  427. /**
  428. * Adds the declaration of the attribute keeping track of an attribute's loaded state
  429. * @param string &$script The script will be modified in this method.
  430. * @param Column $col
  431. **/
  432. protected function addColumnAttributeLoaderDeclaration(&$script, Column $col)
  433. {
  434. $clo = strtolower($col->getName());
  435. $script .= "
  436. protected \$".$clo."_isLoaded = false;
  437. ";
  438. }
  439. /**
  440. * Adds the comment about the serialized attribute
  441. * @param string &$script The script will be modified in this method.
  442. * @param Column $col
  443. **/
  444. protected function addColumnAttributeUnserializedComment(&$script, Column $col)
  445. {
  446. $clo = strtolower($col->getName());
  447. $script .= "
  448. /**
  449. * The unserialized \$$clo value - i.e. the persisted object.
  450. * This is necessary to avoid repeated calls to unserialize() at runtime.
  451. * @var object
  452. */";
  453. }
  454. /**
  455. * Adds the declaration of the serialized attribute
  456. * @param string &$script The script will be modified in this method.
  457. * @param Column $col
  458. **/
  459. protected function addColumnAttributeUnserializedDeclaration(&$script, Column $col)
  460. {
  461. $clo = strtolower($col->getName()) . "_unserialized";
  462. $script .= "
  463. protected \$" . $clo . ";
  464. ";
  465. }
  466. /**
  467. * Adds the getPeer() method.
  468. * This is a convenient, non introspective way of getting the Peer class for a particular object.
  469. * @param string &$script The script will be modified in this method.
  470. */
  471. protected function addGetPeer(&$script)
  472. {
  473. $this->addGetPeerComment($script);
  474. $this->addGetPeerFunctionOpen($script);
  475. $this->addGetPeerFunctionBody($script);
  476. $this->addGetPeerFunctionClose($script);
  477. }
  478. /**
  479. * Add the comment for the getPeer method
  480. * @param string &$script The script will be modified in this method.
  481. **/
  482. protected function addGetPeerComment(&$script)
  483. {
  484. $script .= "
  485. /**
  486. * Returns a peer instance associated with this om.
  487. *
  488. * Since Peer classes are not to have any instance attributes, this method returns the
  489. * same instance for all member of this class. The method could therefore
  490. * be static, but this would prevent one from overriding the behavior.
  491. *
  492. * @return ".$this->getPeerClassname()."
  493. */";
  494. }
  495. /**
  496. * Adds the function declaration (function opening) for the getPeer method
  497. * @param string &$script The script will be modified in this method.
  498. **/
  499. protected function addGetPeerFunctionOpen(&$script)
  500. {
  501. $script .= "
  502. public function getPeer()
  503. {";
  504. }
  505. /**
  506. * Adds the body of the getPeer method
  507. * @param string &$script The script will be modified in this method.
  508. **/
  509. protected function addGetPeerFunctionBody(&$script)
  510. {
  511. $script .= "
  512. if (self::\$peer === null) {
  513. " . $this->buildObjectInstanceCreationCode('self::$peer', $this->getPeerClassname()) . "
  514. }
  515. return self::\$peer;";
  516. }
  517. /**
  518. * Add the function close for the getPeer method
  519. * Note: this is just a } and the body ends with a return statement, so it's quite useless. But it's here anyway for consisency, cause there's a close function for all functions and in some other instances, they are useful
  520. * @param string &$script The script will be modified in this method.
  521. **/
  522. protected function addGetPeerFunctionClose(&$script)
  523. {
  524. $script .= "
  525. }
  526. ";
  527. }
  528. /**
  529. * Adds the constructor for this object.
  530. * @param string &$script The script will be modified in this method.
  531. * @see addConstructor()
  532. */
  533. protected function addConstructor(&$script)
  534. {
  535. $this->addConstructorComment($script);
  536. $this->addConstructorOpen($script);
  537. $this->addConstructorBody($script);
  538. $this->addConstructorClose($script);
  539. }
  540. /**
  541. * Adds the comment for the constructor
  542. * @param string &$script The script will be modified in this method.
  543. **/
  544. protected function addConstructorComment(&$script)
  545. {
  546. $script .= "
  547. /**
  548. * Initializes internal state of ".$this->getClassname()." object.
  549. * @see applyDefaults()
  550. */";
  551. }
  552. /**
  553. * Adds the function declaration for the constructor
  554. * @param string &$script The script will be modified in this method.
  555. **/
  556. protected function addConstructorOpen(&$script)
  557. {
  558. $script .= "
  559. public function __construct()
  560. {";
  561. }
  562. /**
  563. * Adds the function body for the constructor
  564. * @param string &$script The script will be modified in this method.
  565. **/
  566. protected function addConstructorBody(&$script)
  567. {
  568. $script .= "
  569. parent::__construct();
  570. \$this->applyDefaultValues();";
  571. }
  572. /**
  573. * Adds the function close for the constructor
  574. * @param string &$script The script will be modified in this method.
  575. **/
  576. protected function addConstructorClose(&$script)
  577. {
  578. $script .= "
  579. }
  580. ";
  581. }
  582. /**
  583. * Adds the applyDefaults() method, which is called from the constructor.
  584. * @param string &$script The script will be modified in this method.
  585. * @see addConstructor()
  586. */
  587. protected function addApplyDefaultValues(&$script)
  588. {
  589. $this->addApplyDefaultValuesComment($script);
  590. $this->addApplyDefaultValuesOpen($script);
  591. $this->addApplyDefaultValuesBody($script);
  592. $this->addApplyDefaultValuesClose($script);
  593. }
  594. /**
  595. * Adds the comment for the applyDefaults method
  596. * @param string &$script The script will be modified in this method.
  597. * @see addApplyDefaultValues()
  598. **/
  599. protected function addApplyDefaultValuesComment(&$script)
  600. {
  601. $script .= "
  602. /**
  603. * Applies default values to this object.
  604. * This method should be called from the object's constructor (or
  605. * equivalent initialization method).
  606. * @see __construct()
  607. */";
  608. }
  609. /**
  610. * Adds the function declaration for the applyDefaults method
  611. * @param string &$script The script will be modified in this method.
  612. * @see addApplyDefaultValues()
  613. **/
  614. protected function addApplyDefaultValuesOpen(&$script)
  615. {
  616. $script .= "
  617. public function applyDefaultValues()
  618. {";
  619. }
  620. /**
  621. * Adds the function body of the applyDefault method
  622. * @param string &$script The script will be modified in this method.
  623. * @see addApplyDefaultValues()
  624. **/
  625. protected function addApplyDefaultValuesBody(&$script)
  626. {
  627. $table = $this->getTable();
  628. // FIXME - Apply support for PHP default expressions here
  629. // see: http://propel.phpdb.org/trac/ticket/378
  630. $colsWithDefaults = array();
  631. foreach ($table->getColumns() as $col) {
  632. $def = $col->getDefaultValue();
  633. if ($def !== null && !$def->isExpression()) {
  634. $colsWithDefaults[] = $col;
  635. }
  636. }
  637. $colconsts = array();
  638. foreach ($colsWithDefaults as $col) {
  639. $clo = strtolower($col->getName());
  640. $defaultValue = $this->getDefaultValueString($col);
  641. $script .= "
  642. \$this->".$clo." = $defaultValue;";
  643. }
  644. }
  645. /**
  646. * Adds the function close for the applyDefaults method
  647. * @param string &$script The script will be modified in this method.
  648. * @see addApplyDefaultValues()
  649. **/
  650. protected function addApplyDefaultValuesClose(&$script)
  651. {
  652. $script .= "
  653. }
  654. ";
  655. }
  656. // --------------------------------------------------------------
  657. //
  658. // A C C E S S O R M E T H O D S
  659. //
  660. // --------------------------------------------------------------
  661. /**
  662. * Adds a date/time/timestamp getter method.
  663. * @param string &$script The script will be modified in this method.
  664. * @param Column $col The current column.
  665. * @see parent::addColumnAccessors()
  666. */
  667. protected function addTemporalAccessor(&$script, Column $col)
  668. {
  669. $this->addTemporalAccessorComment($script, $col);
  670. $this->addTemporalAccessorOpen($script, $col);
  671. $this->addTemporalAccessorBody($script, $col);
  672. $this->addTemporalAccessorClose($script, $col);
  673. } // addTemporalAccessor
  674. /**
  675. * Adds the comment for a temporal accessor
  676. * @param string &$script The script will be modified in this method.
  677. * @param Column $col The current column.
  678. * @see addTemporalAccessor
  679. **/
  680. public function addTemporalAccessorComment(&$script, Column $col)
  681. {
  682. $clo = strtolower($col->getName());
  683. $useDateTime = $this->getBuildProperty('useDateTimeClass');
  684. $dateTimeClass = $this->getBuildProperty('dateTimeClass');
  685. if (!$dateTimeClass) {
  686. $dateTimeClass = 'DateTime';
  687. }
  688. $handleMysqlDate = false;
  689. if ($this->getPlatform() instanceof MysqlPlatform) {
  690. if ($col->getType() === PropelTypes::TIMESTAMP) {
  691. $handleMysqlDate = true;
  692. $mysqlInvalidDateString = '0000-00-00 00:00:00';
  693. } elseif ($col->getType() === PropelTypes::DATE) {
  694. $handleMysqlDate = true;
  695. $mysqlInvalidDateString = '0000-00-00';
  696. }
  697. // 00:00:00 is a valid time, so no need to check for that.
  698. }
  699. $script .= "
  700. /**
  701. * Get the [optionally formatted] temporal [$clo] column value.
  702. * ".$col->getDescription();
  703. if (!$useDateTime) {
  704. $script .= "
  705. * This accessor only only work with unix epoch dates. Consider enabling the propel.useDateTimeClass
  706. * option in order to avoid converstions to integers (which are limited in the dates they can express).";
  707. }
  708. $script .= "
  709. *
  710. * @param string \$format The date/time format string (either date()-style or strftime()-style).
  711. * If format is null, then the raw ".($useDateTime ? 'DateTime object' : 'unix timestamp integer')." will be returned.";
  712. if ($useDateTime) {
  713. $script .= "
  714. * @return mixed Formatted date/time value as string or $dateTimeClass object (if format is null), null if column is null" .($handleMysqlDate ? ', and 0 if column value is ' . $mysqlInvalidDateString : '');
  715. } else {
  716. $script .= "
  717. * @return mixed Formatted date/time value as string or (integer) unix timestamp (if format is null), null if column is null".($handleMysqlDate ? ', and 0 if column value is ' . $mysqlInvalidDateString : '');
  718. }
  719. $script .= "
  720. * @throws PropelException - if unable to parse/validate the date/time value.
  721. */";
  722. }
  723. /**
  724. * Adds the function declaration for a temporal accessor
  725. * @param string &$script The script will be modified in this method.
  726. * @param Column $col The current column.
  727. * @see addTemporalAccessor
  728. **/
  729. public function addTemporalAccessorOpen(&$script, Column $col)
  730. {
  731. $cfc = $col->getPhpName();
  732. $defaultfmt = null;
  733. $visibility = $col->getAccessorVisibility();
  734. // Default date/time formatter strings are specified in build.properties
  735. if ($col->getType() === PropelTypes::DATE) {
  736. $defaultfmt = $this->getBuildProperty('defaultDateFormat');
  737. } elseif ($col->getType() === PropelTypes::TIME) {
  738. $defaultfmt = $this->getBuildProperty('defaultTimeFormat');
  739. } elseif ($col->getType() === PropelTypes::TIMESTAMP) {
  740. $defaultfmt = $this->getBuildProperty('defaultTimeStampFormat');
  741. }
  742. if (empty($defaultfmt)) {
  743. $defaultfmt = 'null';
  744. } else {
  745. $defaultfmt = var_export($defaultfmt, true);
  746. }
  747. $script .= "
  748. ".$visibility." function get$cfc(\$format = ".$defaultfmt."";
  749. if ($col->isLazyLoad()) $script .= ", \$con = null";
  750. $script .= ")
  751. {";
  752. }
  753. protected function getAccessorLazyLoadSnippet(Column $col)
  754. {
  755. if ($col->isLazyLoad()) {
  756. $clo = strtolower($col->getName());
  757. $defaultValueString = 'null';
  758. $def = $col->getDefaultValue();
  759. if ($def !== null && !$def->isExpression()) {
  760. $defaultValueString = $this->getDefaultValueString($col);
  761. }
  762. return "
  763. if (!\$this->{$clo}_isLoaded && \$this->{$clo} === {$defaultValueString} && !\$this->isNew()) {
  764. \$this->load{$col->getPhpName()}(\$con);
  765. }
  766. ";
  767. }
  768. }
  769. /**
  770. * Adds the body of the temporal accessor
  771. * @param string &$script The script will be modified in this method.
  772. * @param Column $col The current column.
  773. * @see addTemporalAccessor
  774. **/
  775. protected function addTemporalAccessorBody(&$script, Column $col)
  776. {
  777. $cfc = $col->getPhpName();
  778. $clo = strtolower($col->getName());
  779. $useDateTime = $this->getBuildProperty('useDateTimeClass');
  780. $dateTimeClass = $this->getBuildProperty('dateTimeClass');
  781. if (!$dateTimeClass) {
  782. $dateTimeClass = 'DateTime';
  783. }
  784. $this->declareClasses($dateTimeClass);
  785. $defaultfmt = null;
  786. // Default date/time formatter strings are specified in build.properties
  787. if ($col->getType() === PropelTypes::DATE) {
  788. $defaultfmt = $this->getBuildProperty('defaultDateFormat');
  789. } elseif ($col->getType() === PropelTypes::TIME) {
  790. $defaultfmt = $this->getBuildProperty('defaultTimeFormat');
  791. } elseif ($col->getType() === PropelTypes::TIMESTAMP) {
  792. $defaultfmt = $this->getBuildProperty('defaultTimeStampFormat');
  793. }
  794. if (empty($defaultfmt)) {
  795. $defaultfmt = null;
  796. }
  797. $handleMysqlDate = false;
  798. if ($this->getPlatform() instanceof MysqlPlatform) {
  799. if ($col->getType() === PropelTypes::TIMESTAMP) {
  800. $handleMysqlDate = true;
  801. $mysqlInvalidDateString = '0000-00-00 00:00:00';
  802. } elseif ($col->getType() === PropelTypes::DATE) {
  803. $handleMysqlDate = true;
  804. $mysqlInvalidDateString = '0000-00-00';
  805. }
  806. // 00:00:00 is a valid time, so no need to check for that.
  807. }
  808. if ($col->isLazyLoad()) {
  809. $script .= $this->getAccessorLazyLoadSnippet($col);
  810. }
  811. $script .= "
  812. if (\$this->$clo === null) {
  813. return null;
  814. }
  815. ";
  816. if ($handleMysqlDate) {
  817. $script .= "
  818. if (\$this->$clo === '$mysqlInvalidDateString') {
  819. // while technically this is not a default value of null,
  820. // this seems to be closest in meaning.
  821. return null;
  822. } else {
  823. try {
  824. \$dt = new $dateTimeClass(\$this->$clo);
  825. } catch (Exception \$x) {
  826. throw new PropelException(\"Internally stored date/time/timestamp value could not be converted to $dateTimeClass: \" . var_export(\$this->$clo, true), \$x);
  827. }
  828. }
  829. ";
  830. } else {
  831. $script .= "
  832. try {
  833. \$dt = new $dateTimeClass(\$this->$clo);
  834. } catch (Exception \$x) {
  835. throw new PropelException(\"Internally stored date/time/timestamp value could not be converted to $dateTimeClass: \" . var_export(\$this->$clo, true), \$x);
  836. }
  837. ";
  838. } // if handleMyqlDate
  839. $script .= "
  840. if (\$format === null) {";
  841. if ($useDateTime) {
  842. $script .= "
  843. // Because propel.useDateTimeClass is true, we return a $dateTimeClass object.
  844. return \$dt;";
  845. } else {
  846. $script .= "
  847. // We cast here to maintain BC in API; obviously we will lose data if we're dealing with pre-/post-epoch dates.
  848. return (int) \$dt->format('U');";
  849. }
  850. $script .= "
  851. } elseif (strpos(\$format, '%') !== false) {
  852. return strftime(\$format, \$dt->format('U'));
  853. } else {
  854. return \$dt->format(\$format);
  855. }";
  856. }
  857. /**
  858. * Adds the body of the temporal accessor
  859. * @param string &$script The script will be modified in this method.
  860. * @param Column $col The current column.
  861. * @see addTemporalAccessorClose
  862. **/
  863. protected function addTemporalAccessorClose(&$script, Column $col)
  864. {
  865. $script .= "
  866. }
  867. ";
  868. }
  869. /**
  870. * Adds an object getter method.
  871. * @param string &$script The script will be modified in this method.
  872. * @param Column $col The current column.
  873. * @see parent::addColumnAccessors()
  874. */
  875. protected function addObjectAccessor(&$script, Column $col)
  876. {
  877. $this->addDefaultAccessorComment($script, $col);
  878. $this->addDefaultAccessorOpen($script, $col);
  879. $this->addObjectAccessorBody($script, $col);
  880. $this->addDefaultAccessorClose($script, $col);
  881. }
  882. /**
  883. * Adds the function body for an object accessor method
  884. * @param string &$script The script will be modified in this method.
  885. * @param Column $col The current column.
  886. * @see addDefaultAccessor()
  887. **/
  888. protected function addObjectAccessorBody(&$script, Column $col)
  889. {
  890. $cfc = $col->getPhpName();
  891. $clo = strtolower($col->getName());
  892. $cloUnserialized = $clo.'_unserialized';
  893. if ($col->isLazyLoad()) {
  894. $script .= $this->getAccessorLazyLoadSnippet($col);
  895. }
  896. $script .= "
  897. if (null == \$this->$cloUnserialized && null !== \$this->$clo) {
  898. \$this->$cloUnserialized = unserialize(\$this->$clo);
  899. }
  900. return \$this->$cloUnserialized;";
  901. }
  902. /**
  903. * Adds an array getter method.
  904. * @param string &$script The script will be modified in this method.
  905. * @param Column $col The current column.
  906. * @see parent::addColumnAccessors()
  907. */
  908. protected function addArrayAccessor(&$script, Column $col)
  909. {
  910. $this->addDefaultAccessorComment($script, $col);
  911. $this->addDefaultAccessorOpen($script, $col);
  912. $this->addArrayAccessorBody($script, $col);
  913. $this->addDefaultAccessorClose($script, $col);
  914. }
  915. /**
  916. * Adds the function body for an array accessor method
  917. * @param string &$script The script will be modified in this method.
  918. * @param Column $col The current column.
  919. * @see addDefaultAccessor()
  920. **/
  921. protected function addArrayAccessorBody(&$script, Column $col)
  922. {
  923. $cfc = $col->getPhpName();
  924. $clo = strtolower($col->getName());
  925. $cloUnserialized = $clo.'_unserialized';
  926. if ($col->isLazyLoad()) {
  927. $script .= $this->getAccessorLazyLoadSnippet($col);
  928. }
  929. $script .= "
  930. if (null === \$this->$cloUnserialized) {
  931. \$this->$cloUnserialized = array();
  932. }
  933. if (!\$this->$cloUnserialized && null !== \$this->$clo) {
  934. \$$cloUnserialized = substr(\$this->$clo, 2, -2);
  935. \$this->$cloUnserialized = \$$cloUnserialized ? explode(' | ', \$$cloUnserialized) : array();
  936. }
  937. return \$this->$cloUnserialized;";
  938. }
  939. /**
  940. * Adds an enum getter method.
  941. * @param string &$script The script will be modified in this method.
  942. * @param Column $col The current column.
  943. * @see parent::addColumnAccessors()
  944. */
  945. protected function addEnumAccessor(&$script, Column $col)
  946. {
  947. $clo = strtolower($col->getName());
  948. $script .= "
  949. /**
  950. * Get the [$clo] column value.
  951. * ".$col->getDescription();
  952. if ($col->isLazyLoad()) {
  953. $script .= "
  954. * @param PropelPDO \$con An optional PropelPDO connection to use for fetching this lazy-loaded column.";
  955. }
  956. $script .= "
  957. * @return ".$col->getPhpType()."
  958. * @throws PropelException - if the stored enum key is unknown.
  959. */";
  960. $this->addDefaultAccessorOpen($script, $col);
  961. $this->addEnumAccessorBody($script, $col);
  962. $this->addDefaultAccessorClose($script, $col);
  963. }
  964. /**
  965. * Adds the function body for an enum accessor method
  966. * @param string &$script The script will be modified in this method.
  967. * @param Column $col The current column.
  968. * @see addDefaultAccessor()
  969. **/
  970. protected function addEnumAccessorBody(&$script, Column $col)
  971. {
  972. $cfc = $col->getPhpName();
  973. $clo = strtolower($col->getName());
  974. if ($col->isLazyLoad()) {
  975. $script .= $this->getAccessorLazyLoadSnippet($col);
  976. }
  977. $script .= "
  978. if (null === \$this->$clo) {
  979. return null;
  980. }
  981. \$valueSet = " . $this->getPeerClassname() . "::getValueSet(" . $this->getColumnConstant($col) . ");
  982. if (!isset(\$valueSet[\$this->$clo])) {
  983. throw new PropelException('Unknown stored enum key: ' . \$this->$clo);
  984. }
  985. return \$valueSet[\$this->$clo];";
  986. }
  987. /**
  988. * Adds a tester method for an array column.
  989. * @param string &$script The script will be modified in this method.
  990. * @param Column $col The current column.
  991. */
  992. protected function addHasArrayElement(&$script, Column $col)
  993. {
  994. $clo = strtolower($col->getName());
  995. $cfc = $col->getPhpName();
  996. $visibility = $col->getAccessorVisibility();
  997. $singularPhpName = rtrim($cfc, 's');
  998. $script .= "
  999. /**
  1000. * Test the presence of a value in the [$clo] array column value.
  1001. * @param mixed \$value
  1002. * ".$col->getDescription();
  1003. if ($col->isLazyLoad()) {
  1004. $script .= "
  1005. * @param PropelPDO \$con An optional PropelPDO connection to use for fetching this lazy-loaded column.";
  1006. }
  1007. $script .= "
  1008. * @return boolean
  1009. */
  1010. $visibility function has$singularPhpName(\$value";
  1011. if ($col->isLazyLoad()) $script .= ", PropelPDO \$con = null";
  1012. $script .= ")
  1013. {
  1014. return in_array(\$value, \$this->get$cfc(";
  1015. if ($col->isLazyLoad()) $script .= "\$con";
  1016. $script .= "));
  1017. } // has$singularPhpName()
  1018. ";
  1019. }
  1020. /**
  1021. * Adds a normal (non-temporal) getter method.
  1022. * @param string &$script The script will be modified in this method.
  1023. * @param Column $col The current column.
  1024. * @see parent::addColumnAccessors()
  1025. */
  1026. protected function addDefaultAccessor(&$script, Column $col)
  1027. {
  1028. $this->addDefaultAccessorComment($script, $col);
  1029. $this->addDefaultAccessorOpen($script, $col);
  1030. $this->addDefaultAccessorBody($script, $col);
  1031. $this->addDefaultAccessorClose($script, $col);
  1032. }
  1033. /**
  1034. * Add the comment for a default accessor method (a getter)
  1035. * @param string &$script The script will be modified in this method.
  1036. * @param Column $col The current column.
  1037. * @see addDefaultAccessor()
  1038. **/
  1039. public function addDefaultAccessorComment(&$script, Column $col)
  1040. {
  1041. $clo=strtolower($col->getName());
  1042. $script .= "
  1043. /**
  1044. * Get the [$clo] column value.
  1045. * ".$col->getDescription();
  1046. if ($col->isLazyLoad()) {
  1047. $script .= "
  1048. * @param PropelPDO \$con An optional PropelPDO connection to use for fetching this lazy-loaded column.";
  1049. }
  1050. $script .= "
  1051. * @return ".$col->getPhpType()."
  1052. */";
  1053. }
  1054. /**
  1055. * Adds the function declaration for a default accessor
  1056. * @param string &$script The script will be modified in this method.
  1057. * @param Column $col The current column.
  1058. * @see addDefaultAccessor()
  1059. **/
  1060. public function addDefaultAccessorOpen(&$script, Column $col)
  1061. {
  1062. $cfc = $col->getPhpName();
  1063. $visibility = $col->getAccessorVisibility();
  1064. $script .= "
  1065. ".$visibility." function get$cfc(";
  1066. if ($col->isLazyLoad()) $script .= "PropelPDO \$con = null";
  1067. $script .= ")
  1068. {";
  1069. }
  1070. /**
  1071. * Adds the function body for a default accessor method
  1072. * @param string &$script The script will be modified in this method.
  1073. * @param Column $col The current column.
  1074. * @see addDefaultAccessor()
  1075. **/
  1076. protected function addDefaultAccessorBody(&$script, Column $col)
  1077. {
  1078. $cfc = $col->getPhpName();
  1079. $clo = strtolower($col->getName());
  1080. if ($col->isLazyLoad()) {
  1081. $script .= $this->getAccessorLazyLoadSnippet($col);
  1082. }
  1083. $script .= "
  1084. return \$this->$clo;";
  1085. }
  1086. /**
  1087. * Adds the function close for a default accessor method
  1088. * @param string &$script The script will be modified in this method.
  1089. * @param Column $col The current column.
  1090. * @see addDefaultAccessor()
  1091. **/
  1092. protected function addDefaultAccessorClose(&$script, Column $col)
  1093. {
  1094. $script .= "
  1095. }
  1096. ";
  1097. }
  1098. /**
  1099. * Adds the lazy loader method.
  1100. * @param string &$script The script will be modified in this method.
  1101. * @param Column $col The current column.
  1102. * @see parent::addColumnAccessors()
  1103. */
  1104. protected function addLazyLoader(&$script, Column $col)
  1105. {
  1106. $this->addLazyLoaderComment($script, $col);
  1107. $this->addLazyLoaderOpen($script, $col);
  1108. $this->addLazyLoaderBody($script, $col);
  1109. $this->addLazyLoaderClose($script, $col);
  1110. }
  1111. /**
  1112. * Adds the comment for the lazy loader method
  1113. * @param string &$script The script will be modified in this method.
  1114. * @param Column $col The current column.
  1115. * @see addLazyLoader()
  1116. **/
  1117. protected function addLazyLoaderComment(&$script, Column $col)
  1118. {
  1119. $clo = strtolower($col->getName());
  1120. $script .= "
  1121. /**
  1122. * Load the value for the lazy-loaded [$clo] column.
  1123. *
  1124. * This method performs an additional query to return the value for
  1125. * the [$clo] column, since it is not populated by
  1126. * the hydrate() method.
  1127. *
  1128. * @param PropelPDO \$con (optional) The PropelPDO connection to use.
  1129. * @return void
  1130. * @throws PropelException - any underlying error will be wrapped and re-thrown.
  1131. */";
  1132. }
  1133. /**
  1134. * Adds the function declaration for the lazy loader method
  1135. * @param string &$script The script will be modified in this method.
  1136. * @param Column $col The current column.
  1137. * @see addLazyLoader()
  1138. **/
  1139. protected function addLazyLoaderOpen(&$script, Column $col)
  1140. {
  1141. $cfc = $col->getPhpName();
  1142. $script .= "
  1143. protected function load$cfc(PropelPDO \$con = null)
  1144. {";
  1145. }
  1146. /**
  1147. * Adds the function body for the lazy loader method
  1148. * @param string &$script The script will be modified in this method.
  1149. * @param Column $col The current column.
  1150. * @see addLazyLoader()
  1151. **/
  1152. protected function addLazyLoaderBody(&$script, Column $col)
  1153. {
  1154. $platform = $this->getPlatform();
  1155. $clo = strtolower($col->getName());
  1156. // pdo_sqlsrv driver requires the use of PDOStatement::bindColumn() or a hex string will be returned
  1157. if ($col->getType() === PropelTypes::BLOB && $platform instanceof SqlsrvPlatform) {
  1158. $script .= "
  1159. \$c = \$this->buildPkeyCriteria();
  1160. \$c->addSelectColumn(".$this->getColumnConstant($col).");
  1161. try {
  1162. \$row = array(0 => null);
  1163. \$stmt = ".$this->getPeerClassname()."::doSelectStmt(\$c, \$con);
  1164. \$stmt->bindColumn(1, \$row[0], PDO::PARAM_LOB, 0, PDO::SQLSRV_ENCODING_BINARY);
  1165. \$stmt->fetch(PDO::FETCH_BOUND);
  1166. \$stmt->closeCursor();";
  1167. } else {
  1168. $script .= "
  1169. \$c = \$this->buildPkeyCriteria();
  1170. \$c->addSelectColumn(".$this->getColumnConstant($col).");
  1171. try {
  1172. \$stmt = ".$this->getPeerClassname()."::doSelectStmt(\$c, \$con);
  1173. \$row = \$stmt->fetch(PDO::FETCH_NUM);
  1174. \$stmt->closeCursor();";
  1175. }
  1176. if ($col->getType() === PropelTypes::CLOB && $platform instanceof OraclePlatform) {
  1177. // PDO_OCI returns a stream for CLOB objects, while other PDO adapters return a string...
  1178. $script .= "
  1179. \$this->$clo = stream_get_contents(\$row[0]);";
  1180. } elseif ($col->isLobType() && !$platform->hasStreamBlobImpl()) {
  1181. $script .= "
  1182. if (\$row[0] !== null) {
  1183. \$this->$clo = fopen('php://memory', 'r+');
  1184. fwrite(\$this->$clo, \$row[0]);
  1185. rewind(\$this->$clo);
  1186. } else {
  1187. \$this->$clo = null;
  1188. }";
  1189. } elseif ($col->isPhpPrimitiveType()) {
  1190. $script .= "
  1191. \$this->$clo = (\$row[0] !== null) ? (".$col->getPhpType().") \$row[0] : null;";
  1192. } elseif ($col->isPhpObjectType()) {
  1193. $script .= "
  1194. \$this->$clo = (\$row[0] !== null) ? new ".$col->getPhpType()."(\$row[0]) : null;";
  1195. } else {
  1196. $script .= "
  1197. \$this->$clo = \$row[0];";
  1198. }
  1199. $script .= "
  1200. \$this->".$clo."_isLoaded = true;
  1201. } catch (Exception \$e) {
  1202. throw new PropelException(\"Error loading value for [$clo] column on demand.\", \$e);
  1203. }";
  1204. }
  1205. /**
  1206. * Adds the function close for the lazy loader
  1207. * @param string &$script The script will be modified in this method.
  1208. * @param Column $col The current column.
  1209. * @see addLazyLoader()
  1210. **/
  1211. protected function addLazyLoaderClose(&$script, Column $col)
  1212. {
  1213. $script .= "
  1214. }";
  1215. } // addLazyLoader()
  1216. // --------------------------------------------------------------
  1217. //
  1218. // M U T A T O R M E T H O D S
  1219. //
  1220. // --------------------------------------------------------------
  1221. /**
  1222. * Adds the open of the mutator (setter) method for a column.
  1223. * @param string &$script The script will be modified in this method.
  1224. * @param Column $col The current column.
  1225. */
  1226. protected function addMutatorOpen(&$script, Column $col)
  1227. {
  1228. $this->addMutatorComment($script, $col);
  1229. $this->addMutatorOpenOpen($script, $col);
  1230. $this->addMutatorOpenBody($script, $col);
  1231. }
  1232. /**
  1233. * Adds the comment for a mutator
  1234. * @param string &$script The script will be modified in this method.
  1235. * @param Column $col The current column.
  1236. * @see addMutatorOpen()
  1237. **/
  1238. public function addMutatorComment(&$script, Column $col)
  1239. {
  1240. $clo = strtolower($col->getName());
  1241. $script .= "
  1242. /**
  1243. * Set the value of [$clo] column.
  1244. * ".$col->getDescription()."
  1245. * @param ".$col->getPhpType()." \$v new value
  1246. * @return ".$this->getObjectClassname()." The current object (for fluent API support)
  1247. */";
  1248. }
  1249. /**
  1250. * Adds the mutator function declaration
  1251. * @param string &$script The script will be modified in this method.
  1252. * @param Column $col The current column.
  1253. * @see addMutatorOpen()
  1254. **/
  1255. public function addMutatorOpenOpen(&$script, Column $col)
  1256. {
  1257. $cfc = $col->getPhpName();
  1258. $visibility = $col->getMutatorVisibility();
  1259. $script .= "
  1260. ".$visibility." function set$cfc(\$v)
  1261. {";
  1262. }
  1263. /**
  1264. * Adds the mutator open body part
  1265. * @param string &$script The script will be modified in this method.
  1266. * @param Column $col The current column.
  1267. * @see addMutatorOpen()
  1268. **/
  1269. protected function addMutatorOpenBody(&$script, Column $col)
  1270. {
  1271. $clo = strtolower($col->getName());
  1272. $cfc = $col->getPhpName();
  1273. if ($col->isLazyLoad()) {
  1274. $script .= "
  1275. // Allow unsetting the lazy loaded column even when its not loaded.
  1276. if (!\$this->".$clo."_isLoaded && \$v === null) {
  1277. \$this->modifiedColumns[] = ".$this->getColumnConstant($col).";
  1278. }
  1279. // explicitly set the is-loaded flag to true for this lazy load col;
  1280. // it doesn't matter if the value is actually set or not (logic below) as
  1281. // any attempt to set the value means that no db lookup should be performed
  1282. // when the get$cfc() method is called.
  1283. \$this->".$clo."_isLoaded = true;
  1284. ";
  1285. }
  1286. }
  1287. /**
  1288. * Adds the close of the mutator (setter) method for a column.
  1289. *
  1290. * @param string &$script The script will be modified in this method.
  1291. * @param Column $col The current column.
  1292. */
  1293. protected function addMutatorClose(&$script, Column $col)
  1294. {
  1295. $this->addMutatorCloseBody($script, $col);
  1296. $this->addMutatorCloseClose($script, $col);
  1297. }
  1298. /**
  1299. * Adds the body of the close part of a mutator
  1300. * @param string &$script The script will be modified in this method.
  1301. * @param Column $col The current column.
  1302. * @see addMutatorClose()
  1303. **/
  1304. protected function addMutatorCloseBody(&$script, Column $col)
  1305. {
  1306. $table = $this->getTable();
  1307. $cfc = $col->getPhpName();
  1308. $clo = strtolower($col->getName());
  1309. if ($col->isForeignKey()) {
  1310. foreach ($col->getForeignKeys() as $fk) {
  1311. $tblFK = $table->getDatabase()->getTable($fk->getForeignTableName());
  1312. $colFK = $tblFK->getColumn($fk->getMappedForeignColumn($col->getName()));
  1313. $varName = $this->getFKVarName($fk);
  1314. $script .= "
  1315. if (\$this->$varName !== null && \$this->".$varName."->get".$colFK->getPhpName()."() !== \$v) {
  1316. \$this->$varName = null;
  1317. }
  1318. ";
  1319. } // foreach fk
  1320. } /* if col is foreign key */
  1321. foreach ($col->getReferrers() as $refFK) {
  1322. $tblFK = $this->getDatabase()->getTable($refFK->getForeignTableName());
  1323. if ( $tblFK->getName() != $table->getName() ) {
  1324. foreach ($col->getForeignKeys() as $fk) {
  1325. $tblFK = $table->getDatabase()->getTable($fk->getForeignTableName());
  1326. $colFK = $tblFK->getColumn($fk->getMappedForeignColumn($col->getName()));
  1327. if ($refFK->isLocalPrimaryKey()) {
  1328. $varName = $this->getPKRefFKVarName($refFK);
  1329. $script .= "
  1330. // update associated ".$tblFK->getPhpName()."
  1331. if (\$this->$varName !== null) {
  1332. \$this->{$varName}->set".$colFK->getPhpName()."(\$v);
  1333. }
  1334. ";
  1335. } else {
  1336. $collName = $this->getRefFKCollVarName($refFK);
  1337. $script .= "
  1338. // update associated ".$tblFK->getPhpName()."
  1339. if (\$this->$collName !== null) {
  1340. foreach (\$this->$collName as \$referrerObject) {
  1341. \$referrerObject->set".$colFK->getPhpName()."(\$v);
  1342. }
  1343. }
  1344. ";
  1345. } // if (isLocalPrimaryKey
  1346. } // foreach col->getPrimaryKeys()
  1347. } // if tablFk != table
  1348. } // foreach
  1349. }
  1350. /**
  1351. * Adds the close for the mutator close
  1352. * @param string &$script The script will be modified in this method.
  1353. * @param Column $col The current column.
  1354. * @see addMutatorClose()
  1355. **/
  1356. protected function addMutatorCloseClose(&$script, Column $col)
  1357. {
  1358. $cfc = $col->getPhpName();
  1359. $script .= "
  1360. return \$this;
  1361. } // set$cfc()
  1362. ";
  1363. }
  1364. /**
  1365. * Adds a setter for BLOB columns.
  1366. * @param string &$script The script will be modified in this method.
  1367. * @param Column $col The current column.
  1368. * @see parent::addColumnMutators()
  1369. */
  1370. protected function addLobMutator(&$script, Column $col)
  1371. {
  1372. $this->addMutatorOpen($script, $col);
  1373. $clo = strtolower($col->getName());
  1374. $script .= "
  1375. // Because BLOB columns are streams in PDO we have to assume that they are
  1376. // always modified when a new value is passed in. For example, the contents
  1377. // of the stream itself may have changed externally.
  1378. if (!is_resource(\$v) && \$v !== null) {
  1379. \$this->$clo = fopen('php://memory', 'r+');
  1380. fwrite(\$this->$clo, \$v);
  1381. rewind(\$this->$clo);
  1382. } else { // it's already a stream
  1383. \$this->$clo = \$v;
  1384. }
  1385. \$this->modifiedColumns[] = ".$this->getColumnConstant($col).";
  1386. ";
  1387. $this->addMutatorClose($script, $col);
  1388. } // addLobMutatorSnippet
  1389. /**
  1390. * Adds a setter method for date/time/timestamp columns.
  1391. * @param string &$script The script will be modified in this method.
  1392. * @param Column $col The current column.
  1393. * @see parent::addColumnMutators()
  1394. */
  1395. protected function addTemporalMutator(&$script, Column $col)
  1396. {
  1397. $cfc = $col->getPhpName();
  1398. $clo = strtolower($col->getName());
  1399. $visibility = $col->getMutatorVisibility();
  1400. $dateTimeClass = $this->getBuildProperty('dateTimeClass');
  1401. if (!$dateTimeClass) {
  1402. $dateTimeClass = 'DateTime';
  1403. }
  1404. $this->declareClasses($dateTimeClass, 'DateTimeZone', 'PropelDateTime');
  1405. $this->addTemporalMutatorComment($script, $col);
  1406. $this->addMutatorOpenOpen($script, $col);
  1407. $this->addMutatorOpenBody($script, $col);
  1408. $fmt = var_export($this->getTemporalFormatter($col), true);
  1409. $script .= "
  1410. \$dt = PropelDateTime::newInstance(\$v, null, '$dateTimeClass');
  1411. if (\$this->$clo !== null || \$dt !== null) {
  1412. \$currentDateAsString = (\$this->$clo !== null && \$tmpDt = new $dateTimeClass(\$this->$clo)) ? \$tmpDt->format($fmt) : null;
  1413. \$newDateAsString = \$dt ? \$dt->format($fmt) : null;";
  1414. if (($def = $col->getDefaultValue()) !== null && !$def->isExpression()) {
  1415. $defaultValue = $this->getDefaultValueString($col);
  1416. $script .= "
  1417. if ( (\$currentDateAsString !== \$newDateAsString) // normalized values don't match
  1418. || (\$dt->format($fmt) === $defaultValue) // or the entered value matches the default
  1419. ) {";
  1420. } else {
  1421. $script .= "
  1422. if (\$currentDateAsString !== \$newDateAsString) {";
  1423. }
  1424. $script .= "
  1425. \$this->$clo = \$newDateAsString;
  1426. \$this->modifiedColumns[] = ".$this->getColumnConstant($col).";
  1427. }
  1428. } // if either are not null
  1429. ";
  1430. $this->addMutatorClose($script, $col);
  1431. }
  1432. public function addTemporalMutatorComment(&$script, Column $col)
  1433. {
  1434. $cfc = $col->getPhpName();
  1435. $clo = strtolower($col->getName());
  1436. $script .= "
  1437. /**
  1438. * Sets the value of [$clo] column to a normalized version of the date/time value specified.
  1439. * ".$col->getDescription()."
  1440. * @param mixed \$v string, integer (timestamp), or DateTime value.
  1441. * Empty strings are treated as null.
  1442. * @return ".$this->getObjectClassname()." The current object (for fluent API support)
  1443. */";
  1444. }
  1445. /**
  1446. * Adds a setter for Object columns.
  1447. * @param string &$script The script will be modified in this method.
  1448. * @param Column $col The current column.
  1449. * @see parent::addColumnMutators()
  1450. */
  1451. protected function addObjectMutator(&$script, Column $col)
  1452. {
  1453. $clo = strtolower($col->getName());
  1454. $cloUnserialized = $clo.'_unserialized';
  1455. $this->addMutatorOpen($script, $col);
  1456. $script .= "
  1457. if (\$this->$cloUnserialized !== \$v) {
  1458. \$this->$cloUnserialized = \$v;
  1459. \$this->$clo = serialize(\$v);
  1460. \$this->modifiedColumns[] = ".$this->getColumnConstant($col).";
  1461. }
  1462. ";
  1463. $this->addMutatorClose($script, $col);
  1464. }
  1465. /**
  1466. * Adds a setter for Array columns.
  1467. * @param string &$script The script will be modified in this method.
  1468. * @param Column $col The current column.
  1469. * @see parent::addColumnMutators()
  1470. */
  1471. protected function addArrayMutator(&$script, Column $col)
  1472. {
  1473. $clo = strtolower($col->getName());
  1474. $cloUnserialized = $clo.'_unserialized';
  1475. $this->addMutatorOpen($script, $col);
  1476. $script .= "
  1477. if (\$this->$cloUnserialized !== \$v) {
  1478. \$this->$cloUnserialized = \$v;
  1479. \$this->$clo = '| ' . implode(' | ', \$v) . ' |';
  1480. \$this->modifiedColumns[] = ".$this->getColumnConstant($col).";
  1481. }
  1482. ";
  1483. $this->addMutatorClose($script, $col);
  1484. }
  1485. /**
  1486. * Adds a push method for an array column.
  1487. * @param string &$script The script will be modified in this method.
  1488. * @param Column $col The current column.
  1489. */
  1490. protected function addAddArrayElement(&$script, Column $col)
  1491. {
  1492. $clo = strtolower($col->getName());
  1493. $cfc = $col->getPhpName();
  1494. $visibility = $col->getAccessorVisibility();
  1495. $singularPhpName = rtrim($cfc, 's');
  1496. $script .= "
  1497. /**
  1498. * Adds a value to the [$clo] array column value.
  1499. * @param mixed \$value
  1500. * ".$col->getDescription();
  1501. if ($col->isLazyLoad()) {
  1502. $script .= "
  1503. * @param PropelPDO \$con An optional PropelPDO connection to use for fetching this lazy-loaded column.";
  1504. }
  1505. $script .= "
  1506. * @return ".$this->getObjectClassname()." The current object (for fluent API support)
  1507. */
  1508. $visibility function add$singularPhpName(\$value";
  1509. if ($col->isLazyLoad()) $script .= ", PropelPDO \$con = null";
  1510. $script .= ")
  1511. {
  1512. \$currentArray = \$this->get$cfc(";
  1513. if ($col->isLazyLoad()) $script .= "\$con";
  1514. $script .= ");
  1515. \$currentArray []= \$value;
  1516. \$this->set$cfc(\$currentArray);
  1517. return \$this;
  1518. } // add$singularPhpName()
  1519. ";
  1520. }
  1521. /**
  1522. * Adds a remove method for an array column.
  1523. * @param string &$script The script will be modified in this method.
  1524. * @param Column $col The current column.
  1525. */
  1526. protected function addRemoveArrayElement(&$script, Column $col)
  1527. {
  1528. $clo = strtolower($col->getName());
  1529. $cfc = $col->getPhpName();
  1530. $visibility = $col->getAccessorVisibility();
  1531. $singularPhpName = rtrim($cfc, 's');
  1532. $script .= "
  1533. /**
  1534. * Removes a value from the [$clo] array column value.
  1535. * @param mixed \$value
  1536. * ".$col->getDescription();
  1537. if ($col->isLazyLoad()) {
  1538. $script .= "
  1539. * @param PropelPDO \$con An optional PropelPDO connection to use for fetching this lazy-loaded column.";
  1540. }
  1541. $script .= "
  1542. * @return ".$this->getObjectClassname()." The current object (for fluent API support)
  1543. */
  1544. $visibility function remove$singularPhpName(\$value";
  1545. if ($col->isLazyLoad()) $script .= ", PropelPDO \$con = null";
  1546. // we want to reindex the array, so array_ functions are not the best choice
  1547. $script .= ")
  1548. {
  1549. \$targetArray = array();
  1550. foreach (\$this->get$cfc(";
  1551. if ($col->isLazyLoad()) $script .= "\$con";
  1552. $script .= ") as \$element) {
  1553. if (\$element != \$value) {
  1554. \$targetArray []= \$element;
  1555. }
  1556. }
  1557. \$this->set$cfc(\$targetArray);
  1558. return \$this;
  1559. } // remove$singularPhpName()
  1560. ";
  1561. }
  1562. /**
  1563. * Adds a setter for Enum columns.
  1564. * @param string &$script The script will be modified in this method.
  1565. * @param Column $col The current column.
  1566. * @see parent::addColumnMutators()
  1567. */
  1568. protected function addEnumMutator(&$script, Column $col)
  1569. {
  1570. $clo = strtolower($col->getName());
  1571. $script .= "
  1572. /**
  1573. * Set the value of [$clo] column.
  1574. * ".$col->getDescription()."
  1575. * @param ".$col->getPhpType()." \$v new value
  1576. * @return ".$this->getObjectClassname()." The current object (for fluent API support)
  1577. * @throws PropelException - if the value is not accepted by this enum.
  1578. */";
  1579. $this->addMutatorOpenOpen($script, $col);
  1580. $this->addMutatorOpenBody($script, $col);
  1581. $script .= "
  1582. if (\$v !== null) {
  1583. \$valueSet = " . $this->getPeerClassname() . "::getValueSet(" . $this->getColumnConstant($col) . ");
  1584. if (!in_array(\$v, \$valueSet)) {
  1585. throw new PropelException(sprintf('Value \"%s\" is not accepted in this enumerated column', \$v));
  1586. }
  1587. \$v = array_search(\$v, \$valueSet);
  1588. }
  1589. if (\$this->$clo !== \$v) {
  1590. \$this->$clo = \$v;
  1591. \$this->modifiedColumns[] = ".$this->getColumnConstant($col).";
  1592. }
  1593. ";
  1594. $this->addMutatorClose($script, $col);
  1595. }
  1596. /**
  1597. * Adds setter method for boolean columns.
  1598. * @param string &$script The script will be modified in this method.
  1599. * @param Column $col The current column.
  1600. * @see parent::addColumnMutators()
  1601. */
  1602. protected function addBooleanMutator(&$script, Column $col)
  1603. {
  1604. $clo = strtolower($col->getName());
  1605. $this->addBooleanMutatorComment($script, $col);
  1606. $this->addMutatorOpenOpen($script, $col);
  1607. $this->addMutatorOpenBody($script, $col);
  1608. $script .= "
  1609. if (\$v !== null) {
  1610. if (is_string(\$v)) {
  1611. \$v = in_array(strtolower(\$v), array('false', 'off', '-', 'no', 'n', '0', '')) ? false : true;
  1612. } else {
  1613. \$v = (boolean) \$v;
  1614. }
  1615. }
  1616. ";
  1617. $script .= "
  1618. if (\$this->$clo !== \$v) {
  1619. \$this->$clo = \$v;
  1620. \$this->modifiedColumns[] = ".$this->getColumnConstant($col).";
  1621. }
  1622. ";
  1623. $this->addMutatorClose($script, $col);
  1624. }
  1625. public function addBooleanMutatorComment(&$script, Column $col)
  1626. {
  1627. $cfc = $col->getPhpName();
  1628. $clo = strtolower($col->getName());
  1629. $script .= "
  1630. /**
  1631. * Sets the value of the [$clo] column.
  1632. * Non-boolean arguments are converted using the following rules:
  1633. * * 1, '1', 'true', 'on', and 'yes' are converted to boolean true
  1634. * * 0, '0', 'false', 'off', and 'no' are converted to boolean false
  1635. * Check on string values is case insensitive (so 'FaLsE' is seen as 'false').
  1636. * ".$col->getDescription()."
  1637. * @param boolean|integer|string \$v The new value
  1638. * @return ".$this->getObjectClassname()." The current object (for fluent API support)
  1639. */";
  1640. }
  1641. /**
  1642. * Adds setter method for "normal" columns.
  1643. * @param string &$script The script will be modified in this method.
  1644. * @param Column $col The current column.
  1645. * @see parent::addColumnMutators()
  1646. */
  1647. protected function addDefaultMutator(&$script, Column $col)
  1648. {
  1649. $clo = strtolower($col->getName());
  1650. $this->addMutatorOpen($script, $col);
  1651. // Perform type-casting to ensure that we can use type-sensitive
  1652. // checking in mutators.
  1653. if ($col->isPhpPrimitiveType()) {
  1654. $script .= "
  1655. if (\$v !== null) {
  1656. \$v = (".$col->getPhpType().") \$v;
  1657. }
  1658. ";
  1659. }
  1660. $script .= "
  1661. if (\$this->$clo !== \$v) {
  1662. \$this->$clo = \$v;
  1663. \$this->modifiedColumns[] = ".$this->getColumnConstant($col).";
  1664. }
  1665. ";
  1666. $this->addMutatorClose($script, $col);
  1667. }
  1668. /**
  1669. * Adds the hasOnlyDefaultValues() method.
  1670. * @param string &$script The script will be modified in this method.
  1671. */
  1672. protected function addHasOnlyDefaultValues(&$script)
  1673. {
  1674. $this->addHasOnlyDefaultValuesComment($script);
  1675. $this->addHasOnlyDefaultValuesOpen($script);
  1676. $this->addHasOnlyDefaultValuesBody($script);
  1677. $this->addHasOnlyDefaultValuesClose($script);
  1678. }
  1679. /**
  1680. * Adds the comment for the hasOnlyDefaultValues method
  1681. * @param string &$script The script will be modified in this method.
  1682. * @see addHasOnlyDefaultValues
  1683. **/
  1684. protected function addHasOnlyDefaultValuesComment(&$script)
  1685. {
  1686. $script .= "
  1687. /**
  1688. * Indicates whether the columns in this object are only set to default values.
  1689. *
  1690. * This method can be used in conjunction with isModified() to indicate whether an object is both
  1691. * modified _and_ has some values set which are non-default.
  1692. *
  1693. * @return boolean Whether the columns in this object are only been set with default values.
  1694. */";
  1695. }
  1696. /**
  1697. * Adds the function declaration for the hasOnlyDefaultValues method
  1698. * @param string &$script The script will be modified in this method.
  1699. * @see addHasOnlyDefaultValues
  1700. **/
  1701. protected function addHasOnlyDefaultValuesOpen(&$script)
  1702. {
  1703. $script .= "
  1704. public function hasOnlyDefaultValues()
  1705. {";
  1706. }
  1707. /**
  1708. * Adds the function body for the hasOnlyDefaultValues method
  1709. * @param string &$script The script will be modified in this method.
  1710. * @see addHasOnlyDefaultValues
  1711. **/
  1712. protected function addHasOnlyDefaultValuesBody(&$script)
  1713. {
  1714. $table = $this->getTable();
  1715. $colsWithDefaults = array();
  1716. foreach ($table->getColumns() as $col) {
  1717. $def = $col->getDefaultValue();
  1718. if ($def !== null && !$def->isExpression()) {
  1719. $colsWithDefaults[] = $col;
  1720. }
  1721. }
  1722. foreach ($colsWithDefaults as $col) {
  1723. $clo = strtolower($col->getName());
  1724. $def = $col->getDefaultValue();
  1725. $script .= "
  1726. if (\$this->$clo !== " . $this->getDefaultValueString($col).") {
  1727. return false;
  1728. }
  1729. ";
  1730. }
  1731. }
  1732. /**
  1733. * Adds the function close for the hasOnlyDefaultValues method
  1734. * @param string &$script The script will be modified in this method.
  1735. * @see addHasOnlyDefaultValues
  1736. **/
  1737. protected function addHasOnlyDefaultValuesClose(&$script)
  1738. {
  1739. $script .= "
  1740. // otherwise, everything was equal, so return true
  1741. return true;";
  1742. $script .= "
  1743. } // hasOnlyDefaultValues()
  1744. ";
  1745. }
  1746. /**
  1747. * Adds the hydrate() method, which sets attributes of the object based on a ResultSet.
  1748. * @param string &$script The script will be modified in this method.
  1749. */
  1750. protected function addHydrate(&$script)
  1751. {
  1752. $this->addHydrateComment($script);
  1753. $this->addHydrateOpen($script);
  1754. $this->addHydrateBody($script);
  1755. $this->addHydrateClose($script);
  1756. }
  1757. /**
  1758. * Adds the comment for the hydrate method
  1759. * @param string &$script The script will be modified in this method.
  1760. * @see addHydrate()
  1761. */
  1762. protected function addHydrateComment(&$script)
  1763. {
  1764. $script .= "
  1765. /**
  1766. * Hydrates (populates) the object variables with values from the database resultset.
  1767. *
  1768. * An offset (0-based \"start column\") is specified so that objects can be hydrated
  1769. * with a subset of the columns in the resultset rows. This is needed, for example,
  1770. * for results of JOIN queries where the resultset row includes columns from two or
  1771. * more tables.
  1772. *
  1773. * @param array \$row The row returned by PDOStatement->fetch(PDO::FETCH_NUM)
  1774. * @param int \$startcol 0-based offset column which indicates which restultset column to start with.
  1775. * @param boolean \$rehydrate Whether this object is being re-hydrated from the database.
  1776. * @return int next starting column
  1777. * @throws PropelException - Any caught Exception will be rewrapped as a PropelException.
  1778. */";
  1779. }
  1780. /**
  1781. * Adds the function declaration for the hydrate method
  1782. * @param string &$script The script will be modified in this method.
  1783. * @see addHydrate()
  1784. */
  1785. protected function addHydrateOpen(&$script)
  1786. {
  1787. $script .= "
  1788. public function hydrate(\$row, \$startcol = 0, \$rehydrate = false)
  1789. {";
  1790. }
  1791. /**
  1792. * Adds the function body for the hydrate method
  1793. * @param string &$script The script will be modified in this method.
  1794. * @see addHydrate()
  1795. */
  1796. protected function addHydrateBody(&$script)
  1797. {
  1798. $table = $this->getTable();
  1799. $platform = $this->getPlatform();
  1800. $script .= "
  1801. try {
  1802. ";
  1803. $n = 0;
  1804. foreach ($table->getColumns() as $col) {
  1805. if (!$col->isLazyLoad()) {
  1806. $clo = strtolower($col->getName());
  1807. if ($col->getType() === PropelTypes::CLOB_EMU && $this->getPlatform() instanceof OraclePlatform) {
  1808. // PDO_OCI returns a stream for CLOB objects, while other PDO adapters return a string...
  1809. $script .= "
  1810. \$this->$clo = stream_get_contents(\$row[\$startcol + $n]);";
  1811. } elseif ($col->isLobType() && !$platform->hasStreamBlobImpl()) {
  1812. $script .= "
  1813. if (\$row[\$startcol + $n] !== null) {
  1814. \$this->$clo = fopen('php://memory', 'r+');
  1815. fwrite(\$this->$clo, \$row[\$startcol + $n]);
  1816. rewind(\$this->$clo);
  1817. } else {
  1818. \$this->$clo = null;
  1819. }";
  1820. } elseif ($col->isPhpPrimitiveType()) {
  1821. $script .= "
  1822. \$this->$clo = (\$row[\$startcol + $n] !== null) ? (".$col->getPhpType().") \$row[\$startcol + $n] : null;";
  1823. } elseif ($col->getType() === PropelTypes::OBJECT) {
  1824. $script .= "
  1825. \$this->$clo = \$row[\$startcol + $n];";
  1826. } elseif ($col->getType() === PropelTypes::PHP_ARRAY) {
  1827. $cloUnserialized = $clo . '_unserialized';
  1828. $script .= "
  1829. \$this->$clo = \$row[\$startcol + $n];
  1830. \$this->$cloUnserialized = null;";
  1831. } elseif ($col->isPhpObjectType()) {
  1832. $script .= "
  1833. \$this->$clo = (\$row[\$startcol + $n] !== null) ? new ".$col->getPhpType()."(\$row[\$startcol + $n]) : null;";
  1834. } else {
  1835. $script .= "
  1836. \$this->$clo = \$row[\$startcol + $n];";
  1837. }
  1838. $n++;
  1839. } // if col->isLazyLoad()
  1840. } /* foreach */
  1841. if ($this->getBuildProperty("addSaveMethod")) {
  1842. $script .= "
  1843. \$this->resetModified();
  1844. ";
  1845. }
  1846. $script .= "
  1847. \$this->setNew(false);
  1848. if (\$rehydrate) {
  1849. \$this->ensureConsistency();
  1850. }
  1851. \$this->postHydrate(\$row, \$startcol, \$rehydrate);";
  1852. $this->applyBehaviorModifier('postHydrate', $script, " ");
  1853. $script .= "
  1854. return \$startcol + $n; // $n = ".$this->getPeerClassname()."::NUM_HYDRATE_COLUMNS.
  1855. } catch (Exception \$e) {
  1856. throw new PropelException(\"Error populating ".$this->getStubObjectBuilder()->getClassname()." object\", \$e);
  1857. }";
  1858. }
  1859. /**
  1860. * Adds the function close for the hydrate method
  1861. * @param string &$script The script will be modified in this method.
  1862. * @see addHydrate()
  1863. */
  1864. protected function addHydrateClose(&$script)
  1865. {
  1866. $script .= "
  1867. }
  1868. ";
  1869. }
  1870. /**
  1871. * Adds the buildPkeyCriteria method
  1872. * @param string &$script The script will be modified in this method.
  1873. **/
  1874. protected function addBuildPkeyCriteria(&$script)
  1875. {
  1876. $this->addBuildPkeyCriteriaComment($script);
  1877. $this->addBuildPkeyCriteriaOpen($script);
  1878. $this->addBuildPkeyCriteriaBody($script);
  1879. $this->addBuildPkeyCriteriaClose($script);
  1880. }
  1881. /**
  1882. * Adds the comment for the buildPkeyCriteria method
  1883. * @param string &$script The script will be modified in this method.
  1884. * @see addBuildPkeyCriteria()
  1885. **/
  1886. protected function addBuildPkeyCriteriaComment(&$script)
  1887. {
  1888. $script .= "
  1889. /**
  1890. * Builds a Criteria object containing the primary key for this object.
  1891. *
  1892. * Unlike buildCriteria() this method includes the primary key values regardless
  1893. * of whether or not they have been modified.
  1894. *
  1895. * @return Criteria The Criteria object containing value(s) for primary key(s).
  1896. */";
  1897. }
  1898. /**
  1899. * Adds the function declaration for the buildPkeyCriteria method
  1900. * @param string &$script The script will be modified in this method.
  1901. * @see addBuildPkeyCriteria()
  1902. **/
  1903. protected function addBuildPkeyCriteriaOpen(&$script)
  1904. {
  1905. $script .= "
  1906. public function buildPkeyCriteria()
  1907. {";
  1908. }
  1909. /**
  1910. * Adds the function body for the buildPkeyCriteria method
  1911. * @param string &$script The script will be modified in this method.
  1912. * @see addBuildPkeyCriteria()
  1913. **/
  1914. protected function addBuildPkeyCriteriaBody(&$script)
  1915. {
  1916. $script .= "
  1917. \$criteria = new Criteria(".$this->getPeerClassname()."::DATABASE_NAME);";
  1918. foreach ($this->getTable()->getPrimaryKey() as $col) {
  1919. $clo = strtolower($col->getName());
  1920. $script .= "
  1921. \$criteria->add(".$this->getColumnConstant($col).", \$this->$clo);";
  1922. }
  1923. }
  1924. /**
  1925. * Adds the function close for the buildPkeyCriteria method
  1926. * @param string &$script The script will be modified in this method.
  1927. * @see addBuildPkeyCriteria()
  1928. **/
  1929. protected function addBuildPkeyCriteriaClose(&$script)
  1930. {
  1931. $script .= "
  1932. return \$criteria;
  1933. }
  1934. ";
  1935. }
  1936. /**
  1937. * Adds the buildCriteria method
  1938. * @param string &$script The script will be modified in this method.
  1939. **/
  1940. protected function addBuildCriteria(&$script)
  1941. {
  1942. $this->addBuildCriteriaComment($script);
  1943. $this->addBuildCriteriaOpen($script);
  1944. $this->addBuildCriteriaBody($script);
  1945. $this->addBuildCriteriaClose($script);
  1946. }
  1947. /**
  1948. * Adds comment for the buildCriteria method
  1949. * @param string &$script The script will be modified in this method.
  1950. * @see addBuildCriteria()
  1951. **/
  1952. protected function addBuildCriteriaComment(&$script)
  1953. {
  1954. $script .= "
  1955. /**
  1956. * Build a Criteria object containing the values of all modified columns in this object.
  1957. *
  1958. * @return Criteria The Criteria object containing all modified values.
  1959. */";
  1960. }
  1961. /**
  1962. * Adds the function declaration of the buildCriteria method
  1963. * @param string &$script The script will be modified in this method.
  1964. * @see addBuildCriteria()
  1965. **/
  1966. protected function addBuildCriteriaOpen(&$script)
  1967. {
  1968. $script .= "
  1969. public function buildCriteria()
  1970. {";
  1971. }
  1972. /**
  1973. * Adds the function body of the buildCriteria method
  1974. * @param string &$script The script will be modified in this method.
  1975. * @see addBuildCriteria()
  1976. **/
  1977. protected function addBuildCriteriaBody(&$script)
  1978. {
  1979. $script .= "
  1980. \$criteria = new Criteria(".$this->getPeerClassname()."::DATABASE_NAME);
  1981. ";
  1982. foreach ($this->getTable()->getColumns() as $col) {
  1983. $clo = strtolower($col->getName());
  1984. $script .= "
  1985. if (\$this->isColumnModified(".$this->getColumnConstant($col).")) \$criteria->add(".$this->getColumnConstant($col).", \$this->$clo);";
  1986. }
  1987. }
  1988. /**
  1989. * Adds the function close of the buildCriteria method
  1990. * @param string &$script The script will be modified in this method.
  1991. * @see addBuildCriteria()
  1992. **/
  1993. protected function addBuildCriteriaClose(&$script)
  1994. {
  1995. $script .= "
  1996. return \$criteria;
  1997. }
  1998. ";
  1999. }
  2000. /**
  2001. * Adds the toArray method
  2002. * @param string &$script The script will be modified in this method.
  2003. **/
  2004. protected function addToArray(&$script)
  2005. {
  2006. $fks = $this->getTable()->getForeignKeys();
  2007. $referrers = $this->getTable()->getReferrers();
  2008. $hasFks = count($fks) > 0 || count($referrers) > 0;
  2009. $objectClassName = $this->getObjectClassname();
  2010. $pkGetter = $this->getTable()->hasCompositePrimaryKey() ? 'serialize($this->getPrimaryKey())' : '$this->getPrimaryKey()';
  2011. $defaultKeyType = $this->getDefaultKeyType();
  2012. $script .= "
  2013. /**
  2014. * Exports the object as an array.
  2015. *
  2016. * You can specify the key type of the array by passing one of the class
  2017. * type constants.
  2018. *
  2019. * @param string \$keyType (optional) One of the class type constants BasePeer::TYPE_PHPNAME, BasePeer::TYPE_STUDLYPHPNAME,
  2020. * BasePeer::TYPE_COLNAME, BasePeer::TYPE_FIELDNAME, BasePeer::TYPE_NUM.
  2021. * Defaults to BasePeer::$defaultKeyType.
  2022. * @param boolean \$includeLazyLoadColumns (optional) Whether to include lazy loaded columns. Defaults to true.
  2023. * @param array \$alreadyDumpedObjects List of objects to skip to avoid recursion";
  2024. if ($hasFks) {
  2025. $script .= "
  2026. * @param boolean \$includeForeignObjects (optional) Whether to include hydrated related objects. Default to FALSE.";
  2027. }
  2028. $script .= "
  2029. *
  2030. * @return array an associative array containing the field names (as keys) and field values
  2031. */
  2032. public function toArray(\$keyType = BasePeer::$defaultKeyType, \$includeLazyLoadColumns = true, \$alreadyDumpedObjects = array()" . ($hasFks ? ", \$includeForeignObjects = false" : '') . ")
  2033. {
  2034. if (isset(\$alreadyDumpedObjects['$objectClassName'][$pkGetter])) {
  2035. return '*RECURSION*';
  2036. }
  2037. \$alreadyDumpedObjects['$objectClassName'][$pkGetter] = true;
  2038. \$keys = ".$this->getPeerClassname()."::getFieldNames(\$keyType);
  2039. \$result = array(";
  2040. foreach ($this->getTable()->getColumns() as $num => $col) {
  2041. if ($col->isLazyLoad()) {
  2042. $script .= "
  2043. \$keys[$num] => (\$includeLazyLoadColumns) ? \$this->get".$col->getPhpName()."() : null,";
  2044. } else {
  2045. $script .= "
  2046. \$keys[$num] => \$this->get".$col->getPhpName()."(),";
  2047. }
  2048. }
  2049. $script .= "
  2050. );";
  2051. if ($hasFks) {
  2052. $script .= "
  2053. if (\$includeForeignObjects) {";
  2054. foreach ($fks as $fk) {
  2055. $script .= "
  2056. if (null !== \$this->" . $this->getFKVarName($fk) . ") {
  2057. \$result['" . $this->getFKPhpNameAffix($fk, $plural = false) . "'] = \$this->" . $this->getFKVarName($fk) . "->toArray(\$keyType, \$includeLazyLoadColumns, \$alreadyDumpedObjects, true);
  2058. }";
  2059. }
  2060. foreach ($referrers as $fk) {
  2061. if ($fk->isLocalPrimaryKey()) {
  2062. $script .= "
  2063. if (null !== \$this->" . $this->getPKRefFKVarName($fk) . ") {
  2064. \$result['" . $this->getRefFKPhpNameAffix($fk, $plural = false) . "'] = \$this->" . $this->getPKRefFKVarName($fk) . "->toArray(\$keyType, \$includeLazyLoadColumns, \$alreadyDumpedObjects, true);
  2065. }";
  2066. } else {
  2067. $script .= "
  2068. if (null !== \$this->" . $this->getRefFKCollVarName($fk) . ") {
  2069. \$result['" . $this->getRefFKPhpNameAffix($fk, $plural = true) . "'] = \$this->" . $this->getRefFKCollVarName($fk) . "->toArray(null, true, \$keyType, \$includeLazyLoadColumns, \$alreadyDumpedObjects);
  2070. }";
  2071. }
  2072. }
  2073. $script .= "
  2074. }";
  2075. }
  2076. $script .= "
  2077. return \$result;
  2078. }
  2079. ";
  2080. } // addToArray()
  2081. /**
  2082. * Adds the getByName method
  2083. * @param string &$script The script will be modified in this method.
  2084. **/
  2085. protected function addGetByName(&$script)
  2086. {
  2087. $this->addGetByNameComment($script);
  2088. $this->addGetByNameOpen($script);
  2089. $this->addGetByNameBody($script);
  2090. $this->addGetByNameClose($script);
  2091. }
  2092. /**
  2093. * Adds the comment for the getByName method
  2094. * @param string &$script The script will be modified in this method.
  2095. * @see addGetByName
  2096. **/
  2097. protected function addGetByNameComment(&$script)
  2098. {
  2099. $defaultKeyType = $this->getDefaultKeyType();
  2100. $script .= "
  2101. /**
  2102. * Retrieves a field from the object by name passed in as a string.
  2103. *
  2104. * @param string \$name name
  2105. * @param string \$type The type of fieldname the \$name is of:
  2106. * one of the class type constants BasePeer::TYPE_PHPNAME, BasePeer::TYPE_STUDLYPHPNAME
  2107. * BasePeer::TYPE_COLNAME, BasePeer::TYPE_FIELDNAME, BasePeer::TYPE_NUM.
  2108. * Defaults to BasePeer::$defaultKeyType
  2109. * @return mixed Value of field.
  2110. */";
  2111. }
  2112. /**
  2113. * Adds the function declaration for the getByName method
  2114. * @param string &$script The script will be modified in this method.
  2115. * @see addGetByName
  2116. **/
  2117. protected function addGetByNameOpen(&$script)
  2118. {
  2119. $defaultKeyType = $this->getDefaultKeyType();
  2120. $script .= "
  2121. public function getByName(\$name, \$type = BasePeer::$defaultKeyType)
  2122. {";
  2123. }
  2124. /**
  2125. * Adds the function body for the getByName method
  2126. * @param string &$script The script will be modified in this method.
  2127. * @see addGetByName
  2128. **/
  2129. protected function addGetByNameBody(&$script)
  2130. {
  2131. $script .= "
  2132. \$pos = ".$this->getPeerClassname()."::translateFieldName(\$name, \$type, BasePeer::TYPE_NUM);
  2133. \$field = \$this->getByPosition(\$pos);";
  2134. }
  2135. /**
  2136. * Adds the function close for the getByName method
  2137. * @param string &$script The script will be modified in this method.
  2138. * @see addGetByName
  2139. **/
  2140. protected function addGetByNameClose(&$script)
  2141. {
  2142. $script .= "
  2143. return \$field;
  2144. }
  2145. ";
  2146. }
  2147. /**
  2148. * Adds the getByPosition method
  2149. * @param string &$script The script will be modified in this method.
  2150. **/
  2151. protected function addGetByPosition(&$script)
  2152. {
  2153. $this->addGetByPositionComment($script);
  2154. $this->addGetByPositionOpen($script);
  2155. $this->addGetByPositionBody($script);
  2156. $this->addGetByPositionClose($script);
  2157. }
  2158. /**
  2159. * Adds comment for the getByPosition method
  2160. * @param string &$script The script will be modified in this method.
  2161. * @see addGetByPosition
  2162. **/
  2163. protected function addGetByPositionComment(&$script)
  2164. {
  2165. $script .= "
  2166. /**
  2167. * Retrieves a field from the object by Position as specified in the xml schema.
  2168. * Zero-based.
  2169. *
  2170. * @param int \$pos position in xml schema
  2171. * @return mixed Value of field at \$pos
  2172. */";
  2173. }
  2174. /**
  2175. * Adds the function declaration for the getByPosition method
  2176. * @param string &$script The script will be modified in this method.
  2177. * @see addGetByPosition
  2178. **/
  2179. protected function addGetByPositionOpen(&$script)
  2180. {
  2181. $script .= "
  2182. public function getByPosition(\$pos)
  2183. {";
  2184. }
  2185. /**
  2186. * Adds the function body for the getByPosition method
  2187. * @param string &$script The script will be modified in this method.
  2188. * @see addGetByPosition
  2189. **/
  2190. protected function addGetByPositionBody(&$script)
  2191. {
  2192. $table = $this->getTable();
  2193. $script .= "
  2194. switch (\$pos) {";
  2195. $i = 0;
  2196. foreach ($table->getColumns() as $col) {
  2197. $cfc = $col->getPhpName();
  2198. $script .= "
  2199. case $i:
  2200. return \$this->get$cfc();
  2201. break;";
  2202. $i++;
  2203. } /* foreach */
  2204. $script .= "
  2205. default:
  2206. return null;
  2207. break;
  2208. } // switch()";
  2209. }
  2210. /**
  2211. * Adds the function close for the getByPosition method
  2212. * @param string &$script The script will be modified in this method.
  2213. * @see addGetByPosition
  2214. **/
  2215. protected function addGetByPositionClose(&$script)
  2216. {
  2217. $script .= "
  2218. }
  2219. ";
  2220. }
  2221. protected function addSetByName(&$script)
  2222. {
  2223. $table = $this->getTable();
  2224. $defaultKeyType = $this->getDefaultKeyType();
  2225. $script .= "
  2226. /**
  2227. * Sets a field from the object by name passed in as a string.
  2228. *
  2229. * @param string \$name peer name
  2230. * @param mixed \$value field value
  2231. * @param string \$type The type of fieldname the \$name is of:
  2232. * one of the class type constants BasePeer::TYPE_PHPNAME, BasePeer::TYPE_STUDLYPHPNAME
  2233. * BasePeer::TYPE_COLNAME, BasePeer::TYPE_FIELDNAME, BasePeer::TYPE_NUM.
  2234. * Defaults to BasePeer::$defaultKeyType
  2235. * @return void
  2236. */
  2237. public function setByName(\$name, \$value, \$type = BasePeer::$defaultKeyType)
  2238. {
  2239. \$pos = ".$this->getPeerClassname()."::translateFieldName(\$name, \$type, BasePeer::TYPE_NUM);
  2240. \$this->setByPosition(\$pos, \$value);
  2241. }
  2242. ";
  2243. }
  2244. protected function addSetByPosition(&$script)
  2245. {
  2246. $table = $this->getTable();
  2247. $script .= "
  2248. /**
  2249. * Sets a field from the object by Position as specified in the xml schema.
  2250. * Zero-based.
  2251. *
  2252. * @param int \$pos position in xml schema
  2253. * @param mixed \$value field value
  2254. * @return void
  2255. */
  2256. public function setByPosition(\$pos, \$value)
  2257. {
  2258. switch (\$pos) {";
  2259. $i = 0;
  2260. foreach ($table->getColumns() as $col) {
  2261. $cfc = $col->getPhpName();
  2262. $cptype = $col->getPhpType();
  2263. $script .= "
  2264. case $i:";
  2265. if (PropelTypes::ENUM === $col->getType()) {
  2266. $script .= "
  2267. \$valueSet = " . $this->getPeerClassname() . "::getValueSet(" . $this->getColumnConstant($col) . ");
  2268. if (isset(\$valueSet[\$value])) {
  2269. \$value = \$valueSet[\$value];
  2270. }";
  2271. } elseif (PropelTypes::PHP_ARRAY === $col->getType()) {
  2272. $script .= "
  2273. if (!is_array(\$value)) {
  2274. \$v = trim(substr(\$value, 2, -2));
  2275. \$value = \$v ? explode(' | ', \$v) : array();
  2276. }";
  2277. }
  2278. $script .= "
  2279. \$this->set$cfc(\$value);
  2280. break;";
  2281. $i++;
  2282. } /* foreach */
  2283. $script .= "
  2284. } // switch()
  2285. }
  2286. ";
  2287. } // addSetByPosition()
  2288. protected function addFromArray(&$script)
  2289. {
  2290. $defaultKeyType = $this->getDefaultKeyType();
  2291. $table = $this->getTable();
  2292. $script .= "
  2293. /**
  2294. * Populates the object using an array.
  2295. *
  2296. * This is particularly useful when populating an object from one of the
  2297. * request arrays (e.g. \$_POST). This method goes through the column
  2298. * names, checking to see whether a matching key exists in populated
  2299. * array. If so the setByName() method is called for that column.
  2300. *
  2301. * You can specify the key type of the array by additionally passing one
  2302. * of the class type constants BasePeer::TYPE_PHPNAME, BasePeer::TYPE_STUDLYPHPNAME,
  2303. * BasePeer::TYPE_COLNAME, BasePeer::TYPE_FIELDNAME, BasePeer::TYPE_NUM.
  2304. * The default key type is the column's BasePeer::$defaultKeyType
  2305. *
  2306. * @param array \$arr An array to populate the object from.
  2307. * @param string \$keyType The type of keys the array uses.
  2308. * @return void
  2309. */
  2310. public function fromArray(\$arr, \$keyType = BasePeer::$defaultKeyType)
  2311. {
  2312. \$keys = ".$this->getPeerClassname()."::getFieldNames(\$keyType);
  2313. ";
  2314. foreach ($table->getColumns() as $num => $col) {
  2315. $cfc = $col->getPhpName();
  2316. //TODO: remove. not used
  2317. $cptype = $col->getPhpType();
  2318. $script .= "
  2319. if (array_key_exists(\$keys[$num], \$arr)) \$this->set$cfc(\$arr[\$keys[$num]]);";
  2320. } /* foreach */
  2321. $script .= "
  2322. }
  2323. ";
  2324. } // addFromArray
  2325. /**
  2326. * Adds a delete() method to remove the object form the datastore.
  2327. * @param string &$script The script will be modified in this method.
  2328. */
  2329. protected function addDelete(&$script)
  2330. {
  2331. $this->addDeleteComment($script);
  2332. $this->addDeleteOpen($script);
  2333. $this->addDeleteBody($script);
  2334. $this->addDeleteClose($script);
  2335. }
  2336. /**
  2337. * Adds the comment for the delete function
  2338. * @param string &$script The script will be modified in this method.
  2339. * @see addDelete()
  2340. **/
  2341. protected function addDeleteComment(&$script)
  2342. {
  2343. $script .= "
  2344. /**
  2345. * Removes this object from datastore and sets delete attribute.
  2346. *
  2347. * @param PropelPDO \$con
  2348. * @return void
  2349. * @throws PropelException
  2350. * @throws Exception
  2351. * @see BaseObject::setDeleted()
  2352. * @see BaseObject::isDeleted()
  2353. */";
  2354. }
  2355. /**
  2356. * Adds the function declaration for the delete function
  2357. * @param string &$script The script will be modified in this method.
  2358. * @see addDelete()
  2359. **/
  2360. protected function addDeleteOpen(&$script)
  2361. {
  2362. $script .= "
  2363. public function delete(PropelPDO \$con = null)
  2364. {";
  2365. }
  2366. /**
  2367. * Adds the function body for the delete function
  2368. * @param string &$script The script will be modified in this method.
  2369. * @see addDelete()
  2370. **/
  2371. protected function addDeleteBody(&$script)
  2372. {
  2373. $script .= "
  2374. if (\$this->isDeleted()) {
  2375. throw new PropelException(\"This object has already been deleted.\");
  2376. }
  2377. if (\$con === null) {
  2378. \$con = Propel::getConnection(".$this->getPeerClassname()."::DATABASE_NAME, Propel::CONNECTION_WRITE);
  2379. }
  2380. \$con->beginTransaction();
  2381. try {
  2382. \$deleteQuery = ".$this->getQueryClassname()."::create()
  2383. ->filterByPrimaryKey(\$this->getPrimaryKey());";
  2384. if ($this->getGeneratorConfig()->getBuildProperty('addHooks')) {
  2385. $script .= "
  2386. \$ret = \$this->preDelete(\$con);";
  2387. // apply behaviors
  2388. $this->applyBehaviorModifier('preDelete', $script, " ");
  2389. $script .= "
  2390. if (\$ret) {
  2391. \$deleteQuery->delete(\$con);
  2392. \$this->postDelete(\$con);";
  2393. // apply behaviors
  2394. $this->applyBehaviorModifier('postDelete', $script, " ");
  2395. $script .= "
  2396. \$con->commit();
  2397. \$this->setDeleted(true);
  2398. } else {
  2399. \$con->commit();
  2400. }";
  2401. } else {
  2402. // apply behaviors
  2403. $this->applyBehaviorModifier('preDelete', $script, " ");
  2404. $script .= "
  2405. \$deleteQuery->delete(\$con);";
  2406. // apply behaviors
  2407. $this->applyBehaviorModifier('postDelete', $script, " ");
  2408. $script .= "
  2409. \$con->commit();
  2410. \$this->setDeleted(true);";
  2411. }
  2412. $script .= "
  2413. } catch (Exception \$e) {
  2414. \$con->rollBack();
  2415. throw \$e;
  2416. }";
  2417. }
  2418. /**
  2419. * Adds the function close for the delete function
  2420. * @param string &$script The script will be modified in this method.
  2421. * @see addDelete()
  2422. **/
  2423. protected function addDeleteClose(&$script)
  2424. {
  2425. $script .= "
  2426. }
  2427. ";
  2428. } // addDelete()
  2429. /**
  2430. * Adds a reload() method to re-fetch the data for this object from the database.
  2431. * @param string &$script The script will be modified in this method.
  2432. */
  2433. protected function addReload(&$script)
  2434. {
  2435. $table = $this->getTable();
  2436. $script .= "
  2437. /**
  2438. * Reloads this object from datastore based on primary key and (optionally) resets all associated objects.
  2439. *
  2440. * This will only work if the object has been saved and has a valid primary key set.
  2441. *
  2442. * @param boolean \$deep (optional) Whether to also de-associated any related objects.
  2443. * @param PropelPDO \$con (optional) The PropelPDO connection to use.
  2444. * @return void
  2445. * @throws PropelException - if this object is deleted, unsaved or doesn't have pk match in db
  2446. */
  2447. public function reload(\$deep = false, PropelPDO \$con = null)
  2448. {
  2449. if (\$this->isDeleted()) {
  2450. throw new PropelException(\"Cannot reload a deleted object.\");
  2451. }
  2452. if (\$this->isNew()) {
  2453. throw new PropelException(\"Cannot reload an unsaved object.\");
  2454. }
  2455. if (\$con === null) {
  2456. \$con = Propel::getConnection(".$this->getPeerClassname()."::DATABASE_NAME, Propel::CONNECTION_READ);
  2457. }
  2458. // We don't need to alter the object instance pool; we're just modifying this instance
  2459. // already in the pool.
  2460. \$stmt = ".$this->getPeerClassname()."::doSelectStmt(\$this->buildPkeyCriteria(), \$con);
  2461. \$row = \$stmt->fetch(PDO::FETCH_NUM);
  2462. \$stmt->closeCursor();
  2463. if (!\$row) {
  2464. throw new PropelException('Cannot find matching row in the database to reload object values.');
  2465. }
  2466. \$this->hydrate(\$row, 0, true); // rehydrate
  2467. ";
  2468. // support for lazy load columns
  2469. foreach ($table->getColumns() as $col) {
  2470. if ($col->isLazyLoad()) {
  2471. $clo = strtolower($col->getName());
  2472. $script .= "
  2473. // Reset the $clo lazy-load column
  2474. \$this->" . $clo . " = null;
  2475. \$this->".$clo."_isLoaded = false;
  2476. ";
  2477. }
  2478. }
  2479. $script .= "
  2480. if (\$deep) { // also de-associate any related objects?
  2481. ";
  2482. foreach ($table->getForeignKeys() as $fk) {
  2483. $varName = $this->getFKVarName($fk);
  2484. $script .= "
  2485. \$this->".$varName." = null;";
  2486. }
  2487. foreach ($table->getReferrers() as $refFK) {
  2488. if ($refFK->isLocalPrimaryKey()) {
  2489. $script .= "
  2490. \$this->".$this->getPKRefFKVarName($refFK)." = null;
  2491. ";
  2492. } else {
  2493. $script .= "
  2494. \$this->".$this->getRefFKCollVarName($refFK)." = null;
  2495. ";
  2496. }
  2497. }
  2498. foreach ($table->getCrossFks() as $fkList) {
  2499. list($refFK, $crossFK) = $fkList;
  2500. $script .= "
  2501. \$this->" . $this->getCrossFKVarName($crossFK). " = null;";
  2502. }
  2503. $script .= "
  2504. } // if (deep)
  2505. }
  2506. ";
  2507. } // addReload()
  2508. /**
  2509. * Adds the methods related to refreshing, saving and deleting the object.
  2510. * @param string &$script The script will be modified in this method.
  2511. */
  2512. protected function addManipulationMethods(&$script)
  2513. {
  2514. $this->addReload($script);
  2515. $this->addDelete($script);
  2516. $this->addSave($script);
  2517. $this->addDoSave($script);
  2518. $script .= $this->addDoInsert();
  2519. $script .= $this->addDoUpdate();
  2520. }
  2521. /**
  2522. * Adds the methods related to validationg the object.
  2523. * @param string &$script The script will be modified in this method.
  2524. */
  2525. protected function addValidationMethods(&$script)
  2526. {
  2527. $this->addValidationFailuresAttribute($script);
  2528. $this->addGetValidationFailures($script);
  2529. $this->addValidate($script);
  2530. $this->addDoValidate($script);
  2531. }
  2532. /**
  2533. * Adds the $validationFailures attribute to store ValidationFailed objects.
  2534. * @param string &$script The script will be modified in this method.
  2535. */
  2536. protected function addValidationFailuresAttribute(&$script)
  2537. {
  2538. $script .= "
  2539. /**
  2540. * Array of ValidationFailed objects.
  2541. * @var array ValidationFailed[]
  2542. */
  2543. protected \$validationFailures = array();
  2544. ";
  2545. }
  2546. /**
  2547. * Adds the getValidationFailures() method.
  2548. * @param string &$script The script will be modified in this method.
  2549. */
  2550. protected function addGetValidationFailures(&$script)
  2551. {
  2552. $script .= "
  2553. /**
  2554. * Gets any ValidationFailed objects that resulted from last call to validate().
  2555. *
  2556. *
  2557. * @return array ValidationFailed[]
  2558. * @see validate()
  2559. */
  2560. public function getValidationFailures()
  2561. {
  2562. return \$this->validationFailures;
  2563. }
  2564. ";
  2565. } // addGetValidationFailures()
  2566. /**
  2567. * Adds the correct getPrimaryKey() method for this object.
  2568. * @param string &$script The script will be modified in this method.
  2569. */
  2570. protected function addGetPrimaryKey(&$script)
  2571. {
  2572. $pkeys = $this->getTable()->getPrimaryKey();
  2573. if (count($pkeys) == 1) {
  2574. $this->addGetPrimaryKey_SinglePK($script);
  2575. } elseif (count($pkeys) > 1) {
  2576. $this->addGetPrimaryKey_MultiPK($script);
  2577. } else {
  2578. // no primary key -- this is deprecated, since we don't *need* this method anymore
  2579. $this->addGetPrimaryKey_NoPK($script);
  2580. }
  2581. }
  2582. /**
  2583. * Adds the getPrimaryKey() method for tables that contain a single-column primary key.
  2584. * @param string &$script The script will be modified in this method.
  2585. */
  2586. protected function addGetPrimaryKey_SinglePK(&$script)
  2587. {
  2588. $table = $this->getTable();
  2589. $pkeys = $table->getPrimaryKey();
  2590. $cptype = $pkeys[0]->getPhpType();
  2591. $script .= "
  2592. /**
  2593. * Returns the primary key for this object (row).
  2594. * @return $cptype
  2595. */
  2596. public function getPrimaryKey()
  2597. {
  2598. return \$this->get".$pkeys[0]->getPhpName()."();
  2599. }
  2600. ";
  2601. } // addetPrimaryKey_SingleFK
  2602. /**
  2603. * Adds the setPrimaryKey() method for tables that contain a multi-column primary key.
  2604. * @param string &$script The script will be modified in this method.
  2605. */
  2606. protected function addGetPrimaryKey_MultiPK(&$script)
  2607. {
  2608. $script .= "
  2609. /**
  2610. * Returns the composite primary key for this object.
  2611. * The array elements will be in same order as specified in XML.
  2612. * @return array
  2613. */
  2614. public function getPrimaryKey()
  2615. {
  2616. \$pks = array();";
  2617. $i = 0;
  2618. foreach ($this->getTable()->getPrimaryKey() as $pk) {
  2619. $script .= "
  2620. \$pks[$i] = \$this->get".$pk->getPhpName()."();";
  2621. $i++;
  2622. } /* foreach */
  2623. $script .= "
  2624. return \$pks;
  2625. }
  2626. ";
  2627. } // addGetPrimaryKey_MultiFK()
  2628. /**
  2629. * Adds the getPrimaryKey() method for objects that have no primary key.
  2630. * This "feature" is dreprecated, since the getPrimaryKey() method is not required
  2631. * by the Persistent interface (or used by the templates). Hence, this method is also
  2632. * deprecated.
  2633. * @param string &$script The script will be modified in this method.
  2634. * @deprecated
  2635. */
  2636. protected function addGetPrimaryKey_NoPK(&$script)
  2637. {
  2638. $script .= "
  2639. /**
  2640. * Returns null since this table doesn't have a primary key.
  2641. * This method exists only for BC and is deprecated!
  2642. * @return null
  2643. */
  2644. public function getPrimaryKey()
  2645. {
  2646. return null;
  2647. }
  2648. ";
  2649. }
  2650. /**
  2651. * Adds the correct setPrimaryKey() method for this object.
  2652. * @param string &$script The script will be modified in this method.
  2653. */
  2654. protected function addSetPrimaryKey(&$script)
  2655. {
  2656. $pkeys = $this->getTable()->getPrimaryKey();
  2657. if (count($pkeys) == 1) {
  2658. $this->addSetPrimaryKey_SinglePK($script);
  2659. } elseif (count($pkeys) > 1) {
  2660. $this->addSetPrimaryKey_MultiPK($script);
  2661. } else {
  2662. // no primary key -- this is deprecated, since we don't *need* this method anymore
  2663. $this->addSetPrimaryKey_NoPK($script);
  2664. }
  2665. }
  2666. /**
  2667. * Adds the setPrimaryKey() method for tables that contain a single-column primary key.
  2668. * @param string &$script The script will be modified in this method.
  2669. */
  2670. protected function addSetPrimaryKey_SinglePK(&$script)
  2671. {
  2672. $pkeys = $this->getTable()->getPrimaryKey();
  2673. $col = $pkeys[0];
  2674. $clo=strtolower($col->getName());
  2675. $ctype = $col->getPhpType();
  2676. $script .= "
  2677. /**
  2678. * Generic method to set the primary key ($clo column).
  2679. *
  2680. * @param $ctype \$key Primary key.
  2681. * @return void
  2682. */
  2683. public function setPrimaryKey(\$key)
  2684. {
  2685. \$this->set".$col->getPhpName()."(\$key);
  2686. }
  2687. ";
  2688. } // addSetPrimaryKey_SinglePK
  2689. /**
  2690. * Adds the setPrimaryKey() method for tables that contain a multi-columnprimary key.
  2691. * @param string &$script The script will be modified in this method.
  2692. */
  2693. protected function addSetPrimaryKey_MultiPK(&$script)
  2694. {
  2695. $script .="
  2696. /**
  2697. * Set the [composite] primary key.
  2698. *
  2699. * @param array \$keys The elements of the composite key (order must match the order in XML file).
  2700. * @return void
  2701. */
  2702. public function setPrimaryKey(\$keys)
  2703. {";
  2704. $i = 0;
  2705. foreach ($this->getTable()->getPrimaryKey() as $pk) {
  2706. $pktype = $pk->getPhpType();
  2707. $script .= "
  2708. \$this->set".$pk->getPhpName()."(\$keys[$i]);";
  2709. $i++;
  2710. } /* foreach ($table->getPrimaryKey() */
  2711. $script .= "
  2712. }
  2713. ";
  2714. } // addSetPrimaryKey_MultiPK
  2715. /**
  2716. * Adds the setPrimaryKey() method for objects that have no primary key.
  2717. * This "feature" is dreprecated, since the setPrimaryKey() method is not required
  2718. * by the Persistent interface (or used by the templates). Hence, this method is also
  2719. * deprecated.
  2720. * @param string &$script The script will be modified in this method.
  2721. * @deprecated
  2722. */
  2723. protected function addSetPrimaryKey_NoPK(&$script)
  2724. {
  2725. $script .="
  2726. /**
  2727. * Dummy primary key setter.
  2728. *
  2729. * This function only exists to preserve backwards compatibility. It is no longer
  2730. * needed or required by the Persistent interface. It will be removed in next BC-breaking
  2731. * release of Propel.
  2732. *
  2733. * @deprecated
  2734. */
  2735. public function setPrimaryKey(\$pk)
  2736. {
  2737. // do nothing, because this object doesn't have any primary keys
  2738. }
  2739. ";
  2740. }
  2741. /**
  2742. * Adds the isPrimaryKeyNull() method
  2743. * @param string &$script The script will be modified in this method.
  2744. */
  2745. protected function addIsPrimaryKeyNull(&$script)
  2746. {
  2747. $table = $this->getTable();
  2748. $pkeys = $table->getPrimaryKey();
  2749. $script .= "
  2750. /**
  2751. * Returns true if the primary key for this object is null.
  2752. * @return boolean
  2753. */
  2754. public function isPrimaryKeyNull()
  2755. {";
  2756. if (count($pkeys) == 1) {
  2757. $script .= "
  2758. return null === \$this->get" . $pkeys[0]->getPhpName() . "();";
  2759. } else {
  2760. $tests = array();
  2761. foreach ($pkeys as $pkey) {
  2762. $tests[]= "(null === \$this->get" . $pkey->getPhpName() . "())";
  2763. }
  2764. $script .= "
  2765. return " . join(' && ', $tests) . ";";
  2766. }
  2767. $script .= "
  2768. }
  2769. ";
  2770. } // addetPrimaryKey_SingleFK
  2771. // --------------------------------------------------------------------
  2772. // Complex OM Methods
  2773. // --------------------------------------------------------------------
  2774. /**
  2775. * Constructs variable name for fkey-related objects.
  2776. * @param ForeignKey $fk
  2777. * @return string
  2778. */
  2779. public function getFKVarName(ForeignKey $fk)
  2780. {
  2781. return 'a' . $this->getFKPhpNameAffix($fk, $plural = false);
  2782. }
  2783. /**
  2784. * Constructs variable name for objects which referencing current table by specified foreign key.
  2785. * @param ForeignKey $fk
  2786. * @return string
  2787. */
  2788. public function getRefFKCollVarName(ForeignKey $fk)
  2789. {
  2790. return 'coll' . $this->getRefFKPhpNameAffix($fk, $plural = true);
  2791. }
  2792. /**
  2793. * Constructs variable name for single object which references current table by specified foreign key
  2794. * which is ALSO a primary key (hence one-to-one relationship).
  2795. * @param ForeignKey $fk
  2796. * @return string
  2797. */
  2798. public function getPKRefFKVarName(ForeignKey $fk)
  2799. {
  2800. return 'single' . $this->getRefFKPhpNameAffix($fk, $plural = false);
  2801. }
  2802. // ----------------------------------------------------------------
  2803. //
  2804. // F K M E T H O D S
  2805. //
  2806. // ----------------------------------------------------------------
  2807. /**
  2808. * Adds the methods that get & set objects related by foreign key to the current object.
  2809. * @param string &$script The script will be modified in this method.
  2810. */
  2811. protected function addFKMethods(&$script)
  2812. {
  2813. foreach ($this->getTable()->getForeignKeys() as $fk) {
  2814. $this->declareClassFromBuilder($this->getNewStubObjectBuilder($fk->getForeignTable()));
  2815. $this->declareClassFromBuilder($this->getNewStubQueryBuilder($fk->getForeignTable()));
  2816. $this->addFKMutator($script, $fk);
  2817. $this->addFKAccessor($script, $fk);
  2818. } // foreach fk
  2819. }
  2820. /**
  2821. * Adds the class attributes that are needed to store fkey related objects.
  2822. * @param string &$script The script will be modified in this method.
  2823. */
  2824. protected function addFKAttributes(&$script, ForeignKey $fk)
  2825. {
  2826. $className = $this->getForeignTable($fk)->getPhpName();
  2827. $varName = $this->getFKVarName($fk);
  2828. $script .= "
  2829. /**
  2830. * @var $className
  2831. */
  2832. protected $".$varName.";
  2833. ";
  2834. }
  2835. /**
  2836. * Adds the mutator (setter) method for setting an fkey related object.
  2837. * @param string &$script The script will be modified in this method.
  2838. */
  2839. protected function addFKMutator(&$script, ForeignKey $fk)
  2840. {
  2841. $table = $this->getTable();
  2842. $tblFK = $this->getForeignTable($fk);
  2843. $joinTableObjectBuilder = $this->getNewObjectBuilder($tblFK);
  2844. $className = $joinTableObjectBuilder->getObjectClassname();
  2845. $varName = $this->getFKVarName($fk);
  2846. $script .= "
  2847. /**
  2848. * Declares an association between this object and a $className object.
  2849. *
  2850. * @param $className \$v
  2851. * @return ".$this->getObjectClassname()." The current object (for fluent API support)
  2852. * @throws PropelException
  2853. */
  2854. public function set".$this->getFKPhpNameAffix($fk, $plural = false)."($className \$v = null)
  2855. {";
  2856. foreach ($fk->getLocalColumns() as $columnName) {
  2857. $column = $table->getColumn($columnName);
  2858. $lfmap = $fk->getLocalForeignMapping();
  2859. $colFKName = $lfmap[$columnName];
  2860. $colFK = $tblFK->getColumn($colFKName);
  2861. $script .= "
  2862. if (\$v === null) {
  2863. \$this->set".$column->getPhpName()."(".$this->getDefaultValueString($column).");
  2864. } else {
  2865. \$this->set".$column->getPhpName()."(\$v->get".$colFK->getPhpName()."());
  2866. }
  2867. ";
  2868. } /* foreach local col */
  2869. $script .= "
  2870. \$this->$varName = \$v;
  2871. ";
  2872. // Now add bi-directional relationship binding, taking into account whether this is
  2873. // a one-to-one relationship.
  2874. if ($fk->isLocalPrimaryKey()) {
  2875. $script .= "
  2876. // Add binding for other direction of this 1:1 relationship.
  2877. if (\$v !== null) {
  2878. \$v->set".$this->getRefFKPhpNameAffix($fk, $plural = false)."(\$this);
  2879. }
  2880. ";
  2881. } else {
  2882. $script .= "
  2883. // Add binding for other direction of this n:n relationship.
  2884. // If this object has already been added to the $className object, it will not be re-added.
  2885. if (\$v !== null) {
  2886. \$v->add".$this->getRefFKPhpNameAffix($fk, $plural = false)."(\$this);
  2887. }
  2888. ";
  2889. }
  2890. $script .= "
  2891. return \$this;
  2892. }
  2893. ";
  2894. }
  2895. /**
  2896. * Adds the accessor (getter) method for getting an fkey related object.
  2897. * @param string &$script The script will be modified in this method.
  2898. */
  2899. protected function addFKAccessor(&$script, ForeignKey $fk)
  2900. {
  2901. $table = $this->getTable();
  2902. $varName = $this->getFKVarName($fk);
  2903. $fkQueryBuilder = $this->getNewStubQueryBuilder($this->getForeignTable($fk));
  2904. $fkObjectBuilder = $this->getNewObjectBuilder($this->getForeignTable($fk))->getStubObjectBuilder();
  2905. $className = $fkObjectBuilder->getClassname(); // get the Classname that has maybe a prefix
  2906. $and = "";
  2907. $conditional = "";
  2908. $localColumns = array(); // foreign key local attributes names
  2909. // If the related columns are a primary key on the foreign table
  2910. // then use retrieveByPk() instead of doSelect() to take advantage
  2911. // of instance pooling
  2912. $useRetrieveByPk = $fk->isForeignPrimaryKey();
  2913. foreach ($fk->getLocalColumns() as $columnName) {
  2914. $lfmap = $fk->getLocalForeignMapping();
  2915. $localColumn = $table->getColumn($columnName);
  2916. $foreignColumn = $fk->getForeignTable()->getColumn($lfmap[$columnName]);
  2917. $column = $table->getColumn($columnName);
  2918. $cptype = $column->getPhpType();
  2919. $clo = strtolower($column->getName());
  2920. $localColumns[$foreignColumn->getPosition()] = '$this->'.$clo;
  2921. if ($cptype == "integer" || $cptype == "float" || $cptype == "double") {
  2922. $conditional .= $and . "\$this->". $clo ." != 0";
  2923. } elseif ($cptype == "string") {
  2924. $conditional .= $and . "(\$this->" . $clo ." !== \"\" && \$this->".$clo." !== null)";
  2925. } else {
  2926. $conditional .= $and . "\$this->" . $clo ." !== null";
  2927. }
  2928. $and = " && ";
  2929. }
  2930. ksort($localColumns); // restoring the order of the foreign PK
  2931. $localColumns = count($localColumns) > 1 ?
  2932. ('array('.implode(', ', $localColumns).')') : reset($localColumns);
  2933. $script .= "
  2934. /**
  2935. * Get the associated $className object
  2936. *
  2937. * @param PropelPDO \$con Optional Connection object.
  2938. * @return $className The associated $className object.
  2939. * @throws PropelException
  2940. */
  2941. public function get".$this->getFKPhpNameAffix($fk, $plural = false)."(PropelPDO \$con = null)
  2942. {";
  2943. $script .= "
  2944. if (\$this->$varName === null && ($conditional)) {";
  2945. if ($useRetrieveByPk) {
  2946. $script .= "
  2947. \$this->$varName = ".$fkQueryBuilder->getClassname()."::create()->findPk($localColumns, \$con);";
  2948. } else {
  2949. $script .= "
  2950. \$this->$varName = ".$fkQueryBuilder->getClassname()."::create()
  2951. ->filterBy" . $this->getRefFKPhpNameAffix($fk, $plural = false) . "(\$this) // here
  2952. ->findOne(\$con);";
  2953. }
  2954. if ($fk->isLocalPrimaryKey()) {
  2955. $script .= "
  2956. // Because this foreign key represents a one-to-one relationship, we will create a bi-directional association.
  2957. \$this->{$varName}->set".$this->getRefFKPhpNameAffix($fk, $plural = false)."(\$this);";
  2958. } else {
  2959. $script .= "
  2960. /* The following can be used additionally to
  2961. guarantee the related object contains a reference
  2962. to this object. This level of coupling may, however, be
  2963. undesirable since it could result in an only partially populated collection
  2964. in the referenced object.
  2965. \$this->{$varName}->add".$this->getRefFKPhpNameAffix($fk, $plural = true)."(\$this);
  2966. */";
  2967. }
  2968. $script .= "
  2969. }
  2970. return \$this->$varName;
  2971. }
  2972. ";
  2973. } // addFKAccessor
  2974. /**
  2975. * Adds a convenience method for setting a related object by specifying the primary key.
  2976. * This can be used in conjunction with the getPrimaryKey() for systems where nothing is known
  2977. * about the actual objects being related.
  2978. * @param string &$script The script will be modified in this method.
  2979. */
  2980. protected function addFKByKeyMutator(&$script, ForeignKey $fk)
  2981. {
  2982. $table = $this->getTable();
  2983. #$className = $this->getForeignTable($fk)->getPhpName();
  2984. $methodAffix = $this->getFKPhpNameAffix($fk);
  2985. #$varName = $this->getFKVarName($fk);
  2986. $script .= "
  2987. /**
  2988. * Provides convenient way to set a relationship based on a
  2989. * key. e.g.
  2990. * <code>\$bar->setFooKey(\$foo->getPrimaryKey())</code>
  2991. *";
  2992. if (count($fk->getLocalColumns()) > 1) {
  2993. $script .= "
  2994. * Note: It is important that the xml schema used to create this class
  2995. * maintains consistency in the order of related columns between
  2996. * ".$table->getName()." and ". $tblFK->getName().".
  2997. * If for some reason this is impossible, this method should be
  2998. * overridden in <code>".$table->getPhpName()."</code>.";
  2999. }
  3000. $script .= "
  3001. * @return ".$this->getObjectClassname()." The current object (for fluent API support)
  3002. * @throws PropelException
  3003. */
  3004. public function set".$methodAffix."Key(\$key)
  3005. {
  3006. ";
  3007. if (count($fk->getLocalColumns()) > 1) {
  3008. $i = 0;
  3009. foreach ($fk->getLocalColumns() as $colName) {
  3010. $col = $table->getColumn($colName);
  3011. $fktype = $col->getPhpType();
  3012. $script .= "
  3013. \$this->set".$col->getPhpName()."( ($fktype) \$key[$i] );
  3014. ";
  3015. $i++;
  3016. } /* foreach */
  3017. } else {
  3018. $lcols = $fk->getLocalColumns();
  3019. $colName = $lcols[0];
  3020. $col = $table->getColumn($colName);
  3021. $fktype = $col->getPhpType();
  3022. $script .= "
  3023. \$this->set".$col->getPhpName()."( ($fktype) \$key);
  3024. ";
  3025. }
  3026. $script .= "
  3027. return \$this;
  3028. }
  3029. ";
  3030. } // addFKByKeyMutator()
  3031. /**
  3032. * Adds the method that fetches fkey-related (referencing) objects but also joins in data from another table.
  3033. * @param string &$script The script will be modified in this method.
  3034. */
  3035. protected function addRefFKGetJoinMethods(&$script, ForeignKey $refFK)
  3036. {
  3037. $table = $this->getTable();
  3038. $tblFK = $refFK->getTable();
  3039. $join_behavior = $this->getGeneratorConfig()->getBuildProperty('useLeftJoinsInDoJoinMethods') ? 'Criteria::LEFT_JOIN' : 'Criteria::INNER_JOIN';
  3040. $peerClassname = $this->getStubPeerBuilder()->getClassname();
  3041. $fkQueryClassname = $this->getNewStubQueryBuilder($refFK->getTable())->getClassname();
  3042. $relCol = $this->getRefFKPhpNameAffix($refFK, $plural=true);
  3043. $collName = $this->getRefFKCollVarName($refFK);
  3044. $fkPeerBuilder = $this->getNewPeerBuilder($tblFK);
  3045. $className = $fkPeerBuilder->getObjectClassname();
  3046. $lastTable = "";
  3047. foreach ($tblFK->getForeignKeys() as $fk2) {
  3048. $tblFK2 = $this->getForeignTable($fk2);
  3049. $doJoinGet = !$tblFK2->isForReferenceOnly();
  3050. // it doesn't make sense to join in rows from the curent table, since we are fetching
  3051. // objects related to *this* table (i.e. the joined rows will all be the same row as current object)
  3052. if ($this->getTable()->getPhpName() == $tblFK2->getPhpName()) {
  3053. $doJoinGet = false;
  3054. }
  3055. $relCol2 = $this->getFKPhpNameAffix($fk2, $plural = false);
  3056. if ( $this->getRelatedBySuffix($refFK) != "" &&
  3057. ($this->getRelatedBySuffix($refFK) == $this->getRelatedBySuffix($fk2))) {
  3058. $doJoinGet = false;
  3059. }
  3060. if ($doJoinGet) {
  3061. $script .= "
  3062. /**
  3063. * If this collection has already been initialized with
  3064. * an identical criteria, it returns the collection.
  3065. * Otherwise if this ".$table->getPhpName()." is new, it will return
  3066. * an empty collection; or if this ".$table->getPhpName()." has previously
  3067. * been saved, it will retrieve related $relCol from storage.
  3068. *
  3069. * This method is protected by default in order to keep the public
  3070. * api reasonable. You can provide public methods for those you
  3071. * actually need in ".$table->getPhpName().".
  3072. *
  3073. * @param Criteria \$criteria optional Criteria object to narrow the query
  3074. * @param PropelPDO \$con optional connection object
  3075. * @param string \$join_behavior optional join type to use (defaults to $join_behavior)
  3076. * @return PropelObjectCollection|{$className}[] List of $className objects
  3077. */
  3078. public function get".$relCol."Join".$relCol2."(\$criteria = null, \$con = null, \$join_behavior = $join_behavior)
  3079. {";
  3080. $script .= "
  3081. \$query = $fkQueryClassname::create(null, \$criteria);
  3082. \$query->joinWith('" . $this->getFKPhpNameAffix($fk2, $plural=false) . "', \$join_behavior);
  3083. return \$this->get". $relCol . "(\$query, \$con);
  3084. }
  3085. ";
  3086. } /* end if ($doJoinGet) */
  3087. } /* end foreach ($tblFK->getForeignKeys() as $fk2) { */
  3088. } // function
  3089. // ----------------------------------------------------------------
  3090. //
  3091. // R E F E R R E R F K M E T H O D S
  3092. //
  3093. // ----------------------------------------------------------------
  3094. /**
  3095. * Adds the attributes used to store objects that have referrer fkey relationships to this object.
  3096. * <code>protected collVarName;</code>
  3097. * <code>private lastVarNameCriteria = null;</code>
  3098. * @param string &$script The script will be modified in this method.
  3099. */
  3100. protected function addRefFKAttributes(&$script, ForeignKey $refFK)
  3101. {
  3102. $joinedTableObjectBuilder = $this->getNewObjectBuilder($refFK->getTable());
  3103. $className = $joinedTableObjectBuilder->getObjectClassname();
  3104. if ($refFK->isLocalPrimaryKey()) {
  3105. $script .= "
  3106. /**
  3107. * @var $className one-to-one related $className object
  3108. */
  3109. protected $".$this->getPKRefFKVarName($refFK).";
  3110. ";
  3111. } else {
  3112. $script .= "
  3113. /**
  3114. * @var PropelObjectCollection|{$className}[] Collection to store aggregation of $className objects.
  3115. */
  3116. protected $".$this->getRefFKCollVarName($refFK).";
  3117. protected $".$this->getRefFKCollVarName($refFK)."Partial;
  3118. ";
  3119. }
  3120. }
  3121. /**
  3122. * Adds the methods for retrieving, initializing, adding objects that are related to this one by foreign keys.
  3123. * @param string &$script The script will be modified in this method.
  3124. */
  3125. protected function addRefFKMethods(&$script)
  3126. {
  3127. if (!$referrers = $this->getTable()->getReferrers()) {
  3128. return;
  3129. }
  3130. $this->addInitRelations($script, $referrers);
  3131. foreach ($referrers as $refFK) {
  3132. $this->declareClassFromBuilder($this->getNewStubObjectBuilder($refFK->getTable()));
  3133. $this->declareClassFromBuilder($this->getNewStubQueryBuilder($refFK->getTable()));
  3134. if ($refFK->isLocalPrimaryKey()) {
  3135. $this->addPKRefFKGet($script, $refFK);
  3136. $this->addPKRefFKSet($script, $refFK);
  3137. } else {
  3138. $this->addRefFKClear($script, $refFK);
  3139. $this->addRefFKPartial($script, $refFK);
  3140. $this->addRefFKInit($script, $refFK);
  3141. $this->addRefFKGet($script, $refFK);
  3142. $this->addRefFKSet($script, $refFK);
  3143. $this->addRefFKCount($script, $refFK);
  3144. $this->addRefFKAdd($script, $refFK);
  3145. $this->addRefFKDoAdd($script, $refFK);
  3146. $this->addRefFKRemove($script, $refFK);
  3147. $this->addRefFKGetJoinMethods($script, $refFK);
  3148. }
  3149. }
  3150. }
  3151. protected function addInitRelations(&$script, $referrers)
  3152. {
  3153. $script .= "
  3154. /**
  3155. * Initializes a collection based on the name of a relation.
  3156. * Avoids crafting an 'init[\$relationName]s' method name
  3157. * that wouldn't work when StandardEnglishPluralizer is used.
  3158. *
  3159. * @param string \$relationName The name of the relation to initialize
  3160. * @return void
  3161. */
  3162. public function initRelation(\$relationName)
  3163. {";
  3164. foreach ($referrers as $refFK) {
  3165. if (!$refFK->isLocalPrimaryKey()) {
  3166. $relationName = $this->getRefFKPhpNameAffix($refFK);
  3167. $relCol = $this->getRefFKPhpNameAffix($refFK, $plural = true);
  3168. $script .= "
  3169. if ('$relationName' == \$relationName) {
  3170. \$this->init$relCol();
  3171. }";
  3172. }
  3173. }
  3174. $script .= "
  3175. }
  3176. ";
  3177. }
  3178. /**
  3179. * Adds the method that clears the referrer fkey collection.
  3180. * @param string &$script The script will be modified in this method.
  3181. */
  3182. protected function addRefFKClear(&$script, ForeignKey $refFK)
  3183. {
  3184. $relCol = $this->getRefFKPhpNameAffix($refFK, $plural = true);
  3185. $collName = $this->getRefFKCollVarName($refFK);
  3186. $script .= "
  3187. /**
  3188. * Clears out the $collName collection
  3189. *
  3190. * This does not modify the database; however, it will remove any associated objects, causing
  3191. * them to be refetched by subsequent calls to accessor method.
  3192. *
  3193. * @return ".$this->getObjectClassname()." The current object (for fluent API support)
  3194. * @see add$relCol()
  3195. */
  3196. public function clear$relCol()
  3197. {
  3198. \$this->$collName = null; // important to set this to null since that means it is uninitialized
  3199. \$this->{$collName}Partial = null;
  3200. return \$this;
  3201. }
  3202. ";
  3203. } // addRefererClear()
  3204. /**
  3205. * Adds the method that clears the referrer fkey collection.
  3206. * @param string &$script The script will be modified in this method.
  3207. */
  3208. protected function addRefFKPartial(&$script, ForeignKey $refFK)
  3209. {
  3210. $relCol = $this->getRefFKPhpNameAffix($refFK, $plural = true);
  3211. $collName = $this->getRefFKCollVarName($refFK);
  3212. $script .= "
  3213. /**
  3214. * reset is the $collName collection loaded partially
  3215. *
  3216. * @return void
  3217. */
  3218. public function resetPartial{$relCol}(\$v = true)
  3219. {
  3220. \$this->{$collName}Partial = \$v;
  3221. }
  3222. ";
  3223. } // addRefFKPartial()
  3224. /**
  3225. * Adds the method that initializes the referrer fkey collection.
  3226. * @param string &$script The script will be modified in this method.
  3227. */
  3228. protected function addRefFKInit(&$script, ForeignKey $refFK)
  3229. {
  3230. $relCol = $this->getRefFKPhpNameAffix($refFK, $plural = true);
  3231. $collName = $this->getRefFKCollVarName($refFK);
  3232. $script .= "
  3233. /**
  3234. * Initializes the $collName collection.
  3235. *
  3236. * By default this just sets the $collName collection to an empty array (like clear$collName());
  3237. * however, you may wish to override this method in your stub class to provide setting appropriate
  3238. * to your application -- for example, setting the initial array to the values stored in database.
  3239. *
  3240. * @param boolean \$overrideExisting If set to true, the method call initializes
  3241. * the collection even if it is not empty
  3242. *
  3243. * @return void
  3244. */
  3245. public function init$relCol(\$overrideExisting = true)
  3246. {
  3247. if (null !== \$this->$collName && !\$overrideExisting) {
  3248. return;
  3249. }
  3250. \$this->$collName = new PropelObjectCollection();
  3251. \$this->{$collName}->setModel('" . $this->getNewStubObjectBuilder($refFK->getTable())->getClassname() . "');
  3252. }
  3253. ";
  3254. } // addRefererInit()
  3255. /**
  3256. * Adds the method that adds an object into the referrer fkey collection.
  3257. * @param string &$script The script will be modified in this method.
  3258. */
  3259. protected function addRefFKAdd(&$script, ForeignKey $refFK)
  3260. {
  3261. $tblFK = $refFK->getTable();
  3262. $joinedTableObjectBuilder = $this->getNewObjectBuilder($refFK->getTable());
  3263. $className = $joinedTableObjectBuilder->getObjectClassname();
  3264. if ($tblFK->getChildrenColumn()) {
  3265. $className = 'Base' . $className;
  3266. $namespace = $joinedTableObjectBuilder->getNamespace();
  3267. $this->declareClass($namespace.'\\'.$className);
  3268. }
  3269. $collName = $this->getRefFKCollVarName($refFK);
  3270. $script .= "
  3271. /**
  3272. * Method called to associate a $className object to this object
  3273. * through the $className foreign key attribute.
  3274. *
  3275. * @param $className \$l $className
  3276. * @return ".$this->getObjectClassname()." The current object (for fluent API support)
  3277. */
  3278. public function add".$this->getRefFKPhpNameAffix($refFK, $plural = false)."($className \$l)
  3279. {
  3280. if (\$this->$collName === null) {
  3281. \$this->init".$this->getRefFKPhpNameAffix($refFK, $plural = true)."();
  3282. \$this->{$collName}Partial = true;
  3283. }
  3284. if (!in_array(\$l, \$this->{$collName}->getArrayCopy(), true)) { // only add it if the **same** object is not already associated
  3285. \$this->doAdd" . $this->getRefFKPhpNameAffix($refFK, $plural = false) . "(\$l);
  3286. }
  3287. return \$this;
  3288. }
  3289. ";
  3290. } // addRefererAdd
  3291. /**
  3292. * Adds the method that returns the size of the referrer fkey collection.
  3293. * @param string &$script The script will be modified in this method.
  3294. */
  3295. protected function addRefFKCount(&$script, ForeignKey $refFK)
  3296. {
  3297. $table = $this->getTable();
  3298. $tblFK = $refFK->getTable();
  3299. $peerClassname = $this->getStubPeerBuilder()->getClassname();
  3300. $fkQueryClassname = $this->getNewStubQueryBuilder($refFK->getTable())->getClassname();
  3301. $relCol = $this->getRefFKPhpNameAffix($refFK, $plural = true);
  3302. $collName = $this->getRefFKCollVarName($refFK);
  3303. $joinedTableObjectBuilder = $this->getNewObjectBuilder($refFK->getTable());
  3304. $className = $joinedTableObjectBuilder->getObjectClassname();
  3305. $script .= "
  3306. /**
  3307. * Returns the number of related $className objects.
  3308. *
  3309. * @param Criteria \$criteria
  3310. * @param boolean \$distinct
  3311. * @param PropelPDO \$con
  3312. * @return int Count of related $className objects.
  3313. * @throws PropelException
  3314. */
  3315. public function count$relCol(Criteria \$criteria = null, \$distinct = false, PropelPDO \$con = null)
  3316. {
  3317. \$partial = \$this->{$collName}Partial && !\$this->isNew();
  3318. if (null === \$this->$collName || null !== \$criteria || \$partial) {
  3319. if (\$this->isNew() && null === \$this->$collName) {
  3320. return 0;
  3321. } else {
  3322. if(\$partial && !\$criteria) {
  3323. return count(\$this->get$relCol());
  3324. }
  3325. \$query = $fkQueryClassname::create(null, \$criteria);
  3326. if (\$distinct) {
  3327. \$query->distinct();
  3328. }
  3329. return \$query
  3330. ->filterBy" . $this->getFKPhpNameAffix($refFK) . "(\$this)
  3331. ->count(\$con);
  3332. }
  3333. } else {
  3334. return count(\$this->$collName);
  3335. }
  3336. }
  3337. ";
  3338. } // addRefererCount
  3339. /**
  3340. * Adds the method that returns the referrer fkey collection.
  3341. * @param string &$script The script will be modified in this method.
  3342. */
  3343. protected function addRefFKGet(&$script, ForeignKey $refFK)
  3344. {
  3345. $table = $this->getTable();
  3346. $tblFK = $refFK->getTable();
  3347. $peerClassname = $this->getStubPeerBuilder()->getClassname();
  3348. $fkQueryClassname = $this->getNewStubQueryBuilder($refFK->getTable())->getClassname();
  3349. $relCol = $this->getRefFKPhpNameAffix($refFK, $plural = true);
  3350. $collName = $this->getRefFKCollVarName($refFK);
  3351. $joinedTableObjectBuilder = $this->getNewObjectBuilder($refFK->getTable());
  3352. $className = $joinedTableObjectBuilder->getObjectClassname();
  3353. $script .= "
  3354. /**
  3355. * Gets an array of $className objects which contain a foreign key that references this object.
  3356. *
  3357. * If the \$criteria is not null, it is used to always fetch the results from the database.
  3358. * Otherwise the results are fetched from the database the first time, then cached.
  3359. * Next time the same method is called without \$criteria, the cached collection is returned.
  3360. * If this ".$this->getObjectClassname()." is new, it will return
  3361. * an empty collection or the current collection; the criteria is ignored on a new object.
  3362. *
  3363. * @param Criteria \$criteria optional Criteria object to narrow the query
  3364. * @param PropelPDO \$con optional connection object
  3365. * @return PropelObjectCollection|{$className}[] List of $className objects
  3366. * @throws PropelException
  3367. */
  3368. public function get$relCol(\$criteria = null, PropelPDO \$con = null)
  3369. {
  3370. \$partial = \$this->{$collName}Partial && !\$this->isNew();
  3371. if (null === \$this->$collName || null !== \$criteria || \$partial) {
  3372. if (\$this->isNew() && null === \$this->$collName) {
  3373. // return empty collection
  3374. \$this->init".$this->getRefFKPhpNameAffix($refFK, $plural = true)."();
  3375. } else {
  3376. \$$collName = $fkQueryClassname::create(null, \$criteria)
  3377. ->filterBy" . $this->getFKPhpNameAffix($refFK) . "(\$this)
  3378. ->find(\$con);
  3379. if (null !== \$criteria) {
  3380. if (false !== \$this->{$collName}Partial && count(\$$collName)) {
  3381. \$this->init".$this->getRefFKPhpNameAffix($refFK, $plural = true)."(false);
  3382. foreach(\$$collName as \$obj) {
  3383. if (false == \$this->{$collName}->contains(\$obj)) {
  3384. \$this->{$collName}->append(\$obj);
  3385. }
  3386. }
  3387. \$this->{$collName}Partial = true;
  3388. }
  3389. return \$$collName;
  3390. }
  3391. if(\$partial && \$this->$collName) {
  3392. foreach(\$this->$collName as \$obj) {
  3393. if(\$obj->isNew()) {
  3394. \${$collName}[] = \$obj;
  3395. }
  3396. }
  3397. }
  3398. \$this->$collName = \$$collName;
  3399. \$this->{$collName}Partial = false;
  3400. }
  3401. }
  3402. return \$this->$collName;
  3403. }
  3404. ";
  3405. } // addRefererGet()
  3406. protected function addRefFKSet(&$script, $refFK)
  3407. {
  3408. $relatedName = $this->getRefFKPhpNameAffix($refFK, $plural = true);
  3409. $relatedObjectClassName = $this->getRefFKPhpNameAffix($refFK, $plural = false);
  3410. // No lcfirst() in PHP < 5.3
  3411. $inputCollection = $relatedName;
  3412. $inputCollection[0] = strtolower($inputCollection[0]);
  3413. // No lcfirst() in PHP < 5.3
  3414. $inputCollectionEntry = $this->getRefFKPhpNameAffix($refFK, $plural = false);
  3415. $inputCollectionEntry[0] = strtolower($inputCollectionEntry[0]);
  3416. $collName = $this->getRefFKCollVarName($refFK);
  3417. $relCol = $this->getFKPhpNameAffix($refFK, $plural = false);
  3418. $script .= "
  3419. /**
  3420. * Sets a collection of $relatedObjectClassName objects related by a one-to-many relationship
  3421. * to the current object.
  3422. * It will also schedule objects for deletion based on a diff between old objects (aka persisted)
  3423. * and new objects from the given Propel collection.
  3424. *
  3425. * @param PropelCollection \${$inputCollection} A Propel collection.
  3426. * @param PropelPDO \$con Optional connection object
  3427. * @return ".$this->getObjectClassname()." The current object (for fluent API support)
  3428. */
  3429. public function set{$relatedName}(PropelCollection \${$inputCollection}, PropelPDO \$con = null)
  3430. {
  3431. \$this->{$inputCollection}ScheduledForDeletion = \$this->get{$relatedName}(new Criteria(), \$con)->diff(\${$inputCollection});
  3432. foreach (\$this->{$inputCollection}ScheduledForDeletion as \${$inputCollectionEntry}Removed) {
  3433. \${$inputCollectionEntry}Removed->set{$relCol}(null);
  3434. }
  3435. \$this->{$collName} = null;
  3436. foreach (\${$inputCollection} as \${$inputCollectionEntry}) {
  3437. \$this->add{$relatedObjectClassName}(\${$inputCollectionEntry});
  3438. }
  3439. \$this->{$collName} = \${$inputCollection};
  3440. \$this->{$collName}Partial = false;
  3441. return \$this;
  3442. }
  3443. ";
  3444. }
  3445. /**
  3446. * @param string &$script The script will be modified in this method.
  3447. * @param ForeignKey $refFK
  3448. * @param ForeignKey $crossFK
  3449. */
  3450. protected function addRefFKDoAdd(&$script, $refFK)
  3451. {
  3452. $relatedObjectClassName = $this->getRefFKPhpNameAffix($refFK, $plural = false);
  3453. // lcfirst() doesn't exist in PHP < 5.3
  3454. $lowerRelatedObjectClassName = $relatedObjectClassName;
  3455. $lowerRelatedObjectClassName[0] = strtolower($lowerRelatedObjectClassName[0]);
  3456. $collName = $this->getRefFKCollVarName($refFK);
  3457. $script .= "
  3458. /**
  3459. * @param {$relatedObjectClassName} \${$lowerRelatedObjectClassName} The $lowerRelatedObjectClassName object to add.
  3460. */
  3461. protected function doAdd{$relatedObjectClassName}(\${$lowerRelatedObjectClassName})
  3462. {
  3463. \$this->{$collName}[]= \${$lowerRelatedObjectClassName};
  3464. \${$lowerRelatedObjectClassName}->set" . $this->getFKPhpNameAffix($refFK, $plural = false)."(\$this);
  3465. }
  3466. ";
  3467. }
  3468. /**
  3469. * @param string &$script The script will be modified in this method.
  3470. * @param ForeignKey $refFK
  3471. * @param ForeignKey $crossFK
  3472. */
  3473. protected function addRefFKRemove(&$script, $refFK)
  3474. {
  3475. $relatedName = $this->getRefFKPhpNameAffix($refFK, $plural = true);
  3476. $relatedObjectClassName = $this->getRefFKPhpNameAffix($refFK, $plural = false);
  3477. // No lcfirst() in PHP < 5.3
  3478. $inputCollection = $relatedName . 'ScheduledForDeletion';
  3479. $inputCollection[0] = strtolower($inputCollection[0]);
  3480. // lcfirst() doesn't exist in PHP < 5.3
  3481. $lowerRelatedObjectClassName = $relatedObjectClassName;
  3482. $lowerRelatedObjectClassName[0] = strtolower($lowerRelatedObjectClassName[0]);
  3483. $collName = $this->getRefFKCollVarName($refFK);
  3484. $relCol = $this->getFKPhpNameAffix($refFK, $plural = false);
  3485. $script .= "
  3486. /**
  3487. * @param {$relatedObjectClassName} \${$lowerRelatedObjectClassName} The $lowerRelatedObjectClassName object to remove.
  3488. * @return ".$this->getObjectClassname()." The current object (for fluent API support)
  3489. */
  3490. public function remove{$relatedObjectClassName}(\${$lowerRelatedObjectClassName})
  3491. {
  3492. if (\$this->get{$relatedName}()->contains(\${$lowerRelatedObjectClassName})) {
  3493. \$this->{$collName}->remove(\$this->{$collName}->search(\${$lowerRelatedObjectClassName}));
  3494. if (null === \$this->{$inputCollection}) {
  3495. \$this->{$inputCollection} = clone \$this->{$collName};
  3496. \$this->{$inputCollection}->clear();
  3497. }
  3498. \$this->{$inputCollection}[]= \${$lowerRelatedObjectClassName};
  3499. \${$lowerRelatedObjectClassName}->set{$relCol}(null);
  3500. }
  3501. return \$this;
  3502. }
  3503. ";
  3504. }
  3505. /**
  3506. * Adds the method that gets a one-to-one related referrer fkey.
  3507. * This is for one-to-one relationship special case.
  3508. * @param string &$script The script will be modified in this method.
  3509. */
  3510. protected function addPKRefFKGet(&$script, ForeignKey $refFK)
  3511. {
  3512. $table = $this->getTable();
  3513. $tblFK = $refFK->getTable();
  3514. $joinedTableObjectBuilder = $this->getNewObjectBuilder($refFK->getTable());
  3515. $className = $joinedTableObjectBuilder->getObjectClassname();
  3516. $queryClassname = $this->getNewStubQueryBuilder($refFK->getTable())->getClassname();
  3517. $varName = $this->getPKRefFKVarName($refFK);
  3518. $script .= "
  3519. /**
  3520. * Gets a single $className object, which is related to this object by a one-to-one relationship.
  3521. *
  3522. * @param PropelPDO \$con optional connection object
  3523. * @return $className
  3524. * @throws PropelException
  3525. */
  3526. public function get".$this->getRefFKPhpNameAffix($refFK, $plural = false)."(PropelPDO \$con = null)
  3527. {
  3528. ";
  3529. $script .= "
  3530. if (\$this->$varName === null && !\$this->isNew()) {
  3531. \$this->$varName = $queryClassname::create()->findPk(\$this->getPrimaryKey(), \$con);
  3532. }
  3533. return \$this->$varName;
  3534. }
  3535. ";
  3536. } // addPKRefFKGet()
  3537. /**
  3538. * Adds the method that sets a one-to-one related referrer fkey.
  3539. * This is for one-to-one relationships special case.
  3540. * @param string &$script The script will be modified in this method.
  3541. * @param ForeignKey $refFK The referencing foreign key.
  3542. */
  3543. protected function addPKRefFKSet(&$script, ForeignKey $refFK)
  3544. {
  3545. $tblFK = $refFK->getTable();
  3546. $joinedTableObjectBuilder = $this->getNewObjectBuilder($refFK->getTable());
  3547. $className = $joinedTableObjectBuilder->getObjectClassname();
  3548. $varName = $this->getPKRefFKVarName($refFK);
  3549. $script .= "
  3550. /**
  3551. * Sets a single $className object as related to this object by a one-to-one relationship.
  3552. *
  3553. * @param $className \$v $className
  3554. * @return ".$this->getObjectClassname()." The current object (for fluent API support)
  3555. * @throws PropelException
  3556. */
  3557. public function set".$this->getRefFKPhpNameAffix($refFK, $plural = false)."($className \$v = null)
  3558. {
  3559. \$this->$varName = \$v;
  3560. // Make sure that that the passed-in $className isn't already associated with this object
  3561. if (\$v !== null && \$v->get".$this->getFKPhpNameAffix($refFK, $plural = false)."() === null) {
  3562. \$v->set".$this->getFKPhpNameAffix($refFK, $plural = false)."(\$this);
  3563. }
  3564. return \$this;
  3565. }
  3566. ";
  3567. } // addPKRefFKSet
  3568. protected function addCrossFKAttributes(&$script, ForeignKey $crossFK)
  3569. {
  3570. $joinedTableObjectBuilder = $this->getNewObjectBuilder($crossFK->getForeignTable());
  3571. $className = $joinedTableObjectBuilder->getObjectClassname();
  3572. $relatedName = $this->getFKPhpNameAffix($crossFK, $plural = true);
  3573. $script .= "
  3574. /**
  3575. * @var PropelObjectCollection|{$className}[] Collection to store aggregation of $className objects.
  3576. */
  3577. protected $" . $this->getCrossFKVarName($crossFK) . ";
  3578. ";
  3579. }
  3580. protected function addScheduledForDeletionAttribute(&$script, $fkName)
  3581. {
  3582. // No lcfirst() in PHP < 5.3
  3583. $fkName[0] = strtolower($fkName[0]);
  3584. $script .= "
  3585. /**
  3586. * An array of objects scheduled for deletion.
  3587. * @var PropelObjectCollection
  3588. */
  3589. protected \${$fkName}ScheduledForDeletion = null;
  3590. ";
  3591. }
  3592. protected function addCrossFkScheduledForDeletion(&$script, $refFK, $crossFK)
  3593. {
  3594. $queryClassName = $this->getRefFKPhpNameAffix($refFK, $plural = false) . 'Query';
  3595. $relatedName = $this->getFKPhpNameAffix($crossFK, $plural = true);
  3596. // No lcfirst() in PHP < 5.3
  3597. $lowerRelatedName = $relatedName;
  3598. $lowerRelatedName[0] = strtolower($lowerRelatedName[0]);
  3599. // No lcfirst() in PHP < 5.3
  3600. $lowerSingleRelatedName = $this->getFKPhpNameAffix($crossFK, $plural = false);
  3601. $lowerSingleRelatedName[0] = strtolower($lowerSingleRelatedName[0]);
  3602. $middelFks = $refFK->getTable()->getForeignKeys();
  3603. $isFirstPk = ($middelFks[0]->getForeignTableCommonName() == $this->getTable()->getCommonName());
  3604. $script .= "
  3605. if (\$this->{$lowerRelatedName}ScheduledForDeletion !== null) {
  3606. if (!\$this->{$lowerRelatedName}ScheduledForDeletion->isEmpty()) {
  3607. \$pks = array();
  3608. \$pk = \$this->getPrimaryKey();
  3609. foreach (\$this->{$lowerRelatedName}ScheduledForDeletion->getPrimaryKeys(false) as \$remotePk) {";
  3610. if ($isFirstPk) {
  3611. $script .= "
  3612. \$pks[] = array(\$pk, \$remotePk);";
  3613. } else {
  3614. $script .= "
  3615. \$pks[] = array(\$remotePk, \$pk);";
  3616. }
  3617. $script .= "
  3618. }
  3619. $queryClassName::create()
  3620. ->filterByPrimaryKeys(\$pks)
  3621. ->delete(\$con);
  3622. \$this->{$lowerRelatedName}ScheduledForDeletion = null;
  3623. }
  3624. foreach (\$this->get{$relatedName}() as \${$lowerSingleRelatedName}) {
  3625. if (\${$lowerSingleRelatedName}->isModified()) {
  3626. \${$lowerSingleRelatedName}->save(\$con);
  3627. }
  3628. }
  3629. }
  3630. ";
  3631. }
  3632. protected function addRefFkScheduledForDeletion(&$script, $refFK)
  3633. {
  3634. $relatedName = $this->getRefFKPhpNameAffix($refFK, $plural = true);
  3635. // No lcfirst() in PHP < 5.3
  3636. $lowerRelatedName = $relatedName;
  3637. $lowerRelatedName[0] = strtolower($lowerRelatedName[0]);
  3638. // No lcfirst() in PHP < 5.3
  3639. $lowerSingleRelatedName = $this->getRefFKPhpNameAffix($refFK, $plural = false);
  3640. $lowerSingleRelatedName[0] = strtolower($lowerSingleRelatedName[0]);
  3641. $queryClassName = $this->getNewStubQueryBuilder($refFK->getTable())->getClassname();
  3642. $localColumn = $refFK->getLocalColumn();
  3643. $script .= "
  3644. if (\$this->{$lowerRelatedName}ScheduledForDeletion !== null) {
  3645. if (!\$this->{$lowerRelatedName}ScheduledForDeletion->isEmpty()) {";
  3646. if (!$refFK->isComposite() && !$localColumn->isNotNull()) {
  3647. $script .= "
  3648. foreach (\$this->{$lowerRelatedName}ScheduledForDeletion as \${$lowerSingleRelatedName}) {
  3649. // need to save related object because we set the relation to null
  3650. \${$lowerSingleRelatedName}->save(\$con);
  3651. }";
  3652. } else {
  3653. $script .= "
  3654. $queryClassName::create()
  3655. ->filterByPrimaryKeys(\$this->{$lowerRelatedName}ScheduledForDeletion->getPrimaryKeys(false))
  3656. ->delete(\$con);";
  3657. }
  3658. $script .= "
  3659. \$this->{$lowerRelatedName}ScheduledForDeletion = null;
  3660. }
  3661. }
  3662. ";
  3663. }
  3664. protected function getCrossFKVarName(ForeignKey $crossFK)
  3665. {
  3666. return 'coll' . $this->getFKPhpNameAffix($crossFK, $plural = true);
  3667. }
  3668. protected function addCrossFKMethods(&$script)
  3669. {
  3670. foreach ($this->getTable()->getCrossFks() as $fkList) {
  3671. list($refFK, $crossFK) = $fkList;
  3672. $this->declareClassFromBuilder($this->getNewStubObjectBuilder($crossFK->getForeignTable()));
  3673. $this->declareClassFromBuilder($this->getNewStubQueryBuilder($crossFK->getForeignTable()));
  3674. $this->addCrossFKClear($script, $crossFK);
  3675. $this->addCrossFKInit($script, $crossFK);
  3676. $this->addCrossFKGet($script, $refFK, $crossFK);
  3677. $this->addCrossFKSet($script, $refFK, $crossFK);
  3678. $this->addCrossFKCount($script, $refFK, $crossFK);
  3679. $this->addCrossFKAdd($script, $refFK, $crossFK);
  3680. $this->addCrossFKDoAdd($script, $refFK, $crossFK);
  3681. $this->addCrossFKRemove($script, $refFK, $crossFK);
  3682. }
  3683. }
  3684. /**
  3685. * Adds the method that clears the referrer fkey collection.
  3686. * @param string &$script The script will be modified in this method.
  3687. */
  3688. protected function addCrossFKClear(&$script, ForeignKey $crossFK)
  3689. {
  3690. $relCol = $this->getFKPhpNameAffix($crossFK, $plural = true);
  3691. $collName = $this->getCrossFKVarName($crossFK);
  3692. $script .= "
  3693. /**
  3694. * Clears out the $collName collection
  3695. *
  3696. * This does not modify the database; however, it will remove any associated objects, causing
  3697. * them to be refetched by subsequent calls to accessor method.
  3698. *
  3699. * @return ".$this->getObjectClassname()." The current object (for fluent API support)
  3700. * @see add$relCol()
  3701. */
  3702. public function clear$relCol()
  3703. {
  3704. \$this->$collName = null; // important to set this to null since that means it is uninitialized
  3705. \$this->{$collName}Partial = null;
  3706. return \$this;
  3707. }
  3708. ";
  3709. } // addRefererClear()
  3710. /**
  3711. * Adds the method that initializes the referrer fkey collection.
  3712. * @param string &$script The script will be modified in this method.
  3713. */
  3714. protected function addCrossFKInit(&$script, ForeignKey $crossFK)
  3715. {
  3716. $relCol = $this->getFKPhpNameAffix($crossFK, $plural = true);
  3717. $collName = $this->getCrossFKVarName($crossFK);
  3718. $relatedObjectClassName = $this->getNewStubObjectBuilder($crossFK->getForeignTable())->getClassname();
  3719. $script .= "
  3720. /**
  3721. * Initializes the $collName collection.
  3722. *
  3723. * By default this just sets the $collName collection to an empty collection (like clear$relCol());
  3724. * however, you may wish to override this method in your stub class to provide setting appropriate
  3725. * to your application -- for example, setting the initial array to the values stored in database.
  3726. *
  3727. * @return void
  3728. */
  3729. public function init$relCol()
  3730. {
  3731. \$this->$collName = new PropelObjectCollection();
  3732. \$this->{$collName}->setModel('$relatedObjectClassName');
  3733. }
  3734. ";
  3735. }
  3736. protected function addCrossFKGet(&$script, $refFK, $crossFK)
  3737. {
  3738. $relatedName = $this->getFKPhpNameAffix($crossFK, $plural = true);
  3739. $relatedObjectClassName = $this->getNewStubObjectBuilder($crossFK->getForeignTable())->getClassname();
  3740. $selfRelationName = $this->getFKPhpNameAffix($refFK, $plural = false);
  3741. $relatedQueryClassName = $this->getNewStubQueryBuilder($crossFK->getForeignTable())->getClassname();
  3742. $crossRefTableName = $crossFK->getTableName();
  3743. $collName = $this->getCrossFKVarName($crossFK);
  3744. $script .= "
  3745. /**
  3746. * Gets a collection of $relatedObjectClassName objects related by a many-to-many relationship
  3747. * to the current object by way of the $crossRefTableName cross-reference table.
  3748. *
  3749. * If the \$criteria is not null, it is used to always fetch the results from the database.
  3750. * Otherwise the results are fetched from the database the first time, then cached.
  3751. * Next time the same method is called without \$criteria, the cached collection is returned.
  3752. * If this ".$this->getObjectClassname()." is new, it will return
  3753. * an empty collection or the current collection; the criteria is ignored on a new object.
  3754. *
  3755. * @param Criteria \$criteria Optional query object to filter the query
  3756. * @param PropelPDO \$con Optional connection object
  3757. *
  3758. * @return PropelObjectCollection|{$relatedObjectClassName}[] List of {$relatedObjectClassName} objects
  3759. */
  3760. public function get{$relatedName}(\$criteria = null, PropelPDO \$con = null)
  3761. {
  3762. if (null === \$this->$collName || null !== \$criteria) {
  3763. if (\$this->isNew() && null === \$this->$collName) {
  3764. // return empty collection
  3765. \$this->init{$relatedName}();
  3766. } else {
  3767. \$$collName = $relatedQueryClassName::create(null, \$criteria)
  3768. ->filterBy{$selfRelationName}(\$this)
  3769. ->find(\$con);
  3770. if (null !== \$criteria) {
  3771. return \$$collName;
  3772. }
  3773. \$this->$collName = \$$collName;
  3774. }
  3775. }
  3776. return \$this->$collName;
  3777. }
  3778. ";
  3779. }
  3780. protected function addCrossFKSet(&$script, $refFK, $crossFK)
  3781. {
  3782. $relatedNamePlural = $this->getFKPhpNameAffix($crossFK, $plural = true);
  3783. $relatedName = $this->getFKPhpNameAffix($crossFK, $plural = false);
  3784. $relatedObjectClassName = $this->getNewStubObjectBuilder($crossFK->getForeignTable())->getClassname();
  3785. $crossRefTableName = $crossFK->getTableName();
  3786. $collName = $this->getCrossFKVarName($crossFK);
  3787. // No lcfirst() in PHP < 5.3
  3788. $inputCollection = $relatedNamePlural;
  3789. $inputCollection[0] = strtolower($inputCollection[0]);
  3790. // No lcfirst() in PHP < 5.3
  3791. $inputCollectionEntry = $this->getFKPhpNameAffix($crossFK, $plural = false);
  3792. $inputCollectionEntry[0] = strtolower($inputCollectionEntry[0]);
  3793. $script .= "
  3794. /**
  3795. * Sets a collection of $relatedObjectClassName objects related by a many-to-many relationship
  3796. * to the current object by way of the $crossRefTableName cross-reference table.
  3797. * It will also schedule objects for deletion based on a diff between old objects (aka persisted)
  3798. * and new objects from the given Propel collection.
  3799. *
  3800. * @param PropelCollection \${$inputCollection} A Propel collection.
  3801. * @param PropelPDO \$con Optional connection object
  3802. * @return ".$this->getObjectClassname()." The current object (for fluent API support)
  3803. */
  3804. public function set{$relatedNamePlural}(PropelCollection \${$inputCollection}, PropelPDO \$con = null)
  3805. {
  3806. \$this->clear{$relatedNamePlural}();
  3807. \$current{$relatedNamePlural} = \$this->get{$relatedNamePlural}();
  3808. \$this->{$inputCollection}ScheduledForDeletion = \$current{$relatedNamePlural}->diff(\${$inputCollection});
  3809. foreach (\${$inputCollection} as \${$inputCollectionEntry}) {
  3810. if (!\$current{$relatedNamePlural}->contains(\${$inputCollectionEntry})) {
  3811. \$this->doAdd{$relatedName}(\${$inputCollectionEntry});
  3812. }
  3813. }
  3814. \$this->$collName = \${$inputCollection};
  3815. return \$this;
  3816. }
  3817. ";
  3818. }
  3819. protected function addCrossFKCount(&$script, $refFK, $crossFK)
  3820. {
  3821. $relatedName = $this->getFKPhpNameAffix($crossFK, $plural = true);
  3822. $relatedObjectClassName = $this->getNewStubObjectBuilder($crossFK->getForeignTable())->getClassname();
  3823. $selfRelationName = $this->getFKPhpNameAffix($refFK, $plural = false);
  3824. $relatedQueryClassName = $this->getNewStubQueryBuilder($crossFK->getForeignTable())->getClassname();
  3825. $crossRefTableName = $refFK->getTableName();
  3826. $collName = $this->getCrossFKVarName($crossFK);
  3827. $script .= "
  3828. /**
  3829. * Gets the number of $relatedObjectClassName objects related by a many-to-many relationship
  3830. * to the current object by way of the $crossRefTableName cross-reference table.
  3831. *
  3832. * @param Criteria \$criteria Optional query object to filter the query
  3833. * @param boolean \$distinct Set to true to force count distinct
  3834. * @param PropelPDO \$con Optional connection object
  3835. *
  3836. * @return int the number of related $relatedObjectClassName objects
  3837. */
  3838. public function count{$relatedName}(\$criteria = null, \$distinct = false, PropelPDO \$con = null)
  3839. {
  3840. if (null === \$this->$collName || null !== \$criteria) {
  3841. if (\$this->isNew() && null === \$this->$collName) {
  3842. return 0;
  3843. } else {
  3844. \$query = $relatedQueryClassName::create(null, \$criteria);
  3845. if (\$distinct) {
  3846. \$query->distinct();
  3847. }
  3848. return \$query
  3849. ->filterBy{$selfRelationName}(\$this)
  3850. ->count(\$con);
  3851. }
  3852. } else {
  3853. return count(\$this->$collName);
  3854. }
  3855. }
  3856. ";
  3857. }
  3858. /**
  3859. * Adds the method that adds an object into the referrer fkey collection.
  3860. * @param string &$script The script will be modified in this method.
  3861. */
  3862. protected function addCrossFKAdd(&$script, ForeignKey $refFK, ForeignKey $crossFK)
  3863. {
  3864. $relCol = $this->getFKPhpNameAffix($crossFK, $plural = true);
  3865. $collName = $this->getCrossFKVarName($crossFK);
  3866. $tblFK = $refFK->getTable();
  3867. $joinedTableObjectBuilder = $this->getNewObjectBuilder($refFK->getTable());
  3868. $className = $joinedTableObjectBuilder->getObjectClassname();
  3869. $crossObjectName = '$' . $crossFK->getForeignTable()->getStudlyPhpName();
  3870. $crossObjectClassName = $this->getNewObjectBuilder($crossFK->getForeignTable())->getObjectClassname();
  3871. $relatedObjectClassName = $this->getFKPhpNameAffix($crossFK, $plural = false);
  3872. $script .= "
  3873. /**
  3874. * Associate a " . $crossObjectClassName . " object to this object
  3875. * through the " . $tblFK->getName() . " cross reference table.
  3876. *
  3877. * @param " . $crossObjectClassName . " " . $crossObjectName . " The $className object to relate
  3878. * @return ".$this->getObjectClassname()." The current object (for fluent API support)
  3879. */
  3880. public function add{$relatedObjectClassName}($crossObjectClassName $crossObjectName)
  3881. {
  3882. if (\$this->" . $collName . " === null) {
  3883. \$this->init" . $relCol . "();
  3884. }
  3885. if (!\$this->" . $collName . "->contains(" . $crossObjectName . ")) { // only add it if the **same** object is not already associated
  3886. \$this->doAdd{$relatedObjectClassName}($crossObjectName);
  3887. \$this->" . $collName . "[]= " . $crossObjectName . ";
  3888. }
  3889. return \$this;
  3890. }
  3891. ";
  3892. }
  3893. /**
  3894. * @param string &$script The script will be modified in this method.
  3895. * @param ForeignKey $refFK
  3896. * @param ForeignKey $crossFK
  3897. */
  3898. protected function addCrossFKDoAdd(&$script, ForeignKey $refFK, ForeignKey $crossFK)
  3899. {
  3900. $relatedObjectClassName = $this->getFKPhpNameAffix($crossFK, $plural = false);
  3901. // lcfirst() doesn't exist in PHP < 5.3
  3902. $lowerRelatedObjectClassName = $relatedObjectClassName;
  3903. $lowerRelatedObjectClassName[0] = strtolower($lowerRelatedObjectClassName[0]);
  3904. $joinedTableObjectBuilder = $this->getNewObjectBuilder($refFK->getTable());
  3905. $className = $joinedTableObjectBuilder->getObjectClassname();
  3906. $refKObjectClassName = $this->getRefFKPhpNameAffix($refFK, $plural = false);
  3907. $tblFK = $refFK->getTable();
  3908. $foreignObjectName = '$' . $tblFK->getStudlyPhpName();
  3909. $script .= "
  3910. /**
  3911. * @param {$relatedObjectClassName} \${$lowerRelatedObjectClassName} The $lowerRelatedObjectClassName object to add.
  3912. */
  3913. protected function doAdd{$relatedObjectClassName}(\${$lowerRelatedObjectClassName})
  3914. {
  3915. {$foreignObjectName} = new {$className}();
  3916. {$foreignObjectName}->set{$relatedObjectClassName}(\${$lowerRelatedObjectClassName});
  3917. \$this->add{$refKObjectClassName}({$foreignObjectName});
  3918. }
  3919. ";
  3920. }
  3921. /**
  3922. * Adds the method that remove an object from the referrer fkey collection.
  3923. * @param string $script The script will be modified in this method.
  3924. */
  3925. protected function addCrossFKRemove(&$script, ForeignKey $refFK, ForeignKey $crossFK)
  3926. {
  3927. $relCol = $this->getFKPhpNameAffix($crossFK, $plural = true);
  3928. $collName = 'coll' . $relCol;
  3929. $tblFK = $refFK->getTable();
  3930. $joinedTableObjectBuilder = $this->getNewObjectBuilder($refFK->getTable());
  3931. $className = $joinedTableObjectBuilder->getObjectClassname();
  3932. $lowerRelCol = $relCol;
  3933. $lowerRelCol[0] = strtolower($lowerRelCol[0]);
  3934. $M2MScheduledForDeletion = $lowerRelCol . "ScheduledForDeletion";
  3935. $crossObjectName = '$' . $crossFK->getForeignTable()->getStudlyPhpName();
  3936. $crossObjectClassName = $this->getNewObjectBuilder($crossFK->getForeignTable())->getObjectClassname();
  3937. $relatedObjectClassName = $this->getFKPhpNameAffix($crossFK, $plural = false);
  3938. $script .= "
  3939. /**
  3940. * Remove a {$crossObjectClassName} object to this object
  3941. * through the {$tblFK->getName()} cross reference table.
  3942. *
  3943. * @param {$crossObjectClassName} {$crossObjectName} The $className object to relate
  3944. * @return ".$this->getObjectClassname()." The current object (for fluent API support)
  3945. */
  3946. public function remove{$relatedObjectClassName}($crossObjectClassName $crossObjectName)
  3947. {
  3948. if (\$this->get{$relCol}()->contains({$crossObjectName})) {
  3949. \$this->{$collName}->remove(\$this->{$collName}->search({$crossObjectName}));
  3950. if (null === \$this->{$M2MScheduledForDeletion}) {
  3951. \$this->{$M2MScheduledForDeletion} = clone \$this->{$collName};
  3952. \$this->{$M2MScheduledForDeletion}->clear();
  3953. }
  3954. \$this->{$M2MScheduledForDeletion}[]= {$crossObjectName};
  3955. }
  3956. return \$this;
  3957. }
  3958. ";
  3959. }
  3960. // ----------------------------------------------------------------
  3961. //
  3962. // M A N I P U L A T I O N M E T H O D S
  3963. //
  3964. // ----------------------------------------------------------------
  3965. /**
  3966. * Adds the workhourse doSave() method.
  3967. * @param string &$script The script will be modified in this method.
  3968. */
  3969. protected function addDoSave(&$script)
  3970. {
  3971. $table = $this->getTable();
  3972. $reloadOnUpdate = $table->isReloadOnUpdate();
  3973. $reloadOnInsert = $table->isReloadOnInsert();
  3974. $script .= "
  3975. /**
  3976. * Performs the work of inserting or updating the row in the database.
  3977. *
  3978. * If the object is new, it inserts it; otherwise an update is performed.
  3979. * All related objects are also updated in this method.
  3980. *
  3981. * @param PropelPDO \$con";
  3982. if ($reloadOnUpdate || $reloadOnInsert) {
  3983. $script .= "
  3984. * @param boolean \$skipReload Whether to skip the reload for this object from database.";
  3985. }
  3986. $script .= "
  3987. * @return int The number of rows affected by this insert/update and any referring fk objects' save() operations.
  3988. * @throws PropelException
  3989. * @see save()
  3990. */
  3991. protected function doSave(PropelPDO \$con".($reloadOnUpdate || $reloadOnInsert ? ", \$skipReload = false" : "").")
  3992. {
  3993. \$affectedRows = 0; // initialize var to track total num of affected rows
  3994. if (!\$this->alreadyInSave) {
  3995. \$this->alreadyInSave = true;
  3996. ";
  3997. if ($reloadOnInsert || $reloadOnUpdate) {
  3998. $script .= "
  3999. \$reloadObject = false;
  4000. ";
  4001. }
  4002. if (count($table->getForeignKeys())) {
  4003. $script .= "
  4004. // We call the save method on the following object(s) if they
  4005. // were passed to this object by their coresponding set
  4006. // method. This object relates to these object(s) by a
  4007. // foreign key reference.
  4008. ";
  4009. foreach ($table->getForeignKeys() as $fk) {
  4010. $aVarName = $this->getFKVarName($fk);
  4011. $script .= "
  4012. if (\$this->$aVarName !== null) {
  4013. if (\$this->" . $aVarName . "->isModified() || \$this->" . $aVarName . "->isNew()) {
  4014. \$affectedRows += \$this->" . $aVarName . "->save(\$con);
  4015. }
  4016. \$this->set".$this->getFKPhpNameAffix($fk, $plural = false)."(\$this->$aVarName);
  4017. }
  4018. ";
  4019. } // foreach foreign k
  4020. } // if (count(foreign keys))
  4021. $script .= "
  4022. if (\$this->isNew() || \$this->isModified()) {
  4023. // persist changes
  4024. if (\$this->isNew()) {
  4025. \$this->doInsert(\$con);";
  4026. if ($reloadOnInsert) {
  4027. $script .= "
  4028. if (!\$skipReload) {
  4029. \$reloadObject = true;
  4030. }";
  4031. }
  4032. $script .= "
  4033. } else {
  4034. \$this->doUpdate(\$con);";
  4035. if ($reloadOnUpdate) {
  4036. $script .= "
  4037. if (!\$skipReload) {
  4038. \$reloadObject = true;
  4039. }";
  4040. }
  4041. $script .= "
  4042. }
  4043. \$affectedRows += 1;";
  4044. // We need to rewind any LOB columns
  4045. foreach ($table->getColumns() as $col) {
  4046. $clo = strtolower($col->getName());
  4047. if ($col->isLobType()) {
  4048. $script .= "
  4049. // Rewind the $clo LOB column, since PDO does not rewind after inserting value.
  4050. if (\$this->$clo !== null && is_resource(\$this->$clo)) {
  4051. rewind(\$this->$clo);
  4052. }
  4053. ";
  4054. }
  4055. }
  4056. $script .= "
  4057. \$this->resetModified();
  4058. }
  4059. ";
  4060. if ($table->hasCrossForeignKeys()) {
  4061. foreach ($table->getCrossFks() as $fkList) {
  4062. list($refFK, $crossFK) = $fkList;
  4063. $this->addCrossFkScheduledForDeletion($script, $refFK, $crossFK);
  4064. }
  4065. }
  4066. foreach ($table->getReferrers() as $refFK) {
  4067. $this->addRefFkScheduledForDeletion($script, $refFK);
  4068. if ($refFK->isLocalPrimaryKey()) {
  4069. $varName = $this->getPKRefFKVarName($refFK);
  4070. $script .= "
  4071. if (\$this->$varName !== null) {
  4072. if (!\$this->{$varName}->isDeleted()) {
  4073. \$affectedRows += \$this->{$varName}->save(\$con);
  4074. }
  4075. }
  4076. ";
  4077. } else {
  4078. $collName = $this->getRefFKCollVarName($refFK);
  4079. $script .= "
  4080. if (\$this->$collName !== null) {
  4081. foreach (\$this->$collName as \$referrerFK) {
  4082. if (!\$referrerFK->isDeleted()) {
  4083. \$affectedRows += \$referrerFK->save(\$con);
  4084. }
  4085. }
  4086. }
  4087. ";
  4088. } // if refFK->isLocalPrimaryKey()
  4089. } /* foreach getReferrers() */
  4090. $script .= "
  4091. \$this->alreadyInSave = false;
  4092. ";
  4093. if ($reloadOnInsert || $reloadOnUpdate) {
  4094. $script .= "
  4095. if (\$reloadObject) {
  4096. \$this->reload(\$con);
  4097. }
  4098. ";
  4099. }
  4100. $script .= "
  4101. }
  4102. return \$affectedRows;
  4103. } // doSave()
  4104. ";
  4105. }
  4106. /**
  4107. * get the doInsert() method code
  4108. *
  4109. * @return string the doInsert() method code
  4110. */
  4111. protected function addDoInsert()
  4112. {
  4113. $table = $this->getTable();
  4114. $script = "
  4115. /**
  4116. * Insert the row in the database.
  4117. *
  4118. * @param PropelPDO \$con
  4119. *
  4120. * @throws PropelException
  4121. * @see doSave()
  4122. */
  4123. protected function doInsert(PropelPDO \$con)
  4124. {";
  4125. if ($this->getPlatform() instanceof MssqlPlatform) {
  4126. if ($table->hasAutoIncrementPrimaryKey() ) {
  4127. $script .= "
  4128. \$this->modifiedColumns[] = " . $this->getColumnConstant($table->getAutoIncrementPrimaryKey() ) . ";";
  4129. }
  4130. $script .= "
  4131. \$criteria = \$this->buildCriteria();";
  4132. if ($this->getTable()->getIdMethod() != IDMethod::NO_ID_METHOD) {
  4133. $script .= $this->addDoInsertBodyWithIdMethod();
  4134. } else {
  4135. $script .= $this->addDoInsertBodyStandard();
  4136. }
  4137. } else {
  4138. $script .= $this->addDoInsertBodyRaw();
  4139. }
  4140. $script .= "
  4141. \$this->setNew(false);
  4142. }
  4143. ";
  4144. return $script;
  4145. }
  4146. protected function addDoInsertBodyStandard()
  4147. {
  4148. return "
  4149. \$pk = " . $this->getNewPeerBuilder($this->getTable())->getBasePeerClassname() . "::doInsert(\$criteria, \$con);";
  4150. }
  4151. protected function addDoInsertBodyWithIdMethod()
  4152. {
  4153. $table = $this->getTable();
  4154. $reloadOnInsert = $table->isReloadOnInsert();
  4155. $basePeerClassname = $this->getNewPeerBuilder($table)->getBasePeerClassname();
  4156. $script = '';
  4157. foreach ($table->getPrimaryKey() as $col) {
  4158. if (!$col->isAutoIncrement()) {
  4159. continue;
  4160. }
  4161. $colConst = $this->getColumnConstant($col);
  4162. if (!$table->isAllowPkInsert()) {
  4163. $script .= "
  4164. if (\$criteria->keyContainsValue($colConst) ) {
  4165. throw new PropelException('Cannot insert a value for auto-increment primary key (' . $colConst . ')');
  4166. }";
  4167. if (!$this->getPlatform()->supportsInsertNullPk()) {
  4168. $script .= "
  4169. // remove pkey col since this table uses auto-increment and passing a null value for it is not valid
  4170. \$criteria->remove($colConst);";
  4171. }
  4172. } elseif (!$this->getPlatform()->supportsInsertNullPk()) {
  4173. $script .= "
  4174. // remove pkey col if it is null since this table does not accept that
  4175. if (\$criteria->containsKey($colConst) && !\$criteria->keyContainsValue($colConst) ) {
  4176. \$criteria->remove($colConst);
  4177. }";
  4178. }
  4179. }
  4180. $script .= $this->addDoInsertBodyStandard();
  4181. foreach ($table->getPrimaryKey() as $col) {
  4182. if (!$col->isAutoIncrement()) {
  4183. continue;
  4184. }
  4185. if ($table->isAllowPkInsert()) {
  4186. $script .= "
  4187. if (\$pk !== null) {
  4188. \$this->set".$col->getPhpName()."(\$pk); //[IMV] update autoincrement primary key
  4189. }";
  4190. } else {
  4191. $script .= "
  4192. \$this->set".$col->getPhpName()."(\$pk); //[IMV] update autoincrement primary key";
  4193. }
  4194. }
  4195. return $script;
  4196. }
  4197. /**
  4198. * Boosts ActiveRecord::doInsert() by doing more calculations at buildtime.
  4199. */
  4200. protected function addDoInsertBodyRaw()
  4201. {
  4202. $this->declareClasses('Propel', 'PDO');
  4203. $table = $this->getTable();
  4204. $peerClassname = $this->getPeerClassname();
  4205. $platform = $this->getPlatform();
  4206. $primaryKeyMethodInfo = '';
  4207. if ($table->getIdMethodParameters()) {
  4208. $params = $table->getIdMethodParameters();
  4209. $imp = $params[0];
  4210. $primaryKeyMethodInfo = $imp->getValue();
  4211. } elseif ($table->getIdMethod() == IDMethod::NATIVE && ($platform->getNativeIdMethod() == PropelPlatformInterface::SEQUENCE || $platform->getNativeIdMethod() == PropelPlatformInterface::SERIAL)) {
  4212. $primaryKeyMethodInfo = $platform->getSequenceName($table);
  4213. }
  4214. $query = 'INSERT INTO ' . $platform->quoteIdentifier($table->getName()) . ' (%s) VALUES (%s)';
  4215. $script = "
  4216. \$modifiedColumns = array();
  4217. \$index = 0;
  4218. ";
  4219. foreach ($table->getPrimaryKey() as $column) {
  4220. if (!$column->isAutoIncrement()) {
  4221. continue;
  4222. }
  4223. $constantName = $this->getColumnConstant($column);
  4224. if ($platform->supportsInsertNullPk()) {
  4225. $script .= "
  4226. \$this->modifiedColumns[] = $constantName;";
  4227. }
  4228. $columnProperty = strtolower($column->getName());
  4229. if (!$table->isAllowPkInsert()) {
  4230. $script .= "
  4231. if (null !== \$this->{$columnProperty}) {
  4232. throw new PropelException('Cannot insert a value for auto-increment primary key (' . $constantName . ')');
  4233. }";
  4234. } elseif (!$platform->supportsInsertNullPk()) {
  4235. $script .= "
  4236. // add primary key column only if it is not null since this database does not accept that
  4237. if (null !== \$this->{$columnProperty}) {
  4238. \$this->modifiedColumns[] = $constantName;
  4239. }";
  4240. }
  4241. }
  4242. // if non auto-increment but using sequence, get the id first
  4243. if (!$platform->isNativeIdMethodAutoIncrement() && $table->getIdMethod() == "native") {
  4244. $column = $table->getFirstPrimaryKeyColumn();
  4245. $columnProperty = strtolower($column->getName());
  4246. $script .= "
  4247. if (null === \$this->{$columnProperty}) {
  4248. try {";
  4249. $script .= $platform->getIdentifierPhp('$this->'. $columnProperty, '$con', $primaryKeyMethodInfo, ' ');
  4250. $script .= "
  4251. } catch (Exception \$e) {
  4252. throw new PropelException('Unable to get sequence id.', \$e);
  4253. }
  4254. }
  4255. ";
  4256. }
  4257. $script .= "
  4258. // check the columns in natural order for more readable SQL queries";
  4259. foreach ($table->getColumns() as $column) {
  4260. $constantName = $this->getColumnConstant($column);
  4261. $identifier = var_export($platform->quoteIdentifier(strtoupper($column->getName())), true);
  4262. $script .= "
  4263. if (\$this->isColumnModified($constantName)) {
  4264. \$modifiedColumns[':p' . \$index++] = $identifier;
  4265. }";
  4266. }
  4267. $script .= "
  4268. \$sql = sprintf(
  4269. '$query',
  4270. implode(', ', \$modifiedColumns),
  4271. implode(', ', array_keys(\$modifiedColumns))
  4272. );
  4273. try {
  4274. \$stmt = \$con->prepare(\$sql);
  4275. foreach (\$modifiedColumns as \$identifier => \$columnName) {
  4276. switch (\$columnName) {";
  4277. foreach ($table->getColumns() as $column) {
  4278. $columnNameCase = var_export($platform->quoteIdentifier(strtoupper($column->getName())), true);
  4279. $script .= "
  4280. case $columnNameCase:";
  4281. $script .= $platform->getColumnBindingPHP($column, "\$identifier", '$this->' . strtolower($column->getName()), ' ');
  4282. $script .= "
  4283. break;";
  4284. }
  4285. $script .= "
  4286. }
  4287. }
  4288. \$stmt->execute();
  4289. } catch (Exception \$e) {
  4290. Propel::log(\$e->getMessage(), Propel::LOG_ERR);
  4291. throw new PropelException(sprintf('Unable to execute INSERT statement [%s]', \$sql), \$e);
  4292. }
  4293. ";
  4294. // if auto-increment, get the id after
  4295. if ($platform->isNativeIdMethodAutoIncrement() && $table->getIdMethod() == "native") {
  4296. $column = $table->getFirstPrimaryKeyColumn();
  4297. $columnProperty = strtolower($column->getName());
  4298. $script .= "
  4299. try {";
  4300. $script .= $platform->getIdentifierPhp('$pk', '$con', $primaryKeyMethodInfo);
  4301. $script .= "
  4302. } catch (Exception \$e) {
  4303. throw new PropelException('Unable to get autoincrement id.', \$e);
  4304. }";
  4305. if ($table->isAllowPkInsert()) {
  4306. $script .= "
  4307. if (\$pk !== null) {
  4308. \$this->set".$column->getPhpName()."(\$pk);
  4309. }";
  4310. } else {
  4311. $script .= "
  4312. \$this->set".$column->getPhpName()."(\$pk);";
  4313. }
  4314. $script .= "
  4315. ";
  4316. }
  4317. return $script;
  4318. }
  4319. /**
  4320. * get the doUpdate() method code
  4321. *
  4322. * @return string the doUpdate() method code
  4323. */
  4324. protected function addDoUpdate()
  4325. {
  4326. $basePeerClassname = $this->getNewPeerBuilder($this->getTable())->getBasePeerClassname();
  4327. return "
  4328. /**
  4329. * Update the row in the database.
  4330. *
  4331. * @param PropelPDO \$con
  4332. *
  4333. * @see doSave()
  4334. */
  4335. protected function doUpdate(PropelPDO \$con)
  4336. {
  4337. \$selectCriteria = \$this->buildPkeyCriteria();
  4338. \$valuesCriteria = \$this->buildCriteria();
  4339. {$basePeerClassname}::doUpdate(\$selectCriteria, \$valuesCriteria, \$con);
  4340. }
  4341. ";
  4342. }
  4343. /**
  4344. * Adds the $alreadyInSave attribute, which prevents attempting to re-save the same object.
  4345. * @param string &$script The script will be modified in this method.
  4346. */
  4347. protected function addAlreadyInSaveAttribute(&$script)
  4348. {
  4349. $script .= "
  4350. /**
  4351. * Flag to prevent endless save loop, if this object is referenced
  4352. * by another object which falls in this transaction.
  4353. * @var boolean
  4354. */
  4355. protected \$alreadyInSave = false;
  4356. ";
  4357. }
  4358. /**
  4359. * Adds the save() method.
  4360. * @param string &$script The script will be modified in this method.
  4361. */
  4362. protected function addSave(&$script)
  4363. {
  4364. $this->addSaveComment($script);
  4365. $this->addSaveOpen($script);
  4366. $this->addSaveBody($script);
  4367. $this->addSaveClose($script);
  4368. }
  4369. /**
  4370. * Adds the comment for the save method
  4371. * @param string &$script The script will be modified in this method.
  4372. * @see addSave()
  4373. **/
  4374. protected function addSaveComment(&$script)
  4375. {
  4376. $table = $this->getTable();
  4377. $reloadOnUpdate = $table->isReloadOnUpdate();
  4378. $reloadOnInsert = $table->isReloadOnInsert();
  4379. $script .= "
  4380. /**
  4381. * Persists this object to the database.
  4382. *
  4383. * If the object is new, it inserts it; otherwise an update is performed.
  4384. * All modified related objects will also be persisted in the doSave()
  4385. * method. This method wraps all precipitate database operations in a
  4386. * single transaction.";
  4387. if ($reloadOnUpdate) {
  4388. $script .= "
  4389. *
  4390. * Since this table was configured to reload rows on update, the object will
  4391. * be reloaded from the database if an UPDATE operation is performed (unless
  4392. * the \$skipReload parameter is true).";
  4393. }
  4394. if ($reloadOnInsert) {
  4395. $script .= "
  4396. *
  4397. * Since this table was configured to reload rows on insert, the object will
  4398. * be reloaded from the database if an INSERT operation is performed (unless
  4399. * the \$skipReload parameter is true).";
  4400. }
  4401. $script .= "
  4402. *
  4403. * @param PropelPDO \$con";
  4404. if ($reloadOnUpdate || $reloadOnInsert) {
  4405. $script .= "
  4406. * @param boolean \$skipReload Whether to skip the reload for this object from database.";
  4407. }
  4408. $script .= "
  4409. * @return int The number of rows affected by this insert/update and any referring fk objects' save() operations.
  4410. * @throws PropelException
  4411. * @throws Exception
  4412. * @see doSave()
  4413. */";
  4414. }
  4415. /**
  4416. * Adds the function declaration for the save method
  4417. * @param string &$script The script will be modified in this method.
  4418. * @see addSave()
  4419. **/
  4420. protected function addSaveOpen(&$script)
  4421. {
  4422. $table = $this->getTable();
  4423. $reloadOnUpdate = $table->isReloadOnUpdate();
  4424. $reloadOnInsert = $table->isReloadOnInsert();
  4425. $script .= "
  4426. public function save(PropelPDO \$con = null".($reloadOnUpdate || $reloadOnInsert ? ", \$skipReload = false" : "").")
  4427. {";
  4428. }
  4429. /**
  4430. * Adds the function body for the save method
  4431. * @param string &$script The script will be modified in this method.
  4432. * @see addSave()
  4433. **/
  4434. protected function addSaveBody(&$script)
  4435. {
  4436. $table = $this->getTable();
  4437. $reloadOnUpdate = $table->isReloadOnUpdate();
  4438. $reloadOnInsert = $table->isReloadOnInsert();
  4439. $script .= "
  4440. if (\$this->isDeleted()) {
  4441. throw new PropelException(\"You cannot save an object that has been deleted.\");
  4442. }
  4443. if (\$con === null) {
  4444. \$con = Propel::getConnection(".$this->getPeerClassname()."::DATABASE_NAME, Propel::CONNECTION_WRITE);
  4445. }
  4446. \$con->beginTransaction();
  4447. \$isInsert = \$this->isNew();
  4448. try {";
  4449. if ($this->getGeneratorConfig()->getBuildProperty('addHooks')) {
  4450. // save with runtime hools
  4451. $script .= "
  4452. \$ret = \$this->preSave(\$con);";
  4453. $this->applyBehaviorModifier('preSave', $script, " ");
  4454. $script .= "
  4455. if (\$isInsert) {
  4456. \$ret = \$ret && \$this->preInsert(\$con);";
  4457. $this->applyBehaviorModifier('preInsert', $script, " ");
  4458. $script .= "
  4459. } else {
  4460. \$ret = \$ret && \$this->preUpdate(\$con);";
  4461. $this->applyBehaviorModifier('preUpdate', $script, " ");
  4462. $script .= "
  4463. }
  4464. if (\$ret) {
  4465. \$affectedRows = \$this->doSave(\$con".($reloadOnUpdate || $reloadOnInsert ? ", \$skipReload" : "").");
  4466. if (\$isInsert) {
  4467. \$this->postInsert(\$con);";
  4468. $this->applyBehaviorModifier('postInsert', $script, " ");
  4469. $script .= "
  4470. } else {
  4471. \$this->postUpdate(\$con);";
  4472. $this->applyBehaviorModifier('postUpdate', $script, " ");
  4473. $script .= "
  4474. }
  4475. \$this->postSave(\$con);";
  4476. $this->applyBehaviorModifier('postSave', $script, " ");
  4477. $script .= "
  4478. ".$this->getPeerClassname()."::addInstanceToPool(\$this);
  4479. } else {
  4480. \$affectedRows = 0;
  4481. }
  4482. \$con->commit();
  4483. return \$affectedRows;";
  4484. } else {
  4485. // save without runtime hooks
  4486. $this->applyBehaviorModifier('preSave', $script, " ");
  4487. if ($this->hasBehaviorModifier('preUpdate')) {
  4488. $script .= "
  4489. if (!\$isInsert) {";
  4490. $this->applyBehaviorModifier('preUpdate', $script, " ");
  4491. $script .= "
  4492. }";
  4493. }
  4494. if ($this->hasBehaviorModifier('preInsert')) {
  4495. $script .= "
  4496. if (\$isInsert) {";
  4497. $this->applyBehaviorModifier('preInsert', $script, " ");
  4498. $script .= "
  4499. }";
  4500. }
  4501. $script .= "
  4502. \$affectedRows = \$this->doSave(\$con".($reloadOnUpdate || $reloadOnInsert ? ", \$skipReload" : "").");";
  4503. $this->applyBehaviorModifier('postSave', $script, " ");
  4504. if ($this->hasBehaviorModifier('postUpdate')) {
  4505. $script .= "
  4506. if (!\$isInsert) {";
  4507. $this->applyBehaviorModifier('postUpdate', $script, " ");
  4508. $script .= "
  4509. }";
  4510. }
  4511. if ($this->hasBehaviorModifier('postInsert')) {
  4512. $script .= "
  4513. if (\$isInsert) {";
  4514. $this->applyBehaviorModifier('postInsert', $script, " ");
  4515. $script .= "
  4516. }";
  4517. }
  4518. $script .= "
  4519. \$con->commit();
  4520. ".$this->getPeerClassname()."::addInstanceToPool(\$this);
  4521. return \$affectedRows;";
  4522. }
  4523. $script .= "
  4524. } catch (Exception \$e) {
  4525. \$con->rollBack();
  4526. throw \$e;
  4527. }";
  4528. }
  4529. /**
  4530. * Adds the function close for the save method
  4531. * @param string &$script The script will be modified in this method.
  4532. * @see addSave()
  4533. **/
  4534. protected function addSaveClose(&$script)
  4535. {
  4536. $script .= "
  4537. }
  4538. ";
  4539. }
  4540. /**
  4541. * Adds the $alreadyInValidation attribute, which prevents attempting to re-validate the same object.
  4542. * @param string &$script The script will be modified in this method.
  4543. */
  4544. protected function addAlreadyInValidationAttribute(&$script)
  4545. {
  4546. $script .= "
  4547. /**
  4548. * Flag to prevent endless validation loop, if this object is referenced
  4549. * by another object which falls in this transaction.
  4550. * @var boolean
  4551. */
  4552. protected \$alreadyInValidation = false;
  4553. ";
  4554. }
  4555. /**
  4556. * Adds the validate() method.
  4557. * @param string &$script The script will be modified in this method.
  4558. */
  4559. protected function addValidate(&$script)
  4560. {
  4561. $script .= "
  4562. /**
  4563. * Validates the objects modified field values and all objects related to this table.
  4564. *
  4565. * If \$columns is either a column name or an array of column names
  4566. * only those columns are validated.
  4567. *
  4568. * @param mixed \$columns Column name or an array of column names.
  4569. * @return boolean Whether all columns pass validation.
  4570. * @see doValidate()
  4571. * @see getValidationFailures()
  4572. */
  4573. public function validate(\$columns = null)
  4574. {
  4575. \$res = \$this->doValidate(\$columns);
  4576. if (\$res === true) {
  4577. \$this->validationFailures = array();
  4578. return true;
  4579. } else {
  4580. \$this->validationFailures = \$res;
  4581. return false;
  4582. }
  4583. }
  4584. ";
  4585. } // addValidate()
  4586. /**
  4587. * Adds the workhourse doValidate() method.
  4588. * @param string &$script The script will be modified in this method.
  4589. */
  4590. protected function addDoValidate(&$script)
  4591. {
  4592. $table = $this->getTable();
  4593. $script .= "
  4594. /**
  4595. * This function performs the validation work for complex object models.
  4596. *
  4597. * In addition to checking the current object, all related objects will
  4598. * also be validated. If all pass then <code>true</code> is returned; otherwise
  4599. * an aggreagated array of ValidationFailed objects will be returned.
  4600. *
  4601. * @param array \$columns Array of column names to validate.
  4602. * @return mixed <code>true</code> if all validations pass; array of <code>ValidationFailed</code> objets otherwise.
  4603. */
  4604. protected function doValidate(\$columns = null)
  4605. {
  4606. if (!\$this->alreadyInValidation) {
  4607. \$this->alreadyInValidation = true;
  4608. \$retval = null;
  4609. \$failureMap = array();
  4610. ";
  4611. if (count($table->getForeignKeys()) != 0) {
  4612. $script .= "
  4613. // We call the validate method on the following object(s) if they
  4614. // were passed to this object by their coresponding set
  4615. // method. This object relates to these object(s) by a
  4616. // foreign key reference.
  4617. ";
  4618. foreach ($table->getForeignKeys() as $fk) {
  4619. $aVarName = $this->getFKVarName($fk);
  4620. $script .= "
  4621. if (\$this->".$aVarName." !== null) {
  4622. if (!\$this->".$aVarName."->validate(\$columns)) {
  4623. \$failureMap = array_merge(\$failureMap, \$this->".$aVarName."->getValidationFailures());
  4624. }
  4625. }
  4626. ";
  4627. } /* for () */
  4628. } /* if count(fkeys) */
  4629. $script .= "
  4630. if ((\$retval = ".$this->getPeerClassname()."::doValidate(\$this, \$columns)) !== true) {
  4631. \$failureMap = array_merge(\$failureMap, \$retval);
  4632. }
  4633. ";
  4634. foreach ($table->getReferrers() as $refFK) {
  4635. if ($refFK->isLocalPrimaryKey()) {
  4636. $varName = $this->getPKRefFKVarName($refFK);
  4637. $script .= "
  4638. if (\$this->$varName !== null) {
  4639. if (!\$this->".$varName."->validate(\$columns)) {
  4640. \$failureMap = array_merge(\$failureMap, \$this->".$varName."->getValidationFailures());
  4641. }
  4642. }
  4643. ";
  4644. } else {
  4645. $collName = $this->getRefFKCollVarName($refFK);
  4646. $script .= "
  4647. if (\$this->$collName !== null) {
  4648. foreach (\$this->$collName as \$referrerFK) {
  4649. if (!\$referrerFK->validate(\$columns)) {
  4650. \$failureMap = array_merge(\$failureMap, \$referrerFK->getValidationFailures());
  4651. }
  4652. }
  4653. }
  4654. ";
  4655. }
  4656. } /* foreach getReferrers() */
  4657. $script .= "
  4658. \$this->alreadyInValidation = false;
  4659. }
  4660. return (!empty(\$failureMap) ? \$failureMap : true);
  4661. }
  4662. ";
  4663. } // addDoValidate()
  4664. /**
  4665. * Adds the ensureConsistency() method to ensure that internal state is correct.
  4666. * @param string &$script The script will be modified in this method.
  4667. */
  4668. protected function addEnsureConsistency(&$script)
  4669. {
  4670. $table = $this->getTable();
  4671. $script .= "
  4672. /**
  4673. * Checks and repairs the internal consistency of the object.
  4674. *
  4675. * This method is executed after an already-instantiated object is re-hydrated
  4676. * from the database. It exists to check any foreign keys to make sure that
  4677. * the objects related to the current object are correct based on foreign key.
  4678. *
  4679. * You can override this method in the stub class, but you should always invoke
  4680. * the base method from the overridden method (i.e. parent::ensureConsistency()),
  4681. * in case your model changes.
  4682. *
  4683. * @throws PropelException
  4684. */
  4685. public function ensureConsistency()
  4686. {
  4687. ";
  4688. foreach ($table->getColumns() as $col) {
  4689. $clo=strtolower($col->getName());
  4690. if ($col->isForeignKey()) {
  4691. foreach ($col->getForeignKeys() as $fk) {
  4692. $tblFK = $table->getDatabase()->getTable($fk->getForeignTableName());
  4693. $colFK = $tblFK->getColumn($fk->getMappedForeignColumn($col->getName()));
  4694. $varName = $this->getFKVarName($fk);
  4695. $script .= "
  4696. if (\$this->".$varName." !== null && \$this->$clo !== \$this->".$varName."->get".$colFK->getPhpName()."()) {
  4697. \$this->$varName = null;
  4698. }";
  4699. } // foraech
  4700. } /* if col is foreign key */
  4701. } // foreach
  4702. $script .= "
  4703. } // ensureConsistency
  4704. ";
  4705. } // addCheckRelConsistency
  4706. /**
  4707. * Adds the copy() method, which (in complex OM) includes the $deepCopy param for making copies of related objects.
  4708. * @param string &$script The script will be modified in this method.
  4709. */
  4710. protected function addCopy(&$script)
  4711. {
  4712. $this->addCopyInto($script);
  4713. $table = $this->getTable();
  4714. $script .= "
  4715. /**
  4716. * Makes a copy of this object that will be inserted as a new row in table when saved.
  4717. * It creates a new object filling in the simple attributes, but skipping any primary
  4718. * keys that are defined for the table.
  4719. *
  4720. * If desired, this method can also make copies of all associated (fkey referrers)
  4721. * objects.
  4722. *
  4723. * @param boolean \$deepCopy Whether to also copy all rows that refer (by fkey) to the current row.
  4724. * @return ".$this->getObjectClassname()." Clone of current object.
  4725. * @throws PropelException
  4726. */
  4727. public function copy(\$deepCopy = false)
  4728. {
  4729. // we use get_class(), because this might be a subclass
  4730. \$clazz = get_class(\$this);
  4731. " . $this->buildObjectInstanceCreationCode('$copyObj', '$clazz') . "
  4732. \$this->copyInto(\$copyObj, \$deepCopy);
  4733. return \$copyObj;
  4734. }
  4735. ";
  4736. } // addCopy()
  4737. /**
  4738. * Adds the copyInto() method, which takes an object and sets contents to match current object.
  4739. * In complex OM this method includes the $deepCopy param for making copies of related objects.
  4740. * @param string &$script The script will be modified in this method.
  4741. */
  4742. protected function addCopyInto(&$script)
  4743. {
  4744. $table = $this->getTable();
  4745. $script .= "
  4746. /**
  4747. * Sets contents of passed object to values from current object.
  4748. *
  4749. * If desired, this method can also make copies of all associated (fkey referrers)
  4750. * objects.
  4751. *
  4752. * @param object \$copyObj An object of ".$this->getObjectClassname()." (or compatible) type.
  4753. * @param boolean \$deepCopy Whether to also copy all rows that refer (by fkey) to the current row.
  4754. * @param boolean \$makeNew Whether to reset autoincrement PKs and make the object new.
  4755. * @throws PropelException
  4756. */
  4757. public function copyInto(\$copyObj, \$deepCopy = false, \$makeNew = true)
  4758. {";
  4759. $autoIncCols = array();
  4760. if ($table->hasCompositePrimaryKey()) {
  4761. foreach ($table->getColumns() as $col) {
  4762. /* @var $col Column */
  4763. if ($col->isAutoIncrement()) {
  4764. $autoIncCols[] = $col;
  4765. }
  4766. }
  4767. } else {
  4768. $autoIncCols = $table->getPrimaryKey();
  4769. }
  4770. foreach ($table->getColumns() as $col) {
  4771. if (!in_array($col, $autoIncCols, true)) {
  4772. $script .= "
  4773. \$copyObj->set".$col->getPhpName()."(\$this->get".$col->getPhpName()."());";
  4774. }
  4775. } // foreach
  4776. // Avoid useless code by checking to see if there are any referrers
  4777. // to this table:
  4778. if (count($table->getReferrers()) > 0 || count($table->getForeignKeys()) > 0 ) {
  4779. $script .= "
  4780. if (\$deepCopy && !\$this->startCopy) {
  4781. // important: temporarily setNew(false) because this affects the behavior of
  4782. // the getter/setter methods for fkey referrer objects.
  4783. \$copyObj->setNew(false);
  4784. // store object hash to prevent cycle
  4785. \$this->startCopy = true;
  4786. ";
  4787. foreach ($table->getReferrers() as $fk) {
  4788. //HL: commenting out self-referrential check below
  4789. // it seems to work as expected and is probably desireable to have those referrers from same table deep-copied.
  4790. //if ( $fk->getTable()->getName() != $table->getName() ) {
  4791. if ($fk->isLocalPrimaryKey()) {
  4792. $afx = $this->getRefFKPhpNameAffix($fk, $plural = false);
  4793. $script .= "
  4794. \$relObj = \$this->get$afx();
  4795. if (\$relObj) {
  4796. \$copyObj->set$afx(\$relObj->copy(\$deepCopy));
  4797. }
  4798. ";
  4799. } else {
  4800. $script .= "
  4801. foreach (\$this->get".$this->getRefFKPhpNameAffix($fk, true)."() as \$relObj) {
  4802. if (\$relObj !== \$this) { // ensure that we don't try to copy a reference to ourselves
  4803. \$copyObj->add".$this->getRefFKPhpNameAffix($fk)."(\$relObj->copy(\$deepCopy));
  4804. }
  4805. }
  4806. ";
  4807. }
  4808. // HL: commenting out close of self-referential check
  4809. // } /* if tblFK != table */
  4810. } /* foreach */
  4811. // do deep copy for one to one relation
  4812. foreach ($table->getForeignKeys() as $fk) {
  4813. if ($fk->isLocalPrimaryKey()) {
  4814. $afx = $this->getFKPhpNameAffix($fk, $plural = false);
  4815. $script .= "
  4816. \$relObj = \$this->get$afx();
  4817. if (\$relObj) {
  4818. \$copyObj->set$afx(\$relObj->copy(\$deepCopy));
  4819. }
  4820. ";
  4821. }
  4822. }
  4823. $script .= "
  4824. //unflag object copy
  4825. \$this->startCopy = false;
  4826. } // if (\$deepCopy)
  4827. ";
  4828. } /* if (count referrers > 0 ) */
  4829. $script .= "
  4830. if (\$makeNew) {
  4831. \$copyObj->setNew(true);";
  4832. // Note: we're no longer resetting non-autoincrement primary keys to default values
  4833. // due to: http://propel.phpdb.org/trac/ticket/618
  4834. foreach ($autoIncCols as $col) {
  4835. $coldefval = $col->getPhpDefaultValue();
  4836. $coldefval = var_export($coldefval, true);
  4837. $script .= "
  4838. \$copyObj->set".$col->getPhpName() ."($coldefval); // this is a auto-increment column, so set to default value";
  4839. } // foreach
  4840. $script .= "
  4841. }
  4842. }
  4843. ";
  4844. } // addCopyInto()
  4845. /**
  4846. * Adds clear method
  4847. * @param string &$script The script will be modified in this method.
  4848. */
  4849. protected function addClear(&$script)
  4850. {
  4851. $table = $this->getTable();
  4852. $script .= "
  4853. /**
  4854. * Clears the current object and sets all attributes to their default values
  4855. */
  4856. public function clear()
  4857. {";
  4858. foreach ($table->getColumns() as $col) {
  4859. $clo = strtolower($col->getName());
  4860. $script .= "
  4861. \$this->".$clo." = null;";
  4862. if ($col->isLazyLoad()) {
  4863. $script .= "
  4864. \$this->".$clo."_isLoaded = false;";
  4865. }
  4866. if ($col->getType() == PropelTypes::OBJECT || $col->getType() == PropelTypes::PHP_ARRAY) {
  4867. $cloUnserialized = $clo.'_unserialized';
  4868. $script .="
  4869. \$this->$cloUnserialized = null;";
  4870. }
  4871. }
  4872. $script .= "
  4873. \$this->alreadyInSave = false;
  4874. \$this->alreadyInValidation = false;
  4875. \$this->clearAllReferences();";
  4876. if ($this->hasDefaultValues()) {
  4877. $script .= "
  4878. \$this->applyDefaultValues();";
  4879. }
  4880. $script .= "
  4881. \$this->resetModified();
  4882. \$this->setNew(true);
  4883. \$this->setDeleted(false);
  4884. }
  4885. ";
  4886. }
  4887. /**
  4888. * Adds clearAllReferencers() method which resets all the collections of referencing
  4889. * fk objects.
  4890. * @param string &$script The script will be modified in this method.
  4891. */
  4892. protected function addClearAllReferences(&$script)
  4893. {
  4894. $table = $this->getTable();
  4895. $script .= "
  4896. /**
  4897. * Resets all references to other model objects or collections of model objects.
  4898. *
  4899. * This method is a user-space workaround for PHP's inability to garbage collect
  4900. * objects with circular references (even in PHP 5.3). This is currently necessary
  4901. * when using Propel in certain daemon or large-volumne/high-memory operations.
  4902. *
  4903. * @param boolean \$deep Whether to also clear the references on all referrer objects.
  4904. */
  4905. public function clearAllReferences(\$deep = false)
  4906. {
  4907. if (\$deep) {";
  4908. $vars = array();
  4909. foreach ($this->getTable()->getReferrers() as $refFK) {
  4910. if ($refFK->isLocalPrimaryKey()) {
  4911. $varName = $this->getPKRefFKVarName($refFK);
  4912. $script .= "
  4913. if (\$this->$varName) {
  4914. \$this->{$varName}->clearAllReferences(\$deep);
  4915. }";
  4916. } else {
  4917. $varName = $this->getRefFKCollVarName($refFK);
  4918. $script .= "
  4919. if (\$this->$varName) {
  4920. foreach (\$this->$varName as \$o) {
  4921. \$o->clearAllReferences(\$deep);
  4922. }
  4923. }";
  4924. }
  4925. $vars[] = $varName;
  4926. }
  4927. foreach ($this->getTable()->getCrossFks() as $fkList) {
  4928. list($refFK, $crossFK) = $fkList;
  4929. $varName = $this->getCrossFKVarName($crossFK);
  4930. $script .= "
  4931. if (\$this->$varName) {
  4932. foreach (\$this->$varName as \$o) {
  4933. \$o->clearAllReferences(\$deep);
  4934. }
  4935. }";
  4936. $vars[] = $varName;
  4937. }
  4938. $script .= "
  4939. } // if (\$deep)
  4940. ";
  4941. $this->applyBehaviorModifier('objectClearReferences', $script, " ");
  4942. foreach ($vars as $varName) {
  4943. $script .= "
  4944. if (\$this->$varName instanceof PropelCollection) {
  4945. \$this->{$varName}->clearIterator();
  4946. }
  4947. \$this->$varName = null;";
  4948. }
  4949. foreach ($table->getForeignKeys() as $fk) {
  4950. $varName = $this->getFKVarName($fk);
  4951. $script .= "
  4952. \$this->$varName = null;";
  4953. }
  4954. $script .= "
  4955. }
  4956. ";
  4957. }
  4958. /**
  4959. * Adds a magic __toString() method if a string column was defined as primary string
  4960. * @param string &$script The script will be modified in this method.
  4961. */
  4962. protected function addPrimaryString(&$script)
  4963. {
  4964. foreach ($this->getTable()->getColumns() as $column) {
  4965. if ($column->isPrimaryString()) {
  4966. $script .= "
  4967. /**
  4968. * return the string representation of this object
  4969. *
  4970. * @return string The value of the '{$column->getName()}' column
  4971. */
  4972. public function __toString()
  4973. {
  4974. return (string) \$this->get{$column->getPhpName()}();
  4975. }
  4976. ";
  4977. return;
  4978. }
  4979. }
  4980. // no primary string column, falling back to default string format
  4981. $script .= "
  4982. /**
  4983. * return the string representation of this object
  4984. *
  4985. * @return string
  4986. */
  4987. public function __toString()
  4988. {
  4989. return (string) \$this->exportTo(" . $this->getPeerClassname() . "::DEFAULT_STRING_FORMAT);
  4990. }
  4991. ";
  4992. }
  4993. /**
  4994. * Adds a magic __call() method
  4995. * @param string &$script The script will be modified in this method.
  4996. */
  4997. protected function addMagicCall(&$script)
  4998. {
  4999. $behaviorCallScript = '';
  5000. $this->applyBehaviorModifier('objectCall', $behaviorCallScript, " ");
  5001. if ($behaviorCallScript) {
  5002. $script .= "
  5003. /**
  5004. * Catches calls to virtual methods
  5005. */
  5006. public function __call(\$name, \$params)
  5007. {
  5008. $behaviorCallScript
  5009. return parent::__call(\$name, \$params);
  5010. }
  5011. ";
  5012. }
  5013. }
  5014. protected function addIsAlreadyInSave(&$script)
  5015. {
  5016. $script .= "
  5017. /**
  5018. * return true is the object is in saving state
  5019. *
  5020. * @return boolean
  5021. */
  5022. public function isAlreadyInSave()
  5023. {
  5024. return \$this->alreadyInSave;
  5025. }
  5026. ";
  5027. }
  5028. } // PHP5ObjectBuilder