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 Error {
32 function __construct($artifact, $field_id) {
33 $this->ath = $artifact;
34 $this->artifact_id = (int)$artifact->getID();
35 $this->field_id = (int)$field_id;
39 // Check if the following event is allowed or not.
40 // return true is allowed, false if not.
41 function checkEvent($from, $to) {
46 $res = db_query_params ('SELECT event_id FROM artifact_workflow_event
47 WHERE group_artifact_id=$1
51 array($this->artifact_id,
55 $event_id = db_result($res, 0, 'event_id');
57 // No role based checks for the initial transition.
61 // There is a transition, now check if current role is allowed.
63 $available_roles = RBACEngine::getInstance()->getAvailableRoles() ;
64 $project_role_ids = $this->ath->Group->getRolesId () ;
65 foreach ($available_roles as $role) {
66 if (in_array($role->getID(),$project_role_ids)) {
67 $rids[] = $role->getID() ;
71 $res = db_query_params ('SELECT event_id
72 FROM artifact_workflow_roles
76 db_int_array_to_any_clause($rids)));
77 return db_result($res, 0, 'event_id') ? true : false;
82 function getNotifyFromWorkFlow() {
87 * When a new element is created, add all the new events in the workflow.
89 function addNode($element_id) {
90 $elearray = $this->ath->getExtraFieldElements($this->field_id);
91 foreach ($elearray as $e) {
92 if ($element_id !== $e['element_id']) {
93 $this->_addEvent($e['element_id'], $element_id);
94 $this->_addEvent($element_id, $e['element_id']);
98 // Allow the new element for the Submit form (Initial values).
99 $this->_addEvent('100', $element_id);
103 * When a new element is removed, remove all the events in the workflow.
105 function removeNode($element_id) {
106 $elearray = $this->ath->getExtraFieldElements($this->field_id);
107 foreach ($elearray as $e) {
108 if ($element_id !== $e['element_id']) {
109 $this->_removeEvent($e['element_id'], $element_id);
110 $this->_removeEvent($element_id, $e['element_id']);
114 // Allow the new element for the Submit form (Initial values).
115 $this->_removeEvent('100', $element_id);
118 // Returns all the possible following nodes (no roles involved).
119 function getNextNodes($from) {
121 $res = db_query_params ('SELECT to_value_id FROM artifact_workflow_event
122 WHERE group_artifact_id=$1
124 AND from_value_id=$3',
125 array($this->artifact_id,
129 while($arr = db_fetch_array($res)) {
130 $values[] = $arr['to_value_id'];
137 function saveNextNodes($from, $nodes) {
139 // Get All possible nodes.
140 $current = $this->getNextNodes($from);
142 // Remove events no longer present.
143 foreach ($current as $node) {
144 if (!in_array($node, $nodes)) {
145 if ($from != $node) {
146 $this->_removeEvent($from, $node);
151 // Add missing events.
152 foreach ($nodes as $node) {
153 if (!in_array($node, $current)) {
154 $this->_addEvent($from, $node);
160 function getAllowedRoles($from, $to) {
161 $values = $this->_getRealAllowedRoles($from, $to);
163 // If no values, then no roles defined, all roles are allowed.
164 if (empty($values)) {
165 $roles = $this->ath->Group->getRoles() ;
166 sortRoleList($roles, $this->ath->Group) ;
167 foreach ($roles as $r) {
168 $values[] = $r->getID() ;
175 function saveAllowedRoles($from, $to, $roles) {
177 $event_id = $this->_getEventId($from, $to);
179 // Get All possible roles.
180 $current = $this->_getRealAllowedRoles($from, $to);
182 // Remove roles no longer present.
183 foreach ($current as $role) {
184 if (!in_array($role, $roles)) {
185 $this->_removeRole($event_id, $role);
189 // Add missing roles.
190 foreach ($roles as $role) {
191 if (!in_array($role, $current)) {
192 $this->_addRole($event_id, $role);
198 function _getEventId($from, $to) {
200 $res = db_query_params ('SELECT event_id FROM artifact_workflow_event
201 WHERE group_artifact_id=$1
205 array($this->artifact_id,
210 $this->setError('Unable to get Event Id ($from, $to): '.db_error());
213 return db_result($res, 0, 'event_id');
218 function _addEvent($from, $to) {
220 $res = db_query_params ('INSERT INTO artifact_workflow_event
221 (group_artifact_id, field_id, from_value_id, to_value_id)
222 VALUES ($1, $2, $3, $4)',
223 array($this->artifact_id,
228 $this->setError('Unable to add Event($from, $to): '.db_error());
232 $event_id = $this->_getEventId($from, $to);
234 // By default, all roles are allowed on a new event.
235 foreach ($this->ath->Group->getRoles() as $r) {
236 $this->_addRole($event_id, $r->getID());
243 function _removeEvent($from, $to) {
244 $event_id = $this->_getEventId($from, $to);
247 $res = db_query_params ('DELETE FROM artifact_workflow_event
248 WHERE group_artifact_id=$1
252 array($this->artifact_id,
257 $this->setError('Unable to remove Event($from, $to): '.db_error());
264 function _getRealAllowedRoles($from, $to) {
266 $res = db_query_params ('SELECT role_id
267 FROM artifact_workflow_roles, artifact_workflow_event
268 WHERE artifact_workflow_roles.event_id = artifact_workflow_event.event_id
269 AND group_artifact_id=$1
273 array($this->artifact_id,
278 while($arr = db_fetch_array($res)) {
279 $values[] = $arr['role_id'];
284 function _addRole($event_id, $role_id) {
286 $res = db_query_params ('INSERT INTO artifact_workflow_roles
292 $this->setError('Unable to add Role ($role_id): '.db_error());
299 function _removeRole($event_id, $role_id) {
301 $res = db_query_params ('DELETE FROM artifact_workflow_roles
302 WHERE event_id=$1 AND role_id=$2',
306 $this->setError('Unable to remove Event($from, $to): '.db_error());
316 * Update the required information in the workflow when a new role is created.
317 * In this case, for all the defined events, add the role as allowed.
319 function workflow_add_new_role ($role_id, $group) {
321 $res = db_query_params ('INSERT INTO artifact_workflow_roles
322 SELECT event_id, $1 as role_id
323 FROM artifact_workflow_event, artifact_group_list
324 WHERE artifact_workflow_event.group_artifact_id=artifact_group_list.group_artifact_id
325 AND artifact_group_list.group_id=$2',
329 $this->setError('Unable to register new role in workflows: '.db_error());