fully psalm lvl2 compliant

This commit is contained in:
Michel Roux 2023-06-17 00:07:40 +02:00
parent 174ffd462e
commit d16b0f2d20
9 changed files with 382 additions and 115 deletions

View File

@ -5,6 +5,7 @@
"type": "project", "type": "project",
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"require-dev": { "require-dev": {
"symfony/event-dispatcher": "^5.4.22",
"nextcloud/ocp": "^27.0.0", "nextcloud/ocp": "^27.0.0",
"psalm/phar": "^5.12.0", "psalm/phar": "^5.12.0",
"nextcloud/coding-standard": "^1.1.1" "nextcloud/coding-standard": "^1.1.1"

316
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "5c7be477b217d6074abc6c2f8d2c2256", "content-hash": "72e9bc76d92d0e26e0b3af7ed7ce6a68",
"packages": [], "packages": [],
"packages-dev": [ "packages-dev": [
{ {
@ -379,6 +379,320 @@
"source": "https://github.com/php-fig/log/tree/1.1.4" "source": "https://github.com/php-fig/log/tree/1.1.4"
}, },
"time": "2021-05-03T11:20:27+00:00" "time": "2021-05-03T11:20:27+00:00"
},
{
"name": "symfony/deprecation-contracts",
"version": "v2.5.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66",
"reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "2.5-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
"files": [
"function.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.2"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-01-02T09:53:40+00:00"
},
{
"name": "symfony/event-dispatcher",
"version": "v5.4.22",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
"reference": "1df20e45d56da29a4b1d8259dd6e950acbf1b13f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/1df20e45d56da29a4b1d8259dd6e950acbf1b13f",
"reference": "1df20e45d56da29a4b1d8259dd6e950acbf1b13f",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"symfony/deprecation-contracts": "^2.1|^3",
"symfony/event-dispatcher-contracts": "^2|^3",
"symfony/polyfill-php80": "^1.16"
},
"conflict": {
"symfony/dependency-injection": "<4.4"
},
"provide": {
"psr/event-dispatcher-implementation": "1.0",
"symfony/event-dispatcher-implementation": "2.0"
},
"require-dev": {
"psr/log": "^1|^2|^3",
"symfony/config": "^4.4|^5.0|^6.0",
"symfony/dependency-injection": "^4.4|^5.0|^6.0",
"symfony/error-handler": "^4.4|^5.0|^6.0",
"symfony/expression-language": "^4.4|^5.0|^6.0",
"symfony/http-foundation": "^4.4|^5.0|^6.0",
"symfony/service-contracts": "^1.1|^2|^3",
"symfony/stopwatch": "^4.4|^5.0|^6.0"
},
"suggest": {
"symfony/dependency-injection": "",
"symfony/http-kernel": ""
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\EventDispatcher\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/event-dispatcher/tree/v5.4.22"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2023-03-17T11:31:58+00:00"
},
{
"name": "symfony/event-dispatcher-contracts",
"version": "v2.5.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher-contracts.git",
"reference": "f98b54df6ad059855739db6fcbc2d36995283fe1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/f98b54df6ad059855739db6fcbc2d36995283fe1",
"reference": "f98b54df6ad059855739db6fcbc2d36995283fe1",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"psr/event-dispatcher": "^1"
},
"suggest": {
"symfony/event-dispatcher-implementation": ""
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "2.5-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
"psr-4": {
"Symfony\\Contracts\\EventDispatcher\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Generic abstractions related to dispatching event",
"homepage": "https://symfony.com",
"keywords": [
"abstractions",
"contracts",
"decoupling",
"interfaces",
"interoperability",
"standards"
],
"support": {
"source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.5.2"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-01-02T09:53:40+00:00"
},
{
"name": "symfony/polyfill-php80",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
"reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Php80\\": ""
},
"classmap": [
"Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ion Bazan",
"email": "ion.bazan@gmail.com"
},
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
} }
], ],
"aliases": [], "aliases": [],

View File

@ -14,17 +14,32 @@ namespace OCA\Epubreader\AppInfo;
use OCA\Epubreader\Hooks; use OCA\Epubreader\Hooks;
use OCP\AppFramework\App; use OCP\AppFramework\App;
use OCP\AppFramework\Bootstrap\IBootContext;
use OCP\AppFramework\Bootstrap\IBootstrap;
use OCP\AppFramework\Bootstrap\IRegistrationContext;
use OCP\Util; use OCP\Util;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
class Application extends App { class Application extends App implements IBootstrap {
public const APP_ID = 'epubreader'; public const APP_ID = 'epubreader';
public function __construct() { public function __construct() {
parent::__construct(self::APP_ID); parent::__construct(self::APP_ID);
$l = \OC::$server->getL10N('epubreader'); Util::addscript(self::APP_ID, 'plugin');
Hooks::register(); }
Util::addscript('epubreader', 'plugin');
public function boot(IBootContext $context): void {
/** @psalm-suppress DeprecatedMethod */
Util::connectHook('\OCP\Config', 'js', 'OCA\Epubreader\Hooks', 'announce_settings');
$context->injectFn(function (EventDispatcherInterface $dispatcher) {
$dispatcher->addListener('OC\Files::preDelete', [Hooks::class, 'deleteFile']);
$dispatcher->addListener('OC\User::preDelete', [Hooks::class, 'deleteUser']);
});
}
public function register(IRegistrationContext $context): void {
} }
} }

View File

@ -12,30 +12,48 @@
namespace OCA\Epubreader\Controller; namespace OCA\Epubreader\Controller;
use OCA\Epubreader\Config; use OCA\Epubreader\AppInfo\Application;
use OCP\AppFramework\Controller; use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\JSONResponse; use OCP\AppFramework\Http\JSONResponse;
use OCP\IConfig;
use OCP\IL10N;
use OCP\IRequest;
class SettingsController extends Controller { class SettingsController extends Controller {
private string $userId;
private IL10N $l10n;
private IConfig $configManager;
public function __construct(
string $appName,
IRequest $request,
string $userId,
IL10N $l10n,
IConfig $configManager
) {
parent::__construct($appName, $request);
$this->userId = $userId;
$this->l10n = $l10n;
$this->configManager = $configManager;
}
/** /**
* @brief set preference for file type association * @brief set preference for file type association
* *
* @NoAdminRequired * @NoAdminRequired
* *
* @param int $EpubEnable * @param string $EpubEnable
* @param int $PdfEnable * @param string $PdfEnable
* @param int $CbxEnable * @param string $CbxEnable
*/ */
public function setPreference(int $EpubEnable, int $PdfEnable, int $CbxEnable): JSONResponse { public function setPreference(string $EpubEnable, string $PdfEnable, string $CbxEnable): JSONResponse {
$l = \OC::$server->getL10N('epubreader'); $this->configManager->setUserValue($this->userId, Application::APP_ID, 'epub_enable', $EpubEnable);
$this->configManager->setUserValue($this->userId, Application::APP_ID, 'pdf_enable', $PdfEnable);
Config::set('epub_enable', $EpubEnable); $this->configManager->setUserValue($this->userId, Application::APP_ID, 'cbx_enable', $CbxEnable);
Config::set('pdf_enable', $PdfEnable);
Config::set('cbx_enable', $CbxEnable);
$response = [ $response = [
'data' => ['message' => $l->t('Settings updated successfully.')], 'data' => ['message' => $this->l10n->t('Settings updated successfully.')],
'status' => 'success' 'status' => 'success'
]; ];

View File

@ -10,32 +10,17 @@
namespace OCA\Epubreader; namespace OCA\Epubreader;
use \OC\User\User as User; use OCA\Epubreader\AppInfo\Application;
use OCP\Files\Node; use OCP\IConfig;
use OCP\IDBConnection; use OCP\IDBConnection;
use OCP\Util; use OCP\IUser;
use OCP\Server;
class Hooks { class Hooks {
public static function register(): void {
/** @psalm-suppress DeprecatedMethod */
Util::connectHook('\OCP\Config', 'js', 'OCA\Epubreader\Hooks', 'announce_settings');
\OC::$server->getRootFolder()->listen('\OC\Files', 'preDelete', function (Node $node) {
$fileId = $node->getId();
$connection = \OC::$server->getDatabaseConnection();
self::deleteFile($connection, $fileId);
});
\OC::$server->getUserManager()->listen('\OC\User', 'preDelete', function (User $user) {
$userId = $user->getUID();
$connection = \OC::$server->getDatabaseConnection();
self::deleteUser($connection, $userId);
});
}
public static function announce_settings(array $settings): void { public static function announce_settings(array $settings): void {
// Nextcloud encodes this as JSON, Owncloud does not (yet) (#75) // Nextcloud encodes this as JSON, Owncloud does not (yet) (#75)
// TODO: rmeove this when Owncloud starts encoding oc_appconfig as JSON just like it already encodes most other properties // TODO: remove this when Owncloud starts encoding oc_appconfig as JSON just like it already encodes most other properties
if (array_key_exists('array', $settings) && if (array_key_exists('array', $settings) &&
is_array($settings['array']) && is_array($settings['array']) &&
array_key_exists('oc_appconfig', $settings['array']) array_key_exists('oc_appconfig', $settings['array'])
@ -44,9 +29,9 @@ class Hooks {
/** @var array $array */ /** @var array $array */
$array = ($isJson) ? json_decode((string) $settings['array']['oc_appconfig'], true) : $settings['array']['oc_appconfig']; $array = ($isJson) ? json_decode((string) $settings['array']['oc_appconfig'], true) : $settings['array']['oc_appconfig'];
$array['filesReader'] = [ $array['filesReader'] = [
'enableEpub' => Config::get('epub_enable', 'true'), 'enableEpub' => Server::get(IConfig::class)->getUserValue(Server::get(IUser::class)->getUID(), Application::APP_ID, 'epub_enable', 'true'),
'enablePdf' => Config::get('pdf_enable', 'true'), 'enablePdf' => Server::get(IConfig::class)->getUserValue(Server::get(IUser::class)->getUID(), Application::APP_ID, 'pdf_enable', 'true'),
'enableCbx' => Config::get('cbx_enable', 'true'), 'enableCbx' => Server::get(IConfig::class)->getUserValue(Server::get(IUser::class)->getUID(), Application::APP_ID, 'cbx_enable', 'true'),
]; ];
$settings['array']['oc_appconfig'] = ($isJson) ? json_encode($array) : $array; $settings['array']['oc_appconfig'] = ($isJson) ? json_encode($array) : $array;
} }

View File

@ -11,6 +11,7 @@
namespace OCA\Epubreader\Settings; namespace OCA\Epubreader\Settings;
use OCA\Epubreader\AppInfo\Application;
use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Http\TemplateResponse;
use OCP\IConfig; use OCP\IConfig;
use OCP\Settings\ISettings; use OCP\Settings\ISettings;
@ -34,12 +35,12 @@ class Personal implements ISettings {
*/ */
public function getForm(): TemplateResponse { public function getForm(): TemplateResponse {
$parameters = [ $parameters = [
'EpubEnable' => $this->configManager->getUserValue($this->userId, 'epubreader', 'epub_enable'), 'EpubEnable' => $this->configManager->getUserValue($this->userId, Application::APP_ID, 'epub_enable'),
'PdfEnable' => $this->configManager->getUserValue($this->userId, 'epubreader', 'pdf_enable'), 'PdfEnable' => $this->configManager->getUserValue($this->userId, Application::APP_ID, 'pdf_enable'),
'CbxEnable' => $this->configManager->getUserValue($this->userId, 'epubreader', 'cbx_enable'), 'CbxEnable' => $this->configManager->getUserValue($this->userId, Application::APP_ID, 'cbx_enable'),
]; ];
return new TemplateResponse('epubreader', 'settings-personal', $parameters, ''); return new TemplateResponse(Application::APP_ID, 'settings-personal', $parameters, '');
} }
/** /**
@ -56,7 +57,7 @@ class Personal implements ISettings {
* @since 9.1 * @since 9.1
*/ */
public function getSection(): string { public function getSection(): string {
return 'epubreader'; return Application::APP_ID;
} }
/** /**
@ -65,7 +66,7 @@ class Personal implements ISettings {
* @return string * @return string
*/ */
public function getSectionID(): string { public function getSectionID(): string {
return 'epubreader'; return Application::APP_ID;
} }
/** /**

View File

@ -11,6 +11,7 @@
namespace OCA\Epubreader\Settings; namespace OCA\Epubreader\Settings;
use OCA\Epubreader\AppInfo\Application;
use OCP\IL10N; use OCP\IL10N;
use OCP\IURLGenerator; use OCP\IURLGenerator;
use OCP\Settings\IIconSection; use OCP\Settings\IIconSection;
@ -31,7 +32,7 @@ class PersonalSection implements IIconSection {
* @return string * @return string
*/ */
public function getIcon(): string { public function getIcon(): string {
return $this->urlGenerator->imagePath('epubreader', 'app.svg'); return $this->urlGenerator->imagePath(Application::APP_ID, 'app.svg');
} }
/** /**
@ -40,7 +41,7 @@ class PersonalSection implements IIconSection {
* @return string * @return string
*/ */
public function getID(): string { public function getID(): string {
return 'epubreader'; return Application::APP_ID;
} }
/** /**

View File

@ -1,63 +0,0 @@
<?php
/**
* ownCloud - Epubreader App
*
* @author Frank de Lange
* @copyright 2014,2018 Frank de Lange
*
* This file is licensed under the Affero General Public License version 3 or
* later.
*/
namespace OCA\Epubreader;
/**
* Config class for Reader
*/
class Config {
/**
* @brief get user config value
*
* @param string $key value to retrieve
* @param string $default default value to use
* @return string retrieved value or default
*/
public static function get(string $key, string $default): string {
return \OC::$server->getConfig()->getUserValue(\OC_User::getUser(), 'epubreader', $key, $default);
}
/**
* @brief set user config value
*
* @param string $key key for value to change
* @param string $value value to use
* @return bool success
*/
public static function set(string $key, string $value): bool {
return \OC::$server->getConfig()->setUserValue(\OC_User::getUser(), 'epubreader', $key, $value);
}
/**
* @brief get app config value
*
* @param string $key value to retrieve
* @param string $default default value to use
* @return string retrieved value or default
*/
public static function getApp(string $key, string $default): string {
return \OC::$server->getConfig()->getAppValue('epubreader', $key, $default);
}
/**
* @brief set app config value
*
* @param string $key key for value to change
* @param string $value value to use
* @return bool success
*/
public static function setApp(string $key, string $value): bool {
return \OC::$server->getConfig()->setAppValue('epubreader', $key, $value);
}
}

View File

@ -29,11 +29,6 @@
<referencedClass name="Doctrine\DBAL\Schema\Table" /> <referencedClass name="Doctrine\DBAL\Schema\Table" />
</errorLevel> </errorLevel>
</UndefinedDocblockClass> </UndefinedDocblockClass>
<UndefinedClass>
<errorLevel type="suppress">
<referencedClass name="OC" />
</errorLevel>
</UndefinedClass>
<PropertyNotSetInConstructor errorLevel="suppress" /> <PropertyNotSetInConstructor errorLevel="suppress" />
</issueHandlers> </issueHandlers>
</psalm> </psalm>