[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/src/MVC/Model/ -> WorkflowBehaviorTrait.php (source)

   1  <?php
   2  
   3  /**
   4   * Joomla! Content Management System
   5   *
   6   * @copyright  (C) 2020 Open Source Matters, Inc. <https://www.joomla.org>
   7   * @license    GNU General Public License version 2 or later; see LICENSE
   8   */
   9  
  10  namespace Joomla\CMS\MVC\Model;
  11  
  12  use Joomla\CMS\Component\ComponentHelper;
  13  use Joomla\CMS\Factory;
  14  use Joomla\CMS\Filesystem\Path;
  15  use Joomla\CMS\Form\Form;
  16  use Joomla\CMS\Language\Text;
  17  use Joomla\CMS\Plugin\PluginHelper;
  18  use Joomla\CMS\Workflow\Workflow;
  19  
  20  // phpcs:disable PSR1.Files.SideEffects
  21  \defined('JPATH_PLATFORM') or die;
  22  // phpcs:enable PSR1.Files.SideEffects
  23  
  24  /**
  25   * Trait which supports state behavior
  26   *
  27   * @since  4.0.0
  28   */
  29  trait WorkflowBehaviorTrait
  30  {
  31      /**
  32       * The name of the component.
  33       *
  34       * @var    string
  35       * @since  4.0.0
  36       */
  37      protected $extension = null;
  38  
  39      /**
  40       * The section of the component.
  41       *
  42       * @var    string
  43       * @since  4.0.0
  44       */
  45      protected $section = '';
  46  
  47      /**
  48       * Is workflow for this component enabled?
  49       *
  50       * @var    boolean
  51       * @since  4.0.0
  52       */
  53      protected $workflowEnabled = false;
  54  
  55      /**
  56       * The workflow object
  57       *
  58       * @var    Workflow
  59       * @since  4.0.0
  60       */
  61      protected $workflow;
  62  
  63      /**
  64       * Set Up the workflow
  65       *
  66       * @param   string  $extension  The option and section separated by.
  67       *
  68       * @return  void
  69       *
  70       * @since   4.0.0
  71       */
  72      public function setUpWorkflow($extension)
  73      {
  74          $parts = explode('.', $extension);
  75  
  76          $this->extension = array_shift($parts);
  77  
  78          if (count($parts)) {
  79              $this->section = array_shift($parts);
  80          }
  81  
  82          $this->workflow = new Workflow($extension);
  83  
  84          $params = ComponentHelper::getParams($this->extension);
  85  
  86          $this->workflowEnabled = $params->get('workflow_enabled');
  87  
  88          $this->enableWorkflowBatch();
  89      }
  90  
  91      /**
  92       * Add the workflow batch to the command list. Can be overwritten bei the child class
  93       *
  94       * @return  void
  95       *
  96       * @since   4.0.0
  97       */
  98      protected function enableWorkflowBatch()
  99      {
 100          // Enable batch
 101          if ($this->workflowEnabled && property_exists($this, 'batch_commands')) {
 102              $this->batch_commands['workflowstage_id'] = 'batchWorkflowStage';
 103          }
 104      }
 105  
 106      /**
 107       * Method to allow derived classes to preprocess the form.
 108       *
 109       * @param   Form   $form  A Form object.
 110       * @param   mixed  $data  The data expected for the form.
 111       *
 112       * @return  void
 113       *
 114       * @since   4.0.0
 115       * @see     FormField
 116       */
 117      public function workflowPreprocessForm(Form $form, $data)
 118      {
 119          $this->addTransitionField($form, $data);
 120  
 121          if (!$this->workflowEnabled) {
 122              return;
 123          }
 124  
 125          // Import the workflow plugin group to allow form manipulation.
 126          $this->importWorkflowPlugins();
 127      }
 128  
 129      /**
 130       * Let plugins access stage change events
 131       *
 132       * @return  void
 133       *
 134       * @since   4.0.0
 135       */
 136      public function workflowBeforeStageChange()
 137      {
 138          if (!$this->workflowEnabled) {
 139              return;
 140          }
 141  
 142          $this->importWorkflowPlugins();
 143      }
 144  
 145      /**
 146       * Preparation of workflow data/plugins
 147       *
 148       * @return  void
 149       *
 150       * @since   4.0.0
 151       */
 152      public function workflowBeforeSave()
 153      {
 154          if (!$this->workflowEnabled) {
 155              return;
 156          }
 157  
 158          $this->importWorkflowPlugins();
 159      }
 160  
 161      /**
 162       * Executing of relevant workflow methods
 163       *
 164       * @return  void
 165       *
 166       * @since   4.0.0
 167       */
 168      public function workflowAfterSave($data)
 169      {
 170          // Regardless if workflow is active or not, we have to set the default stage
 171          // So we can work with the workflow, when the user activates it later
 172          $id = $this->getState($this->getName() . '.id');
 173          $isNew = $this->getState($this->getName() . '.new');
 174  
 175          // We save the first stage
 176          if ($isNew) {
 177              // We have to add the paths, because it could be called outside of the extension context
 178              $path = JPATH_BASE . '/components/' . $this->extension;
 179  
 180              $path = Path::check($path);
 181  
 182              Form::addFormPath($path . '/forms');
 183              Form::addFormPath($path . '/models/forms');
 184              Form::addFieldPath($path . '/models/fields');
 185              Form::addFormPath($path . '/model/form');
 186              Form::addFieldPath($path . '/model/field');
 187  
 188              $form = $this->getForm();
 189  
 190              $stage_id = $this->getStageForNewItem($form, $data);
 191  
 192              $this->workflow->createAssociation($id, $stage_id);
 193          }
 194  
 195          if (!$this->workflowEnabled) {
 196              return;
 197          }
 198  
 199          // Execute transition
 200          if (!empty($data['transition'])) {
 201              $this->executeTransition([$id], $data['transition']);
 202          }
 203      }
 204  
 205      /**
 206       * Batch change workflow stage or current.
 207       *
 208       * @param   integer  $value     The workflow stage ID.
 209       * @param   array    $pks       An array of row IDs.
 210       * @param   array    $contexts  An array of item contexts.
 211       *
 212       * @return  mixed  An array of new IDs on success, boolean false on failure.
 213       *
 214       * @since   4.0.0
 215       */
 216      public function batchWorkflowStage(int $value, array $pks, array $contexts)
 217      {
 218          $user = Factory::getApplication()->getIdentity();
 219  
 220          $workflow = Factory::getApplication()->bootComponent('com_workflow');
 221  
 222          if (!$user->authorise('core.admin', $this->option)) {
 223              $this->setError(Text::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EXECUTE_TRANSITION'));
 224          }
 225  
 226          // Get workflow stage information
 227          $stage = $workflow->getMVCFactory()->createTable('Stage', 'Administrator');
 228  
 229          if (empty($value) || !$stage->load($value)) {
 230              Factory::getApplication()->enqueueMessage(Text::sprintf('JGLOBAL_BATCH_WORKFLOW_STAGE_ROW_NOT_FOUND'), 'error');
 231  
 232              return false;
 233          }
 234  
 235          if (empty($pks)) {
 236              Factory::getApplication()->enqueueMessage(Text::sprintf('JGLOBAL_BATCH_WORKFLOW_STAGE_ROW_NOT_FOUND'), 'error');
 237  
 238              return false;
 239          }
 240  
 241          // Update workflow associations
 242          return $this->workflow->updateAssociations($pks, $value);
 243      }
 244  
 245      /**
 246       * Batch change workflow stage or current.
 247       *
 248       * @param   integer  $oldId     The ID of the item copied from
 249       * @param   integer  $newId     The ID of the new item
 250       *
 251       * @return  null
 252       *
 253       * @since   4.0.0
 254       */
 255      public function workflowCleanupBatchMove($oldId, $newId)
 256      {
 257          // Trigger workflow plugins only if enable (will be triggered from parent class)
 258          if ($this->workflowEnabled) {
 259              $this->importWorkflowPlugins();
 260          }
 261  
 262          // We always need an association, so create one
 263          $table = $this->getTable();
 264  
 265          $table->load($newId);
 266  
 267          $catKey = $table->getColumnAlias('catid');
 268  
 269          $stage_id = $this->workflow->getDefaultStageByCategory($table->$catKey);
 270  
 271          if (empty($stage_id)) {
 272              return;
 273          }
 274  
 275          $this->workflow->createAssociation((int) $newId, (int) $stage_id);
 276      }
 277  
 278      /**
 279       * Runs transition for item.
 280       *
 281       * @param   array    $pks           Id of items to execute the transition
 282       * @param   integer  $transitionId  Id of transition
 283       *
 284       * @return  boolean
 285       *
 286       * @since   4.0.0
 287       */
 288      public function executeTransition(array $pks, int $transitionId)
 289      {
 290          $result = $this->workflow->executeTransition($pks, $transitionId);
 291  
 292          if (!$result) {
 293              $app = Factory::getApplication();
 294  
 295              $app->enqueueMessage(Text::_('COM_CONTENT_ERROR_UPDATE_STAGE', $app::MSG_WARNING));
 296  
 297              return false;
 298          }
 299  
 300          return true;
 301      }
 302  
 303      /**
 304       * Import the Workflow plugins.
 305       *
 306       * @param   Form   $form  A Form object.
 307       * @param   mixed  $data  The data expected for the form.
 308       *
 309       * @return  void
 310       */
 311      protected function importWorkflowPlugins()
 312      {
 313          PluginHelper::importPlugin('workflow');
 314      }
 315  
 316      /**
 317       * Adds a transition field to the form. Can be overwritten by the child class if not needed
 318       *
 319       * @param   Form   $form  A Form object.
 320       * @param   mixed  $data  The data expected for the form.
 321       *
 322       * @return  void
 323       * @since   4.0.0
 324       */
 325      protected function addTransitionField(Form $form, $data)
 326      {
 327          $extension = $this->extension . ($this->section ? '.' . $this->section : '');
 328  
 329          $field = new \SimpleXMLElement('<field></field>');
 330  
 331          $field->addAttribute('name', 'transition');
 332          $field->addAttribute('type', $this->workflowEnabled ? 'transition' : 'hidden');
 333          $field->addAttribute('label', 'COM_CONTENT_WORKFLOW');
 334          $field->addAttribute('extension', $extension);
 335  
 336          $form->setField($field);
 337  
 338          $table = $this->getTable();
 339  
 340          $key = $table->getKeyName();
 341  
 342          $id = isset($data->$key) ? $data->$key : $form->getValue($key);
 343  
 344          if ($id) {
 345              // Transition field
 346              $assoc = $this->workflow->getAssociation($id);
 347  
 348              if (!empty($assoc->stage_id)) {
 349                  $form->setFieldAttribute('transition', 'workflow_stage', (int) $assoc->stage_id);
 350              }
 351          } else {
 352              $stage_id = $this->getStageForNewItem($form, $data);
 353  
 354              if (!empty($stage_id)) {
 355                  $form->setFieldAttribute('transition', 'workflow_stage', (int) $stage_id);
 356              }
 357          }
 358      }
 359  
 360      /**
 361       * Try to load a workflow stage for newly created items
 362       * which does not have a workflow assigned yet. If the category is not the
 363       * carrier, overwrite it on your model and deliver your own carrier.
 364       *
 365       * @param   Form   $form  A Form object.
 366       * @param   mixed  $data  The data expected for the form.
 367       *
 368       * @return  boolean|integer  An integer, holding the stage ID or false
 369       * @since   4.0.0
 370       */
 371      protected function getStageForNewItem(Form $form, $data)
 372      {
 373          $table = $this->getTable();
 374  
 375          $hasKey = $table->hasField('catid');
 376  
 377          if (!$hasKey) {
 378              return false;
 379          }
 380  
 381          $catKey = $table->getColumnAlias('catid');
 382  
 383          $field = $form->getField($catKey);
 384  
 385          if (!$field) {
 386              return false;
 387          }
 388  
 389          $catId = isset(((object) $data)->$catKey) ? ((object) $data)->$catKey : $form->getValue($catKey);
 390  
 391          // Try to get the category from the html code of the field
 392          if (empty($catId)) {
 393              $catId = $field->getAttribute('default', null);
 394  
 395              if (!$catId) {
 396                  // Choose the first category available
 397                  $catOptions = $field->options;
 398  
 399                  if ($catOptions && !empty($catOptions[0]->value)) {
 400                      $catId = (int) $catOptions[0]->value;
 401                  }
 402              }
 403          }
 404  
 405          if (empty($catId)) {
 406              return false;
 407          }
 408  
 409          return $this->workflow->getDefaultStageByCategory($catId);
 410      }
 411  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer