aboutsummaryrefslogtreecommitdiff
path: root/app/Controllers/extensionController.php
diff options
context:
space:
mode:
authorGravatar Alexandre Alapetite <alexandre@alapetite.fr> 2023-04-04 10:23:26 +0200
committerGravatar GitHub <noreply@github.com> 2023-04-04 10:23:26 +0200
commit36aa0122e15b6c5a4bf923467b63a577cac5a539 (patch)
tree3dc7d2c5143157165f0248fab7470f86f76b0898 /app/Controllers/extensionController.php
parent2340f7a1bac38647f0267c1d7143c0cf04d68fcc (diff)
Fix extensions in actualize_script (#5243)
* Fix extension freshrss_user_maintenance in actualize_script Follow-up of https://github.com/FreshRSS/FreshRSS/pull/3440 The hook was called before registering all the extensions for the current user * PHPStan Level 6 for extensions And remove 5-year old legacy format of enabled extensions < FreshRSS 1.11.1 * Fix multiple bugs in extensions * Minor typing * Don't change signature of methods supposed to be overridden * PHPStan Level 9 and compatibility Intelliphense * Set as final the methods not supposed to be overriden
Diffstat (limited to 'app/Controllers/extensionController.php')
-rw-r--r--app/Controllers/extensionController.php88
1 files changed, 54 insertions, 34 deletions
diff --git a/app/Controllers/extensionController.php b/app/Controllers/extensionController.php
index d1ea889aa..b482b1a35 100644
--- a/app/Controllers/extensionController.php
+++ b/app/Controllers/extensionController.php
@@ -9,7 +9,7 @@ class FreshRSS_extension_Controller extends FreshRSS_ActionController {
* the common boiler plate for every action. It is triggered by the
* underlying framework.
*/
- public function firstAction() {
+ public function firstAction(): void {
if (!FreshRSS_Auth::hasAccess()) {
Minz_Error::error(403);
}
@@ -18,7 +18,7 @@ class FreshRSS_extension_Controller extends FreshRSS_ActionController {
/**
* This action lists all the extensions available to the current user.
*/
- public function indexAction() {
+ public function indexAction(): void {
FreshRSS_View::prependTitle(_t('admin.extensions.title') . ' ยท ');
$this->view->extension_list = array(
'system' => array(),
@@ -33,14 +33,14 @@ class FreshRSS_extension_Controller extends FreshRSS_ActionController {
$this->view->extensions_installed[$ext->getEntrypoint()] = $ext->getVersion();
}
- $availableExtensions = $this->getAvailableExtensionList();
- $this->view->available_extensions = $availableExtensions;
+ $this->view->available_extensions = $this->getAvailableExtensionList();
}
/**
* fetch extension list from GitHub
+ * @return array<string,array{'name':string,'author':string,'description':string,'version':string,'entrypoint':string,'type':'system'|'user','url':string,'method':string,'directory':string}>
*/
- protected function getAvailableExtensionList() {
+ protected function getAvailableExtensionList(): array {
$extensionListUrl = 'https://raw.githubusercontent.com/FreshRSS/Extensions/master/extensions.json';
$json = @file_get_contents($extensionListUrl);
@@ -51,18 +51,17 @@ class FreshRSS_extension_Controller extends FreshRSS_ActionController {
}
// fetch the list as an array
+ /** @var array<string,mixed> */
$list = json_decode($json, true);
if (empty($list)) {
Minz_Log::warning('Failed to convert extension file list');
return array();
}
- // we could use that for comparing and caching later
- $version = $list['version'];
-
// By now, all the needed data is kept in the main extension file.
// In the future we could fetch detail information from the extensions metadata.json, but I tend to stick with
// the current implementation for now, unless it becomes too much effort maintain the extension list manually
+ /** @var array<string,array{'name':string,'author':string,'description':string,'version':string,'entrypoint':string,'type':'system'|'user','url':string,'method':string,'directory':string}> */
$extensions = $list['extensions'];
return $extensions;
@@ -78,22 +77,24 @@ class FreshRSS_extension_Controller extends FreshRSS_ActionController {
* - additional parameters which should be handle by the extension
* handleConfigureAction() method (POST request).
*/
- public function configureAction() {
- if (Minz_Request::param('ajax')) {
+ public function configureAction(): void {
+ if (Minz_Request::paramBoolean('ajax')) {
$this->view->_layout(false);
} else {
$this->indexAction();
$this->view->_path('extension/index.phtml');
}
- $ext_name = urldecode(Minz_Request::param('e'));
+ $ext_name = urldecode(Minz_Request::paramString('e'));
$ext = Minz_ExtensionManager::findExtension($ext_name);
- if (is_null($ext)) {
+ if ($ext === null) {
Minz_Error::error(404);
+ return;
}
if ($ext->getType() === 'system' && !FreshRSS_Auth::hasAccess('admin')) {
Minz_Error::error(403);
+ return;
}
$this->view->extension = $ext;
@@ -109,41 +110,52 @@ class FreshRSS_extension_Controller extends FreshRSS_ActionController {
* Parameter is:
* - e: the extension name (urlencoded).
*/
- public function enableAction() {
+ public function enableAction(): void {
$url_redirect = array('c' => 'extension', 'a' => 'index');
if (Minz_Request::isPost()) {
- $ext_name = urldecode(Minz_Request::param('e'));
+ $ext_name = urldecode(Minz_Request::paramString('e'));
$ext = Minz_ExtensionManager::findExtension($ext_name);
if (is_null($ext)) {
Minz_Request::bad(_t('feedback.extensions.not_found', $ext_name), $url_redirect);
+ return;
}
if ($ext->isEnabled()) {
Minz_Request::bad(_t('feedback.extensions.already_enabled', $ext_name), $url_redirect);
}
+ $type = $ext->getType();
+ if ($type !== 'user' && !FreshRSS_Auth::hasAccess('admin')) {
+ Minz_Request::bad(_t('feedback.extensions.no_access', $ext_name), $url_redirect);
+ return;
+ }
+
$conf = null;
- if ($ext->getType() === 'system' && FreshRSS_Auth::hasAccess('admin')) {
+ if ($type === 'system') {
$conf = FreshRSS_Context::$system_conf;
- } elseif ($ext->getType() === 'user') {
+ } elseif ($type === 'user') {
$conf = FreshRSS_Context::$user_conf;
- } else {
- Minz_Request::bad(_t('feedback.extensions.no_access', $ext_name), $url_redirect);
}
$res = $ext->install();
- if ($res === true) {
+ if ($conf !== null && $res === true) {
$ext_list = $conf->extensions_enabled;
+ $ext_list = array_filter($ext_list, function($key) use($type) {
+ // Remove from list the extensions that have disappeared or changed type
+ $extension = Minz_ExtensionManager::findExtension($key);
+ return $extension !== null && $extension->getType() === $type;
+ }, ARRAY_FILTER_USE_KEY);
+
$ext_list[$ext_name] = true;
$conf->extensions_enabled = $ext_list;
$conf->save();
Minz_Request::good(_t('feedback.extensions.enable.ok', $ext_name), $url_redirect);
} else {
- Minz_Log::warning('Can not enable extension ' . $ext_name . ': ' . $res);
+ Minz_Log::warning('Cannot enable extension ' . $ext_name . ': ' . $res);
Minz_Request::bad(_t('feedback.extensions.enable.ko', $ext_name, _url('index', 'logs')), $url_redirect);
}
}
@@ -160,45 +172,52 @@ class FreshRSS_extension_Controller extends FreshRSS_ActionController {
* Parameter is:
* - e: the extension name (urlencoded).
*/
- public function disableAction() {
+ public function disableAction(): void {
$url_redirect = array('c' => 'extension', 'a' => 'index');
if (Minz_Request::isPost()) {
- $ext_name = urldecode(Minz_Request::param('e'));
+ $ext_name = urldecode(Minz_Request::paramString('e'));
$ext = Minz_ExtensionManager::findExtension($ext_name);
if (is_null($ext)) {
Minz_Request::bad(_t('feedback.extensions.not_found', $ext_name), $url_redirect);
+ return;
}
if (!$ext->isEnabled()) {
Minz_Request::bad(_t('feedback.extensions.not_enabled', $ext_name), $url_redirect);
}
+ $type = $ext->getType();
+ if ($type !== 'user' && !FreshRSS_Auth::hasAccess('admin')) {
+ Minz_Request::bad(_t('feedback.extensions.no_access', $ext_name), $url_redirect);
+ return;
+ }
+
$conf = null;
- if ($ext->getType() === 'system' && FreshRSS_Auth::hasAccess('admin')) {
+ if ($type === 'system') {
$conf = FreshRSS_Context::$system_conf;
- } elseif ($ext->getType() === 'user') {
+ } elseif ($type === 'user') {
$conf = FreshRSS_Context::$user_conf;
- } else {
- Minz_Request::bad(_t('feedback.extensions.no_access', $ext_name), $url_redirect);
}
$res = $ext->uninstall();
- if ($res === true) {
+ if ($conf !== null && $res === true) {
$ext_list = $conf->extensions_enabled;
- $legacyKey = array_search($ext_name, $ext_list, true);
- if ($legacyKey !== false) { //Legacy format FreshRSS < 1.11.1
- unset($ext_list[$legacyKey]);
- }
+ $ext_list = array_filter($ext_list, function($key) use($type) {
+ // Remove from list the extensions that have disappeared or changed type
+ $extension = Minz_ExtensionManager::findExtension($key);
+ return $extension !== null && $extension->getType() === $type;
+ }, ARRAY_FILTER_USE_KEY);
+
$ext_list[$ext_name] = false;
$conf->extensions_enabled = $ext_list;
$conf->save();
Minz_Request::good(_t('feedback.extensions.disable.ok', $ext_name), $url_redirect);
} else {
- Minz_Log::warning('Can not unable extension ' . $ext_name . ': ' . $res);
+ Minz_Log::warning('Cannot disable extension ' . $ext_name . ': ' . $res);
Minz_Request::bad(_t('feedback.extensions.disable.ko', $ext_name, _url('index', 'logs')), $url_redirect);
}
}
@@ -215,7 +234,7 @@ class FreshRSS_extension_Controller extends FreshRSS_ActionController {
* Parameter is:
* -e: extension name (urlencoded)
*/
- public function removeAction() {
+ public function removeAction(): void {
if (!FreshRSS_Auth::hasAccess('admin')) {
Minz_Error::error(403);
}
@@ -223,11 +242,12 @@ class FreshRSS_extension_Controller extends FreshRSS_ActionController {
$url_redirect = array('c' => 'extension', 'a' => 'index');
if (Minz_Request::isPost()) {
- $ext_name = urldecode(Minz_Request::param('e'));
+ $ext_name = urldecode(Minz_Request::paramString('e'));
$ext = Minz_ExtensionManager::findExtension($ext_name);
if (is_null($ext)) {
Minz_Request::bad(_t('feedback.extensions.not_found', $ext_name), $url_redirect);
+ return;
}
$res = recursive_unlink($ext->getPath());