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 00000000000..f47f88c5225 --- /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 worklfow +-- +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 worklfow +-- +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 00000000000..c3eb9e04ae7 --- /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 worklfow +-- +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 worklfow +-- +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/forms/category.xml b/administrator/components/com_content/forms/category.xml index 61f0f961f17..7fb3cbd4790 100644 --- a/administrator/components/com_content/forms/category.xml +++ b/administrator/components/com_content/forms/category.xml @@ -10,7 +10,7 @@ size="1" sql_select="id, title" sql_from="#__workflows" - sql_where="published = 1" + sql_where="published = 1 AND extension = 'com_content.article'" sql_order="ordering" key_field="id" value_field="title" diff --git a/administrator/components/com_content/src/Model/ArticlesModel.php b/administrator/components/com_content/src/Model/ArticlesModel.php index e9b8e02a02a..4d892a89321 100644 --- a/administrator/components/com_content/src/Model/ArticlesModel.php +++ b/administrator/components/com_content/src/Model/ArticlesModel.php @@ -302,7 +302,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')) { diff --git a/administrator/components/com_content/tmpl/articles/default.php b/administrator/components/com_content/tmpl/articles/default.php index 062d2ff8782..d3fa1fb904e 100644 --- a/administrator/components/com_content/tmpl/articles/default.php +++ b/administrator/components/com_content/tmpl/articles/default.php @@ -221,7 +221,8 @@ 'transitions' => $transitions, 'title' => Text::_($item->stage_title), 'tip_content' => Text::sprintf('JWORKFLOW', Text::_($item->workflow_title)), - 'id' => 'workflow-' . $item->id + 'id' => 'workflow-' . $item->id, + 'task' => 'articles.runTransition' ]; echo (new TransitionButton($options)) diff --git a/administrator/components/com_content/tmpl/featured/default.php b/administrator/components/com_content/tmpl/featured/default.php index 52624114666..3ddeeff4e65 100644 --- a/administrator/components/com_content/tmpl/featured/default.php +++ b/administrator/components/com_content/tmpl/featured/default.php @@ -227,7 +227,8 @@ 'transitions' => $transitions, 'title' => Text::_($item->stage_title), 'tip_content' => Text::sprintf('JWORKFLOW', Text::_($item->workflow_title)), - 'id' => 'workflow-' . $item->id + 'id' => 'workflow-' . $item->id, + '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 e68f878989d..c5d29977ff6 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 2cb76164c13..96d9044bb15 100644 --- a/administrator/components/com_modules/config.xml +++ b/administrator/components/com_modules/config.xml @@ -52,4 +52,26 @@ section="component" /> + +
+
+ + + + +
+
diff --git a/administrator/components/com_modules/forms/filter_modules.xml b/administrator/components/com_modules/forms/filter_modules.xml index 6adc9ec4377..e60a68da459 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 f7fc6f090b8..3f1d5872571 100644 --- a/administrator/components/com_modules/forms/moduleadmin.xml +++ b/administrator/components/com_modules/forms/moduleadmin.xml @@ -150,4 +150,23 @@ validate="rules" /> + +
+ +
diff --git a/administrator/components/com_modules/src/Extension/ModulesComponent.php b/administrator/components/com_modules/src/Extension/ModulesComponent.php index 167c8b8ff60..a2005ba944c 100644 --- a/administrator/components/com_modules/src/Extension/ModulesComponent.php +++ b/administrator/components/com_modules/src/Extension/ModulesComponent.php @@ -11,9 +11,13 @@ \defined('JPATH_PLATFORM') or die; +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\Service\HTML\Modules; use Psr\Container\ContainerInterface; @@ -22,9 +26,49 @@ * * @since 4.0.0 */ -class ModulesComponent extends MVCComponent implements BootableExtensionInterface +class ModulesComponent extends MVCComponent implements BootableExtensionInterface, +WorkflowServiceInterface { use HTMLRegistryAwareTrait; + use WorkflowServiceTrait; + + /** @var array Supported functionality */ + protected $supportedFunctionality = [ + 'core.state' => true, + ]; + + /** + * The trashed condition + * + * @since __DEPLOY_VERSION__ + */ + const CONDITION_NAMES = [ + self::CONDITION_PUBLISHED => 'JPUBLISHED', + self::CONDITION_UNPUBLISHED => 'JUNPUBLISHED', + self::CONDITION_TRASHED => 'JTRASHED', + ]; + + /** + * The published condition + * + * @since __DEPLOY_VERSION__ + */ + const CONDITION_PUBLISHED = 1; + + /** + * The unpublished condition + * + * @since __DEPLOY_VERSION__ + */ + const CONDITION_UNPUBLISHED = 0; + + /** + * The trashed condition + * + * @since __DEPLOY_VERSION__ + */ + const CONDITION_TRASHED = -2; + /** * Booting the extension. This is the function to set up the environment of the extension like @@ -43,4 +87,51 @@ 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 = array( + '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 ModuleHelper::filterTransitions($transitions, $pk); + } } diff --git a/administrator/components/com_modules/src/Helper/ModulesHelper.php b/administrator/components/com_modules/src/Helper/ModulesHelper.php index 6657d2f1b98..24d0ff948c6 100644 --- a/administrator/components/com_modules/src/Helper/ModulesHelper.php +++ b/administrator/components/com_modules/src/Helper/ModulesHelper.php @@ -323,4 +323,28 @@ 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 f0634bbd374..8a3a3c504ac 100644 --- a/administrator/components/com_modules/src/Model/ModuleModel.php +++ b/administrator/components/com_modules/src/Model/ModuleModel.php @@ -19,10 +19,13 @@ 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\CMS\Workflow\Workflow; use Joomla\Database\ParameterType; use Joomla\Registry\Registry; use Joomla\String\StringHelper; @@ -33,8 +36,10 @@ * * @since 1.6 */ -class ModuleModel extends AdminModel +class ModuleModel extends AdminModel implements WorkflowModelInterface { + use WorkflowBehaviorTrait; + /** * The type alias for this content type. * @@ -100,6 +105,8 @@ public function __construct($config = array()) ); parent::__construct($config); + + $this->setUpWorkflow('com_modules.module'); } /** @@ -389,6 +396,8 @@ public function delete(&$pks) // Clear module cache parent::cleanCache($table->module); + + $this->workflow->deleteAssociation($pks); } else { @@ -465,6 +474,16 @@ public function duplicate(&$pks) { $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 { @@ -494,6 +513,27 @@ 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(); @@ -840,6 +880,17 @@ 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); } @@ -900,6 +951,27 @@ protected function preprocessForm(Form $form, $data, $group = 'content') Form::addFormPath(JPATH_ADMINISTRATOR . '/components/com_modules/models/forms'); $form->loadFile('advanced', false); + 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 seperately 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); } @@ -1005,6 +1077,8 @@ public function save($data) return false; } + $this->workflowBeforeSave(); + // Process the menu link mappings. $assignment = $data['assignment'] ?? 0; @@ -1122,6 +1196,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(); @@ -1163,4 +1240,108 @@ 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 defaylt 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 aa337ba202a..7602c0022c4 100644 --- a/administrator/components/com_modules/src/Model/ModulesModel.php +++ b/administrator/components/com_modules/src/Model/ModulesModel.php @@ -229,6 +229,37 @@ 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 * @@ -278,6 +309,7 @@ protected function getListQuery() // Create a new query object. $db = $this->getDbo(); $query = $db->getQuery(true); + $params = ComponentHelper::getParams('com_modules'); // Select the required fields. $query->select( @@ -312,6 +344,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, ' @@ -344,6 +394,16 @@ 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'); @@ -353,7 +413,7 @@ protected function getListQuery() $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]); } @@ -461,6 +521,113 @@ protected function getListQuery() return $query; } + /** + * Method to get all transitions at once for all articles + * + * @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 9a30391068e..e8cbf202ee5 100644 --- a/administrator/components/com_modules/src/View/Modules/HtmlView.php +++ b/administrator/components/com_modules/src/View/Modules/HtmlView.php @@ -12,12 +12,14 @@ \defined('_JEXEC') or die; 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; @@ -97,6 +99,13 @@ 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 26d76efa39f..d76de02c77b 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'; + ?>
@@ -134,6 +137,7 @@ fields = array( + $workflowField, 'showtitle', 'position', 'published', @@ -178,7 +182,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 bd95ae2d29c..ed79feb47cc 100644 --- a/administrator/components/com_modules/tmpl/modules/default.php +++ b/administrator/components/com_modules/tmpl/modules/default.php @@ -9,6 +9,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; @@ -17,6 +20,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; HTMLHelper::_('behavior.multiselect'); @@ -31,6 +36,37 @@ $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; ?>
@@ -50,6 +86,11 @@ + + + + + @@ -91,6 +132,13 @@ $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); + } ?> @@ -115,6 +163,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) : ?> @@ -126,6 +201,7 @@ +
checked_out) : ?> @@ -209,6 +285,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 2a52e9c45f6..d70543f87e9 100644 --- a/administrator/components/com_modules/tmpl/modules/default_batch_body.php +++ b/administrator/components/com_modules/tmpl/modules/default_batch_body.php @@ -9,6 +9,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; @@ -17,6 +19,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); @@ -59,6 +65,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 cfb0cc3c87b..b3ad6edd43a 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." ; 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 9f32556fdb8..bea4d50dcd7 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 b13e0265005..3b99409ab6e 100644 --- a/administrator/language/en-GB/mod_menu.ini +++ b/administrator/language/en-GB/mod_menu.ini @@ -35,6 +35,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 99199575edf..bbaa9049472 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, 161, 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, 171, 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, 128, 1, 'com_modules', 'com_modules', '{"core.admin":{"7":1}}'), -(19, 1, 129, 132, 1, 'com_newsfeeds', 'com_newsfeeds', '{"core.admin":{"7":1},"core.manage":{"6":1}}'), -(20, 1, 133, 134, 1, 'com_plugins', 'com_plugins', '{"core.admin":{"7":1}}'), -(21, 1, 135, 136, 1, 'com_redirect', 'com_redirect', '{"core.admin":{"7":1}}'), -(23, 1, 137, 138, 1, 'com_templates', 'com_templates', '{"core.admin":{"7":1}}'), -(24, 1, 143, 146, 1, 'com_users', 'com_users', '{"core.admin":{"7":1}}'), -(26, 1, 147, 148, 1, 'com_wrapper', 'com_wrapper', '{}'), +(18, 1, 57, 138, 1, 'com_modules', 'com_modules', '{"core.admin":{"7":1}}'), +(19, 1, 139, 142, 1, 'com_newsfeeds', 'com_newsfeeds', '{"core.admin":{"7":1},"core.manage":{"6":1}}'), +(20, 1, 143, 144, 1, 'com_plugins', 'com_plugins', '{"core.admin":{"7":1}}'), +(21, 1, 145, 146, 1, 'com_redirect', 'com_redirect', '{"core.admin":{"7":1}}'), +(23, 1, 147, 148, 1, 'com_templates', 'com_templates', '{"core.admin":{"7":1}}'), +(24, 1, 153, 156, 1, 'com_users', 'com_users', '{"core.admin":{"7":1}}'), +(26, 1, 157, 158, 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, 130, 131, 2, 'com_newsfeeds.category.5', 'Uncategorised', '{}'), -(32, 24, 144, 145, 2, 'com_users.category.7', 'Uncategorised', '{}'), -(33, 1, 149, 150, 1, 'com_finder', 'com_finder', '{"core.admin":{"7":1},"core.manage":{"6":1}}'), -(34, 1, 151, 152, 1, 'com_joomlaupdate', 'com_joomlaupdate', '{}'), -(35, 1, 153, 154, 1, 'com_tags', 'com_tags', '{}'), -(36, 1, 155, 156, 1, 'com_contenthistory', 'com_contenthistory', '{}'), -(37, 1, 157, 158, 1, 'com_ajax', 'com_ajax', '{}'), -(38, 1, 159, 160, 1, 'com_postinstall', 'com_postinstall', '{}'), +(30, 19, 140, 141, 2, 'com_newsfeeds.category.5', 'Uncategorised', '{}'), +(32, 24, 154, 155, 2, 'com_users.category.7', 'Uncategorised', '{}'), +(33, 1, 159, 160, 1, 'com_finder', 'com_finder', '{"core.admin":{"7":1},"core.manage":{"6":1}}'), +(34, 1, 161, 162, 1, 'com_joomlaupdate', 'com_joomlaupdate', '{}'), +(35, 1, 163, 164, 1, 'com_tags', 'com_tags', '{}'), +(36, 1, 165, 166, 1, 'com_contenthistory', 'com_contenthistory', '{}'), +(37, 1, 167, 168, 1, 'com_ajax', 'com_ajax', '{}'), +(38, 1, 169, 170, 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, 139, 140, 1, 'com_privacy', 'com_privacy', '{}'), -(66, 1, 141, 142, 1, 'com_actionlogs', 'com_actionlogs', '{}'), +(65, 1, 149, 150, 1, 'com_privacy', 'com_privacy', '{}'), +(66, 1, 151, 152, 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', '{}'), @@ -105,7 +105,12 @@ INSERT INTO `#__assets` (`id`, `parent_id`, `lft`, `rgt`, `level`, `name`, `titl (85, 18, 120, 121, 2, 'com_modules.module.108', 'Privacy Status', '{}'), (86, 18, 122, 123, 2, 'com_modules.module.96', 'Popular Articles', '{}'), (87, 18, 124, 125, 2, 'com_modules.module.97', 'Recently Added Articles', '{}'), -(88, 18, 126, 127, 2, 'com_modules.module.98', 'Logged-in Users', '{}'); +(88, 18, 126, 127, 2, 'com_modules.module.98', 'Logged-in Users', '{}'), +(89, 18, 128, 137, 2, 'com_modules.workflow.1', 'COM_WORKFLOW_BASIC_WORKFLOW_MODULES', '{}'), +(90, 89, 129, 130, 3, 'com_modules.state.1', 'COM_WORKFLOW_BASIC_STAGE', '{}'), +(91, 89, 131, 132, 3, 'com_modules.transition.1', 'Publish', '{}'), +(92, 89, 133, 134, 3, 'com_modules.transition.2', 'Unpublish', '{}'), +(93, 89, 135, 136, 3, 'com_modules.transition.3', 'Trash', '{}'); -- -------------------------------------------------------- @@ -1077,7 +1082,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, 89, 1, 'COM_WORKFLOW_BASIC_WORKFLOW_MODULES', '', 'com_modules.module', 1, 1, CURRENT_TIMESTAMP(), 42, CURRENT_TIMESTAMP(), 42); -- -------------------------------------------------------- @@ -1126,7 +1132,8 @@ CREATE TABLE IF NOT EXISTS `#__workflow_stages` ( -- INSERT INTO `#__workflow_stages` (`id`, `asset_id`, `ordering`, `workflow_id`, `published`, `title`, `description`, `default`) VALUES -(1, 0, 1, 1, 1, 'COM_WORKFLOW_BASIC_STAGE', '', 1); +(1, 0, 1, 1, 1, 'COM_WORKFLOW_BASIC_STAGE', '', 1), +(2, 90, 1, 2, 1, 'COM_WORKFLOW_BASIC_STAGE', '', 1); -- -------------------------------------------------------- @@ -1167,4 +1174,10 @@ INSERT INTO `#__workflow_transitions` (`id`, `asset_id`, `published`, `ordering` (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"}'); +(7, 64, 1, 7, 1, 'Publish & Feature', '', -1, 1, '{"publishing":"1","featuring":"1"}'), +(8, 92, 1, 1, 2, 'Unpublish', '', -1, 2, '{"publishing":"0"}'), +(9, 91, 1, 2, 2, 'Publish', '', -1, 2, '{"publishing":"1"}'), +(10, 93, 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 8cda51c8fee..6c3ec5eccf5 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, 161, 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, 171, 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, 128, 1, 'com_modules', 'com_modules', '{"core.admin":{"7":1}}'), -(19, 1, 129, 132, 1, 'com_newsfeeds', 'com_newsfeeds', '{"core.admin":{"7":1},"core.manage":{"6":1}}'), -(20, 1, 133, 134, 1, 'com_plugins', 'com_plugins', '{"core.admin":{"7":1}}'), -(21, 1, 135, 136, 1, 'com_redirect', 'com_redirect', '{"core.admin":{"7":1}}'), -(23, 1, 137, 138, 1, 'com_templates', 'com_templates', '{"core.admin":{"7":1}}'), -(24, 1, 143, 146, 1, 'com_users', 'com_users', '{"core.admin":{"7":1}}'), -(26, 1, 147, 148, 1, 'com_wrapper', 'com_wrapper', '{}'), +(18, 1, 57, 138, 1, 'com_modules', 'com_modules', '{"core.admin":{"7":1}}'), +(19, 1, 139, 142, 1, 'com_newsfeeds', 'com_newsfeeds', '{"core.admin":{"7":1},"core.manage":{"6":1}}'), +(20, 1, 143, 144, 1, 'com_plugins', 'com_plugins', '{"core.admin":{"7":1}}'), +(21, 1, 145, 146, 1, 'com_redirect', 'com_redirect', '{"core.admin":{"7":1}}'), +(23, 1, 147, 148, 1, 'com_templates', 'com_templates', '{"core.admin":{"7":1}}'), +(24, 1, 153, 156, 1, 'com_users', 'com_users', '{"core.admin":{"7":1}}'), +(26, 1, 157, 158, 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, 130, 131, 2, 'com_newsfeeds.category.5', 'Uncategorised', '{}'), -(32, 24, 144, 145, 2, 'com_users.category.7', 'Uncategorised', '{}'), -(33, 1, 149, 150, 1, 'com_finder', 'com_finder', '{"core.admin":{"7":1},"core.manage":{"6":1}}'), -(34, 1, 151, 152, 1, 'com_joomlaupdate', 'com_joomlaupdate', '{}'), -(35, 1, 153, 154, 1, 'com_tags', 'com_tags', '{}'), -(36, 1, 155, 156, 1, 'com_contenthistory', 'com_contenthistory', '{}'), -(37, 1, 157, 158, 1, 'com_ajax', 'com_ajax', '{}'), -(38, 1, 159, 160, 1, 'com_postinstall', 'com_postinstall', '{}'), +(30, 19, 140, 141, 2, 'com_newsfeeds.category.5', 'Uncategorised', '{}'), +(32, 24, 154, 155, 2, 'com_users.category.7', 'Uncategorised', '{}'), +(33, 1, 159, 160, 1, 'com_finder', 'com_finder', '{"core.admin":{"7":1},"core.manage":{"6":1}}'), +(34, 1, 161, 162, 1, 'com_joomlaupdate', 'com_joomlaupdate', '{}'), +(35, 1, 163, 164, 1, 'com_tags', 'com_tags', '{}'), +(36, 1, 165, 166, 1, 'com_contenthistory', 'com_contenthistory', '{}'), +(37, 1, 167, 168, 1, 'com_ajax', 'com_ajax', '{}'), +(38, 1, 169, 170, 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, 139, 140, 1, 'com_privacy', 'com_privacy', '{}'), -(66, 1, 141, 142, 1, 'com_actionlogs', 'com_actionlogs', '{}'), +(65, 1, 149, 150, 1, 'com_privacy', 'com_privacy', '{}'), +(66, 1, 151, 152, 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', '{}'), @@ -111,9 +111,14 @@ INSERT INTO "#__assets" ("id", "parent_id", "lft", "rgt", "level", "name", "titl (85, 18, 120, 121, 2, 'com_modules.module.108', 'Privacy Status', '{}'), (86, 18, 122, 123, 2, 'com_modules.module.96', 'Popular Articles', '{}'), (87, 18, 124, 125, 2, 'com_modules.module.97', 'Recently Added Articles', '{}'), -(88, 18, 126, 127, 2, 'com_modules.module.98', 'Logged-in Users', '{}'); +(88, 18, 126, 127, 2, 'com_modules.module.98', 'Logged-in Users', '{}'), +(89, 18, 128, 137, 2, 'com_modules.workflow.1', 'COM_WORKFLOW_BASIC_WORKFLOW_MODULES', '{}'), +(90, 89, 129, 130, 3, 'com_modules.state.1', 'COM_WORKFLOW_BASIC_STAGE', '{}'), +(91, 89, 131, 132, 3, 'com_modules.transition.1', 'Publish', '{}'), +(92, 89, 133, 134, 3, 'com_modules.transition.2', 'Unpublish', '{}'), +(93, 89, 135, 136, 3, 'com_modules.transition.3', 'Trash', '{}'); -SELECT setval('#__assets_id_seq', 89, false); +SELECT setval('#__assets_id_seq', 94, false); -- -- Table structure for table `#__extensions` @@ -1099,9 +1104,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, 89, 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` @@ -1149,9 +1155,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, 90, 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` @@ -1186,6 +1193,12 @@ INSERT INTO "#__workflow_transitions" ("id", "asset_id", "published", "ordering" (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"}'); +(7, 64, 1, 7, 1, 'Publish & Feature', '', -1, 1, '{"publishing":"1","featuring":"1"}'), +(8, 92, 1, 1, 2, 'Unpublish', '', -1, 2, '{"publishing":"0"}'), +(9, 91, 1, 2, 2, 'Publish', '', -1, 2, '{"publishing":"1"}'), +(10, 93, 1, 3, 2, 'Trash', '', -1, 2, '{"publishing":"-2"}'); -SELECT setval('#__workflow_transitions_id_seq', 8, false); +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/layouts/joomla/button/transition-button.php b/layouts/joomla/button/transition-button.php index 965973c6e6f..0ee490f82ee 100644 --- a/layouts/joomla/button/transition-button.php +++ b/layouts/joomla/button/transition-button.php @@ -27,6 +27,7 @@ $tipTitle = $options['tip_title']; $tipContent = $options['tip_content']; $checkboxName = $options['checkbox_name']; +$task = $options['task']; ?>