View source
<?php
include_once 'WorkflowInterface.php';
class Workflow extends Entity implements WorkflowInterface {
public $wid = 0;
public $name = '';
public $tab_roles = array();
public $options = array();
protected $creation_sid = 0;
protected $rebuilding = FALSE;
public $states = NULL;
public $transitions = NULL;
public function __clone() {
foreach ($this->states as &$state) {
$state = clone $state;
}
foreach ($this->transitions as &$transition) {
$transition = clone $transition;
}
}
public function save($create_creation_state = TRUE) {
$is_new = !empty($this->is_new);
$is_rebuild = !empty($this->is_rebuild) || !empty($this->is_reverted);
if ($is_rebuild) {
$this->is_rebuild = TRUE;
$this
->preRebuild();
}
$return = parent::save();
if ($is_new || $is_rebuild) {
$this
->rebuildInternals();
if ($is_rebuild) {
$this->status = ENTITY_IN_CODE;
parent::save();
}
}
if ($is_new) {
$state = $this
->getCreationState();
}
workflow_reset_cache($this->wid);
return $return;
}
protected function preRebuild() {
$this->tab_roles = $this
->rebuildRoles($this->tab_roles);
if (empty($this->label)) {
$this->label = $this->name;
}
}
protected function rebuildInternals() {
if ($this->rebuilding) {
return;
}
$this->rebuilding = TRUE;
if (isset($this->typeMap)) {
foreach ($this->typeMap as $node_type) {
workflow_insert_workflow_type_map($node_type, $this->wid);
}
}
$db_name_map = WorkflowState::getStates($this->wid, TRUE);
$db_states = array();
foreach ($db_name_map as $state) {
$db_states[$state
->getName()] = $state;
}
$db_transitions = array();
foreach (entity_load('WorkflowConfigTransition') as $transition) {
if ($transition->wid == $this->wid) {
$start_name = $db_name_map[$transition->sid]
->getName();
$end_name = $db_name_map[$transition->target_sid]
->getName();
$name = WorkflowConfigTransition::machineName($start_name, $end_name);
$db_transitions[$name] = $transition;
}
}
$states = isset($this->states) ? $this->states : array();
$saved_states = array();
$saved_state_names = array();
foreach ($states as $key => $data) {
$data = (array) $data;
$name = $data['name'];
if (isset($db_states[$name])) {
$state = $db_states[$name];
}
else {
$state = $this
->createState($name, FALSE);
}
$state->wid = $this->wid;
$state->state = $data['state'];
$state->weight = $data['weight'];
$state->sysid = $data['sysid'];
if (!$data['status']) {
$this
->rebuildStateInactive($state);
}
$state->status = $data['status'];
$state
->save();
unset($db_states[$name]);
$saved_states[$key] = $state;
$saved_state_names[$state->sid] = $key;
}
$transitions = isset($this->transitions) ? $this->transitions : array();
foreach ($transitions as $name => $data) {
$data = (array) $data;
if (is_numeric($name)) {
if (isset($saved_states[$data['sid']]) && isset($saved_states[$data['target_sid']])) {
$start_state = $saved_states[$data['sid']];
$end_state = $saved_states[$data['target_sid']];
}
else {
$start_state = $this
->getState($data['sid']);
$end_state = $this
->getState($data['target_sid']);
}
}
else {
$start_state = $saved_states[$data['start_state']];
$end_state = $saved_states[$data['end_state']];
}
$name = WorkflowConfigTransition::machineName($start_state
->getName(), $end_state
->getName());
if (isset($db_transitions[$name])) {
$transition = $db_transitions[$name];
}
else {
$transition = $this
->createTransition($start_state->sid, $end_state->sid);
}
$transition->wid = $this->wid;
$transition->sid = $start_state->sid;
$transition->target_sid = $end_state->sid;
$transition->label = $data['label'];
$transition->roles = $this
->rebuildRoles($data['roles']);
$transition
->save();
unset($db_transitions[$name]);
}
foreach ($db_states as $state) {
$this
->rebuildStateInactive($state);
$state
->delete();
}
foreach ($db_transitions as $transition) {
$transition
->delete();
}
$this->states = $this->transitions = NULL;
$this
->getStates(TRUE, TRUE);
$this
->getTransitions(FALSE, array(), TRUE);
$this->rebuilding = FALSE;
}
protected function rebuildStateInactive($state) {
if (!$state
->isActive()) {
return;
}
$state
->deactivate(NULL);
}
public function delete() {
$wid = $this->wid;
module_invoke_all('workflow', 'workflow delete', $wid, NULL, NULL, FALSE);
foreach ($this
->getStates($all = TRUE) as $state) {
$state
->deactivate(0);
$state
->delete();
}
db_delete('workflows')
->condition('wid', $wid)
->execute();
}
public function isValid() {
$is_valid = TRUE;
$workflow_name = $this
->getName();
$wid = $this
->getWorkflowId();
$states = $this
->getStates($all = FALSE);
if (count($states) < 1) {
$message = t('Workflow %workflow has no states defined, so it cannot be assigned to content yet.', array(
'%workflow' => $workflow_name,
));
drupal_set_message($message, 'warning');
$is_valid = FALSE;
}
$transitions = $this
->getTransitionsBySid($this
->getCreationSid(), $roles = 'ALL');
if (count($transitions) < 1) {
$message = t('Workflow %workflow has no transitions defined, so it cannot be assigned to content yet.', array(
'%workflow' => $workflow_name,
));
drupal_set_message($message, 'warning');
$is_valid = FALSE;
}
if ($this
->getTypeMap() && !count($this->options)) {
$message = t('Please maintain Workflow %workflow on its <a href="@url">settings</a> page.', array(
'%workflow' => $this
->getName(),
'@url' => url(WORKFLOW_ADMIN_UI_PATH . "/manage/{$wid}"),
));
drupal_set_message($message, 'warning');
}
return $is_valid;
}
public function isDeletable() {
$is_deletable = FALSE;
if ($this
->getTypeMap()) {
return $is_deletable;
}
foreach (_workflow_info_fields() as $field) {
if ($field['settings']['wid'] == $this->wid) {
return $is_deletable;
}
}
foreach ($this
->getStates(TRUE) as $state) {
if ($state
->count()) {
return $is_deletable;
}
}
$is_deletable = TRUE;
return $is_deletable;
}
public function getWorkflowId() {
return $this->wid;
}
public function createState($name, $save = TRUE) {
$wid = $this->wid;
$state = workflow_state_load_by_name($name, $wid);
if (!$state) {
$state = entity_create('WorkflowState', array(
'name' => $name,
'state' => $name,
'wid' => $wid,
));
if ($save) {
$state
->save();
}
}
$state
->setWorkflow($this);
$this->states[$state->sid] = $state;
return $state;
}
public function getCreationState() {
$sid = $this
->getCreationSid();
return $sid ? $this
->getState($sid) : $this
->createState(WORKFLOW_CREATION_STATE_NAME);
}
public function getCreationSid() {
if (!$this->creation_sid) {
foreach ($this
->getStates($all = TRUE) as $state) {
if ($state
->isCreationState()) {
$this->creation_sid = $state->sid;
}
}
}
return $this->creation_sid;
}
public function getFirstSid($entity_type, $entity, $field_name, $user, $force) {
$creation_state = $this
->getCreationState();
$options = $creation_state
->getOptions($entity_type, $entity, $field_name, $user, $force);
if ($options) {
$keys = array_keys($options);
$sid = $keys[0];
}
else {
drupal_set_message(t('There are no workflow states available. Please notify your site administrator.'), 'error');
$sid = 0;
}
return $sid;
}
public function getNextSid($entity_type, $entity, $field_name, $user, $force = FALSE) {
$new_sid = workflow_node_current_state($entity, $entity_type, $field_name);
if ($new_sid && ($new_state = workflow_state_load_single($new_sid))) {
$options = $new_state
->getOptions($entity_type, $entity, $field_name, $user, $force);
$flag = $new_state
->isCreationState();
foreach ($options as $sid => $name) {
if ($flag) {
$new_sid = $sid;
break;
}
if ($sid == $new_state->sid) {
$flag = TRUE;
}
}
}
return $new_sid;
}
public function getStates($all = FALSE, $reset = FALSE) {
if ($this->states === NULL || $reset) {
$this->states = $this->wid ? WorkflowState::getStates($this->wid, $reset) : array();
}
$states = array();
foreach ($this->states as $state) {
if ($all === TRUE) {
$states[$state->sid] = $state;
}
elseif ($all === FALSE && ($state
->isActive() && !$state
->isCreationState())) {
$states[$state->sid] = $state;
}
elseif ($all == 'CREATION' && ($state
->isActive() || $state
->isCreationState())) {
$states[$state->sid] = $state;
}
}
return $states;
}
public function getState($key) {
if (is_numeric($key)) {
return workflow_state_load_single($key, $this->wid);
}
else {
return workflow_state_load_by_name($key, $this->wid);
}
}
public function createTransition($sid, $target_sid, $values = array()) {
$workflow = $this;
if (is_numeric($sid) && is_numeric($target_sid)) {
$values['sid'] = $sid;
$values['target_sid'] = $target_sid;
}
else {
$state = $workflow
->getState($sid);
$target_state = $workflow
->getState($target_sid);
$values['sid'] = $state->sid;
$values['target_sid'] = $target_state->sid;
}
if ($transitions = entity_load('WorkflowConfigTransition', FALSE, $values)) {
$transition = reset($transitions);
}
else {
$values['wid'] = $workflow->wid;
$transition = entity_create('WorkflowConfigTransition', $values);
$transition
->save();
}
$transition
->setWorkflow($this);
$this->transitions[$transition->tid] = $transition;
return $transition;
}
public function sortTransitions() {
usort($this->transitions, '_workflow_transitions_sort_by_weight');
}
public function getTransitions($tids = FALSE, array $conditions = array(), $reset = FALSE) {
$config_transitions = array();
$states = $this
->getStates('CREATION');
$sid = isset($conditions['sid']) ? $conditions['sid'] : FALSE;
$target_sid = isset($conditions['target_sid']) ? $conditions['target_sid'] : FALSE;
$roles = isset($conditions['roles']) ? $conditions['roles'] : 'ALL';
if ($this->transitions === NULL) {
$this->transitions = array();
$config_transitions = entity_load('WorkflowConfigTransition', $tids, array(), $reset);
foreach ($config_transitions as &$config_transition) {
if (isset($states[$config_transition->sid])) {
$config_transition
->setWorkflow($this);
$this->transitions[$config_transition->tid] = $config_transition;
}
}
$this
->sortTransitions();
}
$config_transitions = array();
foreach ($this->transitions as &$config_transition) {
if (!isset($states[$config_transition->sid])) {
}
elseif ($sid && $sid != $config_transition->sid) {
}
elseif ($target_sid && $target_sid != $config_transition->target_sid) {
}
elseif ($roles == 'ALL' || $config_transition
->isAllowed($roles)) {
$config_transition
->setWorkflow($this);
$config_transitions[$config_transition->tid] = $config_transition;
}
else {
}
}
return $config_transitions;
}
public function getTransitionsByTid($tid, $roles = '', $reset = FALSE) {
$conditions = array(
'roles' => $roles,
);
return $this
->getTransitions(array(
$tid,
), $conditions, $reset);
}
public function getTransitionsBySid($sid, $roles = '', $reset = FALSE) {
$conditions = array(
'sid' => $sid,
'roles' => $roles,
);
return $this
->getTransitions(FALSE, $conditions, $reset);
}
public function getTransitionsByTargetSid($target_sid, $roles = '', $reset = FALSE) {
$conditions = array(
'target_sid' => $target_sid,
'roles' => $roles,
);
return $this
->getTransitions(FALSE, $conditions, $reset);
}
public function getTransitionsBySidTargetSid($sid, $target_sid, $roles = 'ALL', $reset = FALSE) {
$conditions = array(
'sid' => $sid,
'target_sid' => $target_sid,
'roles' => $roles,
);
return $this
->getTransitions(FALSE, $conditions, $reset);
}
public function getTypeMap() {
$result = array();
$type_maps = module_exists('workflownode') ? workflow_get_workflow_type_map_by_wid($this->wid) : array();
foreach ($type_maps as $map) {
$result[] = $map->type;
}
return $result;
}
public function getSetting($key, array $field = array()) {
switch ($key) {
case 'watchdog_log':
if (isset($this->options['watchdog_log'])) {
return $this->options['watchdog_log'];
}
elseif ($field) {
if (isset($field['settings']['watchdog_log'])) {
return $field['settings']['watchdog_log'];
}
}
drupal_set_message('Setting Workflow::getSetting(' . $key . ') does not exist', 'error');
break;
default:
drupal_set_message('Setting Workflow::getSetting(' . $key . ') does not exist', 'error');
}
}
public function getName() {
return $this->name;
}
protected function defaultLabel() {
return isset($this->label) ? t('@label', array(
'@label' => $this->label,
)) : '';
}
protected function defaultUri() {
$wid = $this->wid;
return array(
'path' => WORKFLOW_ADMIN_UI_PATH . "/manage/{$wid}",
);
}
protected function rebuildRoles(array $roles) {
$new_roles = array();
$role_map = workflow_get_roles(NULL, FALSE);
foreach ($roles as $key => $rid) {
if ($rid == WORKFLOW_ROLE_AUTHOR_RID) {
$new_roles[$rid] = $rid;
}
else {
if ($role = user_role_load_by_name($role_map[$rid])) {
$new_roles[$role->rid] = (int) $role->rid;
}
}
}
return $new_roles;
}
}
function _workflow_transitions_sort_by_weight($a, $b) {
$old_state_a = $a
->getOldState();
$old_state_b = $b
->getOldState();
if ($old_state_a->weight < $old_state_b->weight) {
return -1;
}
if ($old_state_a->weight > $old_state_b->weight) {
return +1;
}
$new_state_a = $a
->getNewState();
$new_state_b = $b
->getNewState();
if ($new_state_a->weight < $new_state_b->weight) {
return -1;
}
if ($new_state_a->weight > $new_state_b->weight) {
return +1;
}
return 0;
}
class WorkflowController extends EntityAPIControllerExportable {
public function delete($ids, DatabaseTransaction $transaction = NULL) {
foreach ($ids as $wid) {
if ($workflow = workflow_load($wid)) {
$workflow
->delete();
}
}
$this
->resetCache();
}
protected function cacheGet($ids, $conditions = array()) {
if ($ids === FALSE && !$conditions) {
return $this->entityCache;
}
return parent::cacheGet($ids, $conditions);
}
protected function attachLoad(&$queried_entities, $revision_id = FALSE) {
foreach ($queried_entities as $entity) {
$entity->states = $entity
->getStates($all = TRUE);
$entity->transitions = $entity
->getTransitions(FALSE);
$entity->typeMap = $entity
->getTypeMap();
}
parent::attachLoad($queried_entities, $revision_id);
}
}