/src/Propel/Generator/Behavior/Sortable/SortableBehaviorQueryBuilderModifier.php

https://github.com/fabienpomerol/Propel2 · PHP · 297 lines · 179 code · 27 blank · 91 comment · 12 complexity · f49357a6ea94517989b40252d01bd1a1 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. namespace Propel\Generator\Behavior\Sortable;
  10. /**
  11. * Behavior to add sortable query methods
  12. *
  13. * @author François Zaninotto
  14. */
  15. class SortableBehaviorQueryBuilderModifier
  16. {
  17. protected $behavior;
  18. protected $table;
  19. protected $builder;
  20. protected $objectClassName;
  21. protected $peerClassName;
  22. public function __construct($behavior)
  23. {
  24. $this->behavior = $behavior;
  25. $this->table = $behavior->getTable();
  26. }
  27. protected function getParameter($key)
  28. {
  29. return $this->behavior->getParameter($key);
  30. }
  31. protected function getColumn($name)
  32. {
  33. return $this->behavior->getColumnForParameter($name);
  34. }
  35. protected function setBuilder($builder)
  36. {
  37. $this->builder = $builder;
  38. $this->objectClassName = $builder->getObjectClassName();
  39. $this->queryClassName = $builder->getQueryClassName();
  40. $this->peerClassName = $builder->getPeerClassName();
  41. }
  42. public function queryMethods($builder)
  43. {
  44. $this->setBuilder($builder);
  45. $script = '';
  46. // select filters
  47. if ($this->behavior->useScope()) {
  48. $this->addInList($script);
  49. }
  50. if ('rank' !== $this->getParameter('rank_column')) {
  51. $this->addFilterByRank($script);
  52. $this->addOrderByRank($script);
  53. }
  54. // select termination methods
  55. if ('rank' !== $this->getParameter('rank_column')
  56. || $this->behavior->useScope()) {
  57. $this->addFindOneByRank($script);
  58. }
  59. $this->addFindList($script);
  60. // utilities
  61. $this->addGetMaxRank($script);
  62. $this->addReorder($script);
  63. return $script;
  64. }
  65. protected function addInList(&$script)
  66. {
  67. $script .= "
  68. /**
  69. * Returns the objects in a certain list, from the list scope
  70. *
  71. * @param int \$scope Scope to determine which objects node to return
  72. *
  73. * @return {$this->queryClassName} The current query, for fluid interface
  74. */
  75. public function inList(\$scope = null)
  76. {
  77. return \$this->addUsingAlias({$this->peerClassName}::SCOPE_COL, \$scope, Criteria::EQUAL);
  78. }
  79. ";
  80. }
  81. protected function addFilterByRank(&$script)
  82. {
  83. $useScope = $this->behavior->useScope();
  84. $peerClassName = $this->peerClassName;
  85. $script .= "
  86. /**
  87. * Filter the query based on a rank in the list
  88. *
  89. * @param integer \$rank rank";
  90. if ($useScope) {
  91. $script .= "
  92. * @param int \$scope Scope to determine which suite to consider";
  93. }
  94. $script .= "
  95. *
  96. * @return " . $this->queryClassName . " The current query, for fluid interface
  97. */
  98. public function filterByRank(\$rank" . ($useScope ? ", \$scope = null" : "") . ")
  99. {
  100. return \$this";
  101. if ($useScope) {
  102. $script .= "
  103. ->inList(\$scope)";
  104. }
  105. $script .= "
  106. ->addUsingAlias($peerClassName::RANK_COL, \$rank, Criteria::EQUAL);
  107. }
  108. ";
  109. }
  110. protected function addOrderByRank(&$script)
  111. {
  112. $script .= "
  113. /**
  114. * Order the query based on the rank in the list.
  115. * Using the default \$order, returns the item with the lowest rank first
  116. *
  117. * @param string \$order either Criteria::ASC (default) or Criteria::DESC
  118. *
  119. * @return " . $this->queryClassName . " The current query, for fluid interface
  120. */
  121. public function orderByRank(\$order = Criteria::ASC)
  122. {
  123. \$order = strtoupper(\$order);
  124. switch (\$order) {
  125. case Criteria::ASC:
  126. return \$this->addAscendingOrderByColumn(\$this->getAliasedColName(" . $this->peerClassName . "::RANK_COL));
  127. break;
  128. case Criteria::DESC:
  129. return \$this->addDescendingOrderByColumn(\$this->getAliasedColName(" . $this->peerClassName . "::RANK_COL));
  130. break;
  131. default:
  132. throw new \Propel\Runtime\Exception\PropelException('" . $this->queryClassName . "::orderBy() only accepts \"asc\" or \"desc\" as argument');
  133. }
  134. }
  135. ";
  136. }
  137. protected function addFindOneByRank(&$script)
  138. {
  139. $useScope = $this->behavior->useScope();
  140. $script .= "
  141. /**
  142. * Get an item from the list based on its rank
  143. *
  144. * @param integer \$rank rank";
  145. if ($useScope) {
  146. $script .= "
  147. * @param int \$scope Scope to determine which suite to consider";
  148. }
  149. $script .= "
  150. * @param ConnectionInterface \$con optional connection
  151. *
  152. * @return {$this->objectClassName}
  153. */
  154. public function findOneByRank(\$rank, " . ($useScope ? "\$scope = null, " : "") . "ConnectionInterface \$con = null)
  155. {
  156. return \$this
  157. ->filterByRank(\$rank" . ($useScope ? ", \$scope" : "") . ")
  158. ->findOne(\$con);
  159. }
  160. ";
  161. }
  162. protected function addFindList(&$script)
  163. {
  164. $useScope = $this->behavior->useScope();
  165. $script .= "
  166. /**
  167. * Returns " . ($useScope ? 'a' : 'the') ." list of objects
  168. *";
  169. if ($useScope) {
  170. $script .= "
  171. * @param int \$scope Scope to determine which list to return";
  172. }
  173. $script .= "
  174. * @param ConnectionInterface \$con Connection to use.
  175. *
  176. * @return mixed the list of results, formatted by the current formatter
  177. */
  178. public function findList(" . ($useScope ? "\$scope = null, " : "") . "\$con = null)
  179. {
  180. return \$this";
  181. if ($useScope) {
  182. $script .= "
  183. ->inList(\$scope)";
  184. }
  185. $script .= "
  186. ->orderByRank()
  187. ->find(\$con);
  188. }
  189. ";
  190. }
  191. protected function addGetMaxRank(&$script)
  192. {
  193. $this->builder->declareClasses(
  194. '\Propel\Runtime\Propel'
  195. );
  196. $useScope = $this->behavior->useScope();
  197. $script .= "
  198. /**
  199. * Get the highest rank
  200. * ";
  201. if ($useScope) {
  202. $script .= "
  203. * @param int \$scope Scope to determine which suite to consider";
  204. }
  205. $script .= "
  206. * @param ConnectionInterface optional connection
  207. *
  208. * @return integer highest position
  209. */
  210. public function getMaxRank(" . ($useScope ? "\$scope = null, " : "") . "ConnectionInterface \$con = null)
  211. {
  212. if (null === \$con) {
  213. \$con = Propel::getServiceContainer()->getReadConnection({$this->peerClassName}::DATABASE_NAME);
  214. }
  215. // shift the objects with a position lower than the one of object
  216. \$this->addSelectColumn('MAX(' . {$this->peerClassName}::RANK_COL . ')');";
  217. if ($useScope) {
  218. $script .= "
  219. \$this->add({$this->peerClassName}::SCOPE_COL, \$scope, Criteria::EQUAL);";
  220. }
  221. $script .= "
  222. \$stmt = \$this->doSelect(\$con);
  223. return \$stmt->fetchColumn();
  224. }
  225. ";
  226. }
  227. protected function addReorder(&$script)
  228. {
  229. $this->builder->declareClasses('\Propel\Runtime\Propel');
  230. $peerClassName = $this->peerClassName;
  231. $columnGetter = 'get' . $this->behavior->getColumnForParameter('rank_column')->getPhpName();
  232. $columnSetter = 'set' . $this->behavior->getColumnForParameter('rank_column')->getPhpName();
  233. $script .= "
  234. /**
  235. * Reorder a set of sortable objects based on a list of id/position
  236. * Beware that there is no check made on the positions passed
  237. * So incoherent positions will result in an incoherent list
  238. *
  239. * @param array \$order id => rank pairs
  240. * @param ConnectionInterface \$con optional connection
  241. *
  242. * @return boolean true if the reordering took place, false if a database problem prevented it
  243. */
  244. public function reorder(array \$order, ConnectionInterface \$con = null)
  245. {
  246. if (null === \$con) {
  247. \$con = Propel::getServiceContainer()->getReadConnection($peerClassName::DATABASE_NAME);
  248. }
  249. \$con->beginTransaction();
  250. try {
  251. \$ids = array_keys(\$order);
  252. \$objects = \$this->findPks(\$ids, \$con);
  253. foreach (\$objects as \$object) {
  254. \$pk = \$object->getPrimaryKey();
  255. if (\$object->$columnGetter() != \$order[\$pk]) {
  256. \$object->$columnSetter(\$order[\$pk]);
  257. \$object->save(\$con);
  258. }
  259. }
  260. \$con->commit();
  261. return true;
  262. } catch (\Propel\Runtime\Exception\PropelException \$e) {
  263. \$con->rollback();
  264. throw \$e;
  265. }
  266. }
  267. ";
  268. }
  269. }