processID); } /** * Verifica se uma instância pertence ao processo que está sendo executado. * @param int instanceID O ID da instância. * @return bool true caso a instância pertença ao processo que está sendo executado ou, false caso contrário. * @access public */ private function checkInstanceAccess($instanceID, $activityID = null) { $instance = $this->getInstanceObject($instanceID); if ($instance === false) return false; if (!is_null($activityID)) { $activityFound = false; foreach ($instance->activities as $activity) if (($activityFound = ($activityID == $activity['wf_activity_id']))) break; if ($activityFound == false) return false; } return $this->checkProcessAccess($instance->pId); } /** * Pega o objeto de uma instância. * @param int instanceID O ID da instância. * @return mixed object caso a instância seja encontrada ou false caso contrário. * @access public */ private function getInstanceObject($instanceID) { $instanceID = (int) $instanceID; $instance = CreateObject('workflow.workflow_instance'); if (!$instance->getInstance($instanceID)) return false; else return $instance; } /** * Construtor do wf_instances. * @return object * @access public */ public function wf_instance() { /* load the DB */ $this->db = &Factory::getInstance('WorkflowObjects')->getDBGalaxia()->Link_ID; /* load the process ID from the runtime */ if (!is_null($GLOBALS['workflow']['wf_runtime']->activity)) $this->processID = (int) $GLOBALS['workflow']['wf_runtime']->activity->getProcessId(); /* if a job is running the process, then load the processID specified by the job */ if (isset($GLOBALS['workflow']['job'])) $this->processID = (int) $GLOBALS['workflow']['job']['processID']; } /** * Dá seqüência no fluxo de uma instância (simula ação do usuário). * @param int $activityID O ID da atividade da instância. * @param int $instanceID O ID da instância. * @return bool true caso a instância tenha sido continuada e false caso contrário. * @access public */ public function continueInstance($activityID, $instanceID) { /* check instanceID */ if (!$this->checkInstanceAccess($instanceID, $activityID)) return false; /* load the instance object */ $instance = $this->getInstanceObject($instanceID); $runActivity = CreateObject('workflow.run_activity'); ob_start(); $output = $runActivity->go($activityID, $instanceID, true); ob_end_clean(); return ($output !== false); } /** * Aborta uma instância * @param int $instanceID O ID da instância. * @return boolean true se foi possível abortar a instância e false caso contrário. * @access public */ public function abort($instanceID) { /* check instanceID */ if (!$this->checkInstanceAccess($instanceID)) return false; /* load the instance object */ $instance = $this->getInstanceObject($instanceID); /* abort the instance */ return $instance->abort(); } /** * Define o nome (identificador) de uma instância * @param int $instanceID O ID da instância. * @param string $name O novo nome da instância. * @return boolean true se foi possível mudar o nome da instância e false caso contrário. * @access public */ public function setName($instanceID, $name) { /* check instanceID */ if (!$this->checkInstanceAccess($instanceID)) return false; /* load the instance object */ $instance = $this->getInstanceObject($instanceID); /* set the name */ $output = $instance->setName($name); $output = $output && $instance->sync(); return $output; } /** * Define a prioridade de uma instância * @param int $instanceID O ID da instância. * @param int $priority A nova prioridade da instância * @return boolean true se foi possível mudar a prioridade da instância e false caso contrário. * @access public */ public function setPriority($instanceID, $priority) { /* check instanceID */ if (!$this->checkInstanceAccess($instanceID)) return false; /* load the instance object */ $instance = $this->getInstanceObject($instanceID); /* ensure the instance priority range */ $priority = max(min((int) $priority, 4), 0); /* set the new priority */ $output = $instance->setPriority($priority); $output = $output && $instance->sync(); return $output; } /** * Busca instâncias ativas que estão "abandonadas". * @param int $numberOfDays O tempo (em dias) em que a instância está abandonada. * @param array $activities Uma lista de atividades das quais se quer as instâncias abandonadas (também pode ser um valor inteiro). * @return array As instâncias que satisfazem o critério de seleção. * @access public */ public function getIdle($numberOfDays, $activities = null) { /* prepare some variables */ $output = array(); $restrictToActivities = !is_null($activities); if (is_numeric($activities)) $activities = array((int) $activities); if (is_numeric($numberOfDays)) $numberOfDays = (int) $numberOfDays; else return $output; /* restrict the range and get the threshold date (in UNIX ERA format) */ $numberOfDays = max(0, $numberOfDays); $threshold = time() - ($numberOfDays * 24 * 60 * 60); /* build the SQL query */ $query = 'SELECT ia.wf_instance_id AS wf_instance_id, ia.wf_activity_id AS wf_activity_id, ia.wf_started AS wf_started, i.wf_name AS wf_name, i.wf_status AS wf_status, ia.wf_user AS wf_user, i.wf_priority AS wf_priority '; $query .= 'FROM egw_wf_instance_activities ia, egw_wf_instances i '; $query .= 'WHERE (ia.wf_instance_id = i.wf_instance_id) AND (i.wf_p_id = ?) AND (ia.wf_started < ?)'; $resultSet = $this->db->query($query, array($this->processID, $threshold)); /* fetch the results */ while ($row = $resultSet->fetchRow()) { /* if required, restrict to specific activities */ if ($restrictToActivities) if (!in_array($row['wf_activity_id'], $activities)) continue; $output[] = $row; } return $output; } /** * Busca todas as instâncias ativas. * @param array $activities Uma lista de atividades das quais se quer as instâncias (também pode ser um valor inteiro). * @return array As instâncias que satisfazem o critério de seleção. * @access public */ public function getAll($activities = null) { return $this->getIdle(0, $activities); } /** * Busca as instâncias filhas de uma instância * Se os parâmetros não forem informados, retorna instâncias filhas das instância atual. * @param int $instanceID O ID da instância pai (não obrigatório). * @param int $activityID O ID da atividade corrente da instância pai * @return array As instâncias filhas do par instância/atividade atual * @access public */ public function getChildren($instanceID = null, $activityID = null) { $output = array(); if (is_null($instanceID)) $instanceID = $GLOBALS['workflow']['wf_runtime']->instance_id; if (is_null($activityID)) $activityID = $GLOBALS['workflow']['wf_runtime']->activity_id; /* check instanceID */ if (!$this->checkInstanceAccess($instanceID, $activityID)) return $output; /* build the SQL query */ $query = 'SELECT i.wf_instance_id AS wf_instance_id, ia.wf_activity_id AS wf_activity_id, ia.wf_started AS wf_started, i.wf_name AS wf_name, i.wf_status AS wf_status, ia.wf_user AS wf_user, ir.wf_parent_lock AS wf_parent_lock '; $query .= 'FROM egw_wf_interinstance_relations ir, egw_wf_instances i LEFT JOIN egw_wf_instance_activities ia ON (ia.wf_instance_id = i.wf_instance_id)'; $query .= 'WHERE (ir.wf_child_instance_id = i.wf_instance_id) AND (ir.wf_parent_instance_id = ?) AND (ir.wf_parent_activity_id = ?)'; $result = $this->db->query($query, array($instanceID, $activityID)); $output = $result->GetArray(-1); return $output; } /** * Busca as propriedades de uma instância (do mesmo processo). * @param int $instanceID O ID da instância. * @return mixed Uma array contento as propriedades da instância (no formato "nome_da_propriedade" => "valor"). Ou false em caso de erro. * @access public */ public function getProperties($instanceID) { /* check instanceID */ if (!$this->checkInstanceAccess($instanceID)) return false; /* load the properties of the instance object */ return $this->getInstanceObject($instanceID)->properties; } /** * Define uma propriedade de uma instância. * @param int $instanceID O ID da instância. * @return bool true caso a propriedade tenha sido alterada com sucesso * @access public */ public function setProperty($instanceID, $propertyName, $propertyValue) { /* check instanceID */ if (!$this->checkInstanceAccess($instanceID)) return false; /* load the instance object */ $instance = $this->getInstanceObject($instanceID); /* set the property */ $output = $instance->set($propertyName, $propertyValue); $output = $output && $instance->sync(); return $output; } /** * Busca as instância de usuários de acordo com alguns critérios * @param mixed $users Um array com IDs de usuários ou perfis (no caso de perfis, deve-se prefixar seu ID com o caractere 'p'). Também pode possuir um único ID (seja de usuário ou de perfil) * @param mixed $activities Um array com IDs de atividades das se quer as instâncias. Também pode ser um inteiro, representando um único ID. Caso possua valor null, o resultado não é filtrado de acordo com as atividades (parâmetro opcional) * @param mixed $status Um array com os status requeridos (para filtrar as instâncias). Também pode ser uma string, representando um único status. Caso possua valor null, o resultado não é filtrado de acordo com o status. Os status podem ser: completed, active, aborted e exception (parâmetro opcional) * @return array As instâncias que satisfazem o critério de seleção. * @access public */ public function getByUser($users, $activities = null, $status = null) { /* check for the supplied users/roles */ if (empty($users)) return array(); if (!is_array($users)) $users = array($users); foreach ($users as &$user) { if (!eregi('^[p]{0,1}[0-9]+$', "$user")) trigger_error('wf_engine::getUserInstances: O usuário/perfil "' . $user . '" é inválido', E_USER_ERROR); $user = "'{$user}'"; } /* check for activity restriction */ $restrictToActivities = !is_null($activities); if (!is_array($activities)) $activities = array((int) $activities); array_walk($activities, create_function('&$a', '$a = (int) $a;')); /* check for status restriction */ $statusPossibleValues = array('completed', 'active', 'aborted', 'exception'); $restrictToStatus = !is_null($status); if (is_string($status)) $status = array($status); /* check if the supplied status are valid */ if ($restrictToStatus) { array_walk($status, create_function('&$a', '$a = strtolower($a);')); foreach ($status as $currentStatus) if (!in_array($currentStatus, $statusPossibleValues)) trigger_error('wf_engine::getUserInstances: O status "' . $currentStatus . '" é inválido', E_USER_ERROR); array_walk($status, create_function('&$a', '$a = "\'$a\'";')); } /* build the SQL query */ $query = "SELECT ia.wf_instance_id AS wf_instance_id, ia.wf_activity_id AS wf_activity_id, ia.wf_started AS wf_started, i.wf_name AS wf_name, i.wf_status AS wf_status, ia.wf_user AS wf_user, i.wf_priority AS wf_priority "; $query .= "FROM egw_wf_instance_activities ia, egw_wf_instances i "; $query .= "WHERE (ia.wf_instance_id = i.wf_instance_id) AND (i.wf_p_id = ?) AND (ia.wf_user IN (" . implode(', ', $users) . "))"; $values = array($this->processID); if ($restrictToActivities) { $query .= ' AND (ia.wf_activity_id = ANY (?))'; $values[] = '{' . implode(', ', $activities) . '}'; } if ($restrictToStatus) { $query .= ' AND (i.wf_status IN (?))'; $values[] = '{' . implode(', ', $status) . '}'; } $resultSet = $this->db->query($query, $values); /* fetch and return the results */ return $resultSet->GetArray(-1); } /** * Busca todas as instâncias que possuem esse nome (identificador). * @param string $name O nome da instância que se quer encontrar. * @return array As instâncias que satisfazem o critério de seleção. * @access public */ public function getByName($name) { /* build the SQL query */ $query = 'SELECT i.wf_instance_id AS wf_instance_id, ia.wf_activity_id AS wf_activity_id, ia.wf_started AS wf_started, i.wf_name AS wf_name, i.wf_status AS wf_status, ia.wf_user AS wf_user, i.wf_priority AS wf_priority '; $query .= 'FROM egw_wf_instances i LEFT JOIN egw_wf_instance_activities ia ON (ia.wf_instance_id = i.wf_instance_id)'; $query .= 'WHERE (i.wf_p_id = ?) AND (UPPER(i.wf_name) = UPPER(?))'; $resultSet = $this->db->query($query, array($this->processID, $name)); return $resultSet->GetArray(); } /** * Verifica se um dado usuário tem acesso a uma instância * @param int $userID O ID do usuário que se quer verificar * @param int $instanceID O ID da instância * @param int $activityID O ID da atividade onde a instância está * @param bool $writeAccess Se true, indica que é necessário que o usuário tenha acesso para modificar a instância (dar seqüência ao fluxo). Se false, não será verificado se o usuário tem permissão de escrita na instância * @return bool true se o usuário tiver acesso à instância (levando em consideração $writeAccess) ou false caso contrário * @access public */ public function checkUserAccess($userID, $instanceID, $activityID, $writeAccess = true) { /* only integers are allowed */ $userID = (int) $userID; $instanceID = (int) $instanceID; $activityID = (int) $activityID; /* load the required instance (for the required user) */ require_once GALAXIA_LIBRARY . SEP . 'src' . SEP . 'GUI' . SEP . 'GUI.php'; $GUI = new GUI(Factory::getInstance('WorkflowObjects')->getDBGalaxia()->Link_ID); $userInstance = $GUI->gui_list_user_instances($userID, 0, -1, '', '', "(ga.wf_is_interactive = 'y') AND (gia.wf_activity_id = {$activityID}) AND (gia.wf_instance_id = {$instanceID})", false, $this->processID, true, false, true, false, false, false); $userInstance = $userInstance['data']; /* if no instance is found, the user does not have access to it */ if (empty($userInstance)) return false; /* if no write access is required, then the user have access to the instance */ if (!$writeAccess) return true; /* write access is required, check for it */ return ($userInstance['wf_readonly'] == 0); } /** * Define o usuário de uma instância (em uma atividade) * @param int $instanceID O ID da instância. * @param int $activityID O ID da atividade. * @param int $userID O ID do usuário. * @return boolean true se foi possível definir o usuário da instância ou false caso contrário. * @access public */ public function setUser($instanceID, $activityID, $userID) { /* check instanceID and activityID */ if (!$this->checkInstanceAccess($instanceID, $activityID)) return false; if ($userID !== '*') { require_once dirname(__FILE__) . '/class.wf_role.php'; require_once dirname(__FILE__) . '/class.wf_engine.php'; $wfRole = new wf_role(); $engine = new wf_engine(); /* get information about the activity */ if (($activityInfo = $engine->getActivityInformationByID($activityID)) === false) return false; /* load the possible roles of the activity */ $possibleRoles = $wfRole->getActivityRoles($activityInfo['name']); if (substr($userID, 0, 1) == 'p') { /* the instance is being set to a role */ /* check if the role is valid */ $roleID = (int) substr($userID, 1); $userID = 'p' . $roleID; $validRole = false; foreach ($possibleRoles as $possibleRole) { if ($roleID == $possibleRole['id']) { $validRole = true; break; } } if (!$validRole) return false; } else { /* the instance is being set to a user */ /* check if the $userID is a number */ if (!is_numeric($userID)) return false; /* check if the user is valid */ $userID = (int) $userID; $validUser = false; foreach ($possibleRoles as $possibleRole) { if ($wfRole->checkUserInRole($userID, $possibleRole['name'])) { $validUser = true; break; } } if (!$validUser) return false; } } $query = 'UPDATE egw_wf_instance_activities SET wf_user = ? WHERE (wf_instance_id = ?) AND (wf_activity_id = ?)'; $this->db->execute($query, array($userID, $instanceID, $activityID)); return true; } /** * Define o perfil que poderá acessar uma instância (em uma atividade) * @param int $instanceID O ID da instância. * @param int $activityID O ID da atividade. * @param string $roleName O nome do perfil. * @return boolean true se foi possível definir o perfil da instância ou false caso contrário. * @access public */ public function setRole($instanceID, $activityID, $roleName) { /* check instanceID and activityID */ if (!$this->checkInstanceAccess($instanceID, $activityID)) return false; /* try to get the role id */ require_once dirname(__FILE__) . '/class.wf_role.php'; $wfRole = new wf_role(); if (($roleID = $wfRole->getRoleIdByName($roleName)) === false) return false; return $this->setUser($instanceID, $activityID, 'p' . $roleID); } } ?>