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 ArtifactWorkflow($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 $res = db_query_params ('SELECT event_id
64 FROM user_group, artifact_workflow_roles
68 AND user_group.role_id=artifact_workflow_roles.role_id',
70 $this->ath->Group->getID(),
72 return db_result($res, 0, 'event_id') ? true : false;
77 function getNotifyFromWorkFlow() {
82 * When a new element is created, add all the new events in the workflow.
84 function addNode($element_id) {
85 $elearray = $this->ath->getExtraFieldElements($this->field_id);
86 foreach ($elearray as $e) {
87 if ($element_id !== $e['element_id']) {
88 $this->_addEvent($e['element_id'], $element_id);
89 $this->_addEvent($element_id, $e['element_id']);
93 // Allow the new element for the Submit form (Initial values).
94 $this->_addEvent('100', $element_id);
98 * When a new element is removed, remove all the events in the workflow.
100 function removeNode($element_id) {
101 $elearray = $this->ath->getExtraFieldElements($this->field_id);
102 foreach ($elearray as $e) {
103 if ($element_id !== $e['element_id']) {
104 $this->_removeEvent($e['element_id'], $element_id);
105 $this->_removeEvent($element_id, $e['element_id']);
109 // Allow the new element for the Submit form (Initial values).
110 $this->_removeEvent('100', $element_id);
113 // Returns all the possible following nodes (no roles involved).
114 function getNextNodes($from) {
116 $res = db_query_params ('SELECT to_value_id FROM artifact_workflow_event
117 WHERE group_artifact_id=$1
119 AND from_value_id=$3',
120 array($this->artifact_id,
124 while($arr = db_fetch_array($res)) {
125 $values[] = $arr['to_value_id'];
132 function saveNextNodes($from, $nodes) {
134 // Get All possible nodes.
135 $current = $this->getNextNodes($from);
137 // Remove events no longer present.
138 foreach ($current as $node) {
139 if (!in_array($node, $nodes)) {
140 if ($from != $node) {
141 $this->_removeEvent($from, $node);
146 // Add missing events.
147 foreach ($nodes as $node) {
148 if (!in_array($node, $current)) {
149 $this->_addEvent($from, $node);
155 function getAllowedRoles($from, $to) {
156 $values = $this->_getRealAllowedRoles($from, $to);
158 // If no values, then no roles defined, all roles are allowed.
159 if (empty($values)) {
160 $res=db_query_params ('SELECT role_id
161 FROM role WHERE group_id=$1 ORDER BY role_name',
162 array($this->ath->Group->getID()));
163 while($arr = db_fetch_array($res)) {
164 $values[] = $arr['role_id'];
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');
214 function _addEvent($from, $to) {
216 $res = db_query_params ('INSERT INTO artifact_workflow_event
217 (group_artifact_id, field_id, from_value_id, to_value_id)
218 VALUES ($1, $2, $3, $4)',
219 array($this->artifact_id,
224 $this->setError('Unable to add Event($from, $to): '.db_error());
228 $event_id = $this->_getEventId($from, $to);
230 // By default, all roles are allowed on a new event.
231 $res=db_query_params ('SELECT role_id
232 FROM role WHERE group_id=$1 ORDER BY role_name',
233 array($this->ath->Group->getID()));
234 while($arr = db_fetch_array($res)) {
235 $this->_addRole($event_id, $arr['role_id']);
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());