diff --git a/administrator/components/com_admin/sql/updates/mysql/4.1.0-2021-07-30.sql b/administrator/components/com_admin/sql/updates/mysql/4.1.0-2021-07-30.sql new file mode 100644 index 0000000000000..76a9605841c17 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/mysql/4.1.0-2021-07-30.sql @@ -0,0 +1,37 @@ +-- +-- Insert a new workflow for com_modules +-- +INSERT INTO `#__workflows` (`id`, `asset_id`, `published`, `title`, `description`, `extension`, `default`, `ordering`, `created`, `created_by`, `modified`, `modified_by`, `checked_out_time`, `checked_out`) VALUES +(NULL, 0, 1, 'COM_WORKFLOW_BASIC_WORKFLOW_MODULES', '', 'com_modules.module', 1, 1, CURRENT_TIMESTAMP(), 0, CURRENT_TIMESTAMP(), 0, NULL, 0); + +-- +-- Inserting the default stage for the new workflow +-- +INSERT INTO `#__workflow_stages` (`id`, `asset_id`, `ordering`, `workflow_id`, `published`, `title`, `description`, `default`, `checked_out_time`, `checked_out`) +SELECT NULL, 0, 1, `id`, 1, 'COM_WORKFLOW_BASIC_STAGE', '', 1, NULL, 0 FROM `#__workflows` WHERE `title` = 'COM_WORKFLOW_BASIC_WORKFLOW_MODULES'; + +-- +-- Inserting the transitions for the new workflow +-- +INSERT INTO `#__workflow_transitions` (`id`, `asset_id`, `published`, `ordering`, `workflow_id`, `title`, `description`, `from_stage_id`, `to_stage_id`, `options`) +SELECT NULL, 0, 1, NULL, `w`.`id`, 'Unpublish', '', -1, `s`.`id`, '{"publishing":"0"}' FROM `#__workflows` as `w` INNER JOIN `#__workflow_stages` as `s` ON `w`.`title` = 'COM_WORKFLOW_BASIC_WORKFLOW_MODULES' AND `s`.`title` = 'COM_WORKFLOW_BASIC_STAGE' AND `s`.`extension` = 'com_modules.module'; + +INSERT INTO `#__workflow_transitions` (`id`, `asset_id`, `published`, `ordering`, `workflow_id`, `title`, `description`, `from_stage_id`, `to_stage_id`, `options`) +SELECT NULL, 0, 1, NULL, `w`.`id`, 'Publish', '', -1, `s`.`id`, '{"publishing":"1"}' FROM `#__workflows` as `w` INNER JOIN `#__workflow_stages` as `s` ON `w`.`title` = 'COM_WORKFLOW_BASIC_WORKFLOW_MODULES' AND `s`.`title` = 'COM_WORKFLOW_BASIC_STAGE' AND `s`.`extension` = 'com_modules.module'; + +INSERT INTO `#__workflow_transitions` (`id`, `asset_id`, `published`, `ordering`, `workflow_id`, `title`, `description`, `from_stage_id`, `to_stage_id`, `options`) +SELECT NULL, 0, 1, NULL, `w`.`id`, 'Trash', '', -1, `s`.`id`, '{"publishing":"-2"}' FROM `#__workflows` as `w` INNER JOIN `#__workflow_stages` as `s` ON `w`.`title` = 'COM_WORKFLOW_BASIC_WORKFLOW_MODULES' AND `s`.`title` = 'COM_WORKFLOW_BASIC_STAGE' AND `s`.`workflow_id` = `w`.`id`; + +-- +-- Creating Associations for existing modules +-- +INSERT INTO `#__workflow_associations` (`item_id`, `stage_id`, `extension`) +SELECT `m`.`id`, `s`.`id`, 'com_modules.module' +FROM `#__modules` as `m` , +( + `#__workflow_stages` as `s` + INNER JOIN `#__workflows` as `w` + ON `w`.`title` = 'COM_WORKFLOW_BASIC_WORKFLOW_MODULES' + AND `s`.`title` = 'COM_WORKFLOW_BASIC_STAGE' + AND `s`.`workflow_id` = `w`.`id` +); \ No newline at end of file diff --git a/administrator/components/com_admin/sql/updates/postgresql/4.1.0-2021-07-30.sql b/administrator/components/com_admin/sql/updates/postgresql/4.1.0-2021-07-30.sql new file mode 100644 index 0000000000000..aa8ef84e84aeb --- /dev/null +++ b/administrator/components/com_admin/sql/updates/postgresql/4.1.0-2021-07-30.sql @@ -0,0 +1,37 @@ +-- +-- Insert a new workflow for com_modules +-- +INSERT INTO "#__workflows" ("id", "asset_id", "published", "title", "description", "extension", "default", "ordering", "created", "created_by", "modified", "modified_by", "checked_out_time", "checked_out") VALUES +(NULL, 0, 1, 'COM_WORKFLOW_BASIC_WORKFLOW_MODULES', '', 'com_modules.module', 1, 1, CURRENT_TIMESTAMP(), 0, CURRENT_TIMESTAMP(), 0, NULL, 0); + +-- +-- Inserting the default stage for the new workflow +-- +INSERT INTO "#__workflow_stages" ("id", "asset_id", "ordering", "workflow_id", "published", "title", "description", "default", "checked_out_time", "checked_out") +SELECT NULL, 0, 1, "id", 1, 'COM_WORKFLOW_BASIC_STAGE', '', 1, NULL, 0 FROM "#__workflows" WHERE "title" = 'COM_WORKFLOW_BASIC_WORKFLOW_MODULES'; + +-- +-- Inserting the transitions for the new workflow +-- +INSERT INTO "#__workflow_transitions" ("id", "asset_id", "published", "ordering", "workflow_id", "title", "description", "from_stage_id", "to_stage_id", "options") +SELECT NULL, 0, 1, NULL, "w"."id", 'Unpublish', '', -1, "s"."id", '{"publishing":"0"}' FROM "#__workflows" as "w" INNER JOIN "#__workflow_stages" as "s" ON "w"."title" = 'COM_WORKFLOW_BASIC_WORKFLOW_MODULES' AND "s"."title" = 'COM_WORKFLOW_BASIC_STAGE' AND "s"."extension" = 'com_modules.module'; + +INSERT INTO "#__workflow_transitions" ("id", "asset_id", "published", "ordering", "workflow_id", "title", "description", "from_stage_id", "to_stage_id", "options") +SELECT NULL, 0, 1, NULL, "w"."id", 'Publish', '', -1, "s"."id", '{"publishing":"1"}' FROM "#__workflows" as "w" INNER JOIN "#__workflow_stages" as "s" ON "w"."title" = 'COM_WORKFLOW_BASIC_WORKFLOW_MODULES' AND "s"."title" = 'COM_WORKFLOW_BASIC_STAGE' AND "s"."extension" = 'com_modules.module'; + +INSERT INTO "#__workflow_transitions" ("id", "asset_id", "published", "ordering", "workflow_id", "title", "description", "from_stage_id", "to_stage_id", "options") +SELECT NULL, 0, 1, NULL, "w"."id", 'Trash', '', -1, "s"."id", '{"publishing":"-2"}' FROM "#__workflows" as "w" INNER JOIN "#__workflow_stages" as "s" ON "w"."title" = 'COM_WORKFLOW_BASIC_WORKFLOW_MODULES' AND "s"."title" = 'COM_WORKFLOW_BASIC_STAGE' AND "s"."workflow_id" = "w"."id"; + +-- +-- Creating Associations for existing modules +-- +INSERT INTO "#__workflow_associations" ("item_id", "stage_id", "extension") +SELECT "m"."id", "s"."id", 'com_modules.module' +FROM "#__modules" as "m", +( + "#__workflow_stages" as "s" + INNER JOIN "#__workflows" as "w" + ON "w"."title" = 'COM_WORKFLOW_BASIC_WORKFLOW_MODULES' + AND "s"."title" = 'COM_WORKFLOW_BASIC_STAGE' + AND "s"."workflow_id" = "w"."id" +); \ No newline at end of file diff --git a/administrator/components/com_content/src/Model/ArticlesModel.php b/administrator/components/com_content/src/Model/ArticlesModel.php index d7b325ff152c5..dd6631448dc5a 100644 --- a/administrator/components/com_content/src/Model/ArticlesModel.php +++ b/administrator/components/com_content/src/Model/ArticlesModel.php @@ -294,7 +294,8 @@ protected function getListQuery() ->join('LEFT', $db->quoteName('#__users', 'ua'), $db->quoteName('ua.id') . ' = ' . $db->quoteName('a.created_by')) ->join('INNER', $db->quoteName('#__workflow_associations', 'wa'), $db->quoteName('wa.item_id') . ' = ' . $db->quoteName('a.id')) ->join('INNER', $db->quoteName('#__workflow_stages', 'ws'), $db->quoteName('ws.id') . ' = ' . $db->quoteName('wa.stage_id')) - ->join('INNER', $db->quoteName('#__workflows', 'w'), $db->quoteName('w.id') . ' = ' . $db->quoteName('ws.workflow_id')); + ->join('INNER', $db->quoteName('#__workflows', 'w'), $db->quoteName('w.id') . ' = ' . $db->quoteName('ws.workflow_id')) + ->where($db->quoteName('wa.extension') . ' = ' . $db->quote('com_content.article')); if (PluginHelper::isEnabled('content', 'vote')) { $query->select( diff --git a/administrator/components/com_content/tmpl/featured/default.php b/administrator/components/com_content/tmpl/featured/default.php index d0f9714e2494b..47241f18f9636 100644 --- a/administrator/components/com_content/tmpl/featured/default.php +++ b/administrator/components/com_content/tmpl/featured/default.php @@ -216,7 +216,7 @@ 'title' => Text::_($item->stage_title), 'tip_content' => Text::sprintf('JWORKFLOW', Text::_($item->workflow_title)), 'id' => 'workflow-' . $item->id, - 'task' => 'articles.runTransitions' + 'task' => 'articles.runTransition' ]; echo (new TransitionButton($options)) diff --git a/administrator/components/com_menus/presets/default.xml b/administrator/components/com_menus/presets/default.xml index 7e8252caf344a..8c62f379d6d93 100644 --- a/administrator/components/com_menus/presets/default.xml +++ b/administrator/components/com_menus/presets/default.xml @@ -99,6 +99,14 @@ link="index.php?option=com_modules&view=modules&client_id=1" quicktask="index.php?option=com_modules&view=select&client_id=1" /> + + + + + +
@@ -15,4 +17,23 @@
+
+ + + + + + +
+
+ + + + +
+
+ + + +
\ No newline at end of file diff --git a/administrator/components/com_modules/config.xml b/administrator/components/com_modules/config.xml index aecb8410f18da..3994657d5482a 100644 --- a/administrator/components/com_modules/config.xml +++ b/administrator/components/com_modules/config.xml @@ -54,4 +54,26 @@ section="component" /> + +
+
+ + + + +
+
diff --git a/administrator/components/com_modules/forms/filter_modules.xml b/administrator/components/com_modules/forms/filter_modules.xml index 6adc9ec4377f8..e60a68da459c9 100644 --- a/administrator/components/com_modules/forms/filter_modules.xml +++ b/administrator/components/com_modules/forms/filter_modules.xml @@ -58,6 +58,16 @@ + + + + + + + +
+ +
diff --git a/administrator/components/com_modules/forms/moduleadmin.xml b/administrator/components/com_modules/forms/moduleadmin.xml index d1f9037110fc4..9e72723f82d55 100644 --- a/administrator/components/com_modules/forms/moduleadmin.xml +++ b/administrator/components/com_modules/forms/moduleadmin.xml @@ -145,4 +145,22 @@ validate="rules" /> + +
+ +
diff --git a/administrator/components/com_modules/src/Extension/ModulesComponent.php b/administrator/components/com_modules/src/Extension/ModulesComponent.php index 1d90e6d75b772..ff167c5b4ebe2 100644 --- a/administrator/components/com_modules/src/Extension/ModulesComponent.php +++ b/administrator/components/com_modules/src/Extension/ModulesComponent.php @@ -10,9 +10,14 @@ namespace Joomla\Component\Modules\Administrator\Extension; +use Joomla\CMS\Factory; use Joomla\CMS\Extension\BootableExtensionInterface; use Joomla\CMS\Extension\MVCComponent; use Joomla\CMS\HTML\HTMLRegistryAwareTrait; +use Joomla\CMS\Language\Text; +use Joomla\CMS\Workflow\WorkflowServiceInterface; +use Joomla\CMS\Workflow\WorkflowServiceTrait; +use Joomla\Component\Modules\Administrator\Helper\ModulesHelper; use Joomla\Component\Modules\Administrator\Service\HTML\Modules; use Psr\Container\ContainerInterface; @@ -21,9 +26,53 @@ * * @since 4.0.0 */ -class ModulesComponent extends MVCComponent implements BootableExtensionInterface +class ModulesComponent extends MVCComponent implements + BootableExtensionInterface, + WorkflowServiceInterface { use HTMLRegistryAwareTrait; + use WorkflowServiceTrait; + + /** + * @var array + * @since __DEPLOY_VERSION_ + */ + protected $supportedFunctionality = [ + 'core.state' => true, + ]; + + /** + * The trashed condition + * + * @since __DEPLOY_VERSION__ + */ + public const CONDITION_NAMES = [ + self::CONDITION_PUBLISHED => 'JPUBLISHED', + self::CONDITION_UNPUBLISHED => 'JUNPUBLISHED', + self::CONDITION_TRASHED => 'JTRASHED', + ]; + + /** + * The published condition + * + * @since __DEPLOY_VERSION__ + */ + public const CONDITION_PUBLISHED = 1; + + /** + * The unpublished condition + * + * @since __DEPLOY_VERSION__ + */ + public const CONDITION_UNPUBLISHED = 0; + + /** + * The trashed condition + * + * @since __DEPLOY_VERSION__ + */ + public const CONDITION_TRASHED = -2; + /** * Booting the extension. This is the function to set up the environment of the extension like @@ -42,4 +91,65 @@ public function boot(ContainerInterface $container) { $this->getRegistry()->register('modules', new Modules()); } + + /** + * Returns valid contexts + * + * @return array + * + * @since __DEPLOY_VERSION__ + */ + public function getWorkflowContexts(): array + { + Factory::getLanguage()->load('com_modules', JPATH_ADMINISTRATOR); + + $contexts = [ + 'com_modules.module' => Text::_('COM_MODULES') + ]; + + return $contexts; + } + + /** + * Returns a table name for the state association + * + * @param string $section An optional section to separate different areas in the component + * + * @return string + * + * @since __DEPLOY_VERSION__ + */ + public function getWorkflowTableBySection(?string $section = null): string + { + return '#__modules'; + } + + /** + * Method to filter transitions by given id of state. + * + * @param array $transitions The Transitions to filter + * @param int $pk Id of the state + * + * @return array + * + * @since __DEPLOY_VERSION__ + */ + public function filterTransitions(array $transitions, int $pk): array + { + return ModulesHelper::filterTransitions($transitions, $pk); + } + + /** + * Returns the workflow context based on the given category section + * + * @param string $section The section + * + * @return string|null + * + * @since __DEPLOY_VERSION__ + */ + public function getCategoryWorkflowContext(?string $section = null): string + { + return array_key_first($this->getWorkflowContexts()); + } } diff --git a/administrator/components/com_modules/src/Helper/ModulesHelper.php b/administrator/components/com_modules/src/Helper/ModulesHelper.php index e2aefdc58a359..fd9d8057f22c4 100644 --- a/administrator/components/com_modules/src/Helper/ModulesHelper.php +++ b/administrator/components/com_modules/src/Helper/ModulesHelper.php @@ -305,4 +305,27 @@ public static function createOptionGroup($label = '', $options = array()) return $group; } + + /** + * Method to filter transitions by given id of state + * + * @param array $transitions Array of transitions + * @param int $pk Id of state + * @param int $workflowId Id of the workflow + * + * @return array + * + * @since __DEPLOY_VERSION__ + */ + public static function filterTransitions(array $transitions, int $pk, int $workflowId = 0): array + { + return array_values( + array_filter( + $transitions, + function ($var) use ($pk, $workflowId) { + return in_array($var['from_stage_id'], [-1, $pk]) && $workflowId == $var['workflow_id']; + } + ) + ); + } } diff --git a/administrator/components/com_modules/src/Model/ModuleModel.php b/administrator/components/com_modules/src/Model/ModuleModel.php index ab36763da9ab9..585207b69941f 100644 --- a/administrator/components/com_modules/src/Model/ModuleModel.php +++ b/administrator/components/com_modules/src/Model/ModuleModel.php @@ -19,11 +19,14 @@ use Joomla\CMS\Helper\ModuleHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Model\AdminModel; +use Joomla\CMS\MVC\Model\WorkflowBehaviorTrait; +use Joomla\CMS\MVC\Model\WorkflowModelInterface; use Joomla\CMS\Object\CMSObject; use Joomla\CMS\Plugin\PluginHelper; use Joomla\CMS\Router\Route; use Joomla\CMS\Table\Table; use Joomla\Component\Modules\Administrator\Helper\ModulesHelper; +use Joomla\CMS\Workflow\Workflow; use Joomla\Database\ParameterType; use Joomla\Registry\Registry; use Joomla\String\StringHelper; @@ -34,8 +37,10 @@ * * @since 1.6 */ -class ModuleModel extends AdminModel +class ModuleModel extends AdminModel implements WorkflowModelInterface { + use WorkflowBehaviorTrait; + /** * The type alias for this content type. * @@ -102,6 +107,8 @@ public function __construct($config = array()) ); parent::__construct($config); + + $this->setUpWorkflow('com_modules.module'); } /** @@ -360,6 +367,8 @@ public function delete(&$pks) // Clear module cache parent::cleanCache($table->module); + + $this->workflow->deleteAssociation($pks); } else { throw new \Exception($table->getError()); } @@ -428,6 +437,16 @@ public function duplicate(&$pks) foreach ($rows as $menuid) { $tuples[] = (int) $table->id . ',' . (int) $menuid; } + + $query = $db->getQuery(true) + ->select($db->quoteName('stage_id')) + ->from($db->quoteName('#__workflow_associations')) + ->where($db->quoteName('extension') . ' = ' . $db->quote('com_modules.module')) + ->where($db->quoteName('item_id') . ' = :moduleid') + ->bind(':moduleid', $pk, ParameterType::INTEGER); + + $db->setQuery($query); + $stageIdTuples[] = (int) $table->id . ',' . (int) $db->loadResult() . ',' . $db->quote('com_modules.module'); } else { throw new \Exception($table->getError()); } @@ -451,6 +470,23 @@ public function duplicate(&$pks) } } + if (!empty($stageIdTuples)) { + $query = $db->getQuery(true) + ->insert($db->quoteName('#__workflow_associations')) + ->columns($db->quoteName(array('item_id', 'stage_id', 'extension'))) + ->values($stageIdTuples); + + $db->setQuery($query); + + try { + $db->execute(); + } catch (\RuntimeException $e) { + Factory::getApplication()->enqueueMessage($e->getMessage(), 'error'); + + return false; + } + } + // Clear modules cache $this->cleanCache(); @@ -762,6 +798,15 @@ public function getTable($type = 'Module', $prefix = 'JTable', $config = array() */ protected function prepareTable($table) { + // Set the publish date to now + if ($table->published == Workflow::CONDITION_PUBLISHED && (int) $table->publish_up == 0) { + $table->publish_up = Factory::getDate()->toSql(); + } + + if ($table->published == Workflow::CONDITION_PUBLISHED && intval($table->publish_down) == 0) { + $table->publish_down = null; + } + $table->title = htmlspecialchars_decode($table->title, ENT_QUOTES); $table->position = trim($table->position); } @@ -852,6 +897,23 @@ protected function preprocessForm(Form $form, $data, $group = 'content') } } + if (ComponentHelper::getParams('com_modules')->get('workflow_enabled')) { + Factory::getLanguage()->load('com_workflow', JPATH_ADMINISTRATOR); + + /** + * The workflowPreprocessForm function enables the workflow plugins and adds the + * transition field to the form. We do not need to add the transition field to the + * form in the case of items so we separately call the importWorkflowPlugins function. + */ + if (!empty(Factory::getApplication()->input->get('id'))) { + $this->workflowPreprocessForm($form, $data); + } else { + // Import the workflow plugin group to allow form manipulation. + $this->importWorkflowPlugins(); + $this->prepareWorkflowField($form, $data); + } + } + // Trigger the default form events. parent::preprocessForm($form, $data, $group); } @@ -948,6 +1010,8 @@ public function save($data) return false; } + $this->workflowBeforeSave(); + // Process the menu link mappings. $assignment = $data['assignment'] ?? 0; @@ -1047,6 +1111,9 @@ public function save($data) $this->setState('module.extension_id', $extensionId); $this->setState('module.id', $table->id); + $this->setState('module.new', $isNew); + + $this->workflowAfterSave($data); // Clear modules cache $this->cleanCache(); @@ -1090,4 +1157,104 @@ protected function cleanCache($group = null, $clientId = 0) { parent::cleanCache('com_modules'); } + + /** + * Method to change the published state of one or more records. + * + * @param array &$pks A list of the primary keys to change. + * @param integer $value The value of the published state. + * + * @return boolean True on success. + * + * @since __DEPLOY_VERSION__ + */ + public function publish(&$pks, $value = 1) + { + $this->workflowBeforeStageChange(); + + return parent::publish($pks, $value); + } + + /** + * Overrides the function in WorkflowBehaviorTrait to get the default + * stage ID while creating a new module. + * + * @param Form $form A Form object. + * @param mixed $data The data expected for the form. + * + * @return boolean|integer An integer, holding the stage ID or false + * + * @since __DEPLOY_VERSION__ + */ + protected function getStageForNewItem(Form $form, $data) + { + $db = $this->getDbo(); + + $query = $db->getQuery(true) + ->select($db->quoteName('id')) + ->from($db->quoteName('#__workflow_stages')) + ->where($db->quoteName('default') . '= 1'); + + if (isset($data['workflow_id'])) { + // If workflow_id is set by the query then we find the stage corresponding to that workflow_id + $query->where($db->quoteName('workflow_id') . ' = :workflowid') + ->bind(':workflowid', $data['workflow_id'], ParameterType::INTEGER); + } else { + // Query to find the default workflow id of the extension type com_modules.module + $defaultWorkflowQuery = $db->getQuery(true) + ->select($db->quoteName('id')) + ->from($db->quoteName('#__workflows')) + ->where($db->quoteName('default') . ' = 1') + ->where($db->quoteName('extension') . ' = ' . $db->quote('com_modules.module')); + + $query->where($db->quoteName('workflow_id') . ' IN (' . $defaultWorkflowQuery . ')'); + } + + $db->setQuery($query); + $defaultStage = $db->loadResult(); + + if (empty($defaultStage)) { + return false; + } + + return $defaultStage; + } + + /** + * Adds default stage to workflow field in the form. + * + * @param Form $form The form to change + * @param array|object $data The form data + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public static function prepareWorkflowField(Form $form, $data) + { + $db = Factory::getDbo(); + + $data = (array) $data; + + $form->setFieldAttribute('workflow_id', 'default', 'inherit'); + + $query = $db->getQuery(true); + + $query->select([$db->quoteName('title'), $db->quoteName('id')]) + ->from($db->quoteName('#__workflows')) + ->where( + [ + $db->quoteName('default') . ' = 1', + $db->quoteName('published') . ' = 1', + $db->quoteName('extension') . ' = ' . $db->quote('com_modules.module'), + ] + ); + + $defaultWorkflow = $db->setQuery($query)->loadObject(); + $field = $form->getField('workflow_id'); + + $field->addOption(Text::sprintf('COM_WORKFLOW_USE_DEFAULT_WORKFLOW', Text::_($defaultWorkflow->title)), ['value' => $defaultWorkflow->id]); + + $field->addOption('- ' . Text::_('COM_MODULES_WORKFLOWS') . ' -', ['disabled' => 'true']); + } } diff --git a/administrator/components/com_modules/src/Model/ModulesModel.php b/administrator/components/com_modules/src/Model/ModulesModel.php index 48579f3f02359..a09248347d1bd 100644 --- a/administrator/components/com_modules/src/Model/ModulesModel.php +++ b/administrator/components/com_modules/src/Model/ModulesModel.php @@ -214,6 +214,34 @@ protected function _getList($query, $limitstart = 0, $limit = 0) return $result; } + /** + * Get the filter form + * + * @param array $data data + * @param boolean $loadData load current data + * + * @return Form|null The \JForm object or null if the form can't be found + * + * @since __DEPLOY_VERSION__ + */ + public function getFilterForm($data = array(), $loadData = true) + { + $form = parent::getFilterForm($data, $loadData); + + $params = ComponentHelper::getParams('com_modules'); + + if (!$params->get('workflow_enabled')) { + $form->removeField('stage', 'filter'); + } else { + $ordering = $form->getField('fullordering', 'list'); + + $ordering->addOption('JSTAGE_ASC', ['value' => 'ws.title ASC']); + $ordering->addOption('JSTAGE_DESC', ['value' => 'ws.title DESC']); + } + + return $form; + } + /** * Translate a list of objects * @@ -255,6 +283,7 @@ protected function getListQuery() // Create a new query object. $db = $this->getDatabase(); $query = $db->getQuery(true); + $params = ComponentHelper::getParams('com_modules'); // Select the required fields. $query->select( @@ -289,6 +318,24 @@ protected function getListQuery() $query->select($db->quoteName('e.name', 'name')) ->join('LEFT', $db->quoteName('#__extensions', 'e') . ' ON ' . $db->quoteName('e.element') . ' = ' . $db->quoteName('a.module')); + // Join over the workflows association + $query->select($db->quoteName('wa.stage_id', 'stage_id')) + ->join('INNER', $db->quoteName('#__workflow_associations', 'wa'), $db->quoteName('wa.item_id') . ' = ' . $db->quoteName('a.id')) + ->where($db->quoteName('wa.extension') . ' = ' . $db->quote('com_modules.module')); + + // Join over the workflows stage + $query->select( + [ + $db->quoteName('ws.title', 'stage_title'), + $db->quoteName('ws.workflow_id', 'workflow_id') + ] + ) + ->join('INNER', $db->quoteName('#__workflow_stages', 'ws'), $db->quoteName('ws.id') . ' = ' . $db->quoteName('wa.stage_id')); + + // Join over the workflows + $query->select($db->quoteName('w.title', 'workflow_title')) + ->join('INNER', $db->quoteName('#__workflows', 'w'), $db->quoteName('w.id') . ' = ' . $db->quoteName('ws.workflow_id')); + // Group (careful with PostgreSQL) $query->group( 'a.id, a.title, a.note, a.position, a.module, a.language, a.checked_out, ' @@ -319,6 +366,15 @@ protected function getListQuery() ->bind(':access', $access, ParameterType::INTEGER); } + // Filter by stage + $workflowStage = (string) $this->getState('filter.stage'); + + if ($params->get('workflow_enabled') && is_numeric($workflowStage)) { + $workflowStage = (int) $workflowStage; + $query->where($db->quoteName('wa.stage_id') . ' = :stage') + ->bind(':stage', $workflowStage, ParameterType::INTEGER); + } + // Filter by published state. $state = $this->getState('filter.state'); @@ -326,7 +382,7 @@ protected function getListQuery() $state = (int) $state; $query->where($db->quoteName('a.published') . ' = :state') ->bind(':state', $state, ParameterType::INTEGER); - } elseif ($state === '') { + } elseif (!is_numeric($workflowStage)) { $query->whereIn($db->quoteName('a.published'), [0, 1]); } @@ -418,6 +474,103 @@ protected function getListQuery() return $query; } + /** + * Method to get all transitions at once for all modules + * + * @return array|boolean + * + * @since __DEPLOY_VERSION__ + */ + public function getTransitions() + { + // Get a storage key. + $store = $this->getStoreId('getTransitions'); + + // Try to load the data from internal storage. + if (isset($this->cache[$store])) { + return $this->cache[$store]; + } + + $db = $this->getDbo(); + $user = Factory::getUser(); + + $items = $this->getItems(); + + if ($items === false) { + return false; + } + + $stageIds = ArrayHelper::getColumn($items, 'stage_id'); + $stageIds = ArrayHelper::toInteger($stageIds); + $stageIds = array_values(array_unique(array_filter($stageIds))); + + $workflowIds = ArrayHelper::getColumn($items, 'workflow_id'); + $workflowIds = ArrayHelper::toInteger($workflowIds); + $workflowIds = array_values(array_unique(array_filter($workflowIds))); + + $this->cache[$store] = array(); + + try { + if (count($stageIds) || count($workflowIds)) { + Factory::getLanguage()->load('com_workflow', JPATH_ADMINISTRATOR); + + $query = $db->getQuery(true); + + $query ->select( + [ + $db->quoteName('t.id', 'value'), + $db->quoteName('t.title', 'text'), + $db->quoteName('t.from_stage_id'), + $db->quoteName('t.to_stage_id'), + $db->quoteName('s.id', 'stage_id'), + $db->quoteName('s.title', 'stage_title'), + $db->quoteName('t.workflow_id'), + ] + ) + ->from($db->quoteName('#__workflow_transitions', 't')) + ->innerJoin( + $db->quoteName('#__workflow_stages', 's'), + $db->quoteName('t.to_stage_id') . ' = ' . $db->quoteName('s.id') + ) + ->where( + [ + $db->quoteName('t.published') . ' = 1', + $db->quoteName('s.published') . ' = 1', + ] + ) + ->order($db->quoteName('t.ordering')); + + $where = []; + + if (count($stageIds)) { + $where[] = $db->quoteName('t.from_stage_id') . ' IN (' . implode(',', $query->bindArray($stageIds)) . ')'; + } + + if (count($workflowIds)) { + $where[] = '(' . $db->quoteName('t.from_stage_id') . ' = -1 AND ' . $db->quoteName('t.workflow_id') . ' IN (' . implode(',', $query->bindArray($workflowIds)) . '))'; + } + + $query->where('((' . implode(') OR (', $where) . '))'); + + $transitions = $db->setQuery($query)->loadAssocList(); + + foreach ($transitions as $key => $transition) { + if (!$user->authorise('core.execute.transition', 'com_modules.transition.' . (int) $transition['value'])) { + unset($transitions[$key]); + } + } + + $this->cache[$store] = $transitions; + } + } catch (\RuntimeException $e) { + $this->setError($e->getMessage()); + + return false; + } + + return $this->cache[$store]; + } + /** * Manipulate the query to be used to evaluate if this is an Empty State to provide specific conditions for this extension. * diff --git a/administrator/components/com_modules/src/View/Modules/HtmlView.php b/administrator/components/com_modules/src/View/Modules/HtmlView.php index 8f505a6f58ede..a9710096b4c0d 100644 --- a/administrator/components/com_modules/src/View/Modules/HtmlView.php +++ b/administrator/components/com_modules/src/View/Modules/HtmlView.php @@ -11,12 +11,14 @@ namespace Joomla\Component\Modules\Administrator\View\Modules; use Joomla\CMS\Factory; +use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Helper\ContentHelper; use Joomla\CMS\Helper\ModuleHelper; use Joomla\CMS\Language\Multilanguage; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\View\GenericDataException; use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView; +use Joomla\CMS\Plugin\PluginHelper; use Joomla\CMS\Toolbar\Toolbar; use Joomla\CMS\Toolbar\ToolbarHelper; @@ -96,6 +98,12 @@ public function display($tpl = null) $this->setLayout('emptystate'); } + if (ComponentHelper::getParams('com_modules')->get('workflow_enabled')) { + PluginHelper::importPlugin('workflow'); + + $this->transitions = $this->get('Transitions'); + } + /** * The code below make sure the remembered position will be available from filter dropdown even if there are no * modules available for this position. This will make the UI less confusing for users in case there is only one diff --git a/administrator/components/com_modules/tmpl/module/edit.php b/administrator/components/com_modules/tmpl/module/edit.php index 0dbdb4680d460..147f374025727 100644 --- a/administrator/components/com_modules/tmpl/module/edit.php +++ b/administrator/components/com_modules/tmpl/module/edit.php @@ -50,6 +50,9 @@ $layout = $isModal ? 'modal' : 'edit'; $tmpl = $isModal || $input->get('tmpl', '', 'cmd') === 'component' ? '&tmpl=component' : ''; +// If the module is already created then display the transition field else display the workflow selection field. +$workflowField = empty($input->get('id')) ? 'workflow_id' : 'transition'; + ?>
@@ -127,6 +130,7 @@ fields = array( + $workflowField, 'showtitle', 'position', 'published', @@ -171,7 +175,7 @@ fieldsets = array(); - $this->ignore_fieldsets = array('basic', 'description'); + $this->ignore_fieldsets = array('basic', 'description', 'workflow'); echo LayoutHelper::render('joomla.edit.params', $this); ?> diff --git a/administrator/components/com_modules/tmpl/modules/default.php b/administrator/components/com_modules/tmpl/modules/default.php index d4ba1df7fdf59..e4bd365a7efc0 100644 --- a/administrator/components/com_modules/tmpl/modules/default.php +++ b/administrator/components/com_modules/tmpl/modules/default.php @@ -10,6 +10,9 @@ defined('_JEXEC') or die; +use Joomla\CMS\Button\PublishedButton; +use Joomla\CMS\Button\TransitionButton; +use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Factory; use Joomla\CMS\Helper\ModuleHelper; use Joomla\CMS\HTML\HTMLHelper; @@ -18,6 +21,8 @@ use Joomla\CMS\Layout\LayoutHelper; use Joomla\CMS\Router\Route; use Joomla\CMS\Session\Session; +use Joomla\Component\Content\Administrator\Helper\ContentHelper; +use Joomla\Utilities\ArrayHelper; /** @var \Joomla\CMS\WebAsset\WebAssetManager $wa */ $wa = $this->document->getWebAssetManager(); @@ -34,6 +39,35 @@ $saveOrderingUrl = 'index.php?option=com_modules&task=modules.saveOrderAjax&tmpl=component&' . Session::getFormToken() . '=1'; HTMLHelper::_('draggablelist.draggable'); } + +$workflow_enabled = ComponentHelper::getParams('com_modules')->get('workflow_enabled'); +$workflow_state = false; + +if ($workflow_enabled) : +// @todo move the script to a file + $js = <<document->getWebAssetManager(); + + $wa->getRegistry()->addExtensionRegistryFile('com_workflow'); + $wa->useScript('com_workflow.admin-items-workflow-buttons') + ->addInlineScript($js, [], ['type' => 'module']); + + $workflow_state = Factory::getApplication()->bootComponent('com_modules')->isFunctionalityUsed('core.state', 'com_modules.module'); +endif; ?>
@@ -53,6 +87,11 @@ + + + + + @@ -96,6 +135,12 @@ $canEdit = $user->authorise('core.edit', 'com_modules.module.' . $item->id); $canCheckin = $user->authorise('core.manage', 'com_checkin') || $item->checked_out == $user->get('id') || is_null($item->checked_out); $canChange = $user->authorise('core.edit.state', 'com_modules.module.' . $item->id) && $canCheckin; + if ($workflow_enabled) { + $transitions = ContentHelper::filterTransitions($this->transitions, (int) $item->stage_id, (int) $item->workflow_id); + + $transitionIds = ArrayHelper::getColumn($transitions, 'value'); + $transitionIds = ArrayHelper::toInteger($transitionIds); + } ?> @@ -117,6 +162,33 @@ + + + $transitions, + 'title' => Text::_($item->stage_title), + 'tip_content' => Text::sprintf('JWORKFLOW', Text::_($item->workflow_title)), + 'id' => 'workflow-' . $item->id, + 'task' => 'modules.runTransition' + ]; + + echo (new TransitionButton($options)) + ->render(0, $i); + ?> + + + 'modules.', + 'disabled' => $workflow_state || !$canChange, + 'id' => 'state-' . $item->id + ]; + + echo (new PublishedButton())->render((int) $item->published, $i, $options, $item->publish_up, $item->publish_down); + ?> + + enabled > 0) : ?> @@ -128,6 +200,7 @@ +
checked_out) : ?> @@ -213,6 +286,11 @@ $this->loadTemplate('batch_body') ); ?> + + + + + diff --git a/administrator/components/com_modules/tmpl/modules/default_batch_body.php b/administrator/components/com_modules/tmpl/modules/default_batch_body.php index 4683baede1166..a275865115f4a 100644 --- a/administrator/components/com_modules/tmpl/modules/default_batch_body.php +++ b/administrator/components/com_modules/tmpl/modules/default_batch_body.php @@ -10,6 +10,8 @@ defined('_JEXEC') or die; +use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Factory; use Joomla\CMS\Helper\ModuleHelper; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; @@ -18,6 +20,10 @@ $clientId = $this->state->get('client_id'); +$params = ComponentHelper::getParams('com_modules'); + +$user = Factory::getUser(); + // Show only Module Positions of published Templates $published = 1; $positions = HTMLHelper::_('modules.positions', $clientId, $published); @@ -60,6 +66,13 @@
+ authorise('core.admin', 'com_modules') && $params->get('workflow_enabled')) : ?> +
+
+ 'com_modules']); ?> +
+
+
= 0) : ?> diff --git a/administrator/language/en-GB/com_modules.ini b/administrator/language/en-GB/com_modules.ini index 0a901fa883d66..ef56c56b0cb27 100644 --- a/administrator/language/en-GB/com_modules.ini +++ b/administrator/language/en-GB/com_modules.ini @@ -21,6 +21,7 @@ COM_MODULES_BATCH_TIP="If choosing to copy a module, any other actions selected COM_MODULES_CHANGE_POSITION_BUTTON="Select" COM_MODULES_CHANGE_POSITION_TITLE="Change" COM_MODULES_COLLAPSE="Collapse" +COM_MODULES_CONFIG_INTEGRATION_SETTINGS_DESC="These settings determine how the Modules Component will integrate with other extensions." COM_MODULES_CONFIGURATION="Module: Options" COM_MODULES_CUSTOM_OUTPUT="Custom Output" COM_MODULES_CUSTOM_POSITION="Active Positions" @@ -190,6 +191,10 @@ COM_MODULES_SUBITEMS="Sub-items" COM_MODULES_TABLE_CAPTION="Table of Modules" COM_MODULES_TYPE_CHOOSE="Select a Module Type" COM_MODULES_TYPE_OR_SELECT_POSITION="Type or Select a Position" +COM_MODULES_WORKFLOW="Workflow" +COM_MODULES_WORKFLOWS="Workflows" +COM_MODULES_WORKFLOW_NOT_FOUND="No default workflow available, please define one or contact an administrator." +COM_MODULES_WORKFLOW_TRANSITION_NOT_ALLOWED="You're not allowed to execute this transition." COM_MODULES_XML_DESCRIPTION="Component for module management in the Administrator Backend." JLIB_RULES_SETTING_NOTES_COM_MODULES="Changes apply to this component only.
Inherited - a Global Configuration setting or higher level setting is applied.
Denied always wins - whatever is set at the Global or higher level and applies to all child elements.
Allowed will enable the action for this component unless overruled by a Global Configuration setting." ; Alternate language strings for the rules form field diff --git a/administrator/language/en-GB/com_workflow.ini b/administrator/language/en-GB/com_workflow.ini index 4dc999e86d2f7..2470c3b42c1dd 100644 --- a/administrator/language/en-GB/com_workflow.ini +++ b/administrator/language/en-GB/com_workflow.ini @@ -8,6 +8,7 @@ COM_WORKFLOW_AUTHOR="Author" COM_WORKFLOW_BASIC_STAGE="Basic Stage" COM_WORKFLOW_BASIC_TAB="Basic" COM_WORKFLOW_BASIC_WORKFLOW="Basic Workflow" +COM_WORKFLOW_BASIC_WORKFLOW_MODULES="Basic Workflow: Modules" COM_WORKFLOW_CHOOSE_CONTEXT_LABEL="Context" COM_WORKFLOW_CONFIGURATION="Workflow: Options" COM_WORKFLOW_COUNT_STAGES="Stages" diff --git a/administrator/language/en-GB/mod_menu.ini b/administrator/language/en-GB/mod_menu.ini index 1734cfa17c9db..0e4a787fb3288 100644 --- a/administrator/language/en-GB/mod_menu.ini +++ b/administrator/language/en-GB/mod_menu.ini @@ -37,6 +37,7 @@ MOD_MENU_EXTENSIONS_LANGUAGE_MANAGER="Languages" MOD_MENU_EXTENSIONS_MODULE_MANAGER="Modules" MOD_MENU_EXTENSIONS_MODULE_MANAGER_ADMINISTRATOR="Administrator Modules" MOD_MENU_EXTENSIONS_MODULE_MANAGER_SITE="Site Modules" +MOD_MENU_EXTENSIONS_MODULE_WORKFLOWS="Modules: Workflows" MOD_MENU_EXTENSIONS_PLUGIN_MANAGER="Plugins" MOD_MENU_EXTENSIONS_TEMPLATE_MANAGER="Templates" MOD_MENU_FIELD_CHECK_DESC="Check for the presence of important menu items." diff --git a/installation/sql/mysql/base.sql b/installation/sql/mysql/base.sql index ca59eeff59fad..cfa5681ef3ea3 100644 --- a/installation/sql/mysql/base.sql +++ b/installation/sql/mysql/base.sql @@ -25,7 +25,7 @@ CREATE TABLE IF NOT EXISTS `#__assets` ( -- INSERT INTO `#__assets` (`id`, `parent_id`, `lft`, `rgt`, `level`, `name`, `title`, `rules`) VALUES -(1, 0, 0, 165, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.login.api":{"8":1},"core.login.offline":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'), +(1, 0, 0, 175, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.login.api":{"8":1},"core.login.offline":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'), (2, 1, 1, 2, 1, 'com_admin', 'com_admin', '{}'), (3, 1, 3, 6, 1, 'com_banners', 'com_banners', '{"core.admin":{"7":1},"core.manage":{"6":1}}'), (4, 1, 7, 8, 1, 'com_cache', 'com_cache', '{"core.admin":{"7":1},"core.manage":{"7":1}}'), @@ -41,24 +41,24 @@ INSERT INTO `#__assets` (`id`, `parent_id`, `lft`, `rgt`, `level`, `name`, `titl (15, 1, 49, 50, 1, 'com_media', 'com_media', '{"core.admin":{"7":1},"core.manage":{"6":1},"core.create":{"3":1},"core.delete":{"5":1}}'), (16, 1, 51, 54, 1, 'com_menus', 'com_menus', '{"core.admin":{"7":1}}'), (17, 1, 55, 56, 1, 'com_messages', 'com_messages', '{"core.admin":{"7":1},"core.manage":{"7":1}}'), -(18, 1, 57, 130, 1, 'com_modules', 'com_modules', '{"core.admin":{"7":1}}'), -(19, 1, 131, 134, 1, 'com_newsfeeds', 'com_newsfeeds', '{"core.admin":{"7":1},"core.manage":{"6":1}}'), -(20, 1, 135, 136, 1, 'com_plugins', 'com_plugins', '{"core.admin":{"7":1}}'), -(21, 1, 137, 138, 1, 'com_redirect', 'com_redirect', '{"core.admin":{"7":1}}'), -(23, 1, 139, 140, 1, 'com_templates', 'com_templates', '{"core.admin":{"7":1}}'), -(24, 1, 145, 148, 1, 'com_users', 'com_users', '{"core.admin":{"7":1}}'), -(26, 1, 149, 150, 1, 'com_wrapper', 'com_wrapper', '{}'), +(18, 1, 57, 140, 1, 'com_modules', 'com_modules', '{"core.admin":{"7":1}}'), +(19, 1, 141, 144, 1, 'com_newsfeeds', 'com_newsfeeds', '{"core.admin":{"7":1},"core.manage":{"6":1}}'), +(20, 1, 145, 146, 1, 'com_plugins', 'com_plugins', '{"core.admin":{"7":1}}'), +(21, 1, 147, 148, 1, 'com_redirect', 'com_redirect', '{"core.admin":{"7":1}}'), +(23, 1, 149, 150, 1, 'com_templates', 'com_templates', '{"core.admin":{"7":1}}'), +(24, 1, 155, 158, 1, 'com_users', 'com_users', '{"core.admin":{"7":1}}'), +(26, 1, 159, 160, 1, 'com_wrapper', 'com_wrapper', '{}'), (27, 8, 18, 19, 2, 'com_content.category.2', 'Uncategorised', '{}'), (28, 3, 4, 5, 2, 'com_banners.category.3', 'Uncategorised', '{}'), (29, 7, 14, 15, 2, 'com_contact.category.4', 'Uncategorised', '{}'), -(30, 19, 132, 133, 2, 'com_newsfeeds.category.5', 'Uncategorised', '{}'), -(32, 24, 146, 147, 2, 'com_users.category.7', 'Uncategorised', '{}'), -(33, 1, 151, 152, 1, 'com_finder', 'com_finder', '{"core.admin":{"7":1},"core.manage":{"6":1}}'), -(34, 1, 153, 154, 1, 'com_joomlaupdate', 'com_joomlaupdate', '{}'), -(35, 1, 155, 156, 1, 'com_tags', 'com_tags', '{}'), -(36, 1, 157, 158, 1, 'com_contenthistory', 'com_contenthistory', '{}'), -(37, 1, 159, 160, 1, 'com_ajax', 'com_ajax', '{}'), -(38, 1, 161, 162, 1, 'com_postinstall', 'com_postinstall', '{}'), +(30, 19, 142, 143, 2, 'com_newsfeeds.category.5', 'Uncategorised', '{}'), +(32, 24, 156, 157, 2, 'com_users.category.7', 'Uncategorised', '{}'), +(33, 1, 161, 162, 1, 'com_finder', 'com_finder', '{"core.admin":{"7":1},"core.manage":{"6":1}}'), +(34, 1, 163, 164, 1, 'com_joomlaupdate', 'com_joomlaupdate', '{}'), +(35, 1, 165, 166, 1, 'com_tags', 'com_tags', '{}'), +(36, 1, 167, 168, 1, 'com_contenthistory', 'com_contenthistory', '{}'), +(37, 1, 169, 170, 1, 'com_ajax', 'com_ajax', '{}'), +(38, 1, 171, 172, 1, 'com_postinstall', 'com_postinstall', '{}'), (39, 18, 58, 59, 2, 'com_modules.module.1', 'Main Menu', '{}'), (40, 18, 60, 61, 2, 'com_modules.module.2', 'Login', '{}'), (41, 18, 62, 63, 2, 'com_modules.module.3', 'Popular Articles', '{}'), @@ -84,8 +84,8 @@ INSERT INTO `#__assets` (`id`, `parent_id`, `lft`, `rgt`, `level`, `name`, `titl (62, 56, 31, 32, 3, 'com_content.transition.5', 'Feature', '{}'), (63, 56, 33, 34, 3, 'com_content.transition.6', 'Unfeature', '{}'), (64, 56, 35, 36, 3, 'com_content.transition.7', 'Publish & Feature', '{}'), -(65, 1, 141, 142, 1, 'com_privacy', 'com_privacy', '{}'), -(66, 1, 143, 144, 1, 'com_actionlogs', 'com_actionlogs', '{}'), +(65, 1, 151, 152, 1, 'com_privacy', 'com_privacy', '{}'), +(66, 1, 153, 154, 1, 'com_actionlogs', 'com_actionlogs', '{}'), (67, 18, 74, 75, 2, 'com_modules.module.88', 'Latest Actions', '{}'), (68, 18, 76, 77, 2, 'com_modules.module.89', 'Privacy Dashboard', '{}'), (70, 18, 88, 89, 2, 'com_modules.module.103', 'Site', '{}'), @@ -107,7 +107,12 @@ INSERT INTO `#__assets` (`id`, `parent_id`, `lft`, `rgt`, `level`, `name`, `titl (87, 18, 124, 125, 2, 'com_modules.module.97', 'Recently Added Articles', '{}'), (88, 18, 126, 127, 2, 'com_modules.module.98', 'Logged-in Users', '{}'), (89, 18, 128, 129, 2, 'com_modules.module.90', 'Login Support', '{}'), -(90, 1, 163, 164, 1, 'com_scheduler', 'com_scheduler', '{}'); +(90, 1, 173, 174, 1, 'com_scheduler', 'com_scheduler', '{}'); +(91, 18, 130, 131, 2, 'com_modules.workflow.1', 'COM_WORKFLOW_BASIC_WORKFLOW_MODULES', '{}'), +(92, 89, 132, 133, 3, 'com_modules.state.1', 'COM_WORKFLOW_BASIC_STAGE', '{}'), +(93, 89, 134, 135, 3, 'com_modules.transition.1', 'Publish', '{}'), +(94, 89, 136, 137, 3, 'com_modules.transition.2', 'Unpublish', '{}'), +(95, 89, 138, 139, 3, 'com_modules.transition.3', 'Trash', '{}'); -- -------------------------------------------------------- @@ -1112,7 +1117,8 @@ CREATE TABLE IF NOT EXISTS `#__workflows` ( -- INSERT INTO `#__workflows` (`id`, `asset_id`, `published`, `title`, `description`, `extension`, `default`, `ordering`, `created`, `created_by`, `modified`, `modified_by`) VALUES -(1, 56, 1, 'COM_WORKFLOW_BASIC_WORKFLOW', '', 'com_content.article', 1, 1, CURRENT_TIMESTAMP(), 42, CURRENT_TIMESTAMP(), 42); +(1, 56, 1, 'COM_WORKFLOW_BASIC_WORKFLOW', '', 'com_content.article', 1, 1, CURRENT_TIMESTAMP(), 42, CURRENT_TIMESTAMP(), 42), +(2, 91, 1, 'COM_WORKFLOW_BASIC_WORKFLOW_MODULES', '', 'com_modules.module', 1, 1, CURRENT_TIMESTAMP(), 42, CURRENT_TIMESTAMP(), 42); -- -------------------------------------------------------- @@ -1161,7 +1167,8 @@ CREATE TABLE IF NOT EXISTS `#__workflow_stages` ( -- INSERT INTO `#__workflow_stages` (`id`, `asset_id`, `ordering`, `workflow_id`, `published`, `title`, `description`, `default`) VALUES -(1, 57, 1, 1, 1, 'COM_WORKFLOW_BASIC_STAGE', '', 1); +(1, 0, 1, 1, 1, 'COM_WORKFLOW_BASIC_STAGE', '', 1), +(2, 92, 1, 2, 1, 'COM_WORKFLOW_BASIC_STAGE', '', 1); -- -------------------------------------------------------- @@ -1196,10 +1203,16 @@ CREATE TABLE IF NOT EXISTS `#__workflow_transitions` ( -- INSERT INTO `#__workflow_transitions` (`id`, `asset_id`, `published`, `ordering`, `workflow_id`, `title`, `description`, `from_stage_id`, `to_stage_id`, `options`) VALUES -(1, 58, 1, 1, 1, 'UNPUBLISH', '', -1, 1, '{"publishing":"0"}'), -(2, 59, 1, 2, 1, 'PUBLISH', '', -1, 1, '{"publishing":"1"}'), -(3, 60, 1, 3, 1, 'TRASH', '', -1, 1, '{"publishing":"-2"}'), -(4, 61, 1, 4, 1, 'ARCHIVE', '', -1, 1, '{"publishing":"2"}'), -(5, 62, 1, 5, 1, 'FEATURE', '', -1, 1, '{"featuring":"1"}'), -(6, 63, 1, 6, 1, 'UNFEATURE', '', -1, 1, '{"featuring":"0"}'), -(7, 64, 1, 7, 1, 'PUBLISH_AND_FEATURE', '', -1, 1, '{"publishing":"1","featuring":"1"}'); +(1, 58, 1, 1, 1, 'Unpublish', '', -1, 1, '{"publishing":"0"}'), +(2, 59, 1, 2, 1, 'Publish', '', -1, 1, '{"publishing":"1"}'), +(3, 60, 1, 3, 1, 'Trash', '', -1, 1, '{"publishing":"-2"}'), +(4, 61, 1, 4, 1, 'Archive', '', -1, 1, '{"publishing":"2"}'), +(5, 62, 1, 5, 1, 'Feature', '', -1, 1, '{"featuring":"1"}'), +(6, 63, 1, 6, 1, 'Unfeature', '', -1, 1, '{"featuring":"0"}'), +(7, 64, 1, 7, 1, 'Publish & Feature', '', -1, 1, '{"publishing":"1","featuring":"1"}'), +(8, 94, 1, 1, 2, 'Unpublish', '', -1, 2, '{"publishing":"0"}'), +(9, 93, 1, 2, 2, 'Publish', '', -1, 2, '{"publishing":"1"}'), +(10, 95, 1, 3, 2, 'Trash', '', -1, 2, '{"publishing":"-2"}'); + +INSERT INTO `#__workflow_associations` (`item_id`, `stage_id`, `extension`) +SELECT `id`, 2, 'com_modules.module' FROM `#__modules`; diff --git a/installation/sql/postgresql/base.sql b/installation/sql/postgresql/base.sql index 4e299b0c7c370..51da742de4ea5 100644 --- a/installation/sql/postgresql/base.sql +++ b/installation/sql/postgresql/base.sql @@ -31,7 +31,7 @@ COMMENT ON COLUMN "#__assets"."rules" IS 'JSON encoded access control.'; -- INSERT INTO "#__assets" ("id", "parent_id", "lft", "rgt", "level", "name", "title", "rules") VALUES -(1, 0, 0, 165, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.login.api":{"8":1},"core.login.offline":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'), +(1, 0, 0, 175, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.login.api":{"8":1},"core.login.offline":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'), (2, 1, 1, 2, 1, 'com_admin', 'com_admin', '{}'), (3, 1, 3, 6, 1, 'com_banners', 'com_banners', '{"core.admin":{"7":1},"core.manage":{"6":1}}'), (4, 1, 7, 8, 1, 'com_cache', 'com_cache', '{"core.admin":{"7":1},"core.manage":{"7":1}}'), @@ -47,24 +47,24 @@ INSERT INTO "#__assets" ("id", "parent_id", "lft", "rgt", "level", "name", "titl (15, 1, 49, 50, 1, 'com_media', 'com_media', '{"core.admin":{"7":1},"core.manage":{"6":1},"core.create":{"3":1},"core.delete":{"5":1}}'), (16, 1, 51, 54, 1, 'com_menus', 'com_menus', '{"core.admin":{"7":1}}'), (17, 1, 55, 56, 1, 'com_messages', 'com_messages', '{"core.admin":{"7":1},"core.manage":{"7":1}}'), -(18, 1, 57, 130, 1, 'com_modules', 'com_modules', '{"core.admin":{"7":1}}'), -(19, 1, 131, 134, 1, 'com_newsfeeds', 'com_newsfeeds', '{"core.admin":{"7":1},"core.manage":{"6":1}}'), -(20, 1, 135, 136, 1, 'com_plugins', 'com_plugins', '{"core.admin":{"7":1}}'), -(21, 1, 137, 138, 1, 'com_redirect', 'com_redirect', '{"core.admin":{"7":1}}'), -(23, 1, 139, 140, 1, 'com_templates', 'com_templates', '{"core.admin":{"7":1}}'), -(24, 1, 145, 148, 1, 'com_users', 'com_users', '{"core.admin":{"7":1}}'), -(26, 1, 149, 150, 1, 'com_wrapper', 'com_wrapper', '{}'), +(18, 1, 57, 140, 1, 'com_modules', 'com_modules', '{"core.admin":{"7":1}}'), +(19, 1, 141, 144, 1, 'com_newsfeeds', 'com_newsfeeds', '{"core.admin":{"7":1},"core.manage":{"6":1}}'), +(20, 1, 145, 146, 1, 'com_plugins', 'com_plugins', '{"core.admin":{"7":1}}'), +(21, 1, 147, 148, 1, 'com_redirect', 'com_redirect', '{"core.admin":{"7":1}}'), +(23, 1, 149, 150, 1, 'com_templates', 'com_templates', '{"core.admin":{"7":1}}'), +(24, 1, 155, 158, 1, 'com_users', 'com_users', '{"core.admin":{"7":1}}'), +(26, 1, 159, 160, 1, 'com_wrapper', 'com_wrapper', '{}'), (27, 8, 18, 19, 2, 'com_content.category.2', 'Uncategorised', '{}'), (28, 3, 4, 5, 2, 'com_banners.category.3', 'Uncategorised', '{}'), (29, 7, 14, 15, 2, 'com_contact.category.4', 'Uncategorised', '{}'), -(30, 19, 132, 133, 2, 'com_newsfeeds.category.5', 'Uncategorised', '{}'), -(32, 24, 146, 147, 2, 'com_users.category.7', 'Uncategorised', '{}'), -(33, 1, 151, 152, 1, 'com_finder', 'com_finder', '{"core.admin":{"7":1},"core.manage":{"6":1}}'), -(34, 1, 153, 154, 1, 'com_joomlaupdate', 'com_joomlaupdate', '{}'), -(35, 1, 155, 156, 1, 'com_tags', 'com_tags', '{}'), -(36, 1, 157, 158, 1, 'com_contenthistory', 'com_contenthistory', '{}'), -(37, 1, 159, 160, 1, 'com_ajax', 'com_ajax', '{}'), -(38, 1, 161, 162, 1, 'com_postinstall', 'com_postinstall', '{}'), +(30, 19, 142, 143, 2, 'com_newsfeeds.category.5', 'Uncategorised', '{}'), +(32, 24, 156, 157, 2, 'com_users.category.7', 'Uncategorised', '{}'), +(33, 1, 161, 162, 1, 'com_finder', 'com_finder', '{"core.admin":{"7":1},"core.manage":{"6":1}}'), +(34, 1, 163, 164, 1, 'com_joomlaupdate', 'com_joomlaupdate', '{}'), +(35, 1, 165, 166, 1, 'com_tags', 'com_tags', '{}'), +(36, 1, 167, 168, 1, 'com_contenthistory', 'com_contenthistory', '{}'), +(37, 1, 169, 170, 1, 'com_ajax', 'com_ajax', '{}'), +(38, 1, 171, 172, 1, 'com_postinstall', 'com_postinstall', '{}'), (39, 18, 58, 59, 2, 'com_modules.module.1', 'Main Menu', '{}'), (40, 18, 60, 61, 2, 'com_modules.module.2', 'Login', '{}'), (41, 18, 62, 63, 2, 'com_modules.module.3', 'Popular Articles', '{}'), @@ -90,8 +90,8 @@ INSERT INTO "#__assets" ("id", "parent_id", "lft", "rgt", "level", "name", "titl (62, 56, 31, 32, 3, 'com_content.transition.5', 'Feature', '{}'), (63, 56, 33, 34, 3, 'com_content.transition.6', 'Unfeature', '{}'), (64, 56, 35, 36, 3, 'com_content.transition.7', 'Publish & Feature', '{}'), -(65, 1, 141, 142, 1, 'com_privacy', 'com_privacy', '{}'), -(66, 1, 143, 144, 1, 'com_actionlogs', 'com_actionlogs', '{}'), +(65, 1, 151, 152, 1, 'com_privacy', 'com_privacy', '{}'), +(66, 1, 153, 154, 1, 'com_actionlogs', 'com_actionlogs', '{}'), (67, 18, 74, 75, 2, 'com_modules.module.88', 'Latest Actions', '{}'), (68, 18, 76, 77, 2, 'com_modules.module.89', 'Privacy Dashboard', '{}'), (70, 18, 88, 89, 2, 'com_modules.module.103', 'Site', '{}'), @@ -113,9 +113,14 @@ INSERT INTO "#__assets" ("id", "parent_id", "lft", "rgt", "level", "name", "titl (87, 18, 124, 125, 2, 'com_modules.module.97', 'Recently Added Articles', '{}'), (88, 18, 126, 127, 2, 'com_modules.module.98', 'Logged-in Users', '{}'), (89, 18, 128, 129, 2, 'com_modules.module.90', 'Login Support', '{}'), -(90, 1, 163, 164, 1, 'com_scheduler', 'com_scheduler', '{}'); +(90, 1, 173, 174, 1, 'com_scheduler', 'com_scheduler', '{}'); +(91, 18, 130, 131, 2, 'com_modules.workflow.1', 'COM_WORKFLOW_BASIC_WORKFLOW_MODULES', '{}'), +(92, 89, 132, 133, 3, 'com_modules.state.1', 'COM_WORKFLOW_BASIC_STAGE', '{}'), +(93, 89, 134, 135, 3, 'com_modules.transition.1', 'Publish', '{}'), +(94, 89, 136, 137, 3, 'com_modules.transition.2', 'Unpublish', '{}'), +(95, 89, 138, 139, 3, 'com_modules.transition.3', 'Trash', '{}'); -SELECT setval('#__assets_id_seq', 91, false); +SELECT setval('#__assets_id_seq', 96, false); -- -- Table structure for table `#__extensions` @@ -1135,9 +1140,10 @@ CREATE INDEX "#__workflows_idx_modified_by" ON "#__workflows" ("modified_by"); CREATE INDEX "#__workflows_idx_checked_out" ON "#__workflows" ("checked_out"); INSERT INTO "#__workflows" ("id", "asset_id", "published", "title", "description", "extension", "default", "ordering", "created", "created_by", "modified", "modified_by") VALUES -(1, 56, 1, 'COM_WORKFLOW_BASIC_WORKFLOW', '', 'com_content.article', 1, 1, CURRENT_TIMESTAMP, 42, CURRENT_TIMESTAMP, 42); +(1, 56, 1, 'COM_WORKFLOW_BASIC_WORKFLOW', '', 'com_content.article', 1, 1, CURRENT_TIMESTAMP, 42, CURRENT_TIMESTAMP, 42), +(2, 91, 1, 'COM_WORKFLOW_BASIC_WORKFLOW_MODULES', '', 'com_modules.module', 1, 1, CURRENT_TIMESTAMP, 42, CURRENT_TIMESTAMP, 42); -SELECT setval('#__workflows_id_seq', 2, false); +SELECT setval('#__workflows_id_seq', 3, false); -- -- Table structure for table `#__workflow_associations` @@ -1185,9 +1191,10 @@ CREATE INDEX "#__workflow_stages_idx_checked_out" ON "#__workflow_stages" ("chec -- INSERT INTO "#__workflow_stages" ("id", "asset_id", "ordering", "workflow_id", "published", "title", "description", "default") VALUES -(1, 57, 1, 1, 1, 'COM_WORKFLOW_BASIC_STAGE', '', 1); +(1, 57, 1, 1, 1, 'COM_WORKFLOW_BASIC_STAGE', '', 1), +(2, 92, 1, 2, 1, 'COM_WORKFLOW_BASIC_STAGE', '', 1); -SELECT setval('#__workflow_stages_id_seq', 2, false); +SELECT setval('#__workflow_stages_id_seq', 3, false); -- -- Table structure for table `#__workflow_transitions` @@ -1216,12 +1223,18 @@ CREATE INDEX "#__workflow_transitions_idx_workflow_id" ON "#__workflow_transitio CREATE INDEX "#__workflow_transitions_idx_checked_out" ON "#__workflow_transitions" ("checked_out"); INSERT INTO "#__workflow_transitions" ("id", "asset_id", "published", "ordering", "workflow_id", "title", "description", "from_stage_id", "to_stage_id", "options") VALUES -(1, 58, 1, 1, 1, 'UNPUBLISH', '', -1, 1, '{"publishing":"0"}'), -(2, 59, 1, 2, 1, 'PUBLISH', '', -1, 1, '{"publishing":"1"}'), -(3, 60, 1, 3, 1, 'TRASH', '', -1, 1, '{"publishing":"-2"}'), -(4, 61, 1, 4, 1, 'ARCHIVE', '', -1, 1, '{"publishing":"2"}'), -(5, 62, 1, 5, 1, 'FEATURE', '', -1, 1, '{"featuring":"1"}'), -(6, 63, 1, 6, 1, 'UNFEATURE', '', -1, 1, '{"featuring":"0"}'), -(7, 64, 1, 7, 1, 'PUBLISH_AND_FEATURE', '', -1, 1, '{"publishing":"1","featuring":"1"}'); - -SELECT setval('#__workflow_transitions_id_seq', 8, false); +(1, 58, 1, 1, 1, 'Unpublish', '', -1, 1, '{"publishing":"0"}'), +(2, 59, 1, 2, 1, 'Publish', '', -1, 1, '{"publishing":"1"}'), +(3, 60, 1, 3, 1, 'Trash', '', -1, 1, '{"publishing":"-2"}'), +(4, 61, 1, 4, 1, 'Archive', '', -1, 1, '{"publishing":"2"}'), +(5, 62, 1, 5, 1, 'Feature', '', -1, 1, '{"featuring":"1"}'), +(6, 63, 1, 6, 1, 'Unfeature', '', -1, 1, '{"featuring":"0"}'), +(7, 64, 1, 7, 1, 'Publish & Feature', '', -1, 1, '{"publishing":"1","featuring":"1"}'), +(8, 94, 1, 1, 2, 'Unpublish', '', -1, 2, '{"publishing":"0"}'), +(9, 93, 1, 2, 2, 'Publish', '', -1, 2, '{"publishing":"1"}'), +(10, 95, 1, 3, 2, 'Trash', '', -1, 2, '{"publishing":"-2"}'); + +SELECT setval('#__workflow_transitions_id_seq', 11, false); + +INSERT INTO "#__workflow_associations" ("item_id", "stage_id", "extension") +SELECT "id", 2, 'com_modules.module' FROM "#__modules"; diff --git a/libraries/src/MVC/Model/WorkflowBehaviorTrait.php b/libraries/src/MVC/Model/WorkflowBehaviorTrait.php index ad99c65315006..5d5527f252ad3 100644 --- a/libraries/src/MVC/Model/WorkflowBehaviorTrait.php +++ b/libraries/src/MVC/Model/WorkflowBehaviorTrait.php @@ -326,7 +326,7 @@ protected function addTransitionField(Form $form, $data) $field->addAttribute('name', 'transition'); $field->addAttribute('type', $this->workflowEnabled ? 'transition' : 'hidden'); - $field->addAttribute('label', 'COM_CONTENT_WORKFLOW'); + $field->addAttribute('label', 'JWORKFLOW_TITLE'); $field->addAttribute('extension', $extension); $form->setField($field);