first commit
This commit is contained in:
@@ -0,0 +1,344 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file controllers/grid/settings/category/CategoryCategoryGridHandler.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2003-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class CategoryCategoryGridHandler
|
||||
*
|
||||
* @ingroup controllers_grid_settings_category
|
||||
*
|
||||
* @brief Handle operations for category management operations.
|
||||
*/
|
||||
|
||||
namespace PKP\controllers\grid\settings\category;
|
||||
|
||||
use APP\core\Request;
|
||||
use APP\facades\Repo;
|
||||
use PKP\controllers\grid\CategoryGridHandler;
|
||||
use PKP\controllers\grid\DataObjectGridCellProvider;
|
||||
use PKP\controllers\grid\feature\OrderCategoryGridItemsFeature;
|
||||
use PKP\controllers\grid\GridColumn;
|
||||
use PKP\controllers\grid\settings\category\form\CategoryForm;
|
||||
use PKP\core\JSONMessage;
|
||||
use PKP\core\PKPRequest;
|
||||
use PKP\facades\Locale;
|
||||
use PKP\file\TemporaryFileManager;
|
||||
use PKP\linkAction\LinkAction;
|
||||
use PKP\linkAction\request\AjaxModal;
|
||||
use PKP\security\authorization\ContextAccessPolicy;
|
||||
use PKP\security\Role;
|
||||
|
||||
class CategoryCategoryGridHandler extends CategoryGridHandler
|
||||
{
|
||||
public $_contextId;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->addRoleAssignment(
|
||||
[Role::ROLE_ID_MANAGER, Role::ROLE_ID_SITE_ADMIN],
|
||||
[
|
||||
'fetchGrid',
|
||||
'fetchCategory',
|
||||
'fetchRow',
|
||||
'addCategory',
|
||||
'editCategory',
|
||||
'updateCategory',
|
||||
'deleteCategory',
|
||||
'uploadImage',
|
||||
'saveSequence',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// Overridden methods from PKPHandler.
|
||||
//
|
||||
/**
|
||||
* @copydoc PKPHandler::authorize()
|
||||
*/
|
||||
public function authorize($request, &$args, $roleAssignments)
|
||||
{
|
||||
$this->addPolicy(new ContextAccessPolicy($request, $roleAssignments));
|
||||
return parent::authorize($request, $args, $roleAssignments);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @copydoc CategoryGridHandler::initialize()
|
||||
*
|
||||
* @param null|mixed $args
|
||||
*/
|
||||
public function initialize($request, $args = null)
|
||||
{
|
||||
parent::initialize($request, $args);
|
||||
|
||||
$context = $request->getContext();
|
||||
$this->_contextId = $context->getId();
|
||||
|
||||
// Set the grid title.
|
||||
$this->setTitle('grid.category.categories');
|
||||
|
||||
// Add grid-level actions.
|
||||
$router = $request->getRouter();
|
||||
$this->addAction(
|
||||
new LinkAction(
|
||||
'addCategory',
|
||||
new AjaxModal(
|
||||
$router->url($request, null, null, 'addCategory'),
|
||||
__('grid.category.add'),
|
||||
'modal_manage'
|
||||
),
|
||||
__('grid.category.add'),
|
||||
'add_category'
|
||||
)
|
||||
);
|
||||
|
||||
// Add grid columns.
|
||||
$cellProvider = new DataObjectGridCellProvider();
|
||||
$cellProvider->setLocale(Locale::getLocale());
|
||||
|
||||
$this->addColumn(
|
||||
new GridColumn(
|
||||
'title',
|
||||
'grid.category.name',
|
||||
null,
|
||||
null,
|
||||
$cellProvider
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc GridHandler::loadData
|
||||
*/
|
||||
public function loadData($request, $filter)
|
||||
{
|
||||
// For top-level rows, only list categories without parents.
|
||||
return Repo::category()->getCollector()
|
||||
->filterByContextIds([$this->_getContextId()])
|
||||
->filterByParentIds([null])
|
||||
->getMany()
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc GridHandler::initFeatures()
|
||||
*/
|
||||
public function initFeatures($request, $args)
|
||||
{
|
||||
return array_merge(
|
||||
parent::initFeatures($request, $args),
|
||||
[new OrderCategoryGridItemsFeature(OrderCategoryGridItemsFeature::ORDER_CATEGORY_GRID_CATEGORIES_AND_ROWS, true, $this)]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc CategoryGridHandler::getDataElementInCategorySequence()
|
||||
*/
|
||||
public function getDataElementInCategorySequence($categoryId, &$category)
|
||||
{
|
||||
return $category->getSequence();
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc CategoryGridHandler::setDataElementInCategorySequence()
|
||||
*/
|
||||
public function setDataElementInCategorySequence($parentCategoryId, &$category, $newSequence)
|
||||
{
|
||||
$category->setSequence($newSequence);
|
||||
Repo::category()->edit($category, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc GridHandler::getDataElementSequence()
|
||||
*/
|
||||
public function getDataElementSequence($gridDataElement)
|
||||
{
|
||||
return $gridDataElement->getSequence();
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc GridHandler::setDataElementSequence()
|
||||
*/
|
||||
public function setDataElementSequence($request, $categoryId, $category, $newSequence)
|
||||
{
|
||||
$category->setSequence($newSequence);
|
||||
Repo::category()->edit($category, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc CategoryGridHandler::getCategoryRowIdParameterName()
|
||||
*/
|
||||
public function getCategoryRowIdParameterName()
|
||||
{
|
||||
return 'parentCategoryId';
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc GridHandler::getRowInstance()
|
||||
*/
|
||||
public function getRowInstance()
|
||||
{
|
||||
return new \PKP\controllers\grid\settings\category\CategoryGridRow();
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc CategoryGridHandler::getCategoryRowInstance()
|
||||
*/
|
||||
public function getCategoryRowInstance()
|
||||
{
|
||||
return new \PKP\controllers\grid\settings\category\CategoryGridCategoryRow();
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc CategoryGridHandler::loadCategoryData()
|
||||
*
|
||||
* @param null|mixed $filter
|
||||
*/
|
||||
public function loadCategoryData($request, &$category, $filter = null)
|
||||
{
|
||||
$categoryId = $category->getId();
|
||||
return Repo::category()->getCollector()
|
||||
->filterByContextIds([$this->_getContextId()])
|
||||
->filterByParentIds([$categoryId])
|
||||
->getMany()
|
||||
->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the add category operation.
|
||||
*
|
||||
* @param array $args
|
||||
* @param PKPRequest $request
|
||||
*/
|
||||
public function addCategory($args, $request)
|
||||
{
|
||||
return $this->editCategory($args, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the edit category operation.
|
||||
*
|
||||
* @param array $args
|
||||
* @param PKPRequest $request
|
||||
*
|
||||
* @return JSONMessage JSON object
|
||||
*/
|
||||
public function editCategory($args, $request)
|
||||
{
|
||||
$categoryForm = $this->_getCategoryForm($request);
|
||||
|
||||
$categoryForm->initData();
|
||||
|
||||
return new JSONMessage(true, $categoryForm->fetch($request));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update category data in database and grid.
|
||||
*
|
||||
* @param array $args
|
||||
* @param PKPRequest $request
|
||||
*
|
||||
* @return JSONMessage JSON object
|
||||
*/
|
||||
public function updateCategory($args, $request)
|
||||
{
|
||||
$categoryForm = $this->_getCategoryForm($request);
|
||||
|
||||
$categoryForm->readInputData();
|
||||
if ($categoryForm->validate()) {
|
||||
$categoryForm->execute();
|
||||
return \PKP\db\DAO::getDataChangedEvent();
|
||||
} else {
|
||||
return new JSONMessage(true, $categoryForm->fetch($request));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a category
|
||||
*
|
||||
* @param array $args
|
||||
* @param PKPRequest $request
|
||||
*
|
||||
* @return JSONMessage JSON object
|
||||
*/
|
||||
public function deleteCategory($args, $request)
|
||||
{
|
||||
if (!$request->checkCSRF()) {
|
||||
return new JSONMessage(false);
|
||||
}
|
||||
|
||||
$context = $request->getContext();
|
||||
$category = Repo::category()->get((int) $request->getUserVar('categoryId'));
|
||||
if ($category && $category->getContextId() == $context->getId()) {
|
||||
Repo::category()->delete($category);
|
||||
}
|
||||
|
||||
// FIXME delete dependent objects?
|
||||
|
||||
return \PKP\db\DAO::getDataChangedEvent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle file uploads for cover/image art for things like Series and Categories.
|
||||
*
|
||||
* @param PKPRequest $request
|
||||
* @param array $args
|
||||
*
|
||||
* @return JSONMessage JSON object
|
||||
*/
|
||||
public function uploadImage($args, $request)
|
||||
{
|
||||
$user = $request->getUser();
|
||||
|
||||
$temporaryFileManager = new TemporaryFileManager();
|
||||
$temporaryFile = $temporaryFileManager->handleUpload('uploadedFile', $user->getId());
|
||||
if ($temporaryFile) {
|
||||
$json = new JSONMessage(true);
|
||||
$json->setAdditionalAttributes([
|
||||
'temporaryFileId' => $temporaryFile->getId()
|
||||
]);
|
||||
return $json;
|
||||
} else {
|
||||
return new JSONMessage(false, __('common.uploadFailed'));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Private helper methods.
|
||||
//
|
||||
/**
|
||||
* Get a CategoryForm instance.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return CategoryForm
|
||||
*/
|
||||
public function _getCategoryForm($request)
|
||||
{
|
||||
// Get the category ID.
|
||||
$categoryId = (int) $request->getUserVar('categoryId');
|
||||
|
||||
// Instantiate the files form.
|
||||
$contextId = $this->_getContextId();
|
||||
return new CategoryForm($contextId, $categoryId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get context id.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function _getContextId()
|
||||
{
|
||||
return $this->_contextId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file controllers/grid/settings/category/CategoryGridCategoryRow.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class CategoryGridCategoryRow
|
||||
*
|
||||
* @ingroup controllers_grid_settings_category
|
||||
*
|
||||
* @brief Category grid category row definition
|
||||
*/
|
||||
|
||||
namespace PKP\controllers\grid\settings\category;
|
||||
|
||||
use APP\facades\Repo;
|
||||
use PKP\controllers\grid\GridCategoryRow;
|
||||
use PKP\controllers\grid\GridRow;
|
||||
use PKP\linkAction\LinkAction;
|
||||
use PKP\linkAction\request\AjaxModal;
|
||||
use PKP\linkAction\request\RemoteActionConfirmationModal;
|
||||
|
||||
class CategoryGridCategoryRow extends GridCategoryRow
|
||||
{
|
||||
//
|
||||
// Overridden methods from GridCategoryRow
|
||||
//
|
||||
/**
|
||||
* @copydoc GridCategoryRow::initialize()
|
||||
*
|
||||
* @param null|mixed $template
|
||||
*/
|
||||
public function initialize($request, $template = null)
|
||||
{
|
||||
// Do the default initialization
|
||||
parent::initialize($request, $template);
|
||||
|
||||
// Is this a new row or an existing row?
|
||||
$categoryId = $this->getId();
|
||||
if (!empty($categoryId) && is_numeric($categoryId)) {
|
||||
// Only add row actions if this is an existing row
|
||||
$category = $this->getData();
|
||||
$router = $request->getRouter();
|
||||
|
||||
$childCategoryCount = Repo::category()->getCollector()
|
||||
->filterByParentIds([$categoryId])
|
||||
->getCount();
|
||||
|
||||
if ($childCategoryCount == 0) {
|
||||
$this->addAction(
|
||||
new LinkAction(
|
||||
'deleteCategory',
|
||||
new RemoteActionConfirmationModal(
|
||||
$request->getSession(),
|
||||
__('common.confirmDelete'),
|
||||
__('common.delete'),
|
||||
$router->url($request, null, null, 'deleteCategory', null, ['categoryId' => $categoryId]),
|
||||
'modal_delete'
|
||||
),
|
||||
__('grid.action.remove'),
|
||||
'delete'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$this->addAction(new LinkAction(
|
||||
'editCategory',
|
||||
new AjaxModal(
|
||||
$router->url($request, null, null, 'editCategory', null, ['categoryId' => $categoryId]),
|
||||
__('grid.category.edit'),
|
||||
'modal_edit'
|
||||
),
|
||||
$category->getLocalizedTitle()
|
||||
), GridRow::GRID_ACTION_POSITION_ROW_CLICK);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Category rows only have one cell and one label. This is it.
|
||||
* return string
|
||||
*/
|
||||
public function getCategoryLabel()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file controllers/grid/settings/category/CategoryGridRow.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class CategoryGridRow
|
||||
*
|
||||
* @ingroup controllers_grid_settings_category
|
||||
*
|
||||
* @brief Category grid row definition
|
||||
*/
|
||||
|
||||
namespace PKP\controllers\grid\settings\category;
|
||||
|
||||
use PKP\controllers\grid\GridRow;
|
||||
use PKP\linkAction\LinkAction;
|
||||
use PKP\linkAction\request\AjaxModal;
|
||||
use PKP\linkAction\request\RemoteActionConfirmationModal;
|
||||
|
||||
class CategoryGridRow extends GridRow
|
||||
{
|
||||
//
|
||||
// Overridden methods from GridRow
|
||||
//
|
||||
/**
|
||||
* @copydoc GridRow::initialize()
|
||||
*
|
||||
* @param null|mixed $template
|
||||
*/
|
||||
public function initialize($request, $template = null)
|
||||
{
|
||||
parent::initialize($request, $template);
|
||||
|
||||
$rowData = $this->getData(); // a Category object
|
||||
assert($rowData != null);
|
||||
|
||||
$rowId = $this->getId();
|
||||
|
||||
// Only add row actions if this is an existing row.
|
||||
if (!empty($rowId) && is_numeric($rowId)) {
|
||||
$actionArgs = array_merge(
|
||||
$this->getRequestArgs(),
|
||||
['categoryId' => $rowData->getId()]
|
||||
);
|
||||
$router = $request->getRouter();
|
||||
|
||||
$this->addAction(new LinkAction(
|
||||
'editCategory',
|
||||
new AjaxModal(
|
||||
$router->url($request, null, null, 'editCategory', null, $actionArgs),
|
||||
__('grid.category.edit')
|
||||
),
|
||||
__('grid.action.edit'),
|
||||
'edit'
|
||||
));
|
||||
|
||||
$this->addAction(new LinkAction(
|
||||
'removeCategory',
|
||||
new RemoteActionConfirmationModal(
|
||||
$request->getSession(),
|
||||
__('grid.category.removeText'),
|
||||
null,
|
||||
$router->url($request, null, null, 'deleteCategory', null, $actionArgs)
|
||||
),
|
||||
__('grid.action.remove'),
|
||||
'delete'
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,427 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file lib/pkp/controllers/grid/settings/category/form/CategoryForm.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2003-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class CategoryForm
|
||||
*
|
||||
* @ingroup controllers_grid_settings_category_form
|
||||
*
|
||||
* @brief Form to add/edit category.
|
||||
*/
|
||||
|
||||
namespace PKP\controllers\grid\settings\category\form;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\facades\Repo;
|
||||
use APP\template\TemplateManager;
|
||||
use PKP\context\SubEditorsDAO;
|
||||
use PKP\core\Core;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\file\ContextFileManager;
|
||||
use PKP\file\TemporaryFileDAO;
|
||||
use PKP\file\TemporaryFileManager;
|
||||
use PKP\form\Form;
|
||||
use PKP\security\Role;
|
||||
use PKP\userGroup\UserGroup;
|
||||
|
||||
class CategoryForm extends Form
|
||||
{
|
||||
/** @var int Id of the category being edited */
|
||||
public $_categoryId;
|
||||
|
||||
/** @var int The context ID of the category being edited */
|
||||
public $_contextId;
|
||||
|
||||
/** @var int $_userId The current user ID */
|
||||
public $_userId;
|
||||
|
||||
/** @var string $_imageExtension Cover image extension */
|
||||
public $_imageExtension;
|
||||
|
||||
/** @var array $_sizeArray Cover image information from getimagesize */
|
||||
public $_sizeArray;
|
||||
|
||||
/** @var array Roles that can be assigned to this category */
|
||||
public $assignableRoles = [Role::ROLE_ID_MANAGER, Role::ROLE_ID_SUB_EDITOR, Role::ROLE_ID_ASSISTANT];
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param int $contextId Context id.
|
||||
* @param int $categoryId Category id.
|
||||
*/
|
||||
public function __construct($contextId, $categoryId = null)
|
||||
{
|
||||
parent::__construct('controllers/grid/settings/category/form/categoryForm.tpl');
|
||||
$this->_contextId = $contextId;
|
||||
$this->_categoryId = $categoryId;
|
||||
|
||||
$request = Application::get()->getRequest();
|
||||
$user = $request->getUser();
|
||||
$this->_userId = $user->getId();
|
||||
|
||||
// Validation checks for this form
|
||||
$form = $this;
|
||||
$this->addCheck(new \PKP\form\validation\FormValidatorLocale($this, 'name', 'required', 'grid.category.nameRequired'));
|
||||
$this->addCheck(new \PKP\form\validation\FormValidatorRegExp($this, 'path', 'required', 'grid.category.pathAlphaNumeric', '/^[a-zA-Z0-9\/._-]+$/'));
|
||||
$this->addCheck(new \PKP\form\validation\FormValidatorCustom(
|
||||
$this,
|
||||
'path',
|
||||
'required',
|
||||
'grid.category.pathExists',
|
||||
function ($path) use ($form, $contextId) {
|
||||
$category = Repo::category()->getCollector()
|
||||
->filterByContextIds([$contextId])
|
||||
->filterByPaths([$path])
|
||||
->getMany()
|
||||
->first();
|
||||
|
||||
return !$category || $category->getPath() == $form->getData('oldPath');
|
||||
}
|
||||
));
|
||||
$this->addCheck(new \PKP\form\validation\FormValidatorPost($this));
|
||||
$this->addCheck(new \PKP\form\validation\FormValidatorCSRF($this));
|
||||
}
|
||||
|
||||
//
|
||||
// Getters and Setters
|
||||
//
|
||||
/**
|
||||
* Get the category id.
|
||||
*
|
||||
* @return int categoryId
|
||||
*/
|
||||
public function getCategoryId()
|
||||
{
|
||||
return $this->_categoryId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the category ID for this section.
|
||||
*
|
||||
* @param int $categoryId
|
||||
*/
|
||||
public function setCategoryId($categoryId)
|
||||
{
|
||||
$this->_categoryId = $categoryId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the context id.
|
||||
*
|
||||
* @return int contextId
|
||||
*/
|
||||
public function getContextId()
|
||||
{
|
||||
return $this->_contextId;
|
||||
}
|
||||
|
||||
//
|
||||
// Implement template methods from Form.
|
||||
//
|
||||
/**
|
||||
* Get all locale field names
|
||||
*/
|
||||
public function getLocaleFieldNames()
|
||||
{
|
||||
return ['name', 'description'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Form::initData()
|
||||
*/
|
||||
public function initData()
|
||||
{
|
||||
$category = Repo::category()->get($this->getCategoryId());
|
||||
|
||||
$this->setData('assignedSubeditors', []);
|
||||
|
||||
if ($category) {
|
||||
if ($category->getContextId() != $this->getContextId()) {
|
||||
throw new \Exception('Wrong context ID for category!');
|
||||
}
|
||||
|
||||
$this->setData('name', $category->getTitle(null)); // Localized
|
||||
$this->setData('description', $category->getDescription(null)); // Localized
|
||||
$this->setData('parentId', $category->getParentId());
|
||||
$this->setData('path', $category->getPath());
|
||||
$this->setData('image', $category->getImage());
|
||||
|
||||
$sortOption = $category->getSortOption() ? $category->getSortOption() : Repo::submission()->getDefaultSortOption();
|
||||
$this->setData('sortOption', $sortOption);
|
||||
|
||||
$subeditorUserGroups = [];
|
||||
$assignedSubeditors = Repo::user()
|
||||
->getCollector()
|
||||
->filterByContextIds([Application::get()->getRequest()->getContext()->getId()])
|
||||
->filterByRoleIds($this->assignableRoles)
|
||||
->assignedToCategoryIds([$this->getCategoryId()])
|
||||
->getIds()
|
||||
->toArray();
|
||||
|
||||
if (!empty($assignedSubeditors)) {
|
||||
$subEditorsDao = DAORegistry::getDAO('SubEditorsDAO'); /** @var SubEditorsDAO $subEditorsDao */
|
||||
$subeditorUserGroups = $subEditorsDao->getAssignedUserGroupIds(
|
||||
Application::get()->getRequest()->getContext()->getId(),
|
||||
Application::ASSOC_TYPE_CATEGORY,
|
||||
$this->getCategoryId(),
|
||||
$assignedSubeditors
|
||||
)->toArray();
|
||||
}
|
||||
|
||||
$this->setData('subeditorUserGroups', $subeditorUserGroups);
|
||||
}
|
||||
|
||||
return parent::initData();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Form::validate()
|
||||
*/
|
||||
public function validate($callHooks = true)
|
||||
{
|
||||
if ($temporaryFileId = $this->getData('temporaryFileId')) {
|
||||
$temporaryFileManager = new TemporaryFileManager();
|
||||
$temporaryFileDao = DAORegistry::getDAO('TemporaryFileDAO'); /** @var TemporaryFileDAO $temporaryFileDao */
|
||||
$temporaryFile = $temporaryFileDao->getTemporaryFile($temporaryFileId, $this->_userId);
|
||||
if (!$temporaryFile ||
|
||||
!($this->_imageExtension = $temporaryFileManager->getImageExtension($temporaryFile->getFileType())) ||
|
||||
!($this->_sizeArray = getimagesize($temporaryFile->getFilePath())) ||
|
||||
$this->_sizeArray[0] <= 0 || $this->_sizeArray[1] <= 0
|
||||
) {
|
||||
$this->addError('temporaryFileId', __('form.invalidImage'));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return parent::validate($callHooks);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Form::readInputData()
|
||||
*/
|
||||
public function readInputData()
|
||||
{
|
||||
$this->readUserVars(['name', 'parentId', 'path', 'description', 'temporaryFileId', 'sortOption', 'subEditors']);
|
||||
|
||||
// For path duplicate checking; excuse the current path.
|
||||
if ($categoryId = $this->getCategoryId()) {
|
||||
$category = Repo::category()->get($categoryId);
|
||||
if ($category->getContextId() != $this->getContextId()) {
|
||||
throw new \Exception('Wrong context ID for category!');
|
||||
}
|
||||
$this->setData('oldPath', $category->getPath());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc Form::fetch()
|
||||
*
|
||||
* @param null|mixed $template
|
||||
*/
|
||||
public function fetch($request, $template = null, $display = false)
|
||||
{
|
||||
$context = $request->getContext();
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
$templateMgr->assign('categoryId', $this->getCategoryId());
|
||||
|
||||
// Provide a list of root categories to the template
|
||||
$rootCategoriesCollection = Repo::category()->getCollector()
|
||||
->filterByParentIds([null])
|
||||
->filterByContextIds([$context->getId()])
|
||||
->getMany();
|
||||
|
||||
$rootCategories = [null => __('common.none')];
|
||||
foreach ($rootCategoriesCollection as $category) {
|
||||
$categoryId = $category->getId();
|
||||
if ($categoryId != $this->getCategoryId()) {
|
||||
// Don't permit time travel paradox
|
||||
$rootCategories[$categoryId] = $category->getLocalizedTitle();
|
||||
}
|
||||
}
|
||||
$templateMgr->assign('rootCategories', $rootCategories);
|
||||
|
||||
// Determine if this category has children of its own;
|
||||
// if so, prevent the user from giving it a parent.
|
||||
// (Forced two-level maximum tree depth.)
|
||||
if ($this->getCategoryId()) {
|
||||
$childCount = Repo::category()->getCollector()
|
||||
->filterByParentIds([$this->getCategoryId()])
|
||||
->filterByContextIds([$context->getId()])
|
||||
->getCount();
|
||||
|
||||
$templateMgr->assign('cannotSelectChild', $childCount > 0);
|
||||
}
|
||||
// Sort options.
|
||||
$templateMgr->assign('sortOptions', Repo::submission()->getSortSelectOptions());
|
||||
|
||||
$assignableUserGroups = Repo::userGroup()
|
||||
->getCollector()
|
||||
->filterByContextIds([$request->getContext()->getId()])
|
||||
->filterByRoleIds($this->assignableRoles)
|
||||
->filterByStageIds([WORKFLOW_STAGE_ID_SUBMISSION])
|
||||
->getMany()
|
||||
->map(function (UserGroup $userGroup) use ($request) {
|
||||
return [
|
||||
'userGroup' => $userGroup,
|
||||
'users' => Repo::user()
|
||||
->getCollector()
|
||||
->filterByUserGroupIds([$userGroup->getId()])
|
||||
->filterByContextIds([$request->getContext()->getId()])
|
||||
->getMany()
|
||||
->mapWithKeys(fn ($user, $key) => [$user->getId() => $user->getFullName()])
|
||||
->toArray()
|
||||
];
|
||||
});
|
||||
|
||||
$templateMgr = TemplateManager::getManager($request);
|
||||
$templateMgr->assign([
|
||||
'assignableUserGroups' => $assignableUserGroups->toArray(),
|
||||
]);
|
||||
|
||||
return parent::fetch($request, $template, $display);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc Form::execute()
|
||||
*/
|
||||
public function execute(...$functionArgs)
|
||||
{
|
||||
$categoryId = $this->getCategoryId();
|
||||
$context = Application::get()->getRequest()->getContext();
|
||||
|
||||
// Get a category object to edit or create
|
||||
if ($categoryId == null) {
|
||||
$category = Repo::category()->dao->newDataObject();
|
||||
$category->setContextId($this->getContextId());
|
||||
} else {
|
||||
$category = Repo::category()->get($categoryId);
|
||||
if ($category->getContextId() != $this->getContextId()) {
|
||||
throw new \Exception('Wrong context ID for category!');
|
||||
}
|
||||
}
|
||||
|
||||
// Set the editable properties of the category object
|
||||
$category->setTitle($this->getData('name'), null); // Localized
|
||||
$category->setDescription($this->getData('description'), null); // Localized
|
||||
$category->setParentId(((int) $this->getData('parentId')) ?: null);
|
||||
$category->setPath($this->getData('path'));
|
||||
$category->setSortOption($this->getData('sortOption'));
|
||||
|
||||
// Update or insert the category object
|
||||
if ($categoryId == null) {
|
||||
$this->setCategoryId(Repo::category()->add($category));
|
||||
$category->setSequence(REALLY_BIG_NUMBER);
|
||||
Repo::category()->dao->resequenceCategories($this->getContextId());
|
||||
} else {
|
||||
Repo::category()->edit($category, []);
|
||||
}
|
||||
|
||||
// Update category editors
|
||||
$subEditorsDao = DAORegistry::getDAO('SubEditorsDAO'); /** @var SubEditorsDAO $subEditorsDao */
|
||||
$subEditorsDao->deleteBySubmissionGroupId($category->getId(), Application::ASSOC_TYPE_CATEGORY, $category->getContextId());
|
||||
$subEditors = $this->getData('subEditors');
|
||||
if (!empty($subEditors)) {
|
||||
$allowedEditors = Repo::user()
|
||||
->getCollector()
|
||||
->filterByRoleIds($this->assignableRoles)
|
||||
->filterByContextIds([$context->getId()])
|
||||
->getIds();
|
||||
foreach ($subEditors as $userGroupId => $userIds) {
|
||||
foreach ($userIds as $userId) {
|
||||
if (!$allowedEditors->contains($userId)) {
|
||||
continue;
|
||||
}
|
||||
$subEditorsDao->insertEditor($context->getId(), $this->getCategoryId(), $userId, Application::ASSOC_TYPE_CATEGORY, (int) $userGroupId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle the image upload if there was one.
|
||||
if ($temporaryFileId = $this->getData('temporaryFileId')) {
|
||||
// Fetch the temporary file storing the uploaded library file
|
||||
$temporaryFileDao = DAORegistry::getDAO('TemporaryFileDAO'); /** @var TemporaryFileDAO $temporaryFileDao */
|
||||
|
||||
$temporaryFile = $temporaryFileDao->getTemporaryFile($temporaryFileId, $this->_userId);
|
||||
$temporaryFilePath = $temporaryFile->getFilePath();
|
||||
$contextFileManager = new ContextFileManager($this->getContextId());
|
||||
$basePath = $contextFileManager->getBasePath() . '/categories/';
|
||||
|
||||
// Delete the old file if it exists
|
||||
$oldSetting = $category->getImage();
|
||||
if ($oldSetting) {
|
||||
$contextFileManager->deleteByPath($basePath . $oldSetting['thumbnailName']);
|
||||
$contextFileManager->deleteByPath($basePath . $oldSetting['name']);
|
||||
}
|
||||
|
||||
// The following variables were fetched in validation
|
||||
assert($this->_sizeArray && $this->_imageExtension);
|
||||
|
||||
// Generate the surrogate images.
|
||||
switch ($this->_imageExtension) {
|
||||
case '.jpg': $image = imagecreatefromjpeg($temporaryFilePath);
|
||||
break;
|
||||
case '.png': $image = imagecreatefrompng($temporaryFilePath);
|
||||
break;
|
||||
case '.gif': $image = imagecreatefromgif($temporaryFilePath);
|
||||
break;
|
||||
default: $image = null; // Suppress warning
|
||||
}
|
||||
assert($image);
|
||||
|
||||
$context = Application::get()->getRequest()->getContext();
|
||||
$coverThumbnailsMaxWidth = $context->getSetting('coverThumbnailsMaxWidth');
|
||||
$coverThumbnailsMaxHeight = $context->getSetting('coverThumbnailsMaxHeight');
|
||||
$thumbnailFilename = $category->getId() . '-category-thumbnail' . $this->_imageExtension;
|
||||
$xRatio = min(1, ($coverThumbnailsMaxWidth ? $coverThumbnailsMaxWidth : 100) / $this->_sizeArray[0]);
|
||||
$yRatio = min(1, ($coverThumbnailsMaxHeight ? $coverThumbnailsMaxHeight : 100) / $this->_sizeArray[1]);
|
||||
|
||||
$ratio = min($xRatio, $yRatio);
|
||||
|
||||
$thumbnailWidth = round($ratio * $this->_sizeArray[0]);
|
||||
$thumbnailHeight = round($ratio * $this->_sizeArray[1]);
|
||||
$thumbnail = imagecreatetruecolor($thumbnailWidth, $thumbnailHeight);
|
||||
imagecopyresampled($thumbnail, $image, 0, 0, 0, 0, $thumbnailWidth, $thumbnailHeight, $this->_sizeArray[0], $this->_sizeArray[1]);
|
||||
|
||||
// Copy the new file over
|
||||
$filename = $category->getId() . '-category' . $this->_imageExtension;
|
||||
$contextFileManager->copyFile($temporaryFile->getFilePath(), $basePath . $filename);
|
||||
|
||||
switch ($this->_imageExtension) {
|
||||
case '.jpg': imagejpeg($thumbnail, $basePath . $thumbnailFilename);
|
||||
break;
|
||||
case '.png': imagepng($thumbnail, $basePath . $thumbnailFilename);
|
||||
break;
|
||||
case '.gif': imagegif($thumbnail, $basePath . $thumbnailFilename);
|
||||
break;
|
||||
}
|
||||
imagedestroy($thumbnail);
|
||||
imagedestroy($image);
|
||||
|
||||
$category->setImage([
|
||||
'name' => $filename,
|
||||
'width' => $this->_sizeArray[0],
|
||||
'height' => $this->_sizeArray[1],
|
||||
'thumbnailName' => $thumbnailFilename,
|
||||
'thumbnailWidth' => $thumbnailWidth,
|
||||
'thumbnailHeight' => $thumbnailHeight,
|
||||
'uploadName' => $temporaryFile->getOriginalFileName(),
|
||||
'dateUploaded' => Core::getCurrentDate(),
|
||||
]);
|
||||
|
||||
// Clean up the temporary file
|
||||
$temporaryFileManager = new TemporaryFileManager();
|
||||
$temporaryFileManager->deleteById($temporaryFileId, $this->_userId);
|
||||
}
|
||||
|
||||
// Update category object to store image information.
|
||||
Repo::category()->edit($category, []);
|
||||
parent::execute(...$functionArgs);
|
||||
return $category;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user