/**
  * {@inheritdoc}
  */
 public function load()
 {
     $entities = array();
     // TODO: D8-port: get entity from proper core methods.
     /* @var $entity EntityInterface */
     $entity = $this->workflow_entity;
     // N.B. This is a custom variable.
     $field_name = workflow_url_get_field_name();
     $entity_type = $entity->getEntityTypeId();
     $entity_id = $entity->id();
     // @todo D8-port: document $limit.
     // @todo d8-port: $limit should be used in pager, not in load().
     $this->limit = \Drupal::config('workflow.settings')->get('workflow_states_per_page');
     $limit = $this->limit;
     // Get Transitions with highest timestamp first.
     $entities = WorkflowTransition::loadMultipleByProperties($entity_type, array($entity_id), [], $field_name, '', $limit, 'DESC');
     return $entities;
 }
 /**
  * {@inheritdoc}
  */
 public function build()
 {
     $form = [];
     // Get the entity for this form.
     /* @var $entity EntityInterface */
     if (!($entity = workflow_url_get_entity())) {
         return $form;
     }
     // Get the field name. Avoid error on Node Add page.
     if (!($field_name = workflow_get_field_name($entity))) {
         return $form;
     }
     /*
      * Output: generate the Transition Form.
      */
     // Create a transition, to pass to the form. No need to use setValues().
     $current_sid = workflow_node_current_state($entity, $field_name);
     $transition = WorkflowTransition::create([$current_sid, 'field_name' => $field_name]);
     $transition->setTargetEntity($entity);
     // Add the WorkflowTransitionForm to the page.
     $form = $this->entityFormBuilder()->getForm($transition, 'add');
     return $form;
 }
示例#3
0
 /**
  * Deactivate a Workflow State, moving existing content to a given State.
  *
  * @param int $new_sid
  *   The state ID, to which all affected entities must be moved.
  */
 public function deactivate($new_sid)
 {
     $current_sid = $this->id();
     $force = TRUE;
     // Notify interested modules. We notify first to allow access to data before we zap it.
     // - re-parents any entity that we don't want to orphan, whilst deactivating a State.
     // - delete any lingering entity to state values.
     // \Drupal::moduleHandler()->invokeAll('workflow', ['state delete', $current_sid, $new_sid, NULL, $force]);
     // Invoke the hook.
     \Drupal::moduleHandler()->invokeAll('entity_' . $this->getEntityTypeId() . '_predelete', array($this, $current_sid, $new_sid));
     // Re-parent any entity that we don't want to orphan, whilst deactivating a State.
     // TODO D8-port: State should not know about Transition: move this to Workflow->DeactivateState.
     if ($new_sid) {
         // A candidate for the batch API.
         // @TODO: Future updates should seriously consider setting this with batch.
         $user = \Drupal::currentUser();
         // We can use global, since deactivate() is a UI-only function.
         $comment = t('Previous state deleted');
         foreach (_workflow_info_fields() as $field_name => $field_info) {
             $entity = NULL;
             $entity_type = $field_info->getTargetEntityTypeId();
             $field_name = $field_info->getName();
             $query = \Drupal::entityQuery($entity_type);
             $query->condition($field_name, $current_sid, '=');
             $result = $entity_type == 'comment' ? array() : $query->execute();
             foreach ($result as $entity_id) {
                 $entity = \Drupal::entityManager()->getStorage($entity_type)->load($entity_id);
                 $transition = WorkflowTransition::create([$current_sid, 'field_name' => $field_name]);
                 $transition->setTargetEntity($entity);
                 $transition->setValues($new_sid, $user->id(), REQUEST_TIME, $comment, TRUE);
                 $transition->force($force);
                 // Execute Transition, invoke 'pre' and 'post' events, save new state in Field-table, save also in workflow_transition_history.
                 // For Workflow Node, only {workflow_node} and {workflow_transition_history} are updated. For Field, also the Entity itself.
                 $new_sid = workflow_execute_transition($transition, $force);
             }
         }
     }
     // Delete the transitions this state is involved in.
     $workflow = Workflow::load($this->wid);
     foreach ($workflow->getTransitionsByStateId($current_sid, '') as $transition) {
         $transition->delete();
     }
     foreach ($workflow->getTransitionsByStateId('', $current_sid) as $transition) {
         $transition->delete();
     }
     // Delete the state. -- We don't actually delete, just deactivate.
     // This is a matter up for some debate, to delete or not to delete, since this
     // causes name conflicts for states. In the meantime, we just stick with what we know.
     // If you really want to delete the states, use workflow_cleanup module, or delete().
     $this->status = FALSE;
     $this->save();
     // Clear the cache.
     self::loadMultiple([], 0, TRUE);
 }
示例#4
0
 /**
  * {@inheritdoc}
  */
 public static function getPreviousStateId(EntityInterface $entity, $field_name = '')
 {
     $sid = '';
     if (!$entity) {
         return $sid;
     }
     // If $field_name is not known, yet, determine it.
     $field_name = $field_name ? $field_name : workflow_get_field_name($entity, $field_name);
     // If $field_name is found, get more details.
     if (!$field_name) {
         // Return the initial value.
         return $sid;
     }
     if (isset($entity->original)) {
         // A changed node.
         workflow_debug(__FILE__, __FUNCTION__, __LINE__, $sid);
         // @todo D8-port: still test this snippet.
     }
     // A node may not have a Workflow attached.
     if ($entity->isNew()) {
         // A new Node. D7: $is_new is not set when saving terms, etc.
         $sid = self::getCreationStateId($entity, $field_name);
     } elseif (!$sid) {
         // @todo?: Read the history with an explicit langcode.
         $langcode = '';
         // $entity->language()->getId();
         $entity_type = $entity->getEntityTypeId();
         if ($last_transition = WorkflowTransition::loadByProperties($entity_type, $entity->id(), [], $field_name, $langcode, 'DESC')) {
             $sid = $last_transition->getFromSid();
         }
     }
     if (!$sid) {
         // No history found on an existing entity.
         $sid = self::getCreationStateId($entity, $field_name);
     }
     return $sid;
 }
 /**
  * {@inheritdoc}
  *
  * Be careful: Widget may be shown in very different places. Test carefully!!
  *  - On a entity add/edit page
  *  - On a entity preview page
  *  - On a entity view page
  *  - On a entity 'workflow history' tab
  *  - On a comment display, in the comment history
  *  - On a comment form, below the comment history
  *
  * @todo D8: change "array $items" to "FieldInterface $items"
  */
 public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state)
 {
     $wid = $this->getFieldSetting('workflow_type');
     if (!($workflow = Workflow::load($wid))) {
         // @todo: add error message.
         return $element;
     }
     /* @var $item \Drupal\workflowfield\Plugin\Field\FieldType\WorkflowItem */
     $item = $items[$delta];
     /* @var $field_config \Drupal\field\Entity\FieldConfig */
     $field_config = $item->getFieldDefinition();
     /* @var $field_storage \Drupal\field\Entity\FieldStorageConfig */
     $field_storage = $field_config->getFieldStorageDefinition();
     $field_name = $field_storage->get('field_name');
     $entity = $item->getEntity();
     $from_sid = workflow_node_current_state($entity, $field_name);
     // Create a transition, to pass to the form. No need to use setValues().
     /* @var $transition WorkflowTransition */
     $transition = WorkflowTransition::create([$from_sid, 'field_name' => $field_name]);
     $transition->setTargetEntity($entity);
     if (!$this->isDefaultValueWidget($form_state)) {
         // Here, not the $element is added, but the entity form.
         // Option 1: use the Element.
         $element['#default_value'] = $transition;
         $element += WorkflowTransitionElement::transitionElement($element, $form_state, $form);
         // Option 2: use the Form, in order to get extra fields.
         //$entity_form_builder = \Drupal::getContainer()->get('entity.form_builder');
         //$element += $entity_form_builder->getForm($transition, 'add');
         //// Remove the action button. The Entity itself has one.
         //unset($element['actions']);
         // Option 3: use the true Element.
         // $form = $this->element($form, $form_state, $transition);
         //$element['workflow_transition'] = array(
         //      '#type' => 'workflow_transition',
         //      '#title' => t('Workflow transition'),
         //      '#default_value' => $transition,
         // );
     } else {
         // @todo D8: add a default value, so people can set a default comment.
         // On the Field settings page, User may not set a default value
         // (this is done by the Workflow module).
         // @see WorkflowState::getOptions();
         // @see WorkflowDefaultWidget::formElement();
         $element = array();
         return $element;
         workflow_debug(__FILE__, __FUNCTION__, __LINE__, '', '');
         // @todo D8-port: still test this snippet.
         // @see workflowfield_form_field_config_edit_form_alter for other settings
         // The Workflow field must have a value, so set to required.
         // Unfortunately, we need hook_form_alter for this.
         //$form['required']['#default_value'] = 1;
         //$form['required']['#disabled'] = TRUE;
         // Explicitly set default value to 'creation' and show element,
         // so people can set a default comment.
         $transition->to_sid = $workflow->getCreationSid();
         $transition->setExecuted(TRUE);
         // @TODO D8-port: use a proper WorkflowTransitionElement call.
         $element['#default_value'] = $transition;
         $element += WorkflowTransitionElement::transitionElement($element, $form_state, $form);
         // No action buttons on default field settings page.
         // This is evaluated in hook_form_alter.
         _workflow_use_action_buttons(FALSE);
         // Make sure the options box is not hidden (when action buttons active).
         //$element['to_sid']['#type'] = 'select';
         $element['to_sid']['#title'] = 'Initial state';
         $element['to_sid']['#access'] = TRUE;
         unset($element['workflow_current_state']);
         return $element;
     }
     return $element;
 }
 /**
  * Prepares a transition to be reverted.
  *
  * @param \Drupal\workflow\Entity\WorkflowTransitionInterface $transition
  *   The transition to be reverted.
  *
  * @return \Drupal\workflow\Entity\WorkflowTransitionInterface
  *   The prepared transition ready to be stored.
  */
 protected function prepareRevertedTransition(WorkflowTransitionInterface $transition)
 {
     $user = \Drupal::currentUser();
     $entity = $transition->getTargetEntity();
     $field_name = $transition->getFieldName();
     $current_sid = workflow_node_current_state($entity, $field_name);
     $previous_sid = $transition->getFromSid();
     $comment = t('State reverted.');
     $transition = WorkflowTransition::create([$current_sid, 'field_name' => $field_name]);
     $transition->setTargetEntity($entity);
     $transition->setValues($previous_sid, $user->id(), REQUEST_TIME, $comment);
     return $transition;
 }
 /**
  * @return WorkflowTransitionInterface
  */
 protected function getTransitionForExecution(EntityInterface $entity)
 {
     $user = workflow_current_user();
     if (!$entity) {
         \Drupal::logger('workflow_action')->notice('Unable to get current entity - entity is not defined.', []);
         return NULL;
     }
     // Get the entity type and numeric ID.
     $entity_id = $entity->id();
     if (!$entity_id) {
         \Drupal::logger('workflow_action')->notice('Unable to get current entity ID - entity is not yet saved.', []);
         return NULL;
     }
     // In 'after saving new content', the node is already saved. Avoid second insert.
     // Todo: clone?
     $entity->enforceIsNew(FALSE);
     $config = $this->configuration;
     $field_name = workflow_get_field_name($entity, $config['field_name']);
     $current_sid = workflow_node_current_state($entity, $field_name);
     if (!$current_sid) {
         \Drupal::logger('workflow_action')->notice('Unable to get current workflow state of entity %id.', array('%id' => $entity_id));
         return NULL;
     }
     $to_sid = isset($config['to_sid']) ? $config['to_sid'] : '';
     // Get the Comment. Parse the $comment variables.
     $comment_string = $this->configuration['comment'];
     $comment = t($comment_string, array('%title' => $entity->label(), '%state' => workflow_get_sid_name($to_sid), '%user' => $user->getUsername()));
     $force = $this->configuration['force'];
     $transition = WorkflowTransition::create([$current_sid, 'field_name' => $field_name]);
     $transition->setTargetEntity($entity);
     $transition->setValues($to_sid, $user->id(), REQUEST_TIME, $comment);
     $transition->force($force);
     return $transition;
 }
 /**
  * Generates an overview table of older revisions of a node,
  * but only if this::historyAccess() allows it.
  *
  * @param \Drupal\node\NodeInterface $node
  *   A node object.
  *
  * @return array
  *   An array as expected by drupal_render().
  */
 public function historyOverview(EntityInterface $node = NULL)
 {
     $form = array();
     /*
      * Get data from parameters.
      */
     // TODO D8-port: make Workflow History tab happen for every entity_type.
     // For workflow_tab_page with multiple workflows, use a separate view. See [#2217291].
     // @see workflow.routing.yml, workflow.links.task.yml, WorkflowTransitionListController.
     //    workflow_debug(__FILE__, __FUNCTION__, __LINE__);  // @todo D8-port: still test this snippet.
     // ATM it only works for Nodes and Terms.
     // This is a hack. The Route should always pass an object.
     // On view tab, $entity is object,
     // On workflow tab, $entity is id().
     // Get the entity for this form.
     if (!($entity = workflow_url_get_entity($node))) {
         return $form;
     }
     /*
      * Get derived data from parameters.
      */
     if (!($field_name = workflow_get_field_name($entity, workflow_url_get_field_name()))) {
         return $form;
     }
     /*
      * Step 1: generate the Transition Form.
      */
     // Create a transition, to pass to the form. No need to use setValues().
     $current_sid = workflow_node_current_state($entity, $field_name);
     $transition = WorkflowTransition::create([$current_sid, 'field_name' => $field_name]);
     $transition->setTargetEntity($entity);
     // Add the WorkflowTransitionForm to the page.
     $form = $this->entityFormBuilder()->getForm($transition, 'add');
     /*
      * Step 2: generate the Transition History List.
      */
     $entity_type = 'workflow_transition';
     // $form = $this->listing('workflow_transition');
     $list_builder = $this->entityManager()->getListBuilder($entity_type);
     // Add the Node explicitly, since $list_builder expects a Transition.
     $list_builder->workflow_entity = $entity;
     $form += $list_builder->render();
     /*
      * Finally: sort the elements (overriding their weight).
      */
     // $form['#weight'] = 10;
     $form['actions']['#weight'] = 100;
     $form['workflow_list_title']['#weight'] = 200;
     $form['table']['#weight'] = 201;
     return $form;
 }
 /**
  * Define the fields. Modify the parent fields.
  * {@inheritdoc}
  */
 public static function baseFieldDefinitions(EntityTypeInterface $entity_type)
 {
     $fields = array();
     // Add the specific ID-field : tid vs. hid.
     $fields['tid'] = BaseFieldDefinition::create('integer')->setLabel(t('Transition ID'))->setDescription(t('The transition ID.'))->setReadOnly(TRUE)->setSetting('unsigned', TRUE);
     // Get the rest of the fields.
     $fields += parent::baseFieldDefinitions($entity_type);
     // The timestamp has a different description.
     $fields['timestamp'] = [];
     // Reset old value.
     $fields['timestamp'] = BaseFieldDefinition::create('created')->setLabel(t('Scheduled'))->setDescription(t('The date+time this transition is scheduled for.'))->setQueryable(FALSE)->setRevisionable(TRUE);
     // Remove the specific ID-field : tid vs. hid.
     unset($fields['hid']);
     return $fields;
 }
 /**
  * {@inheritdoc}
  *
  * N.B. A large part of this function is taken from CommentDefaultFormatter.
  */
 public function viewElements(FieldItemListInterface $items, $langcode)
 {
     $elements = array();
     $output = array();
     $field_name = $this->fieldDefinition->getName();
     $entity = $items->getEntity();
     $entity_type = $entity->getEntityTypeId();
     $status = $items->status;
     $workflow_settings = $this->getFieldSettings();
     $user = \Drupal::currentUser();
     // @todo #2287057: OK?
     // @todo: Perhaps global user is not always the correct user.
     // E.g., on ScheduledTransition->execute()? But this function is mostly used in UI.
     $current_sid = WorkflowManager::getCurrentStateId($entity, $field_name);
     /* @var $current_state WorkflowState */
     $current_state = WorkflowState::load($current_sid);
     // First compose the current value with the normal formatter from list.module.
     $elements = workflow_state_formatter($entity, $field_name, $current_sid);
     // The state must not be deleted, or corrupted.
     if (!$current_state) {
         return $elements;
     }
     // Check permission, so that even with state change rights,
     // the form can be suppressed from the entity view (#1893724).
     $type_id = $current_state->getWorkflowId();
     if (!\Drupal::currentUser()->hasPermission("access {$type_id} workflow_transition form")) {
         return $elements;
     }
     // Workflows are added to the search results and search index by
     // workflow_node_update_index() instead of by this formatter, so don't
     // return anything if the view mode is search_index or search_result.
     if (in_array($this->viewMode, array('search_result', 'search_index'))) {
         return $elements;
     }
     if ($entity_type == 'comment') {
         // No Workflow form allowed on a comment display.
         // (Also, this avoids a lot of error messages.)
         return $elements;
     }
     // Only build form if user has possible target state(s).
     if (!$current_state->showWidget($entity, $field_name, $user, FALSE)) {
         return $elements;
     }
     // Create a transition, to pass to the form. No need to use setValues().
     $transition = WorkflowTransition::create([$current_sid, 'field_name' => $field_name]);
     $transition->setTargetEntity($entity);
     // Remove the default formatter. We are now building the widget.
     $elements = array();
     // BEGIN Copy from CommentDefaultFormatter
     $elements['#cache']['contexts'][] = 'user.permissions';
     $output['workflows'] = [];
     // Add the WorkflowTransitionForm to the page.
     // $build = $this->viewBuilder->viewMultiple($workflows);
     $build = $this->entityFormBuilder()->getForm($transition, 'add');
     $output['workflows'] += $build;
     // Only show the add workflow form if the user has permission.
     $elements['#cache']['contexts'][] = 'user.roles';
     // Do not show the form for the print view mode.
     $elements[] = $output + array('#workflow_type' => $this->getFieldSetting('workflow_type'), '#workflow_display_mode' => $this->getFieldSetting('default_mode'), 'workflows' => array());
     // END Copy from CommentDefaultFormatter
     return $elements;
 }