first commit
This commit is contained in:
@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form>
|
||||
<fields name="filter">
|
||||
<field
|
||||
name="search"
|
||||
type="text"
|
||||
inputmode="search"
|
||||
label="COM_WORKFLOW_FILTER_SEARCH_LABEL"
|
||||
hint="JSEARCH_FILTER"
|
||||
/>
|
||||
<field
|
||||
name="published"
|
||||
type="status"
|
||||
label="JSTATUS"
|
||||
class="js-select-submit-on-change"
|
||||
optionsFilter="-2,0,1"
|
||||
>
|
||||
<option value="">JOPTION_SELECT_PUBLISHED</option>
|
||||
</field>
|
||||
</fields>
|
||||
|
||||
<fields name="list">
|
||||
<field
|
||||
name="fullordering"
|
||||
type="list"
|
||||
label="JGLOBAL_SORT_BY"
|
||||
default="s.ordering ASC"
|
||||
class="js-select-submit-on-change"
|
||||
validate="options"
|
||||
>
|
||||
<option value="">JGLOBAL_SORT_BY</option>
|
||||
<option value="s.ordering ASC">JGRID_HEADING_ORDERING_ASC</option>
|
||||
<option value="s.ordering DESC">JGRID_HEADING_ORDERING_DESC</option>
|
||||
<option value="s.published ASC">JSTATUS_ASC</option>
|
||||
<option value="s.published DESC">JSTATUS_DESC</option>
|
||||
<option value="s.title ASC">JGLOBAL_NAME_ASC</option>
|
||||
<option value="s.title DESC">JGLOBAL_NAME_DESC</option>
|
||||
<option value="s.id ASC">JGRID_HEADING_ID_ASC</option>
|
||||
<option value="s.id DESC">JGRID_HEADING_ID_DESC</option>
|
||||
</field>
|
||||
<field
|
||||
name="limit"
|
||||
type="limitbox"
|
||||
label="JGLOBAL_LIST_LIMIT"
|
||||
default="25"
|
||||
class="js-select-submit-on-change"
|
||||
/>
|
||||
</fields>
|
||||
</form>
|
||||
@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form>
|
||||
<fields name="filter">
|
||||
<field
|
||||
name="search"
|
||||
type="text"
|
||||
inputmode="search"
|
||||
label="COM_WORKFLOW_FILTER_SEARCH_LABEL"
|
||||
hint="JSEARCH_FILTER"
|
||||
/>
|
||||
<field
|
||||
name="published"
|
||||
type="status"
|
||||
label="JSTATUS"
|
||||
class="js-select-submit-on-change"
|
||||
optionsFilter="-2,0,1"
|
||||
>
|
||||
<option value="">JOPTION_SELECT_PUBLISHED</option>
|
||||
</field>
|
||||
<field
|
||||
name="from_stage"
|
||||
type="sql"
|
||||
label="COM_WORKFLOW_FROM_STAGE"
|
||||
class="js-select-submit-on-change"
|
||||
sql_select="id as value, title as from_stage"
|
||||
sql_from="#__workflow_stages"
|
||||
translate="true"
|
||||
>
|
||||
<option value="">COM_WORKFLOW_SELECT_FROM_STAGE</option>
|
||||
</field>
|
||||
<field
|
||||
name="to_stage"
|
||||
type="sql"
|
||||
label="COM_WORKFLOW_TO_STAGE"
|
||||
class="js-select-submit-on-change"
|
||||
sql_select="id as value, title as to_stage"
|
||||
sql_from="#__workflow_stages"
|
||||
translate="true"
|
||||
>
|
||||
<option value="">COM_WORKFLOW_SELECT_TO_STAGE</option>
|
||||
</field>
|
||||
</fields>
|
||||
|
||||
<fields name="list">
|
||||
<field
|
||||
name="fullordering"
|
||||
type="list"
|
||||
label="JGLOBAL_SORT_BY"
|
||||
default="t.ordering ASC"
|
||||
class="js-select-submit-on-change"
|
||||
validate="options"
|
||||
>
|
||||
<option value="">JGLOBAL_SORT_BY</option>
|
||||
<option value="t.ordering ASC">JGRID_HEADING_ORDERING_ASC</option>
|
||||
<option value="t.ordering DESC">JGRID_HEADING_ORDERING_DESC</option>
|
||||
<option value="t.published ASC">JSTATUS_ASC</option>
|
||||
<option value="t.published DESC">JSTATUS_DESC</option>
|
||||
<option value="t.title ASC">JGLOBAL_NAME_ASC</option>
|
||||
<option value="t.title DESC">JGLOBAL_NAME_DESC</option>
|
||||
<option value="from_stage ASC">COM_WORKFLOW_FROM_STAGE_FILTER_ASC</option>
|
||||
<option value="from_stage DESC">COM_WORKFLOW_FROM_STAGE_FILTER_DESC</option>
|
||||
<option value="to_stage ASC">COM_WORKFLOW_TO_STAGE_FILTER_ASC</option>
|
||||
<option value="to_stage DESC">COM_WORKFLOW_TO_STAGE_FILTER_DESC</option>
|
||||
<option value="t.id ASC">JGRID_HEADING_ID_ASC</option>
|
||||
<option value="t.id DESC">JGRID_HEADING_ID_DESC</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="limit"
|
||||
type="limitbox"
|
||||
label="JGLOBAL_LIST_LIMIT"
|
||||
default="25"
|
||||
class="js-select-submit-on-change"
|
||||
/>
|
||||
</fields>
|
||||
</form>
|
||||
@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form addfieldprefix="Joomla\Component\Workflow\Administrator\Field">
|
||||
<fieldset name="group">
|
||||
<field
|
||||
name="extension"
|
||||
type="workflowcontexts"
|
||||
filtermode="selector"
|
||||
class="js-select-submit-on-change"
|
||||
/>
|
||||
</fieldset>
|
||||
<fields name="filter">
|
||||
<field
|
||||
name="search"
|
||||
type="text"
|
||||
inputmode="search"
|
||||
label="COM_WORKFLOW_FILTER_SEARCH_LABEL"
|
||||
description="COM_WORKFLOW_FILTER_SEARCH_DESC"
|
||||
hint="JSEARCH_FILTER"
|
||||
/>
|
||||
<field
|
||||
name="published"
|
||||
type="status"
|
||||
label="JSTATUS"
|
||||
class="js-select-submit-on-change"
|
||||
optionsFilter="-2,0,1"
|
||||
>
|
||||
<option value="">JOPTION_SELECT_PUBLISHED</option>
|
||||
</field>
|
||||
</fields>
|
||||
|
||||
<fields name="list">
|
||||
<field
|
||||
name="fullordering"
|
||||
type="list"
|
||||
label="JGLOBAL_SORT_BY"
|
||||
default="w.ordering ASC"
|
||||
class="js-select-submit-on-change"
|
||||
validate="options"
|
||||
>
|
||||
<option value="">JGLOBAL_SORT_BY</option>
|
||||
<option value="w.ordering ASC">JGRID_HEADING_ORDERING_ASC</option>
|
||||
<option value="w.ordering DESC">JGRID_HEADING_ORDERING_DESC</option>
|
||||
<option value="w.published ASC">JSTATUS_ASC</option>
|
||||
<option value="w.published DESC">JSTATUS_DESC</option>
|
||||
<option value="w.title ASC">JGLOBAL_NAME_ASC</option>
|
||||
<option value="w.title DESC">JGLOBAL_NAME_DESC</option>
|
||||
<option value="w.id ASC">JGRID_HEADING_ID_ASC</option>
|
||||
<option value="w.id DESC">JGRID_HEADING_ID_DESC</option>
|
||||
</field>
|
||||
<field
|
||||
name="limit"
|
||||
type="limitbox"
|
||||
label="JGLOBAL_LIST_LIMIT"
|
||||
default="25"
|
||||
class="js-select-submit-on-change"
|
||||
/>
|
||||
</fields>
|
||||
</form>
|
||||
68
administrator/components/com_workflow/forms/stage.xml
Normal file
68
administrator/components/com_workflow/forms/stage.xml
Normal file
@ -0,0 +1,68 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form>
|
||||
<fieldset name="stage" addfieldprefix="Joomla\Component\Workflow\Administrator\Field">
|
||||
<field
|
||||
name="id"
|
||||
type="text"
|
||||
label="JGLOBAL_FIELD_ID_LABEL"
|
||||
default="0"
|
||||
class="readonly"
|
||||
readonly="true"
|
||||
/>
|
||||
<field
|
||||
name="title"
|
||||
type="text"
|
||||
label="COM_WORKFLOW_FIELD_NAME_LABEL"
|
||||
required="true"
|
||||
/>
|
||||
<field
|
||||
name="description"
|
||||
type="textarea"
|
||||
label="COM_WORKFLOW_STAGE_NOTE"
|
||||
rows="3"
|
||||
cols="60"
|
||||
/>
|
||||
</fieldset>
|
||||
|
||||
<fieldset name="params" label="COM_WORKFLOW_PARAMS_LABEL">
|
||||
<field
|
||||
name="published"
|
||||
type="list"
|
||||
label="COM_WORKFLOW_PUBLISHED_LABEL"
|
||||
required="true"
|
||||
class="form-select-color-state"
|
||||
default="1"
|
||||
validate="options"
|
||||
>
|
||||
<option value="1">JENABLED</option>
|
||||
<option value="0">JDISABLED</option>
|
||||
<option value="-2">JTRASHED</option>
|
||||
</field>
|
||||
<field
|
||||
name="default"
|
||||
type="radio"
|
||||
label="COM_WORKFLOW_FIELD_IS_DEFAULT_LABEL"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="0"
|
||||
>
|
||||
<option value="0">JNO</option>
|
||||
<option value="1">JYES</option>
|
||||
</field>
|
||||
</fieldset>
|
||||
|
||||
<fieldset name="permissions" label="JCONFIG_PERMISSIONS_LABEL">
|
||||
<field
|
||||
name="asset_id"
|
||||
type="hidden"
|
||||
filter="unset"
|
||||
/>
|
||||
<field
|
||||
name="rules"
|
||||
type="rules"
|
||||
label="JCONFIG_PERMISSIONS_LABEL"
|
||||
validate="rules"
|
||||
filter="rules"
|
||||
section="stage"
|
||||
/>
|
||||
</fieldset>
|
||||
</form>
|
||||
80
administrator/components/com_workflow/forms/transition.xml
Normal file
80
administrator/components/com_workflow/forms/transition.xml
Normal file
@ -0,0 +1,80 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form>
|
||||
<fieldset name="transition" addfieldprefix="Joomla\Component\Workflow\Administrator\Field">
|
||||
<field
|
||||
name="id"
|
||||
type="hidden"
|
||||
label="JGLOBAL_FIELD_ID_LABEL"
|
||||
default="0"
|
||||
class="readonly"
|
||||
readonly="true"
|
||||
/>
|
||||
<field
|
||||
name="title"
|
||||
type="text"
|
||||
label="COM_WORKFLOW_FIELD_NAME_LABEL"
|
||||
required="true"
|
||||
/>
|
||||
<field
|
||||
name="from_stage_id"
|
||||
type="sql"
|
||||
label="COM_WORKFLOW_FROM_STAGE"
|
||||
required="true"
|
||||
sql_select="id as value, title as from_stage_id"
|
||||
sql_from="#__workflow_stages"
|
||||
sql_order="ordering"
|
||||
translate="true"
|
||||
>
|
||||
<option value="-1">JALL</option>
|
||||
</field>
|
||||
<field
|
||||
name="to_stage_id"
|
||||
type="sql"
|
||||
label="COM_WORKFLOW_TO_STAGE"
|
||||
required="true"
|
||||
sql_select="id as value, title as to_stage_id"
|
||||
sql_from="#__workflow_stages"
|
||||
sql_order="ordering"
|
||||
translate="true"
|
||||
/>
|
||||
<field
|
||||
name="description"
|
||||
type="textarea"
|
||||
label="COM_WORKFLOW_TRANSITION_NOTE"
|
||||
rows="3"
|
||||
cols="60"
|
||||
/>
|
||||
</fieldset>
|
||||
|
||||
<fieldset name="params" label="COM_WORKFLOW_PARAMS_LABEL">
|
||||
<field
|
||||
name="published"
|
||||
type="list"
|
||||
label="COM_WORKFLOW_PUBLISHED_LABEL"
|
||||
required="true"
|
||||
class="form-select-color-state"
|
||||
default="1"
|
||||
validate="options"
|
||||
>
|
||||
<option value="1">JENABLED</option>
|
||||
<option value="0">JDISABLED</option>
|
||||
<option value="-2">JTRASHED</option>
|
||||
</field>
|
||||
</fieldset>
|
||||
|
||||
<fieldset name="permissions" label="JCONFIG_PERMISSIONS_LABEL">
|
||||
<field
|
||||
name="asset_id"
|
||||
type="hidden"
|
||||
filter="unset"
|
||||
/>
|
||||
<field
|
||||
name="rules"
|
||||
type="rules"
|
||||
label="JCONFIG_PERMISSIONS_LABEL"
|
||||
validate="rules"
|
||||
filter="rules"
|
||||
section="transition"
|
||||
/>
|
||||
</fieldset>
|
||||
</form>
|
||||
84
administrator/components/com_workflow/forms/workflow.xml
Normal file
84
administrator/components/com_workflow/forms/workflow.xml
Normal file
@ -0,0 +1,84 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form>
|
||||
<fieldset name="workflow" addfieldprefix="Joomla\Component\Workflow\Administrator\Field">
|
||||
<field
|
||||
name="id"
|
||||
type="hidden"
|
||||
label="JGLOBAL_FIELD_ID_LABEL"
|
||||
default="0"
|
||||
class="readonly"
|
||||
readonly="true"
|
||||
/>
|
||||
<field
|
||||
name="extension"
|
||||
type="hidden"
|
||||
/>
|
||||
<field
|
||||
name="title"
|
||||
type="text"
|
||||
label="COM_WORKFLOW_FIELD_NAME_LABEL"
|
||||
required="true"
|
||||
/>
|
||||
<field
|
||||
name="description"
|
||||
type="textarea"
|
||||
label="COM_WORKFLOW_WORKFLOW_NOTE"
|
||||
rows="3"
|
||||
cols="60"
|
||||
/>
|
||||
</fieldset>
|
||||
|
||||
<fieldset name="params" label="COM_WORKFLOW_PARAMS_LABEL">
|
||||
<field
|
||||
name="published"
|
||||
type="list"
|
||||
label="COM_WORKFLOW_PUBLISHED_LABEL"
|
||||
required="true"
|
||||
class="form-select-color-state"
|
||||
default="1"
|
||||
validate="options"
|
||||
>
|
||||
<option value="1">JENABLED</option>
|
||||
<option value="0">JDISABLED</option>
|
||||
<option value="-2">JTRASHED</option>
|
||||
</field>
|
||||
<field
|
||||
name="default"
|
||||
type="radio"
|
||||
label="COM_WORKFLOW_FIELD_IS_DEFAULT_LABEL"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="0"
|
||||
>
|
||||
<option value="0">JNO</option>
|
||||
<option value="1">JYES</option>
|
||||
</field>
|
||||
<field
|
||||
name="created"
|
||||
type="hidden"
|
||||
label="COM_WORKFLOW_CREATED_LABEL"
|
||||
readonly="true"
|
||||
/>
|
||||
<field
|
||||
name="modified"
|
||||
type="hidden"
|
||||
label="COM_WORKFLOW_MODIFIED_LABEL"
|
||||
readonly="true"
|
||||
/>
|
||||
</fieldset>
|
||||
|
||||
<fieldset name="permissions" label="JCONFIG_PERMISSIONS_LABEL">
|
||||
<field
|
||||
name="asset_id"
|
||||
type="hidden"
|
||||
filter="unset"
|
||||
/>
|
||||
<field
|
||||
name="rules"
|
||||
type="rules"
|
||||
label="JCONFIG_PERMISSIONS_LABEL"
|
||||
validate="rules"
|
||||
filter="rules"
|
||||
section="workflow"
|
||||
/>
|
||||
</fieldset>
|
||||
</form>
|
||||
51
administrator/components/com_workflow/services/provider.php
Normal file
51
administrator/components/com_workflow/services/provider.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_workflow
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
\defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Dispatcher\ComponentDispatcherFactoryInterface;
|
||||
use Joomla\CMS\Extension\ComponentInterface;
|
||||
use Joomla\CMS\Extension\MVCComponent;
|
||||
use Joomla\CMS\Extension\Service\Provider\ComponentDispatcherFactory;
|
||||
use Joomla\CMS\Extension\Service\Provider\MVCFactory;
|
||||
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
|
||||
use Joomla\DI\Container;
|
||||
use Joomla\DI\ServiceProviderInterface;
|
||||
|
||||
/**
|
||||
* The workflow service provider.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
return new class () implements ServiceProviderInterface {
|
||||
/**
|
||||
* Registers the service provider with a DI container.
|
||||
*
|
||||
* @param Container $container The DI container.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function register(Container $container)
|
||||
{
|
||||
$container->registerServiceProvider(new MVCFactory('\\Joomla\\Component\\Workflow'));
|
||||
$container->registerServiceProvider(new ComponentDispatcherFactory('\\Joomla\\Component\\Workflow'));
|
||||
$container->set(
|
||||
ComponentInterface::class,
|
||||
function (Container $container) {
|
||||
$component = new MVCComponent($container->get(ComponentDispatcherFactoryInterface::class));
|
||||
$component->setMVCFactory($container->get(MVCFactoryInterface::class));
|
||||
|
||||
return $component;
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_workflow
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Workflow\Administrator\Controller;
|
||||
|
||||
use Joomla\CMS\Application\CMSApplication;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Controller\BaseController;
|
||||
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\Input\Input;
|
||||
use Joomla\String\Inflector;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Workflow base controller package.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class DisplayController extends BaseController
|
||||
{
|
||||
/**
|
||||
* The default view.
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $default_view = 'workflows';
|
||||
|
||||
/**
|
||||
* The extension for which the workflow apply.
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $extension;
|
||||
|
||||
/**
|
||||
* The section of the current extension
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $section;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $config An optional associative array of configuration settings.
|
||||
* @param MVCFactoryInterface $factory The factory.
|
||||
* @param CMSApplication $app The Application for the dispatcher
|
||||
* @param Input $input Input
|
||||
*
|
||||
* @since 4.0.0
|
||||
* @throws \InvalidArgumentException when no extension is set
|
||||
*/
|
||||
public function __construct($config = [], MVCFactoryInterface $factory = null, $app = null, $input = null)
|
||||
{
|
||||
parent::__construct($config, $factory, $app, $input);
|
||||
|
||||
// If extension is not set try to get it from input or throw an exception
|
||||
if (empty($this->extension)) {
|
||||
$extension = $this->input->getCmd('extension');
|
||||
|
||||
$parts = explode('.', $extension);
|
||||
|
||||
$this->extension = array_shift($parts);
|
||||
|
||||
if (!empty($parts)) {
|
||||
$this->section = array_shift($parts);
|
||||
}
|
||||
|
||||
if (empty($this->extension)) {
|
||||
throw new \InvalidArgumentException(Text::_('COM_WORKFLOW_ERROR_EXTENSION_NOT_SET'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to display a view.
|
||||
*
|
||||
* @param boolean $cachable If true, the view output will be cached
|
||||
* @param array $urlparams An array of safe URL parameters and their variable types.
|
||||
* @see \Joomla\CMS\Filter\InputFilter::clean() for valid values.
|
||||
*
|
||||
* @return BaseController|boolean This object to support chaining.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public function display($cachable = false, $urlparams = [])
|
||||
{
|
||||
$view = $this->input->get('view');
|
||||
$layout = $this->input->get('layout');
|
||||
$id = $this->input->getInt('id');
|
||||
|
||||
// Check for edit form.
|
||||
if (\in_array($view, ['workflow', 'stage', 'transition']) && $layout == 'edit' && !$this->checkEditId('com_workflow.edit.' . $view, $id)) {
|
||||
// Somehow the person just went to the form - we don't allow that.
|
||||
if (!\count($this->app->getMessageQueue())) {
|
||||
$this->setMessage(Text::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $id), 'error');
|
||||
}
|
||||
|
||||
$url = 'index.php?option=com_workflow&view=' . Inflector::pluralize($view) . '&extension=' . $this->input->getCmd('extension');
|
||||
|
||||
$this->setRedirect(Route::_($url, false));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return parent::display();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,177 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_workflow
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Workflow\Administrator\Controller;
|
||||
|
||||
use Joomla\CMS\Application\CMSApplication;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Controller\FormController;
|
||||
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
|
||||
use Joomla\Input\Input;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* The stage controller
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class StageController extends FormController
|
||||
{
|
||||
/**
|
||||
* The workflow in where the stage belongs to
|
||||
*
|
||||
* @var integer
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $workflowId;
|
||||
|
||||
/**
|
||||
* The extension
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $extension;
|
||||
|
||||
/**
|
||||
* The section of the current extension
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $section;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $config An optional associative array of configuration settings.
|
||||
* @param MVCFactoryInterface $factory The factory.
|
||||
* @param CMSApplication $app The Application for the dispatcher
|
||||
* @param Input $input Input
|
||||
*
|
||||
* @since 4.0.0
|
||||
* @throws \InvalidArgumentException when no extension or workflow id is set
|
||||
*/
|
||||
public function __construct($config = [], MVCFactoryInterface $factory = null, $app = null, $input = null)
|
||||
{
|
||||
parent::__construct($config, $factory, $app, $input);
|
||||
|
||||
// If workflow id is not set try to get it from input or throw an exception
|
||||
if (empty($this->workflowId)) {
|
||||
$this->workflowId = $this->input->getInt('workflow_id');
|
||||
|
||||
if (empty($this->workflowId)) {
|
||||
throw new \InvalidArgumentException(Text::_('COM_WORKFLOW_ERROR_WORKFLOW_ID_NOT_SET'));
|
||||
}
|
||||
}
|
||||
|
||||
// If extension is not set try to get it from input or throw an exception
|
||||
if (empty($this->extension)) {
|
||||
$extension = $this->input->getCmd('extension');
|
||||
|
||||
$parts = explode('.', $extension);
|
||||
|
||||
$this->extension = array_shift($parts);
|
||||
|
||||
if (!empty($parts)) {
|
||||
$this->section = array_shift($parts);
|
||||
}
|
||||
|
||||
if (empty($this->extension)) {
|
||||
throw new \InvalidArgumentException(Text::_('COM_WORKFLOW_ERROR_EXTENSION_NOT_SET'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to check if you can add a new record.
|
||||
*
|
||||
* @param array $data An array of input data.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function allowAdd($data = [])
|
||||
{
|
||||
return $this->app->getIdentity()->authorise('core.create', $this->extension . '.workflow.' . (int) $this->workflowId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to check if you can edit a record.
|
||||
*
|
||||
* @param array $data An array of input data.
|
||||
* @param string $key The name of the key for the primary key.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function allowEdit($data = [], $key = 'id')
|
||||
{
|
||||
$recordId = isset($data[$key]) ? (int) $data[$key] : 0;
|
||||
$user = $this->app->getIdentity();
|
||||
|
||||
$record = $this->getModel()->getItem($recordId);
|
||||
|
||||
if (empty($record->id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check "edit" permission on record asset (explicit or inherited)
|
||||
if ($user->authorise('core.edit', $this->extension . '.stage.' . $recordId)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check "edit own" permission on record asset (explicit or inherited)
|
||||
if ($user->authorise('core.edit.own', $this->extension . '.stage.' . $recordId)) {
|
||||
return !empty($record) && $record->created_by == $user->id;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the URL arguments to append to an item redirect.
|
||||
*
|
||||
* @param integer $recordId The primary key id for the item.
|
||||
* @param string $urlVar The name of the URL variable for the id.
|
||||
*
|
||||
* @return string The arguments to append to the redirect URL.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function getRedirectToItemAppend($recordId = null, $urlVar = 'id')
|
||||
{
|
||||
$append = parent::getRedirectToItemAppend($recordId);
|
||||
|
||||
$append .= '&workflow_id=' . $this->workflowId . '&extension=' . $this->extension . ($this->section ? '.' . $this->section : '');
|
||||
|
||||
return $append;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the URL arguments to append to a list redirect.
|
||||
*
|
||||
* @return string The arguments to append to the redirect URL.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function getRedirectToListAppend()
|
||||
{
|
||||
$append = parent::getRedirectToListAppend();
|
||||
$append .= '&workflow_id=' . $this->workflowId . '&extension=' . $this->extension . ($this->section ? '.' . $this->section : '');
|
||||
|
||||
return $append;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,198 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_workflow
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Workflow\Administrator\Controller;
|
||||
|
||||
use Joomla\CMS\Application\CMSApplication;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Controller\AdminController;
|
||||
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\Input\Input;
|
||||
use Joomla\Utilities\ArrayHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* The workflow stages controller
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class StagesController extends AdminController
|
||||
{
|
||||
/**
|
||||
* The workflow in where the stage belongs to
|
||||
*
|
||||
* @var integer
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $workflowId;
|
||||
|
||||
/**
|
||||
* The extension
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $extension;
|
||||
|
||||
/**
|
||||
* The section of the current extension
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $section;
|
||||
|
||||
/**
|
||||
* The prefix to use with controller messages.
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $text_prefix = 'COM_WORKFLOW_STAGES';
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $config An optional associative array of configuration settings.
|
||||
* @param MVCFactoryInterface $factory The factory.
|
||||
* @param CMSApplication $app The Application for the dispatcher
|
||||
* @param Input $input Input
|
||||
*
|
||||
* @since 4.0.0
|
||||
* @throws \InvalidArgumentException when no extension or workflow id is set
|
||||
*/
|
||||
public function __construct(array $config = [], MVCFactoryInterface $factory = null, $app = null, $input = null)
|
||||
{
|
||||
parent::__construct($config, $factory, $app, $input);
|
||||
|
||||
// If workflow id is not set try to get it from input or throw an exception
|
||||
if (empty($this->workflowId)) {
|
||||
$this->workflowId = $this->input->getInt('workflow_id');
|
||||
|
||||
if (empty($this->workflowId)) {
|
||||
throw new \InvalidArgumentException(Text::_('COM_WORKFLOW_ERROR_WORKFLOW_ID_NOT_SET'));
|
||||
}
|
||||
}
|
||||
|
||||
// If extension is not set try to get it from input or throw an exception
|
||||
if (empty($this->extension)) {
|
||||
$extension = $this->input->getCmd('extension');
|
||||
|
||||
$parts = explode('.', $extension);
|
||||
|
||||
$this->extension = array_shift($parts);
|
||||
|
||||
if (!empty($parts)) {
|
||||
$this->section = array_shift($parts);
|
||||
}
|
||||
|
||||
if (empty($this->extension)) {
|
||||
throw new \InvalidArgumentException(Text::_('COM_WORKFLOW_ERROR_EXTENSION_NOT_SET'));
|
||||
}
|
||||
}
|
||||
|
||||
$this->registerTask('unsetDefault', 'setDefault');
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy for getModel
|
||||
*
|
||||
* @param string $name The model name. Optional.
|
||||
* @param string $prefix The class prefix. Optional.
|
||||
* @param array $config The array of possible config values. Optional.
|
||||
*
|
||||
* @return \Joomla\CMS\MVC\Model\BaseDatabaseModel The model.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function getModel($name = 'Stage', $prefix = 'Administrator', $config = ['ignore_request' => true])
|
||||
{
|
||||
return parent::getModel($name, $prefix, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to set the home property for a list of items
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function setDefault()
|
||||
{
|
||||
// Check for request forgeries
|
||||
$this->checkToken();
|
||||
|
||||
// Get items to publish from the request.
|
||||
$cid = (array) $this->input->get('cid', [], 'int');
|
||||
$data = ['setDefault' => 1, 'unsetDefault' => 0];
|
||||
$task = $this->getTask();
|
||||
$value = ArrayHelper::getValue($data, $task, 0, 'int');
|
||||
|
||||
if (!$value) {
|
||||
$this->setMessage(Text::_('COM_WORKFLOW_DISABLE_DEFAULT'), 'warning');
|
||||
$this->setRedirect(
|
||||
Route::_(
|
||||
'index.php?option=' . $this->option . '&view=' . $this->view_list
|
||||
. '&extension=' . $this->extension,
|
||||
false
|
||||
)
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove zero values resulting from input filter
|
||||
$cid = array_filter($cid);
|
||||
|
||||
if (empty($cid)) {
|
||||
$this->setMessage(Text::_('COM_WORKFLOW_NO_ITEM_SELECTED'), 'warning');
|
||||
} elseif (\count($cid) > 1) {
|
||||
$this->setMessage(Text::_('COM_WORKFLOW_TOO_MANY_STAGES'), 'error');
|
||||
} else {
|
||||
// Get the model.
|
||||
$model = $this->getModel();
|
||||
|
||||
// Make sure the item ids are integers
|
||||
$id = reset($cid);
|
||||
|
||||
// Publish the items.
|
||||
if (!$model->setDefault($id, $value)) {
|
||||
$this->setMessage($model->getError(), 'warning');
|
||||
} else {
|
||||
$this->setMessage(Text::_('COM_WORKFLOW_STAGE_SET_DEFAULT'));
|
||||
}
|
||||
}
|
||||
|
||||
$this->setRedirect(
|
||||
Route::_(
|
||||
'index.php?option=' . $this->option . '&view=' . $this->view_list
|
||||
. '&extension=' . $this->extension
|
||||
. '&workflow_id=' . $this->workflowId,
|
||||
false
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the URL arguments to append to a list redirect.
|
||||
*
|
||||
* @return string The arguments to append to the redirect URL.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function getRedirectToListAppend()
|
||||
{
|
||||
return '&extension=' . $this->extension . ($this->section ? '.' . $this->section : '') . '&workflow_id=' . $this->workflowId;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,178 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_workflow
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Workflow\Administrator\Controller;
|
||||
|
||||
use Joomla\CMS\Application\CMSApplication;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Controller\FormController;
|
||||
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
|
||||
use Joomla\Input\Input;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Transition controller
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class TransitionController extends FormController
|
||||
{
|
||||
/**
|
||||
* The workflow where the transition takes place
|
||||
*
|
||||
* @var integer
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $workflowId;
|
||||
|
||||
/**
|
||||
* The extension
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $extension;
|
||||
|
||||
/**
|
||||
* The section of the current extension
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $section;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $config An optional associative array of configuration settings.
|
||||
* @param MVCFactoryInterface $factory The factory.
|
||||
* @param CMSApplication $app The Application for the dispatcher
|
||||
* @param Input $input Input
|
||||
*
|
||||
* @since 4.0.0
|
||||
* @throws \InvalidArgumentException when no extension or workflow id is set
|
||||
*/
|
||||
public function __construct($config = [], MVCFactoryInterface $factory = null, $app = null, $input = null)
|
||||
{
|
||||
parent::__construct($config, $factory, $app, $input);
|
||||
|
||||
// If workflow id is not set try to get it from input or throw an exception
|
||||
if (empty($this->workflowId)) {
|
||||
$this->workflowId = $this->input->getInt('workflow_id');
|
||||
|
||||
if (empty($this->workflowId)) {
|
||||
throw new \InvalidArgumentException(Text::_('COM_WORKFLOW_ERROR_WORKFLOW_ID_NOT_SET'));
|
||||
}
|
||||
}
|
||||
|
||||
// If extension is not set try to get it from input or throw an exception
|
||||
if (empty($this->extension)) {
|
||||
$extension = $this->input->getCmd('extension');
|
||||
|
||||
$parts = explode('.', $extension);
|
||||
|
||||
$this->extension = array_shift($parts);
|
||||
|
||||
if (!empty($parts)) {
|
||||
$this->section = array_shift($parts);
|
||||
}
|
||||
|
||||
if (empty($this->extension)) {
|
||||
throw new \InvalidArgumentException(Text::_('COM_WORKFLOW_ERROR_EXTENSION_NOT_SET'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to check if you can add a new record.
|
||||
*
|
||||
* @param array $data An array of input data.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function allowAdd($data = [])
|
||||
{
|
||||
return $this->app->getIdentity()->authorise('core.create', $this->extension . '.workflow.' . (int) $this->workflowId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to check if you can edit a record.
|
||||
*
|
||||
* @param array $data An array of input data.
|
||||
* @param string $key The name of the key for the primary key.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function allowEdit($data = [], $key = 'id')
|
||||
{
|
||||
$recordId = isset($data[$key]) ? (int) $data[$key] : 0;
|
||||
$user = $this->app->getIdentity();
|
||||
|
||||
$model = $this->getModel();
|
||||
|
||||
$item = $model->getItem($recordId);
|
||||
|
||||
if (empty($item->id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check "edit" permission on record asset (explicit or inherited)
|
||||
if ($user->authorise('core.edit', $this->extension . '.transition.' . $recordId)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check "edit own" permission on record asset (explicit or inherited)
|
||||
if ($user->authorise('core.edit.own', $this->extension . '.transition.' . $recordId)) {
|
||||
return !empty($item) && $item->created_by == $user->id;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the URL arguments to append to an item redirect.
|
||||
*
|
||||
* @param integer $recordId The primary key id for the item.
|
||||
* @param string $urlVar The name of the URL variable for the id.
|
||||
*
|
||||
* @return string The arguments to append to the redirect URL.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function getRedirectToItemAppend($recordId = null, $urlVar = 'id')
|
||||
{
|
||||
$append = parent::getRedirectToItemAppend($recordId);
|
||||
$append .= '&workflow_id=' . $this->workflowId . '&extension=' . $this->extension;
|
||||
|
||||
return $append;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the URL arguments to append to a list redirect.
|
||||
*
|
||||
* @return string The arguments to append to the redirect URL.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function getRedirectToListAppend()
|
||||
{
|
||||
$append = parent::getRedirectToListAppend();
|
||||
$append .= '&workflow_id=' . $this->workflowId . '&extension=' . $this->extension;
|
||||
|
||||
return $append;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,136 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_workflow
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Workflow\Administrator\Controller;
|
||||
|
||||
use Joomla\CMS\Application\CMSApplication;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Controller\AdminController;
|
||||
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
|
||||
use Joomla\Input\Input;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Workflow Transitions controller
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class TransitionsController extends AdminController
|
||||
{
|
||||
/**
|
||||
* The workflow where the transition takes place
|
||||
*
|
||||
* @var integer
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $workflowId;
|
||||
|
||||
/**
|
||||
* The extension
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $extension;
|
||||
|
||||
/**
|
||||
* The section of the current extension
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $section;
|
||||
|
||||
/**
|
||||
* The prefix to use with controller messages.
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $text_prefix = 'COM_WORKFLOW_TRANSITIONS';
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $config An optional associative array of configuration settings.
|
||||
* @param MVCFactoryInterface $factory The factory.
|
||||
* @param CMSApplication $app The Application for the dispatcher
|
||||
* @param Input $input Input
|
||||
*
|
||||
* @since 4.0.0
|
||||
* @throws \InvalidArgumentException when no extension or workflow id is set
|
||||
*/
|
||||
public function __construct($config = [], MVCFactoryInterface $factory = null, $app = null, $input = null)
|
||||
{
|
||||
parent::__construct($config, $factory, $app, $input);
|
||||
|
||||
// If workflow id is not set try to get it from input or throw an exception
|
||||
if (empty($this->workflowId)) {
|
||||
$this->workflowId = $this->input->getInt('workflow_id');
|
||||
|
||||
if (empty($this->workflowId)) {
|
||||
throw new \InvalidArgumentException(Text::_('COM_WORKFLOW_ERROR_WORKFLOW_ID_NOT_SET'));
|
||||
}
|
||||
}
|
||||
|
||||
// If extension is not set try to get it from input or throw an exception
|
||||
if (empty($this->extension)) {
|
||||
$extension = $this->input->getCmd('extension');
|
||||
|
||||
$parts = explode('.', $extension);
|
||||
|
||||
$this->extension = array_shift($parts);
|
||||
|
||||
if (!empty($parts)) {
|
||||
$this->section = array_shift($parts);
|
||||
}
|
||||
|
||||
if (empty($this->extension)) {
|
||||
throw new \InvalidArgumentException(Text::_('COM_WORKFLOW_ERROR_EXTENSION_NOT_SET'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy for getModel
|
||||
*
|
||||
* @param string $name The model name. Optional.
|
||||
* @param string $prefix The class prefix. Optional.
|
||||
* @param array $config The array of possible config values. Optional.
|
||||
*
|
||||
* @return \Joomla\CMS\MVC\Model\BaseDatabaseModel The model.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function getModel($name = 'Transition', $prefix = 'Administrator', $config = ['ignore_request' => true])
|
||||
{
|
||||
return parent::getModel($name, $prefix, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the URL arguments to append to a list redirect.
|
||||
*
|
||||
* @return string The arguments to append to the redirect URL.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function getRedirectToListAppend()
|
||||
{
|
||||
$append = parent::getRedirectToListAppend();
|
||||
|
||||
$append .= '&extension=' . $this->extension . ($this->section ? '.' . $this->section : '')
|
||||
. '&workflow_id=' . $this->workflowId;
|
||||
|
||||
return $append;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,242 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_workflow
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Workflow\Administrator\Controller;
|
||||
|
||||
use Joomla\CMS\Application\CMSApplication;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Controller\FormController;
|
||||
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
|
||||
use Joomla\CMS\MVC\Model\BaseDatabaseModel;
|
||||
use Joomla\Database\ParameterType;
|
||||
use Joomla\Input\Input;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Workflow controller
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class WorkflowController extends FormController
|
||||
{
|
||||
/**
|
||||
* The extension for which the workflows apply.
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $extension;
|
||||
|
||||
/**
|
||||
* The section of the current extension
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $section;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $config An optional associative array of configuration settings.
|
||||
* @param MVCFactoryInterface $factory The factory.
|
||||
* @param CMSApplication $app The Application for the dispatcher
|
||||
* @param Input $input Input
|
||||
*
|
||||
* @since 4.0.0
|
||||
* @throws \InvalidArgumentException when no extension is set
|
||||
*/
|
||||
public function __construct($config = [], MVCFactoryInterface $factory = null, $app = null, $input = null)
|
||||
{
|
||||
parent::__construct($config, $factory, $app, $input);
|
||||
|
||||
// If extension is not set try to get it from input or throw an exception
|
||||
if (empty($this->extension)) {
|
||||
$extension = $this->input->getCmd('extension');
|
||||
|
||||
$parts = explode('.', $extension);
|
||||
|
||||
$this->extension = array_shift($parts);
|
||||
|
||||
if (!empty($parts)) {
|
||||
$this->section = array_shift($parts);
|
||||
}
|
||||
|
||||
if (empty($this->extension)) {
|
||||
throw new \InvalidArgumentException(Text::_('COM_WORKFLOW_ERROR_EXTENSION_NOT_SET'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to check if you can add a new record.
|
||||
*
|
||||
* @param array $data An array of input data.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function allowAdd($data = [])
|
||||
{
|
||||
return $this->app->getIdentity()->authorise('core.create', $this->extension);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to check if you can edit a record.
|
||||
*
|
||||
* @param array $data An array of input data.
|
||||
* @param string $key The name of the key for the primary key.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function allowEdit($data = [], $key = 'id')
|
||||
{
|
||||
$recordId = isset($data[$key]) ? (int) $data[$key] : 0;
|
||||
$user = $this->app->getIdentity();
|
||||
|
||||
$record = $this->getModel()->getItem($recordId);
|
||||
|
||||
if (empty($record->id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check "edit" permission on record asset (explicit or inherited)
|
||||
if ($user->authorise('core.edit', $this->extension . '.workflow.' . $recordId)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check "edit own" permission on record asset (explicit or inherited)
|
||||
if ($user->authorise('core.edit.own', $this->extension . '.workflow.' . $recordId)) {
|
||||
return !empty($record) && $record->created_by == $user->id;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the URL arguments to append to an item redirect.
|
||||
*
|
||||
* @param integer $recordId The primary key id for the item.
|
||||
* @param string $urlVar The name of the URL variable for the id.
|
||||
*
|
||||
* @return string The arguments to append to the redirect URL.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function getRedirectToItemAppend($recordId = null, $urlVar = 'id')
|
||||
{
|
||||
$append = parent::getRedirectToItemAppend($recordId);
|
||||
$append .= '&extension=' . $this->extension . ($this->section ? '.' . $this->section : '');
|
||||
|
||||
return $append;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the URL arguments to append to a list redirect.
|
||||
*
|
||||
* @return string The arguments to append to the redirect URL.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function getRedirectToListAppend()
|
||||
{
|
||||
$append = parent::getRedirectToListAppend();
|
||||
$append .= '&extension=' . $this->extension . ($this->section ? '.' . $this->section : '');
|
||||
|
||||
return $append;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function that allows child controller access to model data
|
||||
* after the data has been saved.
|
||||
*
|
||||
* @param BaseDatabaseModel $model The data model object.
|
||||
* @param array $validData The validated data.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function postSaveHook(BaseDatabaseModel $model, $validData = [])
|
||||
{
|
||||
$task = $this->getTask();
|
||||
|
||||
// The save2copy task needs to be handled slightly differently.
|
||||
if ($task === 'save2copy') {
|
||||
$table = $model->getTable();
|
||||
|
||||
$key = $table->getKeyName();
|
||||
|
||||
$recordId = (int) $this->input->getInt($key);
|
||||
|
||||
// @todo Moves queries out of the controller.
|
||||
$db = $model->getDbo();
|
||||
$query = $db->getQuery(true);
|
||||
|
||||
$query->select('*')
|
||||
->from($db->quoteName('#__workflow_stages'))
|
||||
->where($db->quoteName('workflow_id') . ' = :id')
|
||||
->bind(':id', $recordId, ParameterType::INTEGER);
|
||||
|
||||
$statuses = $db->setQuery($query)->loadAssocList();
|
||||
|
||||
$smodel = $this->getModel('Stage');
|
||||
|
||||
$workflowID = (int) $model->getState($model->getName() . '.id');
|
||||
|
||||
$mapping = [];
|
||||
|
||||
foreach ($statuses as $status) {
|
||||
$table = $smodel->getTable();
|
||||
|
||||
$oldID = $status['id'];
|
||||
|
||||
$status['workflow_id'] = $workflowID;
|
||||
$status['id'] = 0;
|
||||
|
||||
unset($status['asset_id']);
|
||||
|
||||
$table->save($status);
|
||||
|
||||
$mapping[$oldID] = (int) $table->id;
|
||||
}
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->select('*')
|
||||
->from($db->quoteName('#__workflow_transitions'))
|
||||
->where($db->quoteName('workflow_id') . ' = :id')
|
||||
->bind(':id', $recordId, ParameterType::INTEGER);
|
||||
|
||||
$transitions = $db->setQuery($query)->loadAssocList();
|
||||
|
||||
$tmodel = $this->getModel('Transition');
|
||||
|
||||
foreach ($transitions as $transition) {
|
||||
$table = $tmodel->getTable();
|
||||
|
||||
$transition['from_stage_id'] = $transition['from_stage_id'] != -1 ? $mapping[$transition['from_stage_id']] : -1;
|
||||
$transition['to_stage_id'] = $mapping[$transition['to_stage_id']];
|
||||
|
||||
$transition['workflow_id'] = $workflowID;
|
||||
$transition['id'] = 0;
|
||||
|
||||
unset($transition['asset_id']);
|
||||
|
||||
$table->save($transition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,178 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_workflow
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Workflow\Administrator\Controller;
|
||||
|
||||
use Joomla\CMS\Application\CMSApplication;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Controller\AdminController;
|
||||
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\Input\Input;
|
||||
use Joomla\Utilities\ArrayHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Workflows controller
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class WorkflowsController extends AdminController
|
||||
{
|
||||
/**
|
||||
* The extension for which the workflows apply.
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $extension;
|
||||
|
||||
/**
|
||||
* The section of the current extension
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $section;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $config An optional associative array of configuration settings.
|
||||
* @param MVCFactoryInterface $factory The factory.
|
||||
* @param CMSApplication $app The Application for the dispatcher
|
||||
* @param Input $input Input
|
||||
*
|
||||
* @since 4.0.0
|
||||
* @throws \InvalidArgumentException when no extension is set
|
||||
*/
|
||||
public function __construct($config = [], MVCFactoryInterface $factory = null, $app = null, $input = null)
|
||||
{
|
||||
parent::__construct($config, $factory, $app, $input);
|
||||
|
||||
// If extension is not set try to get it from input or throw an exception
|
||||
if (empty($this->extension)) {
|
||||
$extension = $this->input->getCmd('extension');
|
||||
|
||||
$parts = explode('.', $extension);
|
||||
|
||||
$this->extension = array_shift($parts);
|
||||
|
||||
if (!empty($parts)) {
|
||||
$this->section = array_shift($parts);
|
||||
}
|
||||
|
||||
if (empty($this->extension)) {
|
||||
throw new \InvalidArgumentException(Text::_('COM_WORKFLOW_ERROR_EXTENSION_NOT_SET'));
|
||||
}
|
||||
}
|
||||
|
||||
$this->registerTask('unsetDefault', 'setDefault');
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy for getModel
|
||||
*
|
||||
* @param string $name The model name. Optional.
|
||||
* @param string $prefix The class prefix. Optional.
|
||||
* @param array $config The array of possible config values. Optional.
|
||||
*
|
||||
* @return \Joomla\CMS\MVC\Model\BaseDatabaseModel The model.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function getModel($name = 'Workflow', $prefix = 'Administrator', $config = ['ignore_request' => true])
|
||||
{
|
||||
return parent::getModel($name, $prefix, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to set the home property for a list of items
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function setDefault()
|
||||
{
|
||||
// Check for request forgeries
|
||||
$this->checkToken();
|
||||
|
||||
// Get items to publish from the request.
|
||||
$cid = (array) $this->input->get('cid', [], 'int');
|
||||
$data = ['setDefault' => 1, 'unsetDefault' => 0];
|
||||
$task = $this->getTask();
|
||||
$value = ArrayHelper::getValue($data, $task, 0, 'int');
|
||||
|
||||
if (!$value) {
|
||||
$this->setMessage(Text::_('COM_WORKFLOW_DISABLE_DEFAULT'), 'warning');
|
||||
$this->setRedirect(
|
||||
Route::_(
|
||||
'index.php?option=' . $this->option . '&view=' . $this->view_list
|
||||
. '&extension=' . $this->extension . ($this->section ? '.' . $this->section : ''),
|
||||
false
|
||||
)
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove zero values resulting from input filter
|
||||
$cid = array_filter($cid);
|
||||
|
||||
if (empty($cid)) {
|
||||
$this->setMessage(Text::_('COM_WORKFLOW_NO_ITEM_SELECTED'), 'warning');
|
||||
} elseif (\count($cid) > 1) {
|
||||
$this->setMessage(Text::_('COM_WORKFLOW_TOO_MANY_WORKFLOWS'), 'error');
|
||||
} else {
|
||||
// Get the model.
|
||||
$model = $this->getModel();
|
||||
|
||||
// Make sure the item ids are integers
|
||||
$id = reset($cid);
|
||||
|
||||
// Publish the items.
|
||||
if (!$model->setDefault($id, $value)) {
|
||||
$this->setMessage($model->getError(), 'warning');
|
||||
} else {
|
||||
if ($value === 1) {
|
||||
$ntext = 'COM_WORKFLOW_SET_DEFAULT';
|
||||
} else {
|
||||
$ntext = 'COM_WORKFLOW_ITEM_UNSET_DEFAULT';
|
||||
}
|
||||
|
||||
$this->setMessage(Text::_($ntext, \count($cid)));
|
||||
}
|
||||
}
|
||||
|
||||
$this->setRedirect(
|
||||
Route::_(
|
||||
'index.php?option=' . $this->option . '&view=' . $this->view_list
|
||||
. '&extension=' . $this->extension . ($this->section ? '.' . $this->section : ''),
|
||||
false
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the URL arguments to append to a list redirect.
|
||||
*
|
||||
* @return string The arguments to append to the redirect URL.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function getRedirectToListAppend()
|
||||
{
|
||||
return '&extension=' . $this->extension . ($this->section ? '.' . $this->section : '');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_workflow
|
||||
*
|
||||
* @copyright (C) 2019 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Workflow\Administrator\Dispatcher;
|
||||
|
||||
use Joomla\CMS\Access\Exception\NotAllowed;
|
||||
use Joomla\CMS\Dispatcher\ComponentDispatcher;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* ComponentDispatcher class for com_workflow
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class Dispatcher extends ComponentDispatcher
|
||||
{
|
||||
/**
|
||||
* Workflows have to check for extension permission
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function checkAccess()
|
||||
{
|
||||
$extension = $this->getApplication()->getInput()->getCmd('extension');
|
||||
|
||||
$parts = explode('.', $extension);
|
||||
|
||||
// Check the user has permission to access this component if in the backend
|
||||
if ($this->app->isClient('administrator') && !$this->app->getIdentity()->authorise('core.manage.workflow', $parts[0])) {
|
||||
throw new NotAllowed($this->app->getLanguage()->_('JERROR_ALERTNOAUTHOR'), 403);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_workflow
|
||||
*
|
||||
* @copyright (C) 2019 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Workflow\Administrator\Field;
|
||||
|
||||
use Joomla\CMS\Access\Access;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Form\Field\ListField;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Workflow\WorkflowServiceInterface;
|
||||
use Joomla\Utilities\ArrayHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Components Workflow field.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class ComponentsWorkflowField extends ListField
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
* @since 3.7.0
|
||||
*/
|
||||
protected $type = 'ComponentsWorkflow';
|
||||
|
||||
/**
|
||||
* Method to get a list of options for a list input.
|
||||
*
|
||||
* @return array An array of JHtml options.
|
||||
*
|
||||
* @since 3.7.0
|
||||
*/
|
||||
protected function getOptions()
|
||||
{
|
||||
// Initialise variable.
|
||||
$db = $this->getDatabase();
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->select('DISTINCT a.name AS text, a.element AS value')
|
||||
->from('#__extensions as a')
|
||||
->where('a.enabled >= 1')
|
||||
->where('a.type =' . $db->quote('component'));
|
||||
|
||||
$items = $db->setQuery($query)->loadObjectList();
|
||||
|
||||
$options = [];
|
||||
|
||||
if (\count($items)) {
|
||||
$lang = Factory::getLanguage();
|
||||
|
||||
$components = [];
|
||||
|
||||
// Search for components supporting Fieldgroups - suppose that these components support fields as well
|
||||
foreach ($items as &$item) {
|
||||
$availableActions = Access::getActionsFromFile(
|
||||
JPATH_ADMINISTRATOR . '/components/' . $item->value . '/access.xml',
|
||||
"/access/section[@name='workflow']/"
|
||||
);
|
||||
|
||||
if (!empty($availableActions)) {
|
||||
// Load language
|
||||
$source = JPATH_ADMINISTRATOR . '/components/' . $item->value;
|
||||
$lang->load($item->value . 'sys', JPATH_ADMINISTRATOR)
|
||||
|| $lang->load($item->value . 'sys', $source);
|
||||
|
||||
// Translate component name
|
||||
$item->text = Text::_($item->text);
|
||||
|
||||
$components[] = $item;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($components)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
foreach ($components as $component) {
|
||||
// Search for different contexts
|
||||
$c = Factory::getApplication()->bootComponent($component->value);
|
||||
|
||||
if ($c instanceof WorkflowServiceInterface) {
|
||||
$contexts = $c->getContexts();
|
||||
|
||||
foreach ($contexts as $context) {
|
||||
$newOption = new \stdClass();
|
||||
$newOption->value = strtolower($component->value . '.' . $context);
|
||||
$newOption->text = $component->text . ' - ' . Text::_($context);
|
||||
$options[] = $newOption;
|
||||
}
|
||||
} else {
|
||||
$options[] = $component;
|
||||
}
|
||||
}
|
||||
|
||||
// Sort by name
|
||||
$items = ArrayHelper::sortObjects($options, 'text', 1, true, true);
|
||||
}
|
||||
|
||||
// Merge any additional options in the XML definition.
|
||||
$options = array_merge(parent::getOptions(), $items);
|
||||
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_workflow
|
||||
*
|
||||
* @copyright (C) 2020 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Workflow\Administrator\Field;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Form\Field\ListField;
|
||||
use Joomla\CMS\Workflow\WorkflowServiceInterface;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Fields Contexts
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class WorkflowcontextsField extends ListField
|
||||
{
|
||||
/**
|
||||
* Type of the field
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $type = 'Workflowcontexts';
|
||||
|
||||
/**
|
||||
* Method to get the field input markup for a generic list.
|
||||
* Use the multiple attribute to enable multiselect.
|
||||
*
|
||||
* @return string The field input markup.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function getInput()
|
||||
{
|
||||
if (\count($this->getOptions()) < 2) {
|
||||
$this->layout = 'joomla.form.field.hidden';
|
||||
}
|
||||
|
||||
return parent::getInput();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the field options.
|
||||
*
|
||||
* @return array The field option objects.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function getOptions()
|
||||
{
|
||||
$parts = explode('.', $this->value);
|
||||
|
||||
$component = Factory::getApplication()->bootComponent($parts[0]);
|
||||
|
||||
if ($component instanceof WorkflowServiceInterface) {
|
||||
return $component->getWorkflowContexts();
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_workflow
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Workflow\Administrator\Helper;
|
||||
|
||||
use Joomla\CMS\Helper\ContentHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* The first example class, this is in the same
|
||||
* package as declared at the start of file but
|
||||
* this example has a defined subpackage
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class StageHelper extends ContentHelper
|
||||
{
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_workflow
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Workflow\Administrator\Helper;
|
||||
|
||||
use Joomla\CMS\Helper\ContentHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Workflows component helper
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class WorkflowHelper extends ContentHelper
|
||||
{
|
||||
}
|
||||
373
administrator/components/com_workflow/src/Model/StageModel.php
Normal file
373
administrator/components/com_workflow/src/Model/StageModel.php
Normal file
@ -0,0 +1,373 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_workflow
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
* @since 4.0.0
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Workflow\Administrator\Model;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Form\Form;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Log\Log;
|
||||
use Joomla\CMS\MVC\Model\AdminModel;
|
||||
use Joomla\String\StringHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Model class for stage
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class StageModel extends AdminModel
|
||||
{
|
||||
/**
|
||||
* Auto-populate the model state.
|
||||
*
|
||||
* Note. Calling getState in this method will result in recursion.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function populateState()
|
||||
{
|
||||
parent::populateState();
|
||||
|
||||
$app = Factory::getApplication();
|
||||
$context = $this->option . '.' . $this->name;
|
||||
$extension = $app->getUserStateFromRequest($context . '.filter.extension', 'extension', null, 'cmd');
|
||||
|
||||
$this->setState('filter.extension', $extension);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to change the title
|
||||
*
|
||||
* @param integer $categoryId The id of the category.
|
||||
* @param string $alias The alias.
|
||||
* @param string $title The title.
|
||||
*
|
||||
* @return array Contains the modified title and alias.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function generateNewTitle($categoryId, $alias, $title)
|
||||
{
|
||||
// Alter the title & alias
|
||||
$table = $this->getTable();
|
||||
|
||||
while ($table->load(['title' => $title])) {
|
||||
$title = StringHelper::increment($title);
|
||||
}
|
||||
|
||||
return [$title, $alias];
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to save the form data.
|
||||
*
|
||||
* @param array $data The form data.
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function save($data)
|
||||
{
|
||||
$table = $this->getTable();
|
||||
$context = $this->option . '.' . $this->name;
|
||||
$app = Factory::getApplication();
|
||||
$user = $app->getIdentity();
|
||||
$input = $app->getInput();
|
||||
$workflowID = $app->getUserStateFromRequest($context . '.filter.workflow_id', 'workflow_id', 0, 'int');
|
||||
|
||||
if (empty($data['workflow_id'])) {
|
||||
$data['workflow_id'] = $workflowID;
|
||||
}
|
||||
|
||||
$workflow = $this->getTable('Workflow');
|
||||
|
||||
$workflow->load($data['workflow_id']);
|
||||
|
||||
$parts = explode('.', $workflow->extension);
|
||||
|
||||
if (isset($data['rules']) && !$user->authorise('core.admin', $parts[0])) {
|
||||
unset($data['rules']);
|
||||
}
|
||||
|
||||
// Make sure we use the correct extension when editing an existing workflow
|
||||
$key = $table->getKeyName();
|
||||
$pk = (isset($data[$key])) ? $data[$key] : (int) $this->getState($this->getName() . '.id');
|
||||
|
||||
if ($pk > 0) {
|
||||
$table->load($pk);
|
||||
|
||||
if ((int) $table->workflow_id) {
|
||||
$data['workflow_id'] = (int) $table->workflow_id;
|
||||
}
|
||||
}
|
||||
|
||||
if ($input->get('task') == 'save2copy') {
|
||||
$origTable = clone $this->getTable();
|
||||
|
||||
// Alter the title for save as copy
|
||||
if ($origTable->load(['title' => $data['title']])) {
|
||||
list($title) = $this->generateNewTitle(0, '', $data['title']);
|
||||
$data['title'] = $title;
|
||||
}
|
||||
|
||||
$data['published'] = 0;
|
||||
$data['default'] = 0;
|
||||
}
|
||||
|
||||
return parent::save($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to test whether a record can be deleted.
|
||||
*
|
||||
* @param object $record A record object.
|
||||
*
|
||||
* @return boolean True if allowed to delete the record. Defaults to the permission for the component.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function canDelete($record)
|
||||
{
|
||||
$table = $this->getTable('Workflow', 'Administrator');
|
||||
|
||||
$table->load($record->workflow_id);
|
||||
|
||||
if (empty($record->id) || $record->published != -2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$app = Factory::getApplication();
|
||||
$extension = $app->getUserStateFromRequest('com_workflow.stage.filter.extension', 'extension', null, 'cmd');
|
||||
|
||||
$parts = explode('.', $extension);
|
||||
|
||||
$component = reset($parts);
|
||||
|
||||
if (!$this->getCurrentUser()->authorise('core.delete', $component . '.state.' . (int) $record->id) || $record->default) {
|
||||
$this->setError(Text::_('JLIB_APPLICATION_ERROR_DELETE_NOT_PERMITTED'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to test whether a record can have its state changed.
|
||||
*
|
||||
* @param object $record A record object.
|
||||
*
|
||||
* @return boolean True if allowed to change the state of the record. Defaults to the permission set in the component.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function canEditState($record)
|
||||
{
|
||||
$user = $this->getCurrentUser();
|
||||
$app = Factory::getApplication();
|
||||
$context = $this->option . '.' . $this->name;
|
||||
$extension = $app->getUserStateFromRequest($context . '.filter.extension', 'extension', null, 'cmd');
|
||||
|
||||
if (!property_exists($record, 'workflow_id')) {
|
||||
$workflowID = $app->getUserStateFromRequest($context . '.filter.workflow_id', 'workflow_id', 0, 'int');
|
||||
$record->workflow_id = $workflowID;
|
||||
}
|
||||
|
||||
// Check for existing workflow.
|
||||
if (!empty($record->id)) {
|
||||
return $user->authorise('core.edit.state', $extension . '.state.' . (int) $record->id);
|
||||
}
|
||||
|
||||
// Default to component settings if workflow isn't known.
|
||||
return $user->authorise('core.edit.state', $extension);
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract method for getting the form from the model.
|
||||
*
|
||||
* @param array $data Data for the form.
|
||||
* @param boolean $loadData True if the form is to load its own data (default case), false if not.
|
||||
*
|
||||
* @return Form|boolean A Form object on success, false on failure
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function getForm($data = [], $loadData = true)
|
||||
{
|
||||
// Get the form.
|
||||
$form = $this->loadForm(
|
||||
'com_workflow.state',
|
||||
'stage',
|
||||
[
|
||||
'control' => 'jform',
|
||||
'load_data' => $loadData,
|
||||
]
|
||||
);
|
||||
|
||||
if (empty($form)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$id = $data['id'] ?? $form->getValue('id');
|
||||
|
||||
$item = $this->getItem($id);
|
||||
|
||||
$canEditState = $this->canEditState((object) $item);
|
||||
|
||||
// Modify the form based on access controls.
|
||||
if (!$canEditState || !empty($item->default)) {
|
||||
if (!$canEditState) {
|
||||
$form->setFieldAttribute('published', 'disabled', 'true');
|
||||
$form->setFieldAttribute('published', 'required', 'false');
|
||||
$form->setFieldAttribute('published', 'filter', 'unset');
|
||||
}
|
||||
|
||||
$form->setFieldAttribute('default', 'disabled', 'true');
|
||||
$form->setFieldAttribute('default', 'required', 'false');
|
||||
$form->setFieldAttribute('default', 'filter', 'unset');
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the data that should be injected in the form.
|
||||
*
|
||||
* @return mixed The data for the form.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function loadFormData()
|
||||
{
|
||||
// Check the session for previously entered form data.
|
||||
$data = Factory::getApplication()->getUserState(
|
||||
'com_workflow.edit.state.data',
|
||||
[]
|
||||
);
|
||||
|
||||
if (empty($data)) {
|
||||
$data = $this->getItem();
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to change the home state of one or more items.
|
||||
*
|
||||
* @param array $pk A list of the primary keys to change.
|
||||
* @param integer $value The value of the home state.
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function setDefault($pk, $value = 1)
|
||||
{
|
||||
$table = $this->getTable();
|
||||
|
||||
if ($table->load($pk)) {
|
||||
if (!$table->published) {
|
||||
$this->setError(Text::_('COM_WORKFLOW_ITEM_MUST_PUBLISHED'));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($table->id) || !$this->canEditState($table)) {
|
||||
Log::add(Text::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'), Log::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($value) {
|
||||
// Verify that the home page for this language is unique per client id
|
||||
if ($table->load(['default' => '1', 'workflow_id' => $table->workflow_id])) {
|
||||
$table->default = 0;
|
||||
$table->store();
|
||||
}
|
||||
}
|
||||
|
||||
if ($table->load($pk)) {
|
||||
$table->default = $value;
|
||||
$table->store();
|
||||
}
|
||||
|
||||
// Clean the cache
|
||||
$this->cleanCache();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 4.0.0
|
||||
*/
|
||||
public function publish(&$pks, $value = 1)
|
||||
{
|
||||
$table = $this->getTable();
|
||||
$pks = (array) $pks;
|
||||
$app = Factory::getApplication();
|
||||
$extension = $app->getUserStateFromRequest('com_workflow.state.filter.extension', 'extension', null, 'cmd');
|
||||
|
||||
// Default item existence checks.
|
||||
if ($value != 1) {
|
||||
foreach ($pks as $i => $pk) {
|
||||
if ($table->load($pk) && $table->default) {
|
||||
// Prune items that you can't change.
|
||||
$app->enqueueMessage(Text::_('COM_WORKFLOW_MSG_DISABLE_DEFAULT'), 'error');
|
||||
|
||||
unset($pks[$i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return parent::publish($pks, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to preprocess the form.
|
||||
*
|
||||
* @param Form $form A Form object.
|
||||
* @param mixed $data The data expected for the form.
|
||||
* @param string $group The name of the plugin group to import (defaults to "content").
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function preprocessForm(Form $form, $data, $group = 'content')
|
||||
{
|
||||
$extension = Factory::getApplication()->getInput()->get('extension');
|
||||
|
||||
$parts = explode('.', $extension);
|
||||
|
||||
$extension = array_shift($parts);
|
||||
|
||||
// Set the access control rules field component value.
|
||||
$form->setFieldAttribute('rules', 'component', $extension);
|
||||
|
||||
parent::preprocessForm($form, $data, $group);
|
||||
}
|
||||
}
|
||||
201
administrator/components/com_workflow/src/Model/StagesModel.php
Normal file
201
administrator/components/com_workflow/src/Model/StagesModel.php
Normal file
@ -0,0 +1,201 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_workflow
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
* @since 4.0.0
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Workflow\Administrator\Model;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\MVC\Model\ListModel;
|
||||
use Joomla\Database\DatabaseQuery;
|
||||
use Joomla\Database\ParameterType;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Model class for stages
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class StagesModel extends ListModel
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $config An optional associative array of configuration settings.
|
||||
*
|
||||
* @see JController
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function __construct($config = [])
|
||||
{
|
||||
if (empty($config['filter_fields'])) {
|
||||
$config['filter_fields'] = [
|
||||
'id', 's.id',
|
||||
'title', 's.title',
|
||||
'ordering','s.ordering',
|
||||
'published', 's.published',
|
||||
];
|
||||
}
|
||||
|
||||
parent::__construct($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to auto-populate the model state.
|
||||
*
|
||||
* This method should only be called once per instantiation and is designed
|
||||
* to be called on the first call to the getState() method unless the model
|
||||
* configuration flag to ignore the request is set.
|
||||
*
|
||||
* Note. Calling getState in this method will result in recursion.
|
||||
*
|
||||
* @param string $ordering An optional ordering field.
|
||||
* @param string $direction An optional direction (asc|desc).
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function populateState($ordering = 's.ordering', $direction = 'ASC')
|
||||
{
|
||||
$app = Factory::getApplication();
|
||||
|
||||
$workflowID = $app->getUserStateFromRequest($this->context . '.filter.workflow_id', 'workflow_id', 1, 'int');
|
||||
$extension = $app->getUserStateFromRequest($this->context . '.filter.extension', 'extension', null, 'cmd');
|
||||
|
||||
if ($workflowID) {
|
||||
$table = $this->getTable('Workflow', 'Administrator');
|
||||
|
||||
if ($table->load($workflowID)) {
|
||||
$this->setState('active_workflow', $table->title);
|
||||
}
|
||||
}
|
||||
|
||||
$this->setState('filter.workflow_id', $workflowID);
|
||||
$this->setState('filter.extension', $extension);
|
||||
|
||||
parent::populateState($ordering, $direction);
|
||||
}
|
||||
|
||||
/**
|
||||
* A protected method to get a set of ordering conditions.
|
||||
*
|
||||
* @param object $table A record object.
|
||||
*
|
||||
* @return array An array of conditions to add to ordering queries.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function getReorderConditions($table)
|
||||
{
|
||||
return [
|
||||
$this->getDatabase()->quoteName('workflow_id') . ' = ' . (int) $table->workflow_id,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get a table object, load it if necessary.
|
||||
*
|
||||
* @param string $type The table name. Optional.
|
||||
* @param string $prefix The class prefix. Optional.
|
||||
* @param array $config Configuration array for model. Optional.
|
||||
*
|
||||
* @return \Joomla\CMS\Table\Table A Table object
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function getTable($type = 'Stage', $prefix = 'Administrator', $config = [])
|
||||
{
|
||||
return parent::getTable($type, $prefix, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the data that should be injected in the form.
|
||||
*
|
||||
* @return DatabaseQuery The query to database.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function getListQuery()
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true);
|
||||
|
||||
$query
|
||||
->select(
|
||||
[
|
||||
$db->quoteName('s.id'),
|
||||
$db->quoteName('s.title'),
|
||||
$db->quoteName('s.ordering'),
|
||||
$db->quoteName('s.default'),
|
||||
$db->quoteName('s.published'),
|
||||
$db->quoteName('s.checked_out'),
|
||||
$db->quoteName('s.checked_out_time'),
|
||||
$db->quoteName('s.description'),
|
||||
$db->quoteName('uc.name', 'editor'),
|
||||
]
|
||||
)
|
||||
->from($db->quoteName('#__workflow_stages', 's'))
|
||||
->join('LEFT', $db->quoteName('#__users', 'uc'), $db->quoteName('uc.id') . ' = ' . $db->quoteName('s.checked_out'));
|
||||
|
||||
// Filter by extension
|
||||
if ($workflowID = (int) $this->getState('filter.workflow_id')) {
|
||||
$query->where($db->quoteName('s.workflow_id') . ' = :id')
|
||||
->bind(':id', $workflowID, ParameterType::INTEGER);
|
||||
}
|
||||
|
||||
$status = (string) $this->getState('filter.published');
|
||||
|
||||
// Filter by publish state
|
||||
if (is_numeric($status)) {
|
||||
$status = (int) $status;
|
||||
$query->where($db->quoteName('s.published') . ' = :status')
|
||||
->bind(':status', $status, ParameterType::INTEGER);
|
||||
} elseif ($status === '') {
|
||||
$query->where($db->quoteName('s.published') . ' IN (0, 1)');
|
||||
}
|
||||
|
||||
// Filter by search in title
|
||||
$search = $this->getState('filter.search');
|
||||
|
||||
if (!empty($search)) {
|
||||
$search = '%' . str_replace(' ', '%', trim($search)) . '%';
|
||||
$query->where('(' . $db->quoteName('s.title') . ' LIKE :search1 OR ' . $db->quoteName('s.description') . ' LIKE :search2)')
|
||||
->bind([':search1', ':search2'], $search);
|
||||
}
|
||||
|
||||
// Add the list ordering clause.
|
||||
$query->order($db->escape($this->getState('list.ordering', 's.ordering')) . ' ' . $db->escape($this->getState('list.direction', 'ASC')));
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a workflow object
|
||||
*
|
||||
* @return object The workflow
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function getWorkflow()
|
||||
{
|
||||
$table = $this->getTable('Workflow', 'Administrator');
|
||||
|
||||
$workflowId = (int) $this->getState('filter.workflow_id');
|
||||
|
||||
if ($workflowId > 0) {
|
||||
$table->load($workflowId);
|
||||
}
|
||||
|
||||
return (object) $table->getProperties();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,336 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_workflow
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
* @since 4.0.0
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Workflow\Administrator\Model;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Form\Form;
|
||||
use Joomla\CMS\MVC\Model\AdminModel;
|
||||
use Joomla\CMS\Plugin\PluginHelper;
|
||||
use Joomla\Registry\Registry;
|
||||
use Joomla\String\StringHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Model class for transition
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class TransitionModel extends AdminModel
|
||||
{
|
||||
/**
|
||||
* Auto-populate the model state.
|
||||
*
|
||||
* Note. Calling getState in this method will result in recursion.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function populateState()
|
||||
{
|
||||
parent::populateState();
|
||||
|
||||
$app = Factory::getApplication();
|
||||
$context = $this->option . '.' . $this->name;
|
||||
$extension = $app->getUserStateFromRequest($context . '.filter.extension', 'extension', null, 'cmd');
|
||||
|
||||
$this->setState('filter.extension', $extension);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to test whether a record can be deleted.
|
||||
*
|
||||
* @param object $record A record object.
|
||||
*
|
||||
* @return boolean True if allowed to delete the record. Defaults to the permission for the component.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function canDelete($record)
|
||||
{
|
||||
if (empty($record->id) || $record->published != -2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$app = Factory::getApplication();
|
||||
$extension = $app->getUserStateFromRequest('com_workflow.transition.filter.extension', 'extension', null, 'cmd');
|
||||
|
||||
return $this->getCurrentUser()->authorise('core.delete', $extension . '.transition.' . (int) $record->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to test whether a record can have its state changed.
|
||||
*
|
||||
* @param object $record A record object.
|
||||
*
|
||||
* @return boolean True if allowed to change the state of the record. Defaults to the permission set in the component.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function canEditState($record)
|
||||
{
|
||||
$user = $this->getCurrentUser();
|
||||
$app = Factory::getApplication();
|
||||
$context = $this->option . '.' . $this->name;
|
||||
$extension = $app->getUserStateFromRequest($context . '.filter.extension', 'extension', null, 'cmd');
|
||||
|
||||
if (!property_exists($record, 'workflow_id')) {
|
||||
$workflowID = $app->getUserStateFromRequest($context . '.filter.workflow_id', 'workflow_id', 0, 'int');
|
||||
$record->workflow_id = $workflowID;
|
||||
}
|
||||
|
||||
// Check for existing workflow.
|
||||
if (!empty($record->id)) {
|
||||
return $user->authorise('core.edit.state', $extension . '.transition.' . (int) $record->id);
|
||||
}
|
||||
|
||||
// Default to component settings if workflow isn't known.
|
||||
return $user->authorise('core.edit.state', $extension);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get a single record.
|
||||
*
|
||||
* @param integer $pk The id of the primary key.
|
||||
*
|
||||
* @return \Joomla\CMS\Object\CMSObject|boolean Object on success, false on failure.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function getItem($pk = null)
|
||||
{
|
||||
$item = parent::getItem($pk);
|
||||
|
||||
if (property_exists($item, 'options')) {
|
||||
$registry = new Registry($item->options);
|
||||
$item->options = $registry->toArray();
|
||||
}
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to save the form data.
|
||||
*
|
||||
* @param array $data The form data.
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function save($data)
|
||||
{
|
||||
$table = $this->getTable();
|
||||
$context = $this->option . '.' . $this->name;
|
||||
$app = Factory::getApplication();
|
||||
$user = $app->getIdentity();
|
||||
$input = $app->getInput();
|
||||
|
||||
$workflowID = $app->getUserStateFromRequest($context . '.filter.workflow_id', 'workflow_id', 0, 'int');
|
||||
|
||||
if (empty($data['workflow_id'])) {
|
||||
$data['workflow_id'] = $workflowID;
|
||||
}
|
||||
|
||||
$workflow = $this->getTable('Workflow');
|
||||
|
||||
$workflow->load($data['workflow_id']);
|
||||
|
||||
$parts = explode('.', $workflow->extension);
|
||||
|
||||
if (isset($data['rules']) && !$user->authorise('core.admin', $parts[0])) {
|
||||
unset($data['rules']);
|
||||
}
|
||||
|
||||
// Make sure we use the correct workflow_id when editing an existing transition
|
||||
$key = $table->getKeyName();
|
||||
$pk = (isset($data[$key])) ? $data[$key] : (int) $this->getState($this->getName() . '.id');
|
||||
|
||||
if ($pk > 0) {
|
||||
$table->load($pk);
|
||||
|
||||
if ((int) $table->workflow_id) {
|
||||
$data['workflow_id'] = (int) $table->workflow_id;
|
||||
}
|
||||
}
|
||||
|
||||
if ($input->get('task') == 'save2copy') {
|
||||
$origTable = clone $this->getTable();
|
||||
|
||||
// Alter the title for save as copy
|
||||
if ($origTable->load(['title' => $data['title']])) {
|
||||
list($title) = $this->generateNewTitle(0, '', $data['title']);
|
||||
$data['title'] = $title;
|
||||
}
|
||||
|
||||
$data['published'] = 0;
|
||||
}
|
||||
|
||||
return parent::save($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to change the title
|
||||
*
|
||||
* @param integer $categoryId The id of the category.
|
||||
* @param string $alias The alias.
|
||||
* @param string $title The title.
|
||||
*
|
||||
* @return array Contains the modified title and alias.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function generateNewTitle($categoryId, $alias, $title)
|
||||
{
|
||||
// Alter the title & alias
|
||||
$table = $this->getTable();
|
||||
|
||||
while ($table->load(['title' => $title])) {
|
||||
$title = StringHelper::increment($title);
|
||||
}
|
||||
|
||||
return [$title, $alias];
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract method for getting the form from the model.
|
||||
*
|
||||
* @param array $data Data for the form.
|
||||
* @param boolean $loadData True if the form is to load its own data (default case), false if not.
|
||||
*
|
||||
* @return \Joomla\CMS\Form\Form|boolean A Form object on success, false on failure
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function getForm($data = [], $loadData = true)
|
||||
{
|
||||
// Get the form.
|
||||
$form = $this->loadForm(
|
||||
'com_workflow.transition',
|
||||
'transition',
|
||||
[
|
||||
'control' => 'jform',
|
||||
'load_data' => $loadData,
|
||||
]
|
||||
);
|
||||
|
||||
if (empty($form)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$id = $data['id'] ?? $form->getValue('id');
|
||||
|
||||
$item = $this->getItem($id);
|
||||
|
||||
$canEditState = $this->canEditState((object) $item);
|
||||
|
||||
// Modify the form based on access controls.
|
||||
if (!$canEditState) {
|
||||
$form->setFieldAttribute('published', 'disabled', 'true');
|
||||
$form->setFieldAttribute('published', 'required', 'false');
|
||||
$form->setFieldAttribute('published', 'filter', 'unset');
|
||||
}
|
||||
|
||||
if (!empty($item->workflow_id)) {
|
||||
$data['workflow_id'] = (int) $item->workflow_id;
|
||||
}
|
||||
|
||||
if (empty($data['workflow_id'])) {
|
||||
$context = $this->option . '.' . $this->name;
|
||||
|
||||
$data['workflow_id'] = (int) Factory::getApplication()->getUserStateFromRequest(
|
||||
$context . '.filter.workflow_id',
|
||||
'workflow_id',
|
||||
0,
|
||||
'int'
|
||||
);
|
||||
}
|
||||
|
||||
$where = $this->getDatabase()->quoteName('workflow_id') . ' = ' . (int) $data['workflow_id'];
|
||||
$where .= ' AND ' . $this->getDatabase()->quoteName('published') . ' = 1';
|
||||
|
||||
$form->setFieldAttribute('from_stage_id', 'sql_where', $where);
|
||||
$form->setFieldAttribute('to_stage_id', 'sql_where', $where);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the data that should be injected in the form.
|
||||
*
|
||||
* @return mixed The data for the form.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function loadFormData()
|
||||
{
|
||||
// Check the session for previously entered form data.
|
||||
$data = Factory::getApplication()->getUserState(
|
||||
'com_workflow.edit.transition.data',
|
||||
[]
|
||||
);
|
||||
|
||||
if (empty($data)) {
|
||||
$data = $this->getItem();
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function getWorkflow()
|
||||
{
|
||||
$app = Factory::getApplication();
|
||||
|
||||
$context = $this->option . '.' . $this->name;
|
||||
|
||||
$workflow_id = (int) $app->getUserStateFromRequest($context . '.filter.workflow_id', 'workflow_id', 0, 'int');
|
||||
|
||||
$workflow = $this->getTable('Workflow');
|
||||
|
||||
$workflow->load($workflow_id);
|
||||
|
||||
return (object) $workflow->getProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger the form preparation for the workflow group
|
||||
*
|
||||
* @param Form $form A Form object.
|
||||
* @param mixed $data The data expected for the form.
|
||||
* @param string $group The name of the plugin group to import (defaults to "content").
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @see FormField
|
||||
* @since 4.0.0
|
||||
* @throws \Exception if there is an error in the form event.
|
||||
*/
|
||||
protected function preprocessForm(Form $form, $data, $group = 'content')
|
||||
{
|
||||
$extension = Factory::getApplication()->getInput()->get('extension');
|
||||
|
||||
$parts = explode('.', $extension);
|
||||
|
||||
$extension = array_shift($parts);
|
||||
|
||||
// Set the access control rules field component value.
|
||||
$form->setFieldAttribute('rules', 'component', $extension);
|
||||
|
||||
// Import the appropriate plugin group.
|
||||
PluginHelper::importPlugin('workflow');
|
||||
|
||||
parent::preprocessForm($form, $data, $group);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,248 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_workflow
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
* @since 4.0.0
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Workflow\Administrator\Model;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\MVC\Model\ListModel;
|
||||
use Joomla\Database\DatabaseQuery;
|
||||
use Joomla\Database\ParameterType;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Model class for transitions
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class TransitionsModel extends ListModel
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $config An optional associative array of configuration settings.
|
||||
*
|
||||
* @see JController
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function __construct($config = [])
|
||||
{
|
||||
if (empty($config['filter_fields'])) {
|
||||
$config['filter_fields'] = [
|
||||
'id', 't.id',
|
||||
'published', 't.published',
|
||||
'ordering', 't.ordering',
|
||||
'title', 't.title',
|
||||
'from_stage', 't.from_stage_id',
|
||||
'to_stage', 't.to_stage_id',
|
||||
];
|
||||
}
|
||||
|
||||
parent::__construct($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to auto-populate the model state.
|
||||
*
|
||||
* This method should only be called once per instantiation and is designed
|
||||
* to be called on the first call to the getState() method unless the model
|
||||
* configuration flag to ignore the request is set.
|
||||
*
|
||||
* Note. Calling getState in this method will result in recursion.
|
||||
*
|
||||
* @param string $ordering An optional ordering field.
|
||||
* @param string $direction An optional direction (asc|desc).
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function populateState($ordering = 't.ordering', $direction = 'ASC')
|
||||
{
|
||||
$app = Factory::getApplication();
|
||||
$workflowID = $app->getUserStateFromRequest($this->context . '.filter.workflow_id', 'workflow_id', 1, 'int');
|
||||
$extension = $app->getUserStateFromRequest($this->context . '.filter.extension', 'extension', null, 'cmd');
|
||||
|
||||
if ($workflowID) {
|
||||
$table = $this->getTable('Workflow', 'Administrator');
|
||||
|
||||
if ($table->load($workflowID)) {
|
||||
$this->setState('active_workflow', $table->title);
|
||||
}
|
||||
}
|
||||
|
||||
$this->setState('filter.workflow_id', $workflowID);
|
||||
$this->setState('filter.extension', $extension);
|
||||
|
||||
parent::populateState($ordering, $direction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get a table object, load it if necessary.
|
||||
*
|
||||
* @param string $type The table name. Optional.
|
||||
* @param string $prefix The class prefix. Optional.
|
||||
* @param array $config Configuration array for model. Optional.
|
||||
*
|
||||
* @return \Joomla\CMS\Table\Table A Table object
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function getTable($type = 'Transition', $prefix = 'Administrator', $config = [])
|
||||
{
|
||||
return parent::getTable($type, $prefix, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* A protected method to get a set of ordering conditions.
|
||||
*
|
||||
* @param object $table A record object.
|
||||
*
|
||||
* @return array An array of conditions to add to ordering queries.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function getReorderConditions($table)
|
||||
{
|
||||
return [
|
||||
$this->getDatabase()->quoteName('workflow_id') . ' = ' . (int) $table->workflow_id,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the data that should be injected in the form.
|
||||
*
|
||||
* @return DatabaseQuery The query to database.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function getListQuery()
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true);
|
||||
|
||||
$query
|
||||
->select(
|
||||
[
|
||||
$db->quoteName('t.id'),
|
||||
$db->quoteName('t.title'),
|
||||
$db->quoteName('t.from_stage_id'),
|
||||
$db->quoteName('t.to_stage_id'),
|
||||
$db->quoteName('t.published'),
|
||||
$db->quoteName('t.checked_out'),
|
||||
$db->quoteName('t.checked_out_time'),
|
||||
$db->quoteName('t.ordering'),
|
||||
$db->quoteName('t.description'),
|
||||
$db->quoteName('f_stage.title', 'from_stage'),
|
||||
$db->quoteName('t_stage.title', 'to_stage'),
|
||||
$db->quoteName('uc.name', 'editor'),
|
||||
]
|
||||
)
|
||||
->from($db->quoteName('#__workflow_transitions', 't'))
|
||||
->join('LEFT', $db->quoteName('#__workflow_stages', 'f_stage'), $db->quoteName('f_stage.id') . ' = ' . $db->quoteName('t.from_stage_id'))
|
||||
->join('LEFT', $db->quoteName('#__workflow_stages', 't_stage'), $db->quoteName('t_stage.id') . ' = ' . $db->quoteName('t.to_stage_id'))
|
||||
->join('LEFT', $db->quoteName('#__users', 'uc'), $db->quoteName('uc.id') . ' = ' . $db->quoteName('t.checked_out'));
|
||||
|
||||
// Filter by extension
|
||||
if ($workflowID = (int) $this->getState('filter.workflow_id')) {
|
||||
$query->where($db->quoteName('t.workflow_id') . ' = :id')
|
||||
->bind(':id', $workflowID, ParameterType::INTEGER);
|
||||
}
|
||||
|
||||
$status = (string) $this->getState('filter.published');
|
||||
|
||||
// Filter by status
|
||||
if (is_numeric($status)) {
|
||||
$status = (int) $status;
|
||||
$query->where($db->quoteName('t.published') . ' = :status')
|
||||
->bind(':status', $status, ParameterType::INTEGER);
|
||||
} elseif ($status === '') {
|
||||
$query->where($db->quoteName('t.published') . ' IN (0, 1)');
|
||||
}
|
||||
|
||||
// Filter by column from_stage_id
|
||||
if ($fromStage = (int) $this->getState('filter.from_stage')) {
|
||||
$query->where($db->quoteName('from_stage_id') . ' = :fromStage')
|
||||
->bind(':fromStage', $fromStage, ParameterType::INTEGER);
|
||||
}
|
||||
|
||||
// Filter by column to_stage_id
|
||||
if ($toStage = (int) $this->getState('filter.to_stage')) {
|
||||
$query->where($db->quoteName('to_stage_id') . ' = :toStage')
|
||||
->bind(':toStage', $toStage, ParameterType::INTEGER);
|
||||
}
|
||||
|
||||
// Filter by search in title
|
||||
$search = $this->getState('filter.search');
|
||||
|
||||
if (!empty($search)) {
|
||||
$search = '%' . str_replace(' ', '%', trim($search)) . '%';
|
||||
$query->where('(' . $db->quoteName('t.title') . ' LIKE :search1 OR ' . $db->quoteName('t.description') . ' LIKE :search2)')
|
||||
->bind([':search1', ':search2'], $search);
|
||||
}
|
||||
|
||||
// Add the list ordering clause.
|
||||
$orderCol = $this->state->get('list.ordering', 't.id');
|
||||
$orderDirn = strtoupper($this->state->get('list.direction', 'ASC'));
|
||||
|
||||
$query->order($db->escape($orderCol) . ' ' . ($orderDirn === 'DESC' ? 'DESC' : 'ASC'));
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the filter form
|
||||
*
|
||||
* @param array $data data
|
||||
* @param boolean $loadData load current data
|
||||
*
|
||||
* @return \Joomla\CMS\Form\Form|boolean The Form object or false on error
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function getFilterForm($data = [], $loadData = true)
|
||||
{
|
||||
$form = parent::getFilterForm($data, $loadData);
|
||||
|
||||
$id = (int) $this->getState('filter.workflow_id');
|
||||
|
||||
if ($form) {
|
||||
$where = $this->getDatabase()->quoteName('workflow_id') . ' = ' . $id . ' AND ' . $this->getDatabase()->quoteName('published') . ' = 1';
|
||||
|
||||
$form->setFieldAttribute('from_stage', 'sql_where', $where, 'filter');
|
||||
$form->setFieldAttribute('to_stage', 'sql_where', $where, 'filter');
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a workflow object
|
||||
*
|
||||
* @return object The workflow
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function getWorkflow()
|
||||
{
|
||||
$table = $this->getTable('Workflow', 'Administrator');
|
||||
|
||||
$workflowId = (int) $this->getState('filter.workflow_id');
|
||||
|
||||
if ($workflowId > 0) {
|
||||
$table->load($workflowId);
|
||||
}
|
||||
|
||||
return (object) $table->getProperties();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,398 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_workflow
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
* @since 4.0.0
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Workflow\Administrator\Model;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Form\Form;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Log\Log;
|
||||
use Joomla\CMS\MVC\Model\AdminModel;
|
||||
use Joomla\String\StringHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Model class for workflow
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class WorkflowModel extends AdminModel
|
||||
{
|
||||
/**
|
||||
* Auto-populate the model state.
|
||||
*
|
||||
* Note. Calling getState in this method will result in recursion.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function populateState()
|
||||
{
|
||||
parent::populateState();
|
||||
|
||||
$app = Factory::getApplication();
|
||||
$context = $this->option . '.' . $this->name;
|
||||
$extension = $app->getUserStateFromRequest($context . '.filter.extension', 'extension', null, 'cmd');
|
||||
|
||||
$this->setState('filter.extension', $extension);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to change the title
|
||||
*
|
||||
* @param integer $categoryId The id of the category.
|
||||
* @param string $alias The alias.
|
||||
* @param string $title The title.
|
||||
*
|
||||
* @return array Contains the modified title and alias.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function generateNewTitle($categoryId, $alias, $title)
|
||||
{
|
||||
// Alter the title & alias
|
||||
$table = $this->getTable();
|
||||
|
||||
while ($table->load(['title' => $title])) {
|
||||
$title = StringHelper::increment($title);
|
||||
}
|
||||
|
||||
return [$title, $alias];
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to save the form data.
|
||||
*
|
||||
* @param array $data The form data.
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function save($data)
|
||||
{
|
||||
$table = $this->getTable();
|
||||
$app = Factory::getApplication();
|
||||
$user = $app->getIdentity();
|
||||
$input = $app->getInput();
|
||||
$context = $this->option . '.' . $this->name;
|
||||
$extension = $app->getUserStateFromRequest($context . '.filter.extension', 'extension', null, 'cmd');
|
||||
$data['extension'] = !empty($data['extension']) ? $data['extension'] : $extension;
|
||||
|
||||
// Make sure we use the correct extension when editing an existing workflow
|
||||
$key = $table->getKeyName();
|
||||
$pk = (isset($data[$key])) ? $data[$key] : (int) $this->getState($this->getName() . '.id');
|
||||
|
||||
if ($pk > 0) {
|
||||
$table->load($pk);
|
||||
|
||||
$data['extension'] = $table->extension;
|
||||
}
|
||||
|
||||
if (isset($data['rules']) && !$user->authorise('core.admin', $data['extension'])) {
|
||||
unset($data['rules']);
|
||||
}
|
||||
|
||||
if ($input->get('task') == 'save2copy') {
|
||||
$origTable = clone $this->getTable();
|
||||
|
||||
// Alter the title for save as copy
|
||||
if ($origTable->load(['title' => $data['title']])) {
|
||||
list($title) = $this->generateNewTitle(0, '', $data['title']);
|
||||
$data['title'] = $title;
|
||||
}
|
||||
|
||||
// Unpublish new copy
|
||||
$data['published'] = 0;
|
||||
$data['default'] = 0;
|
||||
}
|
||||
|
||||
$result = parent::save($data);
|
||||
|
||||
// Create default stage for new workflow
|
||||
if ($result && $input->getCmd('task') !== 'save2copy' && $this->getState($this->getName() . '.new')) {
|
||||
$workflow_id = (int) $this->getState($this->getName() . '.id');
|
||||
|
||||
$table = $this->getTable('Stage');
|
||||
|
||||
$table->id = 0;
|
||||
$table->title = 'COM_WORKFLOW_BASIC_STAGE';
|
||||
$table->description = '';
|
||||
$table->workflow_id = $workflow_id;
|
||||
$table->published = 1;
|
||||
$table->default = 1;
|
||||
|
||||
$table->store();
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract method for getting the form from the model.
|
||||
*
|
||||
* @param array $data Data for the form.
|
||||
* @param boolean $loadData True if the form is to load its own data (default case), false if not.
|
||||
*
|
||||
* @return \Joomla\CMS\Form\Form|boolean A Form object on success, false on failure
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function getForm($data = [], $loadData = true)
|
||||
{
|
||||
// Get the form.
|
||||
$form = $this->loadForm(
|
||||
'com_workflow.workflow',
|
||||
'workflow',
|
||||
[
|
||||
'control' => 'jform',
|
||||
'load_data' => $loadData,
|
||||
]
|
||||
);
|
||||
|
||||
if (empty($form)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$id = $data['id'] ?? $form->getValue('id');
|
||||
|
||||
$item = $this->getItem($id);
|
||||
|
||||
$canEditState = $this->canEditState((object) $item);
|
||||
|
||||
// Modify the form based on access controls.
|
||||
if (!$canEditState || !empty($item->default)) {
|
||||
if (!$canEditState) {
|
||||
$form->setFieldAttribute('published', 'disabled', 'true');
|
||||
$form->setFieldAttribute('published', 'required', 'false');
|
||||
$form->setFieldAttribute('published', 'filter', 'unset');
|
||||
}
|
||||
|
||||
$form->setFieldAttribute('default', 'disabled', 'true');
|
||||
$form->setFieldAttribute('default', 'required', 'false');
|
||||
$form->setFieldAttribute('default', 'filter', 'unset');
|
||||
}
|
||||
|
||||
$form->setFieldAttribute('created', 'default', Factory::getDate()->format('Y-m-d H:i:s'));
|
||||
$form->setFieldAttribute('modified', 'default', Factory::getDate()->format('Y-m-d H:i:s'));
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the data that should be injected in the form.
|
||||
*
|
||||
* @return mixed The data for the form.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function loadFormData()
|
||||
{
|
||||
// Check the session for previously entered form data.
|
||||
$data = Factory::getApplication()->getUserState(
|
||||
'com_workflow.edit.workflow.data',
|
||||
[]
|
||||
);
|
||||
|
||||
if (empty($data)) {
|
||||
$data = $this->getItem();
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to preprocess the form.
|
||||
*
|
||||
* @param Form $form Form object.
|
||||
* @param mixed $data The data expected for the form.
|
||||
* @param string $group The name of the plugin group to import (defaults to "content").
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function preprocessForm(Form $form, $data, $group = 'content')
|
||||
{
|
||||
$extension = Factory::getApplication()->getInput()->get('extension');
|
||||
|
||||
$parts = explode('.', $extension);
|
||||
|
||||
$extension = array_shift($parts);
|
||||
|
||||
// Set the access control rules field component value.
|
||||
$form->setFieldAttribute('rules', 'component', $extension);
|
||||
|
||||
parent::preprocessForm($form, $data, $group);
|
||||
}
|
||||
|
||||
/**
|
||||
* A protected method to get a set of ordering conditions.
|
||||
*
|
||||
* @param object $table A record object.
|
||||
*
|
||||
* @return array An array of conditions to add to ordering queries.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function getReorderConditions($table)
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
|
||||
return [
|
||||
$db->quoteName('extension') . ' = ' . $db->quote($table->extension),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to change the default state of one item.
|
||||
*
|
||||
* @param array $pk A list of the primary keys to change.
|
||||
* @param integer $value The value of the home state.
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function setDefault($pk, $value = 1)
|
||||
{
|
||||
$table = $this->getTable();
|
||||
|
||||
if ($table->load($pk)) {
|
||||
if ($table->published !== 1) {
|
||||
$this->setError(Text::_('COM_WORKFLOW_ITEM_MUST_PUBLISHED'));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($table->id) || !$this->canEditState($table)) {
|
||||
Log::add(Text::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'), Log::WARNING, 'jerror');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$date = Factory::getDate()->toSql();
|
||||
|
||||
if ($value) {
|
||||
// Unset other default item
|
||||
if (
|
||||
$table->load(
|
||||
[
|
||||
'default' => '1',
|
||||
'extension' => $table->get('extension'),
|
||||
]
|
||||
)
|
||||
) {
|
||||
$table->default = 0;
|
||||
$table->modified = $date;
|
||||
$table->store();
|
||||
}
|
||||
}
|
||||
|
||||
if ($table->load($pk)) {
|
||||
$table->modified = $date;
|
||||
$table->default = $value;
|
||||
$table->store();
|
||||
}
|
||||
|
||||
// Clean the cache
|
||||
$this->cleanCache();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to test whether a record can be deleted.
|
||||
*
|
||||
* @param object $record A record object.
|
||||
*
|
||||
* @return boolean True if allowed to delete the record. Defaults to the permission for the component.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function canDelete($record)
|
||||
{
|
||||
if (empty($record->id) || $record->published != -2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->getCurrentUser()->authorise('core.delete', $record->extension . '.workflow.' . (int) $record->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to test whether a record can have its state changed.
|
||||
*
|
||||
* @param object $record A record object.
|
||||
*
|
||||
* @return boolean True if allowed to change the state of the record. Defaults to the permission set in the component.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function canEditState($record)
|
||||
{
|
||||
$user = $this->getCurrentUser();
|
||||
|
||||
// Check for existing workflow.
|
||||
if (!empty($record->id)) {
|
||||
return $user->authorise('core.edit.state', $record->extension . '.workflow.' . (int) $record->id);
|
||||
}
|
||||
|
||||
// Default to component settings if workflow isn't known.
|
||||
return $user->authorise('core.edit.state', $record->extension);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 4.0.0
|
||||
*/
|
||||
public function publish(&$pks, $value = 1)
|
||||
{
|
||||
$table = $this->getTable();
|
||||
$pks = (array) $pks;
|
||||
|
||||
$date = Factory::getDate()->toSql();
|
||||
|
||||
// Default workflow item check.
|
||||
foreach ($pks as $i => $pk) {
|
||||
if ($table->load($pk) && $value != 1 && $table->default) {
|
||||
// Prune items that you can't change.
|
||||
Factory::getApplication()->enqueueMessage(Text::_('COM_WORKFLOW_UNPUBLISH_DEFAULT_ERROR'), 'error');
|
||||
unset($pks[$i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Clean the cache.
|
||||
$this->cleanCache();
|
||||
|
||||
// Ensure that previous checks don't empty the array.
|
||||
if (empty($pks)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$table->load($pk);
|
||||
$table->modified = $date;
|
||||
$table->store();
|
||||
|
||||
return parent::publish($pks, $value);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,274 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_workflow
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
* @since 4.0.0
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Workflow\Administrator\Model;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\MVC\Model\ListModel;
|
||||
use Joomla\Database\DatabaseQuery;
|
||||
use Joomla\Database\ParameterType;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Model class for workflows
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class WorkflowsModel extends ListModel
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $config An optional associative array of configuration settings.
|
||||
*
|
||||
* @see JController
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function __construct($config = [])
|
||||
{
|
||||
if (empty($config['filter_fields'])) {
|
||||
$config['filter_fields'] = [
|
||||
'id', 'w.id',
|
||||
'title', 'w.title',
|
||||
'published', 'w.published',
|
||||
'created_by', 'w.created_by',
|
||||
'created', 'w.created',
|
||||
'ordering', 'w.ordering',
|
||||
'modified', 'w.modified',
|
||||
'description', 'w.description',
|
||||
];
|
||||
}
|
||||
|
||||
parent::__construct($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to auto-populate the model state.
|
||||
*
|
||||
* This method should only be called once per instantiation and is designed
|
||||
* to be called on the first call to the getState() method unless the model
|
||||
* configuration flag to ignore the request is set.
|
||||
*
|
||||
* Note. Calling getState in this method will result in recursion.
|
||||
*
|
||||
* @param string $ordering An optional ordering field.
|
||||
* @param string $direction An optional direction (asc|desc).
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function populateState($ordering = 'w.ordering', $direction = 'asc')
|
||||
{
|
||||
$app = Factory::getApplication();
|
||||
$extension = $app->getUserStateFromRequest($this->context . '.filter.extension', 'extension', null, 'cmd');
|
||||
|
||||
$this->setState('filter.extension', $extension);
|
||||
$parts = explode('.', $extension);
|
||||
|
||||
// Extract the component name
|
||||
$this->setState('filter.component', $parts[0]);
|
||||
|
||||
// Extract the optional section name
|
||||
$this->setState('filter.section', (\count($parts) > 1) ? $parts[1] : null);
|
||||
|
||||
parent::populateState($ordering, $direction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get a table object, load it if necessary.
|
||||
*
|
||||
* @param string $type The table name. Optional.
|
||||
* @param string $prefix The class prefix. Optional.
|
||||
* @param array $config Configuration array for model. Optional.
|
||||
*
|
||||
* @return \Joomla\CMS\Table\Table A Table object
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function getTable($type = 'Workflow', $prefix = 'Administrator', $config = [])
|
||||
{
|
||||
return parent::getTable($type, $prefix, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get an array of data items.
|
||||
*
|
||||
* @return mixed An array of data items on success, false on failure.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function getItems()
|
||||
{
|
||||
$items = parent::getItems();
|
||||
|
||||
if ($items) {
|
||||
$this->countItems($items);
|
||||
}
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the filter form
|
||||
*
|
||||
* @param array $data data
|
||||
* @param boolean $loadData load current data
|
||||
*
|
||||
* @return \Joomla\CMS\Form\Form|bool the Form object or false
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function getFilterForm($data = [], $loadData = true)
|
||||
{
|
||||
$form = parent::getFilterForm($data, $loadData);
|
||||
|
||||
if ($form) {
|
||||
$form->setValue('extension', null, $this->getState('filter.extension'));
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the number of transitions and states to all workflow items
|
||||
*
|
||||
* @param array $items The workflow items
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function countItems($items)
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
|
||||
$ids = [0];
|
||||
|
||||
foreach ($items as $item) {
|
||||
$ids[] = (int) $item->id;
|
||||
|
||||
$item->count_states = 0;
|
||||
$item->count_transitions = 0;
|
||||
}
|
||||
|
||||
$query = $db->getQuery(true);
|
||||
|
||||
$query->select(
|
||||
[
|
||||
$db->quoteName('workflow_id'),
|
||||
'COUNT(*) AS ' . $db->quoteName('count'),
|
||||
]
|
||||
)
|
||||
->from($db->quoteName('#__workflow_stages'))
|
||||
->whereIn($db->quoteName('workflow_id'), $ids)
|
||||
->where($db->quoteName('published') . ' >= 0')
|
||||
->group($db->quoteName('workflow_id'));
|
||||
|
||||
$status = $db->setQuery($query)->loadObjectList('workflow_id');
|
||||
|
||||
$query = $db->getQuery(true);
|
||||
|
||||
$query->select(
|
||||
[
|
||||
$db->quoteName('workflow_id'),
|
||||
'COUNT(*) AS ' . $db->quoteName('count'),
|
||||
]
|
||||
)
|
||||
->from($db->quoteName('#__workflow_transitions'))
|
||||
->whereIn($db->quoteName('workflow_id'), $ids)
|
||||
->where($db->quoteName('published') . ' >= 0')
|
||||
->group($db->quoteName('workflow_id'));
|
||||
|
||||
$transitions = $db->setQuery($query)->loadObjectList('workflow_id');
|
||||
|
||||
foreach ($items as $item) {
|
||||
if (isset($status[$item->id])) {
|
||||
$item->count_states = (int) $status[$item->id]->count;
|
||||
}
|
||||
|
||||
if (isset($transitions[$item->id])) {
|
||||
$item->count_transitions = (int) $transitions[$item->id]->count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the data that should be injected in the form.
|
||||
*
|
||||
* @return DatabaseQuery The query to database.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function getListQuery()
|
||||
{
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true);
|
||||
|
||||
$query->select(
|
||||
[
|
||||
$db->quoteName('w.id'),
|
||||
$db->quoteName('w.title'),
|
||||
$db->quoteName('w.created'),
|
||||
$db->quoteName('w.modified'),
|
||||
$db->quoteName('w.published'),
|
||||
$db->quoteName('w.checked_out'),
|
||||
$db->quoteName('w.checked_out_time'),
|
||||
$db->quoteName('w.ordering'),
|
||||
$db->quoteName('w.default'),
|
||||
$db->quoteName('w.created_by'),
|
||||
$db->quoteName('w.description'),
|
||||
$db->quoteName('u.name'),
|
||||
$db->quoteName('uc.name', 'editor'),
|
||||
]
|
||||
)
|
||||
->from($db->quoteName('#__workflows', 'w'))
|
||||
->join('LEFT', $db->quoteName('#__users', 'u'), $db->quoteName('u.id') . ' = ' . $db->quoteName('w.created_by'))
|
||||
->join('LEFT', $db->quoteName('#__users', 'uc'), $db->quoteName('uc.id') . ' = ' . $db->quoteName('w.checked_out'));
|
||||
|
||||
// Filter by extension
|
||||
if ($extension = $this->getState('filter.extension')) {
|
||||
$query->where($db->quoteName('extension') . ' = :extension')
|
||||
->bind(':extension', $extension);
|
||||
}
|
||||
|
||||
$status = (string) $this->getState('filter.published');
|
||||
|
||||
// Filter by status
|
||||
if (is_numeric($status)) {
|
||||
$status = (int) $status;
|
||||
$query->where($db->quoteName('w.published') . ' = :published')
|
||||
->bind(':published', $status, ParameterType::INTEGER);
|
||||
} elseif ($status === '') {
|
||||
$query->where($db->quoteName('w.published') . ' IN (0, 1)');
|
||||
}
|
||||
|
||||
// Filter by search in title
|
||||
$search = $this->getState('filter.search');
|
||||
|
||||
if (!empty($search)) {
|
||||
$search = '%' . str_replace(' ', '%', trim($search)) . '%';
|
||||
$query->where('(' . $db->quoteName('w.title') . ' LIKE :search1 OR ' . $db->quoteName('w.description') . ' LIKE :search2)')
|
||||
->bind([':search1', ':search2'], $search);
|
||||
}
|
||||
|
||||
// Add the list ordering clause.
|
||||
$orderCol = $this->state->get('list.ordering', 'w.ordering');
|
||||
$orderDirn = strtoupper($this->state->get('list.direction', 'ASC'));
|
||||
|
||||
$query->order($db->escape($orderCol) . ' ' . ($orderDirn === 'DESC' ? 'DESC' : 'ASC'));
|
||||
|
||||
return $query;
|
||||
}
|
||||
}
|
||||
278
administrator/components/com_workflow/src/Table/StageTable.php
Normal file
278
administrator/components/com_workflow/src/Table/StageTable.php
Normal file
@ -0,0 +1,278 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_workflow
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Workflow\Administrator\Table;
|
||||
|
||||
use Joomla\CMS\Access\Rules;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Table\Asset;
|
||||
use Joomla\CMS\Table\Table;
|
||||
use Joomla\Database\DatabaseDriver;
|
||||
use Joomla\Database\ParameterType;
|
||||
use Joomla\Event\DispatcherInterface;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Stage table
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class StageTable extends Table
|
||||
{
|
||||
/**
|
||||
* Indicates that columns fully support the NULL value in the database
|
||||
*
|
||||
* @var boolean
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $_supportNullValue = true;
|
||||
|
||||
/**
|
||||
* @param DatabaseDriver $db Database connector object
|
||||
* @param ?DispatcherInterface $dispatcher Event dispatcher for this table
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function __construct(DatabaseDriver $db, DispatcherInterface $dispatcher = null)
|
||||
{
|
||||
parent::__construct('#__workflow_stages', 'id', $db, $dispatcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes workflow with transition and stages.
|
||||
*
|
||||
* @param int $pk Extension ids to delete.
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @throws \UnexpectedValueException
|
||||
*/
|
||||
public function delete($pk = null)
|
||||
{
|
||||
$db = $this->getDbo();
|
||||
$app = Factory::getApplication();
|
||||
$pk = (int) $pk;
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->select($db->quoteName('default'))
|
||||
->from($db->quoteName('#__workflow_stages'))
|
||||
->where($db->quoteName('id') . ' = :id')
|
||||
->bind(':id', $pk, ParameterType::INTEGER);
|
||||
|
||||
$isDefault = $db->setQuery($query)->loadResult();
|
||||
|
||||
if ($isDefault) {
|
||||
$app->enqueueMessage(Text::_('COM_WORKFLOW_MSG_DELETE_IS_DEFAULT'), 'error');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$query = $db->getQuery(true)
|
||||
->delete($db->quoteName('#__workflow_transitions'))
|
||||
->where(
|
||||
[
|
||||
$db->quoteName('to_stage_id') . ' = :idTo',
|
||||
$db->quoteName('from_stage_id') . ' = :idFrom',
|
||||
],
|
||||
'OR'
|
||||
)
|
||||
->bind([':idTo', ':idFrom'], $pk, ParameterType::INTEGER);
|
||||
|
||||
$db->setQuery($query)->execute();
|
||||
|
||||
return parent::delete($pk);
|
||||
} catch (\RuntimeException $e) {
|
||||
$app->enqueueMessage(Text::sprintf('COM_WORKFLOW_MSG_WORKFLOWS_DELETE_ERROR', $e->getMessage()), 'error');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overloaded check function
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @see Table::check()
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function check()
|
||||
{
|
||||
try {
|
||||
parent::check();
|
||||
} catch (\Exception $e) {
|
||||
$this->setError($e->getMessage());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (trim($this->title) === '') {
|
||||
$this->setError(Text::_('JLIB_DATABASE_ERROR_MUSTCONTAIN_A_TITLE_STATE'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!empty($this->default)) {
|
||||
if ((int) $this->published !== 1) {
|
||||
$this->setError(Text::_('COM_WORKFLOW_ITEM_MUST_PUBLISHED'));
|
||||
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
$db = $this->getDbo();
|
||||
$query = $db->getQuery(true);
|
||||
|
||||
$query
|
||||
->select($db->quoteName('id'))
|
||||
->from($db->quoteName('#__workflow_stages'))
|
||||
->where(
|
||||
[
|
||||
$db->quoteName('workflow_id') . ' = :id',
|
||||
$db->quoteName('default') . ' = 1',
|
||||
]
|
||||
)
|
||||
->bind(':id', $this->workflow_id, ParameterType::INTEGER);
|
||||
|
||||
$id = $db->setQuery($query)->loadResult();
|
||||
|
||||
// If there is no default stage => set the current to default to recover
|
||||
if (empty($id)) {
|
||||
$this->default = '1';
|
||||
} elseif ($id === $this->id) {
|
||||
// This stage is the default, but someone has tried to disable it => not allowed
|
||||
$this->setError(Text::_('COM_WORKFLOW_DISABLE_DEFAULT'));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overloaded store function
|
||||
*
|
||||
* @param boolean $updateNulls True to update fields even if they are null.
|
||||
*
|
||||
* @return mixed False on failure, positive integer on success.
|
||||
*
|
||||
* @see Table::store()
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function store($updateNulls = true)
|
||||
{
|
||||
$table = new StageTable($this->getDbo(), $this->getDispatcher());
|
||||
|
||||
if ($this->default == '1') {
|
||||
// Verify that the default is unique for this workflow
|
||||
if ($table->load(['default' => '1', 'workflow_id' => (int) $this->workflow_id])) {
|
||||
$table->default = 0;
|
||||
$table->store();
|
||||
}
|
||||
}
|
||||
|
||||
return parent::store($updateNulls);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to bind an associative array or object to the Table instance.
|
||||
* This method only binds properties that are publicly accessible and optionally
|
||||
* takes an array of properties to ignore when binding.
|
||||
*
|
||||
* @param array|object $src An associative array or object to bind to the Table instance.
|
||||
* @param array|string $ignore An optional array or space separated list of properties to ignore while binding.
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 4.0.0
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function bind($src, $ignore = [])
|
||||
{
|
||||
// Bind the rules.
|
||||
if (isset($src['rules']) && \is_array($src['rules'])) {
|
||||
$rules = new Rules($src['rules']);
|
||||
$this->setRules($rules);
|
||||
}
|
||||
|
||||
return parent::bind($src, $ignore);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to compute the default name of the asset.
|
||||
* The default name is in the form table_name.id
|
||||
* where id is the value of the primary key of the table.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function _getAssetName()
|
||||
{
|
||||
$k = $this->_tbl_key;
|
||||
$workflow = new WorkflowTable($this->getDbo(), $this->getDispatcher());
|
||||
$workflow->load($this->workflow_id);
|
||||
|
||||
$parts = explode('.', $workflow->extension);
|
||||
|
||||
$extension = array_shift($parts);
|
||||
|
||||
return $extension . '.stage.' . (int) $this->$k;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to return the title to use for the asset table.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function _getAssetTitle()
|
||||
{
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parent asset id for the record
|
||||
*
|
||||
* @param Table|null $table A Table object for the asset parent.
|
||||
* @param integer|null $id The id for the asset
|
||||
*
|
||||
* @return integer The id of the asset's parent
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function _getAssetParentId(Table $table = null, $id = null)
|
||||
{
|
||||
$asset = new Asset($this->getDbo(), $this->getDispatcher());
|
||||
|
||||
$workflow = new WorkflowTable($this->getDbo(), $this->getDispatcher());
|
||||
$workflow->load($this->workflow_id);
|
||||
|
||||
$parts = explode('.', $workflow->extension);
|
||||
|
||||
$extension = array_shift($parts);
|
||||
|
||||
$name = $extension . '.workflow.' . (int) $workflow->id;
|
||||
|
||||
$asset->loadByName($name);
|
||||
$assetId = $asset->id;
|
||||
|
||||
return !empty($assetId) ? $assetId : parent::_getAssetParentId($table, $id);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_workflow
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Workflow\Administrator\Table;
|
||||
|
||||
use Joomla\CMS\Access\Rules;
|
||||
use Joomla\CMS\Table\Asset;
|
||||
use Joomla\CMS\Table\Table;
|
||||
use Joomla\Database\DatabaseDriver;
|
||||
use Joomla\Event\DispatcherInterface;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Transition table
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class TransitionTable extends Table
|
||||
{
|
||||
/**
|
||||
* Indicates that columns fully support the NULL value in the database
|
||||
*
|
||||
* @var boolean
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $_supportNullValue = true;
|
||||
|
||||
/**
|
||||
* An array of key names to be json encoded in the bind function
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $_jsonEncode = [
|
||||
'options',
|
||||
];
|
||||
|
||||
/**
|
||||
* @param DatabaseDriver $db Database connector object
|
||||
* @param ?DispatcherInterface $dispatcher Event dispatcher for this table
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function __construct(DatabaseDriver $db, DispatcherInterface $dispatcher = null)
|
||||
{
|
||||
parent::__construct('#__workflow_transitions', 'id', $db, $dispatcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to bind an associative array or object to the Table instance.
|
||||
* This method only binds properties that are publicly accessible and optionally
|
||||
* takes an array of properties to ignore when binding.
|
||||
*
|
||||
* @param array|object $src An associative array or object to bind to the Table instance.
|
||||
* @param array|string $ignore An optional array or space separated list of properties to ignore while binding.
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 4.0.0
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function bind($src, $ignore = [])
|
||||
{
|
||||
// Bind the rules.
|
||||
if (isset($src['rules']) && \is_array($src['rules'])) {
|
||||
$rules = new Rules($src['rules']);
|
||||
$this->setRules($rules);
|
||||
}
|
||||
|
||||
return parent::bind($src, $ignore);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to compute the default name of the asset.
|
||||
* The default name is in the form table_name.id
|
||||
* where id is the value of the primary key of the table.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function _getAssetName()
|
||||
{
|
||||
$k = $this->_tbl_key;
|
||||
$workflow = new WorkflowTable($this->getDbo(), $this->getDispatcher());
|
||||
$workflow->load($this->workflow_id);
|
||||
|
||||
$parts = explode('.', $workflow->extension);
|
||||
|
||||
$extension = array_shift($parts);
|
||||
|
||||
return $extension . '.transition.' . (int) $this->$k;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to return the title to use for the asset table.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function _getAssetTitle()
|
||||
{
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parent asset id for the record
|
||||
*
|
||||
* @param Table $table A Table object for the asset parent.
|
||||
* @param integer $id The id for the asset
|
||||
*
|
||||
* @return integer The id of the asset's parent
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function _getAssetParentId(Table $table = null, $id = null)
|
||||
{
|
||||
$asset = new Asset($this->getDbo(), $this->getDispatcher());
|
||||
|
||||
$workflow = new WorkflowTable($this->getDbo(), $this->getDispatcher());
|
||||
$workflow->load($this->workflow_id);
|
||||
|
||||
$parts = explode('.', $workflow->extension);
|
||||
|
||||
$extension = array_shift($parts);
|
||||
|
||||
$name = $extension . '.workflow.' . (int) $workflow->id;
|
||||
|
||||
$asset->loadByName($name);
|
||||
$assetId = $asset->id;
|
||||
|
||||
return !empty($assetId) ? $assetId : parent::_getAssetParentId($table, $id);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,323 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_workflow
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Workflow\Administrator\Table;
|
||||
|
||||
use Joomla\CMS\Access\Rules;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Table\Table;
|
||||
use Joomla\CMS\User\CurrentUserInterface;
|
||||
use Joomla\CMS\User\CurrentUserTrait;
|
||||
use Joomla\Database\DatabaseDriver;
|
||||
use Joomla\Database\ParameterType;
|
||||
use Joomla\Event\DispatcherInterface;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Workflow table
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class WorkflowTable extends Table implements CurrentUserInterface
|
||||
{
|
||||
use CurrentUserTrait;
|
||||
|
||||
/**
|
||||
* Indicates that columns fully support the NULL value in the database
|
||||
*
|
||||
* @var boolean
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $_supportNullValue = true;
|
||||
|
||||
/**
|
||||
* @param DatabaseDriver $db Database connector object
|
||||
* @param ?DispatcherInterface $dispatcher Event dispatcher for this table
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function __construct(DatabaseDriver $db, DispatcherInterface $dispatcher = null)
|
||||
{
|
||||
$this->typeAlias = '{extension}.workflow';
|
||||
|
||||
parent::__construct('#__workflows', 'id', $db, $dispatcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes workflow with transition and states.
|
||||
*
|
||||
* @param int $pk Extension ids to delete.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @throws \Exception on ACL error
|
||||
*/
|
||||
public function delete($pk = null)
|
||||
{
|
||||
$db = $this->getDbo();
|
||||
$app = Factory::getApplication();
|
||||
$pk = (int) $pk;
|
||||
|
||||
// Gets the workflow information that is going to be deleted.
|
||||
$query = $db->getQuery(true)
|
||||
->select($db->quoteName('default'))
|
||||
->from($db->quoteName('#__workflows'))
|
||||
->where($db->quoteName('id') . ' = :id')
|
||||
->bind(':id', $pk, ParameterType::INTEGER);
|
||||
|
||||
$isDefault = $db->setQuery($query)->loadResult();
|
||||
|
||||
if ($isDefault) {
|
||||
$app->enqueueMessage(Text::_('COM_WORKFLOW_MSG_DELETE_DEFAULT'), 'error');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Delete the workflow states, then transitions from all tables.
|
||||
try {
|
||||
$query = $db->getQuery(true)
|
||||
->delete($db->quoteName('#__workflow_stages'))
|
||||
->where($db->quoteName('workflow_id') . ' = :id')
|
||||
->bind(':id', $pk, ParameterType::INTEGER);
|
||||
|
||||
$db->setQuery($query)->execute();
|
||||
|
||||
$query = $db->getQuery(true)
|
||||
->delete($db->quoteName('#__workflow_transitions'))
|
||||
->where($db->quoteName('workflow_id') . ' = :id')
|
||||
->bind(':id', $pk, ParameterType::INTEGER);
|
||||
|
||||
$db->setQuery($query)->execute();
|
||||
|
||||
return parent::delete($pk);
|
||||
} catch (\RuntimeException $e) {
|
||||
$app->enqueueMessage(Text::sprintf('COM_WORKFLOW_MSG_WORKFLOWS_DELETE_ERROR', $e->getMessage()), 'error');
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overloaded check function
|
||||
*
|
||||
* @return boolean True on success
|
||||
*
|
||||
* @see Table::check()
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function check()
|
||||
{
|
||||
try {
|
||||
parent::check();
|
||||
} catch (\Exception $e) {
|
||||
$this->setError($e->getMessage());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (trim($this->title) === '') {
|
||||
$this->setError(Text::_('JLIB_DATABASE_ERROR_MUSTCONTAIN_A_TITLE_WORKFLOW'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!empty($this->default)) {
|
||||
if ((int) $this->published !== 1) {
|
||||
$this->setError(Text::_('COM_WORKFLOW_ITEM_MUST_PUBLISHED'));
|
||||
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
$db = $this->getDbo();
|
||||
$query = $db->getQuery(true);
|
||||
|
||||
$query
|
||||
->select($db->quoteName('id'))
|
||||
->from($db->quoteName('#__workflows'))
|
||||
->where($db->quoteName('default') . ' = 1');
|
||||
|
||||
$id = $db->setQuery($query)->loadResult();
|
||||
|
||||
// If there is no default workflow => set the current to default to recover
|
||||
if (empty($id)) {
|
||||
$this->default = '1';
|
||||
} elseif ($id === $this->id) {
|
||||
// This workflow is the default, but someone has tried to disable it => not allowed
|
||||
$this->setError(Text::_('COM_WORKFLOW_DISABLE_DEFAULT'));
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overloaded store function
|
||||
*
|
||||
* @param boolean $updateNulls True to update fields even if they are null.
|
||||
*
|
||||
* @return mixed False on failure, positive integer on success.
|
||||
*
|
||||
* @see Table::store()
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function store($updateNulls = true)
|
||||
{
|
||||
$date = Factory::getDate();
|
||||
$user = $this->getCurrentUser();
|
||||
|
||||
$table = new self($this->getDbo(), $this->getDispatcher());
|
||||
|
||||
if ($this->id) {
|
||||
// Existing item
|
||||
$this->modified_by = $user->id;
|
||||
$this->modified = $date->toSql();
|
||||
} else {
|
||||
$this->modified_by = 0;
|
||||
}
|
||||
|
||||
if (!(int) $this->created) {
|
||||
$this->created = $date->toSql();
|
||||
}
|
||||
|
||||
if (empty($this->created_by)) {
|
||||
$this->created_by = $user->id;
|
||||
}
|
||||
|
||||
if (!(int) $this->modified) {
|
||||
$this->modified = $this->created;
|
||||
}
|
||||
|
||||
if (empty($this->modified_by)) {
|
||||
$this->modified_by = $this->created_by;
|
||||
}
|
||||
|
||||
if ((int) $this->default === 1) {
|
||||
// Verify that the default is unique for this workflow
|
||||
if (
|
||||
$table->load(
|
||||
[
|
||||
'default' => '1',
|
||||
'extension' => $this->extension,
|
||||
]
|
||||
)
|
||||
) {
|
||||
$table->default = 0;
|
||||
$table->store();
|
||||
}
|
||||
}
|
||||
|
||||
return parent::store($updateNulls);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to bind an associative array or object to the Table instance.
|
||||
* This method only binds properties that are publicly accessible and optionally
|
||||
* takes an array of properties to ignore when binding.
|
||||
*
|
||||
* @param array|object $src An associative array or object to bind to the Table instance.
|
||||
* @param array|string $ignore An optional array or space separated list of properties to ignore while binding.
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 4.0.0
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function bind($src, $ignore = [])
|
||||
{
|
||||
// Bind the rules.
|
||||
if (isset($src['rules']) && \is_array($src['rules'])) {
|
||||
$rules = new Rules($src['rules']);
|
||||
$this->setRules($rules);
|
||||
}
|
||||
|
||||
return parent::bind($src, $ignore);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to compute the default name of the asset.
|
||||
* The default name is in the form table_name.id
|
||||
* where id is the value of the primary key of the table.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function _getAssetName()
|
||||
{
|
||||
$k = $this->_tbl_key;
|
||||
|
||||
$parts = explode('.', $this->extension);
|
||||
|
||||
$extension = array_shift($parts);
|
||||
|
||||
return $extension . '.workflow.' . (int) $this->$k;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to return the title to use for the asset table.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function _getAssetTitle()
|
||||
{
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parent asset id for the record
|
||||
*
|
||||
* @param Table $table A Table object for the asset parent.
|
||||
* @param integer $id The id for the asset
|
||||
*
|
||||
* @return integer The id of the asset's parent
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function _getAssetParentId(Table $table = null, $id = null)
|
||||
{
|
||||
$assetId = null;
|
||||
|
||||
$parts = explode('.', $this->extension);
|
||||
|
||||
$extension = array_shift($parts);
|
||||
|
||||
// Build the query to get the asset id for the parent category.
|
||||
$query = $this->getDbo()->getQuery(true)
|
||||
->select($this->getDbo()->quoteName('id'))
|
||||
->from($this->getDbo()->quoteName('#__assets'))
|
||||
->where($this->getDbo()->quoteName('name') . ' = :extension')
|
||||
->bind(':extension', $extension);
|
||||
|
||||
// Get the asset id from the database.
|
||||
$this->getDbo()->setQuery($query);
|
||||
|
||||
if ($result = $this->getDbo()->loadResult()) {
|
||||
$assetId = (int) $result;
|
||||
}
|
||||
|
||||
// Return the asset id.
|
||||
if ($assetId) {
|
||||
return $assetId;
|
||||
}
|
||||
|
||||
return parent::_getAssetParentId($table, $id);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,175 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_workflow
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Workflow\Administrator\View\Stage;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\View\GenericDataException;
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
use Joomla\CMS\Toolbar\Toolbar;
|
||||
use Joomla\CMS\Toolbar\ToolbarHelper;
|
||||
use Joomla\Component\Workflow\Administrator\Helper\StageHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* View class to add or edit a stage of a workflow
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
/**
|
||||
* The model state
|
||||
*
|
||||
* @var object
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* From object to generate fields
|
||||
*
|
||||
* @var \Joomla\CMS\Form\Form
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $form;
|
||||
|
||||
/**
|
||||
* Items array
|
||||
*
|
||||
* @var object
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $item;
|
||||
|
||||
/**
|
||||
* The name of current extension
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $extension;
|
||||
|
||||
/**
|
||||
* The section of the current extension
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $section;
|
||||
|
||||
/**
|
||||
* Display item view
|
||||
*
|
||||
* @param string $tpl The name of the template file to parse; automatically searches through the template paths.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function display($tpl = null)
|
||||
{
|
||||
// Get the Data
|
||||
$this->state = $this->get('State');
|
||||
$this->form = $this->get('Form');
|
||||
$this->item = $this->get('Item');
|
||||
|
||||
// Check for errors.
|
||||
if (\count($errors = $this->get('Errors'))) {
|
||||
throw new GenericDataException(implode("\n", $errors), 500);
|
||||
}
|
||||
|
||||
$extension = $this->state->get('filter.extension');
|
||||
|
||||
$parts = explode('.', $extension);
|
||||
|
||||
$this->extension = array_shift($parts);
|
||||
|
||||
if (!empty($parts)) {
|
||||
$this->section = array_shift($parts);
|
||||
}
|
||||
|
||||
// Set the toolbar
|
||||
$this->addToolbar();
|
||||
|
||||
// Display the template
|
||||
parent::display($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the page title and toolbar.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function addToolbar()
|
||||
{
|
||||
Factory::getApplication()->getInput()->set('hidemainmenu', true);
|
||||
|
||||
$user = $this->getCurrentUser();
|
||||
$userId = $user->id;
|
||||
$isNew = empty($this->item->id);
|
||||
$toolbar = Toolbar::getInstance();
|
||||
|
||||
$canDo = StageHelper::getActions($this->extension, 'stage', $this->item->id);
|
||||
|
||||
ToolbarHelper::title(empty($this->item->id) ? Text::_('COM_WORKFLOW_STAGE_ADD') : Text::_('COM_WORKFLOW_STAGE_EDIT'), 'address');
|
||||
|
||||
if ($isNew) {
|
||||
// For new records, check the create permission.
|
||||
if ($canDo->get('core.create')) {
|
||||
$toolbar->apply('stage.apply');
|
||||
}
|
||||
|
||||
$saveGroup = $toolbar->dropdownButton('save-group');
|
||||
$saveGroup->configure(
|
||||
function (Toolbar $childBar) use ($canDo) {
|
||||
// For new records, check the create permission.
|
||||
if ($canDo->get('core.create')) {
|
||||
$childBar->save('stage.save');
|
||||
$childBar->save2new('stage.save2new');
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
$toolbar->cancel('stage.cancel', 'JTOOLBAR_CANCEL');
|
||||
} else {
|
||||
// Since it's an existing record, check the edit permission, or fall back to edit own if the owner.
|
||||
$itemEditable = $canDo->get('core.edit') || ($canDo->get('core.edit.own') && $this->item->created_by == $userId);
|
||||
|
||||
if ($itemEditable) {
|
||||
$toolbar->apply('stage.apply');
|
||||
|
||||
$saveGroup = $toolbar->dropdownButton('save-group');
|
||||
$saveGroup->configure(
|
||||
function (Toolbar $childBar) use ($canDo) {
|
||||
$childBar->save('stage.save');
|
||||
|
||||
// We can save this record, but check the create permission to see if we can return to make a new one.
|
||||
if ($canDo->get('core.create')) {
|
||||
$childBar->save2new('stage.save2new');
|
||||
$childBar->save2copy('stage.save2copy');
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
$toolbar->cancel('stage.cancel');
|
||||
}
|
||||
|
||||
$toolbar->divider();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,213 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_workflow
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Workflow\Administrator\View\Stages;
|
||||
|
||||
use Joomla\CMS\Helper\ContentHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\View\GenericDataException;
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\Toolbar\Button\DropdownButton;
|
||||
use Joomla\CMS\Toolbar\Toolbar;
|
||||
use Joomla\CMS\Toolbar\ToolbarHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Stages view class for the Workflow package.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
/**
|
||||
* An array of stages
|
||||
*
|
||||
* @var array
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $stages;
|
||||
|
||||
/**
|
||||
* The model stage
|
||||
*
|
||||
* @var object
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $stage;
|
||||
|
||||
/**
|
||||
* The HTML for displaying sidebar
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $sidebar;
|
||||
|
||||
/**
|
||||
* The pagination object
|
||||
*
|
||||
* @var \Joomla\CMS\Pagination\Pagination
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $pagination;
|
||||
|
||||
/**
|
||||
* Form object for search filters
|
||||
*
|
||||
* @var \Joomla\CMS\Form\Form
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public $filterForm;
|
||||
|
||||
/**
|
||||
* The active search filters
|
||||
*
|
||||
* @var array
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public $activeFilters;
|
||||
|
||||
/**
|
||||
* The current workflow
|
||||
*
|
||||
* @var object
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $workflow;
|
||||
|
||||
/**
|
||||
* The ID of current workflow
|
||||
*
|
||||
* @var integer
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $workflowID;
|
||||
|
||||
/**
|
||||
* The name of current extension
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $extension;
|
||||
|
||||
/**
|
||||
* The section of the current extension
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $section;
|
||||
|
||||
/**
|
||||
* Display the view
|
||||
*
|
||||
* @param string $tpl The name of the template file to parse; automatically searches through the template paths.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function display($tpl = null)
|
||||
{
|
||||
$this->state = $this->get('State');
|
||||
$this->stages = $this->get('Items');
|
||||
$this->pagination = $this->get('Pagination');
|
||||
$this->filterForm = $this->get('FilterForm');
|
||||
$this->activeFilters = $this->get('ActiveFilters');
|
||||
$this->workflow = $this->get('Workflow');
|
||||
|
||||
// Check for errors.
|
||||
if (\count($errors = $this->get('Errors'))) {
|
||||
throw new GenericDataException(implode("\n", $errors), 500);
|
||||
}
|
||||
|
||||
$this->workflowID = $this->workflow->id;
|
||||
|
||||
$parts = explode('.', $this->workflow->extension);
|
||||
|
||||
$this->extension = array_shift($parts);
|
||||
|
||||
if (!empty($parts)) {
|
||||
$this->section = array_shift($parts);
|
||||
}
|
||||
|
||||
$this->addToolbar();
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the page title and toolbar.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function addToolbar()
|
||||
{
|
||||
$canDo = ContentHelper::getActions($this->extension, 'workflow', $this->workflowID);
|
||||
|
||||
$user = $this->getCurrentUser();
|
||||
|
||||
$toolbar = Toolbar::getInstance('toolbar');
|
||||
|
||||
ToolbarHelper::title(Text::sprintf('COM_WORKFLOW_STAGES_LIST', Text::_($this->state->get('active_workflow', ''))), 'address contact');
|
||||
|
||||
$arrow = $this->getLanguage()->isRtl() ? 'arrow-right' : 'arrow-left';
|
||||
|
||||
$toolbar->link(
|
||||
'JTOOLBAR_BACK',
|
||||
Route::_('index.php?option=com_workflow&view=workflows&extension=' . $this->escape($this->workflow->extension))
|
||||
)
|
||||
->icon('icon-' . $arrow);
|
||||
|
||||
if ($canDo->get('core.create')) {
|
||||
$toolbar->addNew('stage.add');
|
||||
}
|
||||
|
||||
if ($canDo->get('core.edit.state') || $user->authorise('core.admin')) {
|
||||
/** @var DropdownButton $dropdown */
|
||||
$dropdown = $toolbar->dropdownButton('status-group', 'JTOOLBAR_CHANGE_STATUS')
|
||||
->toggleSplit(false)
|
||||
->icon('icon-ellipsis-h')
|
||||
->buttonClass('btn btn-action')
|
||||
->listCheck(true);
|
||||
|
||||
$childBar = $dropdown->getChildToolbar();
|
||||
|
||||
$childBar->publish('stages.publish', 'JTOOLBAR_ENABLE')->listCheck(true);
|
||||
$childBar->unpublish('stages.unpublish', 'JTOOLBAR_DISABLE')->listCheck(true);
|
||||
$childBar->makeDefault('stages.setDefault', 'COM_WORKFLOW_TOOLBAR_DEFAULT');
|
||||
|
||||
if ($canDo->get('core.admin')) {
|
||||
$childBar->checkin('stages.checkin')->listCheck(true);
|
||||
}
|
||||
|
||||
if ($this->state->get('filter.published') !== '-2') {
|
||||
$childBar->trash('stages.trash');
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->state->get('filter.published') === '-2' && $canDo->get('core.delete')) {
|
||||
$toolbar->delete('stages.delete', 'JTOOLBAR_EMPTY_TRASH')
|
||||
->message('JGLOBAL_CONFIRM_DELETE')
|
||||
->listCheck(true);
|
||||
}
|
||||
|
||||
$toolbar->help('Stages_List:_Basic_Workflow');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,207 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_workflow
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Workflow\Administrator\View\Transition;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\View\GenericDataException;
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
use Joomla\CMS\Toolbar\Toolbar;
|
||||
use Joomla\CMS\Toolbar\ToolbarHelper;
|
||||
use Joomla\Component\Workflow\Administrator\Helper\StageHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* View class to add or edit a transition of a workflow
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
/**
|
||||
* The model state
|
||||
*
|
||||
* @var object
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* Form object to generate fields
|
||||
*
|
||||
* @var \Joomla\CMS\Form\Form
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $form;
|
||||
|
||||
/**
|
||||
* Items array
|
||||
*
|
||||
* @var object
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $item;
|
||||
|
||||
/**
|
||||
* That is object of Application
|
||||
*
|
||||
* @var \Joomla\CMS\Application\CMSApplication
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $app;
|
||||
|
||||
/**
|
||||
* The application input object.
|
||||
*
|
||||
* @var \Joomla\CMS\Input\Input
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $input;
|
||||
|
||||
/**
|
||||
* The ID of current workflow
|
||||
*
|
||||
* @var integer
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $workflowID;
|
||||
|
||||
/**
|
||||
* The name of current extension
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $extension;
|
||||
|
||||
/**
|
||||
* The section of the current extension
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $section;
|
||||
|
||||
/**
|
||||
* Display item view
|
||||
*
|
||||
* @param string $tpl The name of the template file to parse; automatically searches through the template paths.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function display($tpl = null)
|
||||
{
|
||||
$this->app = Factory::getApplication();
|
||||
$this->input = $this->app->getInput();
|
||||
|
||||
// Get the Data
|
||||
$this->state = $this->get('State');
|
||||
$this->form = $this->get('Form');
|
||||
$this->item = $this->get('Item');
|
||||
|
||||
// Check for errors.
|
||||
if (\count($errors = $this->get('Errors'))) {
|
||||
throw new GenericDataException(implode("\n", $errors), 500);
|
||||
}
|
||||
|
||||
$extension = $this->state->get('filter.extension');
|
||||
|
||||
$parts = explode('.', $extension);
|
||||
|
||||
$this->extension = array_shift($parts);
|
||||
|
||||
if (!empty($parts)) {
|
||||
$this->section = array_shift($parts);
|
||||
}
|
||||
|
||||
// Get the ID of workflow
|
||||
$this->workflowID = $this->input->getCmd("workflow_id");
|
||||
|
||||
// Set the toolbar
|
||||
$this->addToolbar();
|
||||
|
||||
// Display the template
|
||||
parent::display($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the page title and toolbar.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function addToolbar()
|
||||
{
|
||||
Factory::getApplication()->getInput()->set('hidemainmenu', true);
|
||||
|
||||
$user = $this->getCurrentUser();
|
||||
$userId = $user->id;
|
||||
$isNew = empty($this->item->id);
|
||||
$toolbar = Toolbar::getInstance();
|
||||
$canDo = StageHelper::getActions($this->extension, 'transition', $this->item->id);
|
||||
$canCreate = $canDo->get('core.create');
|
||||
|
||||
ToolbarHelper::title(empty($this->item->id) ? Text::_('COM_WORKFLOW_TRANSITION_ADD') : Text::_('COM_WORKFLOW_TRANSITION_EDIT'), 'address');
|
||||
|
||||
if ($isNew) {
|
||||
// For new records, check the create permission.
|
||||
if ($canCreate) {
|
||||
$toolbar->apply('transition.apply');
|
||||
|
||||
$saveGroup = $toolbar->dropdownButton('save-group');
|
||||
|
||||
$saveGroup->configure(
|
||||
function (Toolbar $childBar) {
|
||||
// For new records, check the create permission.
|
||||
$childBar->save('transition.save');
|
||||
$childBar->save2new('transition.save2new');
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
$toolbar->cancel('transition.cancel', 'JTOOLBAR_CANCEL');
|
||||
} else {
|
||||
// Since it's an existing record, check the edit permission, or fall back to edit own if the owner.
|
||||
$itemEditable = $canDo->get('core.edit') || ($canDo->get('core.edit.own') && $this->item->created_by == $userId);
|
||||
|
||||
if ($itemEditable) {
|
||||
$toolbar->apply('transition.apply');
|
||||
} else {
|
||||
$toolbar->save('transition.save');
|
||||
}
|
||||
|
||||
$saveGroup = $toolbar->dropdownButton('save-group');
|
||||
|
||||
$saveGroup->configure(
|
||||
function (Toolbar $childBar) use ($canCreate) {
|
||||
$childBar->save('transition.save');
|
||||
|
||||
// We can save this record, but check the create permission to see if we can return to make a new one.
|
||||
if ($canCreate) {
|
||||
$childBar->save2new('transition.save2new');
|
||||
$childBar->save2copy('transition.save2copy');
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
$toolbar->cancel('transition.cancel');
|
||||
}
|
||||
|
||||
$toolbar->divider();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,210 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_workflow
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Workflow\Administrator\View\Transitions;
|
||||
|
||||
use Joomla\CMS\Helper\ContentHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\View\GenericDataException;
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\Toolbar\Button\DropdownButton;
|
||||
use Joomla\CMS\Toolbar\Toolbar;
|
||||
use Joomla\CMS\Toolbar\ToolbarHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Transitions view class for the Workflow package.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
/**
|
||||
* An array of transitions
|
||||
*
|
||||
* @var array
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $transitions;
|
||||
|
||||
/**
|
||||
* The model state
|
||||
*
|
||||
* @var object
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* The HTML for displaying sidebar
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $sidebar;
|
||||
|
||||
/**
|
||||
* The pagination object
|
||||
*
|
||||
* @var \Joomla\CMS\Pagination\Pagination
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $pagination;
|
||||
|
||||
/**
|
||||
* Form object for search filters
|
||||
*
|
||||
* @var \Joomla\CMS\Form\Form
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public $filterForm;
|
||||
|
||||
/**
|
||||
* The active search filters
|
||||
*
|
||||
* @var array
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public $activeFilters;
|
||||
|
||||
/**
|
||||
* The current workflow
|
||||
*
|
||||
* @var object
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $workflow;
|
||||
|
||||
/**
|
||||
* The ID of current workflow
|
||||
*
|
||||
* @var integer
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $workflowID;
|
||||
|
||||
/**
|
||||
* The name of current extension
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $extension;
|
||||
|
||||
/**
|
||||
* The section of the current extension
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $section;
|
||||
|
||||
/**
|
||||
* Display the view
|
||||
*
|
||||
* @param string $tpl The name of the template file to parse; automatically searches through the template paths.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function display($tpl = null)
|
||||
{
|
||||
$this->state = $this->get('State');
|
||||
$this->transitions = $this->get('Items');
|
||||
$this->pagination = $this->get('Pagination');
|
||||
$this->filterForm = $this->get('FilterForm');
|
||||
$this->activeFilters = $this->get('ActiveFilters');
|
||||
$this->workflow = $this->get('Workflow');
|
||||
|
||||
// Check for errors.
|
||||
if (\count($errors = $this->get('Errors'))) {
|
||||
throw new GenericDataException(implode("\n", $errors), 500);
|
||||
}
|
||||
|
||||
$this->workflowID = $this->workflow->id;
|
||||
|
||||
$parts = explode('.', $this->workflow->extension);
|
||||
|
||||
$this->extension = array_shift($parts);
|
||||
|
||||
if (!empty($parts)) {
|
||||
$this->section = array_shift($parts);
|
||||
}
|
||||
|
||||
$this->addToolbar();
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the page title and toolbar.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function addToolbar()
|
||||
{
|
||||
$canDo = ContentHelper::getActions($this->extension, 'workflow', $this->workflowID);
|
||||
$user = $this->getCurrentUser();
|
||||
$toolbar = Toolbar::getInstance();
|
||||
|
||||
ToolbarHelper::title(Text::sprintf('COM_WORKFLOW_TRANSITIONS_LIST', Text::_($this->state->get('active_workflow'))), 'address contact');
|
||||
|
||||
$arrow = $this->getLanguage()->isRtl() ? 'arrow-right' : 'arrow-left';
|
||||
|
||||
$toolbar->link(
|
||||
'JTOOLBAR_BACK',
|
||||
Route::_('index.php?option=com_workflow&view=workflows&extension=' . $this->escape($this->workflow->extension))
|
||||
)
|
||||
->icon('icon-' . $arrow);
|
||||
|
||||
if ($canDo->get('core.create')) {
|
||||
$toolbar->addNew('transition.add');
|
||||
}
|
||||
|
||||
if ($canDo->get('core.edit.state') || $user->authorise('core.admin')) {
|
||||
/** @var DropdownButton $dropdown */
|
||||
$dropdown = $toolbar->dropdownButton('status-group', 'JTOOLBAR_CHANGE_STATUS')
|
||||
->toggleSplit(false)
|
||||
->icon('icon-ellipsis-h')
|
||||
->buttonClass('btn btn-action')
|
||||
->listCheck(true);
|
||||
|
||||
$childBar = $dropdown->getChildToolbar();
|
||||
|
||||
$childBar->publish('transitions.publish', 'JTOOLBAR_ENABLE');
|
||||
$childBar->unpublish('transitions.unpublish', 'JTOOLBAR_DISABLE');
|
||||
|
||||
if ($canDo->get('core.admin')) {
|
||||
$childBar->checkin('transitions.checkin')->listCheck(true);
|
||||
}
|
||||
|
||||
if ($this->state->get('filter.published') !== '-2') {
|
||||
$childBar->trash('transitions.trash');
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->state->get('filter.published') === '-2' && $canDo->get('core.delete')) {
|
||||
$toolbar->delete('transitions.delete', 'JTOOLBAR_EMPTY_TRASH')
|
||||
->message('JGLOBAL_CONFIRM_DELETE')
|
||||
->listCheck(true);
|
||||
}
|
||||
|
||||
$toolbar->help('Transitions_List:_Basic_Workflow');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,176 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_workflow
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Workflow\Administrator\View\Workflow;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\View\GenericDataException;
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
use Joomla\CMS\Toolbar\Toolbar;
|
||||
use Joomla\CMS\Toolbar\ToolbarHelper;
|
||||
use Joomla\Component\Workflow\Administrator\Helper\WorkflowHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* View class to add or edit a workflow
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
/**
|
||||
* The model state
|
||||
*
|
||||
* @var object
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* The Form object
|
||||
*
|
||||
* @var \Joomla\CMS\Form\Form
|
||||
*/
|
||||
protected $form;
|
||||
|
||||
/**
|
||||
* The active item
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
protected $item;
|
||||
|
||||
/**
|
||||
* The ID of current workflow
|
||||
*
|
||||
* @var integer
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $workflowID;
|
||||
|
||||
/**
|
||||
* The name of current extension
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $extension;
|
||||
|
||||
/**
|
||||
* The section of the current extension
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $section;
|
||||
|
||||
/**
|
||||
* Display item view
|
||||
*
|
||||
* @param string $tpl The name of the template file to parse; automatically searches through the template paths.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function display($tpl = null)
|
||||
{
|
||||
// Get the Data
|
||||
$this->state = $this->get('State');
|
||||
$this->form = $this->get('Form');
|
||||
$this->item = $this->get('Item');
|
||||
|
||||
// Check for errors.
|
||||
if (\count($errors = $this->get('Errors'))) {
|
||||
throw new GenericDataException(implode("\n", $errors), 500);
|
||||
}
|
||||
|
||||
$extension = $this->state->get('filter.extension');
|
||||
|
||||
$parts = explode('.', $extension);
|
||||
|
||||
$this->extension = array_shift($parts);
|
||||
|
||||
if (!empty($parts)) {
|
||||
$this->section = array_shift($parts);
|
||||
}
|
||||
|
||||
// Set the toolbar
|
||||
$this->addToolbar();
|
||||
|
||||
// Display the template
|
||||
parent::display($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the page title and toolbar.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function addToolbar()
|
||||
{
|
||||
Factory::getApplication()->getInput()->set('hidemainmenu', true);
|
||||
|
||||
$user = $this->getCurrentUser();
|
||||
$userId = $user->id;
|
||||
$isNew = empty($this->item->id);
|
||||
$toolbar = Toolbar::getInstance();
|
||||
$canDo = WorkflowHelper::getActions($this->extension, 'workflow', $this->item->id);
|
||||
|
||||
ToolbarHelper::title(empty($this->item->id) ? Text::_('COM_WORKFLOW_WORKFLOWS_ADD') : Text::_('COM_WORKFLOW_WORKFLOWS_EDIT'), 'address');
|
||||
|
||||
if ($isNew) {
|
||||
// For new records, check the create permission.
|
||||
if ($canDo->get('core.create')) {
|
||||
$toolbar->apply('workflow.apply');
|
||||
|
||||
$saveGroup = $toolbar->dropdownButton('save-group');
|
||||
|
||||
$saveGroup->configure(
|
||||
function (Toolbar $childBar) {
|
||||
$childBar->save('workflow.save');
|
||||
$childBar->save2new('workflow.save2new');
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
$toolbar->cancel('workflow.cancel', 'JTOOLBAR_CANCEL');
|
||||
} else {
|
||||
// Since it's an existing record, check the edit permission, or fall back to edit own if the owner.
|
||||
$itemEditable = $canDo->get('core.edit') || ($canDo->get('core.edit.own') && $this->item->created_by == $userId);
|
||||
|
||||
if ($itemEditable) {
|
||||
$toolbar->apply('workflow.apply');
|
||||
|
||||
$saveGroup = $toolbar->dropdownButton('save-group');
|
||||
|
||||
$saveGroup->configure(
|
||||
function (Toolbar $childBar) use ($canDo) {
|
||||
$childBar->save('workflow.save');
|
||||
|
||||
// We can save this record, but check the create permission to see if we can return to make a new one.
|
||||
if ($canDo->get('core.create')) {
|
||||
$childBar->save2new('workflow.save2new');
|
||||
$childBar->save2copy('workflow.save2copy');
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
$toolbar->cancel('workflow.cancel');
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,187 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_workflow
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Workflow\Administrator\View\Workflows;
|
||||
|
||||
use Joomla\CMS\Helper\ContentHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\View\GenericDataException;
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
use Joomla\CMS\Toolbar\Button\DropdownButton;
|
||||
use Joomla\CMS\Toolbar\Toolbar;
|
||||
use Joomla\CMS\Toolbar\ToolbarHelper;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Workflows view class for the Workflow package.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
/**
|
||||
* An array of workflows
|
||||
*
|
||||
* @var array
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $workflows;
|
||||
|
||||
/**
|
||||
* The model state
|
||||
*
|
||||
* @var object
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* The pagination object
|
||||
*
|
||||
* @var \Joomla\CMS\Pagination\Pagination
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $pagination;
|
||||
|
||||
/**
|
||||
* The HTML for displaying sidebar
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $sidebar;
|
||||
|
||||
/**
|
||||
* Form object for search filters
|
||||
*
|
||||
* @var \Joomla\CMS\Form\Form
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public $filterForm;
|
||||
|
||||
/**
|
||||
* The active search filters
|
||||
*
|
||||
* @var array
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public $activeFilters;
|
||||
|
||||
/**
|
||||
* The name of current extension
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $extension;
|
||||
|
||||
/**
|
||||
* The section of the current extension
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected $section;
|
||||
|
||||
/**
|
||||
* Display the view
|
||||
*
|
||||
* @param string $tpl The name of the template file to parse; automatically searches through the template paths.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function display($tpl = null)
|
||||
{
|
||||
$this->state = $this->get('State');
|
||||
$this->workflows = $this->get('Items');
|
||||
$this->pagination = $this->get('Pagination');
|
||||
$this->filterForm = $this->get('FilterForm');
|
||||
$this->activeFilters = $this->get('ActiveFilters');
|
||||
|
||||
// Check for errors.
|
||||
if (\count($errors = $this->get('Errors'))) {
|
||||
throw new GenericDataException(implode("\n", $errors), 500);
|
||||
}
|
||||
|
||||
$extension = $this->state->get('filter.extension');
|
||||
|
||||
$parts = explode('.', $extension);
|
||||
|
||||
$this->extension = array_shift($parts);
|
||||
|
||||
if (!empty($parts)) {
|
||||
$this->section = array_shift($parts);
|
||||
}
|
||||
|
||||
$this->addToolbar();
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the page title and toolbar.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
protected function addToolbar()
|
||||
{
|
||||
$canDo = ContentHelper::getActions($this->extension, $this->section);
|
||||
$user = $this->getCurrentUser();
|
||||
$toolbar = Toolbar::getInstance();
|
||||
|
||||
ToolbarHelper::title(Text::_('COM_WORKFLOW_WORKFLOWS_LIST'), 'file-alt contact');
|
||||
|
||||
if ($canDo->get('core.create')) {
|
||||
$toolbar->addNew('workflow.add');
|
||||
}
|
||||
|
||||
if ($canDo->get('core.edit.state') || $user->authorise('core.admin')) {
|
||||
/** @var DropdownButton $dropdown */
|
||||
$dropdown = $toolbar->dropdownButton('status-group', 'JTOOLBAR_CHANGE_STATUS')
|
||||
->toggleSplit(false)
|
||||
->icon('icon-ellipsis-h')
|
||||
->buttonClass('btn btn-action')
|
||||
->listCheck(true);
|
||||
|
||||
$childBar = $dropdown->getChildToolbar();
|
||||
|
||||
$childBar->publish('workflows.publish', 'JTOOLBAR_ENABLE');
|
||||
$childBar->unpublish('workflows.unpublish', 'JTOOLBAR_DISABLE');
|
||||
$childBar->makeDefault('workflows.setDefault', 'COM_WORKFLOW_TOOLBAR_DEFAULT');
|
||||
|
||||
if ($canDo->get('core.admin')) {
|
||||
$childBar->checkin('workflows.checkin')->listCheck(true);
|
||||
}
|
||||
|
||||
if ($canDo->get('core.edit.state') && $this->state->get('filter.published') != -2) {
|
||||
$childBar->trash('workflows.trash');
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->state->get('filter.published') === '-2' && $canDo->get('core.delete')) {
|
||||
$toolbar->delete('workflows.delete', 'JTOOLBAR_EMPTY_TRASH')
|
||||
->message('JGLOBAL_CONFIRM_DELETE')
|
||||
->listCheck(true);
|
||||
}
|
||||
|
||||
if ($canDo->get('core.admin') || $canDo->get('core.options')) {
|
||||
$toolbar->preferences($this->extension);
|
||||
}
|
||||
|
||||
$toolbar->help('Workflows_List');
|
||||
}
|
||||
}
|
||||
89
administrator/components/com_workflow/tmpl/stage/edit.php
Normal file
89
administrator/components/com_workflow/tmpl/stage/edit.php
Normal file
@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_workflow
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Layout\LayoutHelper;
|
||||
use Joomla\CMS\Router\Route;
|
||||
|
||||
/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
|
||||
$wa = $this->document->getWebAssetManager();
|
||||
$wa->useScript('keepalive')
|
||||
->useScript('form.validate');
|
||||
|
||||
$app = Factory::getApplication();
|
||||
$user = $app->getIdentity();
|
||||
$input = $app->getInput();
|
||||
|
||||
// In case of modal
|
||||
$isModal = $input->get('layout') === 'modal';
|
||||
$layout = $isModal ? 'modal' : 'edit';
|
||||
$tmpl = $isModal || $input->get('tmpl', '', 'cmd') === 'component' ? '&tmpl=component' : '';
|
||||
$clientId = $this->state->get('item.client_id', 0);
|
||||
$lang = $this->getLanguage()->getTag();
|
||||
|
||||
?>
|
||||
|
||||
<form action="<?php echo Route::_('index.php?option=com_workflow&view=stage&workflow_id=' . $input->getCmd('workflow_id') . '&extension=' . $input->getCmd('extension') . '&layout=' . $layout . $tmpl . '&id=' . (int) $this->item->id); ?>" method="post" name="adminForm" id="workflow-form" aria-label="<?php echo Text::_('COM_WORKFLOW_STAGE_FORM_' . ((int) $this->item->id === 0 ? 'NEW' : 'EDIT'), true); ?>" class="form-validate">
|
||||
|
||||
<?php echo LayoutHelper::render('joomla.edit.title_alias', $this); ?>
|
||||
|
||||
<?php // Add the translation of the workflow item title when client is administrator ?>
|
||||
<?php if ($clientId === 0 && $this->item->id != 0) : ?>
|
||||
<div class="row title-alias form-vertical mb-3">
|
||||
<div class="col-12">
|
||||
<div class="control-group">
|
||||
<div class="control-label">
|
||||
<label for="stage_title_translation"><?php echo Text::sprintf('COM_WORKFLOW_TITLE_TRANSLATION', $lang); ?></label>
|
||||
</div>
|
||||
<div class="controls">
|
||||
<input id="stage_title_translation" class="form-control" value="<?php echo Text::_($this->item->title); ?>" readonly="readonly" type="text">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="main-card">
|
||||
<?php echo HTMLHelper::_('uitab.startTabSet', 'myTab', ['active' => 'details', 'recall' => true, 'breakpoint' => 768]); ?>
|
||||
|
||||
<?php echo HTMLHelper::_('uitab.addTab', 'myTab', 'details', Text::_('COM_WORKFLOW_DESCRIPTION')); ?>
|
||||
<div class="row">
|
||||
<div class="col-lg-9">
|
||||
<?php echo $this->form->renderField('description'); ?>
|
||||
</div>
|
||||
<div class="col-lg-3">
|
||||
<fieldset class="form-vertical">
|
||||
<?php echo $this->form->renderField('published'); ?>
|
||||
<?php echo $this->form->renderField('default'); ?>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
<?php echo HTMLHelper::_('uitab.endTab'); ?>
|
||||
|
||||
<?php if ($user->authorise('core.admin', $this->extension)) : ?>
|
||||
<?php echo HTMLHelper::_('uitab.addTab', 'myTab', 'permissions', Text::_('COM_WORKFLOW_RULES_TAB')); ?>
|
||||
<fieldset id="fieldset-rules" class="options-form">
|
||||
<legend><?php echo Text::_('COM_WORKFLOW_RULES_TAB'); ?></legend>
|
||||
<?php echo $this->form->getInput('rules'); ?>
|
||||
</fieldset>
|
||||
<?php echo HTMLHelper::_('uitab.endTab'); ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php echo HTMLHelper::_('uitab.endTabSet'); ?>
|
||||
|
||||
<?php echo $this->form->getInput('workflow_id'); ?>
|
||||
<input type="hidden" name="task" value="stage.edit" />
|
||||
<?php echo HTMLHelper::_('form.token'); ?>
|
||||
</div>
|
||||
</form>
|
||||
158
administrator/components/com_workflow/tmpl/stages/default.php
Normal file
158
administrator/components/com_workflow/tmpl/stages/default.php
Normal file
@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_workflow
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
* @since 4.0.0
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Layout\LayoutHelper;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\Session\Session;
|
||||
|
||||
/** @var \Joomla\CMS\WebAsset\WebAssetManager $wa */
|
||||
$wa = $this->document->getWebAssetManager();
|
||||
$wa->useScript('table.columns')
|
||||
->useScript('multiselect');
|
||||
|
||||
$user = $this->getCurrentUser();
|
||||
$userId = $user->id;
|
||||
|
||||
$listOrder = $this->escape($this->state->get('list.ordering'));
|
||||
$listDirn = $this->escape($this->state->get('list.direction'));
|
||||
$saveOrderingUrl = '';
|
||||
|
||||
$saveOrder = ($listOrder == 's.ordering');
|
||||
|
||||
if ($saveOrder) {
|
||||
$saveOrderingUrl = 'index.php?option=com_workflow&task=stages.saveOrderAjax&workflow_id=' . (int) $this->workflowID . '&extension=' . $this->escape($this->extension) . '&' . Session::getFormToken() . '=1';
|
||||
HTMLHelper::_('draggablelist.draggable');
|
||||
}
|
||||
?>
|
||||
<form action="<?php echo Route::_('index.php?option=com_workflow&view=stages&workflow_id=' . (int) $this->workflowID . '&extension=' . $this->extension); ?>" method="post" name="adminForm" id="adminForm">
|
||||
<div class="row">
|
||||
<?php if (!empty($this->sidebar)) : ?>
|
||||
<div id="j-sidebar-container" class="col-md-2">
|
||||
<?php echo $this->sidebar; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="<?php if (!empty($this->sidebar)) {
|
||||
echo 'col-md-10';
|
||||
} else {
|
||||
echo 'col-md-12';
|
||||
} ?>">
|
||||
<div id="j-main-container" class="j-main-container">
|
||||
<?php
|
||||
// Search tools bar
|
||||
echo LayoutHelper::render('joomla.searchtools.default', ['view' => $this]);
|
||||
?>
|
||||
<?php if (empty($this->stages)) : ?>
|
||||
<div class="alert alert-info">
|
||||
<span class="icon-info-circle" aria-hidden="true"></span><span class="visually-hidden"><?php echo Text::_('INFO'); ?></span>
|
||||
<?php echo Text::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<table class="table">
|
||||
<caption class="visually-hidden">
|
||||
<?php echo Text::_('COM_WORKFLOW_STAGES_TABLE_CAPTION'); ?>,
|
||||
<span id="orderedBy"><?php echo Text::_('JGLOBAL_SORTED_BY'); ?> </span>,
|
||||
<span id="filteredBy"><?php echo Text::_('JGLOBAL_FILTERED_BY'); ?></span>
|
||||
</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="w-1 text-center d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('grid.checkall'); ?>
|
||||
</td>
|
||||
<th scope="col" class="w-1 text-center d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', '', 's.ordering', $listDirn, $listOrder, null, 'asc', 'JGRID_HEADING_ORDERING', 'icon-menu-2'); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-1 text-center">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'JSTATUS', 's.published', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-1 text-center">
|
||||
<?php echo Text::_('COM_WORKFLOW_DEFAULT'); ?>
|
||||
</th>
|
||||
<th scope="col">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_WORKFLOW_NAME', 's.title', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-5 d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_WORKFLOW_ID', 's.id', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="js-draggable" data-url="<?php echo $saveOrderingUrl; ?>" data-direction="<?php echo strtolower($listDirn); ?>">
|
||||
<?php foreach ($this->stages as $i => $item) :
|
||||
$edit = Route::_('index.php?option=com_workflow&task=stage.edit&id=' . $item->id . '&workflow_id=' . (int) $this->workflowID . '&extension=' . $this->extension);
|
||||
|
||||
$canEdit = $user->authorise('core.edit', $this->extension . '.stage.' . $item->id);
|
||||
$canCheckin = $user->authorise('core.admin', 'com_workflow') || $item->checked_out == $userId || is_null($item->checked_out);
|
||||
$canChange = $user->authorise('core.edit.state', $this->extension . '.stage.' . $item->id) && $canCheckin;
|
||||
|
||||
?>
|
||||
<tr class="row<?php echo $i % 2; ?>">
|
||||
<td class="text-center d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('grid.id', $i, $item->id, false, 'cid', 'cb', Text::_($item->title)); ?>
|
||||
</td>
|
||||
<td class="text-center d-none d-md-table-cell">
|
||||
<?php
|
||||
$iconClass = '';
|
||||
if (!$canChange) {
|
||||
$iconClass = ' inactive';
|
||||
} elseif (!$saveOrder) {
|
||||
$iconClass = ' inactive" title="' . Text::_('JORDERINGDISABLED');
|
||||
}
|
||||
?>
|
||||
<span class="sortable-handler<?php echo $iconClass ?>">
|
||||
<span class="icon-ellipsis-v" aria-hidden="true"></span>
|
||||
</span>
|
||||
<?php if ($canChange && $saveOrder) : ?>
|
||||
<input type="text" name="order[]" size="5" value="<?php echo $item->ordering; ?>" class="width-20 text-area-order hidden">
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<?php echo HTMLHelper::_('jgrid.published', $item->published, $i, 'stages.', $canChange); ?>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<?php echo HTMLHelper::_('jgrid.isdefault', $item->default, $i, 'stages.', $canChange); ?>
|
||||
</td>
|
||||
<th scope="row">
|
||||
<?php if ($item->checked_out) : ?>
|
||||
<?php echo HTMLHelper::_('jgrid.checkedout', $i, $item->editor, $item->checked_out_time, 'stages.', $canCheckin); ?>
|
||||
<?php endif; ?>
|
||||
<?php if ($canEdit) : ?>
|
||||
<a href="<?php echo $edit; ?>" title="<?php echo Text::_('JACTION_EDIT'); ?> <?php echo $this->escape(Text::_($item->title)); ?>">
|
||||
<?php echo $this->escape(Text::_($item->title)); ?>
|
||||
</a>
|
||||
<div class="small"><?php echo $this->escape(Text::_($item->description)); ?></div>
|
||||
<?php else : ?>
|
||||
<?php echo $this->escape(Text::_($item->title)); ?>
|
||||
<div class="small"><?php echo $this->escape(Text::_($item->description)); ?></div>
|
||||
<?php endif; ?>
|
||||
</th>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<?php echo (int) $item->id; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php // load the pagination. ?>
|
||||
<?php echo $this->pagination->getListFooter(); ?>
|
||||
|
||||
<?php endif; ?>
|
||||
<input type="hidden" name="task" value="">
|
||||
<input type="hidden" name="boxchecked" value="0">
|
||||
<input type="hidden" name="workflow_id" value="<?php echo (int) $this->workflowID ?>">
|
||||
<input type="hidden" name="extension" value="<?php echo $this->extension ?>">
|
||||
<?php echo HTMLHelper::_('form.token'); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_workflow
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Layout\LayoutHelper;
|
||||
use Joomla\CMS\Router\Route;
|
||||
|
||||
/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
|
||||
$wa = $this->document->getWebAssetManager();
|
||||
$wa->useScript('keepalive')
|
||||
->useScript('form.validate');
|
||||
|
||||
$app = Factory::getApplication();
|
||||
$user = $app->getIdentity();
|
||||
|
||||
$this->ignore_fieldsets = ['params', 'transition', 'permissions'];
|
||||
$this->useCoreUI = true;
|
||||
|
||||
// In case of modal
|
||||
$isModal = $this->input->get('layout') === 'modal';
|
||||
$layout = $isModal ? 'modal' : 'edit';
|
||||
$tmpl = $isModal || $this->input->get('tmpl', '', 'cmd') === 'component' ? '&tmpl=component' : '';
|
||||
|
||||
?>
|
||||
|
||||
<form action="<?php echo Route::_('index.php?option=com_workflow&view=transition&workflow_id=' . $this->workflowID . '&extension=' . $this->input->getCmd('extension') . '&layout=' . $layout . $tmpl . '&id=' . (int) $this->item->id); ?>" method="post" name="adminForm" id="workflow-form" aria-label="<?php echo Text::_('COM_WORKFLOW_TRANSITION_FORM_' . ((int) $this->item->id === 0 ? 'NEW' : 'EDIT'), true); ?>" class="form-validate">
|
||||
<?php echo LayoutHelper::render('joomla.edit.title_alias', $this); ?>
|
||||
<div class="main-card">
|
||||
<?php echo HTMLHelper::_('uitab.startTabSet', 'myTab', ['active' => 'details', 'recall' => true, 'breakpoint' => 768]); ?>
|
||||
|
||||
<?php echo HTMLHelper::_('uitab.addTab', 'myTab', 'details', Text::_('COM_WORKFLOW_TRANSITION')); ?>
|
||||
<div class="row">
|
||||
<div class="col-lg-9">
|
||||
<?php echo $this->form->renderField('from_stage_id'); ?>
|
||||
<?php echo $this->form->renderField('to_stage_id'); ?>
|
||||
<?php echo $this->form->renderField('description'); ?>
|
||||
</div>
|
||||
<div class="col-lg-3">
|
||||
<?php echo LayoutHelper::render('joomla.edit.global', $this); ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php echo HTMLHelper::_('uitab.endTab'); ?>
|
||||
|
||||
<?php echo LayoutHelper::render('joomla.edit.params', $this); ?>
|
||||
|
||||
<?php if ($user->authorise('core.admin', $this->extension)) : ?>
|
||||
<?php echo HTMLHelper::_('uitab.addTab', 'myTab', 'permissions', Text::_('COM_WORKFLOW_RULES_TAB')); ?>
|
||||
<fieldset id="fieldset-rules" class="options-form">
|
||||
<legend><?php echo Text::_('COM_WORKFLOW_RULES_TAB'); ?></legend>
|
||||
<?php echo $this->form->getInput('rules'); ?>
|
||||
</fieldset>
|
||||
<?php echo HTMLHelper::_('uitab.endTab'); ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php echo HTMLHelper::_('uitab.endTabSet'); ?>
|
||||
</div>
|
||||
<?php echo $this->form->getInput('workflow_id'); ?>
|
||||
<input type="hidden" name="task" value="transition.edit" />
|
||||
<?php echo HTMLHelper::_('form.token'); ?>
|
||||
</form>
|
||||
@ -0,0 +1,165 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_workflow
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
* @since 4.0.0
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Layout\LayoutHelper;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\Session\Session;
|
||||
|
||||
/** @var \Joomla\CMS\WebAsset\WebAssetManager $wa */
|
||||
$wa = $this->document->getWebAssetManager();
|
||||
$wa->useScript('table.columns')
|
||||
->useScript('multiselect');
|
||||
|
||||
$user = $this->getCurrentUser();
|
||||
|
||||
$listOrder = $this->escape($this->state->get('list.ordering'));
|
||||
$listDirn = $this->escape($this->state->get('list.direction'));
|
||||
$saveOrderingUrl = '';
|
||||
|
||||
$saveOrder = ($listOrder == 't.ordering');
|
||||
|
||||
if ($saveOrder) {
|
||||
$saveOrderingUrl = 'index.php?option=com_workflow&task=transitions.saveOrderAjax&workflow_id=' . (int) $this->workflowID . '&extension=' . $this->escape($this->workflow->extension) . '&' . Session::getFormToken() . '=1';
|
||||
HTMLHelper::_('draggablelist.draggable');
|
||||
}
|
||||
?>
|
||||
<form action="<?php echo Route::_('index.php?option=com_workflow&view=transitions&workflow_id=' . (int) $this->workflowID . '&extension=' . $this->escape($this->workflow->extension)); ?>" method="post" name="adminForm" id="adminForm">
|
||||
<div class="row">
|
||||
<?php if (!empty($this->sidebar)) : ?>
|
||||
<div id="j-sidebar-container" class="col-md-2">
|
||||
<?php echo $this->sidebar; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="<?php if (!empty($this->sidebar)) {
|
||||
echo 'col-md-10';
|
||||
} else {
|
||||
echo 'col-md-12';
|
||||
} ?>">
|
||||
<div id="j-main-container" class="j-main-container">
|
||||
<?php
|
||||
// Search tools bar
|
||||
echo LayoutHelper::render('joomla.searchtools.default', ['view' => $this]);
|
||||
?>
|
||||
<?php if (empty($this->transitions)) : ?>
|
||||
<div class="alert alert-info">
|
||||
<span class="icon-info-circle" aria-hidden="true"></span><span class="visually-hidden"><?php echo Text::_('INFO'); ?></span>
|
||||
<?php echo Text::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<table class="table">
|
||||
<caption class="visually-hidden">
|
||||
<?php echo Text::_('COM_WORKFLOW_TRANSITIONS_TABLE_CAPTION'); ?>,
|
||||
<span id="orderedBy"><?php echo Text::_('JGLOBAL_SORTED_BY'); ?> </span>,
|
||||
<span id="filteredBy"><?php echo Text::_('JGLOBAL_FILTERED_BY'); ?></span>
|
||||
</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="w-1 text-center d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('grid.checkall'); ?>
|
||||
</td>
|
||||
<th scope="col" class="w-1 text-center d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', '', 't.ordering', $listDirn, $listOrder, null, 'asc', 'JGRID_HEADING_ORDERING', 'icon-menu-2'); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-1 text-center">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'JSTATUS', 't.published', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-20">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_WORKFLOW_NAME', 't.title', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-20">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_WORKFLOW_FROM_STAGE', 'from_stage', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-20">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_WORKFLOW_TO_STAGE', 'to_stage', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-3 d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_WORKFLOW_ID', 't.id', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="js-draggable" data-url="<?php echo $saveOrderingUrl; ?>" data-direction="<?php echo strtolower($listDirn); ?>">
|
||||
<?php foreach ($this->transitions as $i => $item) :
|
||||
$edit = Route::_('index.php?option=com_workflow&task=transition.edit&id=' . $item->id . '&workflow_id=' . (int) $this->workflowID . '&extension=' . $this->escape($this->workflow->extension));
|
||||
|
||||
$canEdit = $user->authorise('core.edit', $this->extension . '.transition.' . $item->id);
|
||||
$canCheckin = $user->authorise('core.admin', 'com_workflow') || $item->checked_out == $user->id || is_null($item->checked_out);
|
||||
$canChange = $user->authorise('core.edit.state', $this->extension . '.transition.' . $item->id) && $canCheckin;
|
||||
?>
|
||||
<tr class="row<?php echo $i % 2; ?>">
|
||||
<td class="text-center d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('grid.id', $i, $item->id, false, 'cid', 'cb', Text::_($item->title)); ?>
|
||||
</td>
|
||||
<td class="text-center d-none d-md-table-cell">
|
||||
<?php
|
||||
$iconClass = '';
|
||||
if (!$canChange) {
|
||||
$iconClass = ' inactive';
|
||||
} elseif (!$saveOrder) {
|
||||
$iconClass = ' inactive" title="' . Text::_('JORDERINGDISABLED');
|
||||
}
|
||||
?>
|
||||
<span class="sortable-handler<?php echo $iconClass ?>">
|
||||
<span class="icon-ellipsis-v" aria-hidden="true"></span>
|
||||
</span>
|
||||
<?php if ($canChange && $saveOrder) : ?>
|
||||
<input type="text" name="order[]" size="5" value="<?php echo $item->ordering; ?>" class="width-20 text-area-order hidden">
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<?php echo HTMLHelper::_('jgrid.published', $item->published, $i, 'transitions.', $canChange); ?>
|
||||
</td>
|
||||
<th scope="row">
|
||||
<?php if ($item->checked_out) : ?>
|
||||
<?php echo HTMLHelper::_('jgrid.checkedout', $i, $item->editor, $item->checked_out_time, 'transitions.', $canCheckin); ?>
|
||||
<?php endif; ?>
|
||||
<?php if ($canEdit) : ?>
|
||||
<a href="<?php echo $edit; ?>" title="<?php echo Text::_('JACTION_EDIT'); ?> <?php echo $this->escape(Text::_($item->title)); ?>">
|
||||
<?php echo $this->escape(Text::_($item->title)); ?>
|
||||
</a>
|
||||
<div class="small"><?php echo $this->escape(Text::_($item->description)); ?></div>
|
||||
<?php else : ?>
|
||||
<?php echo $this->escape(Text::_($item->title)); ?>
|
||||
<div class="small"><?php echo $this->escape(Text::_($item->description)); ?></div>
|
||||
<?php endif; ?>
|
||||
</th>
|
||||
<td class="nowrap">
|
||||
<?php if ($item->from_stage_id < 0) : ?>
|
||||
<?php echo Text::_('JALL'); ?>
|
||||
<?php else : ?>
|
||||
<?php echo ' ' . $this->escape(Text::_($item->from_stage)); ?>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td class="nowrap">
|
||||
<?php echo ' ' . $this->escape(Text::_($item->to_stage)); ?>
|
||||
</td>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<?php echo (int) $item->id; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php // load the pagination. ?>
|
||||
<?php echo $this->pagination->getListFooter(); ?>
|
||||
<?php endif; ?>
|
||||
<input type="hidden" name="task" value="">
|
||||
<input type="hidden" name="boxchecked" value="0">
|
||||
<input type="hidden" name="workflow_id" value="<?php echo (int) $this->workflowID ?>">
|
||||
<input type="hidden" name="extension" value="<?php echo $this->escape($this->workflow->extension); ?>">
|
||||
<?php echo HTMLHelper::_('form.token'); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
90
administrator/components/com_workflow/tmpl/workflow/edit.php
Normal file
90
administrator/components/com_workflow/tmpl/workflow/edit.php
Normal file
@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_workflow
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Layout\LayoutHelper;
|
||||
use Joomla\CMS\Router\Route;
|
||||
|
||||
/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
|
||||
$wa = $this->document->getWebAssetManager();
|
||||
$wa->useScript('keepalive')
|
||||
->useScript('form.validate');
|
||||
|
||||
$app = Factory::getApplication();
|
||||
$user = $app->getIdentity();
|
||||
$input = $app->getInput();
|
||||
|
||||
// In case of modal
|
||||
$isModal = $input->get('layout') === 'modal';
|
||||
$layout = $isModal ? 'modal' : 'edit';
|
||||
$tmpl = $isModal || $input->get('tmpl', '', 'cmd') === 'component' ? '&tmpl=component' : '';
|
||||
$clientId = $this->state->get('item.client_id', 0);
|
||||
$lang = $this->getLanguage()->getTag();
|
||||
?>
|
||||
|
||||
<form action="<?php echo Route::_('index.php?option=com_workflow&view=workflow&extension=' . $input->getCmd('extension') . '&layout=' . $layout . $tmpl . '&id=' . (int) $this->item->id); ?>" method="post" name="adminForm" id="workflow-form" aria-label="<?php echo Text::_('COM_WORKFLOW_FORM_' . ((int) $this->item->id === 0 ? 'NEW' : 'EDIT'), true); ?>" class="form-validate">
|
||||
|
||||
<?php echo LayoutHelper::render('joomla.edit.title_alias', $this); ?>
|
||||
|
||||
<?php // Add the translation of the workflow item title when client is administrator ?>
|
||||
<?php if ($clientId === 0 && $this->item->id != 0) : ?>
|
||||
<div class="row title-alias form-vertical mb-3">
|
||||
<div class="col-md-6">
|
||||
<div class="control-group">
|
||||
<div class="control-label">
|
||||
<label for="workflow_title_translation"><?php echo Text::sprintf('COM_WORKFLOW_TITLE_TRANSLATION', $lang); ?></label>
|
||||
</div>
|
||||
<div class="controls">
|
||||
<input id="workflow_title_translation" class="form-control" value="<?php echo Text::_($this->item->title); ?>" readonly="readonly" type="text">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="main-card">
|
||||
<?php echo HTMLHelper::_('uitab.startTabSet', 'myTab', ['active' => 'general', 'recall' => true, 'breakpoint' => 768]); ?>
|
||||
|
||||
<?php echo HTMLHelper::_('uitab.addTab', 'myTab', 'description', Text::_('COM_WORKFLOW_DESCRIPTION'));?>
|
||||
<div class="row">
|
||||
<div class="col-lg-9">
|
||||
<div class="form-vertical">
|
||||
<?php echo $this->form->renderField('description'); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3">
|
||||
<fieldset class="form-vertical">
|
||||
<?php echo $this->form->renderField('published'); ?>
|
||||
<?php echo $this->form->renderField('default'); ?>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
<?php echo HTMLHelper::_('uitab.endTab'); ?>
|
||||
|
||||
<?php if ($user->authorise('core.admin', $this->extension)) : ?>
|
||||
<?php echo HTMLHelper::_('uitab.addTab', 'myTab', 'permissions', Text::_('COM_WORKFLOW_RULES_TAB')); ?>
|
||||
<fieldset id="fieldset-rules" class="options-form">
|
||||
<legend><?php echo Text::_('COM_WORKFLOW_RULES_TAB'); ?></legend>
|
||||
<?php echo $this->form->getInput('rules'); ?>
|
||||
</fieldset>
|
||||
<?php echo HTMLHelper::_('uitab.endTab'); ?>
|
||||
|
||||
<?php endif; ?>
|
||||
|
||||
<?php echo HTMLHelper::_('uitab.endTabSet'); ?>
|
||||
</div>
|
||||
<?php echo $this->form->getInput('extension'); ?>
|
||||
<input type="hidden" name="task" value="workflow.edit" />
|
||||
<?php echo HTMLHelper::_('form.token'); ?>
|
||||
</form>
|
||||
191
administrator/components/com_workflow/tmpl/workflows/default.php
Normal file
191
administrator/components/com_workflow/tmpl/workflows/default.php
Normal file
@ -0,0 +1,191 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_workflow
|
||||
*
|
||||
* @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
* @since 4.0.0
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Layout\LayoutHelper;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\Session\Session;
|
||||
|
||||
/** @var \Joomla\CMS\WebAsset\WebAssetManager $wa */
|
||||
$wa = $this->document->getWebAssetManager();
|
||||
$wa->useScript('table.columns')
|
||||
->useScript('multiselect');
|
||||
|
||||
$listOrder = $this->escape($this->state->get('list.ordering'));
|
||||
$listDirn = $this->escape($this->state->get('list.direction'));
|
||||
|
||||
$saveOrder = $listOrder == 'w.ordering';
|
||||
|
||||
$orderingColumn = 'created';
|
||||
$saveOrderingUrl = '';
|
||||
|
||||
if (strpos($listOrder, 'modified') !== false) {
|
||||
$orderingColumn = 'modified';
|
||||
}
|
||||
|
||||
if ($saveOrder) {
|
||||
$saveOrderingUrl = 'index.php?option=com_workflow&task=workflows.saveOrderAjax&tmpl=component&extension=' . $this->escape($this->extension) . '&' . Session::getFormToken() . '=1';
|
||||
HTMLHelper::_('draggablelist.draggable');
|
||||
}
|
||||
|
||||
$extension = $this->escape($this->state->get('filter.extension'));
|
||||
|
||||
$user = $this->getCurrentUser();
|
||||
$userId = $user->id;
|
||||
?>
|
||||
<form action="<?php echo Route::_('index.php?option=com_workflow&view=workflows&extension=' . $extension); ?>" method="post" name="adminForm" id="adminForm">
|
||||
<div class="row">
|
||||
<?php if (!empty($this->sidebar)) : ?>
|
||||
<div id="j-sidebar-container" class="col-md-2">
|
||||
<?php echo $this->sidebar; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="<?php if (!empty($this->sidebar)) {
|
||||
echo 'col-md-10';
|
||||
} else {
|
||||
echo 'col-md-12';
|
||||
} ?>">
|
||||
<div id="j-main-container" class="j-main-container">
|
||||
<?php
|
||||
// Search tools bar
|
||||
echo LayoutHelper::render('joomla.searchtools.default', ['view' => $this, 'options' => ['selectorFieldName' => 'extension']]);
|
||||
?>
|
||||
<?php if (empty($this->workflows)) : ?>
|
||||
<div class="alert alert-info">
|
||||
<span class="icon-info-circle" aria-hidden="true"></span><span class="visually-hidden"><?php echo Text::_('INFO'); ?></span>
|
||||
<?php echo Text::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<table class="table">
|
||||
<caption class="visually-hidden">
|
||||
<?php echo Text::_('COM_WORKFLOW_WORKFLOWS_TABLE_CAPTION'); ?>,
|
||||
<span id="orderedBy"><?php echo Text::_('JGLOBAL_SORTED_BY'); ?> </span>,
|
||||
<span id="filteredBy"><?php echo Text::_('JGLOBAL_FILTERED_BY'); ?></span>
|
||||
</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="w-1 text-center d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('grid.checkall'); ?>
|
||||
</td>
|
||||
<th scope="col" class="w-1 text-center d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', '', 'w.ordering', $listDirn, $listOrder, null, 'asc', 'JGRID_HEADING_ORDERING', 'icon-sort'); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-1 text-center">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'JSTATUS', 'w.published', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_WORKFLOW_NAME', 'w.title', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-10 text-center d-none d-md-table-cell">
|
||||
<?php echo Text::_('COM_WORKFLOW_DEFAULT'); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-10 text-center d-none d-md-table-cell">
|
||||
<?php echo Text::_('COM_WORKFLOW_COUNT_STAGES'); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-10 text-center d-none d-md-table-cell">
|
||||
<?php echo Text::_('COM_WORKFLOW_COUNT_TRANSITIONS'); ?>
|
||||
</th>
|
||||
<th scope="col" class="w-10 d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('searchtools.sort', 'COM_WORKFLOW_ID', 'w.id', $listDirn, $listOrder); ?>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody <?php if ($saveOrder) :
|
||||
?> class="js-draggable" data-url="<?php echo $saveOrderingUrl; ?>" data-direction="<?php echo strtolower($listDirn); ?>" data-nested="false"<?php
|
||||
endif; ?>>
|
||||
<?php foreach ($this->workflows as $i => $item) :
|
||||
$states = Route::_('index.php?option=com_workflow&view=stages&workflow_id=' . $item->id . '&extension=' . $extension);
|
||||
$transitions = Route::_('index.php?option=com_workflow&view=transitions&workflow_id=' . $item->id . '&extension=' . $extension);
|
||||
$edit = Route::_('index.php?option=com_workflow&task=workflow.edit&id=' . $item->id . '&extension=' . $extension);
|
||||
|
||||
$canEdit = $user->authorise('core.edit', $extension . '.workflow.' . $item->id);
|
||||
$canCheckin = $user->authorise('core.admin', 'com_workflow') || $item->checked_out == $userId || is_null($item->checked_out);
|
||||
$canEditOwn = $user->authorise('core.edit.own', $extension . '.workflow.' . $item->id) && $item->created_by == $userId;
|
||||
$canChange = $user->authorise('core.edit.state', $extension . '.workflow.' . $item->id) && $canCheckin;
|
||||
?>
|
||||
<tr class="row<?php echo $i % 2; ?>" data-draggable-group="0">
|
||||
<td class="text-center d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('grid.id', $i, $item->id, false, 'cid', 'cb', Text::_($item->title)); ?>
|
||||
</td>
|
||||
<td class="text-center d-none d-md-table-cell">
|
||||
<?php
|
||||
$iconClass = '';
|
||||
if (!$canChange) {
|
||||
$iconClass = ' inactive';
|
||||
} elseif (!$saveOrder) {
|
||||
$iconClass = ' inactive" title="' . Text::_('JORDERINGDISABLED');
|
||||
}
|
||||
?>
|
||||
<span class="sortable-handler<?php echo $iconClass ?>">
|
||||
<span class="icon-ellipsis-v" aria-hidden="true"></span>
|
||||
</span>
|
||||
<?php if ($canChange && $saveOrder) : ?>
|
||||
<input type="text" name="order[]" size="5" value="<?php echo $item->ordering; ?>" class="width-20 text-area-order hidden">
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<?php echo HTMLHelper::_('jgrid.published', $item->published, $i, 'workflows.', $canChange); ?>
|
||||
</td>
|
||||
<th scope="row">
|
||||
<?php if ($item->checked_out) : ?>
|
||||
<?php echo HTMLHelper::_('jgrid.checkedout', $i, $item->editor, $item->checked_out_time, 'workflows.', $canCheckin); ?>
|
||||
<?php endif; ?>
|
||||
<?php if ($canEdit || $canEditOwn) : ?>
|
||||
<a href="<?php echo $edit; ?>" title="<?php echo Text::_('JACTION_EDIT', true); ?> <?php echo Text::_($item->title, true); ?>">
|
||||
<?php echo $this->escape(Text::_($item->title)); ?>
|
||||
</a>
|
||||
<div class="small"><?php echo $item->description; ?></div>
|
||||
<?php else : ?>
|
||||
<?php echo $this->escape(Text::_($item->title)); ?>
|
||||
<div class="small"><?php echo $item->description; ?></div>
|
||||
<?php endif; ?>
|
||||
</th>
|
||||
<td class="text-center d-none d-md-table-cell">
|
||||
<?php echo HTMLHelper::_('jgrid.isdefault', $item->default, $i, 'workflows.', $canChange); ?>
|
||||
</td>
|
||||
<td class="text-center btns d-none d-md-table-cell itemnumber">
|
||||
<a class="btn <?php echo ($item->count_states > 0) ? 'btn-warning' : 'btn-secondary'; ?>"
|
||||
href="<?php echo Route::_('index.php?option=com_workflow&view=stages&workflow_id=' . (int) $item->id . '&extension=' . $extension); ?>" aria-describedby="tip-stages<?php echo $i; ?>">
|
||||
<?php echo $item->count_states; ?>
|
||||
</a>
|
||||
<div role="tooltip" id="tip-stages<?php echo $i; ?>">
|
||||
<?php echo Text::_('COM_WORKFLOW_COUNT_STAGES'); ?>
|
||||
</div>
|
||||
</td>
|
||||
<td class="text-center btns d-none d-md-table-cell itemnumber">
|
||||
<a class="btn <?php echo ($item->count_transitions > 0) ? 'btn-info' : 'btn-secondary'; ?>"
|
||||
href="<?php echo Route::_('index.php?option=com_workflow&view=transitions&workflow_id=' . (int) $item->id . '&extension=' . $extension); ?>" aria-describedby="tip-transitions<?php echo $i; ?>">
|
||||
<?php echo $item->count_transitions; ?>
|
||||
</a>
|
||||
<div role="tooltip" id="tip-transitions<?php echo $i; ?>">
|
||||
<?php echo Text::_('COM_WORKFLOW_COUNT_TRANSITIONS'); ?>
|
||||
</div>
|
||||
</td>
|
||||
<td class="d-none d-md-table-cell">
|
||||
<?php echo $item->id; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach ?>
|
||||
</table>
|
||||
<?php // load the pagination. ?>
|
||||
<?php echo $this->pagination->getListFooter(); ?>
|
||||
|
||||
<?php endif; ?>
|
||||
<input type="hidden" name="task" value="">
|
||||
<input type="hidden" name="boxchecked" value="0">
|
||||
<?php echo HTMLHelper::_('form.token'); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<metadata>
|
||||
<layout title="COM_WORKFLOW_WORKFLOWS_VIEW_DEFAULT_TITLE">
|
||||
<message>
|
||||
<![CDATA[COM_WORKFLOW_WORKFLOWS_VIEW_DEFAULT_DESC]]>
|
||||
</message>
|
||||
</layout>
|
||||
<fieldset name="request">
|
||||
<fields name="request">
|
||||
<field
|
||||
name="extension"
|
||||
type="ComponentsWorkflow"
|
||||
label="COM_WORKFLOW_CHOOSE_CONTEXT_LABEL"
|
||||
required="true"
|
||||
addfieldprefix="Joomla\Component\Workflow\Administrator\Field"
|
||||
>
|
||||
<option value="">COM_MENUS_OPTION_SELECT_CONTEXT</option>
|
||||
</field>
|
||||
</fields>
|
||||
</fieldset>
|
||||
</metadata>
|
||||
28
administrator/components/com_workflow/workflow.xml
Normal file
28
administrator/components/com_workflow/workflow.xml
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<extension type="component" method="upgrade">
|
||||
<name>com_workflow</name>
|
||||
<author>Joomla! Project</author>
|
||||
<creationDate>2017-06</creationDate>
|
||||
<copyright>(C) 2018 Open Source Matters, Inc.</copyright>
|
||||
<license>GNU General Public License version 2 or later; see LICENSE.txt</license>
|
||||
<authorEmail>admin@joomla.org</authorEmail>
|
||||
<authorUrl>www.joomla.org</authorUrl>
|
||||
<version>4.0.0</version>
|
||||
<description>COM_WORKFLOW_XML_DESCRIPTION</description>
|
||||
<namespace path="src">Joomla\Component\Workflow</namespace>
|
||||
<administration>
|
||||
<menu>COM_WORKFLOW</menu>
|
||||
<files folder="admin">
|
||||
<filename>access.xml</filename>
|
||||
<filename>workflow.xml</filename>
|
||||
<folder>forms</folder>
|
||||
<folder>services</folder>
|
||||
<folder>src</folder>
|
||||
<folder>tmpl</folder>
|
||||
</files>
|
||||
<languages folder="admin">
|
||||
<language tag="en-GB">language/en-GB/com_workflow.ini</language>
|
||||
<language tag="en-GB">language/en-GB/com_workflow.sys.ini</language>
|
||||
</languages>
|
||||
</administration>
|
||||
</extension>
|
||||
Reference in New Issue
Block a user