3 * The ArtifactWorkflow class manages workflow for trackers.
5 * The workflow is attached to custom status field only.
7 * Associated tables are:
8 * - artifact_workflow_event : to track allowed events.
9 * - artifact_workflow_roles : to track roles allowed to perform an event.
10 * - artifact_workflow_notify : to track notification associated to an event (not implemented).
12 * An event is a transition from one value to another.
14 * NOTE: Code should be improved to manage any kind of custom fields not only of type
15 * 'Status' but maybe also for the 'select' also.
17 * 2008 : Alain Peyrat <alain.peyrat@alcatel-lucent.com>
20 * @todo: the getAllowedRoles should be replaced by getRealAllowedRoles code. (to be tested).
21 * @todo: Some code could use a db direct to array func instead of the while.
24 require_once $gfcommon.'include/Error.class.php';
26 class ArtifactWorkflow extends FFError {
32 function __construct($artifact, $field_id) {
33 $this->ath = $artifact;
34 $this->artifact_id = (int)$artifact->getID();
35 $this->field_id = (int)$field_id;
38 // Check if the following event is allowed or not.
39 // return true is allowed, false if not.
40 function checkEvent($from, $to) {
44 $res = db_query_params ('SELECT event_id FROM artifact_workflow_event
45 WHERE group_artifact_id=$1
49 array($this->artifact_id,
53 $event_id = db_result($res, 0, 'event_id');
55 // No role based checks for the initial transition.
59 // There is a transition, now check if current role is allowed.
61 $available_roles = RBACEngine::getInstance()->getAvailableRoles() ;
62 $project_role_ids = $this->ath->Group->getRolesId () ;
63 foreach ($available_roles as $role) {
64 if (in_array($role->getID(),$project_role_ids)) {
65 $rids[] = $role->getID() ;
69 $res = db_query_params ('SELECT event_id
70 FROM artifact_workflow_roles
74 db_int_array_to_any_clause($rids)));
75 return db_result($res, 0, 'event_id') ? true : false;
80 function getNotifyFromWorkFlow() {
85 * When a new element is created, add all the new events in the workflow.
87 function addNode($element_id) {
88 $elearray = $this->ath->getExtraFieldElements($this->field_id);
89 foreach ($elearray as $e) {
90 if ($element_id !== $e['element_id']) {
91 $this->_addEvent($e['element_id'], $element_id);
92 $this->_addEvent($element_id, $e['element_id']);
96 // Allow the new element for the Submit form (Initial values).
97 $this->_addEvent('100', $element_id);
101 * When a new element is removed, remove all the events in the workflow.
103 function removeNode($element_id) {
104 $elearray = $this->ath->getExtraFieldElements($this->field_id);
105 foreach ($elearray as $e) {
106 if ($element_id !== $e['element_id']) {
107 $this->_removeEvent($e['element_id'], $element_id);
108 $this->_removeEvent($element_id, $e['element_id']);
112 // Allow the new element for the Submit form (Initial values).
113 $this->_removeEvent('100', $element_id);
116 // Returns all the possible following nodes (no roles involved).
117 function getNextNodes($from) {
119 $res = db_query_params ('SELECT to_value_id FROM artifact_workflow_event
120 WHERE group_artifact_id=$1
122 AND from_value_id=$3',
123 array($this->artifact_id,
127 while($arr = db_fetch_array($res)) {
128 $values[] = $arr['to_value_id'];
134 function saveNextNodes($from, $nodes) {
136 // Get All possible nodes.
137 $current = $this->getNextNodes($from);
139 // Remove events no longer present.
140 foreach ($current as $node) {
141 if (!in_array($node, $nodes)) {
142 if ($from != $node) {
143 $this->_removeEvent($from, $node);
148 // Add missing events.
149 foreach ($nodes as $node) {
150 if (!in_array($node, $current)) {
151 $this->_addEvent($from, $node);
157 function getAllowedRoles($from, $to) {
158 $values = $this->_getRealAllowedRoles($from, $to);
160 // If no values, then no roles defined, all roles are allowed.
161 if (empty($values)) {
162 $roles = $this->ath->Group->getRoles() ;
163 sortRoleList($roles, $this->ath->Group) ;
164 foreach ($roles as $r) {
165 $values[] = $r->getID() ;
171 function saveAllowedRoles($from, $to, $roles) {
173 $event_id = $this->_getEventId($from, $to);
175 // Get All possible roles.
176 $current = $this->_getRealAllowedRoles($from, $to);
178 // Remove roles no longer present.
179 foreach ($current as $role) {
180 if (!in_array($role, $roles)) {
181 $this->_removeRole($event_id, $role);
185 // Add missing roles.
186 foreach ($roles as $role) {
187 if (!in_array($role, $current)) {
188 $this->_addRole($event_id, $role);
194 function _getEventId($from, $to) {
196 $res = db_query_params ('SELECT event_id FROM artifact_workflow_event
197 WHERE group_artifact_id=$1
201 array($this->artifact_id,
206 $this->setError('Unable to get Event Id ($from, $to): '.db_error());
209 return db_result($res, 0, 'event_id');
213 function _addEvent($from, $to) {
215 $res = db_query_params ('INSERT INTO artifact_workflow_event
216 (group_artifact_id, field_id, from_value_id, to_value_id)
217 VALUES ($1, $2, $3, $4)',
218 array($this->artifact_id,
223 $this->setError('Unable to add Event($from, $to): '.db_error());
227 $event_id = $this->_getEventId($from, $to);
229 // By default, all roles are allowed on a new event.
230 foreach ($this->ath->Group->getRoles() as $r) {
231 $this->_addRole($event_id, $r->getID());
238 function _removeEvent($from, $to) {
239 $event_id = $this->_getEventId($from, $to);
241 $res = db_query_params ('DELETE FROM artifact_workflow_event
242 WHERE group_artifact_id=$1
246 array($this->artifact_id,
251 $this->setError('Unable to remove Event($from, $to): '.db_error());
258 function _getRealAllowedRoles($from, $to) {
260 $res = db_query_params ('SELECT role_id
261 FROM artifact_workflow_roles, artifact_workflow_event
262 WHERE artifact_workflow_roles.event_id = artifact_workflow_event.event_id
263 AND group_artifact_id=$1
267 array($this->artifact_id,
272 while($arr = db_fetch_array($res)) {
273 $values[] = $arr['role_id'];
278 function _addRole($event_id, $role_id) {
280 $res = db_query_params ('INSERT INTO artifact_workflow_roles
286 $this->setError('Unable to add Role ($role_id): '.db_error());
293 function _removeRole($event_id, $role_id) {
295 $res = db_query_params ('DELETE FROM artifact_workflow_roles
296 WHERE event_id=$1 AND role_id=$2',
300 $this->setError('Unable to remove Event($from, $to): '.db_error());
310 * Update the required information in the workflow when a new role is created.
311 * In this case, for all the defined events, add the role as allowed.
313 function workflow_add_new_role ($role_id, $group) {
315 $res = db_query_params ('INSERT INTO artifact_workflow_roles
316 SELECT event_id, $1 as role_id
317 FROM artifact_workflow_event, artifact_group_list
318 WHERE artifact_workflow_event.group_artifact_id=artifact_group_list.group_artifact_id
319 AND artifact_group_list.group_id=$2',
323 $this->setError('Unable to register new role in workflows: '.db_error());