/core/classes/TBGWorkflow.class.php

https://github.com/pb30/thebuggenie · PHP · 336 lines · 193 code · 39 blank · 104 comment · 21 complexity · 899a731b06e83f2e91902688017bb18c MD5 · raw file

  1. <?php
  2. /**
  3. * Workflow class
  4. *
  5. * @author Daniel Andre Eikeland <zegenie@zegeniestudios.net>
  6. * @version 3.0
  7. * @license http://www.opensource.org/licenses/mozilla1.1.php Mozilla Public License 1.1 (MPL 1.1)
  8. * @package thebuggenie
  9. * @subpackage core
  10. */
  11. /**
  12. * Workflow class
  13. *
  14. * @package thebuggenie
  15. * @subpackage core
  16. *
  17. * @Table(name="TBGWorkflowsTable")
  18. */
  19. class TBGWorkflow extends TBGIdentifiableScopedClass
  20. {
  21. protected static $_workflows = null;
  22. protected static $_num_workflows = null;
  23. /**
  24. * The name of the object
  25. *
  26. * @var string
  27. * @Column(type="string", length=200)
  28. */
  29. protected $_name;
  30. /**
  31. * The workflow description
  32. *
  33. * @var string
  34. * @Column(type="string", length=200)
  35. */
  36. protected $_description = null;
  37. /**
  38. * Whether the workflow is active or not
  39. *
  40. * @var boolean
  41. * @Column(type="boolean")
  42. */
  43. protected $_is_active = true;
  44. /**
  45. * This workflow's steps
  46. *
  47. * @var array|TBGWorkflowStep
  48. * @Relates(class="TBGWorkflowStep", collection=true, foreign_column="workflow_id")
  49. */
  50. protected $_steps = null;
  51. protected $_num_steps = null;
  52. /**
  53. * This workflow's transitions
  54. *
  55. * @var array|TBGWorkflowTransition
  56. * @Relates(class="TBGWorkflowTransition", collection=true, foreign_column="workflow_id")
  57. */
  58. protected $_transitions = null;
  59. /**
  60. * This workflow's schemes
  61. *
  62. * @var array|TBGWorkflowTransition
  63. * @Relates(class="TBGWorkflowScheme", collection=true, manytomany=true, joinclass="TBGWorkflowIssuetypeTable")
  64. */
  65. protected $_schemes = null;
  66. protected $_num_schemes = null;
  67. protected static function _populateWorkflows()
  68. {
  69. if (self::$_workflows === null)
  70. {
  71. self::$_workflows = TBGWorkflowsTable::getTable()->getAll();
  72. }
  73. }
  74. /**
  75. * Return all workflows in the system
  76. *
  77. * @return array An array of TBGWorkflow objects
  78. */
  79. public static function getAll()
  80. {
  81. self::_populateWorkflows();
  82. return self::$_workflows;
  83. }
  84. public static function loadFixtures(TBGScope $scope)
  85. {
  86. $workflow = new TBGWorkflow();
  87. $workflow->setName("Default workflow");
  88. $workflow->setDescription("This is the default workflow. It is used by all projects with no specific workflow selected, and for issue types with no specific workflow specified. This workflow cannot be edited or removed.");
  89. $workflow->setScope($scope->getID());
  90. $workflow->save();
  91. TBGSettings::saveSetting(TBGSettings::SETTING_DEFAULT_WORKFLOW, $workflow->getID(), 'core', $scope->getID());
  92. TBGWorkflowStep::loadFixtures($scope, $workflow);
  93. }
  94. public static function getWorkflowsCount()
  95. {
  96. if (self::$_num_workflows === null)
  97. {
  98. if (self::$_workflows !== null)
  99. self::$_num_workflows = count(self::$_workflows);
  100. else
  101. self::$_num_workflows = TBGWorkflowsTable::getTable()->countWorkflows();
  102. }
  103. return self::$_num_workflows;
  104. }
  105. public static function getCustomWorkflowsCount()
  106. {
  107. return self::getWorkflowsCount() - 1;
  108. }
  109. /**
  110. * Returns the workflows description
  111. *
  112. * @return string
  113. */
  114. public function getDescription()
  115. {
  116. return $this->_description;
  117. }
  118. /**
  119. * Set the workflows description
  120. *
  121. * @param string $description
  122. */
  123. public function setDescription($description)
  124. {
  125. $this->_description = $description;
  126. }
  127. /**
  128. * Whether this is the builtin workflow that cannot be
  129. * edited or removed
  130. *
  131. * @return boolean
  132. */
  133. public function isCore()
  134. {
  135. return ($this->getID() == TBGSettings::getCoreWorkflow()->getID());
  136. }
  137. /**
  138. * Whether this is the builtin workflow that cannot be edited or removed
  139. *
  140. * @return boolean
  141. */
  142. public function isActive()
  143. {
  144. return (bool) $this->_is_active;
  145. }
  146. protected function _populateTransitions()
  147. {
  148. if ($this->_transitions === null)
  149. {
  150. $this->_b2dbLazyload('_transitions');
  151. }
  152. }
  153. /**
  154. * Get all transitions in this workflow
  155. *
  156. * @return array An array of TBGWorkflowTransition objects
  157. */
  158. public function getTransitions()
  159. {
  160. $this->_populateTransitions();
  161. return $this->_transitions;
  162. }
  163. protected function _populateSteps()
  164. {
  165. if ($this->_steps === null)
  166. {
  167. $this->_b2dbLazyload('_steps');
  168. }
  169. }
  170. /**
  171. * Get all steps in this workflow
  172. *
  173. * @return array An array of TBGWorkflowStep objects
  174. */
  175. public function getSteps()
  176. {
  177. $this->_populateSteps();
  178. return $this->_steps;
  179. }
  180. /**
  181. * Get the first step in this workflow
  182. *
  183. * @return TBGWorkflowStep
  184. */
  185. public function getFirstStep()
  186. {
  187. $steps = $this->getSteps();
  188. return (is_array($steps)) ? array_shift($steps) : null;
  189. }
  190. public function getNumberOfSteps()
  191. {
  192. if ($this->_num_steps === null && $this->_steps !== null)
  193. {
  194. $this->_num_steps = count($this->_steps);
  195. }
  196. elseif ($this->_num_steps === null)
  197. {
  198. $this->_b2dbLazycount('_steps');
  199. }
  200. return $this->_num_steps;
  201. }
  202. public function isInUse()
  203. {
  204. return (bool) $this->getNumberOfSchemes();
  205. }
  206. public function getNumberOfSchemes()
  207. {
  208. if ($this->_num_schemes === null && $this->_schemes !== null)
  209. {
  210. $this->_num_schemes = count($this->_schemes);
  211. }
  212. elseif ($this->_num_schemes === null)
  213. {
  214. $this->_num_schemes = $this->_b2dbLazycount('_schemes');
  215. }
  216. return $this->_num_schemes;
  217. }
  218. public function copy($new_name)
  219. {
  220. $new_workflow = new TBGWorkflow();
  221. $new_workflow->setName($new_name);
  222. $new_workflow->save();
  223. $step_mapper = array();
  224. $transition_mapper = array();
  225. foreach ($this->getSteps() as $key => $step)
  226. {
  227. $this->_steps[$key] = $step->copy($new_workflow);
  228. $step_mapper[$key] = $this->_steps[$key]->getID();
  229. }
  230. foreach ($this->getTransitions() as $key => $transition)
  231. {
  232. $old_id = $transition->getID();
  233. $this->_transitions[$key] = $transition->copy($new_workflow);
  234. $transition_mapper[$old_id] = $this->_transitions[$key]->getID();
  235. }
  236. TBGWorkflowStepTransitionsTable::getTable()->copyByWorkflowIDs($this->getID(), $new_workflow->getID());
  237. TBGWorkflowStepTransitionsTable::getTable()->reMapStepIDsByWorkflowID($new_workflow->getID(), $step_mapper);
  238. TBGWorkflowTransitionsTable::getTable()->reMapByWorkflowID($new_workflow->getID(), $step_mapper);
  239. TBGWorkflowStepTransitionsTable::getTable()->reMapTransitionIDsByWorkflowID($new_workflow->getID(), $transition_mapper);
  240. return $new_workflow;
  241. }
  242. public function moveIssueToMatchingWorkflowStep(TBGIssue $issue)
  243. {
  244. $change_step = false;
  245. if ($issue->isStatusChanged() || $issue->isResolutionChanged())
  246. {
  247. $change_step = true;
  248. }
  249. if ($change_step)
  250. {
  251. foreach ($this->getSteps() as $step)
  252. {
  253. if ($step->hasLinkedStatus() && $issue->getStatus() instanceof TBGStatus && $step->getLinkedStatusID() == $issue->getStatus()->getID())
  254. {
  255. $step->applyToIssue($issue);
  256. return true;
  257. }
  258. }
  259. foreach ($this->getSteps() as $step)
  260. {
  261. if (!$step->hasLinkedStatus())
  262. {
  263. foreach ($step->getIncomingTransitions() as $transition)
  264. {
  265. if ($transition->hasPostValidationRule(TBGWorkflowTransitionValidationRule::RULE_STATUS_VALID))
  266. {
  267. $rule = $transition->getPostValidationRule(TBGWorkflowTransitionValidationRule::RULE_STATUS_VALID);
  268. if ($rule->isValid($issue->getStatus()))
  269. {
  270. $step->applyToIssue($issue);
  271. return true;
  272. }
  273. }
  274. }
  275. }
  276. }
  277. }
  278. }
  279. /**
  280. * Return the items name
  281. *
  282. * @return string
  283. */
  284. public function getName()
  285. {
  286. return $this->_name;
  287. }
  288. /**
  289. * Set the edition name
  290. *
  291. * @param string $name
  292. */
  293. public function setName($name)
  294. {
  295. $this->_name = $name;
  296. }
  297. }