diff --git a/.github/workflows/psalm.yml b/.github/workflows/psalm.yml new file mode 100644 index 00000000..9934b3e6 --- /dev/null +++ b/.github/workflows/psalm.yml @@ -0,0 +1,56 @@ +# 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 + +name: Psalm static analysis + +on: + pull_request: + paths: + - .github/workflows/psalm.yml + - appinfo/** + - composer.* + - lib/** + - templates/** + - tests/** + push: + branches: + - main + - stable* + - test + paths: + - .github/workflows/psalm.yml + - appinfo/** + - composer.* + - lib/** + - templates/** + - tests/** + +concurrency: + group: psalm-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + static-analysis: + runs-on: ubuntu-latest + + name: Psalm check + steps: + - name: Checkout + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + + - name: Set up php + uses: shivammathur/setup-php@c5fc0d8281aba02c7fda07d3a70cc5371548067d # v2 + with: + php-version: 8.2 + coverage: none + ini-file: development + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Install dependencies + run: composer i + + - name: Run coding standards check + run: composer run psalm diff --git a/appinfo/info.xml b/appinfo/info.xml index bdff9d0c..f56b39d0 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -37,7 +37,7 @@ include text processing providers to: 1.0.3 agpl Julien Veyssier - TPAssistant + TpAssistant https://github.com/nextcloud/assistant @@ -48,17 +48,17 @@ include text processing providers to: https://github.com/nextcloud/assistant/raw/main/img/screenshot2.jpg https://github.com/nextcloud/assistant/raw/main/img/screenshot3.jpg - OCA\TPAssistant\Cron\CleanupImageGenerations + OCA\TpAssistant\Cron\CleanupImageGenerations - OCA\TPAssistant\Command\CleanupImageGenerations + OCA\TpAssistant\Command\CleanupImageGenerations - OCA\TPAssistant\Settings\Admin - OCA\TPAssistant\Settings\Personal - OCA\TPAssistant\Settings\PersonalSection + OCA\TpAssistant\Settings\Admin + OCA\TpAssistant\Settings\Personal + OCA\TpAssistant\Settings\PersonalSection diff --git a/composer.json b/composer.json index cb19da3d..d602b616 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,7 @@ "lint": "find . -name \\*.php -not -path './vendor/*' -print0 | xargs -0 -n1 php -l", "cs:check": "php-cs-fixer fix --dry-run --diff", "cs:fix": "php-cs-fixer fix", - "psalm": "psalm.phar", + "psalm": "psalm.phar --no-cache", "test:unit": "phpunit --config tests/phpunit.xml" }, "require-dev": { diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 65a9c075..c641d857 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -1,16 +1,16 @@ // SPDX-License-Identifier: AGPL-3.0-or-later -namespace OCA\TPAssistant\Command; +namespace OCA\TpAssistant\Command; use Exception; -use OCA\TPAssistant\AppInfo\Application; -use OCA\TPAssistant\Service\Text2Image\CleanUpService; +use OC\Core\Command\Base; +use OCA\TpAssistant\AppInfo\Application; +use OCA\TpAssistant\Service\Text2Image\CleanUpService; use OCP\IConfig; -use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -class CleanupImageGenerations extends Command { +class CleanupImageGenerations extends Base { public function __construct( private CleanUpService $cleanUpService, private IConfig $config diff --git a/lib/Controller/AssistantController.php b/lib/Controller/AssistantController.php index 31553667..4162667d 100644 --- a/lib/Controller/AssistantController.php +++ b/lib/Controller/AssistantController.php @@ -1,9 +1,9 @@ // SPDX-License-Identifier: AGPL-3.0-or-later -namespace OCA\TPAssistant\Controller; +namespace OCA\TpAssistant\Controller; use Exception; -use OCA\TPAssistant\Service\FreePrompt\FreePromptService; +use OCA\TpAssistant\Service\FreePrompt\FreePromptService; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\NoAdminRequired; diff --git a/lib/Controller/Text2ImageController.php b/lib/Controller/Text2ImageController.php index f1954c46..1f49f626 100644 --- a/lib/Controller/Text2ImageController.php +++ b/lib/Controller/Text2ImageController.php @@ -3,11 +3,11 @@ // SPDX-FileCopyrightText: Sami Finnilä // SPDX-License-Identifier: AGPL-3.0-or-later -namespace OCA\TPAssistant\Controller; +namespace OCA\TpAssistant\Controller; use Exception; -use OCA\TPAssistant\AppInfo\Application; -use OCA\TPAssistant\Service\Text2Image\Text2ImageHelperService; +use OCA\TpAssistant\AppInfo\Application; +use OCA\TpAssistant\Service\Text2Image\Text2ImageHelperService; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\AnonRateLimit; @@ -83,8 +83,8 @@ public function getImage(string $imageGenId, int $fileNameId): DataDisplayRespon try { $result = $this->text2ImageHelperService->getImage($imageGenId, $fileNameId); } catch (Exception $e) { - $response = new DataResponse(['error' => $e->getMessage()], $e->getCode()); - if ($e->getCode() === Http::STATUS_BAD_REQUEST | Http::STATUS_UNAUTHORIZED) { + $response = new DataResponse(['error' => $e->getMessage()], (int) $e->getCode()); + if ($e->getCode() === Http::STATUS_BAD_REQUEST || $e->getCode() === Http::STATUS_UNAUTHORIZED) { // Throttle brute force attempts $response->throttle(['action' => 'imageGenId']); } @@ -114,8 +114,8 @@ public function getGenerationInfo(string $imageGenId): DataResponse { try { $result = $this->text2ImageHelperService->getGenerationInfo($imageGenId, true); } catch (Exception $e) { - $response = new DataResponse(['error' => $e->getMessage()], $e->getCode()); - if ($e->getCode() === Http::STATUS_BAD_REQUEST | Http::STATUS_UNAUTHORIZED) { + $response = new DataResponse(['error' => $e->getMessage()], (int) $e->getCode()); + if ($e->getCode() === Http::STATUS_BAD_REQUEST || $e->getCode() === Http::STATUS_UNAUTHORIZED) { // Throttle brute force attempts $response->throttle(['action' => 'imageGenId']); } @@ -140,8 +140,8 @@ public function setVisibilityOfImageFiles(string $imageGenId, array $fileVisStat try { $this->text2ImageHelperService->setVisibilityOfImageFiles($imageGenId, $fileVisStatusArray); } catch (Exception $e) { - $response = new DataResponse(['error' => $e->getMessage()], $e->getCode()); - if($e->getCode() === Http::STATUS_BAD_REQUEST | Http::STATUS_UNAUTHORIZED) { + $response = new DataResponse(['error' => $e->getMessage()], (int) $e->getCode()); + if($e->getCode() === Http::STATUS_BAD_REQUEST || $e->getCode() === Http::STATUS_UNAUTHORIZED) { // Throttle brute force attempts $response->throttle(['action' => 'imageGenId']); } diff --git a/lib/Cron/CleanupImageGenerations.php b/lib/Cron/CleanupImageGenerations.php index ec15d76d..600b2465 100644 --- a/lib/Cron/CleanupImageGenerations.php +++ b/lib/Cron/CleanupImageGenerations.php @@ -4,11 +4,11 @@ // SPDX-FileCopyrightText: Sami Finnilä // SPDX-License-Identifier: AGPL-3.0-or-later -namespace OCA\TPAssistant\Cron; +namespace OCA\TpAssistant\Cron; use Exception; -use OCA\TPAssistant\Db\Text2Image\ImageGenerationMapper; -use OCA\TPAssistant\Service\Text2Image\CleanUpService; +use OCA\TpAssistant\Db\Text2Image\ImageGenerationMapper; +use OCA\TpAssistant\Service\Text2Image\CleanUpService; use OCP\AppFramework\Utility\ITimeFactory; use OCP\BackgroundJob\TimedJob; use Psr\Log\LoggerInterface; diff --git a/lib/Db/FreePrompt/Prompt.php b/lib/Db/FreePrompt/Prompt.php index 360b5733..af2a6cdb 100644 --- a/lib/Db/FreePrompt/Prompt.php +++ b/lib/Db/FreePrompt/Prompt.php @@ -4,7 +4,7 @@ // SPDX-FileCopyrightText: Sami Finnilä // SPDX-License-Identifier: AGPL-3.0-or-later -namespace OCA\TPAssistant\Db\FreePrompt; +namespace OCA\TpAssistant\Db\FreePrompt; use OCP\AppFramework\Db\Entity; diff --git a/lib/Db/FreePrompt/PromptMapper.php b/lib/Db/FreePrompt/PromptMapper.php index 73aae1d6..c9a02fd3 100644 --- a/lib/Db/FreePrompt/PromptMapper.php +++ b/lib/Db/FreePrompt/PromptMapper.php @@ -5,10 +5,10 @@ declare(strict_types=1); -namespace OCA\TPAssistant\Db\FreePrompt; +namespace OCA\TpAssistant\Db\FreePrompt; use DateTime; -use OCA\TPAssistant\AppInfo\Application; +use OCA\TpAssistant\AppInfo\Application; use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Db\MultipleObjectsReturnedException; use OCP\AppFramework\Db\QBMapper; @@ -17,7 +17,7 @@ use OCP\IDBConnection; /** - * @implements QBMapper + * @extends QBMapper */ class PromptMapper extends QBMapper { public function __construct(IDBConnection $db) { @@ -124,7 +124,7 @@ public function createPrompt(string $userId, string $value, ?int $timestamp = nu if ($timestamp === null) { $timestamp = (new DateTime())->getTimestamp(); } - + try { $prompt = $this->getPromptOfUserByValue($userId, $value); $prompt->setTimestamp($timestamp); diff --git a/lib/Db/Text2Image/ImageFileName.php b/lib/Db/Text2Image/ImageFileName.php index 8ad10c11..e581524d 100644 --- a/lib/Db/Text2Image/ImageFileName.php +++ b/lib/Db/Text2Image/ImageFileName.php @@ -4,7 +4,7 @@ // SPDX-FileCopyrightText: Sami Finnilä // SPDX-License-Identifier: AGPL-3.0-or-later -namespace OCA\TPAssistant\Db\Text2Image; +namespace OCA\TpAssistant\Db\Text2Image; use OCP\AppFramework\Db\Entity; diff --git a/lib/Db/Text2Image/ImageFileNameMapper.php b/lib/Db/Text2Image/ImageFileNameMapper.php index acf670a0..89ab1bd6 100644 --- a/lib/Db/Text2Image/ImageFileNameMapper.php +++ b/lib/Db/Text2Image/ImageFileNameMapper.php @@ -4,9 +4,10 @@ // SPDX-FileCopyrightText: Sami Finnilä // SPDX-License-Identifier: AGPL-3.0-or-later -namespace OCA\TPAssistant\Db\Text2Image; +namespace OCA\TpAssistant\Db\Text2Image; use OCP\AppFramework\Db\DoesNotExistException; +use OCP\AppFramework\Db\Entity; use OCP\AppFramework\Db\MultipleObjectsReturnedException; use OCP\AppFramework\Db\QBMapper; use OCP\DB\Exception; @@ -14,7 +15,7 @@ use OCP\IDBConnection; /** - * @implements QBMapper + * @extends QBMapper */ class ImageFileNameMapper extends QBMapper { public function __construct(IDBConnection $db) { @@ -81,11 +82,9 @@ public function setFileNameHidden(int $fileNameId, bool $hidden = true): int { /** * @param int $generationId * @param int $fileNameId - * @return ImageFileName|null - * + * @return ImageFileName|Entity|null */ - - public function getImageFileNameOfGenerationId(int $generationId, int $fileNameId): ImageFileName | null { + public function getImageFileNameOfGenerationId(int $generationId, int $fileNameId): ImageFileName|Entity|null { $qb = $this->db->getQueryBuilder(); $qb->select('file_name') @@ -106,21 +105,16 @@ public function getImageFileNameOfGenerationId(int $generationId, int $fileNameI /** * @param int $generationId * @param string $fileName - * @param string $prompt - * @return ImageFileName + * @return ImageFileName|Entity * @throws Exception */ - public function createImageFileName(int $generationId, string $fileName): ImageFileName { + public function createImageFileName(int $generationId, string $fileName): ImageFileName|Entity { $imageFile = new ImageFileName(); $imageFile->setGenerationId($generationId); $imageFile->setFileName($fileName); return $this->insert($imageFile); } - /** - * - */ - /** * @param int $generationId * @return void diff --git a/lib/Db/Text2Image/ImageGeneration.php b/lib/Db/Text2Image/ImageGeneration.php index b3b824b7..59e06707 100644 --- a/lib/Db/Text2Image/ImageGeneration.php +++ b/lib/Db/Text2Image/ImageGeneration.php @@ -4,7 +4,7 @@ // SPDX-FileCopyrightText: Sami Finnilä // SPDX-License-Identifier: AGPL-3.0-or-later -namespace OCA\TPAssistant\Db\Text2Image; +namespace OCA\TpAssistant\Db\Text2Image; use OCP\AppFramework\Db\Entity; diff --git a/lib/Db/Text2Image/ImageGenerationMapper.php b/lib/Db/Text2Image/ImageGenerationMapper.php index 5f030b8d..477a508a 100644 --- a/lib/Db/Text2Image/ImageGenerationMapper.php +++ b/lib/Db/Text2Image/ImageGenerationMapper.php @@ -4,11 +4,12 @@ // SPDX-FileCopyrightText: Sami Finnilä // SPDX-License-Identifier: AGPL-3.0-or-later -namespace OCA\TPAssistant\Db\Text2Image; +namespace OCA\TpAssistant\Db\Text2Image; use DateTime; -use OCA\TPAssistant\AppInfo\Application; +use OCA\TpAssistant\AppInfo\Application; use OCP\AppFramework\Db\DoesNotExistException; +use OCP\AppFramework\Db\Entity; use OCP\AppFramework\Db\MultipleObjectsReturnedException; use OCP\AppFramework\Db\QBMapper; use OCP\DB\Exception; @@ -16,7 +17,7 @@ use OCP\IDBConnection; /** - * @implements QBMapper + * @extends QBMapper */ class ImageGenerationMapper extends QBMapper { public function __construct( @@ -29,13 +30,12 @@ public function __construct( /** * @param string $imageGenId - * @param int $fileNameId - * @return ImageGeneration - * @throws Exception + * @return ImageGeneration|Entity * @throws DoesNotExistException + * @throws Exception * @throws MultipleObjectsReturnedException */ - public function getImageGenerationOfImageGenId(string $imageGenId): ImageGeneration { + public function getImageGenerationOfImageGenId(string $imageGenId): ImageGeneration|Entity { $qb = $this->db->getQueryBuilder(); $qb->select('*') @@ -52,10 +52,10 @@ public function getImageGenerationOfImageGenId(string $imageGenId): ImageGenerat * @param string $prompt * @param string $userId * @param int|null $expCompletionTime - * @return ImageGeneration + * @return ImageGeneration|Entity * @throws Exception */ - public function createImageGeneration(string $imageGenId, string $prompt = '', string $userId = '', ?int $expCompletionTime = null): ImageGeneration { + public function createImageGeneration(string $imageGenId, string $prompt = '', string $userId = '', ?int $expCompletionTime = null): ImageGeneration|Entity { $imageGeneration = new ImageGeneration(); $imageGeneration->setImageGenId($imageGenId); $imageGeneration->setTimestamp((new DateTime())->getTimestamp()); @@ -171,7 +171,7 @@ public function setNotifyReady(string $imageGenId, bool $notifyReady): int { /** * @param int $maxAge - * @return array('deleted_generations' => int, 'file_names' => string[]) + * @return array ('deleted_generations' => int, 'file_names' => string[]) * @throws Exception * @throws \RuntimeException */ diff --git a/lib/Db/Text2Image/Prompt.php b/lib/Db/Text2Image/Prompt.php index 0b6b2275..b1f780ec 100644 --- a/lib/Db/Text2Image/Prompt.php +++ b/lib/Db/Text2Image/Prompt.php @@ -4,7 +4,7 @@ // SPDX-FileCopyrightText: Sami Finnilä // SPDX-License-Identifier: AGPL-3.0-or-later -namespace OCA\TPAssistant\Db\Text2Image; +namespace OCA\TpAssistant\Db\Text2Image; use OCP\AppFramework\Db\Entity; diff --git a/lib/Db/Text2Image/PromptMapper.php b/lib/Db/Text2Image/PromptMapper.php index abb3afa9..141bee99 100644 --- a/lib/Db/Text2Image/PromptMapper.php +++ b/lib/Db/Text2Image/PromptMapper.php @@ -6,10 +6,10 @@ declare(strict_types=1); -namespace OCA\TPAssistant\Db\Text2Image; +namespace OCA\TpAssistant\Db\Text2Image; use DateTime; -use OCA\TPAssistant\AppInfo\Application; +use OCA\TpAssistant\AppInfo\Application; use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Db\Entity; use OCP\AppFramework\Db\MultipleObjectsReturnedException; @@ -19,7 +19,7 @@ use OCP\IDBConnection; /** - * @implements QBMapper + * @extends QBMapper */ class PromptMapper extends QBMapper { public function __construct(IDBConnection $db) { @@ -28,12 +28,12 @@ public function __construct(IDBConnection $db) { /** * @param int $id - * @return Prompt | Entity + * @return Prompt|Entity * @throws DoesNotExistException * @throws Exception * @throws MultipleObjectsReturnedException */ - public function getPrompt(int $id): Prompt | Entity { + public function getPrompt(int $id): Prompt|Entity { $qb = $this->db->getQueryBuilder(); $qb->select('*') @@ -48,12 +48,12 @@ public function getPrompt(int $id): Prompt | Entity { /** * @param int $id * @param string $userId - * @return Prompt + * @return Prompt|Entity * @throws DoesNotExistException * @throws Exception * @throws MultipleObjectsReturnedException */ - public function getPromptOfUser(int $id, string $userId): Prompt { + public function getPromptOfUser(int $id, string $userId): Prompt|Entity { $qb = $this->db->getQueryBuilder(); $qb->select('*') @@ -71,12 +71,12 @@ public function getPromptOfUser(int $id, string $userId): Prompt { /** * @param string $userId * @param string $value - * @return Prompt + * @return Prompt|Entity * @throws DoesNotExistException * @throws Exception * @throws MultipleObjectsReturnedException */ - public function getPromptOfUserByValue(string $userId, string $value): Prompt { + public function getPromptOfUserByValue(string $userId, string $value): Prompt|Entity { $qb = $this->db->getQueryBuilder(); $qb->select('*') @@ -115,11 +115,12 @@ public function getPromptsOfUser(string $userId): array { * @param string $userId * @param string $value * @param int|null $timestamp - * @return Prompt + * @return Prompt|Entity * @throws Exception */ - public function createPrompt(string $userId, string $value, ?int $timestamp = null): Prompt { + public function createPrompt(string $userId, string $value, ?int $timestamp = null): Prompt|Entity { try { + /** @var Prompt $prompt */ $prompt = $this->getPromptOfUserByValue($userId, $value); $ts = (new DateTime())->getTimestamp(); $prompt->setTimestamp($ts); diff --git a/lib/Db/Text2Image/StaleGeneration.php b/lib/Db/Text2Image/StaleGeneration.php index 09e3c6b9..1f0a835d 100644 --- a/lib/Db/Text2Image/StaleGeneration.php +++ b/lib/Db/Text2Image/StaleGeneration.php @@ -4,7 +4,7 @@ // SPDX-FileCopyrightText: Sami Finnilä // SPDX-License-Identifier: AGPL-3.0-or-later -namespace OCA\TPAssistant\Db\Text2Image; +namespace OCA\TpAssistant\Db\Text2Image; use OCP\AppFramework\Db\Entity; diff --git a/lib/Db/Text2Image/StaleGenerationMapper.php b/lib/Db/Text2Image/StaleGenerationMapper.php index 40d426c0..fece0816 100644 --- a/lib/Db/Text2Image/StaleGenerationMapper.php +++ b/lib/Db/Text2Image/StaleGenerationMapper.php @@ -5,9 +5,10 @@ declare(strict_types=1); -namespace OCA\TPAssistant\Db\Text2Image; +namespace OCA\TpAssistant\Db\Text2Image; use OCP\AppFramework\Db\DoesNotExistException; +use OCP\AppFramework\Db\Entity; use OCP\AppFramework\Db\MultipleObjectsReturnedException; use OCP\AppFramework\Db\QBMapper; use OCP\DB\Exception; @@ -16,7 +17,7 @@ use RuntimeException; /** - * @implements QBMapper + * @extends QBMapper */ class StaleGenerationMapper extends QBMapper { public function __construct(IDBConnection $db) { @@ -25,12 +26,12 @@ public function __construct(IDBConnection $db) { /** * @param int $id - * @return StaleGeneration + * @return StaleGeneration|Entity * @throws DoesNotExistException * @throws Exception * @throws MultipleObjectsReturnedException */ - public function getStaleGeneration(int $id): StaleGeneration { + public function getStaleGeneration(int $id): StaleGeneration|Entity { $qb = $this->db->getQueryBuilder(); $qb->select('*') @@ -84,15 +85,13 @@ public function genIdExists(string $imageGenId): bool { /** * @param string $imageGenId - * @return StaleGeneration + * @return StaleGeneration|Entity inserted StaleGeneration * @throws Exception */ - public function createStaleGeneration(string $imageGenId): StaleGeneration { + public function createStaleGeneration(string $imageGenId): StaleGeneration|Entity { $staleGen = new StaleGeneration(); $staleGen->setImageGenId($imageGenId); - $insertedStaleGeneration = $this->insert($staleGen); - - return $insertedStaleGeneration; + return $this->insert($staleGen); } } diff --git a/lib/Event/BeforeAssistantNotificationEvent.php b/lib/Event/BeforeAssistantNotificationEvent.php index 30d91d4b..afa8aed6 100644 --- a/lib/Event/BeforeAssistantNotificationEvent.php +++ b/lib/Event/BeforeAssistantNotificationEvent.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace OCA\TPAssistant\Event; +namespace OCA\TpAssistant\Event; use OCP\EventDispatcher\Event; use OCP\TextProcessing\Task; diff --git a/lib/Listener/BeforeTemplateRenderedListener.php b/lib/Listener/BeforeTemplateRenderedListener.php index 8f430c6c..c2da303d 100644 --- a/lib/Listener/BeforeTemplateRenderedListener.php +++ b/lib/Listener/BeforeTemplateRenderedListener.php @@ -2,9 +2,9 @@ declare(strict_types=1); -namespace OCA\TPAssistant\Listener; +namespace OCA\TpAssistant\Listener; -use OCA\TPAssistant\AppInfo\Application; +use OCA\TpAssistant\AppInfo\Application; use OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent; use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Services\IInitialState; @@ -16,6 +16,9 @@ use OCP\TextProcessing\IManager as ITextProcessingManager; use OCP\Util; +/** + * @template-implements IEventListener + */ class BeforeTemplateRenderedListener implements IEventListener { public function __construct( diff --git a/lib/Listener/FreePrompt/FreePromptReferenceListener.php b/lib/Listener/FreePrompt/FreePromptReferenceListener.php index 1ff9be33..3c80572e 100644 --- a/lib/Listener/FreePrompt/FreePromptReferenceListener.php +++ b/lib/Listener/FreePrompt/FreePromptReferenceListener.php @@ -3,30 +3,23 @@ // SPDX-FileCopyrightText: Sami Finnilä // SPDX-License-Identifier: AGPL-3.0-or-later -namespace OCA\TPAssistant\Listener\FreePrompt; +namespace OCA\TpAssistant\Listener\FreePrompt; -use OCA\TPAssistant\AppInfo\Application; -use OCP\AppFramework\Services\IInitialState; +use OCA\TpAssistant\AppInfo\Application; use OCP\Collaboration\Reference\RenderReferenceEvent; use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventListener; use OCP\IConfig; -use OCP\IGroupManager; use OCP\TextProcessing\IManager; use OCP\Util; -use Psr\Log\LoggerInterface; - /** * @implements IEventListener */ class FreePromptReferenceListener implements IEventListener { public function __construct( private IConfig $config, - private IInitialState $initialState, private ?string $userId, - private LoggerInterface $logger, - private IGroupManager $iGroupManager, private IManager $textProcessingManager, ) { @@ -40,8 +33,8 @@ public function handle(Event $event): void { if ($this->config->getAppValue(Application::APP_ID, 'free_prompt_picker_enabled', '1') === '1' && $this->config->getUserValue($this->userId, Application::APP_ID, 'free_prompt_picker_enabled', '1') === '1') { - - // Double check that atleast one provider is registered + + // Double check that at least one provider is registered if ($this->textProcessingManager->hasProviders()) { Util::addScript(Application::APP_ID, Application::APP_ID . '-textGenerationReference'); } diff --git a/lib/Listener/TaskFailedListener.php b/lib/Listener/TaskFailedListener.php index 657302be..5eb10980 100644 --- a/lib/Listener/TaskFailedListener.php +++ b/lib/Listener/TaskFailedListener.php @@ -1,15 +1,18 @@ + */ class TaskFailedListener implements IEventListener { public function __construct( diff --git a/lib/Listener/TaskSuccessfulListener.php b/lib/Listener/TaskSuccessfulListener.php index ce2a9a7f..ecbe1203 100644 --- a/lib/Listener/TaskSuccessfulListener.php +++ b/lib/Listener/TaskSuccessfulListener.php @@ -1,15 +1,18 @@ + */ class TaskSuccessfulListener implements IEventListener { public function __construct( diff --git a/lib/Listener/Text2Image/Text2ImageReferenceListener.php b/lib/Listener/Text2Image/Text2ImageReferenceListener.php index b99d99d8..acc03807 100644 --- a/lib/Listener/Text2Image/Text2ImageReferenceListener.php +++ b/lib/Listener/Text2Image/Text2ImageReferenceListener.php @@ -3,10 +3,9 @@ // SPDX-FileCopyrightText: Sami Finnilä // SPDX-License-Identifier: AGPL-3.0-or-later -namespace OCA\TPAssistant\Listener\Text2Image; +namespace OCA\TpAssistant\Listener\Text2Image; -use OCA\TPAssistant\AppInfo\Application; -use OCP\AppFramework\Services\IInitialState; +use OCA\TpAssistant\AppInfo\Application; use OCP\Collaboration\Reference\RenderReferenceEvent; use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventListener; @@ -14,10 +13,12 @@ use OCP\TextToImage\IManager; use OCP\Util; +/** + * @template-implements IEventListener + */ class Text2ImageReferenceListener implements IEventListener { public function __construct( private IConfig $config, - private IInitialState $initialState, private ?string $userId, private IManager $manager ) { diff --git a/lib/Listener/Text2Image/Text2ImageResultListener.php b/lib/Listener/Text2Image/Text2ImageResultListener.php index 16cc07ae..b831a433 100644 --- a/lib/Listener/Text2Image/Text2ImageResultListener.php +++ b/lib/Listener/Text2Image/Text2ImageResultListener.php @@ -1,11 +1,12 @@ + */ class Text2ImageResultListener implements IEventListener { - /** - * Constructor - * @param Text2ImageHelperService $text2ImageService - * @param ImageGenerationMapper $imageGenerationMapper - * @param LoggerInterface $logger - * @param AssistantService $assistantService - * @param IURLGenerator $urlGenerator - */ + public function __construct( private Text2ImageHelperService $text2ImageService, private ImageGenerationMapper $imageGenerationMapper, @@ -74,13 +71,15 @@ public function handle(Event $event): void { if ($event instanceof TaskFailedEvent) { $this->logger->warning('Image generation task failed: ' . $imageGenId); $this->imageGenerationMapper->setFailed($imageGenId, true); - + $this->assistantService->sendNotification($event->getTask()); } // Only send the notification if the user enabled them for this task: try { - if($this->imageGenerationMapper->getImageGenerationOfImageGenId($imageGenId)->getNotifyReady()) { + /** @var ImageGeneration $imageGeneration */ + $imageGeneration = $this->imageGenerationMapper->getImageGenerationOfImageGenId($imageGenId); + if ($imageGeneration->getNotifyReady()) { $this->assistantService->sendNotification($event->getTask(), $link); } } catch (\OCP\Db\Exception | DoesNotExistException | MultipleObjectsReturnedException $e) { diff --git a/lib/Migration/Version010003Date20231208083112.php b/lib/Migration/Version010003Date20231208083112.php index 10e5a2e8..d5607525 100644 --- a/lib/Migration/Version010003Date20231208083112.php +++ b/lib/Migration/Version010003Date20231208083112.php @@ -5,7 +5,7 @@ declare(strict_types=1); -namespace OCA\TPAssistant\Migration; +namespace OCA\TpAssistant\Migration; use Closure; use OCP\DB\ISchemaWrapper; diff --git a/lib/Notification/Notifier.php b/lib/Notification/Notifier.php index 1582c523..66f5928f 100644 --- a/lib/Notification/Notifier.php +++ b/lib/Notification/Notifier.php @@ -1,9 +1,9 @@ // SPDX-License-Identifier: AGPL-3.0-or-later -namespace OCA\TPAssistant\Reference; +namespace OCA\TpAssistant\Reference; -use OC\Collaboration\Reference\ReferenceManager; -use OCA\TPAssistant\AppInfo\Application; -use OCA\TPAssistant\Service\FreePrompt\FreePromptService; +use OCA\TpAssistant\AppInfo\Application; use OCP\Collaboration\Reference\ADiscoverableReferenceProvider; use OCP\Collaboration\Reference\IReference; +use OCP\Collaboration\Reference\IReferenceManager; use OCP\IL10N; use OCP\IURLGenerator; @@ -17,8 +16,7 @@ class FreePromptReferenceProvider extends ADiscoverableReferenceProvider { public function __construct( private IL10N $l10n, private IURLGenerator $urlGenerator, - private ReferenceManager $referenceManager, - private FreePromptService $freePromptService, + private IReferenceManager $referenceManager, private ?string $userId ) { } diff --git a/lib/Reference/Text2ImageReferenceProvider.php b/lib/Reference/Text2ImageReferenceProvider.php index 5be32355..12353be5 100644 --- a/lib/Reference/Text2ImageReferenceProvider.php +++ b/lib/Reference/Text2ImageReferenceProvider.php @@ -3,15 +3,15 @@ // SPDX-FileCopyrightText: Sami Finnilä // SPDX-License-Identifier: AGPL-3.0-or-later -namespace OCA\TPAssistant\Reference; +namespace OCA\TpAssistant\Reference; use Exception; -use OC\Collaboration\Reference\ReferenceManager; -use OCA\TPAssistant\AppInfo\Application; -use OCA\TPAssistant\Db\Text2Image\ImageGenerationMapper; -use OCA\TPAssistant\Service\Text2Image\Text2ImageHelperService; +use OCA\TpAssistant\AppInfo\Application; +use OCA\TpAssistant\Db\Text2Image\ImageGeneration; +use OCA\TpAssistant\Db\Text2Image\ImageGenerationMapper; use OCP\Collaboration\Reference\ADiscoverableReferenceProvider; use OCP\Collaboration\Reference\IReference; +use OCP\Collaboration\Reference\IReferenceManager; use OCP\Collaboration\Reference\Reference; use OCP\IL10N; use OCP\IURLGenerator; @@ -22,8 +22,7 @@ class Text2ImageReferenceProvider extends ADiscoverableReferenceProvider { public function __construct( private IL10N $l10n, private IURLGenerator $urlGenerator, - private ReferenceManager $referenceManager, - private Text2ImageHelperService $text2ImageHelperService, + private IReferenceManager $referenceManager, private ImageGenerationMapper $imageGenerationMapper, private ?string $userId ) { @@ -75,6 +74,7 @@ public function resolveReference(string $referenceText): ?IReference { } try { + /** @var ImageGeneration $imageGeneration */ $imageGeneration = $this->imageGenerationMapper->getImageGenerationOfImageGenId($imageGenId); } catch (Exception $e) { $imageGeneration = null; diff --git a/lib/Service/AssistantService.php b/lib/Service/AssistantService.php index 3ef5aae3..dc84d523 100644 --- a/lib/Service/AssistantService.php +++ b/lib/Service/AssistantService.php @@ -1,9 +1,9 @@ setApp(Application::APP_ID) ->setUser($task->getUserId()) ->setDateTime(new DateTime()) - ->setObject($objectType, $task->getId()) + ->setObject($objectType, (string) ($task->getId() ?? 0)) ->setSubject($subject, $params); $manager->notify($notification); diff --git a/lib/Service/FreePrompt/FreePromptService.php b/lib/Service/FreePrompt/FreePromptService.php index dce67d3a..fec5bdae 100644 --- a/lib/Service/FreePrompt/FreePromptService.php +++ b/lib/Service/FreePrompt/FreePromptService.php @@ -3,11 +3,11 @@ // SPDX-FileCopyrightText: Sami Finnilä // SPDX-License-Identifier: AGPL-3.0-or-later -namespace OCA\TPAssistant\Service\FreePrompt; +namespace OCA\TpAssistant\Service\FreePrompt; use Exception; -use OCA\TPAssistant\AppInfo\Application; -use OCA\TPAssistant\Db\FreePrompt\PromptMapper; +use OCA\TpAssistant\AppInfo\Application; +use OCA\TpAssistant\Db\FreePrompt\PromptMapper; use OCP\AppFramework\Http; use OCP\DB\Exception as DBException; use OCP\IConfig; diff --git a/lib/Service/Text2Image/CleanUpService.php b/lib/Service/Text2Image/CleanUpService.php index 6c47c887..c54b1d63 100644 --- a/lib/Service/Text2Image/CleanUpService.php +++ b/lib/Service/Text2Image/CleanUpService.php @@ -3,11 +3,11 @@ // SPDX-FileCopyrightText: Sami Finnilä // SPDX-License-Identifier: AGPL-3.0-or-later -namespace OCA\TPAssistant\Service\Text2Image; +namespace OCA\TpAssistant\Service\Text2Image; use Exception; -use OCA\TPAssistant\AppInfo\Application; -use OCA\TPAssistant\Db\Text2Image\ImageGenerationMapper; +use OCA\TpAssistant\AppInfo\Application; +use OCA\TpAssistant\Db\Text2Image\ImageGenerationMapper; use OCP\Files\IAppData; use OCP\Files\NotFoundException; use OCP\Files\NotPermittedException; @@ -31,7 +31,7 @@ public function __construct( /** * @param int|null $maxAge - * @return array('deleted_files' => int, 'file_deletion_errors' => int, 'deleted_generations' => int) + * @return array ('deleted_files' => int, 'file_deletion_errors' => int, 'deleted_generations' => int) * @throws Exception */ public function cleanupGenerationsAndFiles(?int $maxAge = null): array { diff --git a/lib/Service/Text2Image/Text2ImageHelperService.php b/lib/Service/Text2Image/Text2ImageHelperService.php index f1370241..17118227 100644 --- a/lib/Service/Text2Image/Text2ImageHelperService.php +++ b/lib/Service/Text2Image/Text2ImageHelperService.php @@ -3,18 +3,20 @@ // SPDX-FileCopyrightText: Sami Finnilä // SPDX-License-Identifier: AGPL-3.0-or-later -namespace OCA\TPAssistant\Service\Text2Image; +namespace OCA\TpAssistant\Service\Text2Image; use DateTime; use Exception as BaseException; use GdImage; -use OCA\TPAssistant\AppInfo\Application; -use OCA\TPAssistant\Db\Text2Image\ImageFileNameMapper; -use OCA\TPAssistant\Db\Text2Image\ImageGenerationMapper; -use OCA\TPAssistant\Db\Text2Image\PromptMapper; -use OCA\TPAssistant\Db\Text2Image\StaleGenerationMapper; -use OCA\TPAssistant\Service\AssistantService; +use OCA\TpAssistant\AppInfo\Application; +use OCA\TpAssistant\Db\Text2Image\ImageFileName; +use OCA\TpAssistant\Db\Text2Image\ImageFileNameMapper; +use OCA\TpAssistant\Db\Text2Image\ImageGeneration; +use OCA\TpAssistant\Db\Text2Image\ImageGenerationMapper; +use OCA\TpAssistant\Db\Text2Image\PromptMapper; +use OCA\TpAssistant\Db\Text2Image\StaleGenerationMapper; +use OCA\TpAssistant\Service\AssistantService; use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Db\MultipleObjectsReturnedException; @@ -24,37 +26,22 @@ use OCP\Files\NotFoundException; use OCP\Files\NotPermittedException; use OCP\Files\SimpleFS\ISimpleFolder; -use OCP\IConfig; use OCP\IImage; use OCP\IL10N; use OCP\IURLGenerator; +use OCP\PreConditionNotMetException; +use OCP\TextToImage\Exception\TaskFailureException; use OCP\TextToImage\IManager; use OCP\TextToImage\Task; use Psr\Log\LoggerInterface; +use Random\RandomException; use RuntimeException; class Text2ImageHelperService { - /** - * @var ISimpleFolder|null - */ + private ?ISimpleFolder $imageDataFolder = null; - /** - * @param IConfig $config - * @param LoggerInterface $logger - * @param IManager $textToImageManager - * @param string|null $userId - * @param PromptMapper $promptMapper - * @param ImageGenerationMapper $imageGenerationMapper - * @param ImageFileNameMapper $imageFileNameMapper - * @param StaleGenerationMapper $staleGenerationMapper - * @param IAppData $appData - * @param IURLGenerator $urlGenerator - * @param IL10N $l10n - * @param AssistantService $assistantService - */ public function __construct( - private IConfig $config, private LoggerInterface $logger, private IManager $textToImageManager, private ?string $userId, @@ -74,10 +61,12 @@ public function __construct( * * @param string $prompt * @param int $nResults - * @param bool $storePrompt + * @param bool $displayPrompt * @return array - * @throws \Exception - * @throws \OCP\TextToImage\Exception\TaskFailureException; + * @throws Exception + * @throws PreConditionNotMetException + * @throws TaskFailureException ; + * @throws RandomException */ public function processPrompt(string $prompt, int $nResults, bool $displayPrompt): array { if (!$this->textToImageManager->hasProviders()) { @@ -95,7 +84,7 @@ public function processPrompt(string $prompt, int $nResults, bool $displayPrompt $promptTask = new Task($prompt, Application::APP_ID, $nResults, $this->userId, $imageGenId); $this->textToImageManager->runOrScheduleTask($promptTask); - + $taskExecuted = false; /** @var IImage[]|null $images */ @@ -260,7 +249,7 @@ public function notifyUser(string $imageGenId): void { $this->logger->debug('Task for the given generation id does not exist or could not be retrieved: ' . $e->getMessage(), ['app' => Application::APP_ID]); return; } - + // Generate the link: $link = $this->urlGenerator->linkToRouteAbsolute( Application::APP_ID . '.Text2Image.showGenerationPage', @@ -295,7 +284,7 @@ public function getImageDataFolder(): ISimpleFolder { } catch (NotPermittedException | RuntimeException $e) { $this->logger->debug('Image data folder could not be created: ' . $e->getMessage(), ['app' => Application::APP_ID]); - throw new Exception('Image data folder could not be created: ' . $e->getMessage()); + throw new \Exception('Image data folder could not be created: ' . $e->getMessage()); } } } @@ -313,6 +302,7 @@ public function getImageDataFolder(): ISimpleFolder { public function getGenerationInfo(string $imageGenId, bool $updateTimestamp = true): array { // Check whether the task has completed: try { + /** @var ImageGeneration $imageGeneration */ $imageGeneration = $this->imageGenerationMapper->getImageGenerationOfImageGenId($imageGenId); } catch (DoesNotExistException $e) { try { @@ -380,12 +370,13 @@ public function getGenerationInfo(string $imageGenId, bool $updateTimestamp = tr * Get image based on imageFileNameId (imageGenId is used to prevent guessing image ids) * @param string $imageGenId * @param int $imageFileNameId - * @return array('image' => string, 'content-type' => string) + * @return array ('image' => string, 'content-type' => string) * @throws BaseException */ public function getImage(string $imageGenId, int $imageFileNameId): ?array { try { $generationId = $this->imageGenerationMapper->getImageGenerationOfImageGenId($imageGenId)->getId(); + /** @var ImageFileName $imageFileName */ $imageFileName = $this->imageFileNameMapper->getImageFileNameOfGenerationId($generationId, $imageFileNameId); } catch (Exception | DoesNotExistException | MultipleObjectsReturnedException $e) { $this->logger->debug('Image request error : ' . $e->getMessage(), ['app' => Application::APP_ID]); @@ -425,6 +416,7 @@ public function getImage(string $imageGenId, int $imageFileNameId): ?array { */ public function cancelGeneration(string $imageGenId): void { try { + /** @var ImageGeneration $imageGeneration */ $imageGeneration = $this->imageGenerationMapper->getImageGenerationOfImageGenId($imageGenId); } catch (Exception | DoesNotExistException | MultipleObjectsReturnedException $e) { $this->logger->warning('Image generation being deleted not in db: ' . $e->getMessage(), ['app' => Application::APP_ID]); @@ -502,6 +494,7 @@ public function cancelGeneration(string $imageGenId): void { */ public function setVisibilityOfImageFiles(string $imageGenId, array $fileVisSatusArray): void { try { + /** @var ImageGeneration $imageGeneration */ $imageGeneration = $this->imageGenerationMapper->getImageGenerationOfImageGenId($imageGenId); } catch (DoesNotExistException $e) { $this->logger->debug('Image request error : ' . $e->getMessage()); @@ -532,6 +525,7 @@ public function setVisibilityOfImageFiles(string $imageGenId, array $fileVisSatu */ public function notifyWhenReady(string $imageGenId): void { try { + /** @var ImageGeneration $imageGeneration */ $imageGeneration = $this->imageGenerationMapper->getImageGenerationOfImageGenId($imageGenId); } catch (DoesNotExistException $e) { $this->logger->debug('Image request error : ' . $e->getMessage()); diff --git a/lib/Settings/Admin.php b/lib/Settings/Admin.php index 5925c63a..0279d50d 100644 --- a/lib/Settings/Admin.php +++ b/lib/Settings/Admin.php @@ -1,8 +1,8 @@ config->getAppValue(Application::APP_ID, 'assistant_enabled', '1') === '1'; $textToImagePickerAvailable = $this->textToImageManager->hasProviders(); $textToImagePickerEnabled = $this->config->getAppValue(Application::APP_ID, 'text_to_image_picker_enabled', '1') === '1'; - $maxImageGenerationIdleTime = $this->config->getAppValue(Application::APP_ID, 'max_image_generation_idle_time', Application::DEFAULT_MAX_IMAGE_GENERATION_IDLE_TIME); + $maxImageGenerationIdleTime = (int) $this->config->getAppValue(Application::APP_ID, 'max_image_generation_idle_time', (string) Application::DEFAULT_MAX_IMAGE_GENERATION_IDLE_TIME); $freePromptPickerEnabled = $this->config->getAppValue(Application::APP_ID, 'free_prompt_picker_enabled', '1') === '1'; $adminConfig = [ diff --git a/lib/Settings/Personal.php b/lib/Settings/Personal.php index 2207bf04..1e8cf27f 100644 --- a/lib/Settings/Personal.php +++ b/lib/Settings/Personal.php @@ -1,8 +1,8 @@ urlGenerator->imagePath('settings', 'ai.svg'); } diff --git a/psalm.xml b/psalm.xml new file mode 100644 index 00000000..ad581540 --- /dev/null +++ b/psalm.xml @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assistant.js b/src/assistant.js index ba68bcf3..7b4b0b21 100644 --- a/src/assistant.js +++ b/src/assistant.js @@ -7,7 +7,7 @@ __webpack_public_path__ = linkTo('assistant', 'js/') // eslint-disable-line /** * Creates an assistant modal and return a promise which provides the result * - * OCA.TPAssistant.openAssistantForm({ + * OCA.TpAssistant.openAssistantForm({ * appId: 'my_app_id', * identifier: 'my task identifier', * taskType: 'OCP\\TextProcessing\\FreePromptTaskType', diff --git a/src/main.js b/src/main.js index ccc03ddf..44f8b551 100644 --- a/src/main.js +++ b/src/main.js @@ -3,16 +3,16 @@ import { subscribe } from '@nextcloud/event-bus' import { loadState } from '@nextcloud/initial-state' /** - * - Expose OCA.TPAssistant.openTextProcessingModal to let apps use the assistant + * - Expose OCA.TpAssistant.openTextProcessingModal to let apps use the assistant * - Add a header right menu entry * - Listen to notification event */ function init() { - if (!OCA.TPAssistant) { + if (!OCA.TpAssistant) { /** * @namespace */ - OCA.TPAssistant = { + OCA.TpAssistant = { openAssistantForm, openAssistantResult, } diff --git a/templates/adminSettings.php b/templates/adminSettings.php index bc61638d..7bd7b0d9 100644 --- a/templates/adminSettings.php +++ b/templates/adminSettings.php @@ -1,5 +1,5 @@ diff --git a/templates/imageGenerationPage.php b/templates/imageGenerationPage.php index 70f5340c..70392b4b 100644 --- a/templates/imageGenerationPage.php +++ b/templates/imageGenerationPage.php @@ -1,9 +1,9 @@ -
\ No newline at end of file +
diff --git a/templates/personalSettings.php b/templates/personalSettings.php index 11a15da1..900212d2 100644 --- a/templates/personalSettings.php +++ b/templates/personalSettings.php @@ -1,5 +1,5 @@ diff --git a/templates/taskResultPage.php b/templates/taskResultPage.php index e64b076a..c155548f 100644 --- a/templates/taskResultPage.php +++ b/templates/taskResultPage.php @@ -1,4 +1,4 @@ get(IAppManager::class)->loadApp(Application::APP_ID); diff --git a/tests/psalm-baseline.xml b/tests/psalm-baseline.xml new file mode 100644 index 00000000..5a9a7d82 --- /dev/null +++ b/tests/psalm-baseline.xml @@ -0,0 +1,3 @@ + + + diff --git a/tests/stubs/oc_core_command_base.php b/tests/stubs/oc_core_command_base.php new file mode 100644 index 00000000..bbae1a65 --- /dev/null +++ b/tests/stubs/oc_core_command_base.php @@ -0,0 +1,63 @@ +