PageRenderTime 47ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/libraries/rokcommon/RokCommon/Doctrine/Extensions/Orderable/Doctrine/Template/Listener/Orderable.php

https://gitlab.com/che234/adn
PHP | 366 lines | 241 code | 39 blank | 86 comment | 28 complexity | 2a465fe5c5237d3ff6fa029787f436cd MD5 | raw file
  1. <?php
  2. /**
  3. * @version $Id: Orderable.php 30067 2016-03-08 13:44:25Z matias $
  4. * @author RocketTheme http://www.rockettheme.com
  5. * @copyright Copyright (C) 2007 - 2016 RocketTheme, LLC
  6. * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPLv2 only
  7. */
  8. defined('ROKCOMMON') or die;
  9. /**
  10. *
  11. */
  12. class Doctrine_Template_Listener_Orderable extends Doctrine_Record_Listener
  13. {
  14. /**
  15. * Array of orderable options
  16. *
  17. * @var string
  18. */
  19. protected $_options = array();
  20. /**
  21. * __construct
  22. *
  23. * @param array|string $options
  24. *
  25. * @return Doctrine_Template_Listener_Orderable
  26. */
  27. public function __construct(array $options)
  28. {
  29. $this->_options = $options;
  30. }
  31. /**
  32. * Set the Orderable columns when a record is inserted
  33. *
  34. * @param Doctrine_Event $event
  35. *
  36. * @throws Exception
  37. * @return void
  38. */
  39. public function preInsert(Doctrine_Event $event)
  40. {
  41. /** @var $record Doctrine_Record */
  42. $record = $event->getInvoker();
  43. $name = $record->getTable()->getFieldName($this->_options['name']);
  44. $modified = $record->getModified();
  45. $conn = $record->getTable()->getConnection();
  46. try {
  47. $conn->beginInternalTransaction();
  48. // Figure out what the
  49. if (!isset($modified[$name])) {
  50. if ($this->_options['initialPosition'] == 'last') {
  51. $highest = $this->getHighestPosition($record);
  52. if (is_numeric($highest)) {
  53. $initialPosition = $highest + 1;
  54. } else {
  55. $initialPosition = 0;
  56. }
  57. $record->{$name} = $initialPosition;
  58. } else {
  59. // shift higher records
  60. $record->{$name} = 0;
  61. $this->shiftOrder($record, $this->getOrderByVales($event,false));
  62. }
  63. } else {
  64. $this->shiftOrder($record, $this->getOrderByVales($event,false));
  65. }
  66. $conn->commit();
  67. } catch (Exception $e) {
  68. $conn->rollback();
  69. throw $e;
  70. }
  71. }
  72. /**
  73. * @param Doctrine_Event $event
  74. *
  75. * @throws Exception
  76. */
  77. public function postInsert(Doctrine_Event $event)
  78. {
  79. /** @var $record Doctrine_Record */
  80. $record = $event->getInvoker();
  81. $conn = $record->getTable()->getConnection();
  82. try {
  83. $conn->beginInternalTransaction();
  84. //$this->reorder($record);
  85. $conn->commit();
  86. } catch (Exception $e) {
  87. $conn->rollback();
  88. throw $e;
  89. }
  90. }
  91. /**
  92. * @param Doctrine_Event $event
  93. *
  94. * @throws Exception
  95. * @return void
  96. */
  97. public function preUpdate(Doctrine_Event $event)
  98. {
  99. /** @var $record Doctrine_Record */
  100. $record = $event->getInvoker();
  101. $conn = $record->getTable()->getConnection();
  102. $name = $record->getTable()->getFieldName($this->_options['name']);
  103. $modified = $record->getModified();
  104. $original = $record->getModified(true);
  105. if (array_key_exists($name, $modified)) {
  106. try {
  107. $conn->beginInternalTransaction();
  108. $this->shiftOrder($record, $this->getOrderByVales($event, false));
  109. $conn->commit();
  110. } catch (Exception $e) {
  111. $conn->rollback();
  112. throw $e;
  113. }
  114. }
  115. $ordered_col = false;
  116. foreach ($this->_options['orderableBy'] as $orderBy) {
  117. if (array_key_exists($orderBy, $modified)) {
  118. $ordered_col = true;
  119. }
  120. }
  121. // ordered column changed
  122. if ($ordered_col) {
  123. try {
  124. $conn->beginInternalTransaction();
  125. // remove from old ordered set
  126. $this->reduceOrder($record, $this->getOrderByVales($event, true));
  127. // add into new ordered set
  128. $this->shiftOrder($record, $this->getOrderByVales($event, false));
  129. $conn->commit();
  130. } catch (Exception $e) {
  131. $conn->rollback();
  132. throw $e;
  133. }
  134. }
  135. }
  136. protected function getOrderByVales(Doctrine_Event $event, $original = false)
  137. {
  138. $values = array();
  139. $record = $event->getInvoker();
  140. $mod_values = $record->getModified($original);
  141. foreach ($this->_options['orderableBy'] as $orderBy) {
  142. if (array_key_exists($orderBy, $mod_values)) {
  143. $values[$orderBy] = $mod_values[$orderBy];
  144. } else {
  145. $values[$orderBy] = $record->{$orderBy};
  146. }
  147. }
  148. return $values;
  149. }
  150. /**
  151. * @param Doctrine_Event $event
  152. *
  153. * @throws Exception
  154. * @return void
  155. */
  156. public function postUpdate(Doctrine_Event $event)
  157. {
  158. /** @var $record Doctrine_Record */
  159. $record = $event->getInvoker();
  160. $conn = $record->getTable()->getConnection();
  161. try {
  162. $conn->beginInternalTransaction();
  163. $this->reorder($record);
  164. $conn->commit();
  165. } catch (Exception $e) {
  166. $conn->rollback();
  167. throw $e;
  168. }
  169. }
  170. public function preDelete(Doctrine_Event $event)
  171. {
  172. /** @var $record Doctrine_Record */
  173. $record = $event->getInvoker();
  174. $conn = $record->getTable()->getConnection();
  175. try {
  176. $conn->beginInternalTransaction();
  177. $this->reduceOrder($record, $this->getOrderByVales($event, false));
  178. $conn->commit();
  179. } catch (Exception $e) {
  180. $conn->rollback();
  181. throw $e;
  182. }
  183. }
  184. /**
  185. * @param Doctrine_Record $record
  186. */
  187. protected function reorder(Doctrine_Record $record)
  188. {
  189. $table = $this->getTableForRecord($record);
  190. $name = $table->getFieldName($this->_options['name']);
  191. $key_columns = $table->getIdentifier();
  192. if (!is_array($key_columns)) {
  193. $key_columns = array($key_columns);
  194. }
  195. $ret_columns = array_merge($key_columns, array($name));
  196. /** @var Doctrine_Query $query */
  197. $query = $table->createQuery()->select(implode(',', $ret_columns))->where($name . '>= 0')->orderBy($name);
  198. foreach ($this->_options['orderableBy'] as $orderBy) {
  199. if (is_null($record->{$orderBy})) {
  200. $query->andWhere($orderBy . ' IS NULL');
  201. } else {
  202. $value = $record->{$orderBy};
  203. if ($value instanceof Doctrine_Record) {
  204. $identitier = (array)$value->identifier();
  205. $value = current($identitier);
  206. }
  207. $query->andWhere($orderBy . ' = ?', $value);
  208. }
  209. }
  210. $reorderables = $query->execute(array(), Doctrine_Core::HYDRATE_SCALAR);
  211. $query->free(true);
  212. $component_name = $table->getComponentName();
  213. $retmap = array();
  214. foreach ($key_columns as $key_column) $retmap[$component_name . '_' . $key_column] = $key_column;
  215. /** @var Doctrine_Query $query */
  216. Doctrine_Manager::getInstance()->getCurrentConnection()->standaloneQuery('SET @reorderrownum=-1;')->execute();
  217. $query = $table->createQuery()->update()->set($name, '(@reorderrownum:=@reorderrownum+1)')->where($name . ' >= 0');;
  218. foreach ($retmap as $retcol => $id_field) {
  219. $query->andWhereIn($id_field, self::array_column($reorderables, $retcol));
  220. $query->orderBy('FIELD('.$id_field.','.implode(',',self::array_column($reorderables, $retcol)).')');
  221. }
  222. $effected = $query->execute();
  223. $query->free(true);
  224. }
  225. protected static function array_column($array, $column)
  226. {
  227. foreach ($array as $row) $ret[] = $row[$column];
  228. return $ret;
  229. }
  230. /**
  231. * @param Doctrine_Record $record
  232. *
  233. * @return integer
  234. */
  235. protected function getHighestPosition(Doctrine_Record $record)
  236. {
  237. $table = $this->getTableForRecord($record);
  238. $name = $table->getFieldName($this->_options['name']);
  239. $query = $table->createQuery('r')->select('MAX(r.' . $name . ')');
  240. foreach ($this->_options['orderableBy'] as $orderBy) {
  241. if (is_null($record->{$orderBy})) {
  242. $query->andWhere('r.' . $orderBy . ' IS NULL');
  243. } else {
  244. $value = $record->{$orderBy};
  245. if ($value instanceof Doctrine_Record) {
  246. $identitier = (array)$value->identifier();
  247. $value = current($identitier);
  248. }
  249. $query->andWhere('r.' . $orderBy . ' = ?', $value);
  250. }
  251. }
  252. $max_order = $query->fetchOne(array(), Doctrine_Core::HYDRATE_SINGLE_SCALAR);
  253. $query->free();
  254. return $max_order;
  255. }
  256. /**
  257. * @param Doctrine_Record $record
  258. * @param array $order_by_vals
  259. *
  260. * @return void
  261. */
  262. protected function shiftOrder(Doctrine_Record $record, array $order_by_vals)
  263. {
  264. $table = $this->getTableForRecord($record);
  265. $name = $table->getFieldName($this->_options['name']);
  266. $query = $table->createQuery()->update()->set($name, '1+' . $name)->where($name . ' >= ' . $record->{$name});
  267. foreach ($order_by_vals as $order_by_col => $order_by_val) {
  268. if (is_null($order_by_val)) {
  269. $query->andWhere($order_by_col . ' IS NULL');
  270. } else {
  271. if ($order_by_val instanceof Doctrine_Record) {
  272. $identitier = (array)$order_by_val->identifier();
  273. $order_by_val = current($identitier);
  274. }
  275. $query->andWhere($order_by_col . ' = ?', $order_by_val);
  276. }
  277. }
  278. $query->execute();
  279. }
  280. /**
  281. * @param Doctrine_Record $record
  282. * @param array $order_by_vals
  283. *
  284. * @return void
  285. */
  286. protected function reduceOrder(Doctrine_Record $record, array $order_by_vals)
  287. {
  288. $table = $this->getTableForRecord($record);
  289. $name = $table->getFieldName($this->_options['name']);
  290. $query = $table->createQuery()->update()->set($name, "$name - 1")->where($name . ' > ' . $record->{$name});
  291. foreach ($order_by_vals as $order_by_col => $order_by_val) {
  292. if (is_null($order_by_val)) {
  293. $query->andWhere($order_by_col . ' IS NULL');
  294. } else {
  295. if ($order_by_val instanceof Doctrine_Record) {
  296. $identitier = (array)$order_by_val->identifier();
  297. $order_by_val = current($identitier);
  298. }
  299. $query->andWhere($order_by_col . ' = ?', $order_by_val);
  300. }
  301. }
  302. $query->execute();
  303. }
  304. /**
  305. * @param Doctrine_Record $record
  306. *
  307. * @return Doctrine_Table
  308. */
  309. protected function getTableForRecord(Doctrine_Record $record)
  310. {
  311. /* fix for use with Column Aggregation Inheritance */
  312. if ($record->getTable()->getOption('inheritanceMap')) {
  313. $parentTable = $record->getTable()->getOption('parents');
  314. $i = 0;
  315. // Be sure that you do not instanciate an abstract class;
  316. $reflectionClass = new ReflectionClass($parentTable[$i]);
  317. while ($reflectionClass->isAbstract()) {
  318. $i++;
  319. $reflectionClass = new ReflectionClass($parentTable[$i]);
  320. }
  321. $table = Doctrine_Core::getTable($parentTable[$i]);
  322. } else {
  323. $table = $record->getTable();
  324. }
  325. return $table;
  326. }
  327. }