state_flow.module in State Machine 6
Same filename and directory in other branches
A base implementation of the state machine class and its relationship to revisions
File
modules/state_flow/state_flow.moduleView source
<?php
/**
* @file
* A base implementation of the state machine class and its relationship to revisions
*/
/**
* Implementation of hook_menu().
*
*/
function state_flow_menu() {
$items = array();
$items['node/%node/events'] = array(
'title' => 'Events',
'description' => 'The available events',
'type' => MENU_LOCAL_TASK,
'page callback' => 'state_flow_events',
'page arguments' => array(
1,
),
'access callback' => TRUE,
'weight' => 10,
);
return $items;
}
/**
* Implementation of hook_menu_alter
* Change the edit link so the most recent revision is always edited
*
* @param array $items
*/
function state_flow_menu_alter(&$items) {
$items['node/%node/edit']['page callback'] = 'state_flow_node_page_edit';
}
/**
* Implementation of hook_theme()
*
* @return array
*/
function state_flow_theme() {
return array(
'state_flow_states' => array(
'arguments' => array(
'states' => NULL,
),
),
);
}
/**
* Theme function to show states of a node
*
* @param array $states
* @return string
*/
function theme_state_flow_states($states) {
$header = array(
t('Vid'),
t('Nid'),
t('State'),
t('Timestamp'),
);
$rows = array();
foreach ($states as $state) {
$rows[] = array(
$state->vid,
$state->nid,
$state->state,
$state->timestamp,
);
}
return theme('table', $header, $rows);
}
/**
* Show the states as a node tab
*
* @param object $node
* @return array
*/
function state_flow_events($node) {
$states = state_flow_get_history($node->nid);
$state_flow = state_flow_load_state_machine($node);
drupal_set_title('Events');
$events = $state_flow
->get_available_events();
$output = !empty($events) ? drupal_get_form('state_flow_events_form', $state_flow) : t('No events to fire');
$output .= theme('state_flow_states', $states);
return $output;
}
/**
* Retrieve the states history for a node.
*
* @param int $nid
* @return array
*/
function state_flow_get_history($nid) {
$query = "SELECT * FROM {node_revision_states} WHERE nid = %d AND status = 1";
$result = db_query($query, $nid);
$history = array();
while ($record = db_fetch_object($result)) {
$history[] = $record;
}
return $history;
}
/**
* Custom form to show the events that are available
*
* @param array $form_state
* @param object $node
* @return array
*/
function state_flow_events_form(&$form_state, $state_flow) {
$form = array();
$events = $state_flow
->get_available_events();
$form['events'] = array(
'#type' => 'radios',
'#title' => t('Fire event'),
'#options' => drupal_map_assoc($events),
);
$form['state_flow'] = array(
'#type' => 'value',
'#value' => $state_flow,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Update'),
);
return $form;
}
/**
* Implementation of hook_form_submit
*
* @param array $form
* @param array $form_state
*/
function state_flow_events_form_submit($form, &$form_state) {
$event = $form_state['values']['events'];
$state_flow = $form_state['values']['state_flow'];
$state_flow
->fire_event($event);
$state = $state_flow
->get_current_state();
drupal_set_message(t('Node transitioned to @state state.', array(
'@state' => $state,
)));
}
/**
* Load the state_flow state_machine for the given node.
*/
function state_flow_load_state_machine($node) {
static $object = array();
if (!isset($object[$node->vid])) {
ctools_include('plugins');
$machine_type = variable_get('state_flow_' . $node->type, 'state_flow');
$plugin = ctools_get_plugins('state_flow', 'plugins', $machine_type);
if (!empty($plugin)) {
$class = ctools_plugin_get_class($plugin, 'handler');
$object[$node->vid] = new $class($node);
}
}
return $object[$node->vid];
}
/**
* Implementation of hook_ctools_plugin_plugins().
*/
function state_flow_ctools_plugin_plugins() {
return array(
'cache' => TRUE,
'use hooks' => TRUE,
);
}
/**
* Implementation of hook_state_flow_plugins().
*/
function state_flow_state_flow_plugins() {
$info = array();
$path = drupal_get_path('module', 'state_flow') . '/plugins';
$info['state_flow'] = array(
'handler' => array(
'class' => 'StateFlow',
'file' => 'state_flow.inc',
'path' => $path,
),
);
return $info;
}
/**
* Implementation of hook_nodeapi().
*/
function state_flow_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
// Use Drupal 7 style node hooks.
switch ($op) {
case 'delete revision':
$node_hook = 'state_flow_node_revision_delete';
break;
default:
$node_hook = 'state_flow_node_' . $op;
break;
}
if (function_exists($node_hook)) {
return $node_hook($node, $a3, $a4);
}
}
/**
* Implementation of hook_node_presave()
*
* @param object $node
*/
function state_flow_node_presave(&$node) {
$state_flow = state_flow_load_state_machine($node);
$state = $state_flow
->get_current_state();
if ($state == 'published') {
//force revision
$node->revision = TRUE;
}
}
/**
* Implementation of hook_node_insert().
*/
function state_flow_node_insert(&$node) {
$state_flow = state_flow_load_state_machine($node);
$state_flow
->persist();
}
/**
* Implementation of hook_node_update().
*/
function state_flow_node_update(&$node) {
$state_flow = state_flow_load_state_machine($node);
$state_flow
->persist();
state_flow_prevent_live_revision($node->nid);
}
/**
* Implementation of hook_node_delete().
*/
function state_flow_node_delete(&$node) {
db_query('DELETE FROM {node_revision_states} WHERE nid = %d', $node->nid);
}
/**
* Implementation of hook_node_revision_delete().
*/
function state_flow_node_revision_delete(&$node) {
db_query('DELETE FROM {node_revision_states} WHERE vid = %d', $node->vid);
}
/**
* Helper function to to load the lastest revision on node edit
*
* @param object $node
*/
function state_flow_node_page_edit($node) {
$state_flow = state_flow_load_state_machine($node);
$vid = $state_flow
->get_latest_revision($node->nid);
//Load the latest revision if it doesn't match what is part of the node
if ($node->vid != $vid) {
$node = node_load($node->nid, $vid);
}
return node_page_edit($node);
}
function state_flow_prevent_live_revision($nid) {
$revision_state = state_flow_live_revision($nid);
if ($revision_state != NULL) {
$live_version = state_flow_revision_info($revision_state['vid']);
db_query("UPDATE {node} SET vid = %d, changed = '%s', title = '%s', status = 1 WHERE nid = %d", $live_version->vid, $live_version->timestamp, $live_version->title, $nid);
}
}
function state_flow_live_revision($nid) {
$state = 'published';
$query = "SELECT *\n FROM {node_revision_states}\n WHERE nid = %d AND state = '%s'\n ORDER BY timestamp\n DESC\n LIMIT 1";
$revision_state = db_fetch_array(db_query($query, $nid, $state));
return $revision_state;
}
function state_flow_revision_info($vid) {
$result = db_query('SELECT * FROM {node_revisions} WHERE vid = %d', $vid);
return db_fetch_object($result);
}
Functions
Name | Description |
---|---|
state_flow_ctools_plugin_plugins | Implementation of hook_ctools_plugin_plugins(). |
state_flow_events | Show the states as a node tab |
state_flow_events_form | Custom form to show the events that are available |
state_flow_events_form_submit | Implementation of hook_form_submit |
state_flow_get_history | Retrieve the states history for a node. |
state_flow_live_revision | |
state_flow_load_state_machine | Load the state_flow state_machine for the given node. |
state_flow_menu | Implementation of hook_menu(). |
state_flow_menu_alter | Implementation of hook_menu_alter Change the edit link so the most recent revision is always edited |
state_flow_nodeapi | Implementation of hook_nodeapi(). |
state_flow_node_delete | Implementation of hook_node_delete(). |
state_flow_node_insert | Implementation of hook_node_insert(). |
state_flow_node_page_edit | Helper function to to load the lastest revision on node edit |
state_flow_node_presave | Implementation of hook_node_presave() |
state_flow_node_revision_delete | Implementation of hook_node_revision_delete(). |
state_flow_node_update | Implementation of hook_node_update(). |
state_flow_prevent_live_revision | |
state_flow_revision_info | |
state_flow_state_flow_plugins | Implementation of hook_state_flow_plugins(). |
state_flow_theme | Implementation of hook_theme() |
theme_state_flow_states | Theme function to show states of a node |