WorkflowConfigTransition.php 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. <?php
  2. /**
  3. * @file
  4. * Contains workflow\includes\Entity\WorkflowConfigTransition.
  5. * Contains workflow\includes\Entity\WorkflowConfigTransitionController.
  6. */
  7. /**
  8. * Implements a configurated Transition.
  9. */
  10. class WorkflowConfigTransition extends Entity {
  11. // Transition data.
  12. public $tid = 0;
  13. // public $old_sid = 0;
  14. // public $new_sid = 0;
  15. public $sid = 0; // @todo D8: remove $sid, use $new_sid. (requires conversion of Views displays.)
  16. public $target_sid = 0;
  17. public $roles = array();
  18. // Extra fields.
  19. public $wid = 0;
  20. // The following must explicitely defined, and not be public, to avoid errors when exporting with json_encode().
  21. protected $workflow = NULL;
  22. /**
  23. * Entity class functions.
  24. */
  25. /*
  26. // Implementing clone needs a list of tid-less transitions, and a conversion
  27. // of sids for both States and ConfigTransitions.
  28. // public function __clone() {}
  29. */
  30. public function __construct(array $values = array(), $entityType = NULL) {
  31. // Please be aware that $entity_type and $entityType are different things!
  32. return parent::__construct($values, $entityType = 'WorkflowConfigTransition');
  33. }
  34. /**
  35. * Permanently deletes the entity.
  36. */
  37. public function delete() {
  38. // Notify any interested modules before we delete, in case there's data needed.
  39. // @todo D8: this can be replaced by a hook_entity_delete(?)
  40. module_invoke_all('workflow', 'transition delete', $this->tid, NULL, NULL, FALSE);
  41. return parent::delete();
  42. }
  43. protected function defaultLabel() {
  44. return isset($this->label) ? t('@label', array('@label' => $this->label)) : '';
  45. }
  46. protected function defaultUri() {
  47. $wid = $this->wid;
  48. return array('path' => WORKFLOW_ADMIN_UI_PATH . "/manage/$wid/transitions/");
  49. }
  50. /**
  51. * Property functions.
  52. */
  53. /**
  54. * Returns the Workflow object of this State.
  55. *
  56. * @param Workflow $workflow
  57. * An optional workflow object. Can be used as a setter.
  58. *
  59. * @return Workflow
  60. * Workflow object.
  61. */
  62. public function setWorkflow($workflow) {
  63. $this->wid = $workflow->wid;
  64. $this->workflow = $workflow;
  65. }
  66. public function getWorkflow() {
  67. if (isset($this->workflow)) {
  68. return $this->workflow;
  69. }
  70. return workflow_load_single($this->wid);
  71. }
  72. public function getOldState() {
  73. return workflow_state_load_single($this->sid);
  74. }
  75. public function getNewState() {
  76. return workflow_state_load_single($this->target_sid);
  77. }
  78. /**
  79. * Verifies if the given transition is allowed.
  80. *
  81. * - In settings;
  82. * - In permissions;
  83. * - By permission hooks, implemented by other modules.
  84. *
  85. * @param string|array $user_roles
  86. * The string 'ALL' to force allowing the transition, or an array of role
  87. * IDs to compare against the roles allowed for the transition.
  88. *
  89. * @return bool
  90. * If the transition is allowed, this function returns TRUE. Otherwise, it
  91. * returns FALSE.
  92. */
  93. public function isAllowed($user_roles) {
  94. if ($user_roles === 'ALL') {
  95. // Superuser.
  96. return TRUE;
  97. }
  98. elseif ($user_roles) {
  99. return array_intersect($user_roles, $this->roles) == TRUE;
  100. }
  101. return TRUE;
  102. }
  103. /**
  104. * Generate a machine name for a transition.
  105. */
  106. public static function machineName($start_name, $end_name) {
  107. $new_name = sprintf("%s_to_%s", $start_name, $end_name);
  108. // Special case: replace parens in creation state transition names.
  109. $new_name = str_replace("(creation)", "_creation", $new_name);
  110. return $new_name;
  111. }
  112. public function save() {
  113. parent::save();
  114. // Ensure Workflow is marked overridden.
  115. $workflow = $this->getWorkflow();
  116. if ($workflow->status == ENTITY_IN_CODE) {
  117. $workflow->status = ENTITY_OVERRIDDEN;
  118. $workflow->save();
  119. }
  120. }
  121. /**
  122. * Helper debugging function to easily show the contents of a transition.
  123. */
  124. public function dpm($function = 'not_specified') {
  125. $transition = $this;
  126. $time = NULL;
  127. // Do this extensive $user_name lines, for some troubles with Action.
  128. $t_string = get_class($this) . ' ' . $this->identifier() . " in function '$function'";
  129. //$output[] = 'Entity = ' . ((!$entity) ? 'NULL' : ($entity_type . '/' . $entity_bundle . '/' . $entity_id));
  130. //$output[] = 'Field = ' . $transition->getFieldName();
  131. $output[] = 'From/To = ' . $transition->sid . ' > ' . $transition->target_sid . ' @ ' . $time;
  132. //$output[] = 'Comment = ' . $user_name . ' says: ' . $transition->getComment();
  133. //$output[] = 'Forced = ' . ($transition->isForced() ? 'yes' : 'no');
  134. if (function_exists('dpm')) { dpm($output, $t_string); }
  135. }
  136. }
  137. /**
  138. * Implements a controller class for WorkflowConfigTransition.
  139. *
  140. * The 'true' controller class is 'Workflow'.
  141. */
  142. class WorkflowConfigTransitionController extends EntityAPIController {
  143. /**
  144. * Overrides DrupalDefaultEntityController::cacheGet().
  145. *
  146. * Override default function, due to core issue #1572466.
  147. */
  148. protected function cacheGet($ids, $conditions = array()) {
  149. // Load any available entities from the internal cache.
  150. if ($ids === FALSE && !$conditions) {
  151. return $this->entityCache;
  152. }
  153. return parent::cacheGet($ids, $conditions);
  154. }
  155. public function save($entity, DatabaseTransaction $transaction = NULL) {
  156. $workflow = $entity->getWorkflow();
  157. // To avoid double posting, check if this transition already exist.
  158. if (empty($entity->tid)) {
  159. if ($workflow) {
  160. $config_transitions = $workflow->getTransitionsBySidTargetSid($entity->sid, $entity->target_sid);
  161. $config_transition = reset($config_transitions);
  162. if ($config_transition) {
  163. $entity->tid = $config_transition->tid;
  164. }
  165. }
  166. }
  167. // Create the machine_name. This can be used to rebuild/revert the Feature in a target system.
  168. if (empty($entity->name)) {
  169. $entity->name = $entity->sid . '_' . $entity->target_sid;
  170. }
  171. $return = parent::save($entity, $transaction);
  172. if ($return) {
  173. // Save in current workflow for the remainder of this page request.
  174. // Keep in sync with Workflow::getTransitions() !
  175. $workflow = $entity->getWorkflow();
  176. if ($workflow) {
  177. $workflow->transitions[$entity->tid] = $entity;
  178. // $workflow->sortTransitions();
  179. }
  180. }
  181. // Reset the cache for the affected workflow, to force reload upon next page_load.
  182. workflow_reset_cache($entity->wid);
  183. return $return;
  184. }
  185. }