diff --git a/appinfo/app.php b/appinfo/app.php deleted file mode 100644 index 3a8af3f..0000000 --- a/appinfo/app.php +++ /dev/null @@ -1,20 +0,0 @@ -getL10N('epubreader'); - -\OCA\Epubreader\Hooks::register(); -Util::addscript('epubreader', 'plugin'); diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php new file mode 100644 index 0000000..913555c --- /dev/null +++ b/lib/AppInfo/Application.php @@ -0,0 +1,30 @@ +getL10N('epubreader'); + Hooks::register(); + Util::addscript('epubreader', 'plugin'); + } +} diff --git a/lib/Controller/PageController.php b/lib/Controller/PageController.php index 13427dd..e91ff0a 100644 --- a/lib/Controller/PageController.php +++ b/lib/Controller/PageController.php @@ -75,15 +75,15 @@ class PageController extends Controller { ]; /** - * $fileInfo = [ - * fileId => null, - * fileName => null, - * fileType => null - * ]; + * @var array{ + * fileId: int, + * fileName: string, + * fileType: string + * } $fileInfo */ - $fileInfo = $this->getFileInfo($this->request->getParam('file')); + $fileInfo = $this->getFileInfo((string) $this->request->getParam('file')); $fileId = $fileInfo['fileId']; - $type = $this->request->getParam('type'); + $type = (string) $this->request->getParam('type'); $scope = $template = $templates[$type]; $params = [ @@ -139,7 +139,7 @@ class PageController extends Controller { if ($type == FileInfo::TYPE_FOLDER && $node instanceof Folder) { $query = []; parse_str(parse_url($path, PHP_URL_QUERY), $query); - if (isset($query['path'])) { + if (isset($query['path']) && is_string($query['path'])) { $node = $node->get($query['path']); } else { throw new NotFoundException('Shared file path or name not set'); @@ -150,11 +150,11 @@ class PageController extends Controller { } else { $filePath = $path; $fileId = $this->rootFolder->getUserFolder($this->userId) - ->get(preg_replace("/.*\/remote.php\/webdav(.*)/", "$1", rawurldecode($this->request->getParam('file')))) + ->get(preg_replace("/.*\/remote.php\/webdav(.*)/", "$1", rawurldecode((string) $this->request->getParam('file')))) ->getId(); } - /** @var array $pathInfo */ + /** @var string[] $pathInfo */ $pathInfo = pathInfo($filePath); return [ diff --git a/lib/Controller/PreferenceController.php b/lib/Controller/PreferenceController.php index 7505aed..2da664d 100644 --- a/lib/Controller/PreferenceController.php +++ b/lib/Controller/PreferenceController.php @@ -57,10 +57,8 @@ class PreferenceController extends Controller { * @param int $fileId * @param string $name * @param string $value - * - * @return array|\OCP\AppFramework\Http\JSONResponse */ - public function set(string $scope, int $fileId, string $name, string $value) { + public function set(string $scope, int $fileId, string $name, string $value): JSONResponse { return new JSONResponse($this->preferenceService->set($scope, $fileId, $name, $value)); } diff --git a/lib/Controller/SettingsController.php b/lib/Controller/SettingsController.php index 5e82f47..d0759e0 100644 --- a/lib/Controller/SettingsController.php +++ b/lib/Controller/SettingsController.php @@ -34,10 +34,10 @@ class SettingsController extends Controller { Config::set('pdf_enable', $PdfEnable); Config::set('cbx_enable', $CbxEnable); - $response = array( - 'data' => array('message' => $l->t('Settings updated successfully.')), + $response = [ + 'data' => ['message' => $l->t('Settings updated successfully.')], 'status' => 'success' - ); + ]; return new JSONResponse($response); } diff --git a/lib/Db/ReaderEntity.php b/lib/Db/ReaderEntity.php index a95bc9f..f9bbbc8 100644 --- a/lib/Db/ReaderEntity.php +++ b/lib/Db/ReaderEntity.php @@ -12,12 +12,20 @@ namespace OCA\Epubreader\Db; use OCP\AppFramework\Db\Entity; +/** + * @psalm-type SerializedEntity = array + */ abstract class ReaderEntity extends Entity { protected int $lastModified; // modification timestamp - /* returns decoded json if input is json, otherwise returns input */ + /** + * returns decoded json if input is json, otherwise returns input + * + * @return string|array + */ public static function conditional_json_decode(string $el): mixed { + /** @var array $result */ $result = json_decode($el); if (json_last_error() === JSON_ERROR_NONE) { return $result; @@ -34,5 +42,13 @@ abstract class ReaderEntity extends Entity { $this->lastModified = $lastModified; } + /** + * @psalm-return SerializedEntity + */ abstract public function toService(): array; + + /** + * @psalm-return SerializedEntity + */ + abstract public function jsonSerialize(): array; } diff --git a/lib/Hooks.php b/lib/Hooks.php index 19bc86e..98bce2f 100644 --- a/lib/Hooks.php +++ b/lib/Hooks.php @@ -18,6 +18,7 @@ use OCP\Util; 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) { @@ -35,12 +36,20 @@ class Hooks { public static function announce_settings(array $settings): void { // 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 - $isJson = self::isJson($settings['array']['oc_appconfig']); - $array = ($isJson) ? json_decode($settings['array']['oc_appconfig'], true) : $settings['array']['oc_appconfig']; - $array['filesReader']['enableEpub'] = Config::get('epub_enable', 'true'); - $array['filesReader']['enablePdf'] = Config::get('pdf_enable', 'true'); - $array['filesReader']['enableCbx'] = Config::get('cbx_enable', 'true'); - $settings['array']['oc_appconfig'] = ($isJson) ? json_encode($array) : $array; + if (array_key_exists('array', $settings) && + is_array($settings['array']) && + array_key_exists('oc_appconfig', $settings['array']) + ) { + $isJson = self::isJson($settings['array']['oc_appconfig']); + /** @var array $array */ + $array = ($isJson) ? json_decode((string) $settings['array']['oc_appconfig'], true) : $settings['array']['oc_appconfig']; + $array['filesReader'] = [ + 'enableEpub' => Config::get('epub_enable', 'true'), + 'enablePdf' => Config::get('pdf_enable', 'true'), + 'enableCbx' => Config::get('cbx_enable', 'true'), + ]; + $settings['array']['oc_appconfig'] = ($isJson) ? json_encode($array) : $array; + } } protected static function deleteFile(IDBConnection $connection, int $fileId): void { diff --git a/lib/Service/BookmarkService.php b/lib/Service/BookmarkService.php index 19e6654..eacf74b 100644 --- a/lib/Service/BookmarkService.php +++ b/lib/Service/BookmarkService.php @@ -13,6 +13,9 @@ namespace OCA\Epubreader\Service; use OCA\Epubreader\Db\BookmarkMapper; use OCA\Epubreader\Db\ReaderEntity; +/** + * @psalm-import-type SerializedEntity from ReaderEntity + */ class BookmarkService extends Service { // "bookmark" name to use for the cursor (current reading position) @@ -34,11 +37,13 @@ class BookmarkService extends Service { * @param int $fileId * @param ?string $name * @param ?string $type + * + * @psalm-return SerializedEntity[] */ public function get($fileId, ?string $name = null, ?string $type = null): array { $result = $this->bookmarkMapper->get($fileId, $name, $type); return array_map( - function (ReaderEntity $entity) { + function (ReaderEntity $entity): array { return $entity->toService(); }, $result); } @@ -62,9 +67,11 @@ class BookmarkService extends Service { * @brief get cursor (current position in book) * * @param int $fileId + * + * @psalm-return SerializedEntity */ public function getCursor(int $fileId): array { - $result = $this->get($fileId, static::CURSOR); + $result = $this->get($fileId, self::CURSOR); if (count($result) === 1) { return $result[0]; } @@ -78,7 +85,7 @@ class BookmarkService extends Service { * @param string $value */ public function setCursor(int $fileId, string $value): ReaderEntity { - return $this->bookmarkMapper->set($fileId, static::CURSOR, $value, static::bookmark_type); + return $this->bookmarkMapper->set($fileId, self::CURSOR, $value, self::bookmark_type); } /** @@ -100,6 +107,6 @@ class BookmarkService extends Service { * @param int $fileId */ public function deleteCursor(int $fileId): void { - $this->delete($fileId, static::CURSOR, static::bookmark_type); + $this->delete($fileId, self::CURSOR, self::bookmark_type); } } diff --git a/lib/Service/PreferenceService.php b/lib/Service/PreferenceService.php index e3133d1..adbc03b 100644 --- a/lib/Service/PreferenceService.php +++ b/lib/Service/PreferenceService.php @@ -13,6 +13,9 @@ namespace OCA\Epubreader\Service; use OCA\Epubreader\Db\PreferenceMapper; use OCA\Epubreader\Db\ReaderEntity; +/** + * @psalm-import-type SerializedEntity from ReaderEntity + */ class PreferenceService extends Service { // (ab)use the fact that $fileId never goes below 1 by using the @@ -39,12 +42,12 @@ class PreferenceService extends Service { * @param int $fileId * @param ?string $name * - * @return array + * @psalm-return SerializedEntity */ public function get(string $scope, int $fileId, ?string $name = null): array { $result = $this->preferenceMapper->get($scope, $fileId, $name); return array_map( - function ($entity) { + function (ReaderEntity $entity): array { return $entity->toService(); }, $result); } @@ -71,7 +74,7 @@ class PreferenceService extends Service { * @param ?string $name */ public function getDefault(string $scope, ?string $name = null): array { - return $this->get($scope, static::DEFAULTS, $name); + return $this->get($scope, self::DEFAULTS, $name); } /** @@ -82,7 +85,7 @@ class PreferenceService extends Service { * @param string $value */ public function setDefault($scope, $name, $value): ReaderEntity { - return $this->preferenceMapper->set($scope, static::DEFAULTS, $name, $value); + return $this->preferenceMapper->set($scope, self::DEFAULTS, $name, $value); } /** @@ -107,6 +110,6 @@ class PreferenceService extends Service { * */ public function deleteDefault(string $scope, ?string $name = null): void { - $this->delete($scope, static::DEFAULTS, $name); + $this->delete($scope, self::DEFAULTS, $name); } } diff --git a/psalm.xml b/psalm.xml index c79ee1e..fef7a59 100644 --- a/psalm.xml +++ b/psalm.xml @@ -34,11 +34,6 @@ - - - - -