[/info]: info on workflow with list of states * /workflow//edit|clone|delete|export: workflow operations form * /workflow//fields: field UI for workflow as state bundle * /workflow//fields: view modes for workflow as state bundle * /state[/list]: list of states * /state/[/info]: info on state, with list of previous/next states * and list of entities in state * /state//edit|clone|delete|export * state operations form. Main point of interest is the transitions subform */ /** * Implements hook_entity_bundle_info(). */ function wing_entity_bundle_info() { $bundles = array(); foreach (wing_get_workflows() as $workflow => $title) { $bundles['wing_state'][$type] = array( 'label' => $title, 'admin' => array( // Place the Field UI paths for comments one level below the // corresponding paths for nodes, so that they appear in the same set // of local tasks. Note that the paths use a different placeholder name // and thus a different menu loader callback, so that Field UI page // callbacks get a comment bundle name from the node type in the URL. // See comment_node_type_load() and comment_menu_alter(). 'path' => 'admin/content/wing/manage/%wing_workflow', 'bundle argument' => 4, 'real path' => 'admin/content/wing/manage/' . $workflow. '/comment', ), ); } return $bundles; } /** * Implements hook_entity_view_mode(). */ function wing_entity_view_mode_info() { $ret = array( 'wing_state' => array( 'full' => array( 'label' => t('Full'), 'custom settings' => FALSE, ), 'summary' => array( 'label' => t('Summary'), 'custom settings' => FALSE, ), 'simple' => array( 'label' => t('Simple'), 'custom settings' => FALSE, ), ), ); dsm($ret, __FUNCTION__); return $ret; } /** * Implements hook_field_extra_fields(). */ function wing_field_extra_fields() { $ret = array(); foreach (wing_get_workflows() as $workflow => $title) { $ret['wing_state'][$workflow]['workflow'] = array( 'display' => array( 'label' => t('Workflow name'), 'description' => t('The workflow to which the state belongs'), 'weight' => -9, 'visible' => FALSE, ), ); } dsm($ret, __FUNCTION__); return $ret; } /** * Helper to retrive the list or workflows or a specific workflow. * * @param string $workflow */ function wing_get_workflows($workflow = NULL) { $workflows = config('wing')->get('workflows'); if (isset($workflow)) { $ret = isset($workflows[$workflow]) ? $workflows[$workflow] : FALSE; } else { $ret = (array) $workflows; } dsm($ret, __FUNCTION__ . "($workflow)"); return $ret; } /** * Implements hook_help(). */ function wing_help($path, $arg) { switch ($path) { case 'admin/help#wing': $ret = '

' . t('About') . '

' . t('Wing is a new workflow system redesigned from the ground up for Drupal 8. States are entities, Workflows are their bundles, and any fieldable entity type (not just nodes) can be subjected to a workflow by adding an entity_reference to a Wing state field to its field list.'); break; default: $ret = NULL; } return $ret; } /** * Implements hook_menu(). */ function wing_menu() { $items = array(); $items['admin/content/wing'] = array( 'access arguments' => array('administer wing'), 'description' => 'Report general Wing information', 'file' => 'wing.admin.inc', 'page callback' => 'wing_page_info', 'title' => 'Wing', 'type' => MENU_LOCAL_TASK | MENU_NORMAL_ITEM, 'weight' => 23, // 'W' ); // Tabs begin here. $items['admin/content/wing/info'] = array( 'title' => 'Info', 'type' => MENU_DEFAULT_LOCAL_TASK, ); $items['admin/content/wing/overview'] = array( 'title' => 'States', 'access arguments' => array('administer wing'), 'description' => 'List and edit workflow states', 'file' => 'wing.pages.inc', 'page callback' => 'wing_overview', 'title' => 'Wing', 'type' => MENU_LOCAL_TASK, ); $items['admin/content/wing/%wing_state'] = array( 'access arguments' => array('administer wing'), 'page arguments' => array(3), 'page callback' => 'wing_state_page', 'title' => 'State permalink', ); $items['admin/content/wing/%wing_state/view'] = array( 'title' => 'View state', 'type' => MENU_DEFAULT_LOCAL_TASK, ); $items['admin/content/wing/%wing_state/edit'] = array( 'title' => 'Edit', 'page callback' => 'wing_state_edit_page', 'page arguments' => array(3), 'access callback' => 'wing_state_access', 'access arguments' => array('edit', 3), 'type' => MENU_LOCAL_TASK, ); $items['admin/content/wing/%wing_state/delete'] = array( 'title' => 'Delete', 'page callback' => 'wing_state_confirm_delete_page', 'page arguments' => array(3), 'access arguments' => array('administer wing'), 'type' => MENU_LOCAL_TASK, 'file' => 'wing.admin.inc', 'weight' => 20, ); $items['admin/content/wing/settings'] = array( 'title' => 'Settings', 'type' => MENU_LOCAL_TASK, 'page callback' => 'drupal_get_form', 'page arguments' => array('wing_settings_form'), 'file' => 'wing.admin.inc', 'access arguments' => array('administer wing'), 'weight' => 99, ); return $items; } /** * TODO implement * * @param string $op * @param Drupal\wing\Plugin\Core\Entity\State $state * * @return boolean */ function wing_state_access($op, State $state) { } /** * Entity URI callback. */ function wing_uri(State $state) { return array( 'path' => 'admin/content/wing/' . $state->id(), ); } /** * Menu loader for workflow. * * @param string $workflow * * @return boolean */ function wing_workflow_load($workflow) { $ret = wing_get_workflows($workflow); dsm($ret, __FUNCTION__); return $ret; } function WIPWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWww() {} /** * Implements hook_entity_info(). * * Workflow is the bundle entity for state, but this concept is obsolete in D8, * so we ignore it. */ function Zwing_entity_info() { $defaults = array( 'entity keys' => array( 'label' => 'title', 'module' => 'module', 'name' => 'machine_name', 'status' => 'status', ), 'exportable' => TRUE, 'fieldable' => FALSE, 'label callback' => 'entity_class_label', 'module' => 'wing', 'uri callback' => 'entity_class_uri', ); $ret = array(); $type = 'wing_workflow'; $class = 'WingWorkflow'; $ret[$type] = array_merge_recursive(array( 'access callback' => "{$type}_access", 'base table' => $type, 'controller class' => "{$class}Controller", 'entity class' => $class, 'entity keys' => array( 'id' => 'wid', ), 'export' => array( 'default hook' => "default_{$type}s", ), 'features controller class' => "{$class}FeaturesController", 'label' => t('Wing: Workflow'), 'load hook' => "{$type}_load", // Enable hook_wing_workflow_load(). 'views controller class' => "{$class}ViewsController", ), $defaults); $type = 'wing_state'; $class = 'WingState'; $ret[$type] = array_merge_recursive(array( 'access callback' => '{$type}_access', 'base table' => $type, 'bundle keys' => array('bundle' => 'workflow'), 'bundles' => array(), 'controller class' => "{$class}Controller", 'entity class' => $class, 'entity keys' => array( 'id' => 'sid', 'bundle' => 'workflow', ), 'export' => array( 'default_hook' => "default_{$type}s", ), 'features controller class' => "{$class}FeaturesController", 'label' => t('Wing: State'), 'load hook' => "{$type}_load", // Enable hook_wing_state_load(). 'views controller class' => "{$class}ViewsController", ), $defaults); return $ret; } /** * Implements hook_entity_info_alter(). * * Sort initial Wing entity info keys for easier debugging. */ function Zwing_entity_info_alter(&$info) { ksort($info['wing_state']); ksort($info['wing_workflow']); } /** * Implements hook_field_info(). * * Define "wing_transition" as a UI-less field. */ function Zwing_field_info() { $ret = array( 'wing_transition' => array( 'label' => t('Wing: Transition'), 'description' => t('Store access from one workflow state to another.'), 'settings' => array(), 'instance_settings' => array(), 'default_widget' => 'text_textfield', 'default_formatter' => 'text_default', // 'default_widget' => 'wing_transition_widget', // 'default_formatter' => 'wing_transition_default', // 'no_ui' => FALSE, ), ); dsm($ret, __FUNCTION__); return $ret; } /** * Implements hook_field_widget_info(). */ function Zwing_field_widget_info() { $ret = array( 'text_textfield' => array( 'label' => t('Text field'), 'field types' => array('text'), 'settings' => array('size' => 60), 'behaviors' => array( 'multiple values' => FIELD_BEHAVIOR_DEFAULT, 'default value' => FIELD_BEHAVIOR_DEFAULT, ), ), ); return $ret; } /** * Implements hook_field_widget_info_alter(). */ function Zwing_field_widget_info_alter(&$info) { if (module_exists('text')) { $info['text_textfield']['field types'][] = 'wing_transition'; } } /** * Implements hook_permission(). */ function Zwing_permission() { $ret = array( 'administer wing' => array( 'title' => t('Administer Wing'), 'description' => t('Perform administration tasks for Wing.'), ), ); return $ret; } /** * Entity access callback for wing_state. * * @param string $op * 'create', 'update', 'delete' or 'view' * @param WingState $entity * @param stdClass $account * @param string $entity_type * * @return boolean */ function Zwing_state_access($op, $entity, $account, $entity_type) { // dsm(get_defined_vars(), __FUNCTION__); return TRUE; } /** * Implements hook_view_api(). */ function Zwing_views_api() { $path = drupal_get_path('module', 'wing'); $ret = array( 'api' => 3, 'path' => "$path/views", 'template path' => "$path/themes", ); return $ret; } /** * Entity access callback for wing_workflow. * * @param string $op * 'create', 'update', 'delete' or 'view' * @param WingWorkflow $entity * @param stdClass $account * @param string $entity_type * * @return boolean */ function Zwing_workflow_access($op, $entity, $account, $entity_type) { $s_entity = isset($entity) ? "$entity" : 'NULL'; $s_account = isset($account) ? $account->uid : "''"; // dsm(__FUNCTION__ . "('$op', $s_entity, $s_account, '$entity_type')"); return TRUE; } function Zwing_workflow_exists($machine_name) { $ret = entity_load_multiple_by_name('wing_workflow', array($machine_name)); dsm($ret, __FUNCTION__); return $ret; }