Index: states.install =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/workflow_ng/states/Attic/states.install,v retrieving revision 1.1.2.1 diff -u -p -r1.1.2.1 states.install --- states.install 24 Aug 2007 13:43:30 -0000 1.1.2.1 +++ states.install 29 Dec 2007 14:14:40 -0000 @@ -23,6 +23,15 @@ function states_install() { state varchar(127), PRIMARY KEY (uid, machine) ) /*!40100 DEFAULT CHARACTER SET UTF8 */ "); + db_query("CREATE TABLE if not exists {states_custom} ( + sid int unsigned NOT NULL auto_increment, + label varchar(127), + entity_type int unsigned NOT NULL default '0', + entity_filter longtext NOT NULL, + states longtext NOT NULL, + init_state varchar(127), + PRIMARY KEY (sid) + ) /*!40100 DEFAULT CHARACTER SET UTF8 */ "); break; case 'pgsql': db_query("CREATE TABLE {node_state} ( @@ -39,10 +48,53 @@ function states_install() { state varchar(127), PRIMARY KEY (uid, machine) )"); + db_query("CREATE TABLE {states_custom} ( + sid serial CHECK (sid >= 0), + label varchar(127), + entity_type int_unsigned NOT NULL default '0', + entity_filter text NOT NULL, + states text NOT NULL, + init_state varchar(127), + PRIMARY KEY (sid) + )"); + break; + default: + break; + } +} + +/* + * Due to the addition of web interface configurable states, a new table is required + */ +function states_update_5001() { + switch ($GLOBALS['db_type']) { + case 'mysqli': + case 'mysql': + db_query("CREATE TABLE if not exists {states_custom} ( + sid int unsigned NOT NULL auto_increment, + label varchar(127), + entity_type int unsigned NOT NULL default '0', + entity_filter longtext NOT NULL, + states longtext NOT NULL, + init_state varchar(127), + PRIMARY KEY (sid) + ) /*!40100 DEFAULT CHARACTER SET UTF8 */ "); + break; + case 'pgsql': + db_query("CREATE TABLE {states_custom} ( + sid serial CHECK (sid >= 0), + label varchar(127), + entity_type int_unsigned NOT NULL default '0', + entity_filter text NOT NULL, + states text NOT NULL, + init_state varchar(127), + PRIMARY KEY (sid) + )"); break; default: break; } + return array(); } /* @@ -51,5 +103,6 @@ function states_install() { function states_uninstall() { db_query("DROP TABLE {node_state}"); db_query("DROP TABLE {users_state}"); + db_query("DROP TABLE {states_custom}"); variable_del('state_machines'); } Index: states.module =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/workflow_ng/states/Attic/states.module,v retrieving revision 1.1.2.6 diff -u -p -r1.1.2.6 states.module --- states.module 25 Dec 2007 23:08:58 -0000 1.1.2.6 +++ states.module 27 Dec 2007 20:03:51 -0000 @@ -13,6 +13,7 @@ if (module_exists('views')) { if (module_exists('workflow_ng')) { include_once(drupal_get_path('module', 'states') .'/states_workflow_ng.inc'); } +include_once(drupal_get_path('module', 'states') .'/states_admin.inc'); /* * Returns all defined state machines Index: states_admin.inc =================================================================== RCS file: states_admin.inc diff -N states_admin.inc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ states_admin.inc 29 Dec 2007 15:49:45 -0000 @@ -0,0 +1,681 @@ + $row->label, + '#states' => unserialize($row->states), + 'can_edit' => TRUE, + 'custom_sid' => $row->sid, + ); + if ($row->init_state != '') { + $state['#init_state'] = $row->init_state; + } + if ($row->entity_type == STATES_ADMIN_ENTITY_NODE) { + $state['#entity'] = 'node'; + if ($row->entity_filter !== '') { + $state['#types'] = unserialize($row->entity_filter); + } + } + else if ($row->entity_type == STATES_ADMIN_ENTITY_USER) { + $state['#entity'] = 'user'; + if ($row->entity_filter !== '') { + $state['#roles'] = unserialize($row->entity_filter); + } + } + $machines['custom_state_'. $row->sid] = $state; + } + return $machines; +} + +/** + * Implementation of hook_perm(). + */ +function states_perm() { + return array('administer state'); +} + +/** + * Implementation of hook_menu(). + */ +function states_menu($may_cache) { + $items = array(); + if ($may_cache) { + $items[] = array( + 'path' => STATES_ADMIN_UI_PATH, + 'title' => t('Custom state machines'), + 'description' => t('View, edit, create and delete custom state machines.'), + 'callback' => 'drupal_get_form', + 'callback arguments' => array('states_admin_overview', NULL), + 'access' => user_access('administer state'), + 'type' => MENU_NORMAL_ITEM, + ); + $items[] = array( + 'path' => STATES_ADMIN_UI_PATH .'/0/list', + 'title' => t('Overview'), + 'weight' => -5, + 'type' => MENU_DEFAULT_LOCAL_TASK, + ); + $items[] = array( + 'path' => STATES_ADMIN_UI_PATH .'/0/add', + 'title' => t('Create a new state machine'), + 'type' => MENU_LOCAL_TASK, + 'callback' => 'drupal_get_form', + 'callback arguments' => array('states_admin_create'), + 'access' => user_access('administer state'), + ); + } + else if (arg(0) == 'admin' && arg(1) == 'build' && arg(2) == 'state-machines') { + $machines = states_get_machines(); + if (isset($machines[arg(3)]) && $machines[arg(3)]['can_edit'] == TRUE) { + $label = $machines[arg(3)]['#label']; + $items[] = array( + //this item lets the menu system create a nicer breadcrumb + 'path' => STATES_ADMIN_UI_PATH .'/'. arg(3), + 'title' => check_plain($label), + 'type' => MENU_CALLBACK, + ); + $items[] = array( + 'path' => STATES_ADMIN_UI_PATH .'/'. arg(3) .'/edit', + 'title' => t('Edit'), + 'type' => MENU_CALLBACK, + 'callback' => 'drupal_get_form', + 'callback arguments' => array('states_admin_edit', arg(3)), + 'access' => user_access('administer state'), + ); + $items[] = array( + 'path' => STATES_ADMIN_UI_PATH .'/'. arg(3) .'/delete', + 'title' => t('Delete'), + 'type' => MENU_CALLBACK, + 'callback' => 'drupal_get_form', + 'callback arguments' => array('states_admin_delete', arg(3)), + 'access' => user_access('administer state'), + ); + } + } + return $items; +} + +function states_admin_overview() { + drupal_set_title("State machines overview"); + states_clear_machine_cache(); + + $form['nodes_header'] = array('#value' => '

'. t('Content state machines') .'

'); + $form['nodes'] = states_admin_overview_table('node'); + $form['users_header'] = array('#value' => '

'. t('User state machines') .'

'); + $form['users'] = states_admin_overview_table('user'); + $form['#redirect'] = FALSE; + return $form; +} + +function states_admin_overview_table($entity) { + $machines = states_get_machines(); + + $header = array(t('Label'), t('States'), t('Initial state'), t('Attribute name'), t($entity=='node'?'Content types':'User roles'), t('Operations')); + + $rows = array(); + foreach ($machines as $name => $machine) { + if ($machine['#entity'] == $entity && isset($machine['can_edit']) && $machine['can_edit'] == TRUE) { + $states = t('(any)'); + if ($machine['#states'] != '*') { + $states = theme('item_list', $machine['#states']); + } + $filter = t('(any)'); + if ($entity == 'node' && isset($machine['#types'])) { + $filter = array(); + $node_names = node_get_types('names'); + foreach ($machine['#types'] as $value) { + $filter[] = $node_names[$value]; + } + if (count($filter) > 0) { + $filter = theme('item_list', $filter); + } + else { + $filter = t('(none)'); + } + } + else if ($entity == 'user' && isset($machine['#roles'])) { + $filter = array(); + $role_names = user_roles(); + foreach ($machine['#roles'] as $value) { + $filter[] = $role_names[$value]; + } + if (count($filter) > 0) { + $filter = theme('item_list', $filter); + } + else { + $filter = t('(none)'); + } + } + $ops = array(); + $path = STATES_ADMIN_UI_PATH .'/'. $name; + $ops[] = l(t('edit'), $path .'/edit'); + $ops[] = l(t('delete'), $path .'/delete'); + $rows[] = array( + check_plain($machine['#label']), + $states, + isset($machine['#init_state']) ? check_plain($machine['#init_state']) : t('(none)'), + check_plain(isset($machine['#attribute_name']) ? isset($machine['#attribute_name']) : $name), + $filter, + implode(' ', $ops), + ); + } + } + + if (count($rows)) { + return array('#value' => theme('table', $header, $rows, array('class' => 'state-configurations'))); + } + + return array('#value' => t('None.')); +} + +function states_admin_trim_value(&$value) { + $value = trim($value); +} + +/** + * Helper function for states_admin_create. Addresses a bug in the D5 Forms API; + * multistep forms do not honour default values for checkboxes. + */ +function states_admin_checkboxes_multistep_fix($elements) { + foreach (element_children($elements) as $key) { + if ($elements[$key]['#type'] == 'checkbox' && isset($elements[$key]['#default_value']) && $elements[$key]['#default_value'] != 0) { + $elements[$key]['#attributes']['checked'] = 'checked'; + } + } + return $elements; +} + +function states_admin_create($form_values = NULL) { + if (!isset($form_values)) { + $form_values = array( + 'step' => 0, + 'saved' => serialize(array()), + // Some decent default values for a new state machine: + 'label' => '', + 'entity' => STATES_ADMIN_ENTITY_NODE, + 'any_state' => 0, + 'state_list' => array(), + 'initial_state' => 0, + 'any_entity' => 0, + 'filters' => array(), + ); + } + return states_admin_form($form_values); +} + +/** + * The custom state creation / editing multistep form + */ +function states_admin_form($form_values) { + // Merge the saved values into the form_values + $saved = unserialize($form_values['saved']); + unset($form_values['saved']); // remove the saved values from the form values so they aren't in both parts of the merge + if (isset($form_values['unset'])) { + // Changing the any_state option will invalidate the initial_state option and the state_list (this has to be done before the unset; silly FAPI checkbox) + if ($form_values['unset'] == 'any_state' && (($saved['any_state'] == 1) != ($form_values['any_state'] == 1))) { + if ($form_values['any_state'] == 1) { + $form_values['state_list'] = '*'; + $form_values['initial_state'] = ''; + } + else { + $form_values['state_list'] = array(); + $form_values['initial_state'] = 0; + } + } + // To allow checkboxes to be unticked, they have to be zeroed in the saved values, as they only appear in the new values if they are ticked + // Similarly, checkbox groups only appear if one or more was ticked. If they were all unticked, they don't appear in new values. + $saved_unset = $form_values['unset']; + unset($form_values['unset']); + if (is_array($saved[$saved_unset])) { + $saved[$saved_unset] = array(); + } + else { + $saved[$saved_unset] = 0; + } + } + $form_values = array_merge($saved, $form_values); + + // Do any processing of the results from the previous step + $from_step = $form_values['step']; + + // The state list is changed from a newline delimited string into an array. It is the only value not left as-is until the + // form submission. This is because it is much more useful to us as an array. + if ($from_step == STATES_ADMIN_STEP_STATES) { + $states = explode("\n", $form_values['state_list']); + array_walk($states, 'states_admin_trim_value'); + $form_values['state_list'] = $states; + } + + // Changing the entity type option will invalidate the filters option (as node filters and role filters are very different) + if (($saved['entity'] == STATES_ADMIN_ENTITY_NODE) != ($form_values['entity'] == STATES_ADMIN_ENTITY_NODE)) { + $form_values['filters'] = array(); + } + + // Move to the next step or previous step + if ($form_values['op'] == t('Back')) { + $step = $from_step - 1; + if ($step == STATES_ADMIN_STEP_FILTERS && $form_values['any_entity'] == 1) { + // The filters step is skipped if any entity is allowed + $step = STATES_ADMIN_STEP_OPTIONS; + } + if ($step == STATES_ADMIN_STEP_STATES && $form_values['any_state'] == 1) { + // The state list step is skipped if any state is allowed + $step = STATES_ADMIN_STEP_BASIC; + } + } + else { + $step = $from_step + 1; + if ($step == STATES_ADMIN_STEP_STATES && $form_values['any_state'] == 1) { + // The state list step is skipped if any state is allowed + $step = STATES_ADMIN_STEP_OPTIONS; + } + if ($step == STATES_ADMIN_STEP_FILTERS && $form_values['any_entity'] == 1) { + // The filters step is skipped if any entity is allowed + $step = STATES_ADMIN_STEP_REVIEW; + } + } + + // Store persistent variables + $form_values['step'] = $step; + $form['saved'] = array( + '#type' => 'hidden', + '#value' => serialize($form_values), + ); + + // Make the new page of the wizard + switch ($step) { + case STATES_ADMIN_STEP_BASIC: + $form['label'] = array( + '#type' => 'textfield', + '#title' => t('Label'), + '#maxlength' => 127, + '#description' => t('Choose an appropriate label for the new state machine.'), + '#required' => TRUE, + '#default_value' => $form_values['label'], + ); + $form['entity'] = array( + '#type' => 'select', + '#title' => t('Entity'), + '#options' => array( + STATES_ADMIN_ENTITY_NODE => t('Content'), + STATES_ADMIN_ENTITY_USER => t('User'), + ), + '#description' => t('Select the type of entity you want the state machine to track.'), + '#required' => TRUE, + '#default_value' => $form_values['entity'], + ); + $form['any_state'] = array( + '#type' => 'checkbox', + '#title' => t('Allow any state'), + '#default_value' => $form_values['any_state'], + '#description' => t('Allows the state machine to have any state, rather than requiring one from a defined pool.'), + ); + $form['unset'] = array( + '#type' => 'hidden', + '#value' => 'any_state', + ); + $form = states_admin_checkboxes_multistep_fix($form); // Workaround FAPI checkbox multistep bug + break; + + case STATES_ADMIN_STEP_STATES: + $form['state_list'] = array( + '#type' => 'textarea', + '#title' => t('Machine states'), + '#description' => t('List the possible states of the state machine, one per line.'), + '#required' => TRUE, + '#default_value' => implode("\n", $form_values['state_list']), + ); + break; + + case STATES_ADMIN_STEP_OPTIONS: + if ($form_values['any_state'] == 1) { + $form['initial_state'] = array( + '#title' => t('Initial state'), + '#type' => 'textfield', + '#maxlength' => 127, + '#description' => t('Choose a initial state for entities, or leave blank to leave entities with no state.'), + '#default_value' => $form_values['initial_state'], + ); + } + else { + $states = $form_values['state_list']; + array_unshift($states, t('(none)')); + $form['initial_state'] = array( + '#title' => t('Initial state'), + '#type' => 'select', + '#options' => $states, + '#description' => t('Choose a initial state for entities.'), + '#required' => TRUE, + '#default_value' => $form_values['initial_state'], + ); + } + $form['any_entity'] = array( + '#type' => 'checkbox', + '#default_value' => $form_values['any_entity'], + ); + $form['unset'] = array( + '#type' => 'hidden', + '#value' => 'any_entity', + ); + if ($form_values['entity'] == STATES_ADMIN_ENTITY_NODE) { + $form['any_entity']['#title'] = t('Allow any content type'); + $form['any_entity']['#description'] = t('Allows the state machine to work on all content types, rather than ones from a defined pool.'); + } + else { + $form['any_entity']['#title'] = t('Allow any user role'); + $form['any_entity']['#description'] = t('Allows the state machine to work on all user roles, rather than ones from a defined pool.'); + } + $form = states_admin_checkboxes_multistep_fix($form); // Workaround FAPI checkbox multistep bug + break; + + case STATES_ADMIN_STEP_FILTERS: + $form['filters'] = array( + '#type' => 'checkboxes', + '#process' => array('expand_checkboxes' => array(), 'states_admin_checkboxes_multistep_fix' => array()), // Workaround FAPI checkbox multistep bug + '#default_value' => $form_values['filters'], + ); + if ($form_values['entity'] == STATES_ADMIN_ENTITY_NODE) { + $form['filters']['#title'] = t('Permitted content types'); + $form['filters']['#description'] = t('The state machine is only valid for the checked content types.'); + $form['filters']['#options'] = node_get_types('names'); + } + else { + $form['filters']['#title'] = t('Permitted user roles'); + $form['filters']['#description'] = t('The state machine is only valid for the checked user roles.'); + $form['filters']['#options'] = user_roles(); + } + $form['unset'] = array( + '#type' => 'hidden', + '#value' => 'filters', + ); + break; + + case STATES_ADMIN_STEP_REVIEW: + $form['review_label'] = array( + '#prefix' => '

'. t('You are about to create the following state machine:') .'

', + '#type' => 'item', + '#title' => t('Label'), + '#value' => $form_values['label'], + ); + if (isset($form_values['sid_to_update'])) { + $form['review_label']['#prefix'] = '

'. t('You are about to update the state machine to the following:') .'

'; + } + + $form['review_entity'] = array( + '#type' => 'item', + '#title' => t('Entity'), + '#value' => $form_values['entity'] == STATES_ADMIN_ENTITY_NODE ? t('Content') : t('User'), + ); + + $form['review_states'] = array( + '#type' => 'item', + '#title' => t('States'), + '#value' => t('(any)'), + ); + if ($form_values['any_state'] != 1) { + $form['review_states']['#value'] = theme('item_list', $form_values['state_list']); + } + + $form['review_initial'] = array( + '#type' => 'item', + '#title' => t('Initial state'), + '#value' => t('(none)'), + ); + if ($form_values['any_state'] == 1) { + if ($form_values['initial_state'] != '') { + $form['review_initial']['#value'] = $form_values['initial_state']; + } + } + else { + if ($form_values['initial_state'] > 0) { + $states = $form_values['state_list']; + $form['review_initial']['#value'] = $states[$form_values['initial_state'] - 1]; + } + } + + $form['review_filter'] = array( + '#type' => 'item', + '#value' => t('(any)'), + ); + if ($form_values['entity'] == STATES_ADMIN_ENTITY_NODE) { + $form['review_filter']['#title'] = t('Content types'); + if ($form_values['any_entity'] != 1) { + $node_names = node_get_types('names'); + $node_list = $form_values['filters']; + foreach ($node_list as &$value) { + $value = $node_names[$value]; + } + if (count($node_list) > 0) { + $form['review_filter']['#value'] = theme('item_list', $node_list); + } + else { + $form['review_filter']['#value'] = t('(none)'); + } + } + } + else { + $form['review_filter']['#title'] = t('User roles'); + if ($form_values['any_entity'] != 1) { + $role_names = user_roles(); + $role_list = $form_values['filters']; + foreach ($role_list as &$value) { + $value = $role_names[$value]; + } + if (count($role_list) > 0) { + $form['review_filter']['#value'] = theme('item_list', $role_list); + } + else { + $form['review_filter']['#value'] = t('(none)'); + } + } + } + + break; + } + + // Put on the form elements common to every page (the next and back buttons) + if ($step != 1) { + $form['back'] = array( + '#type' => 'submit', + '#value' => t('Back'), + ); + } + if ($step == STATES_ADMIN_STEP_REVIEW) { + $form['submit'] = array( + '#type' => 'submit', + '#value' => isset($form_values['sid_to_update']) ? t('Update') : t('Create'), + ); + } + else { + $form['submit'] = array( + '#type' => 'submit', + '#value' => t('Next'), + ); + } + + // Set the form settings and finish + $form['#redirect'] = FALSE; + $form['#multistep'] = TRUE; + $form['#validate'] = array('states_admin_form_validate' => array()); + $form['#submit'] = array('states_admin_form_submit' => array()); + return $form; +} + +/** + * The custom state creation / editing multistep form validation handler + */ +function states_admin_form_validate($form_id, $form_values) { + // Merge the saved variables into the new ones + $saved = unserialize($form_values['saved']); + unset($form_values['saved']); + $form_values = array_merge($saved, $form_values); + + $step = $form_values['step']; + switch ($step) { + case STATES_ADMIN_STEP_STATES: + $states = array(); + if (isset($form_values['state_list'])) { + $states = explode("\n", $form_values['state_list']); + } + array_walk($states, 'states_admin_trim_value'); + foreach ($states as $state) { + if (strlen($state) > 127) { + form_set_error('state_list', t('The state "!state" exceeds the maximum length of 127.', array('!state' => $state))); + } + } + $states_count = array_count_values($states); + foreach ($states_count as $state => $count) { + if ($count != 1) { + form_set_error('state_list', t('The state "!state" appears more than once.', array('!state' => $state))); + } + } + break; + + case STATES_ADMIN_STEP_FILTERS: + $filters = array(); + if (isset($form_values['filters'])) { + $filters = $form_values['filters']; + } + $filters_count = array_count_values($filters); + if (count($filters) == $filters_count[0]) { + drupal_set_message(t('You left all boxes unticked. While this is allowed, was it really intended?')); + } + break; + } +} + +/** + * The custom state creation / editing multistep form submission handler + */ +function states_admin_form_submit($form_id, $form_values) { + // Merge the saved variables into the new ones + $saved = unserialize($form_values['saved']); + unset($form_values['saved']); + $form_values = array_merge($saved, $form_values); + + $step = $form_values['step']; + if ($step == STATES_ADMIN_STEP_REVIEW && $form_values['op'] != t('Back')) { + $label = $form_values['label']; + + $entity_type = $form_values['entity']; + + $entity_filter = ''; + if ($form_values['any_entity'] != 1) { + $entity_filter = serialize(array_keys($form_values['filters'])); + } + + $states = '*'; + if ($form_values['any_state'] != 1) { + $states = $form_values['state_list']; + } + + $init_state = ''; + if ($form_values['any_state'] == 1) { + $init_state = $form_values['initial_state']; + } + else { + if ($form_values['initial_state'] > 0) { + $init_state = $states[$form_values['initial_state'] - 1]; + } + } + + if (isset($form_values['sid_to_update'])) { + db_query("UPDATE {states_custom} SET label = '%s', entity_type = %d, entity_filter = '%s', states = '%s', init_state = '%s' WHERE sid = %d", + $label, $entity_type, $entity_filter, serialize($states), $init_state, $form_values['sid_to_update']); + drupal_set_message(t('State machine updated')); + } + else { + db_query("INSERT INTO {states_custom} (label, entity_type, entity_filter, states, init_state) VALUES ('%s', %d, '%s', '%s', '%s')", + $label, $entity_type, $entity_filter, serialize($states), $init_state); + drupal_set_message(t('New state machine created')); + } + + drupal_goto(STATES_ADMIN_UI_PATH); + } +} + +function states_admin_edit($machine_name, $form_values = NULL) { + if (!isset($form_values)) { + $machines = states_get_machines(); + $machine = $machines[$machine_name]; + + // Transform the state machine definition into form values + $form_values = array( + 'step' => 0, + 'label' => $machine['#label'], + 'entity' => $machine['#entity'] == 'node' ? STATES_ADMIN_ENTITY_NODE : STATES_ADMIN_ENTITY_USER, + 'any_state' => $machine['#states'] == '*' ? 1 : 0, + 'state_list' => $machine['#states'], + 'any_entity' => (isset($machine['#types']) || isset($machine['#roles'])) ? 0 : 1, + 'sid_to_update' => $machine['custom_sid'], + 'filters' => array(), + ); + if ($machine['#states'] == '*') { + $form_values['initial_state'] = isset($machine['#init_state']) ? $machine['#init_state'] : ''; + } + else { + $form_values['initial_state'] = isset($machine['#init_state']) ? array_search($machine['#init_state'], $machine['#states']) : FALSE; + if ($form_values['initial_state'] === FALSE) { + $form_values['initial_state'] = 0; + } + else { + $form_values['initial_state'] = $form_values['initial_state'] + 1; + } + } + if ($machine['#entity'] == 'node' && isset($machine['#types']) && count($machine['#types']) > 0) { + $form_values['filters'] = array_combine(array_values($machine['#types']), array_values($machine['#types'])); + } + else if ($machine['#entity'] == 'user' && isset($machine['#roles']) && count($machine['#roles']) > 0) { + $form_values['filters'] = array_combine(array_values($machine['#roles']), array_values($machine['#roles'])); + } + $form_values['saved'] = serialize($form_values); // So that the form handler thinks nothing has changed + } + return states_admin_form($form_values); +} + +function states_admin_delete($machine_name) { + $machines = states_get_machines(); + $machine = $machines[$machine_name]; + + $form = array(); + return confirm_form($form, + t('Are you sure you want to delete the state machine "%machine"?', array('%machine' => $machine['#label'])), + array('path' => STATES_ADMIN_UI_PATH), + t('This action cannot be undone.'), t('Delete'), t('Cancel') + ); +} + +function states_admin_delete_submit($form_id, $form_values) { + $machines = states_get_machines(); + $sid_to_delete = $machines[arg(3)]['custom_sid']; + db_query("DELETE FROM {states_custom} WHERE sid = %d", $sid_to_delete); + drupal_set_message(t('State machine deleted')); + return STATES_ADMIN_UI_PATH; +}