Compare commits
45 Commits
dependabot
...
v1.16.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c3df4b112f | ||
|
|
703b6d3062 | ||
|
|
4bb06aa7f5 | ||
|
|
7e995ab110 | ||
|
|
a2046e9a2e | ||
|
|
0262b9ab76 | ||
|
|
b999366fb4 | ||
|
|
9921c5446c | ||
|
|
4c6e9b086a | ||
|
|
ad9c1eb9af | ||
|
|
da0f407121 | ||
|
|
5d59047cbd | ||
|
|
c3c19bcc09 | ||
|
|
c078e3c241 | ||
|
|
95cc40cc38 | ||
|
|
649f995c6b | ||
|
|
9ba7652212 | ||
|
|
4eea72af13 | ||
|
|
b06ac63dbd | ||
|
|
1ccfb6a13a | ||
|
|
86a4d5b2c8 | ||
|
|
3bc7d9dccf | ||
|
|
2a82bc6a63 | ||
|
|
af03e841b1 | ||
|
|
b01c545fd0 | ||
|
|
a0ee1684b1 | ||
|
|
b35279e801 | ||
|
|
a2c03cebb5 | ||
|
|
b391fa9edc | ||
|
|
824540bf98 | ||
|
|
22b8dbec80 | ||
|
|
b36bd37dd6 | ||
|
|
351b4f4165 | ||
|
|
7fb7558d9e | ||
|
|
be9a6f29c6 | ||
|
|
a0bc896123 | ||
|
|
f06e391e36 | ||
|
|
ce0e6a4acc | ||
|
|
997249fc7a | ||
|
|
e48e0aa7ce | ||
|
|
961053230d | ||
|
|
16f0fa8c0c | ||
|
|
daf6aeb650 | ||
|
|
6861730a61 | ||
|
|
839d789f65 |
17
.github/dependabot.yml
vendored
17
.github/dependabot.yml
vendored
@@ -13,23 +13,6 @@ updates:
|
||||
- juliushaertl
|
||||
- luka-nextcloud
|
||||
|
||||
- package-ecosystem: npm
|
||||
target-branch: stable32
|
||||
versioning-strategy: lockfile-only
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: saturday
|
||||
time: "03:15"
|
||||
timezone: Europe/Paris
|
||||
ignore:
|
||||
- dependency-name: "*"
|
||||
update-types: ["version-update:semver-major"]
|
||||
open-pull-requests-limit: 30
|
||||
labels:
|
||||
- 3. to review
|
||||
- dependencies
|
||||
|
||||
- package-ecosystem: npm
|
||||
target-branch: stable31
|
||||
versioning-strategy: lockfile-only
|
||||
|
||||
2
.github/workflows/cypress-e2e.yml
vendored
2
.github/workflows/cypress-e2e.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
||||
node-version: [20.x]
|
||||
# containers: [1, 2, 3]
|
||||
php-versions: [ '8.2' ]
|
||||
server-versions: [ 'master' ]
|
||||
server-versions: [ 'stable32' ]
|
||||
|
||||
env:
|
||||
extensions: mbstring, iconv, fileinfo, intl, sqlite, pdo_sqlite, zip, gd, apcu
|
||||
|
||||
2
.github/workflows/integration.yml
vendored
2
.github/workflows/integration.yml
vendored
@@ -28,7 +28,7 @@ jobs:
|
||||
matrix:
|
||||
php-versions: ['8.1']
|
||||
databases: ['sqlite', 'mysql', 'pgsql']
|
||||
server-versions: ['master']
|
||||
server-versions: ['stable32']
|
||||
|
||||
name: php${{ matrix.php-versions }}-${{ matrix.databases }}-${{ matrix.server-versions }}
|
||||
|
||||
|
||||
2
.github/workflows/npm-audit-fix.yml
vendored
2
.github/workflows/npm-audit-fix.yml
vendored
@@ -24,7 +24,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
branches: ['main', 'master', 'stable32', 'stable31', 'stable30']
|
||||
branches: ['main', 'master', 'stable31', 'stable30']
|
||||
|
||||
name: npm-audit-fix-${{ matrix.branches }}
|
||||
|
||||
|
||||
2
.github/workflows/update-nextcloud-ocp.yml
vendored
2
.github/workflows/update-nextcloud-ocp.yml
vendored
@@ -23,7 +23,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
branches: ['main', 'master', 'stable32', 'stable31', 'stable30']
|
||||
branches: ['main', 'master', 'stable31', 'stable30']
|
||||
|
||||
name: update-nextcloud-ocp-${{ matrix.branches }}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
- Adrian Missy <adrian.missy@onewavestudios.com>
|
||||
- Alexandru Puiu <alexpuiu20@yahoo.com>
|
||||
- Arne Bartelt <arne.bartelt@gmail.com>
|
||||
- Chandi Langecker <git@chandi.it>
|
||||
- Christoph Wurst <christoph@winzerhof-wurst.at>
|
||||
- Gary Kim <gary@garykim.dev>
|
||||
|
||||
18
CHANGELOG.md
18
CHANGELOG.md
@@ -5,6 +5,24 @@
|
||||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## 1.16.0
|
||||
### Added
|
||||
- feat: update default content @luka-nextcloud [#6740](https://github.com/nextcloud/deck/pull/6740)
|
||||
- feat: add board import and export @luka-nextcloud [#6872](https://github.com/nextcloud/deck/pull/6872)
|
||||
- feat: use outline icons @luka-nextcloud [#7114](https://github.com/nextcloud/deck/pull/7114)
|
||||
- Add OCC commands for global calendar feature opt-in and opt-out in Deck @Fledermaus-20 [#7080](https://github.com/nextcloud/deck/pull/7080)
|
||||
- [stable32] Migrate delete icon to Material Symbol outline variant @backportbot [#7211](https://github.com/nextcloud/deck/pull/7211)
|
||||
- Chore(deps): Bump @nextcloud/vue from 8.27.0 to 8.31.0 @luka-nextcloud [#7271](https://github.com/nextcloud/deck/pull/7271)
|
||||
|
||||
### Fixed
|
||||
- CSV export fixes @gidan80 [#6800](https://github.com/nextcloud/deck/pull/6800)
|
||||
- [stable32] fix: Fix colors from due dates and done @backportbot [#7239](https://github.com/nextcloud/deck/pull/7239)
|
||||
- [stable32] fix(darkmode): Fix activity icon colors @backportbot [#7241](https://github.com/nextcloud/deck/pull/7241)
|
||||
- [stable32] fix: redirect to cleaner URL if RewriteBase is enabled @backportbot [#7268](https://github.com/nextcloud/deck/pull/7268)
|
||||
- [stable32] fix: missing push notifications @backportbot [#7270](https://github.com/nextcloud/deck/pull/7270)
|
||||
- [stable32] fix: use text cursor for card title on dashboard @backportbot [#7273](https://github.com/nextcloud/deck/pull/7273)
|
||||
- [stable32] fix: parse arguments to CardService.reorder correctly to int @backportbot [#7276](https://github.com/nextcloud/deck/pull/7276)
|
||||
|
||||
## 1.16.0-beta.1
|
||||
|
||||
### Added
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
- 🚀 Get your project organized
|
||||
|
||||
</description>
|
||||
<version>2.0.0-dev.0</version>
|
||||
<version>1.16.0</version>
|
||||
<licence>agpl</licence>
|
||||
<author>Julius Härtl</author>
|
||||
<namespace>Deck</namespace>
|
||||
@@ -42,7 +42,7 @@
|
||||
<database min-version="9.4">pgsql</database>
|
||||
<database>sqlite</database>
|
||||
<database min-version="8.0">mysql</database>
|
||||
<nextcloud min-version="33" max-version="33"/>
|
||||
<nextcloud min-version="32" max-version="32"/>
|
||||
</dependencies>
|
||||
<background-jobs>
|
||||
<job>OCA\Deck\Cron\DeleteCron</job>
|
||||
|
||||
@@ -9,35 +9,31 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"justinrainbow/json-schema": "^6.0",
|
||||
"bamarni/composer-bin-plugin": "^1.8"
|
||||
"justinrainbow/json-schema": "^6.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"roave/security-advisories": "dev-master",
|
||||
"phpunit/phpunit": "^9",
|
||||
"nextcloud/coding-standard": "^1.1",
|
||||
"nextcloud/ocp": "dev-master"
|
||||
"nextcloud/ocp": "dev-stable32",
|
||||
"psalm/phar": "^5.13"
|
||||
},
|
||||
"config": {
|
||||
"optimize-autoloader": true,
|
||||
"allow-plugins": {
|
||||
"composer/package-versions-deprecated": true,
|
||||
"bamarni/composer-bin-plugin": true
|
||||
"composer/package-versions-deprecated": true
|
||||
},
|
||||
"platform": {
|
||||
"php": "8.1"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"post-install-cmd": [
|
||||
"@composer bin all install --ansi"
|
||||
],
|
||||
"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",
|
||||
"psalm:update-baseline": "psalm --threads=$(nproc) --no-cache --update-baseline",
|
||||
"psalm:fix": "psalm --alter --issues=InvalidReturnType,InvalidNullableReturnType,MismatchingDocblockParamType,MismatchingDocblockReturnType,MissingParamType,InvalidFalsableReturnType",
|
||||
"psalm": "psalm.phar",
|
||||
"psalm:update-baseline": "psalm.phar --update-baseline",
|
||||
"psalm:fix": "psalm.phar --alter --issues=InvalidReturnType,InvalidNullableReturnType,MismatchingDocblockParamType,MismatchingDocblockReturnType,MissingParamType,InvalidFalsableReturnType",
|
||||
"test": [
|
||||
"@test:unit",
|
||||
"@test:integration"
|
||||
|
||||
135
composer.lock
generated
135
composer.lock
generated
@@ -4,77 +4,20 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "263f9ff9e6a13d50ab09bc9f4e06b749",
|
||||
"content-hash": "a802f567c811977afdf6203368ae43e9",
|
||||
"packages": [
|
||||
{
|
||||
"name": "bamarni/composer-bin-plugin",
|
||||
"version": "1.8.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/bamarni/composer-bin-plugin.git",
|
||||
"reference": "92fd7b1e6e9cdae19b0d57369d8ad31a37b6a880"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/bamarni/composer-bin-plugin/zipball/92fd7b1e6e9cdae19b0d57369d8ad31a37b6a880",
|
||||
"reference": "92fd7b1e6e9cdae19b0d57369d8ad31a37b6a880",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"composer-plugin-api": "^2.0",
|
||||
"php": "^7.2.5 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"composer/composer": "^2.0",
|
||||
"ext-json": "*",
|
||||
"phpstan/extension-installer": "^1.1",
|
||||
"phpstan/phpstan": "^1.8",
|
||||
"phpstan/phpstan-phpunit": "^1.1",
|
||||
"phpunit/phpunit": "^8.5 || ^9.5",
|
||||
"symfony/console": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0",
|
||||
"symfony/finder": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0",
|
||||
"symfony/process": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0"
|
||||
},
|
||||
"type": "composer-plugin",
|
||||
"extra": {
|
||||
"class": "Bamarni\\Composer\\Bin\\BamarniBinPlugin"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Bamarni\\Composer\\Bin\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "No conflicts for your bin dependencies",
|
||||
"keywords": [
|
||||
"composer",
|
||||
"conflict",
|
||||
"dependency",
|
||||
"executable",
|
||||
"isolation",
|
||||
"tool"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/bamarni/composer-bin-plugin/issues",
|
||||
"source": "https://github.com/bamarni/composer-bin-plugin/tree/1.8.2"
|
||||
},
|
||||
"time": "2022-10-31T08:38:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "justinrainbow/json-schema",
|
||||
"version": "6.5.2",
|
||||
"version": "6.4.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jsonrainbow/json-schema.git",
|
||||
"reference": "ac0d369c09653cf7af561f6d91a705bc617a87b8"
|
||||
"reference": "ce1fd2d47799bb60668643bc6220f6278a4c1d02"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/ac0d369c09653cf7af561f6d91a705bc617a87b8",
|
||||
"reference": "ac0d369c09653cf7af561f6d91a705bc617a87b8",
|
||||
"url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/ce1fd2d47799bb60668643bc6220f6278a4c1d02",
|
||||
"reference": "ce1fd2d47799bb60668643bc6220f6278a4c1d02",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -84,7 +27,7 @@
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "3.3.0",
|
||||
"json-schema/json-schema-test-suite": "^23.2",
|
||||
"json-schema/json-schema-test-suite": "1.2.0",
|
||||
"marc-mabe/php-enum-phpstan": "^2.0",
|
||||
"phpspec/prophecy": "^1.19",
|
||||
"phpstan/phpstan": "^1.12",
|
||||
@@ -134,22 +77,22 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/jsonrainbow/json-schema/issues",
|
||||
"source": "https://github.com/jsonrainbow/json-schema/tree/6.5.2"
|
||||
"source": "https://github.com/jsonrainbow/json-schema/tree/6.4.2"
|
||||
},
|
||||
"time": "2025-09-09T09:42:27+00:00"
|
||||
"time": "2025-06-03T18:27:04+00:00"
|
||||
},
|
||||
{
|
||||
"name": "marc-mabe/php-enum",
|
||||
"version": "v4.7.2",
|
||||
"version": "v4.7.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/marc-mabe/php-enum.git",
|
||||
"reference": "bb426fcdd65c60fb3638ef741e8782508fda7eef"
|
||||
"reference": "7159809e5cfa041dca28e61f7f7ae58063aae8ed"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/marc-mabe/php-enum/zipball/bb426fcdd65c60fb3638ef741e8782508fda7eef",
|
||||
"reference": "bb426fcdd65c60fb3638ef741e8782508fda7eef",
|
||||
"url": "https://api.github.com/repos/marc-mabe/php-enum/zipball/7159809e5cfa041dca28e61f7f7ae58063aae8ed",
|
||||
"reference": "7159809e5cfa041dca28e61f7f7ae58063aae8ed",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -207,9 +150,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/marc-mabe/php-enum/issues",
|
||||
"source": "https://github.com/marc-mabe/php-enum/tree/v4.7.2"
|
||||
"source": "https://github.com/marc-mabe/php-enum/tree/v4.7.1"
|
||||
},
|
||||
"time": "2025-09-14T11:18:39+00:00"
|
||||
"time": "2024-11-28T04:54:44+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [
|
||||
@@ -433,16 +376,16 @@
|
||||
},
|
||||
{
|
||||
"name": "nextcloud/ocp",
|
||||
"version": "dev-master",
|
||||
"version": "dev-stable32",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nextcloud-deps/ocp.git",
|
||||
"reference": "9a2e6c0bf6f2d87e1db8d18063a5bedf85040bb2"
|
||||
"reference": "5f0db0fc0e5f09a4c8ac06ebc5dedefd21d53603"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nextcloud-deps/ocp/zipball/9a2e6c0bf6f2d87e1db8d18063a5bedf85040bb2",
|
||||
"reference": "9a2e6c0bf6f2d87e1db8d18063a5bedf85040bb2",
|
||||
"url": "https://api.github.com/repos/nextcloud-deps/ocp/zipball/5f0db0fc0e5f09a4c8ac06ebc5dedefd21d53603",
|
||||
"reference": "5f0db0fc0e5f09a4c8ac06ebc5dedefd21d53603",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -452,11 +395,10 @@
|
||||
"psr/event-dispatcher": "^1.0",
|
||||
"psr/log": "^3.0.2"
|
||||
},
|
||||
"default-branch": true,
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "33.0.0-dev"
|
||||
"dev-stable32": "32.0.0-dev"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
@@ -476,9 +418,9 @@
|
||||
"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"
|
||||
"source": "https://github.com/nextcloud-deps/ocp/tree/stable32"
|
||||
},
|
||||
"time": "2025-09-27T00:45:05+00:00"
|
||||
"time": "2025-09-10T00:46:52+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nikic/php-parser",
|
||||
@@ -1130,6 +1072,41 @@
|
||||
],
|
||||
"time": "2024-12-05T13:48:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psalm/phar",
|
||||
"version": "5.26.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/psalm/phar.git",
|
||||
"reference": "8a38e7ad04499a0ccd2c506fd1da6fc01fff4547"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/psalm/phar/zipball/8a38e7ad04499a0ccd2c506fd1da6fc01fff4547",
|
||||
"reference": "8a38e7ad04499a0ccd2c506fd1da6fc01fff4547",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"conflict": {
|
||||
"vimeo/psalm": "*"
|
||||
},
|
||||
"bin": [
|
||||
"psalm.phar"
|
||||
],
|
||||
"type": "library",
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "Composer-based Psalm Phar",
|
||||
"support": {
|
||||
"issues": "https://github.com/psalm/phar/issues",
|
||||
"source": "https://github.com/psalm/phar/tree/5.26.1"
|
||||
},
|
||||
"time": "2024-09-09T16:22:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/clock",
|
||||
"version": "1.0.0",
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
input[type=submit].icon-confirm {
|
||||
border-color: var(--color-border-maxcontrast) !important;
|
||||
border-style: solid;
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
|
||||
24
docs/API.md
24
docs/API.md
@@ -6,7 +6,7 @@ The REST API provides access for authenticated users to their data inside the De
|
||||
|
||||
# Prerequisites
|
||||
|
||||
- All requests require a `OCS-APIRequest` HTTP header to be set to `true` and a `Content-Type` of `application/json`. This does not apply to the endpoint for uploading attachments, which consumes `multipart/form-data`.
|
||||
- All requests require a `OCS-APIRequest` HTTP header to be set to `true` and a `Content-Type` of `application/json`.
|
||||
- The API is located at https://nextcloud.local/index.php/apps/deck/api/v1.0
|
||||
- All request parameters are required, unless otherwise specified
|
||||
|
||||
@@ -733,7 +733,6 @@ The board list endpoint supports setting an `If-Modified-Since` header to limit
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ------- | --------------------------------------- |
|
||||
| labelId | Integer | The label id to assign to the card |
|
||||
|
||||
#### Response
|
||||
|
||||
##### 200 Success
|
||||
@@ -998,12 +997,10 @@ The request can fail with a bad request response for the following reasons:
|
||||
|
||||
#### Request data
|
||||
|
||||
The request is performed as `multipart/form-data`.
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ------- | ----------------------------------------------------------------------------------------------- |
|
||||
| type | String | The type of the attachement. Use `file` or `deck_file`. |
|
||||
| file | Binary | File data to add as an attachment together with the `filename` parameter according to RFC 7578. |
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ------- | --------------------------------------------- |
|
||||
| type | String | The type of the attachement |
|
||||
| file | Binary | File data to add as an attachment |
|
||||
|
||||
- Prior to Deck version v1.3.0 (API v1.0), attachments were stored within deck. For this type of attachments `deck_file` was used as the default type of attachments
|
||||
- Starting with Deck version 1.3.0 (API v1.1) files are stored within the users regular Nextcloud files and the type `file` has been introduced for that
|
||||
@@ -1025,13 +1022,12 @@ The request is performed as `multipart/form-data`.
|
||||
|
||||
#### Request data
|
||||
|
||||
The request is performed as `multipart/form-data`.
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ------- | ----------------------------------------------------------------------------------------------- |
|
||||
| type | String | The type of the attachement. For now only `deck_file` is supported as an attachment type. |
|
||||
| file | Binary | File data to add as an attachment together with the `filename` parameter according to RFC 7578. |
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ------- | --------------------------------------------- |
|
||||
| type | String | The type of the attachement |
|
||||
| file | Binary | File data to add as an attachment |
|
||||
|
||||
For now only `deck_file` is supported as an attachment type.
|
||||
|
||||
#### Response
|
||||
|
||||
|
||||
@@ -516,7 +516,7 @@ class ActivityManager {
|
||||
];
|
||||
}
|
||||
|
||||
private function findDetailsForCard(int $cardId, ?string $subject = null): array {
|
||||
private function findDetailsForCard($cardId, $subject = null) {
|
||||
$card = $this->cardMapper->find($cardId);
|
||||
$stack = $this->stackMapper->find($card->getStackId());
|
||||
$board = $this->boardMapper->find($stack->getBoardId());
|
||||
|
||||
@@ -7,9 +7,6 @@
|
||||
|
||||
namespace OCA\Deck\Activity;
|
||||
|
||||
/**
|
||||
* @psalm-api SettingComment
|
||||
*/
|
||||
class SettingComment extends SettingBase {
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,13 +6,9 @@
|
||||
*/
|
||||
namespace OCA\Deck\Controller;
|
||||
|
||||
use OCA\Deck\Db\Attachment;
|
||||
use OCA\Deck\Service\AttachmentService;
|
||||
use OCP\AppFramework\ApiController;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\Attribute\CORS;
|
||||
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\IRequest;
|
||||
|
||||
@@ -25,52 +21,72 @@ class AttachmentApiController extends ApiController {
|
||||
parent::__construct($appName, $request);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function getAll(string $apiVersion): DataResponse {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
*/
|
||||
public function getAll($apiVersion) {
|
||||
$attachment = $this->attachmentService->findAll($this->request->getParam('cardId'), true);
|
||||
if ($apiVersion === '1.0') {
|
||||
$attachment = array_filter($attachment, fn (Attachment $attachment): bool => $attachment->getType() === 'deck_file');
|
||||
$attachment = array_filter($attachment, function ($attachment) {
|
||||
return $attachment->getType() === 'deck_file';
|
||||
});
|
||||
}
|
||||
return new DataResponse($attachment, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function display(int $cardId, int $attachmentId, string $type = 'deck_file') {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
*/
|
||||
public function display($cardId, $attachmentId, $type = 'deck_file') {
|
||||
return $this->attachmentService->display($cardId, $attachmentId, $type);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function create(int $cardId, string $type, string $data): DataResponse {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
*/
|
||||
public function create($cardId, $type, $data) {
|
||||
$attachment = $this->attachmentService->create($cardId, $type, $data);
|
||||
return new DataResponse($attachment, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function update(int $cardId, int $attachmentId, string $data, string $type = 'deck_file'): DataResponse {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
*/
|
||||
public function update($cardId, $attachmentId, $data, $type = 'deck_file') {
|
||||
$attachment = $this->attachmentService->update($cardId, $attachmentId, $data, $type);
|
||||
return new DataResponse($attachment, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function delete(int $cardId, int $attachmentId, string $type = 'deck_file'): DataResponse {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
*/
|
||||
public function delete($cardId, $attachmentId, $type = 'deck_file') {
|
||||
$attachment = $this->attachmentService->delete($cardId, $attachmentId, $type);
|
||||
return new DataResponse($attachment, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function restore(int $cardId, int $attachmentId, string $type = 'deck_file'): DataResponse {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
*/
|
||||
public function restore($cardId, $attachmentId, $type = 'deck_file') {
|
||||
$attachment = $this->attachmentService->restore($cardId, $attachmentId, $type);
|
||||
return new DataResponse($attachment, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
@@ -7,13 +7,8 @@
|
||||
|
||||
namespace OCA\Deck\Controller;
|
||||
|
||||
use OCA\Deck\BadRequestException;
|
||||
use OCA\Deck\Db\Attachment;
|
||||
use OCA\Deck\Service\AttachmentService;
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
|
||||
use OCP\AppFramework\Http\Response;
|
||||
use OCP\IRequest;
|
||||
|
||||
class AttachmentController extends Controller {
|
||||
@@ -25,66 +20,74 @@ class AttachmentController extends Controller {
|
||||
parent::__construct($appName, $request);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function getAll(int $cardId): array {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function getAll($cardId) {
|
||||
return $this->attachmentService->findAll($cardId, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $cardId
|
||||
* @param $attachmentId
|
||||
* @NoCSRFRequired
|
||||
* @NoAdminRequired
|
||||
* @return \OCP\AppFramework\Http\Response
|
||||
* @throws \OCA\Deck\NotFoundException
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[NoCSRFRequired]
|
||||
public function display(int $cardId, string $attachmentId): Response {
|
||||
['type' => $type, 'attachmentId' => $attachmentId] = $this->extractTypeAndAttachmentId($attachmentId);
|
||||
return $this->attachmentService->display($cardId, $attachmentId, $type);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function create(int $cardId): Attachment {
|
||||
return $this->attachmentService->create(
|
||||
$cardId,
|
||||
$this->request->getParam('type'),
|
||||
$this->request->getParam('data') ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function update(int $cardId, string $attachmentId): Attachment {
|
||||
['type' => $type, 'attachmentId' => $attachmentId] = $this->extractTypeAndAttachmentId($attachmentId);
|
||||
return $this->attachmentService->update($cardId, $attachmentId, $this->request->getParam('data') ?? '', $type);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function delete(int $cardId, string $attachmentId): Attachment {
|
||||
['type' => $type, 'attachmentId' => $attachmentId] = $this->extractTypeAndAttachmentId($attachmentId);
|
||||
return $this->attachmentService->delete($cardId, $attachmentId, $type);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function restore(int $cardId, string $attachmentId): Attachment {
|
||||
['type' => $type, 'attachmentId' => $attachmentId] = $this->extractTypeAndAttachmentId($attachmentId);
|
||||
return $this->attachmentService->restore($cardId, $attachmentId, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{type: string, attachmentId: int}
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
private function extractTypeAndAttachmentId(string $attachmentId): array {
|
||||
public function display($cardId, $attachmentId) {
|
||||
if (!str_contains($attachmentId, ':')) {
|
||||
$type = 'deck_file';
|
||||
} else {
|
||||
[$type, $attachmentId] = [...explode(':', $attachmentId), '', ''];
|
||||
[$type, $attachmentId] = explode(':', $attachmentId);
|
||||
}
|
||||
return $this->attachmentService->display($cardId, $attachmentId, $type);
|
||||
}
|
||||
|
||||
if ($type === '' || !is_numeric($attachmentId)) {
|
||||
throw new BadRequestException('Invalid attachment id');
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function create($cardId) {
|
||||
return $this->attachmentService->create(
|
||||
$cardId,
|
||||
$this->request->getParam('type'),
|
||||
$this->request->getParam('data')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function update($cardId, $attachmentId) {
|
||||
if (!str_contains($attachmentId, ':')) {
|
||||
$type = 'deck_file';
|
||||
} else {
|
||||
[$type, $attachmentId] = explode(':', $attachmentId);
|
||||
}
|
||||
return $this->attachmentService->update($cardId, $attachmentId, $this->request->getParam('data'), $type);
|
||||
}
|
||||
|
||||
return [
|
||||
'type' => $type,
|
||||
'attachmentId' => (int)$attachmentId,
|
||||
];
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function delete($cardId, $attachmentId) {
|
||||
if (!str_contains($attachmentId, ':')) {
|
||||
$type = 'deck_file';
|
||||
} else {
|
||||
[$type, $attachmentId] = explode(':', $attachmentId);
|
||||
}
|
||||
return $this->attachmentService->delete($cardId, $attachmentId, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function restore($cardId, $attachmentId) {
|
||||
if (!str_contains($attachmentId, ':')) {
|
||||
$type = 'deck_file';
|
||||
} else {
|
||||
[$type, $attachmentId] = explode(':', $attachmentId);
|
||||
}
|
||||
return $this->attachmentService->restore($cardId, $attachmentId, $type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,13 +12,10 @@ use OCA\Deck\Service\BoardService;
|
||||
use OCA\Deck\StatusException;
|
||||
use OCP\AppFramework\ApiController;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\Attribute\CORS;
|
||||
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\IRequest;
|
||||
|
||||
use function Sabre\HTTP\parseDate;
|
||||
use OCP\IRequest;
|
||||
use Sabre\HTTP\Util;
|
||||
|
||||
/**
|
||||
* Class BoardApiController
|
||||
@@ -39,18 +36,21 @@ class BoardApiController extends ApiController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all the boards that the current user has access to.
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* Return all of the boards that the current user has access to.
|
||||
*
|
||||
* @param bool $details
|
||||
* @throws StatusException
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[NoCSRFRequired]
|
||||
#[CORS]
|
||||
public function index(bool $details = false): DataResponse {
|
||||
public function index(bool $details = false) {
|
||||
$modified = $this->request->getHeader('If-Modified-Since');
|
||||
if ($modified === '') {
|
||||
if ($modified === null || $modified === '') {
|
||||
$boards = $this->boardService->findAll(0, $details === true);
|
||||
} else {
|
||||
$date = parseDate($modified);
|
||||
$date = Util::parseHTTPDate($modified);
|
||||
if (!$date) {
|
||||
throw new StatusException('Invalid If-Modified-Since header provided.');
|
||||
}
|
||||
@@ -64,12 +64,14 @@ class BoardApiController extends ApiController {
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
*
|
||||
* Return the board specified by $this->request->getParam('boardId').
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[NoCSRFRequired]
|
||||
#[CORS]
|
||||
public function get(): DataResponse {
|
||||
public function get() {
|
||||
$board = $this->boardService->find($this->request->getParam('boardId'));
|
||||
$response = new DataResponse($board, HTTP::STATUS_OK);
|
||||
$response->setETag($board->getEtag());
|
||||
@@ -77,53 +79,68 @@ class BoardApiController extends ApiController {
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* @params $title
|
||||
* @params $color
|
||||
*
|
||||
* Create a board with the specified title and color.
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[NoCSRFRequired]
|
||||
#[CORS]
|
||||
public function create(string $title, string $color): DataResponse {
|
||||
public function create($title, $color) {
|
||||
$board = $this->boardService->create($title, $this->userId, $color);
|
||||
return new DataResponse($board, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* @params $title
|
||||
* @params $color
|
||||
* @params $archived
|
||||
*
|
||||
* Update a board with the specified boardId, title and color, and archived state.
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[NoCSRFRequired]
|
||||
#[CORS]
|
||||
public function update(string $title, string $color, bool $archived = false): DataResponse {
|
||||
public function update($title, $color, $archived = false) {
|
||||
$board = $this->boardService->update($this->request->getParam('boardId'), $title, $color, $archived);
|
||||
return new DataResponse($board, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
*
|
||||
* Delete the board specified by $boardId. Return the board that was deleted.
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[NoCSRFRequired]
|
||||
#[CORS]
|
||||
public function delete(): DataResponse {
|
||||
public function delete() {
|
||||
$board = $this->boardService->delete($this->request->getParam('boardId'));
|
||||
return new DataResponse($board, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
*
|
||||
* Undo the deletion of the board specified by $boardId.
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[NoCSRFRequired]
|
||||
#[CORS]
|
||||
public function undoDelete(): DataResponse {
|
||||
public function undoDelete() {
|
||||
$board = $this->boardService->deleteUndo($this->request->getParam('boardId'));
|
||||
return new DataResponse($board, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
#[NoCSRFRequired]
|
||||
#[CORS]
|
||||
public function addAcl(int $boardId, $type, $participant, $permissionEdit, $permissionShare, $permissionManage) {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*/
|
||||
public function addAcl($boardId, $type, $participant, $permissionEdit, $permissionShare, $permissionManage) {
|
||||
$acl = $this->boardService->addAcl($boardId, $type, $participant, $permissionEdit, $permissionShare, $permissionManage);
|
||||
return new DataResponse($acl, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ use OCA\Deck\Service\Importer\BoardImportService;
|
||||
use OCA\Deck\Service\PermissionService;
|
||||
use OCP\AppFramework\ApiController;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\IL10N;
|
||||
use OCP\IRequest;
|
||||
@@ -32,38 +31,68 @@ class BoardController extends ApiController {
|
||||
parent::__construct($appName, $request);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function index() {
|
||||
return $this->boardService->findAll();
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function read(int $boardId): Board {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $boardId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function read(int $boardId) {
|
||||
return $this->boardService->find($boardId);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function create(string $title, string $color): Board {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $title
|
||||
* @param $color
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function create($title, $color) {
|
||||
return $this->boardService->create($title, $this->userId, $color);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function update(int $id, string $title, string $color, bool $archived): Board {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $id
|
||||
* @param $title
|
||||
* @param $color
|
||||
* @param $archived
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function update($id, $title, $color, $archived) {
|
||||
return $this->boardService->update($id, $title, $color, $archived);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function delete(int $boardId): Board {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $boardId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function delete($boardId) {
|
||||
return $this->boardService->delete($boardId);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function deleteUndo(int $boardId): Board {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $boardId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function deleteUndo($boardId) {
|
||||
return $this->boardService->deleteUndo($boardId);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function getUserPermissions(int $boardId): array {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $boardId
|
||||
* @return array|bool
|
||||
* @internal param $userId
|
||||
*/
|
||||
public function getUserPermissions($boardId) {
|
||||
$permissions = $this->permissionService->getPermissions($boardId);
|
||||
return [
|
||||
'PERMISSION_READ' => $permissions[Acl::PERMISSION_READ],
|
||||
@@ -74,10 +103,16 @@ class BoardController extends ApiController {
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $boardId
|
||||
* @param $type
|
||||
* @param $participant
|
||||
* @param $permissionEdit
|
||||
* @param $permissionShare
|
||||
* @param $permissionManage
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
public function addAcl(int $boardId, int $type, $participant, bool $permissionEdit, bool $permissionShare, bool $permissionManage): Acl {
|
||||
public function addAcl($boardId, $type, $participant, $permissionEdit, $permissionShare, $permissionManage) {
|
||||
return $this->boardService->addAcl($boardId, $type, $participant, $permissionEdit, $permissionShare, $permissionManage);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,9 +9,6 @@ namespace OCA\Deck\Controller;
|
||||
|
||||
use OCA\Deck\Service\Importer\BoardImportService;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\Attribute\CORS;
|
||||
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\AppFramework\OCSController;
|
||||
use OCP\IRequest;
|
||||
@@ -26,9 +23,11 @@ class BoardImportApiController extends OCSController {
|
||||
parent::__construct($appName, $request);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*/
|
||||
public function import(string $system, array $config, array $data): DataResponse {
|
||||
$this->boardImportService->setSystem($system);
|
||||
$config = json_decode(json_encode($config));
|
||||
@@ -39,17 +38,21 @@ class BoardImportApiController extends OCSController {
|
||||
return new DataResponse($this->boardImportService->getBoard(), Http::STATUS_OK);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*/
|
||||
public function getAllowedSystems(): DataResponse {
|
||||
$allowedSystems = $this->boardImportService->getAllowedImportSystems();
|
||||
return new DataResponse($allowedSystems, Http::STATUS_OK);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*/
|
||||
public function getConfigSchema(string $name): DataResponse {
|
||||
$this->boardImportService->setSystem($name);
|
||||
$this->boardImportService->validateSystem();
|
||||
|
||||
@@ -12,9 +12,6 @@ use OCA\Deck\Service\AssignmentService;
|
||||
use OCA\Deck\Service\CardService;
|
||||
use OCP\AppFramework\ApiController;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\Attribute\CORS;
|
||||
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\IRequest;
|
||||
|
||||
@@ -30,7 +27,7 @@ class CardApiController extends ApiController {
|
||||
* @param IRequest $request
|
||||
* @param CardService $cardService
|
||||
* @param AssignmentService $assignmentService
|
||||
* @param string $userId
|
||||
* @param $userId
|
||||
*/
|
||||
public function __construct(
|
||||
string $appName,
|
||||
@@ -83,102 +80,112 @@ class CardApiController extends ApiController {
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
*
|
||||
* Update a card
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function update(string $title, $type, string $owner, string $description = '', int $order = 0, $duedate = null, $archived = null): DataResponse {
|
||||
public function update($title, $type, $owner, $description = '', $order = 0, $duedate = null, $archived = null) {
|
||||
$done = array_key_exists('done', $this->request->getParams()) ? new OptionalNullableValue($this->request->getParam('done', null)) : null;
|
||||
$card = $this->cardService->update($this->request->getParam('cardId'), $title, $this->request->getParam('stackId'), $type, $owner, $description, $order, $duedate, 0, $archived, $done);
|
||||
return new DataResponse($card, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* Delete a specific card.
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function delete(): DataResponse {
|
||||
public function delete() {
|
||||
$card = $this->cardService->delete($this->request->getParam('cardId'));
|
||||
return new DataResponse($card, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* Assign a label to a card.
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function assignLabel(int $labelId): DataResponse {
|
||||
public function assignLabel($labelId) {
|
||||
$card = $this->cardService->assignLabel($this->request->getParam('cardId'), $labelId);
|
||||
return new DataResponse($card, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* Assign a label to a card.
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function removeLabel(int $labelId): DataResponse {
|
||||
public function removeLabel($labelId) {
|
||||
$card = $this->cardService->removeLabel($this->request->getParam('cardId'), $labelId);
|
||||
return new DataResponse($card, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* Assign a user to a card
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function assignUser(int $cardId, string $userId, int $type = 0): DataResponse {
|
||||
public function assignUser($cardId, $userId, $type = 0) {
|
||||
$card = $this->assignmentService->assignUser($cardId, $userId, $type);
|
||||
return new DataResponse($card, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* Unassign a user from a card
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function unassignUser(int $cardId, string $userId, int $type = 0): DataResponse {
|
||||
public function unassignUser($cardId, $userId, $type = 0) {
|
||||
$card = $this->assignmentService->unassignUser($cardId, $userId, $type);
|
||||
return new DataResponse($card, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* Archive card
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function archive(int $cardId): DataResponse {
|
||||
public function archive($cardId) {
|
||||
$card = $this->cardService->archive($cardId);
|
||||
return new DataResponse($card, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* Unarchive card
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function unarchive(int $cardId): DataResponse {
|
||||
public function unarchive($cardId) {
|
||||
$card = $this->cardService->unarchive($cardId);
|
||||
return new DataResponse($card, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* Reorder cards
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function reorder(int $stackId, int $order): DataResponse {
|
||||
$card = $this->cardService->reorder((int)$this->request->getParam('cardId'), $stackId, $order);
|
||||
public function reorder($stackId, $order) {
|
||||
$card = $this->cardService->reorder((int)$this->request->getParam('cardId'), (int)$stackId, (int)$order);
|
||||
return new DataResponse($card, HTTP::STATUS_OK);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,12 +7,9 @@
|
||||
|
||||
namespace OCA\Deck\Controller;
|
||||
|
||||
use OCA\Deck\Db\Assignment;
|
||||
use OCA\Deck\Db\Card;
|
||||
use OCA\Deck\Service\AssignmentService;
|
||||
use OCA\Deck\Service\CardService;
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||
use OCP\IRequest;
|
||||
|
||||
class CardController extends Controller {
|
||||
@@ -26,26 +23,45 @@ class CardController extends Controller {
|
||||
parent::__construct($appName, $request);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function read(int $cardId): Card {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $cardId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function read($cardId) {
|
||||
return $this->cardService->find($cardId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Card[]
|
||||
* @NoAdminRequired
|
||||
* @param $cardId
|
||||
* @param $stackId
|
||||
* @param $order
|
||||
* @return array
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
public function reorder(int $cardId, int $stackId, int $order): array {
|
||||
return $this->cardService->reorder($cardId, $stackId, $order);
|
||||
public function reorder($cardId, $stackId, $order) {
|
||||
return $this->cardService->reorder((int)$cardId, (int)$stackId, (int)$order);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function rename(int $cardId, string $title): Card {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $cardId
|
||||
* @param $title
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function rename($cardId, $title) {
|
||||
return $this->cardService->rename($cardId, $title);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function create(string $title, int $stackId, string $type = 'plain', int $order = 999, string $description = '', $duedate = null, array $labels = [], array $users = []): Card {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $title
|
||||
* @param $stackId
|
||||
* @param $type
|
||||
* @param int $order
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function create($title, $stackId, $type = 'plain', $order = 999, string $description = '', $duedate = null, $labels = [], $users = []) {
|
||||
$card = $this->cardService->create($title, $stackId, $type, $order, $this->userId, $description, $duedate);
|
||||
|
||||
foreach ($labels as $label) {
|
||||
@@ -60,68 +76,113 @@ class CardController extends Controller {
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $id
|
||||
* @param $title
|
||||
* @param $stackId
|
||||
* @param $type
|
||||
* @param $order
|
||||
* @param $description
|
||||
* @param $duedate
|
||||
* @param $deletedAt
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
public function update(int $id, string $title, int $stackId, string $type, int $order, string $description, $duedate, $deletedAt): Card {
|
||||
public function update($id, $title, $stackId, $type, $order, $description, $duedate, $deletedAt) {
|
||||
return $this->cardService->update($id, $title, $stackId, $type, $this->userId, $description, $order, $duedate, $deletedAt);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function clone(int $cardId, ?int $targetStackId = null): Card {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $cardId
|
||||
* @param $targetStackId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function clone(int $cardId, ?int $targetStackId = null) {
|
||||
return $this->cardService->cloneCard($cardId, $targetStackId);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function delete(int $cardId): Card {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $cardId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function delete($cardId) {
|
||||
return $this->cardService->delete($cardId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Card[]
|
||||
* @NoAdminRequired
|
||||
* @param $boardId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
public function deleted(int $boardId): array {
|
||||
public function deleted($boardId) {
|
||||
return $this->cardService->fetchDeleted($boardId);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $cardId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function archive($cardId) {
|
||||
return $this->cardService->archive($cardId);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function unarchive(int $cardId): Card {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $cardId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function unarchive($cardId) {
|
||||
return $this->cardService->unarchive($cardId);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function done(int $cardId): Card {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $cardId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function done(int $cardId) {
|
||||
return $this->cardService->done($cardId);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function undone(int $cardId): Card {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $cardId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function undone(int $cardId) {
|
||||
return $this->cardService->undone($cardId);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function assignLabel(int $cardId, int $labelId): void {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $cardId
|
||||
* @param $labelId
|
||||
*/
|
||||
public function assignLabel($cardId, $labelId) {
|
||||
$this->cardService->assignLabel($cardId, $labelId);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function removeLabel(int $cardId, int $labelId): void {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $cardId
|
||||
* @param $labelId
|
||||
*/
|
||||
public function removeLabel($cardId, $labelId) {
|
||||
$this->cardService->removeLabel($cardId, $labelId);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function assignUser(int $cardId, string $userId, int $type = 0): Assignment {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function assignUser($cardId, $userId, $type = 0) {
|
||||
return $this->assignmentService->assignUser($cardId, $userId, $type);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function unassignUser(int $cardId, string $userId, int $type = 0): Assignment {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function unassignUser($cardId, $userId, $type = 0) {
|
||||
return $this->assignmentService->unassignUser($cardId, $userId, $type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,15 +9,11 @@ namespace OCA\Deck\Controller;
|
||||
|
||||
use OCA\Deck\Service\CommentService;
|
||||
use OCA\Deck\StatusException;
|
||||
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
|
||||
use OCP\AppFramework\OCSController;
|
||||
use OCP\IRequest;
|
||||
|
||||
/**
|
||||
* @psalm-api
|
||||
*/
|
||||
class CommentsApiController extends OCSController {
|
||||
public function __construct(
|
||||
string $appName,
|
||||
@@ -31,33 +27,33 @@ class CommentsApiController extends OCSController {
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @throws StatusException
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
public function list(int $cardId, int $limit = 20, int $offset = 0): DataResponse {
|
||||
public function list(string $cardId, int $limit = 20, int $offset = 0): DataResponse {
|
||||
return $this->commentService->list($cardId, $limit, $offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @throws StatusException
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
public function create(int $cardId, string $message, int $parentId = 0): DataResponse {
|
||||
return $this->commentService->create($cardId, $message, $parentId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @throws StatusException
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
public function update(int $cardId, int $commentId, string $message): DataResponse {
|
||||
return $this->commentService->update($cardId, $commentId, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @throws StatusException
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
public function delete(int $cardId, int $commentId): DataResponse {
|
||||
return $this->commentService->delete($cardId, $commentId);
|
||||
}
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
namespace OCA\Deck\Controller;
|
||||
|
||||
use OCA\Deck\Service\ConfigService;
|
||||
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\AppFramework\Http\NotFoundResponse;
|
||||
use OCP\AppFramework\OCSController;
|
||||
@@ -24,15 +22,19 @@ class ConfigController extends OCSController {
|
||||
parent::__construct($AppName, $request);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
#[NoCSRFRequired]
|
||||
/**
|
||||
* @NoCSRFRequired
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function get(): DataResponse {
|
||||
return new DataResponse($this->configService->getAll());
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
#[NoCSRFRequired]
|
||||
public function setValue(string $key, mixed $value): DataResponse|NotFoundResponse {
|
||||
/**
|
||||
* @NoCSRFRequired
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function setValue(string $key, $value) {
|
||||
$result = $this->configService->set($key, $value);
|
||||
if ($result === null) {
|
||||
return new NotFoundResponse();
|
||||
|
||||
@@ -10,9 +10,6 @@ namespace OCA\Deck\Controller;
|
||||
use OCA\Deck\Service\LabelService;
|
||||
use OCP\AppFramework\ApiController;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\Attribute\CORS;
|
||||
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\IRequest;
|
||||
|
||||
@@ -29,50 +26,59 @@ class LabelApiController extends ApiController {
|
||||
$appName,
|
||||
IRequest $request,
|
||||
private LabelService $labelService,
|
||||
private $userId,
|
||||
) {
|
||||
parent::__construct($appName, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* Get a specific label.
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[NoCSRFRequired]
|
||||
#[CORS]
|
||||
public function get(): DataResponse {
|
||||
public function get() {
|
||||
$label = $this->labelService->find($this->request->getParam('labelId'));
|
||||
return new DataResponse($label, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* @params $title
|
||||
* @params $color
|
||||
* Create a new label
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[NoCSRFRequired]
|
||||
#[CORS]
|
||||
public function create(string $title, string $color): DataResponse {
|
||||
public function create($title, $color) {
|
||||
$label = $this->labelService->create($title, $color, $this->request->getParam('boardId'));
|
||||
return new DataResponse($label, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* @params $title
|
||||
* @params $color
|
||||
* Update a specific label
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[NoCSRFRequired]
|
||||
#[CORS]
|
||||
public function update(string $title, string $color): DataResponse {
|
||||
public function update($title, $color) {
|
||||
$label = $this->labelService->update($this->request->getParam('labelId'), $title, $color);
|
||||
return new DataResponse($label, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* Delete a specific label
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[NoCSRFRequired]
|
||||
#[CORS]
|
||||
public function delete(): DataResponse {
|
||||
public function delete() {
|
||||
$label = $this->labelService->delete($this->request->getParam('labelId'));
|
||||
return new DataResponse($label, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
@@ -7,10 +7,8 @@
|
||||
|
||||
namespace OCA\Deck\Controller;
|
||||
|
||||
use OCA\Deck\Db\Label;
|
||||
use OCA\Deck\Service\LabelService;
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||
use OCP\IRequest;
|
||||
|
||||
class LabelController extends Controller {
|
||||
@@ -22,18 +20,34 @@ class LabelController extends Controller {
|
||||
parent::__construct($appName, $request);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function create(string $title, string $color, int $boardId): Label {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $title
|
||||
* @param $color
|
||||
* @param $boardId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function create($title, $color, $boardId) {
|
||||
return $this->labelService->create($title, $color, $boardId);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function update(int $id, string $title, string $color): Label {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $id
|
||||
* @param $title
|
||||
* @param $color
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function update($id, $title, $color) {
|
||||
return $this->labelService->update($id, $title, $color);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function delete(int $labelId): Label {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $labelId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function delete($labelId) {
|
||||
return $this->labelService->delete($labelId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ declare(strict_types=1);
|
||||
namespace OCA\Deck\Controller;
|
||||
|
||||
use OCA\Deck\Service\OverviewService;
|
||||
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\AppFramework\OCSController;
|
||||
use OCP\IRequest;
|
||||
@@ -25,7 +24,9 @@ class OverviewApiController extends OCSController {
|
||||
parent::__construct($appName, $request);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function upcomingCards(): DataResponse {
|
||||
return new DataResponse($this->dashboardService->findUpcomingCards($this->userId));
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ namespace OCA\Deck\Controller;
|
||||
use OCA\Deck\Db\Card;
|
||||
use OCA\Deck\Model\CardDetails;
|
||||
use OCA\Deck\Service\SearchService;
|
||||
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\AppFramework\OCSController;
|
||||
use OCP\IRequest;
|
||||
@@ -27,7 +26,9 @@ class SearchController extends OCSController {
|
||||
parent::__construct($appName, $request);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function search(string $term, ?int $limit = null, ?int $cursor = null): DataResponse {
|
||||
$cards = $this->searchService->searchCards($term, $limit, $cursor);
|
||||
return new DataResponse(array_map(function (Card $card) {
|
||||
|
||||
@@ -7,16 +7,14 @@
|
||||
|
||||
namespace OCA\Deck\Controller;
|
||||
|
||||
use OCA\Deck\Service\BoardService;
|
||||
use OCA\Deck\Service\StackService;
|
||||
use OCA\Deck\StatusException;
|
||||
use OCP\AppFramework\ApiController;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\Attribute\CORS;
|
||||
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\IRequest;
|
||||
use function Sabre\HTTP\parseDate;
|
||||
use Sabre\HTTP\Util;
|
||||
|
||||
/**
|
||||
* Class StackApiController
|
||||
@@ -31,21 +29,23 @@ class StackApiController extends ApiController {
|
||||
$appName,
|
||||
IRequest $request,
|
||||
private StackService $stackService,
|
||||
private BoardService $boardService,
|
||||
) {
|
||||
parent::__construct($appName, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all the stacks in the specified board.
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* Return all of the stacks in the specified board.
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function index(): DataResponse {
|
||||
public function index() {
|
||||
$since = 0;
|
||||
$modified = $this->request->getHeader('If-Modified-Since');
|
||||
if ($modified !== '') {
|
||||
$date = parseDate($modified);
|
||||
if ($modified !== null && $modified !== '') {
|
||||
$date = Util::parseHTTPDate($modified);
|
||||
if (!$date) {
|
||||
throw new StatusException('Invalid If-Modified-Since header provided.');
|
||||
}
|
||||
@@ -56,12 +56,13 @@ class StackApiController extends ApiController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all the stacks in the specified board.
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* Return all of the stacks in the specified board.
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function get(): DataResponse {
|
||||
public function get() {
|
||||
$stack = $this->stackService->find($this->request->getParam('stackId'));
|
||||
$response = new DataResponse($stack, HTTP::STATUS_OK);
|
||||
$response->setETag($stack->getETag());
|
||||
@@ -69,45 +70,55 @@ class StackApiController extends ApiController {
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* @params $title
|
||||
* @params $order
|
||||
*
|
||||
* Create a stack with the specified title and order.
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function create(string $title, int $order): DataResponse {
|
||||
public function create($title, $order) {
|
||||
$stack = $this->stackService->create($title, $this->request->getParam('boardId'), $order);
|
||||
return new DataResponse($stack, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* @params $title
|
||||
* @params $order
|
||||
*
|
||||
* Update a stack by the specified stackId and boardId with the values that were put.
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function update(string $title, int $order) {
|
||||
public function update($title, $order) {
|
||||
$stack = $this->stackService->update($this->request->getParam('stackId'), $title, $this->request->getParam('boardId'), $order, 0);
|
||||
return new DataResponse($stack, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* Delete the stack specified by $this->request->getParam('stackId').
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function delete(): DataResponse {
|
||||
public function delete() {
|
||||
$stack = $this->stackService->delete($this->request->getParam('stackId'));
|
||||
return new DataResponse($stack, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the stacks that have been archived.
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* get the stacks that have been archived.
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function getArchived(): DataResponse {
|
||||
public function getArchived() {
|
||||
$stacks = $this->stackService->findAllArchived($this->request->getParam('boardId'));
|
||||
return new DataResponse($stacks, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
@@ -7,12 +7,10 @@
|
||||
|
||||
namespace OCA\Deck\Controller;
|
||||
|
||||
use OCA\Deck\Db\Stack;
|
||||
use OCA\Deck\Service\StackService;
|
||||
|
||||
use OCP\AppFramework\Controller;
|
||||
|
||||
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||
use OCP\IRequest;
|
||||
|
||||
class StackController extends Controller {
|
||||
@@ -20,54 +18,78 @@ class StackController extends Controller {
|
||||
string $appName,
|
||||
IRequest $request,
|
||||
private StackService $stackService,
|
||||
private $userId,
|
||||
) {
|
||||
parent::__construct($appName, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Stack[]
|
||||
* @NoAdminRequired
|
||||
* @param $boardId
|
||||
* @return array
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
public function index(int $boardId): array {
|
||||
public function index($boardId) {
|
||||
return $this->stackService->findAll($boardId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Stack[]
|
||||
* @NoAdminRequired
|
||||
* @param $boardId
|
||||
* @return array
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
public function archived(int $boardId): array {
|
||||
public function archived($boardId) {
|
||||
return $this->stackService->findAllArchived($boardId);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function create(string $title, int $boardId, int $order = 999): Stack {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $title
|
||||
* @param $boardId
|
||||
* @param int $order
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function create($title, $boardId, $order = 999) {
|
||||
return $this->stackService->create($title, $boardId, $order);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function update(int $id, string $title, int $boardId, int $order, ?int $deletedAt = null): Stack {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $id
|
||||
* @param $title
|
||||
* @param $boardId
|
||||
* @param $order
|
||||
* @param $deletedAt
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function update($id, $title, $boardId, $order, $deletedAt) {
|
||||
return $this->stackService->update($id, $title, $boardId, $order, $deletedAt);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, Stack>
|
||||
* @NoAdminRequired
|
||||
* @param $stackId
|
||||
* @param $order
|
||||
* @return array
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
public function reorder(int $stackId, int $order): array {
|
||||
return $this->stackService->reorder($stackId, $order);
|
||||
public function reorder($stackId, $order) {
|
||||
return $this->stackService->reorder((int)$stackId, (int)$order);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function delete(int $stackId): Stack {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $stackId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function delete($stackId) {
|
||||
return $this->stackService->delete($stackId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Stack[]
|
||||
* @NoAdminRequired
|
||||
* @param $boardId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
public function deleted(int $boardId): array {
|
||||
public function deleted($boardId) {
|
||||
return $this->stackService->fetchDeleted($boardId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,20 +7,6 @@
|
||||
|
||||
namespace OCA\Deck\Db;
|
||||
|
||||
/**
|
||||
* @method int getBoardId()
|
||||
* @method bool isPermissionEdit()
|
||||
* @method void setPermissionEdit(bool $permissionEdit)
|
||||
* @method bool isPermissionShare()
|
||||
* @method void setPermissionShare(bool $permissionShare)
|
||||
* @method bool isPermissionManage()
|
||||
* @method void setPermissionManage(bool $permissionManage)
|
||||
* @method int getType()
|
||||
* @method void setType(int $type)
|
||||
* @method bool isOwner()
|
||||
* @method void setOwner(int $owner)
|
||||
*
|
||||
*/
|
||||
class Acl extends RelationalEntity {
|
||||
public const PERMISSION_READ = 0;
|
||||
public const PERMISSION_EDIT = 1;
|
||||
@@ -51,13 +37,17 @@ class Acl extends RelationalEntity {
|
||||
$this->addResolvable('participant');
|
||||
}
|
||||
|
||||
public function getPermission(int $permission): bool {
|
||||
return match ($permission) {
|
||||
self::PERMISSION_READ => true,
|
||||
self::PERMISSION_EDIT => $this->getPermissionEdit(),
|
||||
self::PERMISSION_SHARE => $this->getPermissionShare(),
|
||||
self::PERMISSION_MANAGE => $this->getPermissionManage(),
|
||||
default => false,
|
||||
};
|
||||
public function getPermission($permission) {
|
||||
switch ($permission) {
|
||||
case self::PERMISSION_READ:
|
||||
return true;
|
||||
case self::PERMISSION_EDIT:
|
||||
return $this->getPermissionEdit();
|
||||
case self::PERMISSION_SHARE:
|
||||
return $this->getPermissionShare();
|
||||
case self::PERMISSION_MANAGE:
|
||||
return $this->getPermissionManage();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,10 +19,13 @@ class AclMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param numeric $boardId
|
||||
* @param int|null $limit
|
||||
* @param int|null $offset
|
||||
* @return Acl[]
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findAll(int $boardId, ?int $limit = null, ?int $offset = null) {
|
||||
public function findAll($boardId, $limit = null, $offset = null) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('id', 'board_id', 'type', 'participant', 'permission_edit', 'permission_share', 'permission_manage')
|
||||
->from('deck_board_acl')
|
||||
@@ -48,9 +51,12 @@ class AclMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param numeric $userId
|
||||
* @param numeric $id
|
||||
* @return bool
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function isOwner(string $userId, int $id): bool {
|
||||
public function isOwner($userId, $id): bool {
|
||||
$aclId = $id;
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('acl.id')
|
||||
@@ -62,7 +68,11 @@ class AclMapper extends DeckMapper implements IPermissionMapper {
|
||||
return count($qb->executeQuery()->fetchAll()) > 0;
|
||||
}
|
||||
|
||||
public function findBoardId(int $id): ?int {
|
||||
/**
|
||||
* @param numeric $id
|
||||
* @return int|null
|
||||
*/
|
||||
public function findBoardId($id): ?int {
|
||||
try {
|
||||
$entity = $this->find($id);
|
||||
return $entity->getBoardId();
|
||||
@@ -77,7 +87,7 @@ class AclMapper extends DeckMapper implements IPermissionMapper {
|
||||
* @return Acl[]
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findByParticipant(int $type, string $participant): array {
|
||||
public function findByParticipant($type, $participant): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
|
||||
$qb->select('*')
|
||||
|
||||
@@ -77,41 +77,26 @@ class AssignmentMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
public function deleteByParticipantOnBoard(string $participant, int $boardId, $type = Assignment::TYPE_USER) {
|
||||
// Step 1: Get all card IDs for the board that have assignments for this participant
|
||||
// This avoids MySQL Error 1093 by separating the SELECT from the DELETE operation
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$cardIdQuery = $this->db->getQueryBuilder();
|
||||
$cardIdQuery->select('a.card_id')
|
||||
->from('deck_assigned_users', 'a')
|
||||
->innerJoin('a', 'deck_cards', 'c', 'c.id = a.card_id')
|
||||
->innerJoin('c', 'deck_stacks', 's', 's.id = c.stack_id')
|
||||
->where($cardIdQuery->expr()->eq('a.participant', $cardIdQuery->createNamedParameter($participant, IQueryBuilder::PARAM_STR)))
|
||||
->andWhere($cardIdQuery->expr()->eq('s.board_id', $cardIdQuery->createNamedParameter($boardId, IQueryBuilder::PARAM_INT)))
|
||||
->andWhere($cardIdQuery->expr()->eq('a.type', $cardIdQuery->createNamedParameter($type, IQueryBuilder::PARAM_INT)));
|
||||
|
||||
$result = $cardIdQuery->executeQuery();
|
||||
$cardIds = [];
|
||||
while ($row = $result->fetch()) {
|
||||
$cardIds[] = $row['card_id'];
|
||||
}
|
||||
$result->closeCursor();
|
||||
|
||||
// Step 2: If we have card IDs, delete the assignments
|
||||
if (!empty($cardIds)) {
|
||||
$deleteQuery = $this->db->getQueryBuilder();
|
||||
$deleteQuery->delete('deck_assigned_users')
|
||||
->where($deleteQuery->expr()->eq('participant', $deleteQuery->createNamedParameter($participant, IQueryBuilder::PARAM_STR)))
|
||||
->andWhere($deleteQuery->expr()->eq('type', $deleteQuery->createNamedParameter($type, IQueryBuilder::PARAM_INT)))
|
||||
->andWhere($deleteQuery->expr()->in('card_id', $deleteQuery->createNamedParameter($cardIds, IQueryBuilder::PARAM_INT_ARRAY)));
|
||||
$deleteQuery->executeStatement();
|
||||
}
|
||||
->where($cardIdQuery->expr()->eq('a.participant', $qb->createNamedParameter($participant, IQueryBuilder::PARAM_STR)))
|
||||
->andWhere($cardIdQuery->expr()->eq('s.board_id', $qb->createNamedParameter($boardId, IQueryBuilder::PARAM_INT)))
|
||||
->andWhere($cardIdQuery->expr()->eq('a.type', $qb->createNamedParameter($type, IQueryBuilder::PARAM_INT)));
|
||||
$qb->delete('deck_assigned_users')
|
||||
->where($qb->expr()->in('card_id', $qb->createFunction($cardIdQuery->getSQL()), IQueryBuilder::PARAM_INT_ARRAY));
|
||||
$qb->executeStatement();
|
||||
}
|
||||
|
||||
|
||||
public function isOwner(string $userId, int $id): bool {
|
||||
public function isOwner($userId, $id): bool {
|
||||
return $this->cardMapper->isOwner($userId, $id);
|
||||
}
|
||||
|
||||
public function findBoardId(int $id): ?int {
|
||||
public function findBoardId($id): ?int {
|
||||
return $this->cardMapper->findBoardId($id);
|
||||
}
|
||||
|
||||
@@ -123,9 +108,6 @@ class AssignmentMapper extends DeckMapper implements IPermissionMapper {
|
||||
* @throws NotFoundException
|
||||
*/
|
||||
public function insert(Entity $entity): Entity {
|
||||
if (!($entity instanceof Assignment)) {
|
||||
throw new \LogicException('Trying to insert a ' . get_class($entity) . ' in the assignment mapper');
|
||||
}
|
||||
$origin = $this->getOrigin($entity);
|
||||
if ($origin === null) {
|
||||
throw new NotFoundException('No origin found for assignment');
|
||||
@@ -144,7 +126,7 @@ class AssignmentMapper extends DeckMapper implements IPermissionMapper {
|
||||
});
|
||||
}
|
||||
|
||||
public function isUserAssigned(int $cardId, string $userId): bool {
|
||||
public function isUserAssigned($cardId, $userId): bool {
|
||||
$assignments = $this->findAll($cardId);
|
||||
foreach ($assignments as $assignment) {
|
||||
$origin = $this->getOrigin($assignment);
|
||||
|
||||
@@ -36,11 +36,13 @@ class AttachmentMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
* @return Attachment
|
||||
* @throws DoesNotExistException
|
||||
* @throws MultipleObjectsReturnedException
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function find(int $id): Attachment {
|
||||
public function find($id) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
->from($this->getTableName())
|
||||
@@ -50,11 +52,14 @@ class AttachmentMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $cardId
|
||||
* @param string $data
|
||||
* @return Attachment
|
||||
* @throws DoesNotExistException
|
||||
* @throws MultipleObjectsReturnedException
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findByData(int $cardId, string $data): Attachment {
|
||||
public function findByData($cardId, $data) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
->from($this->getTableName())
|
||||
@@ -65,10 +70,11 @@ class AttachmentMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $cardId
|
||||
* @return Entity[]
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findAll(int $cardId): array {
|
||||
public function findAll($cardId) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
->from($this->getTableName())
|
||||
@@ -80,9 +86,11 @@ class AttachmentMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Attachment[]
|
||||
* @param null $cardId
|
||||
* @param bool $withOffset
|
||||
* @return array
|
||||
*/
|
||||
public function findToDelete(?int $cardId = null, bool $withOffset = true): array {
|
||||
public function findToDelete($cardId = null, $withOffset = true) {
|
||||
// add buffer of 5 min
|
||||
$timeLimit = time() - (60 * 5);
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
@@ -104,8 +112,12 @@ class AttachmentMapper extends DeckMapper implements IPermissionMapper {
|
||||
|
||||
/**
|
||||
* Check if $userId is owner of Entity with $id
|
||||
*
|
||||
* @param $userId string userId
|
||||
* @param $id int|string unique entity identifier
|
||||
* @return boolean
|
||||
*/
|
||||
public function isOwner(string $userId, int $id): bool {
|
||||
public function isOwner($userId, $id): bool {
|
||||
try {
|
||||
$attachment = $this->find($id);
|
||||
return $this->cardMapper->isOwner($userId, $attachment->getCardId());
|
||||
@@ -118,10 +130,10 @@ class AttachmentMapper extends DeckMapper implements IPermissionMapper {
|
||||
/**
|
||||
* Query boardId for Entity of given $id
|
||||
*
|
||||
* @param $id int unique entity identifier
|
||||
* @param $id int|string unique entity identifier
|
||||
* @return int|null id of Board
|
||||
*/
|
||||
public function findBoardId(int $id): ?int {
|
||||
public function findBoardId($id): ?int {
|
||||
try {
|
||||
$attachment = $this->find($id);
|
||||
} catch (\Exception $e) {
|
||||
|
||||
@@ -10,20 +10,10 @@ namespace OCA\Deck\Db;
|
||||
/**
|
||||
* @method int getId()
|
||||
* @method string getTitle()
|
||||
* @method void setTitle(string $title)
|
||||
* @method int getShared()
|
||||
* @method void setShared(int $shared)
|
||||
* @method bool isArchived()
|
||||
* @method bool getArchived()
|
||||
* @method void setArchived(bool $archived)
|
||||
* @method int getDeletedAt()
|
||||
* @method void setDeletedAt(int $deletedAt)
|
||||
* @method int getLastModified()
|
||||
* @method void setLastModified(int $lastModified)
|
||||
* @method string getOwner()
|
||||
* @method void setOwner(string $owner)
|
||||
* @method string getColor()
|
||||
* @method void setColor(string $color)
|
||||
*/
|
||||
class Board extends RelationalEntity {
|
||||
protected $title;
|
||||
|
||||
@@ -469,16 +469,16 @@ class BoardMapper extends QBMapper implements IPermissionMapper {
|
||||
return parent::delete($entity);
|
||||
}
|
||||
|
||||
public function isOwner(string $userId, int $id): bool {
|
||||
public function isOwner($userId, $id): bool {
|
||||
$board = $this->find($id);
|
||||
return ($board->getOwner() === $userId);
|
||||
}
|
||||
|
||||
public function findBoardId(int $id): ?int {
|
||||
public function findBoardId($id): ?int {
|
||||
return $id;
|
||||
}
|
||||
|
||||
public function mapAcl(Acl &$acl): void {
|
||||
public function mapAcl(Acl &$acl) {
|
||||
$acl->resolveRelation('participant', function ($participant) use (&$acl) {
|
||||
if ($acl->getType() === Acl::PERMISSION_TYPE_USER) {
|
||||
if ($this->userManager->userExists($acl->getParticipant())) {
|
||||
|
||||
@@ -15,18 +15,13 @@ use Sabre\VObject\Component\VCalendar;
|
||||
|
||||
/**
|
||||
* @method string getTitle()
|
||||
* @method void setTitle(string $title)
|
||||
* @method string getDescription()
|
||||
* @method string getDescriptionPrev()
|
||||
* @method int getStackId()
|
||||
* @method void setStackId(int $stackId)
|
||||
* @method int getOrder()
|
||||
* @method void setOrder(int $order)
|
||||
* @method int getLastModified()
|
||||
* @method int getCreatedAt()
|
||||
* @method bool getArchived()
|
||||
* @method string getType()
|
||||
* @method void setType(string $type)
|
||||
* @method int getDeletedAt()
|
||||
* @method void setDeletedAt(int $deletedAt)
|
||||
* @method bool getNotified()
|
||||
@@ -73,8 +68,8 @@ class Card extends RelationalEntity {
|
||||
protected $createdAt;
|
||||
protected $labels;
|
||||
protected $assignedUsers;
|
||||
protected array $attachments = [];
|
||||
protected int $attachmentCount = 0;
|
||||
protected $attachments;
|
||||
protected $attachmentCount;
|
||||
protected $owner;
|
||||
protected $order;
|
||||
protected $archived = false;
|
||||
|
||||
@@ -86,15 +86,16 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
$updatedFields = $entity->getUpdatedFields();
|
||||
if (isset($updatedFields['duedate']) && $updatedFields['duedate']) {
|
||||
try {
|
||||
/** @var Card $existing */
|
||||
$existing = $this->find($entity->getId());
|
||||
if ($entity->getDueDate() !== $existing->getDueDate()) {
|
||||
if ($existing && $entity->getDuedate() !== $existing->getDuedate()) {
|
||||
$entity->setNotified(false);
|
||||
}
|
||||
// remove pending notifications
|
||||
$notification = $this->notificationManager->createNotification();
|
||||
$notification
|
||||
->setApp('deck')
|
||||
->setObject('card', (string)$entity->getId());
|
||||
->setObject('card', $entity->getId());
|
||||
$this->notificationManager->markProcessed($notification);
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
@@ -130,11 +131,7 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
return $card;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Card[]
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findAll($stackId, ?int $limit = null, int $offset = 0, int $since = -1) {
|
||||
public function findAll($stackId, $limit = null, $offset = null, $since = -1) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
->from('deck_cards')
|
||||
@@ -149,32 +146,6 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
return $this->findEntities($qb);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $stackIds
|
||||
* @return array<int, null|Card[]>
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findAllForStacks(array $stackIds, ?int $limit = null, int $offset = 0, int $since = -1): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
->from('deck_cards')
|
||||
->where($qb->expr()->in('stack_id', $qb->createNamedParameter($stackIds, IQueryBuilder::PARAM_INT_ARRAY)))
|
||||
->andWhere($qb->expr()->eq('archived', $qb->createNamedParameter(false, IQueryBuilder::PARAM_BOOL)))
|
||||
->andWhere($qb->expr()->eq('deleted_at', $qb->createNamedParameter(0, IQueryBuilder::PARAM_INT)))
|
||||
->andWhere($qb->expr()->gt('last_modified', $qb->createNamedParameter($since, IQueryBuilder::PARAM_INT)))
|
||||
->setMaxResults($limit)
|
||||
->setFirstResult($offset)
|
||||
->orderBy('order')
|
||||
->addOrderBy('id');
|
||||
|
||||
$rawCards = $this->findEntities($qb);
|
||||
$cards = array_fill_keys($stackIds, null);
|
||||
foreach ($rawCards as $card) {
|
||||
$cards[$card->getStackId()][] = $card;
|
||||
}
|
||||
return $cards;
|
||||
}
|
||||
|
||||
public function queryCardsByBoard(int $boardId): IQueryBuilder {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('c.*')
|
||||
@@ -193,10 +164,7 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
return $qb;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Card[]
|
||||
*/
|
||||
public function findToDelete(int $timeLimit, ?int $limit = null): array {
|
||||
public function findToDelete($timeLimit, $limit = null) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('id', 'title', 'owner', 'archived', 'deleted_at', 'last_modified')
|
||||
->from('deck_cards')
|
||||
@@ -207,10 +175,7 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
return $this->findEntities($qb);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Card[]
|
||||
*/
|
||||
public function findDeleted(int $boardId, ?int $limit = null, int $offset = 0): array {
|
||||
public function findDeleted($boardId, $limit = null, $offset = null) {
|
||||
$qb = $this->queryCardsByBoard($boardId);
|
||||
$qb->andWhere($qb->expr()->neq('c.deleted_at', $qb->createNamedParameter(0, IQueryBuilder::PARAM_INT)))
|
||||
->setMaxResults($limit)
|
||||
@@ -220,10 +185,7 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
return $this->findEntities($qb);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Card[]
|
||||
*/
|
||||
public function findCalendarEntries(int $boardId, ?int $limit = null, $offset = 0): array {
|
||||
public function findCalendarEntries($boardId, $limit = null, $offset = null) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('c.*')
|
||||
->from('deck_cards', 'c')
|
||||
@@ -278,11 +240,7 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
return $this->findEntities($qb);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $boardIds
|
||||
* @return Card[]
|
||||
*/
|
||||
public function findAllWithDue(array $boardIds): array {
|
||||
public function findAllWithDue(array $boardIds) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('c.*')
|
||||
->from('deck_cards', 'c')
|
||||
@@ -299,11 +257,7 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
return $this->findEntities($qb);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $boardIds
|
||||
* @return Card[]
|
||||
*/
|
||||
public function findToMeOrNotAssignedCards(array $boardIds, string $username): array {
|
||||
public function findToMeOrNotAssignedCards(array $boardIds, string $username) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('c.*')
|
||||
->from('deck_cards', 'c')
|
||||
@@ -325,10 +279,7 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
return $this->findEntities($qb);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Card[]
|
||||
*/
|
||||
public function findOverdue(): array {
|
||||
public function findOverdue() {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('id', 'title', 'duedate', 'notified')
|
||||
->from('deck_cards')
|
||||
@@ -340,9 +291,6 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
return $this->findEntities($qb);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Card[]
|
||||
*/
|
||||
public function findUnexposedDescriptionChances() {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('id', 'title', 'duedate', 'notified', 'description_prev', 'last_editor', 'description')
|
||||
@@ -351,9 +299,6 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
return $this->findEntities($qb);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Card[]
|
||||
*/
|
||||
public function search(array $boardIds, SearchQuery $query, ?int $limit = null, ?int $offset = null): array {
|
||||
$qb = $this->queryCardsByBoards($boardIds);
|
||||
$this->extendQueryByFilter($qb, $query);
|
||||
@@ -388,7 +333,7 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
$qb->andWhere($qb->expr()->lt('c.last_modified', $qb->createNamedParameter($offset, IQueryBuilder::PARAM_INT)));
|
||||
}
|
||||
|
||||
$result = $qb->executeQuery();
|
||||
$result = $qb->execute();
|
||||
$entities = [];
|
||||
while ($row = $result->fetch()) {
|
||||
$entities[] = Card::fromRow($row);
|
||||
@@ -431,7 +376,7 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
$qb->andWhere($qb->expr()->lt('comments.id', $qb->createNamedParameter($offset, IQueryBuilder::PARAM_INT)));
|
||||
}
|
||||
|
||||
$result = $qb->executeQuery();
|
||||
$result = $qb->execute();
|
||||
$entities = $result->fetchAll();
|
||||
$result->closeCursor();
|
||||
return $entities;
|
||||
@@ -527,7 +472,7 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
});
|
||||
$groups = $this->groupManager->search($assignment->getValue());
|
||||
foreach ($searchUsers as $user) {
|
||||
$groups = array_merge($groups, $this->groupManager->getUserGroups($user));
|
||||
$groups = array_merge($groups, $this->groupManager->getUserIdGroups($user->getUID()));
|
||||
}
|
||||
|
||||
$assignmentSearches = [];
|
||||
@@ -580,7 +525,7 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
if ($offset !== null) {
|
||||
$qb->setFirstResult($offset);
|
||||
}
|
||||
$result = $qb->executeQuery();
|
||||
$result = $qb->execute();
|
||||
$all = $result->fetchAll();
|
||||
$result->closeCursor();
|
||||
return $all;
|
||||
@@ -592,32 +537,32 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
return parent::delete($entity);
|
||||
}
|
||||
|
||||
public function deleteByStack($stackId): void {
|
||||
public function deleteByStack($stackId) {
|
||||
$cards = $this->findAllByStack($stackId);
|
||||
foreach ($cards as $card) {
|
||||
$this->delete($card);
|
||||
}
|
||||
}
|
||||
|
||||
public function assignLabel(int $card, int $label): void {
|
||||
public function assignLabel($card, $label) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->insert('deck_assigned_labels')
|
||||
->values([
|
||||
'label_id' => $qb->createNamedParameter($label, IQueryBuilder::PARAM_INT),
|
||||
'card_id' => $qb->createNamedParameter($card, IQueryBuilder::PARAM_INT),
|
||||
]);
|
||||
$qb->executeStatement();
|
||||
$qb->execute();
|
||||
}
|
||||
|
||||
public function removeLabel(int $card, int $label): void {
|
||||
public function removeLabel($card, $label) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->delete('deck_assigned_labels')
|
||||
->where($qb->expr()->eq('card_id', $qb->createNamedParameter($card, IQueryBuilder::PARAM_INT)))
|
||||
->andWhere($qb->expr()->eq('label_id', $qb->createNamedParameter($label, IQueryBuilder::PARAM_INT)));
|
||||
$qb->executeStatement();
|
||||
$qb->execute();
|
||||
}
|
||||
|
||||
public function isOwner(string $userId, int $id): bool {
|
||||
public function isOwner($userId, $id): bool {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('c.id')
|
||||
->from($this->getTableName(), 'c')
|
||||
@@ -629,7 +574,7 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
return count($qb->executeQuery()->fetchAll()) > 0;
|
||||
}
|
||||
|
||||
public function findBoardId(int $id): ?int {
|
||||
public function findBoardId($id): ?int {
|
||||
$result = $this->cache->get('findBoardId:' . $id);
|
||||
if ($result === null) {
|
||||
try {
|
||||
@@ -659,11 +604,13 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
public function transferOwnership(string $ownerId, string $newOwnerId, ?int $boardId = null): void {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->update($this->getTableName())
|
||||
->set('owner', $qb->createNamedParameter($newOwnerId, IQueryBuilder::PARAM_STR))
|
||||
->where('owner', $qb->createNamedParameter($ownerId, IQueryBuilder::PARAM_STR))
|
||||
->executeStatement();
|
||||
$params = [
|
||||
'owner' => $ownerId,
|
||||
'newOwner' => $newOwnerId
|
||||
];
|
||||
$sql = "UPDATE `*PREFIX*{$this->tableName}` SET `owner` = :newOwner WHERE `owner` = :owner";
|
||||
$stmt = $this->db->executeQuery($sql, $params);
|
||||
$stmt->closeCursor();
|
||||
}
|
||||
|
||||
public function remapCardOwner(int $boardId, string $userId, string $newUserId): void {
|
||||
|
||||
@@ -19,11 +19,12 @@ use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
abstract class DeckMapper extends QBMapper {
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @return T
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
*/
|
||||
public function find(int $id): Entity {
|
||||
public function find($id) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
->from($this->getTableName())
|
||||
@@ -36,7 +37,7 @@ abstract class DeckMapper extends QBMapper {
|
||||
* Helper function to split passed array into chunks of 1000 elements and
|
||||
* call a given callback for fetching query results
|
||||
*
|
||||
* Can be useful to limit to 1000 results per query for oracle compatibility
|
||||
* Can be useful to limit to 1000 results per query for oracle compatiblity
|
||||
* but still iterate over all results
|
||||
*/
|
||||
public function chunkQuery(array $ids, callable $callback): Generator {
|
||||
|
||||
@@ -8,25 +8,22 @@
|
||||
|
||||
namespace OCA\Deck\Db;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
interface IPermissionMapper {
|
||||
|
||||
/**
|
||||
* Check if $userId is owner of Entity with $id
|
||||
*
|
||||
* @param $userId string userId
|
||||
* @param $id int unique entity identifier
|
||||
* @param $id int|string unique entity identifier
|
||||
* @return boolean
|
||||
*/
|
||||
public function isOwner(string $userId, int $id): bool;
|
||||
public function isOwner($userId, $id): bool;
|
||||
|
||||
/**
|
||||
* Query boardId for Entity of given $id
|
||||
*
|
||||
* @param $id int unique entity identifier
|
||||
* @return ?int id of Board
|
||||
* @param $id int|string unique entity identifier
|
||||
* @return int|null id of Board
|
||||
*/
|
||||
public function findBoardId(int $id): ?int;
|
||||
public function findBoardId($id): ?int;
|
||||
}
|
||||
|
||||
@@ -8,16 +8,7 @@
|
||||
namespace OCA\Deck\Db;
|
||||
|
||||
/**
|
||||
* @method string getTitle()
|
||||
* @method void setTitle(string $title)
|
||||
* @method string getColor()
|
||||
* @method void setColor(string $color)
|
||||
* @method int getBoardId()
|
||||
* @method void setBoardId(int $boardId)
|
||||
* @method int getCardId()
|
||||
* @method void setCardId(int $cardId)
|
||||
* @method int getLastModified()
|
||||
* @method void setLastModified(int $lastModified)
|
||||
* @method getTitle(): string
|
||||
*/
|
||||
class Label extends RelationalEntity {
|
||||
protected $title;
|
||||
@@ -33,7 +24,7 @@ class Label extends RelationalEntity {
|
||||
$this->addType('lastModified', 'integer');
|
||||
}
|
||||
|
||||
public function getETag(): string {
|
||||
public function getETag() {
|
||||
return md5((string)$this->getLastModified());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,10 +20,13 @@ class LabelMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param numeric $boardId
|
||||
* @param int|null $limit
|
||||
* @param int|null $offset
|
||||
* @return Label[]
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findAll(int $boardId, ?int $limit = null, int $offset = 0): array {
|
||||
public function findAll($boardId, $limit = null, $offset = null): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
->from($this->getTableName())
|
||||
@@ -41,10 +44,13 @@ class LabelMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param numeric $cardId
|
||||
* @param int|null $limit
|
||||
* @param int|null $offset
|
||||
* @return Label[]
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findAssignedLabelsForCard(int $cardId, ?int $limit = null, int $offset = 0): array {
|
||||
public function findAssignedLabelsForCard($cardId, $limit = null, $offset = null): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('l.*', 'card_id')
|
||||
->from($this->getTableName(), 'l')
|
||||
@@ -57,7 +63,7 @@ class LabelMapper extends DeckMapper implements IPermissionMapper {
|
||||
return $this->findEntities($qb);
|
||||
}
|
||||
|
||||
public function findAssignedLabelsForCards(array $cardIds, ?int $limit = null, int $offset = 0): array {
|
||||
public function findAssignedLabelsForCards($cardIds, $limit = null, $offset = null): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('l.*', 'card_id')
|
||||
->from($this->getTableName(), 'l')
|
||||
@@ -71,10 +77,13 @@ class LabelMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param numeric $boardId
|
||||
* @param int|null $limit
|
||||
* @param int|null $offset
|
||||
* @return Label[]
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findAssignedLabelsForBoard(int $boardId, ?int $limit = null, int $offset = 0): array {
|
||||
public function findAssignedLabelsForBoard($boardId, $limit = null, $offset = null): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('l.id as id', 'l.title as title', 'l.color as color')
|
||||
->selectAlias('c.id', 'card_id')
|
||||
@@ -104,10 +113,11 @@ class LabelMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, list<Label>>
|
||||
* @param numeric $boardId
|
||||
* @return array
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function getAssignedLabelsForBoard(int $boardId): array {
|
||||
public function getAssignedLabelsForBoard($boardId) {
|
||||
$labels = $this->findAssignedLabelsForBoard($boardId);
|
||||
$result = [];
|
||||
foreach ($labels as $label) {
|
||||
@@ -120,9 +130,11 @@ class LabelMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param numeric $labelId
|
||||
* @return void
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function deleteLabelAssignments(int $labelId): void {
|
||||
public function deleteLabelAssignments($labelId) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->delete('deck_assigned_labels')
|
||||
->where($qb->expr()->eq('label_id', $qb->createNamedParameter($labelId, IQueryBuilder::PARAM_INT)));
|
||||
@@ -130,9 +142,11 @@ class LabelMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param numeric $cardId
|
||||
* @return void
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function deleteLabelAssignmentsForCard(int $cardId): void {
|
||||
public function deleteLabelAssignmentsForCard($cardId) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->delete('deck_assigned_labels')
|
||||
->where($qb->expr()->eq('card_id', $qb->createNamedParameter($cardId, IQueryBuilder::PARAM_INT)));
|
||||
@@ -140,25 +154,33 @@ class LabelMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $userId
|
||||
* @param numeric $labelId
|
||||
* @return bool
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function isOwner(string $userId, int $id): bool {
|
||||
public function isOwner($userId, $labelId): bool {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('l.id')
|
||||
->from($this->getTableName(), 'l')
|
||||
->innerJoin('l', 'deck_boards', 'b', 'l.board_id = b.id')
|
||||
->where($qb->expr()->eq('l.id', $qb->createNamedParameter($id, IQueryBuilder::PARAM_INT)))
|
||||
->where($qb->expr()->eq('l.id', $qb->createNamedParameter($labelId, IQueryBuilder::PARAM_INT)))
|
||||
->andWhere($qb->expr()->eq('b.owner', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR)));
|
||||
|
||||
return count($qb->executeQuery()->fetchAll()) > 0;
|
||||
}
|
||||
|
||||
public function findBoardId(int $id): ?int {
|
||||
/**
|
||||
* @param numeric $id
|
||||
* @return int|null
|
||||
*/
|
||||
public function findBoardId($id): ?int {
|
||||
try {
|
||||
$entity = $this->find($id);
|
||||
return $entity->getBoardId();
|
||||
} catch (DoesNotExistException|MultipleObjectsReturnedException) {
|
||||
return null;
|
||||
} catch (DoesNotExistException $e) {
|
||||
} catch (MultipleObjectsReturnedException $e) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,17 +11,10 @@ use Sabre\VObject\Component\VCalendar;
|
||||
|
||||
/**
|
||||
* @method int getId()
|
||||
* @method string getTitle()
|
||||
* @method void setTitle(string $title)
|
||||
* @method int getBoardId()
|
||||
* @method void setBoardId(int $boardId)
|
||||
* @method int getDeletedAt()
|
||||
* @method void setDeletedAt(int $deletedAt)
|
||||
* @method int getLastModified()
|
||||
* @method void setLastModified(int $lastModified)
|
||||
* @method \int getOrder()
|
||||
* @method void setOrder(int $order)
|
||||
* @method Card[] getCards()
|
||||
* @method int getOrder()
|
||||
*/
|
||||
class Stack extends RelationalEntity {
|
||||
protected $title;
|
||||
|
||||
@@ -35,11 +35,13 @@ class StackMapper extends DeckMapper implements IPermissionMapper {
|
||||
|
||||
|
||||
/**
|
||||
* @param numeric $id
|
||||
* @return Stack
|
||||
* @throws DoesNotExistException
|
||||
* @throws MultipleObjectsReturnedException
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function find(int $id): Stack {
|
||||
public function find($id): Stack {
|
||||
if (isset($this->stackCache[(string)$id])) {
|
||||
return $this->stackCache[(string)$id];
|
||||
}
|
||||
@@ -54,9 +56,11 @@ class StackMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $cardId
|
||||
* @return Stack|null
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findStackFromCardId(int $cardId): ?Stack {
|
||||
public function findStackFromCardId($cardId): ?Stack {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('s.*')
|
||||
->from($this->getTableName(), 's')
|
||||
@@ -72,10 +76,13 @@ class StackMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param numeric $boardId
|
||||
* @param int|null $limit
|
||||
* @param int|null $offset
|
||||
* @return Stack[]
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findAll(int $boardId, ?int $limit = null, int $offset = 0): array {
|
||||
public function findAll($boardId, $limit = null, $offset = null): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
->from($this->getTableName())
|
||||
@@ -88,9 +95,13 @@ class StackMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param numeric $boardId
|
||||
* @param int|null $limit
|
||||
* @param int|null $offset
|
||||
* @return Stack[]
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findDeleted(int $boardId, ?int $limit = null, int $offset = 0): array {
|
||||
public function findDeleted($boardId, $limit = null, $offset = null) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
->from($this->getTableName())
|
||||
@@ -116,9 +127,12 @@ class StackMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param numeric $userId
|
||||
* @param numeric $stackId
|
||||
* @return bool
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function isOwner(string $userId, int $id): bool {
|
||||
public function isOwner($userId, $id): bool {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('s.id')
|
||||
->from($this->getTableName(), 's')
|
||||
@@ -130,9 +144,11 @@ class StackMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param numeric $id
|
||||
* @return int|null
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findBoardId(int $id): ?int {
|
||||
public function findBoardId($id): ?int {
|
||||
$result = $this->cache->get('findBoardId:' . $id);
|
||||
if ($result !== null) {
|
||||
return $result !== false ? $result : null;
|
||||
@@ -149,10 +165,6 @@ class StackMapper extends DeckMapper implements IPermissionMapper {
|
||||
return $result !== false ? $result : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<Stack>
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findToDelete(): array {
|
||||
// add buffer of 5 min
|
||||
$timeLimit = time() - (60 * 5);
|
||||
|
||||
@@ -35,10 +35,6 @@ class BeforeTemplateRenderedListener implements IEventListener {
|
||||
Util::addStyle('deck', 'deck');
|
||||
|
||||
$pathInfo = $this->request->getPathInfo();
|
||||
if (!$pathInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (str_starts_with($pathInfo, '/apps/calendar')) {
|
||||
Util::addScript('deck', 'deck-calendar');
|
||||
}
|
||||
|
||||
@@ -18,10 +18,14 @@ use OCP\EventDispatcher\IEventListener;
|
||||
/** @template-implements IEventListener<Event|AclDeletedEvent|AclCreatedEvent> */
|
||||
class ResourceListener implements IEventListener {
|
||||
|
||||
public function __construct(
|
||||
private readonly IManager $resourceManager,
|
||||
private readonly ResourceProviderCard $resourceProviderCard,
|
||||
) {
|
||||
/** @var IManager */
|
||||
private $resourceManager;
|
||||
/** @var ResourceProviderCard */
|
||||
private $resourceProviderCard;
|
||||
|
||||
public function __construct(IManager $resourceManager, ResourceProviderCard $resourceProviderCard) {
|
||||
$this->resourceManager = $resourceManager;
|
||||
$this->resourceProviderCard = $resourceProviderCard;
|
||||
}
|
||||
|
||||
public function handle(Event $event): void {
|
||||
@@ -34,10 +38,10 @@ class ResourceListener implements IEventListener {
|
||||
$this->resourceManager->invalidateAccessCacheForProvider($this->resourceProviderCard);
|
||||
|
||||
try {
|
||||
$resource = $this->resourceManager->getResourceForUser(ResourceProvider::RESOURCE_TYPE, (string)$boardId, null);
|
||||
$resource = $this->resourceManager->getResourceForUser(ResourceProvider::RESOURCE_TYPE, $boardId, null);
|
||||
$this->resourceManager->invalidateAccessCacheForResource($resource);
|
||||
} catch (ResourceException $e) {
|
||||
// If there is no resource we don't need to invalidate anything, but this should not happen anyway
|
||||
// If there is no resource we don't need to invalidate anything, but this should not happen anyways
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ use OCA\Deck\Db\Board;
|
||||
class BoardSummary extends Board {
|
||||
private Board $board;
|
||||
|
||||
/** @psalm-suppress ConstructorSignatureMismatch */
|
||||
public function __construct(Board $board) {
|
||||
parent::__construct();
|
||||
$this->board = $board;
|
||||
@@ -28,7 +27,7 @@ class BoardSummary extends Board {
|
||||
return $this->board->getter($name);
|
||||
}
|
||||
|
||||
public function __call($methodName, $args) {
|
||||
return $this->board->__call($methodName, $args);
|
||||
public function __call($name, $arguments) {
|
||||
return $this->board->__call($name, $arguments);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ class CardDetails extends Card {
|
||||
private ?Board $board;
|
||||
private ?Reference $referenceData = null;
|
||||
|
||||
/** @psalm-suppress ConstructorSignatureMismatch */
|
||||
public function __construct(Card $card, ?Board $board = null) {
|
||||
parent::__construct();
|
||||
$this->card = $card;
|
||||
|
||||
@@ -95,7 +95,7 @@ class NotificationHelper {
|
||||
|
||||
$shouldNotify = $notificationSetting === ConfigService::SETTING_BOARD_NOTIFICATION_DUE_ALL;
|
||||
|
||||
if ($user->getUID() === $board->getOwner() && count($board->getAcl() ?? []) === 0) {
|
||||
if ($user->getUID() === $board->getOwner() && count($board->getAcl()) === 0) {
|
||||
// Notify if all or assigned is configured for unshared boards
|
||||
$shouldNotify = true;
|
||||
} elseif ($notificationSetting === ConfigService::SETTING_BOARD_NOTIFICATION_DUE_ASSIGNED && $this->assignmentMapper->isUserAssigned($card->getId(), $user->getUID())) {
|
||||
|
||||
@@ -64,7 +64,6 @@ class BoardReferenceProvider implements IReferenceProvider {
|
||||
$reference = new Reference($referenceText);
|
||||
$reference->setTitle($this->l10n->t('Deck board') . ': ' . $board['title']);
|
||||
$ownerDisplayName = $board['owner']['displayname'] ?? $board['owner']['uid'] ?? '???';
|
||||
// TRANSLATORS Owned by {boardOwnerName}
|
||||
$reference->setDescription($this->l10n->t('Owned by %1$s', [$ownerDisplayName]));
|
||||
$imageUrl = $this->urlGenerator->getAbsoluteURL(
|
||||
$this->urlGenerator->imagePath(Application::APP_ID, 'deck-dark.svg')
|
||||
|
||||
@@ -90,7 +90,6 @@ class CommentReferenceProvider implements IReferenceProvider {
|
||||
$reference->setTitle($comment['message']);
|
||||
$boardOwnerDisplayName = $board['owner']['displayname'] ?? $board['owner']['uid'] ?? '???';
|
||||
$reference->setDescription(
|
||||
// TRANSLATORS From {userName}, in {boardTitle}/{stackTitle}, owned by {boardOwnerName}
|
||||
$this->l10n->t('From %1$s, in %2$s/%3$s, owned by %4$s', [
|
||||
$comment['actorDisplayName'],
|
||||
$board['title'],
|
||||
|
||||
@@ -21,6 +21,7 @@ use OCA\Deck\NotFoundException;
|
||||
use OCA\Deck\Notification\NotificationHelper;
|
||||
use OCA\Deck\Validators\AssignmentServiceValidator;
|
||||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
use OCP\AppFramework\Db\Entity;
|
||||
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
|
||||
use OCP\EventDispatcher\IEventDispatcher;
|
||||
|
||||
@@ -91,12 +92,15 @@ class AssignmentService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $cardId
|
||||
* @param $userId
|
||||
* @return bool|null|Entity
|
||||
* @throws BadRequestException
|
||||
* @throws NoPermissionException
|
||||
* @throws MultipleObjectsReturnedException
|
||||
* @throws DoesNotExistException
|
||||
*/
|
||||
public function assignUser(int $cardId, string $userId, int $type = Assignment::TYPE_USER): Assignment {
|
||||
public function assignUser($cardId, $userId, int $type = Assignment::TYPE_USER) {
|
||||
$this->assignmentServiceValidator->check(compact('cardId', 'userId'));
|
||||
|
||||
if ($type !== Assignment::TYPE_USER && $type !== Assignment::TYPE_GROUP) {
|
||||
@@ -140,13 +144,16 @@ class AssignmentService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $cardId
|
||||
* @param $userId
|
||||
* @return Entity
|
||||
* @throws BadRequestException
|
||||
* @throws NotFoundException
|
||||
* @throws NoPermissionException
|
||||
* @throws DoesNotExistException
|
||||
* @throws MultipleObjectsReturnedException
|
||||
*/
|
||||
public function unassignUser(int $cardId, string $userId, int $type = 0): Assignment {
|
||||
public function unassignUser($cardId, $userId, $type = 0) {
|
||||
$this->assignmentServiceValidator->check(compact('cardId', 'userId'));
|
||||
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT);
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@ use OCP\AppFramework\Db\IMapperException;
|
||||
use OCP\AppFramework\Http\Response;
|
||||
use OCP\IL10N;
|
||||
use OCP\IUserManager;
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
|
||||
class AttachmentService {
|
||||
private $attachmentMapper;
|
||||
@@ -81,16 +80,20 @@ class AttachmentService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerExceptionInterface
|
||||
* @param string $type
|
||||
* @param string $class
|
||||
* @throws \OCP\AppFramework\QueryException
|
||||
*/
|
||||
public function registerAttachmentService(string $type, string $class): void {
|
||||
$this->services[$type] = $this->application->getContainer()->get($class);
|
||||
public function registerAttachmentService($type, $class) {
|
||||
$this->services[$type] = $this->application->getContainer()->query($class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
* @return IAttachmentService
|
||||
* @throws InvalidAttachmentType
|
||||
*/
|
||||
public function getService(string $type): IAttachmentService {
|
||||
public function getService($type) {
|
||||
if (isset($this->services[$type])) {
|
||||
return $this->services[$type];
|
||||
}
|
||||
@@ -98,11 +101,16 @@ class AttachmentService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Attachment[]
|
||||
* @param $cardId
|
||||
* @return array
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function findAll(int $cardId, bool $withDeleted = false): array {
|
||||
public function findAll($cardId, $withDeleted = false) {
|
||||
if (is_numeric($cardId) === false) {
|
||||
throw new BadRequestException('card id must be a number');
|
||||
}
|
||||
|
||||
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_READ);
|
||||
|
||||
$attachments = $this->attachmentMapper->findAll($cardId);
|
||||
@@ -114,7 +122,7 @@ class AttachmentService {
|
||||
/** @var IAttachmentService $service */
|
||||
$service = $this->getService($attachmentType);
|
||||
if ($service instanceof ICustomAttachmentService) {
|
||||
$attachments = array_merge($attachments, $service->listAttachments($cardId));
|
||||
$attachments = array_merge($attachments, $service->listAttachments((int)$cardId));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,40 +140,49 @@ class AttachmentService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $cardId
|
||||
* @return int|mixed
|
||||
* @throws BadRequestException
|
||||
* @throws InvalidAttachmentType
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function count(int $cardId): int {
|
||||
$count = $this->attachmentCacheHelper->getAttachmentCount($cardId);
|
||||
public function count($cardId) {
|
||||
if (is_numeric($cardId) === false) {
|
||||
throw new BadRequestException('card id must be a number');
|
||||
}
|
||||
|
||||
$count = $this->attachmentCacheHelper->getAttachmentCount((int)$cardId);
|
||||
if ($count === null) {
|
||||
$count = count($this->attachmentMapper->findAll($cardId));
|
||||
|
||||
foreach (array_keys($this->services) as $attachmentType) {
|
||||
$service = $this->getService($attachmentType);
|
||||
if ($service instanceof ICustomAttachmentService) {
|
||||
$count += $service->getAttachmentCount($cardId);
|
||||
$count += $service->getAttachmentCount((int)$cardId);
|
||||
}
|
||||
}
|
||||
|
||||
$this->attachmentCacheHelper->setAttachmentCount($cardId, $count);
|
||||
$this->attachmentCacheHelper->setAttachmentCount((int)$cardId, $count);
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $cardId
|
||||
* @param $type
|
||||
* @param $data
|
||||
* @return Attachment|\OCP\AppFramework\Db\Entity
|
||||
* @throws NoPermissionException
|
||||
* @throws StatusException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function create(int $cardId, string $type, string $data) {
|
||||
public function create($cardId, $type, $data) {
|
||||
$this->attachmentServiceValidator->check(compact('cardId', 'type'));
|
||||
|
||||
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT);
|
||||
|
||||
$this->attachmentCacheHelper->clearAttachmentCount($cardId);
|
||||
$this->attachmentCacheHelper->clearAttachmentCount((int)$cardId);
|
||||
$attachment = new Attachment();
|
||||
$attachment->setCardId($cardId);
|
||||
$attachment->setType($type);
|
||||
@@ -201,10 +218,12 @@ class AttachmentService {
|
||||
/**
|
||||
* Display the attachment
|
||||
*
|
||||
* @param $attachmentId
|
||||
* @return Response
|
||||
* @throws NoPermissionException
|
||||
* @throws NotFoundException
|
||||
*/
|
||||
public function display(int $cardId, int $attachmentId, string $type = 'deck_file'): Response {
|
||||
public function display($cardId, $attachmentId, $type = 'deck_file') {
|
||||
try {
|
||||
$service = $this->getService($type);
|
||||
} catch (InvalidAttachmentType $e) {
|
||||
@@ -238,10 +257,13 @@ class AttachmentService {
|
||||
/**
|
||||
* Update an attachment with custom data
|
||||
*
|
||||
* @param $attachmentId
|
||||
* @param $data
|
||||
* @return mixed
|
||||
* @throws BadRequestException
|
||||
* @throws NoPermissionException
|
||||
*/
|
||||
public function update(int $cardId, int $attachmentId, string $data, string $type = 'deck_file'): Attachment {
|
||||
public function update($cardId, $attachmentId, $data, $type = 'deck_file') {
|
||||
$this->attachmentServiceValidator->check(compact('cardId', 'type', 'data'));
|
||||
|
||||
try {
|
||||
@@ -362,6 +384,8 @@ class AttachmentService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Attachment $attachment
|
||||
* @return Attachment
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
private function addCreator(Attachment $attachment): Attachment {
|
||||
|
||||
@@ -75,6 +75,8 @@ class BoardService {
|
||||
|
||||
/**
|
||||
* Set a different user than the current one, e.g. when no user is available in occ
|
||||
*
|
||||
* @param string $userId
|
||||
*/
|
||||
public function setUserId(string $userId): void {
|
||||
$this->userId = $userId;
|
||||
@@ -115,18 +117,22 @@ class BoardService {
|
||||
}
|
||||
|
||||
$this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_READ);
|
||||
/** @var Board $board */
|
||||
$board = $this->boardMapper->find($boardId, true, true, $allowDeleted);
|
||||
[$board] = $this->enrichBoards([$board], $fullDetails);
|
||||
return $board;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $mapper
|
||||
* @param $id
|
||||
* @return bool
|
||||
* @throws DoesNotExistException
|
||||
* @throws NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function isArchived($mapper, int $id): bool {
|
||||
public function isArchived($mapper, $id) {
|
||||
$this->boardServiceValidator->check(compact('id'));
|
||||
|
||||
try {
|
||||
@@ -145,12 +151,15 @@ class BoardService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $mapper
|
||||
* @param $id
|
||||
* @return bool
|
||||
* @throws DoesNotExistException
|
||||
* @throws NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function isDeleted($mapper, int $id): bool {
|
||||
public function isDeleted($mapper, $id) {
|
||||
$this->boardServiceValidator->check(compact('mapper', 'id'));
|
||||
|
||||
try {
|
||||
@@ -170,9 +179,13 @@ class BoardService {
|
||||
|
||||
|
||||
/**
|
||||
* @param $title
|
||||
* @param $userId
|
||||
* @param $color
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function create(string $title, string $userId, string $color): Board {
|
||||
public function create($title, $userId, $color) {
|
||||
$this->boardServiceValidator->check(compact('title', 'userId', 'color'));
|
||||
|
||||
if (!$this->permissionService->canCreate()) {
|
||||
@@ -183,8 +196,7 @@ class BoardService {
|
||||
$board->setTitle($title);
|
||||
$board->setOwner($userId);
|
||||
$board->setColor($color);
|
||||
/** @var Board $board */
|
||||
$board = $this->boardMapper->insert($board);
|
||||
$new_board = $this->boardMapper->insert($board);
|
||||
|
||||
// create new labels
|
||||
$default_labels = [
|
||||
@@ -198,31 +210,33 @@ class BoardService {
|
||||
$label = new Label();
|
||||
$label->setColor($labelColor);
|
||||
$label->setTitle($labelTitle);
|
||||
$label->setBoardId($board->getId());
|
||||
$label->setBoardId($new_board->getId());
|
||||
$labels[] = $this->labelMapper->insert($label);
|
||||
}
|
||||
$board->setLabels($labels);
|
||||
$this->boardMapper->mapOwner($board);
|
||||
$permissions = $this->permissionService->matchPermissions($board);
|
||||
$board->setPermissions([
|
||||
$new_board->setLabels($labels);
|
||||
$this->boardMapper->mapOwner($new_board);
|
||||
$permissions = $this->permissionService->matchPermissions($new_board);
|
||||
$new_board->setPermissions([
|
||||
'PERMISSION_READ' => $permissions[Acl::PERMISSION_READ] ?? false,
|
||||
'PERMISSION_EDIT' => $permissions[Acl::PERMISSION_EDIT] ?? false,
|
||||
'PERMISSION_MANAGE' => $permissions[Acl::PERMISSION_MANAGE] ?? false,
|
||||
'PERMISSION_SHARE' => $permissions[Acl::PERMISSION_SHARE] ?? false
|
||||
]);
|
||||
$this->activityManager->triggerEvent(ActivityManager::DECK_OBJECT_BOARD, $board, ActivityManager::SUBJECT_BOARD_CREATE, [], $userId);
|
||||
$this->changeHelper->boardChanged($board->getId());
|
||||
$this->activityManager->triggerEvent(ActivityManager::DECK_OBJECT_BOARD, $new_board, ActivityManager::SUBJECT_BOARD_CREATE, [], $userId);
|
||||
$this->changeHelper->boardChanged($new_board->getId());
|
||||
|
||||
return $board;
|
||||
return $new_board;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @return Board
|
||||
* @throws DoesNotExistException
|
||||
* @throws NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function delete(int $id): Board {
|
||||
public function delete($id) {
|
||||
$this->boardServiceValidator->check(compact('id'));
|
||||
|
||||
$this->permissionService->checkPermission($this->boardMapper, $id, Acl::PERMISSION_MANAGE);
|
||||
@@ -239,11 +253,13 @@ class BoardService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws DoesNotExistException
|
||||
* @throws NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
*/
|
||||
public function deleteUndo(int $id): Board {
|
||||
public function deleteUndo($id) {
|
||||
$this->boardServiceValidator->check(compact('id'));
|
||||
|
||||
$this->permissionService->checkPermission($this->boardMapper, $id, Acl::PERMISSION_MANAGE);
|
||||
@@ -257,12 +273,14 @@ class BoardService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws DoesNotExistException
|
||||
* @throws NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function deleteForce(int $id): Board {
|
||||
public function deleteForce($id) {
|
||||
$this->boardServiceValidator->check(compact('id'));
|
||||
|
||||
$this->permissionService->checkPermission($this->boardMapper, $id, Acl::PERMISSION_MANAGE);
|
||||
@@ -273,12 +291,17 @@ class BoardService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @param $title
|
||||
* @param $color
|
||||
* @param $archived
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws DoesNotExistException
|
||||
* @throws NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function update(int $id, string $title, string $color, bool $archived): Board {
|
||||
public function update($id, $title, $color, $archived) {
|
||||
$this->boardServiceValidator->check(compact('id', 'title', 'color', 'archived'));
|
||||
|
||||
$this->permissionService->checkPermission($this->boardMapper, $id, Acl::PERMISSION_MANAGE);
|
||||
@@ -297,7 +320,7 @@ class BoardService {
|
||||
return $board;
|
||||
}
|
||||
|
||||
private function applyPermissions(int $boardId, bool $edit, bool $share, bool $manage, ?Acl $oldAcl = null): array {
|
||||
private function applyPermissions($boardId, $edit, $share, $manage, $oldAcl = null) {
|
||||
try {
|
||||
$this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_MANAGE);
|
||||
} catch (NoPermissionException $e) {
|
||||
@@ -309,7 +332,7 @@ class BoardService {
|
||||
return [$edit, $share, $manage];
|
||||
}
|
||||
|
||||
public function enrichWithBoardSettings(Board $board): void {
|
||||
public function enrichWithBoardSettings(Board $board) {
|
||||
$globalCalendarConfig = (bool)$this->config->getUserValue($this->userId, Application::APP_ID, 'calendar', true);
|
||||
$settings = [
|
||||
'notify-due' => $this->config->getUserValue($this->userId, Application::APP_ID, 'board:' . $board->getId() . ':notify-due', ConfigService::SETTING_BOARD_NOTIFICATION_DUE_ASSIGNED),
|
||||
@@ -318,7 +341,7 @@ class BoardService {
|
||||
$board->setSettings($settings);
|
||||
}
|
||||
|
||||
public function enrichWithActiveSessions(Board $board): void {
|
||||
public function enrichWithActiveSessions(Board $board) {
|
||||
$sessions = $this->sessionMapper->findAllActive($board->getId());
|
||||
|
||||
$board->setActiveSessions(array_values(
|
||||
@@ -331,11 +354,17 @@ class BoardService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Acl::PERMISSION_TYPE_* $type
|
||||
* @param $boardId
|
||||
* @param $type
|
||||
* @param $participant
|
||||
* @param $edit
|
||||
* @param $share
|
||||
* @param $manage
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws BadRequestException
|
||||
* @throws NoPermissionException
|
||||
*/
|
||||
public function addAcl(int $boardId, int $type, $participant, bool $edit, bool $share, bool $manage): Acl {
|
||||
public function addAcl($boardId, $type, $participant, $edit, $share, $manage) {
|
||||
$this->boardServiceValidator->check(compact('boardId', 'type', 'participant', 'edit', 'share', 'manage'));
|
||||
|
||||
$this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_SHARE);
|
||||
@@ -371,12 +400,17 @@ class BoardService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @param $edit
|
||||
* @param $share
|
||||
* @param $manage
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws DoesNotExistException
|
||||
* @throws NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function updateAcl(int $id, bool $edit, bool $share, bool $manage): Acl {
|
||||
public function updateAcl($id, $edit, $share, $manage) {
|
||||
$this->boardServiceValidator->check(compact('id', 'edit', 'share', 'manage'));
|
||||
|
||||
$this->permissionService->checkPermission($this->aclMapper, $id, Acl::PERMISSION_SHARE);
|
||||
@@ -388,12 +422,12 @@ class BoardService {
|
||||
$acl->setPermissionShare($share);
|
||||
$acl->setPermissionManage($manage);
|
||||
$this->boardMapper->mapAcl($acl);
|
||||
$acl = $this->aclMapper->update($acl);
|
||||
$board = $this->aclMapper->update($acl);
|
||||
$this->changeHelper->boardChanged($acl->getBoardId());
|
||||
|
||||
$this->eventDispatcher->dispatchTyped(new AclUpdatedEvent($acl));
|
||||
|
||||
return $acl;
|
||||
return $board;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -545,23 +579,27 @@ class BoardService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @return Board
|
||||
* @throws DoesNotExistException
|
||||
* @throws NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function export(int $id): Board {
|
||||
public function export($id) : Board {
|
||||
if (is_numeric($id) === false) {
|
||||
throw new BadRequestException('board id must be a number');
|
||||
}
|
||||
|
||||
$this->permissionService->checkPermission($this->boardMapper, $id, Acl::PERMISSION_READ);
|
||||
$board = $this->boardMapper->find($id);
|
||||
$board = $this->boardMapper->find((int)$id);
|
||||
$this->enrichWithCards($board);
|
||||
$this->enrichWithLabels($board);
|
||||
|
||||
return $board;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Board[] $boards
|
||||
* @return Board[]
|
||||
*/
|
||||
/** @param Board[] $boards */
|
||||
private function enrichBoards(array $boards, bool $fullDetails = true): array {
|
||||
$result = [];
|
||||
foreach ($boards as $board) {
|
||||
@@ -677,8 +715,8 @@ class BoardService {
|
||||
}
|
||||
}
|
||||
|
||||
private function enrichWithStacks(Board $board): void {
|
||||
$stacks = $this->stackMapper->findAll($board->getId());
|
||||
private function enrichWithStacks($board, $since = -1) {
|
||||
$stacks = $this->stackMapper->findAll($board->getId(), null, null, $since);
|
||||
|
||||
if (\count($stacks) === 0) {
|
||||
return;
|
||||
@@ -687,8 +725,8 @@ class BoardService {
|
||||
$board->setStacks($stacks);
|
||||
}
|
||||
|
||||
private function enrichWithLabels(Board $board): void {
|
||||
$labels = $this->labelMapper->findAll($board->getId());
|
||||
private function enrichWithLabels($board, $since = -1) {
|
||||
$labels = $this->labelMapper->findAll($board->getId(), null, null, $since);
|
||||
|
||||
if (\count($labels) === 0) {
|
||||
return;
|
||||
@@ -697,7 +735,7 @@ class BoardService {
|
||||
$board->setLabels($labels);
|
||||
}
|
||||
|
||||
private function enrichWithUsers(Board $board): void {
|
||||
private function enrichWithUsers($board, $since = -1) {
|
||||
$boardUsers = $this->permissionService->findUsers($board->getId());
|
||||
if ($boardUsers === null || \count($boardUsers) === 0) {
|
||||
return;
|
||||
@@ -708,7 +746,7 @@ class BoardService {
|
||||
/**
|
||||
* Clean a given board data from the Cache
|
||||
*/
|
||||
private function clearBoardFromCache(Board $board): void {
|
||||
private function clearBoardFromCache(Board $board) {
|
||||
$boardId = $board->getId();
|
||||
$boardOwnerId = $board->getOwner();
|
||||
|
||||
@@ -717,7 +755,7 @@ class BoardService {
|
||||
unset($this->boardsCachePartial[$boardId]);
|
||||
}
|
||||
|
||||
private function enrichWithCards(Board $board): void {
|
||||
private function enrichWithCards($board) {
|
||||
$stacks = $this->stackMapper->findAll($board->getId());
|
||||
foreach ($stacks as $stack) {
|
||||
$cards = $this->cardMapper->findAllByStack($stack->getId());
|
||||
|
||||
@@ -64,14 +64,10 @@ class CardService {
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Card[] $cards
|
||||
* @return CardDetails[]
|
||||
*/
|
||||
public function enrichCards(array $cards): array {
|
||||
public function enrichCards($cards) {
|
||||
$user = $this->userManager->get($this->userId);
|
||||
|
||||
$cardIds = array_map(function (Card $card) use ($user): int {
|
||||
$cardIds = array_map(function (Card $card) use ($user) {
|
||||
// Everything done in here might be heavy as it is executed for every card
|
||||
$cardId = $card->getId();
|
||||
$this->cardMapper->mapOwner($card);
|
||||
@@ -124,8 +120,7 @@ class CardService {
|
||||
);
|
||||
}
|
||||
|
||||
/** @return Card[] */
|
||||
public function fetchDeleted($boardId): array {
|
||||
public function fetchDeleted($boardId) {
|
||||
$this->cardServiceValidator->check(compact('boardId'));
|
||||
$this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_READ);
|
||||
$cards = $this->cardMapper->findDeleted($boardId);
|
||||
@@ -134,12 +129,13 @@ class CardService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \OCA\Deck\Db\RelationalEntity
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function find(int $cardId): Card {
|
||||
public function find(int $cardId) {
|
||||
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_READ);
|
||||
$card = $this->cardMapper->find($cardId);
|
||||
[$card] = $this->enrichCards([$card]);
|
||||
@@ -156,10 +152,7 @@ class CardService {
|
||||
return $card;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Card[]
|
||||
*/
|
||||
public function findCalendarEntries(int $boardId): array {
|
||||
public function findCalendarEntries($boardId) {
|
||||
try {
|
||||
$this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_READ);
|
||||
} catch (NoPermissionException $e) {
|
||||
@@ -170,13 +163,20 @@ class CardService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $title
|
||||
* @param $stackId
|
||||
* @param $type
|
||||
* @param integer $order
|
||||
* @param $description
|
||||
* @param $owner
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws StatusException
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadrequestException
|
||||
*/
|
||||
public function create(string $title, int $stackId, string $type, int $order, string $owner, string $description = '', $duedate = null): Card {
|
||||
public function create($title, $stackId, $type, $order, $owner, $description = '', $duedate = null) {
|
||||
$this->cardServiceValidator->check(compact('title', 'stackId', 'type', 'order', 'owner'));
|
||||
|
||||
$this->permissionService->checkPermission($this->stackMapper, $stackId, Acl::PERMISSION_EDIT);
|
||||
@@ -203,13 +203,19 @@ class CardService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws StatusException
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function delete(int $id): Card {
|
||||
public function delete($id) {
|
||||
if (is_numeric($id) === false) {
|
||||
throw new BadRequestException('card id must be a number');
|
||||
}
|
||||
|
||||
$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
|
||||
if ($this->boardService->isArchived($this->cardMapper, $id)) {
|
||||
throw new StatusException('Operation not allowed. This board is archived.');
|
||||
@@ -227,13 +233,25 @@ class CardService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @param $title
|
||||
* @param $stackId
|
||||
* @param $type
|
||||
* @param $owner
|
||||
* @param $description
|
||||
* @param $order
|
||||
* @param $duedate
|
||||
* @param $deletedAt
|
||||
* @param $archived
|
||||
* @param $done
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws StatusException
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function update(int $id, string $title, int $stackId, string $type, string $owner, string $description = '', int $order = 0, ?string $duedate = null, ?int $deletedAt = null, ?bool $archived = null, ?OptionalNullableValue $done = null): Card {
|
||||
public function update($id, $title, $stackId, $type, $owner, $description = '', $order = 0, $duedate = null, $deletedAt = null, $archived = null, ?OptionalNullableValue $done = null) {
|
||||
$this->cardServiceValidator->check(compact('id', 'title', 'stackId', 'type', 'owner', 'order'));
|
||||
|
||||
$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT, allowDeletedCard: true);
|
||||
@@ -380,13 +398,16 @@ class CardService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @param $title
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws StatusException
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function rename(int $id, string $title): Card {
|
||||
public function rename($id, $title) {
|
||||
$this->cardServiceValidator->check(compact('id', 'title'));
|
||||
|
||||
$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
|
||||
@@ -408,14 +429,17 @@ class CardService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<Card>
|
||||
* @param $id
|
||||
* @param $stackId
|
||||
* @param $order
|
||||
* @return array
|
||||
* @throws StatusException
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function reorder(int $id, int $stackId, int $order): array {
|
||||
public function reorder(int $id, int $stackId, int $order) {
|
||||
$this->cardServiceValidator->check(compact('id', 'stackId', 'order'));
|
||||
|
||||
$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
|
||||
@@ -464,13 +488,15 @@ class CardService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws StatusException
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function archive(int $id): Card {
|
||||
public function archive($id) {
|
||||
$this->cardServiceValidator->check(compact('id'));
|
||||
|
||||
$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
|
||||
@@ -491,13 +517,15 @@ class CardService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws StatusException
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function unarchive(int $id): Card {
|
||||
public function unarchive($id) {
|
||||
$this->cardServiceValidator->check(compact('id'));
|
||||
|
||||
|
||||
@@ -518,6 +546,8 @@ class CardService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @return \OCA\Deck\Db\Card
|
||||
* @throws StatusException
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
@@ -569,13 +599,15 @@ class CardService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $cardId
|
||||
* @param $labelId
|
||||
* @throws StatusException
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function assignLabel(int $cardId, int $labelId): Card {
|
||||
public function assignLabel($cardId, $labelId) {
|
||||
$this->cardServiceValidator->check(compact('cardId', 'labelId'));
|
||||
|
||||
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT);
|
||||
@@ -597,16 +629,18 @@ class CardService {
|
||||
$this->activityManager->triggerEvent(ActivityManager::DECK_OBJECT_CARD, $card, ActivityManager::SUBJECT_LABEL_ASSIGN, ['label' => $label]);
|
||||
|
||||
$this->eventDispatcher->dispatchTyped(new CardUpdatedEvent($card));
|
||||
return $card;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $cardId
|
||||
* @param $labelId
|
||||
* @throws StatusException
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function removeLabel(int $cardId, int $labelId): Card {
|
||||
public function removeLabel($cardId, $labelId) {
|
||||
$this->cardServiceValidator->check(compact('cardId', 'labelId'));
|
||||
|
||||
|
||||
@@ -626,7 +660,6 @@ class CardService {
|
||||
$this->activityManager->triggerEvent(ActivityManager::DECK_OBJECT_CARD, $card, ActivityManager::SUBJECT_LABEL_UNASSING, ['label' => $label]);
|
||||
|
||||
$this->eventDispatcher->dispatchTyped(new CardUpdatedEvent($card));
|
||||
return $card;
|
||||
}
|
||||
|
||||
public function getCardUrl(int $cardId): string {
|
||||
|
||||
@@ -66,7 +66,7 @@ class CirclesService {
|
||||
$circlesManager->startSession($federatedUser);
|
||||
$circle = $circlesManager->getCircle($circleId);
|
||||
$member = $circle->getInitiator();
|
||||
$isUserInCircle = $member->getLevel() >= Member::LEVEL_MEMBER;
|
||||
$isUserInCircle = $member !== null && $member->getLevel() >= Member::LEVEL_MEMBER;
|
||||
|
||||
if (!isset($this->userCircleCache[$circleId])) {
|
||||
$this->userCircleCache[$circleId] = [];
|
||||
|
||||
@@ -22,6 +22,8 @@ use OCP\IUserManager;
|
||||
use OutOfBoundsException;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
use function is_numeric;
|
||||
|
||||
class CommentService {
|
||||
|
||||
public function __construct(
|
||||
@@ -34,9 +36,12 @@ class CommentService {
|
||||
) {
|
||||
}
|
||||
|
||||
public function list(int $cardId, int $limit = 20, int $offset = 0): DataResponse {
|
||||
public function list(string $cardId, int $limit = 20, int $offset = 0): DataResponse {
|
||||
if (!is_numeric($cardId)) {
|
||||
throw new BadRequestException('A valid card id must be provided');
|
||||
}
|
||||
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_READ);
|
||||
$comments = $this->commentsManager->getForObject(Application::COMMENT_ENTITY_TYPE, (string)$cardId, $limit, $offset);
|
||||
$comments = $this->commentsManager->getForObject(Application::COMMENT_ENTITY_TYPE, $cardId, $limit, $offset);
|
||||
$result = [];
|
||||
foreach ($comments as $comment) {
|
||||
$formattedComment = $this->formatComment($comment);
|
||||
@@ -91,13 +96,13 @@ class CommentService {
|
||||
* @throws BadRequestException
|
||||
* @throws NotFoundException|NoPermissionException
|
||||
*/
|
||||
public function create(int $cardId, string $message, int $replyTo = 0): DataResponse {
|
||||
public function create(int $cardId, string $message, string $replyTo = '0'): DataResponse {
|
||||
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_READ);
|
||||
|
||||
// Check if parent is a comment on the same card
|
||||
if ($replyTo !== 0) {
|
||||
if ($replyTo !== '0') {
|
||||
try {
|
||||
$comment = $this->commentsManager->get((string)$replyTo);
|
||||
$comment = $this->commentsManager->get($replyTo);
|
||||
if ($comment->getObjectType() !== Application::COMMENT_ENTITY_TYPE || (int)$comment->getObjectId() !== $cardId) {
|
||||
throw new CommentNotFoundException();
|
||||
}
|
||||
@@ -110,7 +115,7 @@ class CommentService {
|
||||
$comment = $this->commentsManager->create('users', $this->userId, Application::COMMENT_ENTITY_TYPE, (string)$cardId);
|
||||
$comment->setMessage($message);
|
||||
$comment->setVerb('comment');
|
||||
$comment->setParentId((string)$replyTo);
|
||||
$comment->setParentId($replyTo);
|
||||
$this->commentsManager->save($comment);
|
||||
return new DataResponse($this->formatComment($comment, true));
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
@@ -123,8 +128,14 @@ class CommentService {
|
||||
}
|
||||
}
|
||||
|
||||
public function update(int $cardId, int $commentId, string $message): DataResponse {
|
||||
$comment = $this->get($cardId, $commentId);
|
||||
public function update(string $cardId, string $commentId, string $message): DataResponse {
|
||||
if (!is_numeric($cardId)) {
|
||||
throw new BadRequestException('A valid card id must be provided');
|
||||
}
|
||||
if (!is_numeric($commentId)) {
|
||||
throw new BadRequestException('A valid comment id must be provided');
|
||||
}
|
||||
$comment = $this->get((int)$cardId, (int)$commentId);
|
||||
if ($comment->getActorType() !== 'users' || $comment->getActorId() !== $this->userId) {
|
||||
throw new NoPermissionException('Only authors are allowed to edit their comment.');
|
||||
}
|
||||
@@ -134,12 +145,18 @@ class CommentService {
|
||||
return new DataResponse($this->formatComment($comment));
|
||||
}
|
||||
|
||||
public function delete(int $cardId, int $commentId): DataResponse {
|
||||
public function delete(string $cardId, string $commentId): DataResponse {
|
||||
if (!is_numeric($cardId)) {
|
||||
throw new BadRequestException('A valid card id must be provided');
|
||||
}
|
||||
if (!is_numeric($commentId)) {
|
||||
throw new BadRequestException('A valid comment id must be provided');
|
||||
}
|
||||
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_READ);
|
||||
|
||||
try {
|
||||
$comment = $this->commentsManager->get((string)$commentId);
|
||||
if ($comment->getObjectType() !== Application::COMMENT_ENTITY_TYPE || (int)$comment->getObjectId() !== $cardId) {
|
||||
$comment = $this->commentsManager->get($commentId);
|
||||
if ($comment->getObjectType() !== Application::COMMENT_ENTITY_TYPE || $comment->getObjectId() !== $cardId) {
|
||||
throw new CommentNotFoundException();
|
||||
}
|
||||
} catch (CommentNotFoundException $e) {
|
||||
@@ -148,11 +165,11 @@ class CommentService {
|
||||
if ($comment->getActorType() !== 'users' || $comment->getActorId() !== $this->userId) {
|
||||
throw new NoPermissionException('Only authors are allowed to edit their comment.');
|
||||
}
|
||||
$this->commentsManager->delete((string)$commentId);
|
||||
$this->commentsManager->delete($commentId);
|
||||
return new DataResponse([]);
|
||||
}
|
||||
|
||||
private function formatComment(IComment $comment, bool $addReplyTo = false): array {
|
||||
private function formatComment(IComment $comment, $addReplyTo = false): array {
|
||||
$actorDisplayName = $this->userManager->getDisplayName($comment->getActorId()) ?? $comment->getActorId();
|
||||
|
||||
$formattedComment = [
|
||||
|
||||
@@ -48,8 +48,7 @@ class ConfigService {
|
||||
}
|
||||
|
||||
public function getAll(): array {
|
||||
$userId = $this->getUserId();
|
||||
if ($userId === null) {
|
||||
if ($this->getUserId() === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -58,7 +57,7 @@ class ConfigService {
|
||||
'cardDetailsInModal' => $this->isCardDetailsInModal(),
|
||||
'cardIdBadge' => $this->isCardIdBadgeEnabled()
|
||||
];
|
||||
if ($this->groupManager->isAdmin($userId)) {
|
||||
if ($this->groupManager->isAdmin($this->getUserId())) {
|
||||
$data['groupLimit'] = $this->get('groupLimit');
|
||||
}
|
||||
return $data;
|
||||
@@ -96,48 +95,44 @@ class ConfigService {
|
||||
}
|
||||
|
||||
public function isCalendarEnabled(?int $boardId = null): bool {
|
||||
$userId = $this->getUserId();
|
||||
if ($userId === null) {
|
||||
if ($this->getUserId() === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$appConfigState = $this->config->getAppValue(Application::APP_ID, 'calendar', 'yes') === 'yes';
|
||||
$defaultState = (bool)$this->config->getUserValue($userId, Application::APP_ID, 'calendar', $appConfigState);
|
||||
$defaultState = (bool)$this->config->getUserValue($this->getUserId(), Application::APP_ID, 'calendar', $appConfigState);
|
||||
if ($boardId === null) {
|
||||
return $defaultState;
|
||||
}
|
||||
|
||||
return (bool)$this->config->getUserValue($userId, Application::APP_ID, 'board:' . $boardId . ':calendar', $defaultState);
|
||||
return (bool)$this->config->getUserValue($this->getUserId(), Application::APP_ID, 'board:' . $boardId . ':calendar', $defaultState);
|
||||
}
|
||||
|
||||
public function isCardDetailsInModal(?int $boardId = null): bool {
|
||||
$userId = $this->getUserId();
|
||||
if ($userId === null) {
|
||||
if ($this->getUserId() === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$defaultState = (bool)$this->config->getUserValue($userId, Application::APP_ID, 'cardDetailsInModal', true);
|
||||
$defaultState = (bool)$this->config->getUserValue($this->getUserId(), Application::APP_ID, 'cardDetailsInModal', true);
|
||||
if ($boardId === null) {
|
||||
return $defaultState;
|
||||
}
|
||||
|
||||
return (bool)$this->config->getUserValue($userId, Application::APP_ID, 'board:' . $boardId . ':cardDetailsInModal', $defaultState);
|
||||
return (bool)$this->config->getUserValue($this->getUserId(), Application::APP_ID, 'board:' . $boardId . ':cardDetailsInModal', $defaultState);
|
||||
}
|
||||
|
||||
public function isCardIdBadgeEnabled(): bool {
|
||||
$userId = $this->getUserId();
|
||||
if ($userId === null) {
|
||||
if ($this->getUserId() === null) {
|
||||
return false;
|
||||
}
|
||||
$appConfigState = $this->config->getAppValue(Application::APP_ID, 'cardIdBadge', 'yes') === 'no';
|
||||
$defaultState = (bool)$this->config->getUserValue($userId, Application::APP_ID, 'cardIdBadge', $appConfigState);
|
||||
$defaultState = (bool)$this->config->getUserValue($this->getUserId(), Application::APP_ID, 'cardIdBadge', $appConfigState);
|
||||
|
||||
return (bool)$this->config->getUserValue($userId, Application::APP_ID, 'cardIdBadge', $defaultState);
|
||||
return (bool)$this->config->getUserValue($this->getUserId(), Application::APP_ID, 'cardIdBadge', $defaultState);
|
||||
}
|
||||
|
||||
public function set($key, $value) {
|
||||
$userId = $this->getUserId();
|
||||
if ($userId === null) {
|
||||
if ($this->getUserId() === null) {
|
||||
throw new NoPermissionException('Must be logged in to set user config');
|
||||
}
|
||||
|
||||
@@ -145,21 +140,21 @@ class ConfigService {
|
||||
[$scope] = explode(':', $key, 2);
|
||||
switch ($scope) {
|
||||
case 'groupLimit':
|
||||
if (!$this->groupManager->isAdmin($userId)) {
|
||||
if (!$this->groupManager->isAdmin($this->getUserId())) {
|
||||
throw new NoPermissionException('You must be admin to set the group limit');
|
||||
}
|
||||
$result = $this->setGroupLimit($value);
|
||||
break;
|
||||
case 'calendar':
|
||||
$this->config->setUserValue($userId, Application::APP_ID, 'calendar', (string)$value);
|
||||
$this->config->setUserValue($this->getUserId(), Application::APP_ID, 'calendar', (string)$value);
|
||||
$result = $value;
|
||||
break;
|
||||
case 'cardDetailsInModal':
|
||||
$this->config->setUserValue($userId, Application::APP_ID, 'cardDetailsInModal', (string)$value);
|
||||
$this->config->setUserValue($this->getUserId(), Application::APP_ID, 'cardDetailsInModal', (string)$value);
|
||||
$result = $value;
|
||||
break;
|
||||
case 'cardIdBadge':
|
||||
$this->config->setUserValue($userId, Application::APP_ID, 'cardIdBadge', (string)$value);
|
||||
$this->config->setUserValue($this->getUserId(), Application::APP_ID, 'cardIdBadge', (string)$value);
|
||||
$result = $value;
|
||||
break;
|
||||
case 'board':
|
||||
@@ -167,7 +162,7 @@ class ConfigService {
|
||||
if ($boardConfigKey === 'notify-due' && !in_array($value, [self::SETTING_BOARD_NOTIFICATION_DUE_ALL, self::SETTING_BOARD_NOTIFICATION_DUE_ASSIGNED, self::SETTING_BOARD_NOTIFICATION_DUE_OFF], true)) {
|
||||
throw new BadRequestException('Board notification option must be one of: off, assigned, all');
|
||||
}
|
||||
$this->config->setUserValue($userId, Application::APP_ID, $key, (string)$value);
|
||||
$this->config->setUserValue($this->getUserId(), Application::APP_ID, $key, (string)$value);
|
||||
$result = $value;
|
||||
}
|
||||
return $result;
|
||||
|
||||
@@ -124,15 +124,18 @@ class FullTextSearchService {
|
||||
|
||||
|
||||
/**
|
||||
* @param int $cardId
|
||||
*
|
||||
* @return Board
|
||||
* @throws DoesNotExistException
|
||||
* @throws MultipleObjectsReturnedException
|
||||
*/
|
||||
public function getBoardFromCardId(int $cardId): Board {
|
||||
$boardId = $this->cardMapper->findBoardId($cardId);
|
||||
if ($boardId === null) {
|
||||
throw new DoesNotExistException("Board '$cardId' does not exist");
|
||||
}
|
||||
return $this->boardMapper->find($boardId);
|
||||
$boardId = (int)$this->cardMapper->findBoardId($cardId);
|
||||
/** @var Board $board */
|
||||
$board = $this->boardMapper->find($boardId);
|
||||
|
||||
return $board;
|
||||
}
|
||||
|
||||
|
||||
@@ -142,7 +145,7 @@ class FullTextSearchService {
|
||||
* @return Card[]
|
||||
*/
|
||||
private function getCardsFromStack(int $stackId): array {
|
||||
return $this->cardMapper->findAll($stackId);
|
||||
return $this->cardMapper->findAll($stackId, null, null);
|
||||
}
|
||||
|
||||
|
||||
@@ -152,7 +155,7 @@ class FullTextSearchService {
|
||||
* @return Stack[]
|
||||
*/
|
||||
private function getStacksFromBoard(int $boardId): array {
|
||||
return $this->stackMapper->findAll($boardId);
|
||||
return $this->stackMapper->findAll($boardId, null, null);
|
||||
}
|
||||
|
||||
|
||||
@@ -162,6 +165,6 @@ class FullTextSearchService {
|
||||
* @return Board[]
|
||||
*/
|
||||
private function getBoardsFromUser(string $userId): array {
|
||||
return $this->boardMapper->findAllByUser($userId);
|
||||
return $this->boardMapper->findAllByUser($userId, null, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,25 +19,29 @@ use OCP\Comments\IComment;
|
||||
abstract class ABoardImportService {
|
||||
/** @var string */
|
||||
public static $name = '';
|
||||
private BoardImportService $boardImportService;
|
||||
protected bool $needValidateData = true;
|
||||
/** @var BoardImportService */
|
||||
private $boardImportService;
|
||||
/** @var bool */
|
||||
protected $needValidateData = true;
|
||||
/** @var Stack[] */
|
||||
protected array $stacks = [];
|
||||
protected $stacks = [];
|
||||
/** @var Label[] */
|
||||
protected array $labels = [];
|
||||
protected $labels = [];
|
||||
/** @var Card[] */
|
||||
protected array $cards = [];
|
||||
protected $cards = [];
|
||||
/** @var Acl[] */
|
||||
protected array $acls = [];
|
||||
protected $acls = [];
|
||||
/** @var IComment[][] */
|
||||
protected array $comments = [];
|
||||
protected $comments = [];
|
||||
/** @var Assignment[] */
|
||||
protected array $assignments = [];
|
||||
/** @var int[][] */
|
||||
protected array $labelCardAssignments = [];
|
||||
protected $assignments = [];
|
||||
/** @var string[][] */
|
||||
protected $labelCardAssignments = [];
|
||||
|
||||
/**
|
||||
* Configure import service
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
abstract public function bootstrap(): void;
|
||||
|
||||
@@ -64,13 +68,10 @@ abstract class ABoardImportService {
|
||||
|
||||
abstract public function getCardAssignments(): array;
|
||||
|
||||
/**
|
||||
* @return array<int, array<int, int>>
|
||||
*/
|
||||
abstract public function getCardLabelAssignment(): array;
|
||||
|
||||
/**
|
||||
* @return array<int, array<string, IComment>>
|
||||
* @return IComment[][]|array
|
||||
*/
|
||||
abstract public function getComments(): array;
|
||||
|
||||
@@ -97,16 +98,16 @@ abstract class ABoardImportService {
|
||||
$this->acls[$code] = $acl;
|
||||
}
|
||||
|
||||
public function updateComment(int $cardId, string $commentId, IComment $comment): void {
|
||||
public function updateComment(string $cardId, string $commentId, IComment $comment): void {
|
||||
$this->comments[$cardId][$commentId] = $comment;
|
||||
}
|
||||
|
||||
public function updateCardAssignment(int $cardId, int $assignmentId, Entity $assignment): void {
|
||||
public function updateCardAssignment(string $cardId, string $assignmentId, Entity $assignment): void {
|
||||
$this->assignments[$cardId][$assignmentId] = $assignment;
|
||||
}
|
||||
|
||||
public function updateCardLabelsAssignment(int $cardId, int $assignmentId, int $labelId): void {
|
||||
$this->labelCardAssignments[$cardId][$assignmentId] = $labelId;
|
||||
public function updateCardLabelsAssignment(string $cardId, string $assignmentId, string $assignment): void {
|
||||
$this->labelCardAssignments[$cardId][$assignmentId] = $assignment;
|
||||
}
|
||||
|
||||
public function setImportService(BoardImportService $service): void {
|
||||
|
||||
@@ -209,15 +209,14 @@ class BoardImportService {
|
||||
|
||||
public function importBoard(): void {
|
||||
$board = $this->getImportSystem()->getBoard();
|
||||
if ($board === null) {
|
||||
throw new \LogicException('Import board not found');
|
||||
}
|
||||
if (!$this->userManager->userExists($board->getOwner())) {
|
||||
throw new \Exception('Target owner ' . $board->getOwner() . ' not found. Please provide a mapping through the import config.');
|
||||
}
|
||||
|
||||
$this->boardMapper->insert($board);
|
||||
$this->board = $board;
|
||||
if ($board) {
|
||||
$this->boardMapper->insert($board);
|
||||
$this->board = $board;
|
||||
}
|
||||
}
|
||||
|
||||
public function getBoard(bool $reset = false): Board {
|
||||
@@ -293,7 +292,12 @@ class BoardImportService {
|
||||
}
|
||||
}
|
||||
|
||||
public function assignCardToLabel(int $cardId, int $labelId): self {
|
||||
/**
|
||||
* @param mixed $cardId
|
||||
* @param mixed $labelId
|
||||
* @return self
|
||||
*/
|
||||
public function assignCardToLabel($cardId, $labelId): self {
|
||||
$this->cardMapper->assignLabel(
|
||||
$cardId,
|
||||
$labelId
|
||||
@@ -303,14 +307,14 @@ class BoardImportService {
|
||||
|
||||
public function assignCardsToLabels(): void {
|
||||
$data = $this->getImportSystem()->getCardLabelAssignment();
|
||||
foreach ($data as $cardId => $assignment) {
|
||||
foreach ($assignment as $assignmentId => $labelId) {
|
||||
foreach ($data as $cardId => $assignemnt) {
|
||||
foreach ($assignemnt as $assignmentId => $labelId) {
|
||||
try {
|
||||
$this->assignCardToLabel(
|
||||
(int)$cardId,
|
||||
$cardId,
|
||||
$labelId
|
||||
);
|
||||
$this->getImportSystem()->updateCardLabelsAssignment((int)$cardId, (int)$assignmentId, $labelId);
|
||||
$this->getImportSystem()->updateCardLabelsAssignment($cardId, $assignmentId, $labelId);
|
||||
} catch (\Exception $e) {
|
||||
$this->addError('Failed to assign label ' . $labelId . ' to ' . $cardId, $e);
|
||||
}
|
||||
@@ -322,20 +326,20 @@ class BoardImportService {
|
||||
$allComments = $this->getImportSystem()->getComments();
|
||||
foreach ($allComments as $cardId => $comments) {
|
||||
foreach ($comments as $commentId => $comment) {
|
||||
$this->insertComment((int)$cardId, $comment);
|
||||
$this->getImportSystem()->updateComment((int)$cardId, $commentId, $comment);
|
||||
$this->insertComment($cardId, $comment);
|
||||
$this->getImportSystem()->updateComment($cardId, $commentId, $comment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function insertComment(int $cardId, IComment $comment): void {
|
||||
$comment->setObject('deckCard', (string)$cardId);
|
||||
private function insertComment(string $cardId, IComment $comment): void {
|
||||
$comment->setObject('deckCard', $cardId);
|
||||
$comment->setVerb('comment');
|
||||
// Check if parent is a comment on the same card
|
||||
if ($comment->getParentId() !== '0') {
|
||||
try {
|
||||
$parent = $this->commentsManager->get($comment->getParentId());
|
||||
if ($parent->getObjectType() !== Application::COMMENT_ENTITY_TYPE || (int)$parent->getObjectId() !== $cardId) {
|
||||
if ($parent->getObjectType() !== Application::COMMENT_ENTITY_TYPE || $parent->getObjectId() !== $cardId) {
|
||||
throw new CommentNotFoundException();
|
||||
}
|
||||
} catch (CommentNotFoundException $e) {
|
||||
@@ -358,7 +362,7 @@ class BoardImportService {
|
||||
foreach ($assignments as $assignment) {
|
||||
try {
|
||||
$assignment = $this->assignmentMapper->insert($assignment);
|
||||
$this->getImportSystem()->updateCardAssignment((int)$cardId, $assignment->getId(), $assignment);
|
||||
$this->getImportSystem()->updateCardAssignment($cardId, (string)$assignment->getId(), $assignment);
|
||||
$this->addOutput('Assignment ' . $assignment->getParticipant() . ' added');
|
||||
} catch (NotFoundException $e) {
|
||||
$this->addError('No origin or mapping found for card "' . $cardId . '" and ' . $assignment->getTypeString() . ' assignment "' . $assignment->getParticipant(), $e);
|
||||
|
||||
@@ -16,7 +16,6 @@ use OCA\Deck\Db\Card;
|
||||
use OCA\Deck\Db\Label;
|
||||
use OCA\Deck\Db\Stack;
|
||||
use OCA\Deck\Service\Importer\ABoardImportService;
|
||||
use OCP\Comments\IComment;
|
||||
use OCP\IUser;
|
||||
use OCP\IUserManager;
|
||||
|
||||
@@ -119,7 +118,6 @@ class DeckJsonService extends ABoardImportService {
|
||||
$comments[$this->cards[$sourceCard->id]->getId()][$commentOriginal->id] = $comment;
|
||||
}
|
||||
}
|
||||
/** @var array<int, array<string, IComment>> */
|
||||
return $comments;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ use Psr\Log\LoggerInterface;
|
||||
class TrelloApiService extends TrelloJsonService {
|
||||
/** @var string */
|
||||
public static $name = 'Trello API';
|
||||
protected bool $needValidateData = false;
|
||||
protected $needValidateData = false;
|
||||
/** @var IClient */
|
||||
private $httpClient;
|
||||
/** @var LoggerInterface */
|
||||
@@ -176,7 +176,7 @@ class TrelloApiService extends TrelloJsonService {
|
||||
if (empty($queryString['limit'])) {
|
||||
return [];
|
||||
}
|
||||
if ((count($data) < $queryString['limit']) || (count($data) === 0)) {
|
||||
if (count($data) < $queryString['limit']) {
|
||||
return [];
|
||||
}
|
||||
$queryString['before'] = end($data)->id;
|
||||
|
||||
@@ -159,7 +159,6 @@ class TrelloJsonService extends ABoardImportService {
|
||||
$comments[$cardId][$commentId] = $comment;
|
||||
}
|
||||
}
|
||||
/** @var array<int, array<string, IComment>> */
|
||||
return $comments;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,24 +43,33 @@ class LabelService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $labelId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function find(int $labelId): Label {
|
||||
public function find($labelId) {
|
||||
if (is_numeric($labelId) === false) {
|
||||
throw new BadRequestException('label id must be a number');
|
||||
}
|
||||
$this->permissionService->checkPermission($this->labelMapper, $labelId, Acl::PERMISSION_READ);
|
||||
return $this->labelMapper->find($labelId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $title
|
||||
* @param $color
|
||||
* @param $boardId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws StatusException
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function create(string $title, string $color, int $boardId): Label {
|
||||
public function create($title, $color, $boardId) {
|
||||
$this->labelServiceValidator->check(compact('title', 'color', 'boardId'));
|
||||
|
||||
$this->permissionService->checkPermission(null, $boardId, Acl::PERMISSION_MANAGE);
|
||||
@@ -97,13 +106,15 @@ class LabelService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws StatusException
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function delete(int $id): Label {
|
||||
public function delete($id) {
|
||||
$this->labelServiceValidator->check(compact('id'));
|
||||
|
||||
$this->permissionService->checkPermission($this->labelMapper, $id, Acl::PERMISSION_MANAGE);
|
||||
@@ -116,13 +127,17 @@ class LabelService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @param $title
|
||||
* @param $color
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws StatusException
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function update(int $id, string $title, string $color): Label {
|
||||
public function update($id, $title, $color) {
|
||||
$this->labelServiceValidator->check(compact('title', 'color', 'id'));
|
||||
|
||||
$this->permissionService->checkPermission($this->labelMapper, $id, Acl::PERMISSION_MANAGE);
|
||||
|
||||
@@ -9,28 +9,53 @@ declare(strict_types=1);
|
||||
|
||||
namespace OCA\Deck\Service;
|
||||
|
||||
use OCA\Deck\Db\AssignmentMapper;
|
||||
use OCA\Deck\Db\Board;
|
||||
use OCA\Deck\Db\BoardMapper;
|
||||
use OCA\Deck\Db\CardMapper;
|
||||
use OCA\Deck\Db\LabelMapper;
|
||||
use OCA\Deck\Model\CardDetails;
|
||||
use OCP\Comments\ICommentsManager;
|
||||
use OCP\IUserManager;
|
||||
|
||||
class OverviewService {
|
||||
private CardService $cardService;
|
||||
private BoardMapper $boardMapper;
|
||||
private LabelMapper $labelMapper;
|
||||
private CardMapper $cardMapper;
|
||||
private AssignmentMapper $assignedUsersMapper;
|
||||
private IUserManager $userManager;
|
||||
private ICommentsManager $commentsManager;
|
||||
private AttachmentService $attachmentService;
|
||||
|
||||
public function __construct(
|
||||
private readonly CardService $cardService,
|
||||
private readonly BoardMapper $boardMapper,
|
||||
private readonly CardMapper $cardMapper,
|
||||
CardService $cardService,
|
||||
BoardMapper $boardMapper,
|
||||
LabelMapper $labelMapper,
|
||||
CardMapper $cardMapper,
|
||||
AssignmentMapper $assignedUsersMapper,
|
||||
IUserManager $userManager,
|
||||
ICommentsManager $commentsManager,
|
||||
AttachmentService $attachmentService,
|
||||
) {
|
||||
$this->cardService = $cardService;
|
||||
$this->boardMapper = $boardMapper;
|
||||
$this->labelMapper = $labelMapper;
|
||||
$this->cardMapper = $cardMapper;
|
||||
$this->assignedUsersMapper = $assignedUsersMapper;
|
||||
$this->userManager = $userManager;
|
||||
$this->commentsManager = $commentsManager;
|
||||
$this->attachmentService = $attachmentService;
|
||||
}
|
||||
|
||||
public function findUpcomingCards(string $userId): array {
|
||||
$userBoards = $this->boardMapper->findAllForUser($userId);
|
||||
|
||||
$boardOwnerIds = array_filter(array_map(function (Board $board) {
|
||||
return count($board->getAcl() ?? []) === 0 ? $board->getId() : null;
|
||||
return count($board->getAcl()) === 0 ? $board->getId() : null;
|
||||
}, $userBoards));
|
||||
$boardSharedIds = array_filter(array_map(function (Board $board) {
|
||||
return count($board->getAcl() ?? []) > 0 ? $board->getId() : null;
|
||||
return count($board->getAcl()) > 0 ? $board->getId() : null;
|
||||
}, $userBoards));
|
||||
|
||||
$foundCards = array_merge(
|
||||
|
||||
@@ -29,7 +29,6 @@ class PermissionService {
|
||||
private array $users = [];
|
||||
|
||||
private CappedMemoryCache $boardCache;
|
||||
/** @var CappedMemoryCache<array<Acl::PERMISSION_*, bool>> */
|
||||
private CappedMemoryCache $permissionCache;
|
||||
|
||||
public function __construct(
|
||||
@@ -50,16 +49,15 @@ class PermissionService {
|
||||
/**
|
||||
* Get current user permissions for a board by id
|
||||
*
|
||||
* @return array<Acl::PERMISSION_*, bool>
|
||||
* @return bool|array
|
||||
*/
|
||||
public function getPermissions(int $boardId, ?string $userId = null): array {
|
||||
public function getPermissions(int $boardId, ?string $userId = null) {
|
||||
if ($userId === null) {
|
||||
$userId = $this->userId;
|
||||
}
|
||||
|
||||
$cacheKey = $boardId . '-' . $userId;
|
||||
if ($cached = $this->permissionCache->get($cacheKey)) {
|
||||
/** @var array<Acl::PERMISSION_*, bool> $cached */
|
||||
return $cached;
|
||||
}
|
||||
|
||||
|
||||
@@ -75,31 +75,35 @@ class StackService {
|
||||
$this->stackServiceValidator = $stackServiceValidator;
|
||||
}
|
||||
|
||||
/** @param Stack[] $stacks */
|
||||
private function enrichStacksWithCards(array $stacks, $since = -1): void {
|
||||
$cardsByStackId = $this->cardMapper->findAllForStacks(array_map(fn (Stack $stack) => $stack->getId(), $stacks), null, 0, $since);
|
||||
private function enrichStackWithCards($stack, $since = -1) {
|
||||
$cards = $this->cardMapper->findAll($stack->getId(), null, null, $since);
|
||||
|
||||
foreach ($cardsByStackId as $stackId => $cards) {
|
||||
if (!$cards) {
|
||||
continue;
|
||||
}
|
||||
if (\count($cards) === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$stack->setCards($this->cardService->enrichCards($cards));
|
||||
}
|
||||
|
||||
foreach ($stacks as $stack) {
|
||||
if ($stack->getId() === $stackId) {
|
||||
$stack->setCards($this->cardService->enrichCards($cards));
|
||||
break;
|
||||
}
|
||||
}
|
||||
private function enrichStacksWithCards($stacks, $since = -1) {
|
||||
foreach ($stacks as $stack) {
|
||||
$this->enrichStackWithCards($stack, $since);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $stackId
|
||||
*
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function find(int $stackId): Stack {
|
||||
public function find($stackId) {
|
||||
if (is_numeric($stackId) === false) {
|
||||
throw new BadRequestException('stack id must be a number');
|
||||
}
|
||||
|
||||
$this->permissionService->checkPermission($this->stackMapper, $stackId, Acl::PERMISSION_READ);
|
||||
$stack = $this->stackMapper->find($stackId);
|
||||
|
||||
@@ -120,11 +124,17 @@ class StackService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Stack[]
|
||||
* @param $boardId
|
||||
*
|
||||
* @return array
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function findAll(int $boardId, int $since = -1): array {
|
||||
public function findAll($boardId, $since = -1) {
|
||||
if (is_numeric($boardId) === false) {
|
||||
throw new BadRequestException('boardId must be a number');
|
||||
}
|
||||
|
||||
$this->permissionService->checkPermission(null, $boardId, Acl::PERMISSION_READ);
|
||||
$stacks = $this->stackMapper->findAll($boardId);
|
||||
$this->enrichStacksWithCards($stacks, $since);
|
||||
@@ -132,11 +142,7 @@ class StackService {
|
||||
return $stacks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Stack[]
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findCalendarEntries(int $boardId): array {
|
||||
public function findCalendarEntries($boardId) {
|
||||
try {
|
||||
$this->permissionService->checkPermission(null, $boardId, Acl::PERMISSION_READ);
|
||||
} catch (NoPermissionException $e) {
|
||||
@@ -146,11 +152,7 @@ class StackService {
|
||||
return $this->stackMapper->findAll($boardId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Stack[]
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function fetchDeleted(int $boardId): array {
|
||||
public function fetchDeleted($boardId) {
|
||||
$this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_READ);
|
||||
$stacks = $this->stackMapper->findDeleted($boardId);
|
||||
$this->enrichStacksWithCards($stacks);
|
||||
@@ -159,11 +161,17 @@ class StackService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Stack[]
|
||||
* @param $boardId
|
||||
*
|
||||
* @return array
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function findAllArchived(int $boardId): array {
|
||||
public function findAllArchived($boardId) {
|
||||
if (is_numeric($boardId) === false) {
|
||||
throw new BadRequestException('board id must be a number');
|
||||
}
|
||||
|
||||
$this->permissionService->checkPermission(null, $boardId, Acl::PERMISSION_READ);
|
||||
$stacks = $this->stackMapper->findAll($boardId);
|
||||
$labels = $this->labelMapper->getAssignedLabelsForBoard($boardId);
|
||||
@@ -178,18 +186,22 @@ class StackService {
|
||||
$stacks[$stackIndex]->setCards($cards);
|
||||
}
|
||||
|
||||
/** @var Stack[] $stacks */
|
||||
return $stacks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $title
|
||||
* @param $boardId
|
||||
* @param integer $order
|
||||
*
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws StatusException
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function create(string $title, int $boardId, int $order): Stack {
|
||||
public function create($title, $boardId, $order) {
|
||||
$this->stackServiceValidator->check(compact('title', 'boardId', 'order'));
|
||||
|
||||
$this->permissionService->checkPermission(null, $boardId, Acl::PERMISSION_MANAGE);
|
||||
@@ -211,13 +223,19 @@ class StackService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Stack The deleted stack.
|
||||
* @param $id
|
||||
*
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function delete(int $id): Stack {
|
||||
public function delete($id) {
|
||||
if (is_numeric($id) === false) {
|
||||
throw new BadRequestException('stack id must be a number');
|
||||
}
|
||||
|
||||
$this->permissionService->checkPermission($this->stackMapper, $id, Acl::PERMISSION_MANAGE);
|
||||
|
||||
$stack = $this->stackMapper->find($id);
|
||||
@@ -229,19 +247,26 @@ class StackService {
|
||||
);
|
||||
$this->changeHelper->boardChanged($stack->getBoardId());
|
||||
$this->eventDispatcher->dispatchTyped(new BoardUpdatedEvent($stack->getBoardId()));
|
||||
$this->enrichStacksWithCards([$stack]);
|
||||
$this->enrichStackWithCards($stack);
|
||||
|
||||
return $stack;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @param $title
|
||||
* @param $boardId
|
||||
* @param $order
|
||||
* @param $deletedAt
|
||||
*
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws StatusException
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function update(int $id, string $title, int $boardId, int $order, ?int $deletedAt): Stack {
|
||||
public function update($id, $title, $boardId, $order, $deletedAt) {
|
||||
$this->stackServiceValidator->check(compact('id', 'title', 'boardId', 'order'));
|
||||
|
||||
$this->permissionService->checkPermission($this->stackMapper, $id, Acl::PERMISSION_MANAGE);
|
||||
@@ -269,13 +294,16 @@ class StackService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, Stack> The stacks in the correct order.
|
||||
* @param $id
|
||||
* @param $order
|
||||
*
|
||||
* @return array
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function reorder(int $id, int $order): array {
|
||||
public function reorder($id, $order) {
|
||||
$this->stackServiceValidator->check(compact('id', 'order'));
|
||||
|
||||
$this->permissionService->checkPermission($this->stackMapper, $id, Acl::PERMISSION_MANAGE);
|
||||
@@ -296,7 +324,7 @@ class StackService {
|
||||
if ($stack->id !== $id) {
|
||||
$stack->setOrder($i++);
|
||||
}
|
||||
$stack = $this->stackMapper->update($stack);
|
||||
$this->stackMapper->update($stack);
|
||||
$result[$stack->getOrder()] = $stack;
|
||||
}
|
||||
$this->changeHelper->boardChanged($stackToSort->getBoardId());
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace OCA\Deck\Sharing;
|
||||
use OC\Files\Cache\Cache;
|
||||
use OCA\Deck\Cache\AttachmentCacheHelper;
|
||||
use OCA\Deck\Db\Acl;
|
||||
use OCA\Deck\Db\Board;
|
||||
use OCA\Deck\Db\BoardMapper;
|
||||
use OCA\Deck\Db\CardMapper;
|
||||
use OCA\Deck\Db\User;
|
||||
@@ -98,13 +99,9 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function create(IShare $share) {
|
||||
$cardId = (int)$share->getSharedWith();
|
||||
$cardId = $share->getSharedWith();
|
||||
$boardId = $this->cardMapper->findBoardId($cardId);
|
||||
$valid = $boardId !== null;
|
||||
if (!$valid) {
|
||||
throw new GenericShareException('Card not found', $this->l->t('Card not found'), 404);
|
||||
}
|
||||
|
||||
try {
|
||||
$this->permissionService->checkPermission(null, $boardId, Acl::PERMISSION_EDIT);
|
||||
} catch (NoPermissionException $e) {
|
||||
@@ -150,7 +147,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
);
|
||||
$data = $this->getRawShare($shareId);
|
||||
|
||||
$this->attachmentCacheHelper->clearAttachmentCount($cardId);
|
||||
$this->attachmentCacheHelper->clearAttachmentCount((int)$cardId);
|
||||
|
||||
return $this->createShareObject($data);
|
||||
}
|
||||
@@ -216,7 +213,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
->from('share')
|
||||
->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
|
||||
|
||||
$cursor = $qb->executeQuery();
|
||||
$cursor = $qb->execute();
|
||||
$data = $cursor->fetch();
|
||||
$cursor->closeCursor();
|
||||
|
||||
@@ -300,7 +297,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
|
||||
->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
|
||||
->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
|
||||
->executeStatement();
|
||||
->execute();
|
||||
|
||||
/*
|
||||
* Update all user defined group shares
|
||||
@@ -313,7 +310,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
|
||||
->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
|
||||
->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
|
||||
->executeStatement();
|
||||
->execute();
|
||||
|
||||
/*
|
||||
* Now update the permissions for all children that have not set it to 0
|
||||
@@ -323,7 +320,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
->where($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
|
||||
->andWhere($qb->expr()->neq('permissions', $qb->createNamedParameter(0)))
|
||||
->set('permissions', $qb->createNamedParameter($share->getPermissions()))
|
||||
->executeStatement();
|
||||
->execute();
|
||||
|
||||
return $share;
|
||||
}
|
||||
@@ -338,7 +335,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
|
||||
$qb->orWhere($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())));
|
||||
|
||||
$qb->executeStatement();
|
||||
$qb->execute();
|
||||
|
||||
$this->attachmentCacheHelper->clearAttachmentCount((int)$share->getSharedWith());
|
||||
}
|
||||
@@ -358,7 +355,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
|
||||
$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
|
||||
))
|
||||
->executeQuery();
|
||||
->execute();
|
||||
|
||||
$data = $stmt->fetch();
|
||||
$stmt->closeCursor();
|
||||
@@ -379,14 +376,14 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
'file_target' => $qb->createNamedParameter($share->getTarget()),
|
||||
'permissions' => $qb->createNamedParameter(0),
|
||||
'stime' => $qb->createNamedParameter($share->getShareTime()->getTimestamp()),
|
||||
])->executeStatement();
|
||||
])->execute();
|
||||
} elseif ($data['permissions'] !== 0) {
|
||||
// Already a userroom share. Update it.
|
||||
$qb = $this->dbConnection->getQueryBuilder();
|
||||
$qb->update('share')
|
||||
->set('permissions', $qb->createNamedParameter(0))
|
||||
->where($qb->expr()->eq('id', $qb->createNamedParameter($data['id'])))
|
||||
->executeStatement();
|
||||
->execute();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -400,7 +397,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
->where(
|
||||
$qb->expr()->eq('id', $qb->createNamedParameter($share->getId()))
|
||||
);
|
||||
$cursor = $qb->executeQuery();
|
||||
$cursor = $qb->execute();
|
||||
$data = $cursor->fetch();
|
||||
$cursor->closeCursor();
|
||||
|
||||
@@ -417,7 +414,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
$qb->expr()->eq('share_with', $qb->createNamedParameter($recipient))
|
||||
);
|
||||
|
||||
$qb->executeStatement();
|
||||
$qb->execute();
|
||||
|
||||
return $this->getShareById((int)$share->getId(), $recipient);
|
||||
}
|
||||
@@ -438,7 +435,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
|
||||
))
|
||||
->setMaxResults(1)
|
||||
->executeQuery();
|
||||
->execute();
|
||||
|
||||
$data = $stmt->fetch();
|
||||
$stmt->closeCursor();
|
||||
@@ -512,7 +509,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
|
||||
$qb->orderBy('s.id');
|
||||
|
||||
$cursor = $qb->executeQuery();
|
||||
$cursor = $qb->execute();
|
||||
$shares = [];
|
||||
while ($data = $cursor->fetch()) {
|
||||
$shares[$data['fileid']][] = $this->createShareObject($data);
|
||||
@@ -557,7 +554,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
$qb->setFirstResult($offset);
|
||||
$qb->orderBy('id');
|
||||
|
||||
$cursor = $qb->executeQuery();
|
||||
$cursor = $qb->execute();
|
||||
$shares = [];
|
||||
while ($data = $cursor->fetch()) {
|
||||
$shares[] = $this->createShareObject($data);
|
||||
@@ -585,7 +582,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
->where($qb->expr()->eq('s.id', $qb->createNamedParameter($id)))
|
||||
->andWhere($qb->expr()->eq('s.share_type', $qb->createNamedParameter(IShare::TYPE_DECK)));
|
||||
|
||||
$cursor = $qb->executeQuery();
|
||||
$cursor = $qb->execute();
|
||||
$data = $cursor->fetch();
|
||||
$cursor->closeCursor();
|
||||
|
||||
@@ -650,7 +647,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
|
||||
));
|
||||
|
||||
$stmt = $query->executeQuery();
|
||||
$stmt = $query->execute();
|
||||
|
||||
while ($data = $stmt->fetch()) {
|
||||
$this->applyBoardPermission($shareMap[$data['parent']], (int)$data['permissions'], $userId);
|
||||
@@ -680,7 +677,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
->from('share')
|
||||
->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
|
||||
->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_DECK)))
|
||||
->executeQuery();
|
||||
->execute();
|
||||
|
||||
$shares = [];
|
||||
while ($data = $cursor->fetch()) {
|
||||
@@ -752,7 +749,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
|
||||
$qb->andWhere($qb->expr()->eq('dc.deleted_at', $qb->createNamedParameter(0, IQueryBuilder::PARAM_INT)));
|
||||
|
||||
$cursor = $qb->executeQuery();
|
||||
$cursor = $qb->execute();
|
||||
while ($data = $cursor->fetch()) {
|
||||
if (!$this->isAccessibleResult($data)) {
|
||||
continue;
|
||||
@@ -845,7 +842,6 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @psalm-suppress InvalidReturnType Not returning anything
|
||||
*/
|
||||
public function getShareByToken($token) {
|
||||
throw new ShareNotFound();
|
||||
@@ -855,7 +851,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
->from('share')
|
||||
->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_ROOM)))
|
||||
->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
|
||||
->executeQuery();
|
||||
->execute();
|
||||
|
||||
$data = $cursor->fetch();
|
||||
|
||||
@@ -1019,7 +1015,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_DECK)))
|
||||
->orderBy('id');
|
||||
|
||||
$cursor = $qb->executeQuery();
|
||||
$cursor = $qb->execute();
|
||||
while ($data = $cursor->fetch()) {
|
||||
$children[] = $this->createShareObject($data);
|
||||
}
|
||||
@@ -1042,7 +1038,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
)
|
||||
);
|
||||
|
||||
$cursor = $qb->executeQuery();
|
||||
$cursor = $qb->execute();
|
||||
while ($data = $cursor->fetch()) {
|
||||
$share = $this->createShareObject($data);
|
||||
|
||||
@@ -1059,7 +1055,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
->where($qb->expr()->eq('s.share_type', $qb->createNamedParameter(IShare::TYPE_DECK)))
|
||||
->andWhere($qb->expr()->notIn('s.share_with', $qb->createNamedParameter($allCardIds, IQueryBuilder::PARAM_STR_ARRAY)));
|
||||
|
||||
$cursor = $qb->executeQuery();
|
||||
$cursor = $qb->execute();
|
||||
$shares = [];
|
||||
while ($data = $cursor->fetch()) {
|
||||
$shares[] = $this->createShareObject($data);
|
||||
|
||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "deck",
|
||||
"version": "2.0.0-dev.0",
|
||||
"version": "1.16.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "deck",
|
||||
"version": "2.0.0-dev.0",
|
||||
"version": "1.16.0",
|
||||
"license": "agpl",
|
||||
"dependencies": {
|
||||
"@babel/polyfill": "^7.12.1",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "deck",
|
||||
"description": "",
|
||||
"version": "2.0.0-dev.0",
|
||||
"version": "1.16.0",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Julius Härtl",
|
||||
|
||||
10
psalm.xml
10
psalm.xml
@@ -6,8 +6,6 @@
|
||||
xmlns="https://getpsalm.org/schema/config"
|
||||
xsi:schemaLocation="https://getpsalm.org/schema/config"
|
||||
errorBaseline="tests/psalm-baseline.xml"
|
||||
findUnusedBaselineEntry="true"
|
||||
findUnusedCode="false"
|
||||
phpVersion="8.1"
|
||||
>
|
||||
<stubs>
|
||||
@@ -17,7 +15,6 @@
|
||||
<directory name="lib" />
|
||||
<ignoreFiles>
|
||||
<directory name="vendor" />
|
||||
<directory name="vendor-bin" />
|
||||
</ignoreFiles>
|
||||
</projectFiles>
|
||||
<extraFiles>
|
||||
@@ -29,6 +26,13 @@
|
||||
<referencedMethod name="/Db\\.*::.*/" />
|
||||
</errorLevel>
|
||||
</UndefinedMagicMethod>
|
||||
<UndefinedInterfaceMethod>
|
||||
<errorLevel type="suppress">
|
||||
<!-- FIXME Deprecated event handling -->
|
||||
<referencedMethod name="OCP\IUserManager::listen" />
|
||||
<referencedMethod name="OCP\IGroupManager::listen" />
|
||||
</errorLevel>
|
||||
</UndefinedInterfaceMethod>
|
||||
<UndefinedClass>
|
||||
<errorLevel type="suppress">
|
||||
<referencedClass name="OC\*" />
|
||||
|
||||
@@ -276,15 +276,18 @@ export default {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-height: calc(100vh - 50px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.board {
|
||||
padding-left: $board-spacing;
|
||||
position: relative;
|
||||
max-height: calc(100% - var(--default-clickable-area));
|
||||
overflow: hidden;
|
||||
overflow-x: auto;
|
||||
flex-grow: 1;
|
||||
scrollbar-gutter: stable;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -294,15 +297,11 @@ export default {
|
||||
.smooth-dnd-container.horizontal {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
gap: $board-gap;
|
||||
padding: 0 $board-gap;
|
||||
height: 100%;
|
||||
|
||||
&:deep(.stack-draggable-wrapper.smooth-dnd-draggable-wrapper) {
|
||||
display: flex;
|
||||
height: auto;
|
||||
flex: 0 1 $card-max-width;
|
||||
min-width: $card-min-width;
|
||||
|
||||
.stack {
|
||||
display: flex;
|
||||
@@ -310,13 +309,16 @@ export default {
|
||||
position: relative;
|
||||
|
||||
.smooth-dnd-container.vertical {
|
||||
$margin-x: calc($stack-gap * -1);
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $stack-gap;
|
||||
padding: $stack-gap;
|
||||
margin: 0 $margin-x;
|
||||
// Margin left instead of padidng to avoid jumps on dropping a card
|
||||
margin-left: $stack-spacing;
|
||||
padding-right: $stack-spacing;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
padding-top: 15px;
|
||||
margin-top: -10px;
|
||||
scrollbar-gutter: stable;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,10 +14,10 @@
|
||||
{{ stack.title }}
|
||||
</h3>
|
||||
<h3 v-else-if="!editing"
|
||||
title="stack.title"
|
||||
dir="auto"
|
||||
tabindex="0"
|
||||
:aria-label="stack.title"
|
||||
:title="stack.title"
|
||||
class="stack__title"
|
||||
@click="startEditing(stack)"
|
||||
@keydown.enter="startEditing(stack)">
|
||||
@@ -108,7 +108,7 @@
|
||||
</Container>
|
||||
|
||||
<transition name="slide-bottom" appear>
|
||||
<div v-if="showAddCard" class="stack__card-add">
|
||||
<div v-show="showAddCard" class="stack__card-add">
|
||||
<form :class="{ 'icon-loading-small': stateCardCreating }"
|
||||
@submit.prevent.stop="clickAddCard()">
|
||||
<label for="new-stack-input-main" class="hidden-visually">{{ t('deck', 'Add a new card') }}</label>
|
||||
@@ -365,31 +365,37 @@ export default {
|
||||
@import './../../css/variables';
|
||||
|
||||
.stack {
|
||||
width: 100%;
|
||||
width: $stack-width + $stack-spacing * 3;
|
||||
}
|
||||
|
||||
.stack__header {
|
||||
display: flex;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
height: var(--default-clickable-area);
|
||||
z-index: 100;
|
||||
padding-left: $card-spacing;
|
||||
padding-right: $card-spacing;
|
||||
margin: 6px;
|
||||
margin-top: 0;
|
||||
cursor: grab;
|
||||
background-color: var(--color-main-background);
|
||||
|
||||
// Smooth fade out of the cards at the top
|
||||
&:before {
|
||||
content: '';
|
||||
content: ' ';
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: $stack-gap;
|
||||
bottom: 0;
|
||||
width: calc(100% - 16px);
|
||||
height: 20px;
|
||||
top: 30px;
|
||||
left: 0px;
|
||||
z-index: 99;
|
||||
transition: top var(--animation-slow);
|
||||
background-image: linear-gradient(180deg, var(--color-main-background) 0%, transparent 100%);
|
||||
transform: translateY(100%);
|
||||
|
||||
background-image: linear-gradient(180deg, var(--color-main-background) 3px, rgba(255, 255, 255, 0) 100%);
|
||||
body.theme--dark & {
|
||||
background-image: linear-gradient(180deg, var(--color-main-background) 3px, rgba(0, 0, 0, 0) 100%);
|
||||
}
|
||||
}
|
||||
|
||||
& > * {
|
||||
@@ -398,10 +404,8 @@ export default {
|
||||
}
|
||||
|
||||
h3, form {
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: inherit;
|
||||
margin: 0;
|
||||
|
||||
@@ -414,8 +418,9 @@ export default {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: calc($stack-width - 60px);
|
||||
border-radius: 3px;
|
||||
padding: $card-padding;
|
||||
padding: 4px 4px;
|
||||
font-size: var(--default-font-size);
|
||||
|
||||
&:focus-visible {
|
||||
@@ -425,6 +430,7 @@ export default {
|
||||
}
|
||||
|
||||
form {
|
||||
margin: -4px;
|
||||
input {
|
||||
font-weight: bold;
|
||||
padding: 0 6px;
|
||||
@@ -447,25 +453,14 @@ export default {
|
||||
flex-shrink: 0;
|
||||
z-index: 100;
|
||||
display: flex;
|
||||
padding-bottom: $stack-gap;
|
||||
margin-bottom: 5px;
|
||||
padding-top: var(--default-grid-baseline);
|
||||
background-color: var(--color-main-background);
|
||||
position: relative;
|
||||
|
||||
// Smooth fade out of the cards at the top
|
||||
&:before {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: $stack-gap;
|
||||
z-index: 99;
|
||||
transition: bottom var(--animation-slow);
|
||||
background-image: linear-gradient(0deg, var(--color-main-background) 0%, transparent 100%);
|
||||
transform: translateY(-100%);
|
||||
}
|
||||
|
||||
form {
|
||||
display: flex;
|
||||
margin-left: $stack-spacing;
|
||||
margin-right: $stack-spacing;
|
||||
width: 100%;
|
||||
border: 2px solid var(--color-border-maxcontrast);
|
||||
border-radius: var(--border-radius-large);
|
||||
@@ -486,6 +481,7 @@ export default {
|
||||
input {
|
||||
border: none;
|
||||
margin: 0;
|
||||
padding: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -101,8 +101,6 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import './../../css/variables';
|
||||
|
||||
.badges {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
@@ -113,7 +111,6 @@ export default {
|
||||
.icon-badge {
|
||||
color: var(--color-text-maxcontrast);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 2px;
|
||||
|
||||
span,
|
||||
@@ -128,7 +125,6 @@ export default {
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
gap: 3px;
|
||||
height: var(--default-clickable-area);
|
||||
}
|
||||
|
||||
.badge-left, .badge-right {
|
||||
|
||||
@@ -4,10 +4,13 @@
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div v-if="cardId && ( attachments.length > 0 )" class="card-cover">
|
||||
<div v-for="attachment in attachments"
|
||||
<div v-if="referencePreview" class="card-cover">
|
||||
<div class="image-wrapper rounded-left rounded-right" :style="{ backgroundImage: `url(${referencePreview})`}" />
|
||||
</div>
|
||||
<div v-else-if="cardId && ( attachments.length > 0 )" class="card-cover">
|
||||
<div v-for="(attachment, index) in attachments"
|
||||
:key="attachment.id"
|
||||
class="image-wrapper"
|
||||
:class="['image-wrapper', { 'rounded-left': index === 0 }, { 'rounded-right': index === attachments.length - 1 }]"
|
||||
:style="{ backgroundImage: `url(${attachmentPreview(attachment)})` }" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -74,7 +77,9 @@ export default {
|
||||
.card-cover {
|
||||
height: 90px;
|
||||
display: flex;
|
||||
margin: $card-image-margin $card-image-margin 0;
|
||||
margin-top: -4px;
|
||||
margin-left: -4px;
|
||||
margin-right: -4px;
|
||||
|
||||
.image-wrapper {
|
||||
flex: 1;
|
||||
@@ -82,6 +87,12 @@ export default {
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
&.rounded-left {
|
||||
border-top-left-radius: calc(var(--border-radius-large) - 1px);
|
||||
}
|
||||
&.rounded-right {
|
||||
border-top-right-radius: calc(var(--border-radius-large) - 1px);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<template>
|
||||
<AttachmentDragAndDrop v-if="card" :card-id="card.id" class="drop-upload--card">
|
||||
<div :ref="`card${card.id}`"
|
||||
:class="{'compact': compactMode, 'current-card': currentCard, 'no-labels': !hasLabels, 'card__editable': canEdit, 'card__archived': card.archived, 'card__highlight': highlight}"
|
||||
:class="{'compact': compactMode, 'current-card': currentCard, 'has-labels': card.labels && card.labels.length > 0, 'card__editable': canEdit, 'card__archived': card.archived, 'card__highlight': highlight}"
|
||||
tag="div"
|
||||
:tabindex="0"
|
||||
class="card"
|
||||
@@ -331,14 +331,12 @@ export default {
|
||||
border-radius: var(--border-radius-large);
|
||||
font-size: 100%;
|
||||
background-color: var(--color-main-background);
|
||||
padding: $card-padding;
|
||||
margin-bottom: $card-spacing;
|
||||
padding: var(--default-grid-baseline) $card-padding;
|
||||
border: 2px solid var(--color-border-dark);
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $card-gap;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
|
||||
&:deep(*:not(.dragDisabled)) {
|
||||
cursor: pointer;
|
||||
@@ -361,10 +359,12 @@ export default {
|
||||
h4 {
|
||||
font-weight: normal;
|
||||
margin: 0;
|
||||
padding: var(--default-grid-baseline);
|
||||
flex-grow: 1;
|
||||
font-size: 100%;
|
||||
overflow: hidden;
|
||||
word-wrap: break-word;
|
||||
padding-left: 4px;
|
||||
align-self: center;
|
||||
|
||||
:deep(a) {
|
||||
@@ -374,6 +374,9 @@ export default {
|
||||
&.editable {
|
||||
span {
|
||||
cursor: text;
|
||||
padding-right: 8px;
|
||||
padding-top: 3px;
|
||||
padding-bottom: 3px;
|
||||
|
||||
&:focus, &:focus-visible {
|
||||
outline: none;
|
||||
@@ -382,7 +385,6 @@ export default {
|
||||
|
||||
&:focus-within {
|
||||
outline: 2px solid var(--color-border-dark);
|
||||
outline-offset: 4px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
}
|
||||
@@ -425,6 +427,8 @@ export default {
|
||||
.card-labels {
|
||||
display: flex;
|
||||
align-items: end;
|
||||
padding-left: var(--default-grid-baseline);
|
||||
padding-top: var(--default-grid-baseline);
|
||||
|
||||
.labels {
|
||||
flex-wrap: wrap;
|
||||
@@ -440,7 +444,7 @@ export default {
|
||||
|
||||
.card-related {
|
||||
display: flex;
|
||||
padding: 4px;
|
||||
padding: 12px;
|
||||
padding-bottom: 0px;
|
||||
color: var(--color-text-maxcontrast);
|
||||
|
||||
@@ -465,8 +469,8 @@ export default {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
}
|
||||
&.no-labels {
|
||||
padding-bottom: var(--default-grid-baseline);
|
||||
&.has-labels {
|
||||
padding-bottom: $card-padding;
|
||||
}
|
||||
.labels {
|
||||
height: 6px;
|
||||
|
||||
@@ -14,25 +14,45 @@
|
||||
</div>
|
||||
|
||||
<div v-else-if="isValidFilter" class="overview">
|
||||
<div v-for="columnProps in columnPropsList" :key="columnProps.title" class="dashboard-column">
|
||||
<div class="dashboard-column__header">
|
||||
<h3 class="dashboard-column__header-title"
|
||||
:title="columnProps.title"
|
||||
:aria-label="columnProps.title">
|
||||
{{ t('deck', columnProps.title) }}
|
||||
</h3>
|
||||
<div class="dashboard-column">
|
||||
<h3>{{ t('deck', 'Overdue') }}</h3>
|
||||
<div v-for="card in sortCards('overdue')" :key="card.id">
|
||||
<CardItem :id="card.id" />
|
||||
</div>
|
||||
<div class="dashboard-column__list">
|
||||
<template v-if="columnProps.sort === false">
|
||||
<CardItem v-for="card in filterCards(columnProps.filter)"
|
||||
:id="card.id"
|
||||
:key="card.id" />
|
||||
</template>
|
||||
<template v-else>
|
||||
<CardItem v-for="card in sortCards(filterCards(columnProps.filter))"
|
||||
:id="card.id"
|
||||
:key="card.id" />
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div class="dashboard-column">
|
||||
<h3>{{ t('deck', 'Today') }}</h3>
|
||||
<div v-for="card in sortCards('today')" :key="card.id">
|
||||
<CardItem :id="card.id" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dashboard-column">
|
||||
<h3>{{ t('deck', 'Tomorrow') }}</h3>
|
||||
<div v-for="card in sortCards('tomorrow')" :key="card.id">
|
||||
<CardItem :id="card.id" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dashboard-column">
|
||||
<h3>{{ t('deck', 'Next 7 days') }}</h3>
|
||||
<div v-for="card in sortCards('nextSevenDays')" :key="card.id">
|
||||
<CardItem :id="card.id" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dashboard-column">
|
||||
<h3>{{ t('deck', 'Later') }}</h3>
|
||||
<div v-for="card in sortCards('later')" :key="card.id">
|
||||
<CardItem :id="card.id" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dashboard-column">
|
||||
<h3>{{ t('deck', 'No due') }}</h3>
|
||||
<div v-for="card in assignedCardsDashboard.nodue" :key="card.id">
|
||||
<CardItem :id="card.id" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -53,34 +73,6 @@ const SUPPORTED_FILTERS = [
|
||||
FILTER_UPCOMING,
|
||||
]
|
||||
|
||||
const COLUMN_PROPS_LIST = [
|
||||
{
|
||||
title: 'Overdue',
|
||||
filter: 'overdue',
|
||||
},
|
||||
{
|
||||
title: 'Today',
|
||||
filter: 'today',
|
||||
},
|
||||
{
|
||||
title: 'Tomorrow',
|
||||
filter: 'tomorrow',
|
||||
},
|
||||
{
|
||||
title: 'Next 7 days',
|
||||
filter: 'nextSevenDays',
|
||||
},
|
||||
{
|
||||
title: 'Later',
|
||||
filter: 'later',
|
||||
},
|
||||
{
|
||||
title: 'No due',
|
||||
filter: 'nodue',
|
||||
sort: false,
|
||||
},
|
||||
]
|
||||
|
||||
export default {
|
||||
name: 'Overview',
|
||||
components: {
|
||||
@@ -97,7 +89,6 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
loading: true,
|
||||
columnPropsList: COLUMN_PROPS_LIST,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -134,16 +125,16 @@ export default {
|
||||
}
|
||||
this.loading = false
|
||||
},
|
||||
filterCards(when) {
|
||||
return this.assignedCardsDashboard[when]
|
||||
},
|
||||
sortCards(cards) {
|
||||
sortCards(when) {
|
||||
const cards = this.assignedCardsDashboard[when]
|
||||
|
||||
if (!cards) {
|
||||
return null
|
||||
} else {
|
||||
return cards.toSorted((current, next) => {
|
||||
const currentDueDate = new Date(current.duedate)
|
||||
const nextDueDate = new Date(next.duedate)
|
||||
|
||||
return currentDueDate - nextDueDate
|
||||
})
|
||||
}
|
||||
@@ -160,75 +151,38 @@ export default {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-height: calc(100vh - 50px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.overview {
|
||||
position: relative;
|
||||
overflow-x: auto;
|
||||
flex-grow: 1;
|
||||
scrollbar-gutter: stable;
|
||||
height: calc(100% - var(--default-clickable-area));
|
||||
overflow-x: scroll;
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
gap: $board-gap;
|
||||
padding: 0 $board-gap;
|
||||
padding-left: $board-spacing;
|
||||
padding-right: $board-spacing;
|
||||
|
||||
.dashboard-column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 0 1 $card-max-width;
|
||||
min-width: $card-min-width;
|
||||
min-width: $stack-width;
|
||||
width: $stack-width;
|
||||
margin-left: $stack-spacing;
|
||||
margin-right: $stack-spacing;
|
||||
|
||||
.dashboard-column__header {
|
||||
display: flex;
|
||||
h3 {
|
||||
font-size: var(--default-font-size);
|
||||
margin: -6px;
|
||||
margin-bottom: 12px;
|
||||
padding: 6px 13px;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
height: var(--default-clickable-area);
|
||||
z-index: 100;
|
||||
margin-top: 0;
|
||||
background-color: var(--color-main-background);
|
||||
|
||||
// Smooth fade out of the cards at the top
|
||||
&:before {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 20px;
|
||||
top: 30px;
|
||||
left: 0px;
|
||||
z-index: 99;
|
||||
transition: top var(--animation-slow);
|
||||
background-image: linear-gradient(180deg, var(--color-main-background) 3px, rgba(255, 255, 255, 0) 100%);
|
||||
|
||||
body.theme--dark & {
|
||||
background-image: linear-gradient(180deg, var(--color-main-background) 3px, rgba(0, 0, 0, 0) 100%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dashboard-column__header-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: var(--default-clickable-area);
|
||||
margin: 0;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
padding: $card-padding;
|
||||
font-size: var(--default-font-size);
|
||||
}
|
||||
|
||||
.dashboard-column__list {
|
||||
$margin-x: calc($stack-gap * -1);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $stack-gap;
|
||||
padding: $stack-gap;
|
||||
margin: 0 $margin-x;
|
||||
overflow-y: auto;
|
||||
scrollbar-gutter: stable;
|
||||
border: 1px solid var(--color-main-background);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,19 +4,16 @@
|
||||
-->
|
||||
|
||||
<template>
|
||||
<section v-if="searchQuery!==''" class="global-search">
|
||||
<header class="search-header">
|
||||
<h2>
|
||||
<NcRichText :text="$route.params.id ? t('deck', 'Search for {searchQuery} in other boards') : t('deck', 'Search for {searchQuery} in all boards')"
|
||||
:arguments="queryStringArgs" />
|
||||
<span v-if="loading" class="icon-loading-small" />
|
||||
</h2>
|
||||
<NcActions>
|
||||
<NcActionButton icon="icon-close" @click="$store.commit('setSearchQuery', '')" />
|
||||
</NcActions>
|
||||
</header>
|
||||
<div v-if="searchQuery!==''" class="global-search">
|
||||
<h2>
|
||||
<NcRichText :text="t('deck', 'Search for {searchQuery} in all boards')" :arguments="queryStringArgs" />
|
||||
<div v-if="loading" class="icon-loading-small" />
|
||||
</h2>
|
||||
<NcActions>
|
||||
<NcActionButton icon="icon-close" @click="$store.commit('setSearchQuery', '')" />
|
||||
</NcActions>
|
||||
<div class="search-wrapper">
|
||||
<template v-if="loading || filteredResults.length > 0">
|
||||
<div v-if="loading || filteredResults.length > 0" class="search-results">
|
||||
<CardItem v-for="card in filteredResults"
|
||||
:id="card.id"
|
||||
:key="card.id"
|
||||
@@ -29,12 +26,12 @@
|
||||
{{ t('deck', 'No results found') }}
|
||||
</div>
|
||||
</InfiniteLoading>
|
||||
</template>
|
||||
<template v-else>
|
||||
</div>
|
||||
<div v-else>
|
||||
<p>{{ t('deck', 'No results found') }}</p>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@@ -162,7 +159,7 @@ export default {
|
||||
|
||||
.global-search {
|
||||
width: 100%;
|
||||
padding: $board-gap;
|
||||
padding: $board-spacing + $stack-spacing;
|
||||
padding-bottom: 0;
|
||||
overflow: hidden;
|
||||
min-height: 35vh;
|
||||
@@ -172,24 +169,17 @@ export default {
|
||||
border-top: 1px solid var(--color-border);
|
||||
z-index: 1010;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.action-item.icon-close {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
.search-header {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin: 0;
|
||||
padding: var(--default-grid-baseline) var(--default-grid-baseline) $board-gap;
|
||||
.search-wrapper {
|
||||
overflow: scroll;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
h2 > div {
|
||||
@@ -199,24 +189,23 @@ export default {
|
||||
margin-right: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
h2:deep(span) {
|
||||
background-color: var(--color-background-dark);
|
||||
padding: 3px;
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
|
||||
.search-wrapper {
|
||||
overflow: auto;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
.search-results {
|
||||
display: flex;
|
||||
gap: $stack-gap;
|
||||
flex-wrap: wrap;
|
||||
|
||||
& > .drop-upload--card {
|
||||
flex: 0 1 $card-max-width;
|
||||
min-width: $card-min-width;
|
||||
& > div {
|
||||
flex-grow: 0;
|
||||
}
|
||||
}
|
||||
&:deep(.card) {
|
||||
width: $stack-width;
|
||||
margin-right: $stack-spacing;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -62,13 +62,14 @@ export default {
|
||||
$clickable-area: var(--default-clickable-area);
|
||||
|
||||
.card--placeholder {
|
||||
min-width: $card-min-width;
|
||||
max-width: $card-min-width;
|
||||
width: $stack-width;
|
||||
margin-right: $stack-spacing;
|
||||
padding: $card-padding;
|
||||
transition: box-shadow 0.1s ease-in-out;
|
||||
box-shadow: 0 0 2px 0 var(--color-box-shadow);
|
||||
border-radius: var(--border-radius-large);
|
||||
font-size: 100%;
|
||||
margin-bottom: $card-spacing;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,10 +2,8 @@
|
||||
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
$card-min-width: 216px;
|
||||
$card-max-width: 300px;
|
||||
$card-padding: calc(var(--default-grid-baseline) * 2) calc(var(--default-grid-baseline) * 2) var(--default-grid-baseline);
|
||||
$card-gap: calc(var(--default-grid-baseline) * 3);
|
||||
$card-image-margin: calc(var(--default-grid-baseline) * -2);
|
||||
$stack-gap: calc(var(--default-grid-baseline) * 3);
|
||||
$board-gap: calc(var(--default-grid-baseline) * 4);
|
||||
$card-spacing: 8px;
|
||||
$card-padding: 4px;
|
||||
$stack-spacing: 12px;
|
||||
$stack-width: 280px;
|
||||
$board-spacing: 16px;
|
||||
|
||||
@@ -189,7 +189,7 @@ export default {
|
||||
card.assignedUsers = card.assignedUsers || []
|
||||
const existingIndex = state.cards.findIndex(_card => _card.id === card.id)
|
||||
if (existingIndex !== -1) {
|
||||
const existingCard = state.cards[existingIndex]
|
||||
const existingCard = state.cards.find(_card => _card.id === card.id)
|
||||
Vue.set(state.cards, existingIndex, Object.assign({}, existingCard, card))
|
||||
} else {
|
||||
state.cards.push(card)
|
||||
|
||||
@@ -90,8 +90,8 @@
|
||||
}
|
||||
],
|
||||
"assignedUsers": [],
|
||||
"attachments": [],
|
||||
"attachmentCount": 0,
|
||||
"attachments": null,
|
||||
"attachmentCount": null,
|
||||
"owner": {
|
||||
"primaryKey": "admin",
|
||||
"uid": "admin",
|
||||
@@ -123,8 +123,8 @@
|
||||
"createdAt": 1689667572,
|
||||
"labels": [],
|
||||
"assignedUsers": [],
|
||||
"attachments": [],
|
||||
"attachmentCount": 0,
|
||||
"attachments": null,
|
||||
"attachmentCount": null,
|
||||
"owner": {
|
||||
"primaryKey": "admin",
|
||||
"uid": "admin",
|
||||
@@ -168,8 +168,8 @@
|
||||
"type": 0
|
||||
}
|
||||
],
|
||||
"attachments": [],
|
||||
"attachmentCount": 0,
|
||||
"attachments": null,
|
||||
"attachmentCount": null,
|
||||
"owner": {
|
||||
"primaryKey": "admin",
|
||||
"uid": "admin",
|
||||
@@ -240,8 +240,8 @@
|
||||
}
|
||||
],
|
||||
"assignedUsers": [],
|
||||
"attachments": [],
|
||||
"attachmentCount": 0,
|
||||
"attachments": null,
|
||||
"attachmentCount": null,
|
||||
"owner": {
|
||||
"primaryKey": "admin",
|
||||
"uid": "admin",
|
||||
@@ -283,8 +283,8 @@
|
||||
}
|
||||
],
|
||||
"assignedUsers": [],
|
||||
"attachments": [],
|
||||
"attachmentCount": 0,
|
||||
"attachments": null,
|
||||
"attachmentCount": null,
|
||||
"owner": {
|
||||
"primaryKey": "admin",
|
||||
"uid": "admin",
|
||||
@@ -328,8 +328,8 @@
|
||||
"type": 0
|
||||
}
|
||||
],
|
||||
"attachments": [],
|
||||
"attachmentCount": 0,
|
||||
"attachments": null,
|
||||
"attachmentCount": null,
|
||||
"owner": {
|
||||
"primaryKey": "admin",
|
||||
"uid": "admin",
|
||||
@@ -493,8 +493,8 @@
|
||||
"createdAt": 1689667483,
|
||||
"labels": [],
|
||||
"assignedUsers": [],
|
||||
"attachments": [],
|
||||
"attachmentCount": 0,
|
||||
"attachments": null,
|
||||
"attachmentCount": null,
|
||||
"owner": {
|
||||
"primaryKey": "admin",
|
||||
"uid": "admin",
|
||||
@@ -526,8 +526,8 @@
|
||||
"createdAt": 1689667518,
|
||||
"labels": [],
|
||||
"assignedUsers": [],
|
||||
"attachments": [],
|
||||
"attachmentCount": 0,
|
||||
"attachments": null,
|
||||
"attachmentCount": null,
|
||||
"owner": {
|
||||
"primaryKey": "admin",
|
||||
"uid": "admin",
|
||||
@@ -559,8 +559,8 @@
|
||||
"createdAt": 1689667527,
|
||||
"labels": [],
|
||||
"assignedUsers": [],
|
||||
"attachments": [],
|
||||
"attachmentCount": 0,
|
||||
"attachments": null,
|
||||
"attachmentCount": null,
|
||||
"owner": {
|
||||
"primaryKey": "admin",
|
||||
"uid": "admin",
|
||||
@@ -592,8 +592,8 @@
|
||||
"createdAt": 1689667537,
|
||||
"labels": [],
|
||||
"assignedUsers": [],
|
||||
"attachments": [],
|
||||
"attachmentCount": 0,
|
||||
"attachments": null,
|
||||
"attachmentCount": null,
|
||||
"owner": {
|
||||
"primaryKey": "admin",
|
||||
"uid": "admin",
|
||||
@@ -636,8 +636,8 @@
|
||||
"createdAt": 1689667488,
|
||||
"labels": [],
|
||||
"assignedUsers": [],
|
||||
"attachments": [],
|
||||
"attachmentCount": 0,
|
||||
"attachments": null,
|
||||
"attachmentCount": null,
|
||||
"owner": {
|
||||
"primaryKey": "admin",
|
||||
"uid": "admin",
|
||||
@@ -680,8 +680,8 @@
|
||||
"createdAt": 1689667493,
|
||||
"labels": [],
|
||||
"assignedUsers": [],
|
||||
"attachments": [],
|
||||
"attachmentCount": 0,
|
||||
"attachments": null,
|
||||
"attachmentCount": null,
|
||||
"owner": {
|
||||
"primaryKey": "admin",
|
||||
"uid": "admin",
|
||||
@@ -713,8 +713,8 @@
|
||||
"createdAt": 1689667502,
|
||||
"labels": [],
|
||||
"assignedUsers": [],
|
||||
"attachments": [],
|
||||
"attachmentCount": 0,
|
||||
"attachments": null,
|
||||
"attachmentCount": null,
|
||||
"owner": {
|
||||
"primaryKey": "admin",
|
||||
"uid": "admin",
|
||||
|
||||
@@ -1 +1 @@
|
||||
82774
|
||||
82773
|
||||
|
||||
@@ -1,78 +1,152 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<files psalm-version="6.5.0@38fc8444edf0cebc9205296ee6e30e906ade783b">
|
||||
<files psalm-version="5.6.0@e784128902dfe01d489c4123d69918a9f3c1eac5">
|
||||
<file src="lib/Activity/Filter.php">
|
||||
<MethodSignatureMismatch>
|
||||
<code><![CDATA[$types]]></code>
|
||||
<code>$types</code>
|
||||
</MethodSignatureMismatch>
|
||||
</file>
|
||||
<file src="lib/Command/UserExport.php">
|
||||
<ImplementedReturnTypeMismatch>
|
||||
<code>void</code>
|
||||
</ImplementedReturnTypeMismatch>
|
||||
<UndefinedThisPropertyAssignment>
|
||||
<code>$this->boardMapper</code>
|
||||
<code>$this->stackMapper</code>
|
||||
</UndefinedThisPropertyAssignment>
|
||||
<UndefinedThisPropertyFetch>
|
||||
<code>$this->boardMapper</code>
|
||||
<code>$this->stackMapper</code>
|
||||
</UndefinedThisPropertyFetch>
|
||||
</file>
|
||||
<file src="lib/Controller/BoardApiController.php">
|
||||
<UndefinedFunction>
|
||||
<code><![CDATA[parseDate($modified)]]></code>
|
||||
</UndefinedFunction>
|
||||
<TypeDoesNotContainNull>
|
||||
<code>$modified === null</code>
|
||||
<code>$modified === null</code>
|
||||
</TypeDoesNotContainNull>
|
||||
<UndefinedClass>
|
||||
<code>Util</code>
|
||||
</UndefinedClass>
|
||||
<UndefinedThisPropertyAssignment>
|
||||
<code>$this->userId</code>
|
||||
</UndefinedThisPropertyAssignment>
|
||||
<UndefinedThisPropertyFetch>
|
||||
<code>$this->userId</code>
|
||||
</UndefinedThisPropertyFetch>
|
||||
</file>
|
||||
<file src="lib/Controller/CommentsApiController.php">
|
||||
<InvalidScalarArgument>
|
||||
<code>$cardId</code>
|
||||
<code>$cardId</code>
|
||||
<code>$cardId</code>
|
||||
<code>$commentId</code>
|
||||
<code>$commentId</code>
|
||||
<code>$parentId</code>
|
||||
</InvalidScalarArgument>
|
||||
</file>
|
||||
<file src="lib/Controller/PageController.php">
|
||||
<UndefinedClass>
|
||||
<code><![CDATA[LoadSidebar]]></code>
|
||||
<code>LoadSidebar</code>
|
||||
</UndefinedClass>
|
||||
</file>
|
||||
<file src="lib/Controller/StackApiController.php">
|
||||
<UndefinedFunction>
|
||||
<code><![CDATA[parseDate($modified)]]></code>
|
||||
</UndefinedFunction>
|
||||
<RedundantCondition>
|
||||
<code>$modified !== null</code>
|
||||
</RedundantCondition>
|
||||
<UndefinedClass>
|
||||
<code>Util</code>
|
||||
</UndefinedClass>
|
||||
</file>
|
||||
<file src="lib/DAV/Calendar.php">
|
||||
<UndefinedClass>
|
||||
<code><![CDATA[ExternalCalendar]]></code>
|
||||
<code>ExternalCalendar</code>
|
||||
</UndefinedClass>
|
||||
</file>
|
||||
<file src="lib/DAV/CalendarObject.php">
|
||||
<UndefinedClass>
|
||||
<code><![CDATA[ICalendarObject]]></code>
|
||||
<code>ICalendarObject</code>
|
||||
</UndefinedClass>
|
||||
</file>
|
||||
<file src="lib/DAV/CalendarPlugin.php">
|
||||
<UndefinedClass>
|
||||
<code><![CDATA[ICalendarProvider]]></code>
|
||||
<code>ICalendarProvider</code>
|
||||
</UndefinedClass>
|
||||
</file>
|
||||
<file src="lib/DAV/DeckCalendarBackend.php">
|
||||
<UndefinedClass>
|
||||
<code><![CDATA[NotFound]]></code>
|
||||
<code>NotFound</code>
|
||||
</UndefinedClass>
|
||||
</file>
|
||||
<file src="lib/Db/Card.php">
|
||||
<UndefinedClass>
|
||||
<code><![CDATA[VCalendar]]></code>
|
||||
<code><![CDATA[VCalendar]]></code>
|
||||
<code>VCalendar</code>
|
||||
<code>VCalendar</code>
|
||||
</UndefinedClass>
|
||||
</file>
|
||||
<file src="lib/Db/CardMapper.php">
|
||||
<InvalidScalarArgument>
|
||||
<code>$entity->getId()</code>
|
||||
</InvalidScalarArgument>
|
||||
<UndefinedInterfaceMethod>
|
||||
<code>getUserIdGroups</code>
|
||||
</UndefinedInterfaceMethod>
|
||||
</file>
|
||||
<file src="lib/Db/LabelMapper.php">
|
||||
<ParamNameMismatch>
|
||||
<code>$labelId</code>
|
||||
</ParamNameMismatch>
|
||||
</file>
|
||||
<file src="lib/Db/Stack.php">
|
||||
<UndefinedClass>
|
||||
<code><![CDATA[VCalendar]]></code>
|
||||
<code><![CDATA[VCalendar]]></code>
|
||||
<code>VCalendar</code>
|
||||
<code>VCalendar</code>
|
||||
</UndefinedClass>
|
||||
</file>
|
||||
<file src="lib/Model/BoardSummary.php">
|
||||
<ConstructorSignatureMismatch>
|
||||
<code>public function __construct(Board $board) {</code>
|
||||
<code>public function __construct(Board $board) {</code>
|
||||
</ConstructorSignatureMismatch>
|
||||
</file>
|
||||
<file src="lib/Model/CardDetails.php">
|
||||
<ConstructorSignatureMismatch>
|
||||
<code>public function __construct(Card $card, ?Board $board = null) {</code>
|
||||
<code>public function __construct(Card $card, ?Board $board = null) {</code>
|
||||
</ConstructorSignatureMismatch>
|
||||
</file>
|
||||
<file src="lib/Service/AttachmentService.php">
|
||||
<InvalidCatch>
|
||||
<code>try {
|
||||
$attachment = $this->attachmentMapper->find($attachmentId);
|
||||
} catch (IMapperException $e) {
|
||||
throw new NoPermissionException('Permission denied');
|
||||
}</code>
|
||||
</InvalidCatch>
|
||||
</file>
|
||||
<file src="lib/Service/BoardService.php">
|
||||
<TooManyArguments>
|
||||
<code>findAll</code>
|
||||
<code>findAll</code>
|
||||
</TooManyArguments>
|
||||
</file>
|
||||
<file src="lib/Service/CirclesService.php">
|
||||
<RedundantCondition>
|
||||
<code>$member !== null</code>
|
||||
</RedundantCondition>
|
||||
</file>
|
||||
<file src="lib/Service/FileService.php">
|
||||
<RedundantCondition>
|
||||
<code><![CDATA[is_resource($content)]]></code>
|
||||
<code><![CDATA[is_resource($content)]]></code>
|
||||
<code>is_resource($content)</code>
|
||||
<code>is_resource($content)</code>
|
||||
</RedundantCondition>
|
||||
</file>
|
||||
<file src="lib/Service/Importer/BoardImportCommandService.php">
|
||||
<UndefinedInterfaceMethod>
|
||||
<code><![CDATA[ask]]></code>
|
||||
<code><![CDATA[ask]]></code>
|
||||
<code><![CDATA[ask]]></code>
|
||||
</UndefinedInterfaceMethod>
|
||||
<file src="lib/Sharing/DeckShareProvider.php">
|
||||
<InvalidReturnType>
|
||||
<code>getShareByToken</code>
|
||||
</InvalidReturnType>
|
||||
</file>
|
||||
<file src="lib/Service/Importer/Systems/TrelloJsonService.php">
|
||||
<InvalidPropertyFetch>
|
||||
<code><![CDATA[$createCardDate->date]]></code>
|
||||
</InvalidPropertyFetch>
|
||||
</file>
|
||||
<file src="lib/Teams/DeckTeamResourceProvider.php">
|
||||
<FalsableReturnStatement>
|
||||
<code><![CDATA[file_get_contents(__DIR__ . '/../../img/deck-current.svg')]]></code>
|
||||
</FalsableReturnStatement>
|
||||
<file src="lib/Sharing/Listener.php">
|
||||
<InvalidArgument>
|
||||
<code>[self::class, 'listenPreShare']</code>
|
||||
</InvalidArgument>
|
||||
</file>
|
||||
</files>
|
||||
|
||||
@@ -160,7 +160,6 @@ class ActivityManagerTest extends TestCase {
|
||||
'id' => 123,
|
||||
'title' => 'My card',
|
||||
'description' => str_repeat('A', 1000),
|
||||
'stackId' => 42,
|
||||
]);
|
||||
$this->cardMapper->expects(self::any())
|
||||
->method('find')
|
||||
@@ -171,7 +170,6 @@ class ActivityManagerTest extends TestCase {
|
||||
]);
|
||||
$this->stackMapper->expects(self::any())
|
||||
->method('find')
|
||||
->with(42)
|
||||
->willReturn($stack);
|
||||
|
||||
$expectedCard = $card->jsonSerialize();
|
||||
@@ -209,7 +207,6 @@ class ActivityManagerTest extends TestCase {
|
||||
$card->setDescription(str_repeat('A', 5000));
|
||||
$card->setTitle('My card');
|
||||
$card->setId(123);
|
||||
$card->setStackId(42);
|
||||
$this->cardMapper->expects(self::any())
|
||||
->method('find')
|
||||
->willReturn($card);
|
||||
@@ -257,7 +254,6 @@ class ActivityManagerTest extends TestCase {
|
||||
$card->setDescription(str_repeat('A', 5000));
|
||||
$card->setTitle('My card');
|
||||
$card->setId(123);
|
||||
$card->setStackId(42);
|
||||
$this->cardMapper->expects(self::any())
|
||||
->method('find')
|
||||
->willReturn($card);
|
||||
|
||||
@@ -119,7 +119,7 @@ class AttachmentMapperTest extends TestCase {
|
||||
->method('isOwner')
|
||||
->with('admin', 1)
|
||||
->willReturn(true);
|
||||
$this->assertTrue($this->attachmentMapper->isOwner('admin', $this->attachments[0]->getId()));
|
||||
$this->assertTrue($this->attachmentMapper->isOwner('admin', (string)$this->attachments[0]->getId()));
|
||||
}
|
||||
|
||||
public function testIsOwnerInvalid() {
|
||||
@@ -127,7 +127,7 @@ class AttachmentMapperTest extends TestCase {
|
||||
->method('isOwner')
|
||||
->with('admin', 1)
|
||||
->will($this->throwException(new DoesNotExistException('does not exist')));
|
||||
$this->assertFalse($this->attachmentMapper->isOwner('admin', $this->attachments[0]->getId()));
|
||||
$this->assertFalse($this->attachmentMapper->isOwner('admin', (string)$this->attachments[0]->getId()));
|
||||
}
|
||||
|
||||
public function testFindBoardId() {
|
||||
|
||||
@@ -81,8 +81,8 @@ class CardTest extends TestCase {
|
||||
'duedate' => null,
|
||||
'overdue' => 0,
|
||||
'archived' => false,
|
||||
'attachments' => [],
|
||||
'attachmentCount' => 0,
|
||||
'attachments' => null,
|
||||
'attachmentCount' => null,
|
||||
'assignedUsers' => null,
|
||||
'deletedAt' => 0,
|
||||
'commentsUnread' => 0,
|
||||
@@ -110,8 +110,8 @@ class CardTest extends TestCase {
|
||||
'duedate' => null,
|
||||
'overdue' => 0,
|
||||
'archived' => false,
|
||||
'attachments' => [],
|
||||
'attachmentCount' => 0,
|
||||
'attachments' => null,
|
||||
'attachmentCount' => null,
|
||||
'assignedUsers' => null,
|
||||
'deletedAt' => 0,
|
||||
'commentsUnread' => 0,
|
||||
@@ -141,8 +141,8 @@ class CardTest extends TestCase {
|
||||
'duedate' => null,
|
||||
'overdue' => 0,
|
||||
'archived' => false,
|
||||
'attachments' => [],
|
||||
'attachmentCount' => 0,
|
||||
'attachments' => null,
|
||||
'attachmentCount' => null,
|
||||
'assignedUsers' => ['user1'],
|
||||
'deletedAt' => 0,
|
||||
'commentsUnread' => 0,
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
|
||||
*
|
||||
@@ -118,7 +116,7 @@ class AttachmentServiceTest extends TestCase {
|
||||
$this->activityManager = $this->createMock(ActivityManager::class);
|
||||
|
||||
$this->appContainer->expects($this->exactly(2))
|
||||
->method('get')
|
||||
->method('query')
|
||||
->withConsecutive(
|
||||
[FileService::class],
|
||||
[FilesAppService::class]
|
||||
@@ -158,7 +156,7 @@ class AttachmentServiceTest extends TestCase {
|
||||
$fileAppServiceMock = $this->createMock(FilesAppService::class);
|
||||
|
||||
$appContainer->expects($this->exactly(3))
|
||||
->method('get')
|
||||
->method('query')
|
||||
->withConsecutive(
|
||||
[FileService::class],
|
||||
[FilesAppService::class],
|
||||
@@ -187,7 +185,7 @@ class AttachmentServiceTest extends TestCase {
|
||||
$fileAppServiceMock = $this->createMock(FilesAppService::class);
|
||||
|
||||
$appContainer->expects($this->exactly(3))
|
||||
->method('get')
|
||||
->method('query')
|
||||
->withConsecutive(
|
||||
[FileService::class],
|
||||
[FilesAppService::class],
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2016 Julius Härtl <jus@bitgrid.net>
|
||||
*
|
||||
@@ -242,7 +240,6 @@ class BoardServiceTest extends TestCase {
|
||||
|
||||
public function testDelete() {
|
||||
$board = new Board();
|
||||
$board->setId(42);
|
||||
$board->setOwner('admin');
|
||||
$board->setDeletedAt(0);
|
||||
$this->boardMapper->expects($this->once())
|
||||
@@ -255,7 +252,7 @@ class BoardServiceTest extends TestCase {
|
||||
]);
|
||||
$this->sessionMapper->expects($this->once())
|
||||
->method('findAllActive')
|
||||
->with(42)
|
||||
->with(null)
|
||||
->willReturn([]);
|
||||
$boardDeleted = clone $board;
|
||||
$boardDeleted->setDeletedAt(1);
|
||||
@@ -270,7 +267,7 @@ class BoardServiceTest extends TestCase {
|
||||
$user->method('getUID')->willReturn('admin');
|
||||
$acl = new Acl();
|
||||
$acl->setBoardId(123);
|
||||
$acl->setType(Acl::PERMISSION_TYPE_USER);
|
||||
$acl->setType('user');
|
||||
$acl->setParticipant('admin');
|
||||
$acl->setPermissionEdit(true);
|
||||
$acl->setPermissionShare(true);
|
||||
@@ -290,7 +287,7 @@ class BoardServiceTest extends TestCase {
|
||||
'admin' => 'admin',
|
||||
]);
|
||||
$this->assertEquals($acl, $this->service->addAcl(
|
||||
123, Acl::PERMISSION_TYPE_USER, 'admin', true, true, true
|
||||
123, 'user', 'admin', true, true, true
|
||||
));
|
||||
}
|
||||
|
||||
@@ -326,7 +323,7 @@ class BoardServiceTest extends TestCase {
|
||||
public function testAddAclExtendPermission($currentUserAcl, $providedAcl, $resultingAcl) {
|
||||
$existingAcl = new Acl();
|
||||
$existingAcl->setBoardId(123);
|
||||
$existingAcl->setType(Acl::PERMISSION_TYPE_USER);
|
||||
$existingAcl->setType('user');
|
||||
$existingAcl->setParticipant('admin');
|
||||
$existingAcl->setPermissionEdit($currentUserAcl[0]);
|
||||
$existingAcl->setPermissionShare($currentUserAcl[1]);
|
||||
@@ -394,14 +391,14 @@ class BoardServiceTest extends TestCase {
|
||||
->method('dispatchTyped')
|
||||
->with(new AclCreatedEvent($acl));
|
||||
$this->assertEquals($expected, $this->service->addAcl(
|
||||
123, Acl::PERMISSION_TYPE_USER, 'admin', $providedAcl[0], $providedAcl[1], $providedAcl[2]
|
||||
123, 'user', 'admin', $providedAcl[0], $providedAcl[1], $providedAcl[2]
|
||||
));
|
||||
}
|
||||
|
||||
public function testUpdateAcl() {
|
||||
$acl = new Acl();
|
||||
$acl->setBoardId(123);
|
||||
$acl->setType(Acl::PERMISSION_TYPE_USER);
|
||||
$acl->setType('user');
|
||||
$acl->setParticipant('admin');
|
||||
$acl->setPermissionEdit(true);
|
||||
$acl->setPermissionShare(true);
|
||||
|
||||
@@ -183,7 +183,6 @@ class CardServiceTest extends TestCase {
|
||||
->willReturn($boardMock);
|
||||
$card = new Card();
|
||||
$card->setId(1337);
|
||||
$card->setStackId(123);
|
||||
$this->cardMapper->expects($this->any())
|
||||
->method('find')
|
||||
->with(123)
|
||||
@@ -201,7 +200,6 @@ class CardServiceTest extends TestCase {
|
||||
->with([1337])
|
||||
->willReturn([$a1, $a2]);
|
||||
$cardExpected = new Card();
|
||||
$cardExpected->setStackId(123);
|
||||
$cardExpected->setId(1337);
|
||||
$cardExpected->setAssignedUsers([$a1, $a2]);
|
||||
$cardExpected->setRelatedBoard($boardMock);
|
||||
@@ -220,7 +218,6 @@ class CardServiceTest extends TestCase {
|
||||
'stackId' => 123,
|
||||
'order' => 999,
|
||||
'type' => 'text',
|
||||
'id' => 0,
|
||||
]);
|
||||
$stack = Stack::fromParams([
|
||||
'id' => 123,
|
||||
@@ -246,8 +243,6 @@ class CardServiceTest extends TestCase {
|
||||
$card = new Card();
|
||||
$card->setId(1);
|
||||
$card->setTitle('Card title');
|
||||
$card->setType('test');
|
||||
$card->setOrder(0);
|
||||
$card->setOwner('admin');
|
||||
$card->setStackId(12345);
|
||||
$clonedCard = clone $card;
|
||||
@@ -295,7 +290,8 @@ class CardServiceTest extends TestCase {
|
||||
->willReturn([$label]);
|
||||
$this->cardMapper->expects($this->once())
|
||||
->method('assignLabel')
|
||||
->with($clonedCard->getId(), $label->getId());
|
||||
->with($clonedCard->getId(), $label->getId())
|
||||
->willReturn($label);
|
||||
|
||||
$stackMock = new Stack();
|
||||
$stackMock->setBoardId(1234);
|
||||
@@ -333,7 +329,6 @@ class CardServiceTest extends TestCase {
|
||||
]);
|
||||
$this->cardMapper->expects($this->once())->method('find')->willReturn($card);
|
||||
$this->cardMapper->expects($this->once())->method('update')->willReturnCallback(function ($c) {
|
||||
$c->setId(1);
|
||||
return $c;
|
||||
});
|
||||
$this->stackMapper->expects($this->once())
|
||||
|
||||
@@ -220,9 +220,8 @@ class DefaultBoardServiceTest extends TestCase {
|
||||
return $stack;
|
||||
}
|
||||
|
||||
private function assembleTestCard(string $title, int $stackId, string $userId): Card {
|
||||
private function assembleTestCard($title, $stackId, $userId) {
|
||||
$card = new Card();
|
||||
$card->setId(1);
|
||||
$card->setTitle($title);
|
||||
$card->setStackId($stackId);
|
||||
$card->setType('text');
|
||||
|
||||
@@ -192,17 +192,14 @@ class BoardImportServiceTest extends \Test\TestCase {
|
||||
->expects($this->once())
|
||||
->method('save');
|
||||
|
||||
$assignment = new Assignment();
|
||||
$assignment->setId(1);
|
||||
$this->trelloJsonService
|
||||
->method('getCardAssignments')
|
||||
->willReturn([
|
||||
'fakecardid' => [$assignment]
|
||||
'fakecardid' => [new Assignment()]
|
||||
]);
|
||||
$this->assignmentMapper
|
||||
->expects($this->once())
|
||||
->method('insert')
|
||||
->willReturn($assignment);
|
||||
->method('insert');
|
||||
|
||||
$this->boardImportService->import();
|
||||
self::assertTrue(true);
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2016 Julius Härtl <jus@bitgrid.net>
|
||||
*
|
||||
@@ -31,7 +29,6 @@ use OCA\Deck\Db\ChangeHelper;
|
||||
use OCA\Deck\Db\Label;
|
||||
use OCA\Deck\Db\LabelMapper;
|
||||
use OCA\Deck\Validators\LabelServiceValidator;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use Test\TestCase;
|
||||
|
||||
class LabelServiceTest extends TestCase {
|
||||
@@ -45,8 +42,9 @@ class LabelServiceTest extends TestCase {
|
||||
/** @var BoardService|\PHPUnit\Framework\MockObject\MockObject */
|
||||
private $boardService;
|
||||
/** @var ChangeHelper|\PHPUnit\Framework\MockObject\MockObject */
|
||||
private ChangeHelper&MockObject $changeHelper;
|
||||
private LabelServiceValidator&MockObject $labelServiceValidator;
|
||||
private $changeHelper;
|
||||
/** @var LabelServiceValidator\MockObject */
|
||||
private $labelServiceValidator;
|
||||
|
||||
public function setUp(): void {
|
||||
parent::setUp();
|
||||
@@ -68,9 +66,8 @@ class LabelServiceTest extends TestCase {
|
||||
}
|
||||
|
||||
public function testFind() {
|
||||
$label = $this->createMock(Label::class);
|
||||
$this->labelMapper->expects($this->once())->method('find')->willReturn($label);
|
||||
$this->assertEquals($label, $this->labelService->find(123));
|
||||
$this->labelMapper->expects($this->once())->method('find')->willReturn(true);
|
||||
$this->assertTrue($this->labelService->find(123));
|
||||
}
|
||||
|
||||
public function testCreate() {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2016 Julius Härtl <jus@bitgrid.net>
|
||||
*
|
||||
@@ -50,7 +48,8 @@ use Test\TestCase;
|
||||
*/
|
||||
class StackServiceTest extends TestCase {
|
||||
|
||||
private StackService $stackService;
|
||||
/** @var StackService */
|
||||
private $stackService;
|
||||
/** @var \PHPUnit\Framework\MockObject\MockObject|StackMapper */
|
||||
private $stackMapper;
|
||||
/** @var \PHPUnit\Framework\MockObject\MockObject|CardMapper */
|
||||
@@ -130,17 +129,12 @@ class StackServiceTest extends TestCase {
|
||||
}
|
||||
)
|
||||
);
|
||||
$this->cardMapper->expects($this->any())->method('findAllForStacks')->willReturnCallback(function (array $stackIds) {
|
||||
$r = [];
|
||||
foreach ($stackIds as $stackId) {
|
||||
$r[$stackId] = $this->getCards(222);
|
||||
}
|
||||
return $r;
|
||||
});
|
||||
$this->cardMapper->expects($this->any())->method('findAll')->willReturn($this->getCards(222));
|
||||
|
||||
|
||||
$actual = $this->stackService->findAll(123);
|
||||
for ($stackId = 0; $stackId < 3; $stackId++) {
|
||||
for ($cardId = 0; $cardId < 10; $cardId++) {
|
||||
for ($cardId = 0;$cardId < 10;$cardId++) {
|
||||
$this->assertEquals($actual[0]->getCards()[$cardId]->getId(), $cardId);
|
||||
$this->assertEquals($actual[0]->getCards()[$cardId]->getStackId(), 222);
|
||||
$this->assertEquals($actual[0]->getCards()[$cardId]->getLabels(), $this->getLabels()[$cardId]);
|
||||
@@ -217,7 +211,7 @@ class StackServiceTest extends TestCase {
|
||||
$stackToBeDeleted->setBoardId(1);
|
||||
$this->stackMapper->expects($this->once())->method('find')->willReturn($stackToBeDeleted);
|
||||
$this->stackMapper->expects($this->once())->method('update')->willReturn($stackToBeDeleted);
|
||||
$this->cardMapper->expects($this->once())->method('findAllForStacks')->willReturn([]);
|
||||
$this->cardMapper->expects($this->once())->method('findAll')->willReturn([]);
|
||||
$this->stackService->delete(123);
|
||||
$this->assertTrue($stackToBeDeleted->getDeletedAt() <= time(), 'deletedAt is in the past');
|
||||
$this->assertTrue($stackToBeDeleted->getDeletedAt() > 0, 'deletedAt is set');
|
||||
@@ -252,9 +246,6 @@ class StackServiceTest extends TestCase {
|
||||
$this->stackMapper->expects($this->once())
|
||||
->method('findAll')
|
||||
->willReturn($stacks);
|
||||
$this->stackMapper->expects($this->any())
|
||||
->method('update')
|
||||
->willReturnCallback(fn (Stack $stack): Stack => $stack);
|
||||
$actual = $this->stackService->reorder(1, 2);
|
||||
$a = $this->createStack(1, 2);
|
||||
$b = $this->createStack(2, 0);
|
||||
@@ -263,7 +254,7 @@ class StackServiceTest extends TestCase {
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
private function createStack(int $id, int $order) {
|
||||
private function createStack($id, $order) {
|
||||
$stack = new Stack();
|
||||
$stack->setId($id);
|
||||
$stack->setBoardId(1);
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2016 Julius Härtl <jus@bitgrid.net>
|
||||
*
|
||||
@@ -28,47 +26,46 @@ namespace OCA\Deck\Controller;
|
||||
|
||||
use OCA\Deck\Db\Acl;
|
||||
use OCA\Deck\Db\Board;
|
||||
use OCA\Deck\Service\BoardService;
|
||||
use OCA\Deck\Service\Importer\BoardImportService;
|
||||
use OCA\Deck\Service\PermissionService;
|
||||
use OCP\IGroupManager;
|
||||
use OCP\IL10N;
|
||||
use OCP\IRequest;
|
||||
use OCP\IUser;
|
||||
use OCP\IUserManager;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
|
||||
class BoardControllerTest extends \Test\TestCase {
|
||||
private IL10N&MockObject $l10n;
|
||||
private BoardController $controller;
|
||||
private IRequest&MockObject $request;
|
||||
private IUserManager&MockObject $userManager;
|
||||
private IGroupManager&MockObject $groupManager;
|
||||
private BoardService&MockObject $boardService;
|
||||
private PermissionService&MockObject $permissionService;
|
||||
private BoardImportService&MockObject $boardImportService;
|
||||
private $l10n;
|
||||
private $controller;
|
||||
private $request;
|
||||
private $userManager;
|
||||
private $groupManager;
|
||||
private $boardService;
|
||||
private $permissionService;
|
||||
private $boardImportService;
|
||||
private $userId = 'user';
|
||||
|
||||
public function setUp(): void {
|
||||
$this->l10n = $this->getMockBuilder(IL10N::class)
|
||||
$this->l10n = $this->request = $this->getMockBuilder(
|
||||
'\OCP\IL10n')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->request = $this->getMockBuilder(IRequest::class)
|
||||
$this->request = $this->getMockBuilder(
|
||||
'\OCP\IRequest')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->userManager = $this->getMockBuilder(IUserManager::class)
|
||||
$this->userManager = $this->getMockBuilder(
|
||||
'\OCP\IUserManager')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->groupManager = $this->getMockBuilder(IGroupManager::class)
|
||||
$this->groupManager = $this->getMockBuilder(
|
||||
'\OCP\IGroupManager')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->boardService = $this->getMockBuilder(BoardService::class)
|
||||
$this->boardService = $this->getMockBuilder(
|
||||
'\OCA\Deck\Service\BoardService')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->permissionService = $this->getMockBuilder(PermissionService::class)
|
||||
$this->permissionService = $this->getMockBuilder(
|
||||
'\OCA\Deck\Service\PermissionService')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->boardImportService = $this->getMockBuilder(BoardImportService::class)
|
||||
$this->boardImportService = $this->getMockBuilder(
|
||||
'\OCA\Deck\Service\Importer\BoardImportService')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
@@ -110,39 +107,35 @@ class BoardControllerTest extends \Test\TestCase {
|
||||
}
|
||||
|
||||
public function testCreate() {
|
||||
$board = $this->createMock(Board::class);
|
||||
$this->boardService->expects($this->once())
|
||||
->method('create')
|
||||
->with('abc', 'user', 'green')
|
||||
->willReturn($board);
|
||||
$this->assertEquals($board, $this->controller->create('abc', 'green'));
|
||||
->with(1, 'user', 3)
|
||||
->willReturn(1);
|
||||
$this->assertEquals(1, $this->controller->create(1, 3));
|
||||
}
|
||||
|
||||
public function testUpdate(): void {
|
||||
$board = $this->createMock(Board::class);
|
||||
public function testUpdate() {
|
||||
$this->boardService->expects($this->once())
|
||||
->method('update')
|
||||
->with(1, 'abc', 'green', false)
|
||||
->willReturn($board);
|
||||
$this->assertEquals($board, $this->controller->update(1, 'abc', 'green', false));
|
||||
->with(1, 2, 3, false)
|
||||
->willReturn(1);
|
||||
$this->assertEquals(1, $this->controller->update(1, 2, 3, false));
|
||||
}
|
||||
|
||||
public function testDelete(): void {
|
||||
$board = $this->createMock(Board::class);
|
||||
public function testDelete() {
|
||||
$this->boardService->expects($this->once())
|
||||
->method('delete')
|
||||
->with(123)
|
||||
->willReturn($board);
|
||||
$this->assertEquals($board, $this->controller->delete(123));
|
||||
->willReturn(1);
|
||||
$this->assertEquals(1, $this->controller->delete(123));
|
||||
}
|
||||
|
||||
public function testDeleteUndo() {
|
||||
$board = $this->createMock(Board::class);
|
||||
$this->boardService->expects($this->once())
|
||||
->method('deleteUndo')
|
||||
->with(123)
|
||||
->willReturn($board);
|
||||
$this->assertEquals($board, $this->controller->deleteUndo(123));
|
||||
->willReturn(1);
|
||||
$this->assertEquals(1, $this->controller->deleteUndo(123));
|
||||
}
|
||||
|
||||
public function testGetUserPermissions() {
|
||||
@@ -165,22 +158,20 @@ class BoardControllerTest extends \Test\TestCase {
|
||||
$this->assertEquals($expected, $this->controller->getUserPermissions(123));
|
||||
}
|
||||
|
||||
public function testAddAcl(): void {
|
||||
$acl = $this->createMock(Acl::class);
|
||||
public function testAddAcl() {
|
||||
$this->boardService->expects($this->once())
|
||||
->method('addAcl')
|
||||
->with(1, 2, 'user1', true, true, true)
|
||||
->willReturn($acl);
|
||||
$this->assertEquals($acl, $this->controller->addAcl(1, 2, 'user1', true, true, true));
|
||||
->with(1, 2, 3, 4, 5, 6)
|
||||
->willReturn(1);
|
||||
$this->assertEquals(1, $this->controller->addAcl(1, 2, 3, 4, 5, 6));
|
||||
}
|
||||
|
||||
public function testUpdateAcl(): void {
|
||||
$acl = $this->createMock(Acl::class);
|
||||
public function testUpdateAcl() {
|
||||
$this->boardService->expects($this->once())
|
||||
->method('updateAcl')
|
||||
->with(1, true, true, true)
|
||||
->willReturn($acl);
|
||||
$this->assertEquals($acl, $this->controller->updateAcl(1, true, true, true));
|
||||
->with(1, 2, 3, 4)
|
||||
->willReturn(1);
|
||||
$this->assertEquals(1, $this->controller->updateAcl(1, 2, 3, 4));
|
||||
}
|
||||
|
||||
public function testDeleteAcl() {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2018 Ryan Fletcher <ryan.fletcher@codepassion.ca>
|
||||
*
|
||||
@@ -32,16 +30,15 @@ use OCP\AppFramework\Http;
|
||||
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\IRequest;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
|
||||
class CardApiControllerTest extends \Test\TestCase {
|
||||
private CardApiController $controller;
|
||||
private IRequest&MockObject $request;
|
||||
private CardService&MockObject $cardService;
|
||||
private string $userId = 'admin';
|
||||
private array $cardExample;
|
||||
private array $stackExample;
|
||||
private AssignmentService&MockObject $assignmentService;
|
||||
private $controller;
|
||||
private $request;
|
||||
private $cardService;
|
||||
private $userId = 'admin';
|
||||
private $cardExample;
|
||||
private $stackExample;
|
||||
private $assignmentService;
|
||||
|
||||
public function setUp(): void {
|
||||
parent::setUp();
|
||||
@@ -54,7 +51,7 @@ class CardApiControllerTest extends \Test\TestCase {
|
||||
$this->stackExample['id'] = 1;
|
||||
|
||||
$this->controller = new CardApiController(
|
||||
'deck',
|
||||
$appName = 'deck',
|
||||
$this->request,
|
||||
$this->cardService,
|
||||
$this->assignmentService,
|
||||
@@ -62,7 +59,7 @@ class CardApiControllerTest extends \Test\TestCase {
|
||||
);
|
||||
}
|
||||
|
||||
public function testGet(): void {
|
||||
public function testGet() {
|
||||
$card = new Card();
|
||||
$card->setId($this->cardExample['id']);
|
||||
|
||||
@@ -119,7 +116,7 @@ class CardApiControllerTest extends \Test\TestCase {
|
||||
->willReturn($card);
|
||||
|
||||
$expected = new DataResponse($card, HTTP::STATUS_OK);
|
||||
$actual = $this->controller->update('title', 'plain', $this->userId, 'description', 0, null);
|
||||
$actual = $this->controller->update('title', 'plain', 0, 'description', $this->userId, null);
|
||||
$this->assertEquals($expected, $actual);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2016 Julius Härtl <jus@bitgrid.net>
|
||||
*
|
||||
@@ -26,7 +24,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace OCA\Deck\Controller;
|
||||
|
||||
use OCA\Deck\Db\Card;
|
||||
use OCA\Deck\Service\AssignmentService;
|
||||
use OCA\Deck\Service\CardService;
|
||||
use OCP\IRequest;
|
||||
@@ -35,11 +32,17 @@ use Test\TestCase;
|
||||
|
||||
class CardControllerTest extends TestCase {
|
||||
|
||||
private CardController $controller;
|
||||
private IRequest&MockObject $request;
|
||||
private CardService&MockObject $cardService;
|
||||
private AssignmentService&MockObject $assignmentService;
|
||||
private string $userId = 'user';
|
||||
/** @var CardController|MockObject */
|
||||
private $controller;
|
||||
/** @var IRequest|MockObject */
|
||||
private $request;
|
||||
/** @var CardService|MockObject */
|
||||
private $cardService;
|
||||
/** @var AssignmentService|MockObject */
|
||||
private $assignmentService;
|
||||
/** @var string */
|
||||
private $userId = 'user';
|
||||
|
||||
|
||||
public function setUp(): void {
|
||||
$this->request = $this->createMock(IRequest::class);
|
||||
@@ -55,43 +58,39 @@ class CardControllerTest extends TestCase {
|
||||
}
|
||||
|
||||
public function testRead() {
|
||||
$card = $this->createMock(Card::class);
|
||||
$this->cardService->expects($this->once())
|
||||
->method('find')
|
||||
->with(123)
|
||||
->willReturn($card);
|
||||
$this->assertEquals($card, $this->controller->read(123));
|
||||
->willReturn(1);
|
||||
$this->assertEquals(1, $this->controller->read(123));
|
||||
}
|
||||
|
||||
public function testCreate(): void {
|
||||
$card = $this->createMock(Card::class);
|
||||
public function testCreate() {
|
||||
$this->cardService->expects($this->once())
|
||||
->method('create')
|
||||
->with('foo', 1, 'text', 3, $this->userId)
|
||||
->willReturn($card);
|
||||
$this->assertEquals($card, $this->controller->create('foo', 1, 'text', 3));
|
||||
->willReturn(1);
|
||||
$this->assertEquals(1, $this->controller->create('foo', 1, 'text', 3));
|
||||
}
|
||||
|
||||
public function testUpdate(): void {
|
||||
$card = $this->createMock(Card::class);
|
||||
public function testUpdate() {
|
||||
$this->cardService->expects($this->once())
|
||||
->method('update')
|
||||
->with(1, 'title', 3, 'text', $this->userId, 'foo', 5, '2017-01-01 00:00:00')
|
||||
->willReturn($card);
|
||||
$this->assertEquals($card, $this->controller->update(1, 'title', 3, 'text', 5, 'foo', '2017-01-01 00:00:00', null));
|
||||
->willReturn(1);
|
||||
$this->assertEquals(1, $this->controller->update(1, 'title', 3, 'text', 5, 'foo', '2017-01-01 00:00:00', null));
|
||||
}
|
||||
|
||||
public function testDelete(): void {
|
||||
$card = $this->createMock(Card::class);
|
||||
public function testDelete() {
|
||||
$this->cardService->expects($this->once())
|
||||
->method('delete')
|
||||
->with(123)
|
||||
->willReturn($card);
|
||||
$this->assertEquals($card, $this->controller->delete(123));
|
||||
->willReturn(1);
|
||||
$this->assertEquals(1, $this->controller->delete(123));
|
||||
}
|
||||
|
||||
public function testArchive() {
|
||||
$this->cardService->expects($this->once())->method('archive');
|
||||
$this->cardService->expects($this->once())->method('archive')->willReturn(true);
|
||||
$this->controller->archive(1);
|
||||
}
|
||||
public function testUnarchive() {
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
|
||||
namespace OCA\Deck\Controller;
|
||||
|
||||
use OCA\Deck\Db\Label;
|
||||
use OCA\Deck\Service\LabelService;
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\IRequest;
|
||||
@@ -57,30 +56,27 @@ class LabelControllerTest extends \Test\TestCase {
|
||||
}
|
||||
|
||||
|
||||
public function testCreate(): void {
|
||||
$label = $this->createMock(Label::class);
|
||||
public function testCreate() {
|
||||
$this->labelService->expects($this->once())
|
||||
->method('create')
|
||||
->with(1, 2, 3)
|
||||
->willReturn($label);
|
||||
$this->assertEquals($label, $this->controller->create(1, 2, 3));
|
||||
->willReturn(1);
|
||||
$this->assertEquals(1, $this->controller->create(1, 2, 3));
|
||||
}
|
||||
|
||||
public function testUpdate(): void {
|
||||
$label = $this->createMock(Label::class);
|
||||
public function testUpdate() {
|
||||
$this->labelService->expects($this->once())
|
||||
->method('update')
|
||||
->with(1, 2, 3)
|
||||
->willReturn($label);
|
||||
$this->assertEquals($label, $this->controller->update(1, 2, 3));
|
||||
->willReturn(1);
|
||||
$this->assertEquals(1, $this->controller->update(1, 2, 3));
|
||||
}
|
||||
|
||||
public function testDelete(): void {
|
||||
$label = $this->createMock(Label::class);
|
||||
public function testDelete() {
|
||||
$this->labelService->expects($this->once())
|
||||
->method('delete')
|
||||
->with(123)
|
||||
->willReturn($label);
|
||||
$this->assertEquals($label, $this->controller->delete(123));
|
||||
->willReturn(1);
|
||||
$this->assertEquals(1, $this->controller->delete(123));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2016 Julius Härtl <jus@bitgrid.net>
|
||||
*
|
||||
@@ -26,7 +24,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace OCA\Deck\Controller;
|
||||
|
||||
use OCA\Deck\Db\Stack;
|
||||
use OCA\Deck\Service\StackService;
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\IRequest;
|
||||
@@ -70,38 +67,34 @@ class StackControllerTest extends \Test\TestCase {
|
||||
}
|
||||
|
||||
public function testCreate() {
|
||||
$stack = $this->createMock(Stack::class);
|
||||
$this->stackService->expects($this->once())
|
||||
->method('create')
|
||||
->with('abc', 2, 3)
|
||||
->willReturn($stack);
|
||||
$this->assertEquals($stack, $this->controller->create('abc', 2, 3));
|
||||
->with(1, 2, 3)
|
||||
->willReturn(1);
|
||||
$this->assertEquals(1, $this->controller->create(1, 2, 3));
|
||||
}
|
||||
|
||||
public function testUpdate() {
|
||||
$stack = $this->createMock(Stack::class);
|
||||
$this->stackService->expects($this->once())
|
||||
->method('update')
|
||||
->with(1, 'abc', 3, 4)
|
||||
->willReturn($stack);
|
||||
$this->assertEquals($stack, $this->controller->update(1, 'abc', 3, 4, null));
|
||||
->with(1, 2, 3, 4)
|
||||
->willReturn(1);
|
||||
$this->assertEquals(1, $this->controller->update(1, 2, 3, 4, null));
|
||||
}
|
||||
|
||||
public function testReorder() {
|
||||
$stack = $this->createMock(Stack::class);
|
||||
$this->stackService->expects($this->once())
|
||||
->method('reorder')
|
||||
->with(1, 2)
|
||||
->willReturn([$stack]);
|
||||
$this->assertEquals([$stack], $this->controller->reorder(1, 2));
|
||||
->willReturn(1);
|
||||
$this->assertEquals(1, $this->controller->reorder(1, 2));
|
||||
}
|
||||
|
||||
public function testDelete() {
|
||||
$stack = $this->createMock(Stack::class);
|
||||
$this->stackService->expects($this->once())
|
||||
->method('delete')
|
||||
->with(123)
|
||||
->willReturn($stack);
|
||||
$this->assertEquals($stack, $this->controller->delete(123));
|
||||
->willReturn(1);
|
||||
$this->assertEquals(1, $this->controller->delete(123));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"require-dev": {
|
||||
"vimeo/psalm": "^6.4"
|
||||
},
|
||||
"config": {
|
||||
"platform": {
|
||||
"php": "8.1.17"
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user