diff --git a/.github/workflows/psalm-matrix.yml b/.github/workflows/psalm-matrix.yml new file mode 100644 index 0000000..b22a423 --- /dev/null +++ b/.github/workflows/psalm-matrix.yml @@ -0,0 +1,89 @@ +# This workflow is provided via the organization template repository +# +# https://github.com/nextcloud/.github +# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization +# +# SPDX-FileCopyrightText: 2022-2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: MIT + +name: Static analysis + +on: pull_request + +concurrency: + group: psalm-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + matrix: + runs-on: ubuntu-latest-low + outputs: + ocp-matrix: ${{ steps.versions.outputs.ocp-matrix }} + steps: + - name: Checkout app + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - name: Get version matrix + id: versions + uses: icewind1991/nextcloud-version-matrix@8a7bac6300b2f0f3100088b297995a229558ddba # v1.3.2 + + - name: Check enforcement of minimum PHP version ${{ steps.versions.outputs.php-min }} in psalm.xml + run: grep 'phpVersion="${{ steps.versions.outputs.php-min }}' psalm.xml + + static-analysis: + runs-on: ubuntu-latest + needs: matrix + strategy: + # do not stop on another job's failure + fail-fast: false + matrix: ${{ fromJson(needs.matrix.outputs.ocp-matrix) }} + + name: static-psalm-analysis ${{ matrix.ocp-version }} + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - name: Set up php${{ matrix.php-min }} + uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # v2.37.0 + with: + php-version: ${{ matrix.php-min }} + extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite + coverage: none + ini-file: development + # Temporary workaround for missing pcntl_* in PHP 8.3 + ini-values: disable_functions= + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Install dependencies + run: | + composer remove nextcloud/ocp --dev --no-scripts + composer i + + - name: Check for vulnerable PHP dependencies + run: composer require --dev roave/security-advisories:dev-latest + + - name: Install dependencies # zizmor: ignore[template-injection] + run: composer require --dev 'nextcloud/ocp:${{ matrix.ocp-version }}' --ignore-platform-reqs --with-dependencies + + - name: Run coding standards check + run: composer run psalm -- --threads=1 --monochrome --no-progress --output-format=github + + summary: + runs-on: ubuntu-latest-low + needs: static-analysis + + if: always() + + name: static-psalm-analysis-summary + + steps: + - name: Summary status + run: if ${{ needs.static-analysis.result != 'success' }}; then exit 1; fi diff --git a/appinfo/info.xml b/appinfo/info.xml index af018a5..4dd7885 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -21,7 +21,7 @@ https://github.com/nextcloud/integration_davc https://github.com/nextcloud/integration_davc - + diff --git a/composer.json b/composer.json index b629fe1..7ad2710 100644 --- a/composer.json +++ b/composer.json @@ -11,6 +11,7 @@ }, "require-dev": { "nextcloud/coding-standard": "^1.5.0", + "nextcloud/ocp": "dev-master", "phpunit/phpunit": "^11.5", "psalm/phar": "^6.16" }, @@ -31,9 +32,9 @@ "lint": "find . -name \\*.php -not -path './vendor/*' -not -path './build/*' -print0 | xargs -0 -n1 php -l", "cs:check": "php-cs-fixer fix --dry-run --diff", "cs:fix": "php-cs-fixer fix", - "psalm": "psalm --no-cache --threads=$(nproc)", + "psalm": "psalm.phar --no-cache --threads=$(nproc)", "psalm:dev": "@psalm", - "psalm:baseline": "psalm --threads=1 --update-baseline", + "psalm:baseline": "psalm.phar --threads=1 --update-baseline", "test:unit": "phpunit -c tests/php/phpunit.xml --testsuite 'Unit Tests'", "test:integration": "phpunit -c tests/php/phpunit.xml --testsuite 'Integration Tests'" } diff --git a/composer.lock b/composer.lock index 9f3db95..4d8ff58 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "394259a1ba096378c0851c976b62c71c", + "content-hash": "c7cf931be87380c2d1ab218c50684688", "packages": [], "packages-dev": [ { @@ -164,6 +164,56 @@ }, "time": "2026-05-19T18:30:09+00:00" }, + { + "name": "nextcloud/ocp", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/nextcloud-deps/ocp.git", + "reference": "e2e862d9e50fd492906ec0778356c7a0f734f7e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nextcloud-deps/ocp/zipball/e2e862d9e50fd492906ec0778356c7a0f734f7e2", + "reference": "e2e862d9e50fd492906ec0778356c7a0f734f7e2", + "shasum": "" + }, + "require": { + "php": "~8.1 || ~8.2 || ~8.3 || ~8.4 || ~8.5", + "psr/clock": "^1.0", + "psr/container": "^2.0.2", + "psr/event-dispatcher": "^1.0", + "psr/http-client": "^1.0.3", + "psr/log": "^3.0.2" + }, + "default-branch": true, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "35.0.0-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "AGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Christoph Wurst", + "email": "christoph@winzerhof-wurst.at" + }, + { + "name": "Joas Schilling", + "email": "coding@schilljs.com" + } + ], + "description": "Composer package containing Nextcloud's public OCP API and the unstable NCU API", + "support": { + "issues": "https://github.com/nextcloud-deps/ocp/issues", + "source": "https://github.com/nextcloud-deps/ocp/tree/master" + }, + "time": "2026-05-29T02:04:57+00:00" + }, { "name": "nikic/php-parser", "version": "v5.7.0", @@ -884,6 +934,312 @@ }, "time": "2026-03-19T11:11:23+00:00" }, + { + "name": "psr/clock", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/clock.git", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Clock\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for reading the clock.", + "homepage": "https://github.com/php-fig/clock", + "keywords": [ + "clock", + "now", + "psr", + "psr-20", + "time" + ], + "support": { + "issues": "https://github.com/php-fig/clock/issues", + "source": "https://github.com/php-fig/clock/tree/1.0.0" + }, + "time": "2022-11-25T14:36:26+00:00" + }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client" + }, + "time": "2023-09-23T14:17:50+00:00" + }, + { + "name": "psr/http-message", + "version": "2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/2.0" + }, + "time": "2023-04-04T09:54:51+00:00" + }, + { + "name": "psr/log", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.2" + }, + "time": "2024-09-11T13:17:53+00:00" + }, { "name": "sebastian/cli-parser", "version": "3.0.2", @@ -1975,15 +2331,17 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "nextcloud/ocp": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { "php": ">=8.2 <=8.5" }, - "platform-dev": [], + "platform-dev": {}, "platform-overrides": { "php": "8.2" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.9.0" } diff --git a/lib/Controller/UserConfigurationController.php b/lib/Controller/UserConfigurationController.php index c9f8c57..025b985 100644 --- a/lib/Controller/UserConfigurationController.php +++ b/lib/Controller/UserConfigurationController.php @@ -29,7 +29,7 @@ public function __construct( private CoreService $CoreService, private HarmonizationService $HarmonizationService, private ServicesService $ServicesService, - private string $userId, + private ?string $userId, ) { parent::__construct($appName, $request); } @@ -124,7 +124,7 @@ public function Harmonize(int $sid): DataResponse { } // execute command try { - $this->HarmonizationService->performHarmonization($this->userId, $sid, 'M'); + $this->HarmonizationService->performHarmonization($this->userId, $sid); return new DataResponse('success'); } catch (\Throwable $th) { return new DataResponse($th->getMessage(), Http::STATUS_INTERNAL_SERVER_ERROR); @@ -198,7 +198,7 @@ public function localCollectionsDeposit(int $sid, array $ContactCorrelations, ar } // execute command try { - $rs = $this->CoreService->localCollectionsDeposit($this->userId, $sid, $ContactCorrelations, $EventCorrelations); + $this->CoreService->localCollectionsDeposit($this->userId, $sid, $ContactCorrelations, $EventCorrelations); return $this->localCollectionsFetch($sid); } catch (\Throwable $th) { return new DataResponse($th->getMessage(), Http::STATUS_INTERNAL_SERVER_ERROR); diff --git a/lib/Events/UserDeletedListener.php b/lib/Events/UserDeletedListener.php index 4b11d3f..c9365ff 100644 --- a/lib/Events/UserDeletedListener.php +++ b/lib/Events/UserDeletedListener.php @@ -17,6 +17,9 @@ use OCP\User\Events\UserDeletedEvent; use Psr\Log\LoggerInterface; +/** + * @template-implements IEventListener + */ class UserDeletedListener implements IEventListener { public function __construct( @@ -33,7 +36,7 @@ public function handle(Event $event): void { $services = $this->servicesService->fetchByUserId($event->getUser()->getUID()); foreach ($services as $service) { - $this->coreService->disconnectAccount($service->getUid(), $service->Id()); + $this->coreService->disconnectAccount($service->getUid(), $service->getId()); } } catch (Exception $e) { $this->logger->warning($e->getMessage(), ['uid' => $event->getUser()->getUID()]); diff --git a/lib/Models/BaseCollection.php b/lib/Models/BaseCollection.php index c2a12a6..80c3243 100644 --- a/lib/Models/BaseCollection.php +++ b/lib/Models/BaseCollection.php @@ -9,6 +9,9 @@ namespace OCA\DAVC\Models; +/** + * @extends \ArrayObject + */ class BaseCollection extends \ArrayObject { private $type; @@ -35,7 +38,7 @@ public function append($value): void { parent::append($value); } - public function offsetSet($key, $value): void { + public function offsetSet(mixed $key, mixed $value): void { if (!$this->validate($value)) { throw new \InvalidArgumentException( sprintf('Cannot set offset %s with value of type %s in collection expecting %s', var_export($key, true), gettype($value), $this->type) diff --git a/lib/Service/ConfigurationService.php b/lib/Service/ConfigurationService.php index 1dda4a3..bb39f60 100644 --- a/lib/Service/ConfigurationService.php +++ b/lib/Service/ConfigurationService.php @@ -16,9 +16,13 @@ class ConfigurationService { /** * Default System Configuration - * @var array + * @var array * */ - private const _SYSTEM = []; + private const _SYSTEM = [ + 'harmonization_mode' => 'P', + 'harmonization_thread_duration' => '3600', + 'harmonization_thread_pause' => '5', + ]; /** * Default System Secure Parameters @@ -298,7 +302,7 @@ public function retrieveSystemValue(string $key): string { return $value; } else { // return default system configuration value - return self::_SYSTEM[$key]; + return self::_SYSTEM[$key] ?? ''; } } @@ -381,7 +385,7 @@ public function setHarmonizationMode(string $mode): void { * * @since Release 1.0.0 * - * @return string harmonization thread run duration interval (default 3600 seconds) + * @return int harmonization thread run duration interval (default 3600 seconds) */ public function getHarmonizationThreadDuration(): int { @@ -402,14 +406,14 @@ public function getHarmonizationThreadDuration(): int { * * @since Release 1.0.0 * - * @param string $interval harmonization thread pause interval in seconds + * @param int $interval harmonization thread pause interval in seconds * * @return void */ public function setHarmonizationThreadDuration(int $interval): void { // set value - $this->depositSystemValue('harmonization_thread_duration', $interval); + $this->depositSystemValue('harmonization_thread_duration', (string)$interval); } @@ -418,7 +422,7 @@ public function setHarmonizationThreadDuration(int $interval): void { * * @since Release 1.0.0 * - * @return string harmonization thread pause interval (default 5 seconds) + * @return int harmonization thread pause interval (default 5 seconds) */ public function getHarmonizationThreadPause(): int { @@ -429,7 +433,7 @@ public function getHarmonizationThreadPause(): int { if (is_numeric($interval)) { return intval($interval); } else { - return intval($self::_SYSTEM['harmonization_thread_pause']); + return intval(self::_SYSTEM['harmonization_thread_pause']); } } @@ -439,14 +443,14 @@ public function getHarmonizationThreadPause(): int { * * @since Release 1.0.0 * - * @param string $interval harmonization thread pause interval in seconds + * @param int $interval harmonization thread pause interval in seconds * * @return void */ public function setHarmonizationThreadPause(int $interval): void { // set value - $this->depositSystemValue('harmonization_thread_pause', $interval); + $this->depositSystemValue('harmonization_thread_pause', (string)$interval); } @@ -457,7 +461,7 @@ public function setHarmonizationThreadPause(int $interval): void { * * @param string $uid nextcloud user id * - * @return string|null thread id if exists | null if does not exist + * @return int thread id if exists | 0 if does not exist */ public function getHarmonizationThreadId(string $uid): int { @@ -478,7 +482,7 @@ public function getHarmonizationThreadId(string $uid): int { * @since Release 1.0.0 * * @param string $uid nextcloud user id - * @param string $tid thread id + * @param int $tid thread id * * @return void */ @@ -524,7 +528,7 @@ public function getHarmonizationThreadHeartBeat(string $uid): int { public function setHarmonizationThreadHeartBeat(string $uid, int $thb): void { // update harmonization thread id - $this->depositUserValue($uid, 'account_harmonization_thb', $thb); + $this->depositUserValue($uid, 'account_harmonization_thb', (string)$thb); } diff --git a/lib/Service/ContactsService.php b/lib/Service/ContactsService.php index 6fdeb11..fd1d39b 100644 --- a/lib/Service/ContactsService.php +++ b/lib/Service/ContactsService.php @@ -51,7 +51,7 @@ public function harmonize(string $uid, ServiceEntity $service, RemoteClient $rem $this->debug = (bool)$service->getDebug(); // initialize service remote and local services $this->remoteContactsService = $this->remoteFactory->contactsService($this->remoteStore); - $this->localContactsService = $this->localFactory->contactsService($uid); + $this->localContactsService = $this->localFactory->contactsService(); $this->localStore = $this->localFactory->contactsStore(); // retrieve list of collections @@ -122,7 +122,7 @@ public function harmonizeCollection(CollectionEntity $collection): Harmonization // retrieve a delta of remote entity variations try { - $remoteEntityDelta = $this->remoteContactsService->entityDelta($remoteCollectionId, $remoteCollectionSignature, 'B'); + $remoteEntityDelta = $this->remoteContactsService->entityDelta($remoteCollectionId, $remoteCollectionSignature); } catch (\RuntimeException) { $remoteEntityDelta = $this->determineRemoteDelta($collection); } @@ -213,17 +213,17 @@ public function determineRemoteDelta(CollectionEntity $collection): DeltaObject // if NOT found add entity to added delta if (isset($lList[$entry->remoteEntityId])) { if ($entry->remoteSignature !== $lList[$entry->remoteEntityId]->localSignature) { - $delta->modifications[] = $entry->remoteEntityId; + $delta->modifications->append($entry->remoteEntityId); } unset($lList[$entry->remoteEntityId]); } else { - $delta->additions[] = $entry->remoteEntityId; + $delta->additions->append($entry->remoteEntityId); } } // iterate through remaining correlations // if a correlation that was not removed it must have been deleted on the remote system foreach ($lList as $entry) { - $delta->deletions[] = $entry->remoteEntityId; + $delta->deletions->append($entry->remoteEntityId); } return $delta; diff --git a/lib/Service/CoreService.php b/lib/Service/CoreService.php index 29e52fb..04a8d84 100644 --- a/lib/Service/CoreService.php +++ b/lib/Service/CoreService.php @@ -43,11 +43,9 @@ public function __construct( * * @since Release 1.0.0 * - * @param string $uid user id - * @param string $account_bauth_id account username - * @param string $account_bauth_secret account secret + * @param array $configuration service connection data * - * @return object + * @return array|null */ public function locateAccount(array $configuration): ?array { @@ -225,11 +223,12 @@ public function disconnectAccount(string $uid, int $sid): void { // retrieve service information $service = $this->ServicesService->fetch($sid); // determine if user if the service owner - if ($service->getUid() !== $uid) { + if ($service === null || $service->getUid() !== $uid) { return; } // deregister task - $this->TaskService->remove(\OCA\DAVC\Tasks\HarmonizationLauncher::class, ['uid' => $uid, 'sid' => $sid]); + // TODO: re-enable once the harmonization launcher task is implemented (see connectAccount) + //$this->TaskService->remove(\OCA\DAVC\Tasks\HarmonizationLauncher::class, ['uid' => $uid, 'sid' => $sid]); // terminate harmonization thread $this->HarmonizationThreadService->terminate($uid); // initialize contacts data store @@ -266,7 +265,7 @@ public function remoteCollectionsFetch(string $uid, int $sid): array { // retrieve service information $service = $this->ServicesService->fetch($sid); // determine if user is the service owner - if ($service->getUid() !== $uid) { + if ($service === null || $service->getUid() !== $uid) { return $data; } // create remote store client @@ -334,7 +333,7 @@ public function localCollectionsFetch(string $uid, int $sid): array { // retrieve service information $service = $this->ServicesService->fetch($sid); // determine if user if the service owner - if ($service->getUid() !== $uid) { + if ($service === null || $service->getUid() !== $uid) { return $data; } // retrieve local collections @@ -360,7 +359,7 @@ public function localCollectionsFetch(string $uid, int $sid): array { * @param array $cc contacts collection(s) correlations * @param array $ec events collection(s) correlations * - * @return array of collection correlation(s) and attributes + * @return void */ public function localCollectionsDeposit(string $uid, int $sid, array $cc, array $ec): void { @@ -369,7 +368,7 @@ public function localCollectionsDeposit(string $uid, int $sid, array $cc, array // retrieve service information $service = $this->ServicesService->fetch($sid); // determine if user is the service owner - if ($service->getUid() !== $uid) { + if ($service === null || $service->getUid() !== $uid) { return; } $remoteStore = $this->remoteFactory->freshClient($service); @@ -393,7 +392,7 @@ public function localCollectionsDeposit(string $uid, int $sid, array $cc, array switch ((bool)$entry['enabled']) { case false: if (is_numeric($entry['id'])) { - $collection = $localStore->collectionFetch($entry['id']); + $collection = $localStore->collectionFetch((int)$entry['id']); if ($collection->getUid() === $uid) { $localStore->collectionDelete($collection); } @@ -418,7 +417,7 @@ public function localCollectionsDeposit(string $uid, int $sid, array $cc, array $collection->setPermissions($remoteCollection?->permissions); $collection->setLabel('DavC: ' . ($remoteCollection?->label ?? $entry['label'] ?? 'Unknown')); $collection->setColor($remoteCollection?->color ?? $entry['color'] ?? '#0055aa'); - $collection->setVisible(true); + $collection->setVisible(1); $collection->setHesn($remoteCollection?->remoteSignature); $id = $localStore->collectionCreate($collection); } @@ -446,7 +445,7 @@ public function localCollectionsDeposit(string $uid, int $sid, array $cc, array switch ((bool)$entry['enabled']) { case false: if (is_numeric($entry['id'])) { - $collection = $localStore->collectionFetch($entry['id']); + $collection = $localStore->collectionFetch((int)$entry['id']); if ($collection->getUid() === $uid) { $localStore->collectionDelete($collection); } @@ -471,7 +470,7 @@ public function localCollectionsDeposit(string $uid, int $sid, array $cc, array $collection->setPermissions($remoteCollection?->permissions); $collection->setLabel('DavC: ' . ($remoteCollection?->label ?? $entry['label'] ?? 'Unknown')); $collection->setColor($remoteCollection?->color ?? $entry['color'] ?? '#0055aa'); - $collection->setVisible(true); + $collection->setVisible(1); $collection->setHesn($remoteCollection?->remoteSignature); $id = $localStore->collectionCreate($collection); } @@ -490,7 +489,7 @@ public function localCollectionsDeposit(string $uid, int $sid, array $cc, array * @param string $subject notification type * @param array $params notification parameters to pass * - * @return array of collection correlation(s) and attributes + * @return void */ public function publishNotice(string $uid, string $subject, array $params): void { // construct notification object diff --git a/lib/Service/EventsService.php b/lib/Service/EventsService.php index 9cfe8ea..c4c383c 100644 --- a/lib/Service/EventsService.php +++ b/lib/Service/EventsService.php @@ -30,7 +30,7 @@ class EventsService { private RemoteEventsService $remoteEventsService; private LocalEventsService $localEventsService; private RemoteClient $remoteStore; - private readonly EventStore $localStore; + private EventStore $localStore; public function __construct( private readonly LoggerInterface $logger, @@ -51,7 +51,7 @@ public function harmonize(string $uid, ServiceEntity $service, RemoteClient $rem $this->debug = (bool)$service->getDebug(); // initialize service remote and local services $this->remoteEventsService = $this->remoteFactory->eventsService($this->remoteStore); - $this->localEventsService = $this->localFactory->eventsService($uid); + $this->localEventsService = $this->localFactory->eventsService(); $this->localStore = $this->localFactory->eventsStore(); // retrieve list of collections @@ -122,7 +122,7 @@ public function harmonizeCollection(CollectionEntity $collection): Harmonization // retrieve a delta of remote entity variations try { - $remoteEntityDelta = $this->remoteEventsService->entityDelta($remoteCollectionId, $remoteCollectionSignature, 'B'); + $remoteEntityDelta = $this->remoteEventsService->entityDelta($remoteCollectionId, $remoteCollectionSignature); } catch (\RuntimeException) { $remoteEntityDelta = $this->determineRemoteDelta($collection); } @@ -213,17 +213,17 @@ public function determineRemoteDelta(CollectionEntity $collection): DeltaObject // if NOT found add entity to added delta if (isset($lList[$entry->remoteEntityId])) { if ($entry->remoteSignature !== $lList[$entry->remoteEntityId]->localSignature) { - $delta->modifications[] = $entry->remoteEntityId; + $delta->modifications->append($entry->remoteEntityId); } unset($lList[$entry->remoteEntityId]); } else { - $delta->additions[] = $entry->remoteEntityId; + $delta->additions->append($entry->remoteEntityId); } } // iterate through remaining correlations // if a correlation that was not removed it must have been deleted on the remote system foreach ($lList as $entry) { - $delta->deletions[] = $entry->remoteEntityId; + $delta->deletions->append($entry->remoteEntityId); } return $delta; diff --git a/lib/Service/HarmonizationService.php b/lib/Service/HarmonizationService.php index 6143de7..265b1d9 100644 --- a/lib/Service/HarmonizationService.php +++ b/lib/Service/HarmonizationService.php @@ -62,7 +62,7 @@ public function performHarmonizationForService(ServiceEntity $service): void { return; } // update harmonization state and start time - $service->setHarmonizationState(true); + $service->setHarmonizationState(1); $service->setHarmonizationStart(time()); $service = $this->servicesService->deposit($service->getUid(), $service); // initialize store(s) @@ -87,7 +87,7 @@ public function performHarmonizationForService(ServiceEntity $service): void { } // update harmonization state and end time - $service->setHarmonizationState(false); + $service->setHarmonizationState(0); $service->setHarmonizationEnd(time()); $service = $this->servicesService->deposit($service->getUid(), $service); diff --git a/lib/Service/HarmonizationThreadService.php b/lib/Service/HarmonizationThreadService.php index 6e02461..c10c8aa 100644 --- a/lib/Service/HarmonizationThreadService.php +++ b/lib/Service/HarmonizationThreadService.php @@ -33,7 +33,7 @@ public function __construct(LoggerInterface $logger, ConfigurationService $Confi * * @param string $uid nextcloud user id * - * @return string|null thread id on success | null on failure + * @return int thread id on success | 0 on failure */ public function launch(string $uid): int { @@ -65,7 +65,7 @@ public function launch(string $uid): int { * @since Release 1.0.0 * * @param string $uid nextcloud user id - * @param string $tid thread id (optional) + * @param int $tid thread id (optional) * * @return int quantity of threads terminated */ @@ -150,14 +150,7 @@ public function list(?string $uid = null): array { public function getId(string $uid): int { // retrieve thread id - $tid = $this->ConfigurationService->getHarmonizationThreadId($uid); - // return thread id - if (is_numeric($tid)) { - return intval($tid); - } else { - return 0; - } - + return $this->ConfigurationService->getHarmonizationThreadId($uid); } /** @@ -189,14 +182,7 @@ public function setId(string $uid, int $tid): void { public function getHeartBeat(string $uid): ?int { // retrieve thread heart beat - $thb = $this->ConfigurationService->getHarmonizationThreadHeartBeat($uid); - // return thread heart beat - if (is_numeric($thb)) { - return (int)$thb; - } else { - return null; - } - + return $this->ConfigurationService->getHarmonizationThreadHeartBeat($uid); } /** diff --git a/lib/Service/Local/LocalContactsService.php b/lib/Service/Local/LocalContactsService.php index a8fe397..67f2344 100644 --- a/lib/Service/Local/LocalContactsService.php +++ b/lib/Service/Local/LocalContactsService.php @@ -60,7 +60,7 @@ public function collectionFetch(int $id): ?Collection { } public function collectionDelta(int $id): string { - return $this->_Store->chronicleApex($id, true); + return (string)$this->_Store->chronicleApex($id, true); } public function collectionModify(int $id, Collection $mutation): ?Collection { @@ -73,7 +73,7 @@ public function collectionModify(int $id, Collection $mutation): ?Collection { $entry->setLabel($mutation->label); } if (isset($mutation->visible)) { - $entry->setVisible($mutation->visible); + $entry->setVisible((int)$mutation->visible); } if (isset($mutation->color)) { $entry->setColor($mutation->color); diff --git a/lib/Service/Local/LocalEventsService.php b/lib/Service/Local/LocalEventsService.php index df3af87..be1fba9 100644 --- a/lib/Service/Local/LocalEventsService.php +++ b/lib/Service/Local/LocalEventsService.php @@ -62,7 +62,7 @@ public function collectionFetch(int $id): ?Collection { } public function collectionDelta(int $id): string { - return $this->_Store->chronicleApex($id, true); + return (string)$this->_Store->chronicleApex($id, true); } public function collectionModify(int $id, Collection $mutation): ?Collection { @@ -75,7 +75,7 @@ public function collectionModify(int $id, Collection $mutation): ?Collection { $entry->setLabel($mutation->label); } if (isset($mutation->visible)) { - $entry->setVisible($mutation->visible); + $entry->setVisible((int)$mutation->visible); } if (isset($mutation->color)) { $entry->setColor($mutation->color); diff --git a/lib/Service/Remote/RemoteClient.php b/lib/Service/Remote/RemoteClient.php index 061b5d9..7d8ffd5 100644 --- a/lib/Service/Remote/RemoteClient.php +++ b/lib/Service/Remote/RemoteClient.php @@ -278,7 +278,7 @@ public function multiGet(string $collectionPath, array $hrefs, string $reportTyp } /** - * @return array{etag: string|null, statusCode: int, location: string|null, lastModified: string|null, response: IResponse} + * @return array{status: int, etag: string|null, location: string|null, lastModified: string|null} */ public function create(string $path, string $payload, string $contentType): array { $url = $this->constructUrl($path); @@ -295,7 +295,7 @@ public function create(string $path, string $payload, string $contentType): arra } /** - * @return array{etag: string|null, statusCode: int, location: string|null, lastModified: string|null, response: IResponse} + * @return array{status: int, etag: string|null, location: string|null, lastModified: string|null} */ public function update(string $path, string $payload, string $contentType, ?string $etag = null): array { $url = $this->constructUrl($path); diff --git a/lib/Service/Remote/RemoteContactsService.php b/lib/Service/Remote/RemoteContactsService.php index ec874a3..4d57bae 100644 --- a/lib/Service/Remote/RemoteContactsService.php +++ b/lib/Service/Remote/RemoteContactsService.php @@ -60,7 +60,7 @@ public function initialize(RemoteClient $dataStore) { /** * list of collections in remote storage * - * @return array + * @return list */ public function collectionList(string $granularity = 'basic'): array { // transceive @@ -201,8 +201,8 @@ public function entityFetchMultiple(string $location, array $identifiers): array * @return DeltaObject */ public function entityDelta(string $location, string $state): DeltaObject { - $davAbilities = $this->dataStore->capabilities('dav') ?? []; - $davMethods = $this->dataStore->capabilities('allow') ?? []; + $davAbilities = $this->dataStore->capabilities('dav'); + $davMethods = $this->dataStore->capabilities('allow'); if (in_array('sync-collection', $davAbilities, true) === false && in_array('REPORT', $davMethods, true) === false) { throw new RuntimeException('Remote server does not support DAV sync-collection reports.'); diff --git a/lib/Service/Remote/RemoteEventsService.php b/lib/Service/Remote/RemoteEventsService.php index c8cd310..10cc124 100644 --- a/lib/Service/Remote/RemoteEventsService.php +++ b/lib/Service/Remote/RemoteEventsService.php @@ -61,7 +61,7 @@ public function initialize(RemoteClient $dataStore) { /** * list of collections in remote storage * - * @return array + * @return list */ public function collectionList(string $granularity = 'basic'): array { // transceive @@ -202,8 +202,8 @@ public function entityFetchMultiple(string $location, array $identifiers): array * @return DeltaObject */ public function entityDelta(string $location, string $state): DeltaObject { - $davAbilities = $this->dataStore->capabilities('dav') ?? []; - $davMethods = $this->dataStore->capabilities('allow') ?? []; + $davAbilities = $this->dataStore->capabilities('dav'); + $davMethods = $this->dataStore->capabilities('allow'); if (in_array('sync-collection', $davAbilities, true) === false && in_array('REPORT', $davMethods, true) === false) { throw new RuntimeException('Remote server does not support DAV sync-collection reports.'); diff --git a/lib/Service/ServicesService.php b/lib/Service/ServicesService.php index f3e95ba..08975f4 100644 --- a/lib/Service/ServicesService.php +++ b/lib/Service/ServicesService.php @@ -60,7 +60,7 @@ public function fresh(): ServiceEntity { return new ServiceEntity(); } - public function fetch(int $id): ServiceEntity { + public function fetch(int $id): ?ServiceEntity { return $this->_Store->fetch($id); } diff --git a/lib/Settings/AdminSection.php b/lib/Settings/AdminSection.php index 924dc14..c39dd0a 100644 --- a/lib/Settings/AdminSection.php +++ b/lib/Settings/AdminSection.php @@ -55,9 +55,9 @@ public function getPriority(): int { } /** - * @return ?string The relative path to a an icon describing the section + * @return string The relative path to a an icon describing the section */ - public function getIcon(): ?string { + public function getIcon(): string { return $this->urlGenerator->imagePath('core', 'categories/integration.svg'); } diff --git a/lib/Settings/UserSection.php b/lib/Settings/UserSection.php index 7cd6941..4779d5e 100644 --- a/lib/Settings/UserSection.php +++ b/lib/Settings/UserSection.php @@ -55,9 +55,9 @@ public function getPriority(): int { } /** - * @return ?string The relative path to a an icon describing the section + * @return string The relative path to a an icon describing the section */ - public function getIcon(): ?string { + public function getIcon(): string { return $this->urlGenerator->imagePath('core', 'categories/integration.svg'); } diff --git a/lib/Store/Common/Filters/FilterBase.php b/lib/Store/Common/Filters/FilterBase.php index 5dd623a..7ca431d 100644 --- a/lib/Store/Common/Filters/FilterBase.php +++ b/lib/Store/Common/Filters/FilterBase.php @@ -29,7 +29,7 @@ public function attributes(): array { * @since 1.0.0 */ public function comparators(): FilterComparisonOperator { - return new FilterComparisonOperator; + return FilterComparisonOperator::EQ; } /** @@ -37,7 +37,7 @@ public function comparators(): FilterComparisonOperator { * @since 1.0.0 */ public function conjunctions(): FilterConjunctionOperator { - return new FilterConjunctionOperator; + return FilterConjunctionOperator::NONE; } /** @@ -45,10 +45,10 @@ public function conjunctions(): FilterConjunctionOperator { * @since 1.0.0 * */ - public function condition(string $attribute, mixed $value, FilterComparisonOperator $comparator = FilterComparisonOperator::EQ, FilterConjunctionOperator $conjunction = FilterConjunctionOperator::AND): void { - if (!isset($this->properties[$attribute])) { + public function condition(string $property, mixed $value, FilterComparisonOperator $comparator = FilterComparisonOperator::EQ, FilterConjunctionOperator $conjunction = FilterConjunctionOperator::AND): void { + if (!isset($this->attributes[$property])) { $this->conditions[] = [ - 'attribute' => $attribute, + 'attribute' => $property, 'value' => $value, 'comparator' => $comparator, 'conjunction' => $conjunction, diff --git a/lib/Store/Common/Range/RangeDate.php b/lib/Store/Common/Range/RangeDate.php index f4ae953..a17c85f 100644 --- a/lib/Store/Common/Range/RangeDate.php +++ b/lib/Store/Common/Range/RangeDate.php @@ -14,20 +14,15 @@ class RangeDate implements IRangeDate { + protected DateTimeInterface $start; + protected DateTimeInterface $end; + public function __construct( - protected ?DateTimeInterface $start = null, - protected ?DateTimeInterface $end = null, + ?DateTimeInterface $start = null, + ?DateTimeInterface $end = null, ) { - - if ($start === null) { - $start = new DateTime(); - } - if ($end === null) { - $end = new DateTime(); - } - $this->start = $start; - $this->end = $end; - + $this->start = $start ?? new DateTime(); + $this->end = $end ?? new DateTime(); } /** diff --git a/lib/Store/Common/Range/RangeTallyAbsolute.php b/lib/Store/Common/Range/RangeTallyAbsolute.php index 87a66ea..176d87a 100644 --- a/lib/Store/Common/Range/RangeTallyAbsolute.php +++ b/lib/Store/Common/Range/RangeTallyAbsolute.php @@ -54,7 +54,7 @@ public function setPosition(string|int $value): void { * @since 1.0.0 */ public function getCount(): int { - return $this->count; + return (int)$this->count; } /** diff --git a/lib/Store/Common/Range/RangeTallyRelative.php b/lib/Store/Common/Range/RangeTallyRelative.php index 2b263c2..7fd9968 100644 --- a/lib/Store/Common/Range/RangeTallyRelative.php +++ b/lib/Store/Common/Range/RangeTallyRelative.php @@ -54,7 +54,7 @@ public function setPosition(string|int $value): void { * @since 1.0.0 */ public function getCount(): int { - return $this->count; + return (int)$this->count; } /** diff --git a/lib/Store/Common/Sort/SortBase.php b/lib/Store/Common/Sort/SortBase.php index 1a425a5..133cf04 100644 --- a/lib/Store/Common/Sort/SortBase.php +++ b/lib/Store/Common/Sort/SortBase.php @@ -28,13 +28,13 @@ public function attributes(): array { * * @since 1.0.0 * - * @param string $attribute attribute name + * @param string $property attribute name * @param bool $direction true for ascending, false for descending */ - public function condition(string $attribute, bool $direction): void { - if (isset($this->attributes[$attribute])) { - $this->conditions[$attribute] = [ - 'attribute' => $attribute, + public function condition(string $property, bool $direction): void { + if (isset($this->attributes[$property])) { + $this->conditions[$property] = [ + 'attribute' => $property, 'direction' => $direction, ]; } diff --git a/lib/Store/Local/BaseEntity.php b/lib/Store/Local/BaseEntity.php new file mode 100644 index 0000000..7a99a02 --- /dev/null +++ b/lib/Store/Local/BaseEntity.php @@ -0,0 +1,28 @@ +_Store->getQueryBuilder(); @@ -703,11 +703,11 @@ public function entityCreate(Entity $entity): Entity { * * @since Release 1.0.0 * - * @param Entity $entity + * @param BaseEntity $entity * * @return Entity */ - public function entityModify(Entity $entity): Entity { + public function entityModify(BaseEntity $entity): Entity { // construct data store command $cmd = $this->_Store->getQueryBuilder(); @@ -741,11 +741,11 @@ public function entityModify(Entity $entity): Entity { * * @since Release 1.0.0 * - * @param Entity $entity + * @param BaseEntity $entity * * @return Entity */ - public function entityDelete(Entity $entity): Entity { + public function entityDelete(BaseEntity $entity): Entity { // construct data store command $cmd = $this->_Store->getQueryBuilder(); @@ -764,7 +764,7 @@ public function entityDelete(Entity $entity): Entity { * * @since Release 1.0.0 * - * @param string $id entity id + * @param int $id entity id * * @return mixed */ @@ -842,10 +842,10 @@ public function entityDeleteByCollection(int $cid): mixed { * * @param string $uid user id * @param int $sid service id - * @param string $cid collection id - * @param string $eid entity id + * @param int $cid collection id + * @param int $eid entity id * @param string $euuid entity uuid - * @param string $operation operation type (1 - Created, 2 - Modified, 3 - Deleted) + * @param int $operation operation type (1 - Created, 2 - Modified, 3 - Deleted) * * @return string */ @@ -876,7 +876,7 @@ public function chronicleDocument(string $uid, int $sid, int $cid, int $eid, str * @since Release 1.0.0 * * @param int $cid collection id - * @param int $encode weather to encode the result + * @param bool $encode weather to encode the result * * @return int|float|string */ @@ -887,8 +887,13 @@ public function chronicleApex(int $cid, bool $encode = true): int|float|string { ->from($this->_ChronicleTable) ->where($cmd->expr()->eq('cid', $cmd->createNamedParameter($cid))) ->andWhere($cmd->expr()->eq('tag', $cmd->createNamedParameter($this->_EntityIdentifier))); - $stampApex = $cmd->executeQuery()->fetchOne(); - $cmd->executeQuery()->closeCursor(); + $result = $cmd->executeQuery(); + $stampApex = $result->fetchOne(); + $result->closeCursor(); + // normalize missing/false result to 0 + if ($stampApex === false) { + $stampApex = 0; + } if ($encode) { return base64_encode((string)max(0, $stampApex)); @@ -974,7 +979,7 @@ public function chronicleReminisce(int $cid, string $stamp, ?int $limit = null, * * @since Release 1.0.0 * - * @param int $id user id + * @param string $id user id * * @return mixed */ diff --git a/lib/Store/Local/CollectionEntity.php b/lib/Store/Local/CollectionEntity.php index dd6c52d..a91de82 100644 --- a/lib/Store/Local/CollectionEntity.php +++ b/lib/Store/Local/CollectionEntity.php @@ -17,8 +17,8 @@ * @method getId(): int * @method getUid(): ?string * @method setUid(string $uid): void - * @method getSid(): ?string - * @method setSid(string $sid): void + * @method getSid(): ?int + * @method setSid(int $sid): void * @method getType(): ?string * @method setType(string $type): void * @method getCcid(): ?string @@ -31,8 +31,8 @@ * @method setLabel(string $label): void * @method getColor(): ?string * @method setColor(string $color): void - * @method getVisible(): ?string - * @method setVisible(string $visible): void + * @method getVisible(): ?int + * @method setVisible(int $visible): void * @method getHisn(): ?string * @method setHisn(string $hisn): void * @method getHesn(): ?string diff --git a/lib/Store/Local/ContactEntity.php b/lib/Store/Local/ContactEntity.php index 46f5261..95740b4 100644 --- a/lib/Store/Local/ContactEntity.php +++ b/lib/Store/Local/ContactEntity.php @@ -9,18 +9,7 @@ namespace OCA\DAVC\Store\Local; -use OCP\AppFramework\Db\Entity; - /** - * @method getId(): int - * @method getUid(): string - * @method setUid(string $uid): void - * @method getSid(): string - * @method setSid(int $sid): void - * @method getCid(): string - * @method setCid(int $cid): void - * @method getUuid(): string - * @method setUuid(string $uuid): void * @method getSignature(): string * @method setSignature(string $signature): void * @method getCcid(): string @@ -34,7 +23,7 @@ * @method getLabel(): string * @method setLabel(string $label): void */ -class ContactEntity extends Entity { +class ContactEntity extends BaseEntity { protected ?string $uid = null; protected ?int $sid = null; protected ?int $cid = null; diff --git a/lib/Store/Local/EventEntity.php b/lib/Store/Local/EventEntity.php index 28df5ad..7c8fd15 100644 --- a/lib/Store/Local/EventEntity.php +++ b/lib/Store/Local/EventEntity.php @@ -9,18 +9,7 @@ namespace OCA\DAVC\Store\Local; -use OCP\AppFramework\Db\Entity; - /** - * @method getId(): int - * @method getUid(): string - * @method setUid(string $uid): void - * @method getSid(): string - * @method setSid(int $sid): void - * @method getCid(): string - * @method setCid(int $cid): void - * @method getUuid(): string - * @method setUuid(string $uuid): void * @method getSignature(): string * @method setSignature(string $signature): void * @method getCcid(): string @@ -40,7 +29,7 @@ * @method getEndson(): int * @method setEndson(int $endson): void */ -class EventEntity extends Entity { +class EventEntity extends BaseEntity { protected ?string $uid = null; protected ?int $sid = null; protected ?int $cid = null; diff --git a/lib/Store/Local/Filters/ContactFilter.php b/lib/Store/Local/Filters/ContactFilter.php index 4a69446..91760ff 100644 --- a/lib/Store/Local/Filters/ContactFilter.php +++ b/lib/Store/Local/Filters/ContactFilter.php @@ -17,7 +17,6 @@ class ContactFilter extends FilterBase { 'uid' => true, 'sid' => true, 'cid' => true, - 'uid' => true, 'uuid' => true, 'label' => true, ]; diff --git a/lib/Store/Local/Filters/EventFilter.php b/lib/Store/Local/Filters/EventFilter.php index 231a353..311fb38 100644 --- a/lib/Store/Local/Filters/EventFilter.php +++ b/lib/Store/Local/Filters/EventFilter.php @@ -17,7 +17,6 @@ class EventFilter extends FilterBase { 'uid' => true, 'sid' => true, 'cid' => true, - 'uid' => true, 'uuid' => true, 'startson' => true, 'endson' => true, diff --git a/lib/Store/Local/ServicesTemplateStore.php b/lib/Store/Local/ServicesTemplateStore.php index 06c849c..2849151 100644 --- a/lib/Store/Local/ServicesTemplateStore.php +++ b/lib/Store/Local/ServicesTemplateStore.php @@ -32,10 +32,11 @@ public function fetchById(string $id): array { ->from($this->_EntityTable) ->where($cmd->expr()->eq('id', $cmd->createNamedParameter($id))); // execute command - $rs = $cmd->executeQuery()->fetchAll(); - $cmd->executeQuery()->closeCursor(); + $result = $cmd->executeQuery(); + $rs = $result->fetchAll(); + $result->closeCursor(); // return result or null - if (is_array($rs) && count($rs) > 0) { + if (count($rs) > 0) { return $rs; } else { return []; @@ -58,10 +59,11 @@ public function fetchByDomain(string $domain): array { ->from($this->_EntityTable) ->where($cmd->expr()->eq('domain', $cmd->createNamedParameter($domain))); // execute command - $rs = $cmd->executeQuery()->fetchAll(); - $cmd->executeQuery()->closeCursor(); + $result = $cmd->executeQuery(); + $rs = $result->fetchAll(); + $result->closeCursor(); // return result or null - if (is_array($rs) && count($rs) > 0) { + if (count($rs) > 0) { return $rs; } else { return []; diff --git a/lib/Store/Local/Sort/ContactSort.php b/lib/Store/Local/Sort/ContactSort.php index f5f2951..e86717b 100644 --- a/lib/Store/Local/Sort/ContactSort.php +++ b/lib/Store/Local/Sort/ContactSort.php @@ -17,7 +17,6 @@ class ContactSort extends SortBase { 'uid' => true, 'sid' => true, 'cid' => true, - 'uid' => true, 'uuid' => true, 'label' => true, ]; diff --git a/lib/Store/Local/Sort/EventSort.php b/lib/Store/Local/Sort/EventSort.php index ac73313..8a76ef5 100644 --- a/lib/Store/Local/Sort/EventSort.php +++ b/lib/Store/Local/Sort/EventSort.php @@ -17,7 +17,6 @@ class EventSort extends SortBase { 'uid' => true, 'sid' => true, 'cid' => true, - 'uid' => true, 'uuid' => true, 'startson' => true, 'endson' => true, diff --git a/lib/Utile/Sanitizer.php b/lib/Utile/Sanitizer.php index cb76641..43a3fcc 100644 --- a/lib/Utile/Sanitizer.php +++ b/lib/Utile/Sanitizer.php @@ -43,7 +43,7 @@ public static function folder(string $name, bool $lsc = false, bool $tsc = false $name = rtrim($name); } // return result - return $name; + return $name ?? ''; } /** diff --git a/lib/Utile/UUID.php b/lib/Utile/UUID.php index 46b5b57..ac033aa 100644 --- a/lib/Utile/UUID.php +++ b/lib/Utile/UUID.php @@ -30,7 +30,7 @@ class UUID { * @param string $namespace another valid UUID * @param string $name random value * - * @return string a version 3 UUID + * @return string|false a version 3 UUID, or false if the namespace is invalid */ public static function v3($namespace, $name) { if (!self::is_valid($namespace)) { @@ -111,7 +111,7 @@ public static function v4() { * @param string $namespace another valid UUID * @param string $name random value * - * @return string a version 5 UUID + * @return string|false a version 5 UUID, or false if the namespace is invalid */ public static function v5($namespace, $name) { if (!self::is_valid($namespace)) { diff --git a/psalm.xml b/psalm.xml new file mode 100644 index 0000000..5ce72ae --- /dev/null +++ b/psalm.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/psalm-baseline.xml b/tests/psalm-baseline.xml new file mode 100644 index 0000000..92b1cee --- /dev/null +++ b/tests/psalm-baseline.xml @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +