477 lines
15 KiB
PHP
477 lines
15 KiB
PHP
<?php
|
|
|
|
/**
|
|
* @file controllers/grid/plugins/PluginGridHandler.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 PluginGridHandler
|
|
*
|
|
* @ingroup controllers_grid_plugins
|
|
*
|
|
* @brief Handle plugins grid requests.
|
|
*/
|
|
|
|
namespace PKP\controllers\grid\plugins;
|
|
|
|
use APP\notification\NotificationManager;
|
|
use Exception;
|
|
use PKP\controllers\grid\CategoryGridHandler;
|
|
use PKP\controllers\grid\GridColumn;
|
|
use PKP\controllers\grid\GridHandler;
|
|
use PKP\controllers\grid\plugins\form\UploadPluginForm;
|
|
use PKP\core\Core;
|
|
use PKP\core\JSONMessage;
|
|
use PKP\core\PKPApplication;
|
|
use PKP\core\PKPRequest;
|
|
use PKP\db\DAORegistry;
|
|
use PKP\file\FileManager;
|
|
use PKP\file\TemporaryFileManager;
|
|
use PKP\linkAction\LinkAction;
|
|
use PKP\linkAction\request\AjaxModal;
|
|
use PKP\notification\PKPNotification;
|
|
use PKP\plugins\Plugin;
|
|
use PKP\plugins\PluginHelper;
|
|
use PKP\plugins\PluginRegistry;
|
|
use PKP\security\Role;
|
|
use PKP\site\Version;
|
|
use PKP\site\VersionCheck;
|
|
use PKP\site\VersionDAO;
|
|
|
|
abstract class PluginGridHandler extends CategoryGridHandler
|
|
{
|
|
/**
|
|
* Constructor
|
|
*
|
|
* @param array $roles
|
|
*/
|
|
public function __construct($roles)
|
|
{
|
|
$this->addRoleAssignment(
|
|
$roles,
|
|
['enable', 'disable', 'manage', 'fetchGrid', 'fetchCategory', 'fetchRow']
|
|
);
|
|
|
|
$this->addRoleAssignment(
|
|
Role::ROLE_ID_SITE_ADMIN,
|
|
['uploadPlugin', 'upgradePlugin', 'deletePlugin', 'saveUploadPlugin', 'uploadPluginFile']
|
|
);
|
|
|
|
parent::__construct();
|
|
}
|
|
|
|
|
|
//
|
|
// Overridden template methods
|
|
//
|
|
/**
|
|
* @copydoc GridHandler::initialize()
|
|
*
|
|
* @param null|mixed $args
|
|
*/
|
|
public function initialize($request, $args = null)
|
|
{
|
|
parent::initialize($request, $args);
|
|
|
|
// Basic grid configuration
|
|
$this->setTitle('common.plugins');
|
|
|
|
// Set the no items row text
|
|
$this->setEmptyRowText('grid.noItems');
|
|
|
|
// Columns
|
|
$pluginCellProvider = new PluginGridCellProvider();
|
|
$this->addColumn(
|
|
new GridColumn(
|
|
'name',
|
|
'common.name',
|
|
null,
|
|
null,
|
|
$pluginCellProvider,
|
|
[
|
|
'showTotalItemsNumber' => true,
|
|
'collapseAllColumnsInCategories' => true
|
|
]
|
|
)
|
|
);
|
|
|
|
$descriptionColumn = new GridColumn(
|
|
'description',
|
|
'common.description',
|
|
null,
|
|
null,
|
|
$pluginCellProvider
|
|
);
|
|
$descriptionColumn->addFlag('html', true);
|
|
$this->addColumn($descriptionColumn);
|
|
|
|
$this->addColumn(
|
|
new GridColumn(
|
|
'enabled',
|
|
'common.enabled',
|
|
null,
|
|
'controllers/grid/common/cell/selectStatusCell.tpl',
|
|
$pluginCellProvider
|
|
)
|
|
);
|
|
|
|
$router = $request->getRouter();
|
|
|
|
// Grid level actions.
|
|
$userRoles = $this->getAuthorizedContextObject(PKPApplication::ASSOC_TYPE_USER_ROLES);
|
|
if (in_array(Role::ROLE_ID_SITE_ADMIN, $userRoles)) {
|
|
// Install plugin.
|
|
$this->addAction(
|
|
new LinkAction(
|
|
'upload',
|
|
new AjaxModal(
|
|
$router->url($request, null, null, 'uploadPlugin'),
|
|
__('manager.plugins.upload'),
|
|
'modal_add_file'
|
|
),
|
|
__('manager.plugins.upload'),
|
|
'add'
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @copydoc GridHandler::getFilterForm()
|
|
*/
|
|
protected function getFilterForm()
|
|
{
|
|
return 'controllers/grid/plugins/pluginGridFilter.tpl';
|
|
}
|
|
|
|
/**
|
|
* @copydoc GridHandler::getFilterSelectionData()
|
|
*/
|
|
public function getFilterSelectionData($request)
|
|
{
|
|
$category = $request->getUserVar('category');
|
|
$pluginName = $request->getUserVar('pluginName');
|
|
|
|
if (is_null($category)) {
|
|
$category = PluginGalleryGridHandler::PLUGIN_GALLERY_ALL_CATEGORY_SEARCH_VALUE;
|
|
}
|
|
|
|
return ['category' => $category, 'pluginName' => $pluginName];
|
|
}
|
|
|
|
/**
|
|
* @copydoc GridHandler::renderFilter()
|
|
*/
|
|
public function renderFilter($request, $filterData = [])
|
|
{
|
|
$categoriesSymbolic = $this->loadData($request, null);
|
|
$categories = [PluginGalleryGridHandler::PLUGIN_GALLERY_ALL_CATEGORY_SEARCH_VALUE => __('grid.plugin.allCategories')];
|
|
foreach ($categoriesSymbolic as $category) {
|
|
$categories[$category] = __("plugins.categories.{$category}");
|
|
}
|
|
$filterData['categories'] = $categories;
|
|
|
|
return parent::renderFilter($request, $filterData);
|
|
}
|
|
|
|
/**
|
|
* @copydoc CategoryGridHandler::getCategoryRowInstance()
|
|
*/
|
|
protected function getCategoryRowInstance()
|
|
{
|
|
return new PluginCategoryGridRow();
|
|
}
|
|
|
|
/**
|
|
* @copydoc CategoryGridHandler::loadCategoryData()
|
|
*
|
|
* @param null|mixed $filter
|
|
*/
|
|
public function loadCategoryData($request, &$categoryDataElement, $filter = null)
|
|
{
|
|
$plugins = PluginRegistry::loadCategory($categoryDataElement);
|
|
|
|
$versionDao = DAORegistry::getDAO('VersionDAO'); /** @var VersionDAO $versionDao */
|
|
$fileManager = new FileManager();
|
|
|
|
$notHiddenPlugins = [];
|
|
foreach ((array) $plugins as $plugin) {
|
|
if (!$plugin->getHideManagement()) {
|
|
$notHiddenPlugins[$plugin->getName()] = $plugin;
|
|
}
|
|
$version = $plugin->getCurrentVersion();
|
|
if ($version == null) { // this plugin is on the file system, but not installed.
|
|
$versionFile = $plugin->getPluginPath() . '/version.xml';
|
|
if ($fileManager->fileExists($versionFile)) {
|
|
$versionInfo = VersionCheck::parseVersionXML($versionFile);
|
|
$pluginVersion = $versionInfo['version'];
|
|
} else {
|
|
$pluginVersion = new Version(
|
|
1,
|
|
0,
|
|
0,
|
|
0, // Major, minor, revision, build
|
|
Core::getCurrentDate(), // Date installed
|
|
1, // Current
|
|
'plugins.' . $plugin->getCategory(), // Type
|
|
basename($plugin->getPluginPath()), // Product
|
|
'', // Class name
|
|
0, // Lazy load
|
|
$plugin->isSitePlugin() // Site wide
|
|
);
|
|
}
|
|
$versionDao->insertVersion($pluginVersion, true);
|
|
}
|
|
}
|
|
|
|
if (!is_null($filter) && isset($filter['pluginName']) && $filter['pluginName'] != '') {
|
|
// Find all plugins that have the filter name string in their display names.
|
|
$filteredPlugins = [];
|
|
foreach ($notHiddenPlugins as $plugin) { /** @var Plugin $plugin */
|
|
$pluginName = $plugin->getDisplayName();
|
|
if (stristr($pluginName, $filter['pluginName']) !== false) {
|
|
$filteredPlugins[$plugin->getName()] = $plugin;
|
|
}
|
|
}
|
|
ksort($filteredPlugins);
|
|
return $filteredPlugins;
|
|
}
|
|
|
|
ksort($notHiddenPlugins);
|
|
return $notHiddenPlugins;
|
|
}
|
|
|
|
/**
|
|
* @copydoc CategoryGridHandler::getCategoryRowIdParameterName()
|
|
*/
|
|
public function getCategoryRowIdParameterName()
|
|
{
|
|
return 'category';
|
|
}
|
|
|
|
/**
|
|
* @copydoc GridHandler::loadData()
|
|
*/
|
|
protected function loadData($request, $filter)
|
|
{
|
|
$categories = PluginRegistry::getCategories();
|
|
if (is_array($filter) && isset($filter['category']) && in_array($filter['category'], $categories)) {
|
|
return [$filter['category'] => $filter['category']];
|
|
} else {
|
|
return array_combine($categories, $categories);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Public handler methods.
|
|
//
|
|
/**
|
|
* Manage a plugin.
|
|
*
|
|
* @param array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function manage($args, $request)
|
|
{
|
|
$plugin = $this->getAuthorizedContextObject(PKPApplication::ASSOC_TYPE_PLUGIN); /** @var Plugin $plugin */
|
|
return $plugin->manage($args, $request);
|
|
}
|
|
|
|
/**
|
|
* Enable a plugin.
|
|
*
|
|
* @param array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function enable($args, $request)
|
|
{
|
|
$plugin = $this->getAuthorizedContextObject(PKPApplication::ASSOC_TYPE_PLUGIN); /** @var Plugin $plugin */
|
|
if ($request->checkCSRF() && $plugin->getCanEnable()) {
|
|
$plugin->setEnabled(true);
|
|
if (empty($args['disableNotification'])) {
|
|
$user = $request->getUser();
|
|
$notificationManager = new NotificationManager();
|
|
$notificationManager->createTrivialNotification($user->getId(), PKPNotification::NOTIFICATION_TYPE_PLUGIN_ENABLED, ['pluginName' => $plugin->getDisplayName()]);
|
|
}
|
|
return \PKP\db\DAO::getDataChangedEvent($request->getUserVar('plugin'), $request->getUserVar($this->getCategoryRowIdParameterName()));
|
|
}
|
|
return new JSONMessage(false);
|
|
}
|
|
|
|
/**
|
|
* Disable a plugin.
|
|
*
|
|
* @param array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function disable($args, $request)
|
|
{
|
|
$plugin = $this->getAuthorizedContextObject(PKPApplication::ASSOC_TYPE_PLUGIN); /** @var Plugin $plugin */
|
|
if ($request->checkCSRF() && $plugin->getCanDisable()) {
|
|
$plugin->setEnabled(false);
|
|
if (empty($args['disableNotification'])) {
|
|
$user = $request->getUser();
|
|
$notificationManager = new NotificationManager();
|
|
$notificationManager->createTrivialNotification($user->getId(), PKPNotification::NOTIFICATION_TYPE_PLUGIN_DISABLED, ['pluginName' => $plugin->getDisplayName()]);
|
|
}
|
|
return \PKP\db\DAO::getDataChangedEvent($request->getUserVar('plugin'), $request->getUserVar($this->getCategoryRowIdParameterName()));
|
|
}
|
|
return new JSONMessage(false);
|
|
}
|
|
|
|
/**
|
|
* Show upload plugin form to upload a new plugin.
|
|
*
|
|
* @param array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage
|
|
*/
|
|
public function uploadPlugin($args, $request)
|
|
{
|
|
return $this->_showUploadPluginForm(PluginHelper::PLUGIN_ACTION_UPLOAD, $request);
|
|
}
|
|
|
|
/**
|
|
* Show upload plugin form to update an existing plugin.
|
|
*
|
|
* @param array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage
|
|
*/
|
|
public function upgradePlugin($args, $request)
|
|
{
|
|
return $this->_showUploadPluginForm(PluginHelper::PLUGIN_ACTION_UPGRADE, $request);
|
|
}
|
|
|
|
/**
|
|
* Upload a plugin file.
|
|
*
|
|
* @param array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function uploadPluginFile($args, $request)
|
|
{
|
|
$temporaryFileManager = new TemporaryFileManager();
|
|
$user = $request->getUser();
|
|
|
|
// Return the temporary file id.
|
|
if ($temporaryFile = $temporaryFileManager->handleUpload('uploadedFile', $user->getId())) {
|
|
$json = new JSONMessage(true);
|
|
$json->setAdditionalAttributes([
|
|
'temporaryFileId' => $temporaryFile->getId()
|
|
]);
|
|
return $json;
|
|
} else {
|
|
return new JSONMessage(false, __('manager.plugins.uploadError'));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Save upload plugin file form.
|
|
*
|
|
* @param array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function saveUploadPlugin($args, $request)
|
|
{
|
|
if (!$request->checkCSRF()) {
|
|
throw new Exception('CSRF mismatch!');
|
|
}
|
|
$function = $request->getUserVar('function');
|
|
$uploadPluginForm = new UploadPluginForm($function);
|
|
$uploadPluginForm->readInputData();
|
|
|
|
if ($uploadPluginForm->validate()) {
|
|
if ($uploadPluginForm->execute()) {
|
|
return \PKP\db\DAO::getDataChangedEvent();
|
|
}
|
|
}
|
|
|
|
return new JSONMessage(false);
|
|
}
|
|
|
|
/**
|
|
* Delete plugin.
|
|
*
|
|
* @param array $args
|
|
* @param PKPRequest $request
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function deletePlugin($args, $request)
|
|
{
|
|
if (!$request->checkCSRF()) {
|
|
return new JSONMessage(false);
|
|
}
|
|
|
|
$plugin = $this->getAuthorizedContextObject(PKPApplication::ASSOC_TYPE_PLUGIN);
|
|
$category = $plugin->getCategory();
|
|
$productName = basename($plugin->getPluginPath());
|
|
|
|
$versionDao = DAORegistry::getDAO('VersionDAO'); /** @var VersionDAO $versionDao */
|
|
$installedPlugin = $versionDao->getCurrentVersion('plugins.' . $category, $productName);
|
|
|
|
$notificationMgr = new NotificationManager();
|
|
$user = $request->getUser();
|
|
$pluginName = ['pluginName' => $plugin->getDisplayName()];
|
|
if ($installedPlugin) {
|
|
$pluginDest = Core::getBaseDir() . "/plugins/{$category}/{$productName}";
|
|
$pluginLibDest = Core::getBaseDir() . '/' . PKP_LIB_PATH . "/plugins/{$category}/{$productName}";
|
|
|
|
// make sure plugin type is valid and then delete the files
|
|
if (in_array($category, PluginRegistry::getCategories())) {
|
|
// Delete the plugin from the file system.
|
|
$fileManager = new FileManager();
|
|
$fileManager->rmtree($pluginDest);
|
|
$fileManager->rmtree($pluginLibDest);
|
|
}
|
|
|
|
if (is_dir($pluginDest) || is_dir($pluginLibDest)) {
|
|
$notificationMgr->createTrivialNotification($user->getId(), PKPNotification::NOTIFICATION_TYPE_ERROR, ['contents' => __('manager.plugins.deleteError', $pluginName)]);
|
|
} else {
|
|
$versionDao->disableVersion('plugins.' . $category, $productName);
|
|
$notificationMgr->createTrivialNotification($user->getId(), PKPNotification::NOTIFICATION_TYPE_SUCCESS, ['contents' => __('manager.plugins.deleteSuccess', $pluginName)]);
|
|
}
|
|
} else {
|
|
$notificationMgr->createTrivialNotification($user->getId(), PKPNotification::NOTIFICATION_TYPE_ERROR, ['contents' => __('manager.plugins.doesNotExist', $pluginName)]);
|
|
}
|
|
|
|
return \PKP\db\DAO::getDataChangedEvent($plugin->getName());
|
|
}
|
|
|
|
/**
|
|
* Fetch upload plugin form.
|
|
*
|
|
* @param string $function
|
|
* @param PKPRequest $request Request object
|
|
*
|
|
* @return JSONMessage JSON object
|
|
*/
|
|
public function _showUploadPluginForm($function, $request)
|
|
{
|
|
$uploadPluginForm = new UploadPluginForm($function);
|
|
$uploadPluginForm->initData();
|
|
|
|
return new JSONMessage(true, $uploadPluginForm->fetch($request));
|
|
}
|
|
}
|
|
|
|
if (!PKP_STRICT_MODE) {
|
|
class_alias('\PKP\controllers\grid\plugins\PluginGridHandler', '\PluginGridHandler');
|
|
}
|