Compare commits
1 Commits
mod-1
...
fix/7263-d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c37f6f92c4 |
2
.github/CODEOWNERS
vendored
Normal file
2
.github/CODEOWNERS
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# App maintainers
|
||||
* @luka-nextcloud @grnd-alt @elzody
|
||||
120
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
Normal file
120
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
Thanks for reporting issues back!
|
||||
|
||||
Guidelines for submitting issues:
|
||||
|
||||
* Please search the existing issues first, it's likely that your issue was already reported or even fixed.
|
||||
|
||||
* SECURITY: Report any potential security bug to us via our HackerOne page (https://hackerone.com/nextcloud) following our security policy (https://nextcloud.com/security/) instead of filing an issue in our bug tracker.
|
||||
|
||||
* The issues in other components should be reported in their respective repositories: You will find them in our GitHub Organization (https://github.com/nextcloud/)
|
||||
|
||||
* You can also use the Issue Template app to prefill most of the required information: https://apps.nextcloud.com/apps/issuetemplate
|
||||
-->
|
||||
|
||||
<!--- Please keep this note for other contributors -->
|
||||
|
||||
### How to use GitHub
|
||||
|
||||
* Please use the 👍 [reaction](https://blog.github.com/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/) to show that you are affected by the same issue.
|
||||
* Please don't comment if you have no relevant information to add. It's just extra noise for everyone subscribed to this issue.
|
||||
* Subscribe to receive notifications on status change and new comments.
|
||||
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Client details:**
|
||||
- OS: [e.g. iOS]
|
||||
- Browser [e.g. chrome, safari]
|
||||
- Version [e.g. 22]
|
||||
- Device: [e.g. iPhone6, desktop]
|
||||
|
||||
<details>
|
||||
<summary>Server details</summary>
|
||||
<!--
|
||||
You can use the Issue Template application to prefill most of the required information: https://apps.nextcloud.com/apps/issuetemplate
|
||||
-->
|
||||
|
||||
**Operating system**:
|
||||
|
||||
**Web server:**
|
||||
|
||||
**Database:**
|
||||
|
||||
**PHP version:**
|
||||
|
||||
**Nextcloud version:** (see Nextcloud admin page)
|
||||
|
||||
**Where did you install Nextcloud from:**
|
||||
|
||||
**Signing status:**
|
||||
|
||||
```
|
||||
Login as admin user into your Nextcloud and access
|
||||
http://example.com/index.php/settings/integrity/failed
|
||||
paste the results here.
|
||||
```
|
||||
|
||||
**List of activated apps:**
|
||||
|
||||
```
|
||||
If you have access to your command line run e.g.:
|
||||
sudo -u www-data php occ app:list
|
||||
from within your Nextcloud installation folder
|
||||
```
|
||||
|
||||
**Nextcloud configuration:**
|
||||
|
||||
```
|
||||
If you have access to your command line run e.g.:
|
||||
sudo -u www-data php occ config:list system
|
||||
from within your Nextcloud installation folder
|
||||
|
||||
or
|
||||
|
||||
Insert your config.php content here
|
||||
Make sure to remove all sensitive content such as passwords. (e.g. database password, passwordsalt, secret, smtp password, …)
|
||||
```
|
||||
|
||||
**Are you using an external user-backend, if yes which one:** LDAP/ActiveDirectory/Webdav/...
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Logs</summary>
|
||||
|
||||
#### Nextcloud log (data/nextcloud.log)
|
||||
```
|
||||
Insert your Nextcloud log here
|
||||
```
|
||||
|
||||
#### Browser log
|
||||
```
|
||||
Insert your browser log here, this could for example include:
|
||||
|
||||
a) The javascript console log
|
||||
b) The network log
|
||||
c) ...
|
||||
```
|
||||
|
||||
</details>
|
||||
39
.github/ISSUE_TEMPLATE/Feature_request.md
vendored
Normal file
39
.github/ISSUE_TEMPLATE/Feature_request.md
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
Thanks for reporting issues back!
|
||||
|
||||
Guidelines for submitting issues:
|
||||
|
||||
* Please search the existing issues first, it's likely that your issue was already reported or even fixed.
|
||||
|
||||
* SECURITY: Report any potential security bug to us via our HackerOne page (https://hackerone.com/nextcloud) following our security policy (https://nextcloud.com/security/) instead of filing an issue in our bug tracker.
|
||||
|
||||
* The issues in other components should be reported in their respective repositories: You will find them in our GitHub Organization (https://github.com/nextcloud/)
|
||||
|
||||
* You can also use the Issue Template app to prefill most of the required information: https://apps.nextcloud.com/apps/issuetemplate
|
||||
-->
|
||||
|
||||
<!--- Please keep this note for other contributors -->
|
||||
|
||||
### How to use GitHub
|
||||
|
||||
* Please use the 👍 [reaction](https://blog.github.com/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/) to show that you are affected by the same issue.
|
||||
* Please don't comment if you have no relevant information to add. It's just extra noise for everyone subscribed to this issue.
|
||||
* Subscribe to receive notifications on status change and new comments.
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
101
.github/dependabot.yml
vendored
Normal file
101
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: npm
|
||||
directory: "/"
|
||||
target-branch: "main"
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: saturday
|
||||
time: "03:00"
|
||||
timezone: Europe/Paris
|
||||
open-pull-requests-limit: 10
|
||||
reviewers:
|
||||
- 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
|
||||
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: stable30
|
||||
versioning-strategy: lockfile-only
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: saturday
|
||||
time: "03:30"
|
||||
timezone: Europe/Paris
|
||||
ignore:
|
||||
- dependency-name: "*"
|
||||
update-types: ["version-update:semver-major"]
|
||||
open-pull-requests-limit: 30
|
||||
labels:
|
||||
- 3. to review
|
||||
- dependencies
|
||||
|
||||
- package-ecosystem: composer
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: saturday
|
||||
time: "03:45"
|
||||
timezone: Europe/Paris
|
||||
open-pull-requests-limit: 10
|
||||
reviewers:
|
||||
- juliushaertl
|
||||
- luka-nextcloud
|
||||
|
||||
- package-ecosystem: composer
|
||||
directory: "/tests/integration"
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: saturday
|
||||
time: "04:00"
|
||||
timezone: Europe/Paris
|
||||
open-pull-requests-limit: 10
|
||||
reviewers:
|
||||
- juliushaertl
|
||||
- luka-nextcloud
|
||||
|
||||
- package-ecosystem: github-actions
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: saturday
|
||||
time: "04:15"
|
||||
timezone: Europe/Paris
|
||||
open-pull-requests-limit: 10
|
||||
reviewers:
|
||||
- juliushaertl
|
||||
- luka-nextcloud
|
||||
17
.github/pull_request_template.md
vendored
Normal file
17
.github/pull_request_template.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
* Resolves: # <!-- related github issue -->
|
||||
* Target version: main
|
||||
|
||||
### Summary
|
||||
|
||||
|
||||
### TODO
|
||||
|
||||
- [ ] ...
|
||||
|
||||
### Checklist
|
||||
|
||||
- [ ] Code is properly formatted
|
||||
- [ ] Sign-off message is added to all commits
|
||||
- [ ] Tests (unit, integration, api and/or acceptance) are included
|
||||
- [ ] Documentation (manuals or wiki) has been updated or is not required
|
||||
@@ -3,7 +3,9 @@ name: Package build
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- draggable
|
||||
- main
|
||||
- master
|
||||
- stable*
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -28,14 +30,14 @@ jobs:
|
||||
tools: composer
|
||||
- name: install dependencies
|
||||
run: |
|
||||
wget https://github.com/ChristophWurst/krankerl/releases/download/v0.13.3/krankerl_0.13.3_amd64.deb
|
||||
sudo dpkg -i krankerl_0.13.3_amd64.deb
|
||||
wget https://github.com/ChristophWurst/krankerl/releases/download/v0.14.0/krankerl_0.14.0_amd64.deb
|
||||
sudo dpkg -i krankerl_0.14.0_amd64.deb
|
||||
- name: package
|
||||
run: |
|
||||
uname -a
|
||||
RUST_BACKTRACE=1 krankerl --version
|
||||
RUST_BACKTRACE=1 krankerl package
|
||||
- uses: https://data.forgejo.org/forgejo/upload-artifact@v4
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Deck app tarball
|
||||
path: build/artifacts/deck.tar.gz
|
||||
191
.github/workflows/appstore-build-publish.yml
vendored
Normal file
191
.github/workflows/appstore-build-publish.yml
vendored
Normal file
@@ -0,0 +1,191 @@
|
||||
# This workflow is provided via the organization template repository
|
||||
#
|
||||
# https://github.com/nextcloud/.github
|
||||
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
name: Build and publish app release
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
build_and_publish:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
# Only allowed to be run on nextcloud-releases repositories
|
||||
if: ${{ github.repository_owner == 'nextcloud-releases' }}
|
||||
|
||||
steps:
|
||||
- name: Check actor permission
|
||||
uses: skjnldsv/check-actor-permission@69e92a3c4711150929bca9fcf34448c5bf5526e7 # v3.0
|
||||
with:
|
||||
require: write
|
||||
|
||||
- name: Set app env
|
||||
run: |
|
||||
# Split and keep last
|
||||
echo "APP_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV
|
||||
echo "APP_VERSION=${GITHUB_REF##*/}" >> $GITHUB_ENV
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
path: ${{ env.APP_NAME }}
|
||||
|
||||
- name: Get app version number
|
||||
id: app-version
|
||||
uses: skjnldsv/xpath-action@f5b036e9d973f42c86324833fd00be90665fbf77 # master
|
||||
with:
|
||||
filename: ${{ env.APP_NAME }}/appinfo/info.xml
|
||||
expression: "//info//version/text()"
|
||||
|
||||
- name: Validate app version against tag
|
||||
run: |
|
||||
[ "${{ env.APP_VERSION }}" = "v${{ fromJSON(steps.app-version.outputs.result).version }}" ]
|
||||
|
||||
- name: Get appinfo data
|
||||
id: appinfo
|
||||
uses: skjnldsv/xpath-action@f5b036e9d973f42c86324833fd00be90665fbf77 # master
|
||||
with:
|
||||
filename: ${{ env.APP_NAME }}/appinfo/info.xml
|
||||
expression: "//info//dependencies//nextcloud/@min-version"
|
||||
|
||||
- name: Read package.json node and npm engines version
|
||||
uses: skjnldsv/read-package-engines-version-actions@06d6baf7d8f41934ab630e97d9e6c0bc9c9ac5e4 # v3
|
||||
id: versions
|
||||
# Continue if no package.json
|
||||
continue-on-error: true
|
||||
with:
|
||||
path: ${{ env.APP_NAME }}
|
||||
fallbackNode: '^20'
|
||||
fallbackNpm: '^10'
|
||||
|
||||
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
|
||||
# Skip if no package.json
|
||||
if: ${{ steps.versions.outputs.nodeVersion }}
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.1.0
|
||||
with:
|
||||
node-version: ${{ steps.versions.outputs.nodeVersion }}
|
||||
|
||||
- name: Set up npm ${{ steps.versions.outputs.npmVersion }}
|
||||
# Skip if no package.json
|
||||
if: ${{ steps.versions.outputs.npmVersion }}
|
||||
run: npm i -g 'npm@${{ steps.versions.outputs.npmVersion }}'
|
||||
|
||||
- name: Get php version
|
||||
id: php-versions
|
||||
uses: icewind1991/nextcloud-version-matrix@58becf3b4bb6dc6cef677b15e2fd8e7d48c0908f # v1.3.1
|
||||
with:
|
||||
filename: ${{ env.APP_NAME }}/appinfo/info.xml
|
||||
|
||||
- name: Set up php ${{ steps.php-versions.outputs.php-min }}
|
||||
uses: shivammathur/setup-php@0f7f1d08e3e32076e51cae65eb0b0c871405b16e # v2.34.1
|
||||
with:
|
||||
php-version: ${{ steps.php-versions.outputs.php-min }}
|
||||
coverage: none
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Check composer.json
|
||||
id: check_composer
|
||||
uses: andstor/file-existence-action@076e0072799f4942c8bc574a82233e1e4d13e9d6 # v3.0.0
|
||||
with:
|
||||
files: "${{ env.APP_NAME }}/composer.json"
|
||||
|
||||
- name: Install composer dependencies
|
||||
if: steps.check_composer.outputs.files_exists == 'true'
|
||||
run: |
|
||||
cd ${{ env.APP_NAME }}
|
||||
composer install --no-dev
|
||||
|
||||
- name: Build ${{ env.APP_NAME }}
|
||||
# Skip if no package.json
|
||||
if: ${{ steps.versions.outputs.nodeVersion }}
|
||||
env:
|
||||
CYPRESS_INSTALL_BINARY: 0
|
||||
run: |
|
||||
cd ${{ env.APP_NAME }}
|
||||
npm ci
|
||||
npm run build --if-present
|
||||
|
||||
- name: Check Krankerl config
|
||||
id: krankerl
|
||||
uses: andstor/file-existence-action@076e0072799f4942c8bc574a82233e1e4d13e9d6 # v3.0.0
|
||||
with:
|
||||
files: ${{ env.APP_NAME }}/krankerl.toml
|
||||
|
||||
- name: Install Krankerl
|
||||
if: steps.krankerl.outputs.files_exists == 'true'
|
||||
run: |
|
||||
wget https://github.com/ChristophWurst/krankerl/releases/download/v0.14.0/krankerl_0.14.0_amd64.deb
|
||||
sudo dpkg -i krankerl_0.14.0_amd64.deb
|
||||
|
||||
- name: Package ${{ env.APP_NAME }} ${{ env.APP_VERSION }} with krankerl
|
||||
if: steps.krankerl.outputs.files_exists == 'true'
|
||||
run: |
|
||||
cd ${{ env.APP_NAME }}
|
||||
krankerl package
|
||||
|
||||
- name: Package ${{ env.APP_NAME }} ${{ env.APP_VERSION }} with makefile
|
||||
if: steps.krankerl.outputs.files_exists != 'true'
|
||||
run: |
|
||||
cd ${{ env.APP_NAME }}
|
||||
make appstore
|
||||
|
||||
- name: Checkout server ${{ fromJSON(steps.appinfo.outputs.result).nextcloud.min-version }}
|
||||
continue-on-error: true
|
||||
id: server-checkout
|
||||
run: |
|
||||
NCVERSION='${{ fromJSON(steps.appinfo.outputs.result).nextcloud.min-version }}'
|
||||
wget --quiet https://download.nextcloud.com/server/releases/latest-$NCVERSION.zip
|
||||
unzip latest-$NCVERSION.zip
|
||||
|
||||
- name: Checkout server master fallback
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
if: ${{ steps.server-checkout.outcome != 'success' }}
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: true
|
||||
repository: nextcloud/server
|
||||
path: nextcloud
|
||||
|
||||
- name: Sign app
|
||||
run: |
|
||||
# Extracting release
|
||||
cd ${{ env.APP_NAME }}/build/artifacts
|
||||
tar -xvf ${{ env.APP_NAME }}.tar.gz
|
||||
cd ../../../
|
||||
# Setting up keys
|
||||
echo '${{ secrets.APP_PRIVATE_KEY }}' > ${{ env.APP_NAME }}.key
|
||||
wget --quiet "https://github.com/nextcloud/app-certificate-requests/raw/master/${{ env.APP_NAME }}/${{ env.APP_NAME }}.crt"
|
||||
# Signing
|
||||
php nextcloud/occ integrity:sign-app --privateKey=../${{ env.APP_NAME }}.key --certificate=../${{ env.APP_NAME }}.crt --path=../${{ env.APP_NAME }}/build/artifacts/${{ env.APP_NAME }}
|
||||
# Rebuilding archive
|
||||
cd ${{ env.APP_NAME }}/build/artifacts
|
||||
tar -zcvf ${{ env.APP_NAME }}.tar.gz ${{ env.APP_NAME }}
|
||||
|
||||
- name: Attach tarball to github release
|
||||
uses: svenstaro/upload-release-action@81c65b7cd4de9b2570615ce3aad67a41de5b1a13 # v2
|
||||
id: attach_to_release
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: ${{ env.APP_NAME }}/build/artifacts/${{ env.APP_NAME }}.tar.gz
|
||||
asset_name: ${{ env.APP_NAME }}-${{ env.APP_VERSION }}.tar.gz
|
||||
tag: ${{ github.ref }}
|
||||
overwrite: true
|
||||
|
||||
- name: Upload app to Nextcloud appstore
|
||||
uses: nextcloud-releases/nextcloud-appstore-push-action@a011fe619bcf6e77ddebc96f9908e1af4071b9c1 # v1
|
||||
with:
|
||||
app_name: ${{ env.APP_NAME }}
|
||||
appstore_token: ${{ secrets.APPSTORE_TOKEN }}
|
||||
download_url: ${{ steps.attach_to_release.outputs.browser_download_url }}
|
||||
app_private_key: ${{ secrets.APP_PRIVATE_KEY }}
|
||||
153
.github/workflows/cypress-e2e.yml
vendored
Normal file
153
.github/workflows/cypress-e2e.yml
vendored
Normal file
@@ -0,0 +1,153 @@
|
||||
name: Cypress
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- stable*
|
||||
|
||||
env:
|
||||
APP_NAME: deck
|
||||
CYPRESS_baseUrl: http://localhost:8081/index.php
|
||||
|
||||
jobs:
|
||||
cypress:
|
||||
|
||||
runs-on: 'ubuntu-latest'
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
node-version: [20.x]
|
||||
# containers: [1, 2, 3]
|
||||
php-versions: [ '8.2' ]
|
||||
server-versions: [ 'master' ]
|
||||
|
||||
env:
|
||||
extensions: mbstring, iconv, fileinfo, intl, sqlite, pdo_sqlite, zip, gd, apcu
|
||||
key: cache-v1
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: ghcr.io/nextcloud/continuous-integration-postgres-14:latest
|
||||
ports:
|
||||
- 4444:5432/tcp
|
||||
env:
|
||||
POSTGRES_USER: root
|
||||
POSTGRES_PASSWORD: rootpassword
|
||||
POSTGRES_DB: nextcloud
|
||||
options: --health-cmd pg_isready --health-interval 5s --health-timeout 2s --health-retries 5
|
||||
|
||||
steps:
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4.4.0
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
- name: Register text Git reference
|
||||
run: |
|
||||
text_app_ref="$(if [ "${{ matrix.server-versions }}" = "master" ]; then echo -n "main"; else echo -n "${{ matrix.server-versions }}"; fi)"
|
||||
echo "text_app_ref=$text_app_ref" >> $GITHUB_ENV
|
||||
|
||||
- name: Checkout server
|
||||
uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
repository: nextcloud/server
|
||||
ref: ${{ matrix.server-versions }}
|
||||
|
||||
- name: Checkout submodules
|
||||
shell: bash
|
||||
run: |
|
||||
auth_header="$(git config --local --get http.https://github.com/.extraheader)"
|
||||
git submodule sync --recursive
|
||||
git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1
|
||||
|
||||
- name: Checkout ${{ env.APP_NAME }}
|
||||
uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
path: apps/${{ env.APP_NAME }}
|
||||
|
||||
- name: Checkout text
|
||||
uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
repository: nextcloud/text
|
||||
ref: ${{ env.text_app_ref }}
|
||||
path: apps/text
|
||||
|
||||
- name: Setup cache environment
|
||||
id: extcache
|
||||
uses: shivammathur/cache-extensions@v1
|
||||
with:
|
||||
php-version: ${{ matrix.php-versions }}
|
||||
extensions: ${{ env.extensions }}
|
||||
key: ${{ env.key }}
|
||||
|
||||
- name: Cache extensions
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ steps.extcache.outputs.dir }}
|
||||
key: ${{ steps.extcache.outputs.key }}
|
||||
restore-keys: ${{ steps.extcache.outputs.key }}
|
||||
|
||||
- name: Set up php ${{ matrix.php-versions }}
|
||||
uses: shivammathur/setup-php@2.34.1
|
||||
with:
|
||||
php-version: ${{ matrix.php-versions }}
|
||||
extensions: ${{ env.extensions }}
|
||||
ini-values:
|
||||
apc.enable_cli=on
|
||||
coverage: none
|
||||
|
||||
- name: Install composer dependencies
|
||||
working-directory: apps/${{ env.APP_NAME }}
|
||||
run: |
|
||||
composer install --no-dev
|
||||
|
||||
- name: Set up Nextcloud
|
||||
env:
|
||||
DB_PORT: 4444
|
||||
PHP_CLI_SERVER_WORKERS: 20
|
||||
run: |
|
||||
mkdir data
|
||||
echo '<?php $CONFIG=["memcache.local"=>"\OC\Memcache\APCu","hashing_default_password"=>true];' > config/config.php
|
||||
php occ maintenance:install --verbose --database=pgsql --database-name=nextcloud --database-host=127.0.0.1 --database-port=$DB_PORT --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass admin
|
||||
php occ background:cron
|
||||
php -f index.php
|
||||
php -S 0.0.0.0:8081 &
|
||||
export OC_PASS=1234561
|
||||
php occ user:add --password-from-env user1
|
||||
php occ user:add --password-from-env user2
|
||||
php occ app:enable deck
|
||||
php occ app:list
|
||||
curl -v http://localhost:8081/index.php/login
|
||||
|
||||
- name: Cypress run
|
||||
uses: cypress-io/github-action@v6
|
||||
with:
|
||||
build: npm run dev
|
||||
record: false
|
||||
parallel: false
|
||||
browser: chrome
|
||||
wait-on: '${{ env.CYPRESS_baseUrl }}'
|
||||
working-directory: 'apps/${{ env.APP_NAME }}'
|
||||
config: defaultCommandTimeout=10000,video=false
|
||||
env:
|
||||
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
|
||||
npm_package_name: ${{ env.APP_NAME }}
|
||||
|
||||
- name: Upload test failure screenshots
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: Upload screenshots
|
||||
path: apps/${{ env.APP_NAME }}/cypress/screenshots/
|
||||
retention-days: 5
|
||||
|
||||
- name: Upload nextcloud logs
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: Upload nextcloud log
|
||||
path: data/nextcloud.log
|
||||
retention-days: 5
|
||||
49
.github/workflows/dependabot-approve-merge.yml
vendored
Normal file
49
.github/workflows/dependabot-approve-merge.yml
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
# This workflow is provided via the organization template repository
|
||||
#
|
||||
# https://github.com/nextcloud/.github
|
||||
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
name: Dependabot
|
||||
|
||||
on:
|
||||
pull_request_target: # zizmor: ignore[dangerous-triggers]
|
||||
branches:
|
||||
- main
|
||||
- master
|
||||
- stable*
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: dependabot-approve-merge-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
auto-approve-merge:
|
||||
if: github.event.pull_request.user.login == 'dependabot[bot]' || github.event.pull_request.user.login == 'renovate[bot]'
|
||||
runs-on: ubuntu-latest-low
|
||||
permissions:
|
||||
# for hmarr/auto-approve-action to approve PRs
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- name: Disabled on forks
|
||||
if: ${{ github.event.pull_request.head.repo.full_name != github.repository }}
|
||||
run: |
|
||||
echo 'Can not approve PRs from forks'
|
||||
exit 1
|
||||
|
||||
# GitHub actions bot approve
|
||||
- uses: hmarr/auto-approve-action@b40d6c9ed2fa10c9a2749eca7eb004418a705501 # v2
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# Nextcloud bot approve and merge request
|
||||
- uses: ahmadnassri/action-dependabot-auto-merge@45fc124d949b19b6b8bf6645b6c9d55f4f9ac61a # v2
|
||||
with:
|
||||
target: minor
|
||||
github-token: ${{ secrets.DEPENDABOT_AUTOMERGE_TOKEN }}
|
||||
36
.github/workflows/fixup.yml
vendored
Normal file
36
.github/workflows/fixup.yml
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
# This workflow is provided via the organization template repository
|
||||
#
|
||||
# https://github.com/nextcloud/.github
|
||||
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
name: Block fixup and squash commits
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, ready_for_review, reopened, synchronize]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: fixup-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
commit-message-check:
|
||||
if: github.event.pull_request.draft == false
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
name: Block fixup and squash commits
|
||||
|
||||
runs-on: ubuntu-latest-low
|
||||
|
||||
steps:
|
||||
- name: Run check
|
||||
uses: skjnldsv/block-fixup-merge-action@c138ea99e45e186567b64cf065ce90f7158c236a # v2
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
165
.github/workflows/integration.yml
vendored
Normal file
165
.github/workflows/integration.yml
vendored
Normal file
@@ -0,0 +1,165 @@
|
||||
name: Integration tests
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/integration.yml'
|
||||
- 'appinfo/**'
|
||||
- 'lib/**'
|
||||
- 'templates/**'
|
||||
- 'tests/**'
|
||||
- 'composer.json'
|
||||
- 'composer.lock'
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- master
|
||||
- stable*
|
||||
|
||||
env:
|
||||
APP_NAME: deck
|
||||
|
||||
jobs:
|
||||
integration:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
php-versions: ['8.1']
|
||||
databases: ['sqlite', 'mysql', 'pgsql']
|
||||
server-versions: ['master']
|
||||
|
||||
name: php${{ matrix.php-versions }}-${{ matrix.databases }}-${{ matrix.server-versions }}
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:14
|
||||
ports:
|
||||
- 4445:5432/tcp
|
||||
env:
|
||||
POSTGRES_USER: root
|
||||
POSTGRES_PASSWORD: rootpassword
|
||||
POSTGRES_DB: nextcloud
|
||||
options: --health-cmd pg_isready --health-interval 5s --health-timeout 2s --health-retries 5
|
||||
mysql:
|
||||
image: mariadb:10.5
|
||||
ports:
|
||||
- 4444:3306/tcp
|
||||
env:
|
||||
MYSQL_ROOT_PASSWORD: rootpassword
|
||||
options: --health-cmd="mysqladmin ping" --health-interval 5s --health-timeout 2s --health-retries 5
|
||||
|
||||
steps:
|
||||
- name: Checkout server
|
||||
uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
repository: nextcloud/server
|
||||
ref: ${{ matrix.server-versions }}
|
||||
|
||||
- name: Checkout submodules
|
||||
shell: bash
|
||||
run: |
|
||||
auth_header="$(git config --local --get http.https://github.com/.extraheader)"
|
||||
git submodule sync --recursive
|
||||
git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1
|
||||
cd build/integration && composer require --dev phpunit/phpunit:~9
|
||||
|
||||
- name: Checkout app
|
||||
uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
path: apps/${{ env.APP_NAME }}
|
||||
|
||||
- name: Checkout activity
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
repository: nextcloud/activity
|
||||
ref: ${{ matrix.server-versions }}
|
||||
path: apps/activity
|
||||
|
||||
- name: Set up php ${{ matrix.php-versions }}
|
||||
uses: shivammathur/setup-php@2.34.1
|
||||
with:
|
||||
php-version: ${{ matrix.php-versions }}
|
||||
extensions: mbstring, iconv, fileinfo, intl, sqlite, pdo_sqlite, mysql, pdo_mysql, pgsql, pdo_pgsql, apcu, gd
|
||||
ini-values:
|
||||
apc.enable_cli=on
|
||||
coverage: none
|
||||
|
||||
- name: Set up dependencies
|
||||
working-directory: apps/${{ env.APP_NAME }}
|
||||
run: composer i --no-dev
|
||||
|
||||
- name: Set up Nextcloud
|
||||
run: |
|
||||
if [ "${{ matrix.databases }}" = "mysql" ]; then
|
||||
export DB_PORT=4444
|
||||
elif [ "${{ matrix.databases }}" = "pgsql" ]; then
|
||||
export DB_PORT=4445
|
||||
fi
|
||||
mkdir data
|
||||
./occ maintenance:install --verbose --database=${{ matrix.databases }} --database-name=nextcloud --database-host=127.0.0.1 --database-port=$DB_PORT --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass admin
|
||||
./occ config:system:set hashing_default_password --value=true --type=boolean
|
||||
./occ config:system:set memcache.local --value="\\OC\\Memcache\\APCu"
|
||||
./occ config:system:set memcache.distributed --value="\\OC\\Memcache\\APCu"
|
||||
cat config/config.php
|
||||
./occ user:list
|
||||
./occ app:enable --force ${{ env.APP_NAME }}
|
||||
./occ config:system:set query_log_file --value "$PWD/query.log"
|
||||
php -S localhost:8080 &
|
||||
|
||||
- name: Run behat
|
||||
working-directory: apps/${{ env.APP_NAME }}/tests/integration
|
||||
run: ./run.sh
|
||||
|
||||
- name: Print log
|
||||
if: always()
|
||||
run: cat data/nextcloud.log
|
||||
|
||||
- name: Query count
|
||||
if: ${{ matrix.databases == 'mysql' }}
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{secrets.GITHUB_TOKEN}}
|
||||
script: |
|
||||
let myOutput = ''
|
||||
let myError = ''
|
||||
|
||||
const options = {}
|
||||
options.listeners = {
|
||||
stdout: (data) => {
|
||||
myOutput += data.toString()
|
||||
},
|
||||
stderr: (data) => {
|
||||
myError += data.toString()
|
||||
}
|
||||
}
|
||||
await exec.exec(`/bin/bash -c "cat query.log | wc -l"`, [], options)
|
||||
msg = myOutput
|
||||
const queryCount = parseInt(myOutput, 10)
|
||||
|
||||
myOutput = ''
|
||||
await exec.exec('cat', ['apps/${{ env.APP_NAME }}/tests/integration/base-query-count.txt'], options)
|
||||
const baseCount = parseInt(myOutput, 10)
|
||||
|
||||
const absoluteIncrease = queryCount - baseCount
|
||||
const relativeIncrease = baseCount <= 0 ? 100 : (parseInt((absoluteIncrease / baseCount * 10000), 10) / 100)
|
||||
|
||||
if (absoluteIncrease >= 100 || relativeIncrease > 5) {
|
||||
const comment = `🐢 Performance warning.\nIt looks like the query count of the integration tests increased with this PR.\nDatabase query count is now ` + queryCount + ' was ' + baseCount + ' (+' + relativeIncrease + '%)\nPlease check your code again. If you added a new test this can be expected and the base value in tests/integration/base-query-count.txt can be increased.'
|
||||
github.rest.issues.createComment({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: comment
|
||||
})
|
||||
}
|
||||
if (queryCount < 100) {
|
||||
const comment = `🐈 Performance messuring seems broken. Failed to get query count.`
|
||||
github.rest.issues.createComment({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: comment
|
||||
})
|
||||
}
|
||||
100
.github/workflows/lint-eslint.yml
vendored
Normal file
100
.github/workflows/lint-eslint.yml
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
# This workflow is provided via the organization template repository
|
||||
#
|
||||
# https://github.com/nextcloud/.github
|
||||
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
name: Lint eslint
|
||||
|
||||
on: pull_request
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: lint-eslint-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
changes:
|
||||
runs-on: ubuntu-latest-low
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
|
||||
outputs:
|
||||
src: ${{ steps.changes.outputs.src}}
|
||||
|
||||
steps:
|
||||
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
||||
id: changes
|
||||
continue-on-error: true
|
||||
with:
|
||||
filters: |
|
||||
src:
|
||||
- '.github/workflows/**'
|
||||
- 'src/**'
|
||||
- 'appinfo/info.xml'
|
||||
- 'package.json'
|
||||
- 'package-lock.json'
|
||||
- 'tsconfig.json'
|
||||
- '.eslintrc.*'
|
||||
- '.eslintignore'
|
||||
- '**.js'
|
||||
- '**.ts'
|
||||
- '**.vue'
|
||||
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
needs: changes
|
||||
if: needs.changes.outputs.src != 'false'
|
||||
|
||||
name: NPM lint
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Read package.json node and npm engines version
|
||||
uses: skjnldsv/read-package-engines-version-actions@06d6baf7d8f41934ab630e97d9e6c0bc9c9ac5e4 # v3
|
||||
id: versions
|
||||
with:
|
||||
fallbackNode: '^20'
|
||||
fallbackNpm: '^10'
|
||||
|
||||
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.1.0
|
||||
with:
|
||||
node-version: ${{ steps.versions.outputs.nodeVersion }}
|
||||
|
||||
- name: Set up npm ${{ steps.versions.outputs.npmVersion }}
|
||||
run: npm i -g 'npm@${{ steps.versions.outputs.npmVersion }}'
|
||||
|
||||
- name: Install dependencies
|
||||
env:
|
||||
CYPRESS_INSTALL_BINARY: 0
|
||||
PUPPETEER_SKIP_DOWNLOAD: true
|
||||
run: npm ci
|
||||
|
||||
- name: Lint
|
||||
run: npm run lint
|
||||
|
||||
summary:
|
||||
permissions:
|
||||
contents: none
|
||||
runs-on: ubuntu-latest-low
|
||||
needs: [changes, lint]
|
||||
|
||||
if: always()
|
||||
|
||||
# This is the summary, we just avoid to rename it so that branch protection rules still match
|
||||
name: eslint
|
||||
|
||||
steps:
|
||||
- name: Summary status
|
||||
run: if ${{ needs.changes.outputs.src != 'false' && needs.lint.result != 'success' }}; then exit 1; fi
|
||||
52
.github/workflows/lint-php-cs.yml
vendored
Normal file
52
.github/workflows/lint-php-cs.yml
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
# This workflow is provided via the organization template repository
|
||||
#
|
||||
# https://github.com/nextcloud/.github
|
||||
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
name: Lint php-cs
|
||||
|
||||
on: pull_request
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: lint-php-cs-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
name: php-cs
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Get php version
|
||||
id: versions
|
||||
uses: icewind1991/nextcloud-version-matrix@58becf3b4bb6dc6cef677b15e2fd8e7d48c0908f # v1.3.1
|
||||
|
||||
- name: Set up php${{ steps.versions.outputs.php-min }}
|
||||
uses: shivammathur/setup-php@0f7f1d08e3e32076e51cae65eb0b0c871405b16e # v2.34.1
|
||||
with:
|
||||
php-version: ${{ steps.versions.outputs.php-min }}
|
||||
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite
|
||||
coverage: none
|
||||
ini-file: development
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
composer remove nextcloud/ocp --dev
|
||||
composer i
|
||||
|
||||
- name: Lint
|
||||
run: composer run cs:check || ( echo 'Please run `composer run cs:fix` to format your code' && exit 1 )
|
||||
75
.github/workflows/lint-php.yml
vendored
Normal file
75
.github/workflows/lint-php.yml
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
# This workflow is provided via the organization template repository
|
||||
#
|
||||
# https://github.com/nextcloud/.github
|
||||
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
name: Lint php
|
||||
|
||||
on: pull_request
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: lint-php-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
matrix:
|
||||
runs-on: ubuntu-latest-low
|
||||
outputs:
|
||||
php-versions: ${{ steps.versions.outputs.php-versions }}
|
||||
steps:
|
||||
- name: Checkout app
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Get version matrix
|
||||
id: versions
|
||||
uses: icewind1991/nextcloud-version-matrix@58becf3b4bb6dc6cef677b15e2fd8e7d48c0908f # v1.0.0
|
||||
|
||||
php-lint:
|
||||
runs-on: ubuntu-latest
|
||||
needs: matrix
|
||||
strategy:
|
||||
matrix:
|
||||
php-versions: ${{fromJson(needs.matrix.outputs.php-versions)}}
|
||||
|
||||
name: php-lint
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Set up php ${{ matrix.php-versions }}
|
||||
uses: shivammathur/setup-php@0f7f1d08e3e32076e51cae65eb0b0c871405b16e # v2.34.1
|
||||
with:
|
||||
php-version: ${{ matrix.php-versions }}
|
||||
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite
|
||||
coverage: none
|
||||
ini-file: development
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Lint
|
||||
run: composer run lint
|
||||
|
||||
summary:
|
||||
permissions:
|
||||
contents: none
|
||||
runs-on: ubuntu-latest-low
|
||||
needs: php-lint
|
||||
|
||||
if: always()
|
||||
|
||||
name: php-lint-summary
|
||||
|
||||
steps:
|
||||
- name: Summary status
|
||||
run: if ${{ needs.php-lint.result != 'success' && needs.php-lint.result != 'skipped' }}; then exit 1; fi
|
||||
53
.github/workflows/lint-stylelint.yml
vendored
Normal file
53
.github/workflows/lint-stylelint.yml
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
# This workflow is provided via the organization template repository
|
||||
#
|
||||
# https://github.com/nextcloud/.github
|
||||
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
name: Lint stylelint
|
||||
|
||||
on: pull_request
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: lint-stylelint-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
name: stylelint
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Read package.json node and npm engines version
|
||||
uses: skjnldsv/read-package-engines-version-actions@06d6baf7d8f41934ab630e97d9e6c0bc9c9ac5e4 # v3
|
||||
id: versions
|
||||
with:
|
||||
fallbackNode: '^20'
|
||||
fallbackNpm: '^10'
|
||||
|
||||
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.1.0
|
||||
with:
|
||||
node-version: ${{ steps.versions.outputs.nodeVersion }}
|
||||
|
||||
- name: Set up npm ${{ steps.versions.outputs.npmVersion }}
|
||||
run: npm i -g 'npm@${{ steps.versions.outputs.npmVersion }}'
|
||||
|
||||
- name: Install dependencies
|
||||
env:
|
||||
CYPRESS_INSTALL_BINARY: 0
|
||||
run: npm ci
|
||||
|
||||
- name: Lint
|
||||
run: npm run stylelint
|
||||
34
.github/workflows/nodejs.yml
vendored
Normal file
34
.github/workflows/nodejs.yml
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
name: Node CI
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [14.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4.4.0
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: Set up npm7
|
||||
run: npm i -g npm@7
|
||||
- name: install dependencies
|
||||
run: |
|
||||
npm ci
|
||||
- name: build
|
||||
env:
|
||||
RELATIVE_CI_KEY: ${{ secrets.RELATIVE_CI_KEY }}
|
||||
RELATIVE_CI_SLUG: nextcloud/deck
|
||||
run: |
|
||||
mkdir -p js
|
||||
npm run build --if-present -- --profile --json | tail -n +6 > js/webpack-stats.json
|
||||
npx relative-ci-agent
|
||||
|
||||
|
||||
81
.github/workflows/npm-audit-fix.yml
vendored
Normal file
81
.github/workflows/npm-audit-fix.yml
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
# This workflow is provided via the organization template repository
|
||||
#
|
||||
# https://github.com/nextcloud/.github
|
||||
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2023-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
name: Npm audit fix and compile
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
# At 2:30 on Sundays
|
||||
- cron: '30 2 * * 0'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
branches: ['main', 'master', 'stable32', 'stable31', 'stable30']
|
||||
|
||||
name: npm-audit-fix-${{ matrix.branches }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
id: checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
ref: ${{ matrix.branches }}
|
||||
continue-on-error: true
|
||||
|
||||
- name: Read package.json node and npm engines version
|
||||
uses: skjnldsv/read-package-engines-version-actions@06d6baf7d8f41934ab630e97d9e6c0bc9c9ac5e4 # v3
|
||||
id: versions
|
||||
with:
|
||||
fallbackNode: '^20'
|
||||
fallbackNpm: '^10'
|
||||
|
||||
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.1.0
|
||||
with:
|
||||
node-version: ${{ steps.versions.outputs.nodeVersion }}
|
||||
|
||||
- name: Set up npm ${{ steps.versions.outputs.npmVersion }}
|
||||
run: npm i -g 'npm@${{ steps.versions.outputs.npmVersion }}'
|
||||
|
||||
- name: Fix npm audit
|
||||
id: npm-audit
|
||||
uses: nextcloud-libraries/npm-audit-action@1b1728b2b4a7a78d69de65608efcf4db0e3e42d0 # v0.2.0
|
||||
|
||||
- name: Run npm ci and npm run build
|
||||
if: steps.checkout.outcome == 'success'
|
||||
env:
|
||||
CYPRESS_INSTALL_BINARY: 0
|
||||
run: |
|
||||
npm ci
|
||||
npm run build --if-present
|
||||
|
||||
- name: Create Pull Request
|
||||
if: steps.checkout.outcome == 'success'
|
||||
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
|
||||
with:
|
||||
token: ${{ secrets.COMMAND_BOT_PAT }}
|
||||
commit-message: 'fix(deps): Fix npm audit'
|
||||
committer: GitHub <noreply@github.com>
|
||||
author: nextcloud-command <nextcloud-command@users.noreply.github.com>
|
||||
signoff: true
|
||||
branch: automated/noid/${{ matrix.branches }}-fix-npm-audit
|
||||
title: '[${{ matrix.branches }}] Fix npm audit'
|
||||
body: ${{ steps.npm-audit.outputs.markdown }}
|
||||
labels: |
|
||||
dependencies
|
||||
3. to review
|
||||
200
.github/workflows/phpunit-mysql.yml
vendored
Normal file
200
.github/workflows/phpunit-mysql.yml
vendored
Normal file
@@ -0,0 +1,200 @@
|
||||
# This workflow is provided via the organization template repository
|
||||
#
|
||||
# https://github.com/nextcloud/.github
|
||||
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2022-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
name: PHPUnit MySQL
|
||||
|
||||
on: pull_request
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: phpunit-mysql-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
matrix:
|
||||
runs-on: ubuntu-latest-low
|
||||
outputs:
|
||||
matrix: ${{ steps.versions.outputs.sparse-matrix }}
|
||||
steps:
|
||||
- name: Checkout app
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Get version matrix
|
||||
id: versions
|
||||
uses: icewind1991/nextcloud-version-matrix@58becf3b4bb6dc6cef677b15e2fd8e7d48c0908f # v1.3.1
|
||||
with:
|
||||
matrix: '{"mysql-versions": ["8.4"]}'
|
||||
|
||||
changes:
|
||||
runs-on: ubuntu-latest-low
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
|
||||
outputs:
|
||||
src: ${{ steps.changes.outputs.src}}
|
||||
|
||||
steps:
|
||||
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
||||
id: changes
|
||||
continue-on-error: true
|
||||
with:
|
||||
filters: |
|
||||
src:
|
||||
- '.github/workflows/**'
|
||||
- 'appinfo/**'
|
||||
- 'lib/**'
|
||||
- 'templates/**'
|
||||
- 'tests/**'
|
||||
- 'vendor/**'
|
||||
- 'vendor-bin/**'
|
||||
- '.php-cs-fixer.dist.php'
|
||||
- 'composer.json'
|
||||
- 'composer.lock'
|
||||
|
||||
phpunit-mysql:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
needs: [changes, matrix]
|
||||
if: needs.changes.outputs.src != 'false'
|
||||
|
||||
strategy:
|
||||
matrix: ${{ fromJson(needs.matrix.outputs.matrix) }}
|
||||
|
||||
name: MySQL ${{ matrix.mysql-versions }} PHP ${{ matrix.php-versions }} Nextcloud ${{ matrix.server-versions }}
|
||||
|
||||
services:
|
||||
mysql:
|
||||
image: ghcr.io/nextcloud/continuous-integration-mysql-${{ matrix.mysql-versions }}:latest
|
||||
ports:
|
||||
- 4444:3306/tcp
|
||||
env:
|
||||
MYSQL_ROOT_PASSWORD: rootpassword
|
||||
options: --health-cmd="mysqladmin ping" --health-interval 5s --health-timeout 2s --health-retries 10
|
||||
|
||||
steps:
|
||||
- name: Set app env
|
||||
if: ${{ env.APP_NAME == '' }}
|
||||
run: |
|
||||
# Split and keep last
|
||||
echo "APP_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV
|
||||
|
||||
- name: Checkout server
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: true
|
||||
repository: nextcloud/server
|
||||
ref: ${{ matrix.server-versions }}
|
||||
|
||||
- name: Checkout app
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
path: apps/${{ env.APP_NAME }}
|
||||
|
||||
- name: Set up php ${{ matrix.php-versions }}
|
||||
uses: shivammathur/setup-php@0f7f1d08e3e32076e51cae65eb0b0c871405b16e # v2.34.1
|
||||
with:
|
||||
php-version: ${{ matrix.php-versions }}
|
||||
# https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation
|
||||
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, mysql, pdo_mysql
|
||||
coverage: none
|
||||
ini-file: development
|
||||
# Temporary workaround for missing pcntl_* in PHP 8.3
|
||||
ini-values: disable_functions=
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Enable ONLY_FULL_GROUP_BY MySQL option
|
||||
run: |
|
||||
echo "SET GLOBAL sql_mode=(SELECT CONCAT(@@sql_mode,',ONLY_FULL_GROUP_BY'));" | mysql -h 127.0.0.1 -P 4444 -u root -prootpassword
|
||||
echo 'SELECT @@sql_mode;' | mysql -h 127.0.0.1 -P 4444 -u root -prootpassword
|
||||
|
||||
- name: Check composer file existence
|
||||
id: check_composer
|
||||
uses: andstor/file-existence-action@076e0072799f4942c8bc574a82233e1e4d13e9d6 # v3.0.0
|
||||
with:
|
||||
files: apps/${{ env.APP_NAME }}/composer.json
|
||||
|
||||
- name: Set up dependencies
|
||||
# Only run if phpunit config file exists
|
||||
if: steps.check_composer.outputs.files_exists == 'true'
|
||||
working-directory: apps/${{ env.APP_NAME }}
|
||||
run: |
|
||||
composer remove nextcloud/ocp --dev
|
||||
composer i
|
||||
|
||||
- name: Set up Nextcloud
|
||||
env:
|
||||
DB_PORT: 4444
|
||||
run: |
|
||||
mkdir data
|
||||
./occ maintenance:install --verbose --database=mysql --database-name=nextcloud --database-host=127.0.0.1 --database-port=$DB_PORT --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass admin
|
||||
./occ app:enable --force ${{ env.APP_NAME }}
|
||||
|
||||
- name: Check PHPUnit script is defined
|
||||
id: check_phpunit
|
||||
continue-on-error: true
|
||||
working-directory: apps/${{ env.APP_NAME }}
|
||||
run: |
|
||||
composer run --list | grep '^ test:unit ' | wc -l | grep 1
|
||||
|
||||
- name: PHPUnit
|
||||
# Only run if phpunit config file exists
|
||||
if: steps.check_phpunit.outcome == 'success'
|
||||
working-directory: apps/${{ env.APP_NAME }}
|
||||
run: composer run test:unit
|
||||
|
||||
- name: Check PHPUnit integration script is defined
|
||||
id: check_integration
|
||||
continue-on-error: true
|
||||
working-directory: apps/${{ env.APP_NAME }}
|
||||
run: |
|
||||
composer run --list | grep '^ test:integration ' | wc -l | grep 1
|
||||
|
||||
- name: Run Nextcloud
|
||||
# Only run if phpunit integration config file exists
|
||||
if: steps.check_integration.outcome == 'success'
|
||||
run: php -S localhost:8080 &
|
||||
|
||||
- name: PHPUnit integration
|
||||
# Only run if phpunit integration config file exists
|
||||
if: steps.check_integration.outcome == 'success'
|
||||
working-directory: apps/${{ env.APP_NAME }}
|
||||
run: composer run test:integration
|
||||
|
||||
- name: Print logs
|
||||
if: always()
|
||||
run: |
|
||||
cat data/nextcloud.log
|
||||
|
||||
- name: Skipped
|
||||
# Fail the action when neither unit nor integration tests ran
|
||||
if: steps.check_phpunit.outcome == 'failure' && steps.check_integration.outcome == 'failure'
|
||||
run: |
|
||||
echo 'Neither PHPUnit nor PHPUnit integration tests are specified in composer.json scripts'
|
||||
exit 1
|
||||
|
||||
summary:
|
||||
permissions:
|
||||
contents: none
|
||||
runs-on: ubuntu-latest-low
|
||||
needs: [changes, phpunit-mysql]
|
||||
|
||||
if: always()
|
||||
|
||||
name: phpunit-mysql-summary
|
||||
|
||||
steps:
|
||||
- name: Summary status
|
||||
run: if ${{ needs.changes.outputs.src != 'false' && needs.phpunit-mysql.result != 'success' }}; then exit 1; fi
|
||||
198
.github/workflows/phpunit-pgsql.yml
vendored
Normal file
198
.github/workflows/phpunit-pgsql.yml
vendored
Normal file
@@ -0,0 +1,198 @@
|
||||
# This workflow is provided via the organization template repository
|
||||
#
|
||||
# https://github.com/nextcloud/.github
|
||||
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2022-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
name: PHPUnit PostgreSQL
|
||||
|
||||
on: pull_request
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: phpunit-pgsql-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
matrix:
|
||||
runs-on: ubuntu-latest-low
|
||||
outputs:
|
||||
php-version: ${{ steps.versions.outputs.php-available-list }}
|
||||
server-max: ${{ steps.versions.outputs.branches-max-list }}
|
||||
steps:
|
||||
- name: Checkout app
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Get version matrix
|
||||
id: versions
|
||||
uses: icewind1991/nextcloud-version-matrix@58becf3b4bb6dc6cef677b15e2fd8e7d48c0908f # v1.3.1
|
||||
|
||||
changes:
|
||||
runs-on: ubuntu-latest-low
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
|
||||
outputs:
|
||||
src: ${{ steps.changes.outputs.src }}
|
||||
|
||||
steps:
|
||||
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
||||
id: changes
|
||||
continue-on-error: true
|
||||
with:
|
||||
filters: |
|
||||
src:
|
||||
- '.github/workflows/**'
|
||||
- 'appinfo/**'
|
||||
- 'lib/**'
|
||||
- 'templates/**'
|
||||
- 'tests/**'
|
||||
- 'vendor/**'
|
||||
- 'vendor-bin/**'
|
||||
- '.php-cs-fixer.dist.php'
|
||||
- 'composer.json'
|
||||
- 'composer.lock'
|
||||
|
||||
phpunit-pgsql:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
needs: [changes, matrix]
|
||||
if: needs.changes.outputs.src != 'false'
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
php-versions: ${{ fromJson(needs.matrix.outputs.php-version) }}
|
||||
server-versions: ${{ fromJson(needs.matrix.outputs.server-max) }}
|
||||
|
||||
name: PostgreSQL PHP ${{ matrix.php-versions }} Nextcloud ${{ matrix.server-versions }}
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: ghcr.io/nextcloud/continuous-integration-postgres-14:latest
|
||||
ports:
|
||||
- 4444:5432/tcp
|
||||
env:
|
||||
POSTGRES_USER: root
|
||||
POSTGRES_PASSWORD: rootpassword
|
||||
POSTGRES_DB: nextcloud
|
||||
options: --health-cmd pg_isready --health-interval 5s --health-timeout 2s --health-retries 5
|
||||
|
||||
steps:
|
||||
- name: Set app env
|
||||
if: ${{ env.APP_NAME == '' }}
|
||||
run: |
|
||||
# Split and keep last
|
||||
echo "APP_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV
|
||||
|
||||
- name: Checkout server
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: true
|
||||
repository: nextcloud/server
|
||||
ref: ${{ matrix.server-versions }}
|
||||
|
||||
- name: Checkout app
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
path: apps/${{ env.APP_NAME }}
|
||||
|
||||
- name: Set up php ${{ matrix.php-versions }}
|
||||
uses: shivammathur/setup-php@0f7f1d08e3e32076e51cae65eb0b0c871405b16e # v2.34.1
|
||||
with:
|
||||
php-version: ${{ matrix.php-versions }}
|
||||
# https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation
|
||||
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, pgsql, pdo_pgsql
|
||||
coverage: none
|
||||
ini-file: development
|
||||
# Temporary workaround for missing pcntl_* in PHP 8.3
|
||||
ini-values: disable_functions=
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Check composer file existence
|
||||
id: check_composer
|
||||
uses: andstor/file-existence-action@076e0072799f4942c8bc574a82233e1e4d13e9d6 # v3.0.0
|
||||
with:
|
||||
files: apps/${{ env.APP_NAME }}/composer.json
|
||||
|
||||
- name: Set up dependencies
|
||||
# Only run if phpunit config file exists
|
||||
if: steps.check_composer.outputs.files_exists == 'true'
|
||||
working-directory: apps/${{ env.APP_NAME }}
|
||||
run: |
|
||||
composer remove nextcloud/ocp --dev
|
||||
composer i
|
||||
|
||||
- name: Set up Nextcloud
|
||||
env:
|
||||
DB_PORT: 4444
|
||||
run: |
|
||||
mkdir data
|
||||
./occ maintenance:install --verbose --database=pgsql --database-name=nextcloud --database-host=127.0.0.1 --database-port=$DB_PORT --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass admin
|
||||
./occ app:enable --force ${{ env.APP_NAME }}
|
||||
|
||||
- name: Check PHPUnit script is defined
|
||||
id: check_phpunit
|
||||
continue-on-error: true
|
||||
working-directory: apps/${{ env.APP_NAME }}
|
||||
run: |
|
||||
composer run --list | grep '^ test:unit ' | wc -l | grep 1
|
||||
|
||||
- name: PHPUnit
|
||||
# Only run if phpunit config file exists
|
||||
if: steps.check_phpunit.outcome == 'success'
|
||||
working-directory: apps/${{ env.APP_NAME }}
|
||||
run: composer run test:unit
|
||||
|
||||
- name: Check PHPUnit integration script is defined
|
||||
id: check_integration
|
||||
continue-on-error: true
|
||||
working-directory: apps/${{ env.APP_NAME }}
|
||||
run: |
|
||||
composer run --list | grep '^ test:integration ' | wc -l | grep 1
|
||||
|
||||
- name: Run Nextcloud
|
||||
# Only run if phpunit integration config file exists
|
||||
if: steps.check_integration.outcome == 'success'
|
||||
run: php -S localhost:8080 &
|
||||
|
||||
- name: PHPUnit integration
|
||||
# Only run if phpunit integration config file exists
|
||||
if: steps.check_integration.outcome == 'success'
|
||||
working-directory: apps/${{ env.APP_NAME }}
|
||||
run: composer run test:integration
|
||||
|
||||
- name: Print logs
|
||||
if: always()
|
||||
run: |
|
||||
cat data/nextcloud.log
|
||||
|
||||
- name: Skipped
|
||||
# Fail the action when neither unit nor integration tests ran
|
||||
if: steps.check_phpunit.outcome == 'failure' && steps.check_integration.outcome == 'failure'
|
||||
run: |
|
||||
echo 'Neither PHPUnit nor PHPUnit integration tests are specified in composer.json scripts'
|
||||
exit 1
|
||||
|
||||
summary:
|
||||
permissions:
|
||||
contents: none
|
||||
runs-on: ubuntu-latest-low
|
||||
needs: [changes, phpunit-pgsql]
|
||||
|
||||
if: always()
|
||||
|
||||
name: phpunit-pgsql-summary
|
||||
|
||||
steps:
|
||||
- name: Summary status
|
||||
run: if ${{ needs.changes.outputs.src != 'false' && needs.phpunit-pgsql.result != 'success' }}; then exit 1; fi
|
||||
187
.github/workflows/phpunit-sqlite.yml
vendored
Normal file
187
.github/workflows/phpunit-sqlite.yml
vendored
Normal file
@@ -0,0 +1,187 @@
|
||||
# This workflow is provided via the organization template repository
|
||||
#
|
||||
# https://github.com/nextcloud/.github
|
||||
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2022-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
name: PHPUnit SQLite
|
||||
|
||||
on: pull_request
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: phpunit-sqlite-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
matrix:
|
||||
runs-on: ubuntu-latest-low
|
||||
outputs:
|
||||
php-version: ${{ steps.versions.outputs.php-available-list }}
|
||||
server-max: ${{ steps.versions.outputs.branches-max-list }}
|
||||
steps:
|
||||
- name: Checkout app
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Get version matrix
|
||||
id: versions
|
||||
uses: icewind1991/nextcloud-version-matrix@58becf3b4bb6dc6cef677b15e2fd8e7d48c0908f # v1.3.1
|
||||
|
||||
changes:
|
||||
runs-on: ubuntu-latest-low
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
|
||||
outputs:
|
||||
src: ${{ steps.changes.outputs.src}}
|
||||
|
||||
steps:
|
||||
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
||||
id: changes
|
||||
continue-on-error: true
|
||||
with:
|
||||
filters: |
|
||||
src:
|
||||
- '.github/workflows/**'
|
||||
- 'appinfo/**'
|
||||
- 'lib/**'
|
||||
- 'templates/**'
|
||||
- 'tests/**'
|
||||
- 'vendor/**'
|
||||
- 'vendor-bin/**'
|
||||
- '.php-cs-fixer.dist.php'
|
||||
- 'composer.json'
|
||||
- 'composer.lock'
|
||||
|
||||
phpunit-sqlite:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
needs: [changes, matrix]
|
||||
if: needs.changes.outputs.src != 'false'
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
php-versions: ${{ fromJson(needs.matrix.outputs.php-version) }}
|
||||
server-versions: ${{ fromJson(needs.matrix.outputs.server-max) }}
|
||||
|
||||
name: SQLite PHP ${{ matrix.php-versions }} Nextcloud ${{ matrix.server-versions }}
|
||||
|
||||
steps:
|
||||
- name: Set app env
|
||||
if: ${{ env.APP_NAME == '' }}
|
||||
run: |
|
||||
# Split and keep last
|
||||
echo "APP_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV
|
||||
|
||||
- name: Checkout server
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: true
|
||||
repository: nextcloud/server
|
||||
ref: ${{ matrix.server-versions }}
|
||||
|
||||
- name: Checkout app
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
path: apps/${{ env.APP_NAME }}
|
||||
|
||||
- name: Set up php ${{ matrix.php-versions }}
|
||||
uses: shivammathur/setup-php@0f7f1d08e3e32076e51cae65eb0b0c871405b16e # v2.34.1
|
||||
with:
|
||||
php-version: ${{ matrix.php-versions }}
|
||||
# https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation
|
||||
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite
|
||||
coverage: none
|
||||
ini-file: development
|
||||
# Temporary workaround for missing pcntl_* in PHP 8.3
|
||||
ini-values: disable_functions=
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Check composer file existence
|
||||
id: check_composer
|
||||
uses: andstor/file-existence-action@076e0072799f4942c8bc574a82233e1e4d13e9d6 # v3.0.0
|
||||
with:
|
||||
files: apps/${{ env.APP_NAME }}/composer.json
|
||||
|
||||
- name: Set up dependencies
|
||||
# Only run if phpunit config file exists
|
||||
if: steps.check_composer.outputs.files_exists == 'true'
|
||||
working-directory: apps/${{ env.APP_NAME }}
|
||||
run: |
|
||||
composer remove nextcloud/ocp --dev
|
||||
composer i
|
||||
|
||||
- name: Set up Nextcloud
|
||||
env:
|
||||
DB_PORT: 4444
|
||||
run: |
|
||||
mkdir data
|
||||
./occ maintenance:install --verbose --database=sqlite --database-name=nextcloud --database-host=127.0.0.1 --database-port=$DB_PORT --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass admin
|
||||
./occ app:enable --force ${{ env.APP_NAME }}
|
||||
|
||||
- name: Check PHPUnit script is defined
|
||||
id: check_phpunit
|
||||
continue-on-error: true
|
||||
working-directory: apps/${{ env.APP_NAME }}
|
||||
run: |
|
||||
composer run --list | grep '^ test:unit ' | wc -l | grep 1
|
||||
|
||||
- name: PHPUnit
|
||||
# Only run if phpunit config file exists
|
||||
if: steps.check_phpunit.outcome == 'success'
|
||||
working-directory: apps/${{ env.APP_NAME }}
|
||||
run: composer run test:unit
|
||||
|
||||
- name: Check PHPUnit integration script is defined
|
||||
id: check_integration
|
||||
continue-on-error: true
|
||||
working-directory: apps/${{ env.APP_NAME }}
|
||||
run: |
|
||||
composer run --list | grep '^ test:integration ' | wc -l | grep 1
|
||||
|
||||
- name: Run Nextcloud
|
||||
# Only run if phpunit integration config file exists
|
||||
if: steps.check_integration.outcome == 'success'
|
||||
run: php -S localhost:8080 &
|
||||
|
||||
- name: PHPUnit integration
|
||||
# Only run if phpunit integration config file exists
|
||||
if: steps.check_integration.outcome == 'success'
|
||||
working-directory: apps/${{ env.APP_NAME }}
|
||||
run: composer run test:integration
|
||||
|
||||
- name: Print logs
|
||||
if: always()
|
||||
run: |
|
||||
cat data/nextcloud.log
|
||||
|
||||
- name: Skipped
|
||||
# Fail the action when neither unit nor integration tests ran
|
||||
if: steps.check_phpunit.outcome == 'failure' && steps.check_integration.outcome == 'failure'
|
||||
run: |
|
||||
echo 'Neither PHPUnit nor PHPUnit integration tests are specified in composer.json scripts'
|
||||
exit 1
|
||||
|
||||
summary:
|
||||
permissions:
|
||||
contents: none
|
||||
runs-on: ubuntu-latest-low
|
||||
needs: [changes, phpunit-sqlite]
|
||||
|
||||
if: always()
|
||||
|
||||
name: phpunit-sqlite-summary
|
||||
|
||||
steps:
|
||||
- name: Summary status
|
||||
run: if ${{ needs.changes.outputs.src != 'false' && needs.phpunit-sqlite.result != 'success' }}; then exit 1; fi
|
||||
55
.github/workflows/pr-feedback.yml
vendored
Normal file
55
.github/workflows/pr-feedback.yml
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
# This workflow is provided via the organization template repository
|
||||
#
|
||||
# https://github.com/nextcloud/.github
|
||||
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
|
||||
|
||||
# SPDX-FileCopyrightText: 2023-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
# SPDX-FileCopyrightText: 2023 Marcel Klehr <mklehr@gmx.net>
|
||||
# SPDX-FileCopyrightText: 2023 Joas Schilling <213943+nickvergessen@users.noreply.github.com>
|
||||
# SPDX-FileCopyrightText: 2023 Daniel Kesselberg <mail@danielkesselberg.de>
|
||||
# SPDX-FileCopyrightText: 2023 Florian Steffens <florian.steffens@nextcloud.com>
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
name: 'Ask for feedback on PRs'
|
||||
on:
|
||||
schedule:
|
||||
- cron: '30 1 * * *'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
pr-feedback:
|
||||
if: ${{ github.repository_owner == 'nextcloud' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: The get-github-handles-from-website action
|
||||
uses: marcelklehr/get-github-handles-from-website-action@06b2239db0a48fe1484ba0bfd966a3ab81a08308 # v1.0.1
|
||||
id: scrape
|
||||
with:
|
||||
website: 'https://nextcloud.com/team/'
|
||||
|
||||
- name: Get blocklist
|
||||
id: blocklist
|
||||
run: |
|
||||
blocklist=$(curl https://raw.githubusercontent.com/nextcloud/.github/master/non-community-usernames.txt | paste -s -d, -)
|
||||
echo "blocklist=$blocklist" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- uses: nextcloud/pr-feedback-action@1883b38a033fb16f576875e0cf45f98b857655c4 # main
|
||||
with:
|
||||
feedback-message: |
|
||||
Hello there,
|
||||
Thank you so much for taking the time and effort to create a pull request to our Nextcloud project.
|
||||
|
||||
We hope that the review process is going smooth and is helpful for you. We want to ensure your pull request is reviewed to your satisfaction. If you have a moment, our community management team would very much appreciate your feedback on your experience with this PR review process.
|
||||
|
||||
Your feedback is valuable to us as we continuously strive to improve our community developer experience. Please take a moment to complete our short survey by clicking on the following link: https://cloud.nextcloud.com/apps/forms/s/i9Ago4EQRZ7TWxjfmeEpPkf6
|
||||
|
||||
Thank you for contributing to Nextcloud and we hope to hear from you soon!
|
||||
|
||||
(If you believe you should not receive this message, you can add yourself to the [blocklist](https://github.com/nextcloud/.github/blob/master/non-community-usernames.txt).)
|
||||
days-before-feedback: 14
|
||||
start-date: '2024-04-30'
|
||||
exempt-authors: '${{ steps.blocklist.outputs.blocklist }},${{ steps.scrape.outputs.users }}'
|
||||
exempt-bots: true
|
||||
59
.github/workflows/psalm.yml
vendored
Normal file
59
.github/workflows/psalm.yml
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
# This workflow is provided via the organization template repository
|
||||
#
|
||||
# https://github.com/nextcloud/.github
|
||||
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2022-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
name: Static analysis
|
||||
|
||||
on: pull_request
|
||||
|
||||
concurrency:
|
||||
group: psalm-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
static-analysis:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
name: static-psalm-analysis
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Get php version
|
||||
id: versions
|
||||
uses: icewind1991/nextcloud-version-matrix@58becf3b4bb6dc6cef677b15e2fd8e7d48c0908f # v1.3.1
|
||||
|
||||
- name: Check enforcement of minimum PHP version ${{ steps.versions.outputs.php-min }} in psalm.xml
|
||||
run: grep 'phpVersion="${{ steps.versions.outputs.php-min }}' psalm.xml
|
||||
|
||||
- name: Set up php${{ steps.versions.outputs.php-min }}
|
||||
uses: shivammathur/setup-php@0f7f1d08e3e32076e51cae65eb0b0c871405b16e # v2.34.1
|
||||
with:
|
||||
php-version: ${{ steps.versions.outputs.php-min }}
|
||||
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite
|
||||
coverage: none
|
||||
ini-file: development
|
||||
# Temporary workaround for missing pcntl_* in PHP 8.3
|
||||
ini-values: disable_functions=
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
composer remove nextcloud/ocp --dev
|
||||
composer i
|
||||
|
||||
- name: Install nextcloud/ocp
|
||||
run: composer require --dev nextcloud/ocp:dev-${{ steps.versions.outputs.branches-max }} --ignore-platform-reqs --with-dependencies
|
||||
|
||||
- name: Run coding standards check
|
||||
run: composer run psalm -- --threads=1 --monochrome --no-progress --output-format=github
|
||||
27
.github/workflows/reuse.yml
vendored
Normal file
27
.github/workflows/reuse.yml
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
# This workflow is provided via the organization template repository
|
||||
#
|
||||
# https://github.com/nextcloud/.github
|
||||
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
|
||||
|
||||
# SPDX-FileCopyrightText: 2022 Free Software Foundation Europe e.V. <https://fsfe.org>
|
||||
#
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
name: REUSE Compliance Check
|
||||
|
||||
on: [pull_request]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
reuse-compliance-check:
|
||||
runs-on: ubuntu-latest-low
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: REUSE Compliance Check
|
||||
uses: fsfe/reuse-action@bb774aa972c2a89ff34781233d275075cbddf542 # v5.0.0
|
||||
58
.github/workflows/update-nextcloud-ocp-approve-merge.yml
vendored
Normal file
58
.github/workflows/update-nextcloud-ocp-approve-merge.yml
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
# This workflow is provided via the organization template repository
|
||||
#
|
||||
# https://github.com/nextcloud/.github
|
||||
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2023-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
name: Auto approve nextcloud/ocp
|
||||
|
||||
on:
|
||||
pull_request_target: # zizmor: ignore[dangerous-triggers]
|
||||
branches:
|
||||
- main
|
||||
- master
|
||||
- stable*
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: update-nextcloud-ocp-approve-merge-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
auto-approve-merge:
|
||||
if: github.actor == 'nextcloud-command'
|
||||
runs-on: ubuntu-latest-low
|
||||
permissions:
|
||||
# for hmarr/auto-approve-action to approve PRs
|
||||
pull-requests: write
|
||||
# for alexwilson/enable-github-automerge-action to approve PRs
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- name: Disabled on forks
|
||||
if: ${{ github.event.pull_request.head.repo.full_name != github.repository }}
|
||||
run: |
|
||||
echo 'Can not approve PRs from forks'
|
||||
exit 1
|
||||
|
||||
- uses: mdecoleman/pr-branch-name@55795d86b4566d300d237883103f052125cc7508 # v3.0.0
|
||||
id: branchname
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# GitHub actions bot approve
|
||||
- uses: hmarr/auto-approve-action@b40d6c9ed2fa10c9a2749eca7eb004418a705501 # v2
|
||||
if: startsWith(steps.branchname.outputs.branch, 'automated/noid/') && endsWith(steps.branchname.outputs.branch, 'update-nextcloud-ocp')
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# Enable GitHub auto merge
|
||||
- name: Auto merge
|
||||
uses: alexwilson/enable-github-automerge-action@56e3117d1ae1540309dc8f7a9f2825bc3c5f06ff # v2.0.0
|
||||
if: startsWith(steps.branchname.outputs.branch, 'automated/noid/') && endsWith(steps.branchname.outputs.branch, 'update-nextcloud-ocp')
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
123
.github/workflows/update-nextcloud-ocp.yml
vendored
Normal file
123
.github/workflows/update-nextcloud-ocp.yml
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
# This workflow is provided via the organization template repository
|
||||
#
|
||||
# https://github.com/nextcloud/.github
|
||||
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2022-2024 Nextcloud GmbH and Nextcloud contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
name: Update nextcloud/ocp
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: "5 2 * * 0"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
update-nextcloud-ocp:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
branches: ['main', 'master', 'stable32', 'stable31', 'stable30']
|
||||
|
||||
name: update-nextcloud-ocp-${{ matrix.branches }}
|
||||
|
||||
steps:
|
||||
- id: checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
ref: ${{ matrix.branches }}
|
||||
submodules: true
|
||||
continue-on-error: true
|
||||
|
||||
- name: Set up php8.2
|
||||
if: steps.checkout.outcome == 'success'
|
||||
uses: shivammathur/setup-php@0f7f1d08e3e32076e51cae65eb0b0c871405b16e # v2.34.1
|
||||
with:
|
||||
php-version: 8.2
|
||||
# https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation
|
||||
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite
|
||||
coverage: none
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Read codeowners
|
||||
if: steps.checkout.outcome == 'success'
|
||||
id: codeowners
|
||||
run: |
|
||||
grep '/appinfo/info.xml' .github/CODEOWNERS | cut -f 2- -d ' ' | xargs | awk '{ print "codeowners="$0 }' >> $GITHUB_OUTPUT
|
||||
continue-on-error: true
|
||||
|
||||
- name: Composer install
|
||||
if: steps.checkout.outcome == 'success'
|
||||
run: composer install
|
||||
|
||||
- name: Composer update nextcloud/ocp
|
||||
id: update_branch
|
||||
if: ${{ steps.checkout.outcome == 'success' && matrix.branches != 'main' }}
|
||||
run: composer require --dev 'nextcloud/ocp:dev-${{ matrix.branches }}'
|
||||
|
||||
- name: Raise on issue on failure
|
||||
uses: dacbd/create-issue-action@cdb57ab6ff8862aa09fee2be6ba77a59581921c2 # v2.0.0
|
||||
if: ${{ steps.checkout.outcome == 'success' && failure() && steps.update_branch.conclusion == 'failure' }}
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
title: 'Failed to update nextcloud/ocp package on branch ${{ matrix.branches }}'
|
||||
body: 'Please check the output of the GitHub action and manually resolve the issues<br>${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}<br>${{ steps.codeowners.outputs.codeowners }}'
|
||||
|
||||
- name: Composer update nextcloud/ocp
|
||||
id: update_main
|
||||
if: ${{ steps.checkout.outcome == 'success' && matrix.branches == 'main' }}
|
||||
run: composer require --dev nextcloud/ocp:dev-master
|
||||
|
||||
- name: Raise on issue on failure
|
||||
uses: dacbd/create-issue-action@cdb57ab6ff8862aa09fee2be6ba77a59581921c2 # v2.0.0
|
||||
if: ${{ steps.checkout.outcome == 'success' && failure() && steps.update_main.conclusion == 'failure' }}
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
title: 'Failed to update nextcloud/ocp package on branch ${{ matrix.branches }}'
|
||||
body: 'Please check the output of the GitHub action and manually resolve the issues<br>${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}<br>${{ steps.codeowners.outputs.codeowners }}'
|
||||
|
||||
- name: Reset checkout 3rdparty
|
||||
if: steps.checkout.outcome == 'success'
|
||||
run: |
|
||||
git clean -f 3rdparty
|
||||
git checkout 3rdparty
|
||||
continue-on-error: true
|
||||
|
||||
- name: Reset checkout vendor
|
||||
if: steps.checkout.outcome == 'success'
|
||||
run: |
|
||||
git clean -f vendor
|
||||
git checkout vendor
|
||||
continue-on-error: true
|
||||
|
||||
- name: Reset checkout vendor-bin
|
||||
if: steps.checkout.outcome == 'success'
|
||||
run: |
|
||||
git clean -f vendor-bin
|
||||
git checkout vendor-bin
|
||||
continue-on-error: true
|
||||
|
||||
- name: Create Pull Request
|
||||
if: steps.checkout.outcome == 'success'
|
||||
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
|
||||
with:
|
||||
token: ${{ secrets.COMMAND_BOT_PAT }}
|
||||
commit-message: 'chore(dev-deps): Bump nextcloud/ocp package'
|
||||
committer: GitHub <noreply@github.com>
|
||||
author: nextcloud-command <nextcloud-command@users.noreply.github.com>
|
||||
signoff: true
|
||||
branch: 'automated/noid/${{ matrix.branches }}-update-nextcloud-ocp'
|
||||
title: '[${{ matrix.branches }}] Update nextcloud/ocp dependency'
|
||||
body: |
|
||||
Auto-generated update of [nextcloud/ocp](https://github.com/nextcloud-deps/ocp/) dependency
|
||||
labels: |
|
||||
dependencies
|
||||
3. to review
|
||||
@@ -24,7 +24,7 @@ Deck is a kanban style organization tool aimed at personal planning and project
|
||||
### Mobile apps
|
||||
|
||||
- [Nextcloud Deck app for Android](https://github.com/stefan-niedermann/nextcloud-deck) - It is available in [F-Droid](https://f-droid.org/de/packages/it.niedermann.nextcloud.deck/) and the [Google Play Store](https://play.google.com/store/apps/details?id=it.niedermann.nextcloud.deck.play)
|
||||
- Nextcloud Deck app for iOS - It is available in [Apple App store](https://apps.apple.com/de/app/next-deck/id6752478755)
|
||||
- [Nextcloud Deck app for iOS](https://github.com/StCyr/deck-react-native) - It is available in [Apple App store](https://apps.apple.com/ml/app/nextcloud-deck/id1570892788)
|
||||
|
||||
### 3rd-Party Integrations
|
||||
|
||||
|
||||
@@ -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-master",
|
||||
"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"
|
||||
|
||||
102
composer.lock
generated
102
composer.lock
generated
@@ -4,65 +4,8 @@
|
||||
"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": "6950663d9d213151028e780637480220",
|
||||
"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.4.2",
|
||||
@@ -437,12 +380,12 @@
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nextcloud-deps/ocp.git",
|
||||
"reference": "9a2e6c0bf6f2d87e1db8d18063a5bedf85040bb2"
|
||||
"reference": "d927392a2a368c372ef80096171139d4287b2339"
|
||||
},
|
||||
"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/d927392a2a368c372ef80096171139d4287b2339",
|
||||
"reference": "d927392a2a368c372ef80096171139d4287b2339",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -478,7 +421,7 @@
|
||||
"issues": "https://github.com/nextcloud-deps/ocp/issues",
|
||||
"source": "https://github.com/nextcloud-deps/ocp/tree/master"
|
||||
},
|
||||
"time": "2025-09-27T00:45:05+00:00"
|
||||
"time": "2025-09-16T00:45:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nikic/php-parser",
|
||||
@@ -1130,6 +1073,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",
|
||||
|
||||
@@ -9,11 +9,9 @@ OC.L10N.register(
|
||||
"Missing a temporary folder" : "Адсутнічае часовая папка",
|
||||
"Could not write file to disk" : "Не ўдалося запісаць файл на дыск",
|
||||
"A PHP extension stopped the file upload" : "Пашырэнне PHP спыніла запампоўванне файла",
|
||||
"No file uploaded or file size exceeds maximum of %s" : "Файл не запампаваны, або памер файла перавышае максімальны %s",
|
||||
"copy" : "копія",
|
||||
"Done" : "Гатова",
|
||||
"File" : "Файл",
|
||||
"Invalid date, date format must be YYYY-MM-DD" : "Памылковая дата, дата павінна быць у фармаце ГГГГ-ММ-ДД",
|
||||
"Cancel" : "Скасаваць",
|
||||
"Drop your files to upload" : "Перацягніце файлы для запампоўвання",
|
||||
"File already exists" : "Файл ужо існуе",
|
||||
@@ -52,7 +50,6 @@ OC.L10N.register(
|
||||
"Reply" : "Адказаць",
|
||||
"Update" : "Абнавіць",
|
||||
"Description" : "Апісанне",
|
||||
"Formatting help" : "Даведка па фармаціраванні",
|
||||
"Later today – {timeLocale}" : "Пазней сёння – {timeLocale}",
|
||||
"Set due date for later today" : "Задаць дату выканання на пазней сёння",
|
||||
"Tomorrow – {timeLocale}" : "Заўтра – {timeLocale}",
|
||||
@@ -60,7 +57,6 @@ OC.L10N.register(
|
||||
"Set due date for this weekend" : "Задаць дату выканання на гэты ўік-энд",
|
||||
"Next week – {timeLocale}" : "На наступным тыдні – {timeLocale}",
|
||||
"Set due date for next week" : "Задаць дату выканання на наступны тыдзень",
|
||||
"Create a new tag:" : "Стварыць новы тэг:",
|
||||
"(group)" : "(група)",
|
||||
"Open link" : "Адкрыць спасылку",
|
||||
"Edit title" : "Рэдагаваць загаловак",
|
||||
@@ -69,7 +65,6 @@ OC.L10N.register(
|
||||
"Keyboard shortcut" : "Спалучэнне клавіш",
|
||||
"Action" : "Дзеянне",
|
||||
"Shift" : "Shift",
|
||||
"Ctrl" : "Ctrl",
|
||||
"Search" : "Пошук",
|
||||
"Enter" : "Enter",
|
||||
"Shared with you" : "Абагулена з вамі",
|
||||
@@ -84,9 +79,6 @@ OC.L10N.register(
|
||||
"Failed to upload {name}" : "Не ўдалося запампаваць {name}",
|
||||
"Share" : "Абагуліць",
|
||||
"Personal" : "Асабістыя",
|
||||
"Example Task 3" : "Прыклад задання 3",
|
||||
"Example Task 2" : "Прыклад задання 2",
|
||||
"Example Task 1" : "Прыклад задання 1",
|
||||
"Today" : "Сёння",
|
||||
"Tomorrow" : "Заўтра"
|
||||
},
|
||||
|
||||
@@ -7,11 +7,9 @@
|
||||
"Missing a temporary folder" : "Адсутнічае часовая папка",
|
||||
"Could not write file to disk" : "Не ўдалося запісаць файл на дыск",
|
||||
"A PHP extension stopped the file upload" : "Пашырэнне PHP спыніла запампоўванне файла",
|
||||
"No file uploaded or file size exceeds maximum of %s" : "Файл не запампаваны, або памер файла перавышае максімальны %s",
|
||||
"copy" : "копія",
|
||||
"Done" : "Гатова",
|
||||
"File" : "Файл",
|
||||
"Invalid date, date format must be YYYY-MM-DD" : "Памылковая дата, дата павінна быць у фармаце ГГГГ-ММ-ДД",
|
||||
"Cancel" : "Скасаваць",
|
||||
"Drop your files to upload" : "Перацягніце файлы для запампоўвання",
|
||||
"File already exists" : "Файл ужо існуе",
|
||||
@@ -50,7 +48,6 @@
|
||||
"Reply" : "Адказаць",
|
||||
"Update" : "Абнавіць",
|
||||
"Description" : "Апісанне",
|
||||
"Formatting help" : "Даведка па фармаціраванні",
|
||||
"Later today – {timeLocale}" : "Пазней сёння – {timeLocale}",
|
||||
"Set due date for later today" : "Задаць дату выканання на пазней сёння",
|
||||
"Tomorrow – {timeLocale}" : "Заўтра – {timeLocale}",
|
||||
@@ -58,7 +55,6 @@
|
||||
"Set due date for this weekend" : "Задаць дату выканання на гэты ўік-энд",
|
||||
"Next week – {timeLocale}" : "На наступным тыдні – {timeLocale}",
|
||||
"Set due date for next week" : "Задаць дату выканання на наступны тыдзень",
|
||||
"Create a new tag:" : "Стварыць новы тэг:",
|
||||
"(group)" : "(група)",
|
||||
"Open link" : "Адкрыць спасылку",
|
||||
"Edit title" : "Рэдагаваць загаловак",
|
||||
@@ -67,7 +63,6 @@
|
||||
"Keyboard shortcut" : "Спалучэнне клавіш",
|
||||
"Action" : "Дзеянне",
|
||||
"Shift" : "Shift",
|
||||
"Ctrl" : "Ctrl",
|
||||
"Search" : "Пошук",
|
||||
"Enter" : "Enter",
|
||||
"Shared with you" : "Абагулена з вамі",
|
||||
@@ -82,9 +77,6 @@
|
||||
"Failed to upload {name}" : "Не ўдалося запампаваць {name}",
|
||||
"Share" : "Абагуліць",
|
||||
"Personal" : "Асабістыя",
|
||||
"Example Task 3" : "Прыклад задання 3",
|
||||
"Example Task 2" : "Прыклад задання 2",
|
||||
"Example Task 1" : "Прыклад задання 1",
|
||||
"Today" : "Сёння",
|
||||
"Tomorrow" : "Заўтра"
|
||||
},"pluralForm" :"nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);"
|
||||
|
||||
@@ -51,8 +51,8 @@ OC.L10N.register(
|
||||
"{user} has assigned the card {deck-card} on {deck-board} to you." : "{user} har tilknyttet kortet {deck-card} på {deck-board} til dig.",
|
||||
"The card \"%s\" on \"%s\" has reached its due date." : "Kortet \"%s\" på \"%s\" har nået sin forfaldsdato.",
|
||||
"The card {deck-card} on {deck-board} has reached its due date." : "Kortet {deck-card} på {deck-board} har nået sin forfaldsdato.",
|
||||
"%s has mentioned you in a comment on \"%s\"." : " %s har omtalt dig i en kommentar på \"%s\".",
|
||||
"{user} has mentioned you in a comment on {deck-card}." : "{user} har omtalt dig i en kommentar på {deck-card}.",
|
||||
"%s has mentioned you in a comment on \"%s\"." : " %s har nævnt dig i en kommentar på \"%s\".",
|
||||
"{user} has mentioned you in a comment on {deck-card}." : "{user} har nævnt dig i en kommentar på {deck-card}.",
|
||||
"The board \"%s\" has been shared with you by %s." : "Tavlen \"%s\" er blevet delt med dig af %s.",
|
||||
"{user} has shared {deck-board} with you." : "{user} har delt {deck-board} med dig.",
|
||||
"Deck board" : "Opslagstavle",
|
||||
@@ -188,10 +188,6 @@ OC.L10N.register(
|
||||
"Add Attachment" : "Tilføj vedhæftning",
|
||||
"Choose attachment" : "Vælg en vedhæftning",
|
||||
"Select Date" : "Vælg dato",
|
||||
"Later today – {timeLocale}" : "Senere i dag – {timeLocale}",
|
||||
"Tomorrow – {timeLocale}" : "I morgen – {timeLocale}",
|
||||
"This weekend – {timeLocale}" : "Denne weekend – {timeLocale}",
|
||||
"Next week – {timeLocale}" : "Næste uge – {timeLocale}",
|
||||
"Set a due date" : "Angiv en forfaldsdato",
|
||||
"Remove due date" : "Fjern forfaldsdato",
|
||||
"Mark as done" : "Marker som færdig",
|
||||
|
||||
@@ -49,8 +49,8 @@
|
||||
"{user} has assigned the card {deck-card} on {deck-board} to you." : "{user} har tilknyttet kortet {deck-card} på {deck-board} til dig.",
|
||||
"The card \"%s\" on \"%s\" has reached its due date." : "Kortet \"%s\" på \"%s\" har nået sin forfaldsdato.",
|
||||
"The card {deck-card} on {deck-board} has reached its due date." : "Kortet {deck-card} på {deck-board} har nået sin forfaldsdato.",
|
||||
"%s has mentioned you in a comment on \"%s\"." : " %s har omtalt dig i en kommentar på \"%s\".",
|
||||
"{user} has mentioned you in a comment on {deck-card}." : "{user} har omtalt dig i en kommentar på {deck-card}.",
|
||||
"%s has mentioned you in a comment on \"%s\"." : " %s har nævnt dig i en kommentar på \"%s\".",
|
||||
"{user} has mentioned you in a comment on {deck-card}." : "{user} har nævnt dig i en kommentar på {deck-card}.",
|
||||
"The board \"%s\" has been shared with you by %s." : "Tavlen \"%s\" er blevet delt med dig af %s.",
|
||||
"{user} has shared {deck-board} with you." : "{user} har delt {deck-board} med dig.",
|
||||
"Deck board" : "Opslagstavle",
|
||||
@@ -186,10 +186,6 @@
|
||||
"Add Attachment" : "Tilføj vedhæftning",
|
||||
"Choose attachment" : "Vælg en vedhæftning",
|
||||
"Select Date" : "Vælg dato",
|
||||
"Later today – {timeLocale}" : "Senere i dag – {timeLocale}",
|
||||
"Tomorrow – {timeLocale}" : "I morgen – {timeLocale}",
|
||||
"This weekend – {timeLocale}" : "Denne weekend – {timeLocale}",
|
||||
"Next week – {timeLocale}" : "Næste uge – {timeLocale}",
|
||||
"Set a due date" : "Angiv en forfaldsdato",
|
||||
"Remove due date" : "Fjern forfaldsdato",
|
||||
"Mark as done" : "Marker som færdig",
|
||||
|
||||
@@ -373,7 +373,6 @@ OC.L10N.register(
|
||||
"Note: Only the JSON format is supported for importing back into the Deck app." : "Megjegyzés: Csak a JSON formátum támogatott a Kártyák alkalmazásba való importáláskor.",
|
||||
"Export" : "Exportálás",
|
||||
"Loading filtered view" : "Szűrt nézet betöltése",
|
||||
"Search for {searchQuery} in other boards" : "Keresés a(z) {searchQuery} kifejezésre a többi táblában",
|
||||
"Search for {searchQuery} in all boards" : "Keresés a(z) {searchQuery} kifejezésre az összes táblában",
|
||||
"No results found" : "Nincs találat",
|
||||
"Deck board {name}\n* Last modified on {lastMod}" : "{name} kártyatábla\n* Legutóbb módosítva: {lastMod}",
|
||||
|
||||
@@ -371,7 +371,6 @@
|
||||
"Note: Only the JSON format is supported for importing back into the Deck app." : "Megjegyzés: Csak a JSON formátum támogatott a Kártyák alkalmazásba való importáláskor.",
|
||||
"Export" : "Exportálás",
|
||||
"Loading filtered view" : "Szűrt nézet betöltése",
|
||||
"Search for {searchQuery} in other boards" : "Keresés a(z) {searchQuery} kifejezésre a többi táblában",
|
||||
"Search for {searchQuery} in all boards" : "Keresés a(z) {searchQuery} kifejezésre az összes táblában",
|
||||
"No results found" : "Nincs találat",
|
||||
"Deck board {name}\n* Last modified on {lastMod}" : "{name} kártyatábla\n* Legutóbb módosítva: {lastMod}",
|
||||
|
||||
@@ -6,19 +6,16 @@ OC.L10N.register(
|
||||
"No file was uploaded" : "Ulac afaylu i d-yettwasulin",
|
||||
"Missing a temporary folder" : "Ixuṣ ukaram akudan",
|
||||
"Finished" : "Immed",
|
||||
"copy" : "nɣel",
|
||||
"Done" : "Immed",
|
||||
"Attachments" : "Ticeqqufin",
|
||||
"File" : "Afaylu",
|
||||
"Cancel" : "Sefsex",
|
||||
"Open" : "Ldi",
|
||||
"Completed" : "Yemmed",
|
||||
"Open details" : "Ldi talqayt",
|
||||
"Details" : "Talqayt",
|
||||
"Sharing" : "Beṭṭu",
|
||||
"Tags" : "Tibzimin",
|
||||
"Activity" : "Armud",
|
||||
"Transfer" : "Seḍfeṛ",
|
||||
"Owner" : "Bab",
|
||||
"Delete" : "Kkes",
|
||||
"Edit" : "Ẓreg",
|
||||
@@ -29,9 +26,6 @@ OC.L10N.register(
|
||||
"Save" : "Sekles",
|
||||
"Cancel reply" : "Semmet tiririt.",
|
||||
"Reply" : "Err",
|
||||
"Description" : "Aglam",
|
||||
"Open link" : "Nɣel aseɣwen",
|
||||
"Keyboard shortcuts" : "Inegzumen n unasiw",
|
||||
"Ctrl" : "Ctrl",
|
||||
"Search" : "Nadi",
|
||||
"Cancel edit" : "Sefsex aseẓreg",
|
||||
|
||||
@@ -4,19 +4,16 @@
|
||||
"No file was uploaded" : "Ulac afaylu i d-yettwasulin",
|
||||
"Missing a temporary folder" : "Ixuṣ ukaram akudan",
|
||||
"Finished" : "Immed",
|
||||
"copy" : "nɣel",
|
||||
"Done" : "Immed",
|
||||
"Attachments" : "Ticeqqufin",
|
||||
"File" : "Afaylu",
|
||||
"Cancel" : "Sefsex",
|
||||
"Open" : "Ldi",
|
||||
"Completed" : "Yemmed",
|
||||
"Open details" : "Ldi talqayt",
|
||||
"Details" : "Talqayt",
|
||||
"Sharing" : "Beṭṭu",
|
||||
"Tags" : "Tibzimin",
|
||||
"Activity" : "Armud",
|
||||
"Transfer" : "Seḍfeṛ",
|
||||
"Owner" : "Bab",
|
||||
"Delete" : "Kkes",
|
||||
"Edit" : "Ẓreg",
|
||||
@@ -27,9 +24,6 @@
|
||||
"Save" : "Sekles",
|
||||
"Cancel reply" : "Semmet tiririt.",
|
||||
"Reply" : "Err",
|
||||
"Description" : "Aglam",
|
||||
"Open link" : "Nɣel aseɣwen",
|
||||
"Keyboard shortcuts" : "Inegzumen n unasiw",
|
||||
"Ctrl" : "Ctrl",
|
||||
"Search" : "Nadi",
|
||||
"Cancel edit" : "Sefsex aseẓreg",
|
||||
|
||||
140
l10n/mk.js
140
l10n/mk.js
@@ -12,7 +12,7 @@ OC.L10N.register(
|
||||
"You have removed {acl} from the board {board}" : "Го избришавте {acl} од таблата {board}",
|
||||
"{user} has removed {acl} from the board {board}" : "{user} го избриша {acl} од таблата {board}",
|
||||
"You have renamed the board {before} to {board}" : "Ја преименувавте таблата {before} во {board}",
|
||||
"{user} has renamed the board {before} to {board}" : "{user} ја преименуваше таблата {before} во {board}",
|
||||
"{user} has renamed the board {before} to {board}" : "{user} ја преименување таблата {before} во {board}",
|
||||
"You have archived the board {board}" : "Ја архивиравте таблата {board}",
|
||||
"{user} has archived the board {before}" : "{user} ја архивирање таблата {before}",
|
||||
"You have unarchived the board {board}" : "Ја вративте од архива таблата {board}",
|
||||
@@ -20,7 +20,7 @@ OC.L10N.register(
|
||||
"You have created a new list {stack} on board {board}" : "Креиравте нова листа {stack} на таблата {board}",
|
||||
"{user} has created a new list {stack} on board {board}" : "{user} креирање нова листа {stack} на таблата {board}",
|
||||
"You have renamed list {before} to {stack} on board {board}" : "Ја преименувавте листа {before} во {stack} на таблата {board}",
|
||||
"{user} has renamed list {before} to {stack} on board {board}" : "{user} ја преименуваше листата {before} во {stack} на таблата {board}",
|
||||
"{user} has renamed list {before} to {stack} on board {board}" : "{user} ја преименување листата {before} во {stack} на таблата {board}",
|
||||
"You have deleted list {stack} on board {board}" : "Ја избришавте листата {stack} од таблата {board}",
|
||||
"{user} has deleted list {stack} on board {board}" : "{user} ја избриша листата {stack} од таблата {board}",
|
||||
"You have created card {card} in list {stack} on board {board}" : "Креиравте картица {card} во листата {stack} на таблата {board}",
|
||||
@@ -28,7 +28,7 @@ OC.L10N.register(
|
||||
"You have deleted card {card} in list {stack} on board {board}" : "Избришавте картица {card} во листата {stack} на таблата {board}",
|
||||
"{user} has deleted card {card} in list {stack} on board {board}" : "{user} избриша картица {card} во листата {stack} на таблата {board}",
|
||||
"You have renamed the card {before} to {card}" : "Ја преименувавте картицата {before} во {card}",
|
||||
"{user} has renamed the card {before} to {card}" : "{user} ја преименуваше картицата {before} во {card}",
|
||||
"{user} has renamed the card {before} to {card}" : "{user} ја преименување картицата {before} во {card}",
|
||||
"You have added a description to card {card} in list {stack} on board {board}" : "Додадовте опис на картицата {card} во листата {stack} на таблата {board}",
|
||||
"{user} has added a description to card {card} in list {stack} on board {board}" : "{user} додаде опис на картицата {card} во листата {stack} на таблата {board}",
|
||||
"You have updated the description of card {card} in list {stack} on board {board}" : "Го ажуриравте описот на картицата {card} во листата {stack} на таблата {board}",
|
||||
@@ -37,10 +37,6 @@ OC.L10N.register(
|
||||
"{user} has archived card {card} in list {stack} on board {board}" : "{user} ја архивираше картицата {card} во листата {stack} на таблата {board}",
|
||||
"You have unarchived card {card} in list {stack} on board {board}" : "Ја вративте од архива картицата {card} во листата {stack} на таблата {board}",
|
||||
"{user} has unarchived card {card} in list {stack} on board {board}" : "{user} ја врати од архива картицата {card} во листата {stack} на таблата {board}",
|
||||
"You have marked the card {card} as done in list {stack} on board {board}" : "Ја означивте картицата {card} како завршена во листата {stack} на таблата {board}",
|
||||
"{user} has marked card {card} as done in list {stack} on board {board}" : "{user} ја означи картичката {card} како завршена во листата {stack} на таблата {board}",
|
||||
"You have marked the card {card} as undone in list {stack} on board {board}" : "Ја означивте картицата {card} како не-завршена во листата {stack} на таблата {board}",
|
||||
"{user} has marked the card {card} as undone in list {stack} on board {board}" : "{user} ја означи картичката {card} како не-завршена во листата {stack} на таблата {board}",
|
||||
"You have removed the due date of card {card}" : "Го избришавте датумот на истекување на картицата {card}",
|
||||
"{user} has removed the due date of card {card}" : "{user} го избриша датумот на истекување на картицата {card}",
|
||||
"You have set the due date of card {card} to {after}" : "Поставивте датум на истекување на картицата {card}",
|
||||
@@ -69,9 +65,7 @@ OC.L10N.register(
|
||||
"{user} has commented on card {card}" : "{user} коментирање на картицата {card}",
|
||||
"Deck" : "Deck",
|
||||
"Changes in the <strong>Deck app</strong>" : "Промени во <strong>апликацијата Deck</strong>",
|
||||
"A <strong>board, list or card</strong> was changed" : "Променета е <strong>табла, листа или картица</strong>",
|
||||
"A <strong>comment</strong> was created on a card" : "<strong>Коментар</strong> е креиран на картица",
|
||||
"A <strong>card description</strong> has been changed" : "Променет е <strong>опис на картица</strong> ",
|
||||
"The file was uploaded" : "Датотеката е прикачена",
|
||||
"The uploaded file exceeds the upload_max_filesize directive in php.ini" : "Подигнатата датотека ја надминува upload_max_filesize директивата во php.ini",
|
||||
"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" : "Големината на датотеката ја надминува MAX_FILE_SIZE директивата која беше специфицирана во HTML формата",
|
||||
@@ -81,66 +75,35 @@ OC.L10N.register(
|
||||
"Could not write file to disk" : "Неможе да се запишува на дискот",
|
||||
"A PHP extension stopped the file upload" : "PHP додаток го стопираше прикачувањето на датотеката",
|
||||
"No file uploaded or file size exceeds maximum of %s" : "Нема прикачена дадотека или големината го надмминува максимумот од %s",
|
||||
"Invalid file type. Only JSON files are allowed." : "Невалиден тип на датотека. Дозволени се само JSON датотеки.",
|
||||
"Invalid JSON data" : "Невалидни JSON податоци",
|
||||
"Failed to import board" : "Неуспешен увоз на табла",
|
||||
"Cards due today" : "Картици со рок до денес",
|
||||
"Cards due tomorrow" : "Картици со рок до утре",
|
||||
"Upcoming cards" : "Престојни картици",
|
||||
"Load more" : "Вчитај повеќе",
|
||||
"Welcome to Nextcloud Deck!" : "Добредојдовте во Nextcloud Deck!",
|
||||
"The card \"%s\" on \"%s\" has been assigned to you by %s." : "Картицата \"%s\" на \"%s\" ти е доделена од %s.",
|
||||
"{user} has assigned the card {deck-card} on {deck-board} to you." : "{user} ти ја додели картицата {deck-card} на {deck-board}.",
|
||||
"The card \"%s\" on \"%s\" has reached its due date." : "Картицата \"%s\" на \"%s\" го достигна датумот на истекување.",
|
||||
"The card {deck-card} on {deck-board} has reached its due date." : "Картицата {deck-card} на {deck-board} го достигна рокот.",
|
||||
"%s has mentioned you in a comment on \"%s\"." : "%s те спомна во коментар на \"%s\".",
|
||||
"{user} has mentioned you in a comment on {deck-card}." : "{user} те спомна во коментар на {deck-card}.",
|
||||
"The board \"%s\" has been shared with you by %s." : "Таблата \"%s\" ја сподли со тебе %s.",
|
||||
"{user} has shared {deck-board} with you." : "{user} сподели {deck-board} со вас.",
|
||||
"Deck board" : "Табла",
|
||||
"Owned by %1$s" : "Сопственик %1$s",
|
||||
"Deck boards, cards and comments" : "Табли, картици и коментари",
|
||||
"From %1$s, in %2$s/%3$s, owned by %4$s" : "Од %1$s, во %2$s/%3$s, сопственик %4$s",
|
||||
"Create a new deck card" : "Креирај нова картица",
|
||||
"Card comments" : "Коментари на картица",
|
||||
"%s on %s" : "%s на %s",
|
||||
"Deck boards and cards" : "Табли и картици",
|
||||
"No data was provided to create an attachment." : "Нема податоци за креирање на прилог.",
|
||||
"Finished" : "Завршено",
|
||||
"To review" : "На ревизија",
|
||||
"Action needed" : "Потребна е акција",
|
||||
"Later" : "Покасно",
|
||||
"copy" : "копирај",
|
||||
"Read more inside" : "Прочитај повеќе",
|
||||
"Custom lists - click to rename!" : "Прилагодени листи – кликнете за преименување!",
|
||||
"To Do" : "За правење",
|
||||
"In Progress" : "Во тек",
|
||||
"Done" : "Готово",
|
||||
"1. Open to learn more about boards and cards" : "1. Отворете за да дознаете повеќе за таблите и картичките",
|
||||
"2. Drag cards left and right, up and down" : "2. Влечете ги картичките лево и десно, горе и долу",
|
||||
"3. Apply rich formatting and link content" : "3. Применете богато форматирање и поврзете содржина",
|
||||
"4. Share, comment and collaborate!" : "4. Споделувајте, коментирајте и соработувајте!",
|
||||
"Create your first card!" : "Креирајте ја вашата прва картичка!",
|
||||
"This comment has more than %s characters.\nAdded as an attachment to the card with name %s.\nAccessible on URL: %s." : "Коментарот има повеќе од %s карактери.\nДодаден е како пролог на картицата со име %s.\nДостапен е на линк: %s.",
|
||||
"Attachments" : "Прилози",
|
||||
"File" : "Датотека",
|
||||
"date" : "датум",
|
||||
"Card not found" : "Картицата не е пронајдена",
|
||||
"Path is already shared with this card" : "Патеката веќе е споделена со оваа картица",
|
||||
"Invalid date, date format must be YYYY-MM-DD" : "Невалиден датум, форматот мора да биде ГГГГ-ММ-ДД",
|
||||
"Personal planning and team project organization" : "Персонален планер и тимски проект организер",
|
||||
"Deck is a kanban style organization tool aimed at personal planning and project organization for teams integrated with Nextcloud.\n\n\n- 📥 Add your tasks to cards and put them in order\n- 📄 Write down additional notes in Markdown\n- 🔖 Assign labels for even better organization\n- 👥 Share with your team, friends or family\n- 📎 Attach files and embed them in your Markdown description\n- 💬 Discuss with your team using comments\n- ⚡ Keep track of changes in the activity stream\n- 🚀 Get your project organized" : "Deck е алатка за организација во стил на kanban, наменета за лични планови и организација на проекти за тимови интегрирани со Nextcloud.\n\n\n📥 Додај ги задачите на картички и подреди ги\n📄 Запиши дополнителни белешки во Markdown\n🔖 Додели етикети за уште подобра организација\n👥 Сподели со твојот тим, пријатели или семејство\n📎 Прикачи датотеки и вметни ги во Markdown описот\n💬 Дискутирај со твојот тим преку коментари\n⚡ Следи ги промените во активностите\n🚀 Организирај го твојот проект",
|
||||
"Add board" : "Додади табла",
|
||||
"Card details" : "Детали за картица",
|
||||
"Select the board to link to a project" : "Избери табла за поврзување со проект",
|
||||
"Search by board title" : "Барај по име на табла",
|
||||
"Select board" : "Избери табла",
|
||||
"Move/copy card" : "Премести/копирај картица",
|
||||
"Select a board" : "Избери табла",
|
||||
"No lists available" : "Нема достапни листи",
|
||||
"Select a list" : "Избери листа",
|
||||
"Move card" : "Премести картица",
|
||||
"Copy card" : "Копирај картица",
|
||||
"Select the card to link to a project" : "Избери картица за поврзување со проект",
|
||||
"Link to card" : "Линк до картица",
|
||||
"Select a card" : "Избери картица",
|
||||
@@ -161,8 +124,6 @@ OC.L10N.register(
|
||||
"Filter by tag" : "Филтрирај по ознака",
|
||||
"Filter by assigned user" : "Филтрирај по назначени корисници",
|
||||
"Unassigned" : "Неназначени",
|
||||
"Filter by status" : "Филтрирај по статус",
|
||||
"Open and completed" : "Отворени и завршени",
|
||||
"Open" : "Отвори",
|
||||
"Completed" : "Завршено",
|
||||
"Filter by due date" : "Филтрирај по краен рок",
|
||||
@@ -172,17 +133,12 @@ OC.L10N.register(
|
||||
"Next 30 days" : "Следни 30 дена",
|
||||
"No due date" : "Нема краен рок",
|
||||
"Clear filter" : "Исчисти филтри",
|
||||
"View Modes" : "Режими на приказ",
|
||||
"Toggle View Modes" : "Промени режими на приказ",
|
||||
"Hide archived cards" : "Сокриј ги архивираните картици",
|
||||
"Show archived cards" : "Прикажи ги архивираните картици",
|
||||
"Toggle compact mode" : "Вклучи компактен мод",
|
||||
"Hide card cover images" : "Сокриј насловни слики на картици",
|
||||
"Show card cover images" : "Прикажи насловни слики на картици",
|
||||
"Open details" : "Отвори детали",
|
||||
"Details" : "Детали",
|
||||
"Currently present people" : "Моментално приситни корисници",
|
||||
"Loading board" : "Вчитување на табла",
|
||||
"Loading board" : "Вчирување на табла",
|
||||
"Board not found" : "Таблата не е пронајдена",
|
||||
"Create a new list to add cards to this board" : "Додадете нова листа за да додадете картици на таблата",
|
||||
"Sharing" : "Споделување",
|
||||
@@ -193,29 +149,19 @@ OC.L10N.register(
|
||||
"Undo" : "Врати",
|
||||
"Deleted cards" : "Избришани картици",
|
||||
"Failed to create share with {displayName}" : "Неможе да се сподели со {displayName}",
|
||||
"Are you sure you want to transfer the board {title} to {user}?" : "Дали сте сигурни дека сакате да ја префрлите таблата {title} на {user}?",
|
||||
"Transfer the board." : "Префрли табла.",
|
||||
"Transfer" : "Трансфер",
|
||||
"The board has been transferred to {user}" : "Таблата е префрлена на {user}",
|
||||
"Failed to transfer the board to {user}" : "Неуспешно префрлање на таблата на {user}",
|
||||
"Share board with a user, group or team …" : "Сподели табла со корисник, група или тим...",
|
||||
"Searching for users, groups and teams …" : "Пребарување на корисници, групи или тимови...",
|
||||
"No participants found" : "Не се пронајдени учесници",
|
||||
"Board owner" : "Сопственик на таблата",
|
||||
"(Group)" : "(Група)",
|
||||
"(Team)" : "(Тим)",
|
||||
"Can edit" : "Може да се уредува",
|
||||
"Can share" : "Can share",
|
||||
"Can manage" : "Може да ја менаџира",
|
||||
"Owner" : "Сопственик",
|
||||
"Delete" : "Избриши",
|
||||
"List deleted" : "Листата е избришана",
|
||||
"Edit list title" : "Удери наслов на листата",
|
||||
"Archive all cards" : "Архивирај ги сите картици",
|
||||
"Unarchive all cards" : "Врати ги од архива сите картици",
|
||||
"Delete list" : "Избриши листа",
|
||||
"Archive all cards in this list" : "Архивирај ги сите картици во листата",
|
||||
"Unarchive all cards in this list" : "Врати ги од архива сите картици во оваа листа",
|
||||
"Add a new card" : "Додади нова картица",
|
||||
"Card name" : "Име на картицата",
|
||||
"title and color value must be provided" : "Мора да се внесе наслов и боја",
|
||||
@@ -223,39 +169,32 @@ OC.L10N.register(
|
||||
"Add a new tag" : "Додади нова ознака",
|
||||
"Board name" : "Име на табла",
|
||||
"Members" : "Членови",
|
||||
"Assign to users/groups/team" : "Додели на корисници/групи/тимови",
|
||||
"Assign a user to this card…" : "Додели корисник на оваа картица...",
|
||||
"Select a user to assign to this card…" : "Избери на кого да се додели оваа картица…",
|
||||
"File to share" : "Датотека за споделување",
|
||||
"Invalid path selected" : "Избрана невалидна патека",
|
||||
"Upload new files" : "Прикачи нови датотеки",
|
||||
"Share from Files" : "Сподели од датотеките",
|
||||
"Pending share" : "Споделување на чекање",
|
||||
"Add this attachment" : "Додади го овој прилог",
|
||||
"Show in Files" : "Прикажи во датотеките",
|
||||
"Download" : "Преземи",
|
||||
"Remove attachment" : "Отстрани прилог",
|
||||
"Delete Attachment" : "Избриши прилог",
|
||||
"Restore Attachment" : "Врати прилог",
|
||||
"Modified" : "Изменето",
|
||||
"Created" : "Креирано",
|
||||
"The title cannot be empty." : "Насловот неможе да биде празен.",
|
||||
"Cannot close unsaved card!" : "Неможе да се затвори незачувана картица!",
|
||||
"Open in sidebar view" : "Отвори страничен поглед",
|
||||
"Open in bigger view" : "Отвори на голем екран",
|
||||
"Comments" : "Коментари",
|
||||
"Failed to load comments" : "Неуспешно вчитување на коментари",
|
||||
"No comments yet. Begin the discussion!" : "Сеуште нема коментари. Започни дискусија!",
|
||||
"The comment cannot be empty." : "Коментарот неможе да биде празен.",
|
||||
"The comment cannot be longer than 1000 characters." : "Коментарот неможе да биде поголем од 1000 карактери.",
|
||||
"Save" : "Зачувај",
|
||||
"Created:" : "Создадено:",
|
||||
"In reply to" : "Како одговор на",
|
||||
"Cancel reply" : "Откажи одговор",
|
||||
"Reply" : "Одговор",
|
||||
"Update" : "Ажурирај",
|
||||
"Write a description …" : "Напиши опис ...",
|
||||
"Could not save description" : "Неможе да се зачува описот",
|
||||
"Description" : "Опис",
|
||||
"(Unsaved)" : "(Незачувано)",
|
||||
"(Saving…)" : "(Снимање…)",
|
||||
@@ -266,135 +205,67 @@ OC.L10N.register(
|
||||
"Choose attachment" : "Избери прилог",
|
||||
"Select Date" : "Избери датум",
|
||||
"Later today – {timeLocale}" : "Денес покасно – {timeLocale}",
|
||||
"Set due date for later today" : "Постави краен рок за денес подоцна",
|
||||
"Tomorrow – {timeLocale}" : "Утре – {timeLocale}",
|
||||
"Set due date for tomorrow" : "Постави краен рок за утре",
|
||||
"This weekend – {timeLocale}" : "Овој викенд – {timeLocale}",
|
||||
"Set due date for this weekend" : "Постави краен рок за овој викенд",
|
||||
"Next week – {timeLocale}" : "Следна недела – {timeLocale}",
|
||||
"Set due date for next week" : "Постави краен рок за следната недела",
|
||||
"Set due date for this weekend" : "Постави рок за овој викенд",
|
||||
"Assign a due date to this card…" : "Додели рок за оваа картица…",
|
||||
"Set a due date" : "Постави краен рок",
|
||||
"Add due date" : "Додади краен рок",
|
||||
"Choose a date" : "Избери датум",
|
||||
"Remove due date" : "Отстрани краен рок",
|
||||
"Mark as done" : "Означи како готово",
|
||||
"Due at:" : "Краен рок:",
|
||||
"Not done" : "Не е завршено",
|
||||
"Unarchive card" : "Врати картица од архива",
|
||||
"Archive card" : "Архивирај картица",
|
||||
"Assign a tag to this card…" : "Додади ознака на оваа картица...",
|
||||
"Select or create a tag…" : "Избери или креирај ознака...",
|
||||
"Create a new tag:" : "Направи нова ознака:",
|
||||
"(group)" : "(group)",
|
||||
"{count} comments, {unread} unread" : "{count} коментари, {unread} непрочитани",
|
||||
"Todo items" : "Задачи",
|
||||
"Edit card title" : "Измени наслов на картица",
|
||||
"Open link" : "Отвори линк",
|
||||
"Card deleted" : "Картицата е избришана",
|
||||
"Edit title" : "Удери наслов",
|
||||
"Assign to me" : "Доделени мене",
|
||||
"Unassign myself" : "Откажи се",
|
||||
"Mark as not done" : "Означи како не-готово",
|
||||
"Delete card" : "Избриши картица",
|
||||
"seconds ago" : "пред неколку секунди",
|
||||
"Keyboard shortcuts" : "Кратенки преку тастатура",
|
||||
"Boost your productivity using Deck with keyboard shortcuts." : "Зголеми ја продуктивноста со користење на кратенки преку тастатура.",
|
||||
"Board actions" : "Акции за табла",
|
||||
"Keyboard shortcut" : "Кратенка преку тастатура",
|
||||
"Action" : "Акција",
|
||||
"Shift" : "Shift",
|
||||
"Scroll" : "Scroll",
|
||||
"Scroll sideways" : "Лизгај странично",
|
||||
"Navigate between cards" : "Навигација помеѓу картиците",
|
||||
"Esc" : "Esc",
|
||||
"Close card details" : "Затвори детали на картица",
|
||||
"Ctrl" : "Ctrl",
|
||||
"Search" : "Барај",
|
||||
"Show card filters" : "Прикажи филтри за картици",
|
||||
"Clear card filters" : "Исчисти филтри за картици",
|
||||
"Show help dialog" : "Прикажи дијалог за помош",
|
||||
"Card actions" : "Акции за картици",
|
||||
"The following actions can be triggered on the currently highlighted card" : "Следните акции можат да се активираат на моментално обележаната картичка",
|
||||
"Enter" : "Ентер",
|
||||
"Space" : "Празно место",
|
||||
"Open card details" : "Отвори детали на картица",
|
||||
"Edit the card title" : "Измени наслов на картица",
|
||||
"Assign yourself to the current card" : "Доделете се себеси на тековната картица",
|
||||
"Archive/unarchive the current card" : "Архивирај/одархивирај тековната картица",
|
||||
"Mark card as completed/not completed" : "Означи ја картицата како завршена/незавршена",
|
||||
"Open card menu" : "Отвори мени на картица",
|
||||
"All boards" : "Сите табли",
|
||||
"Archived boards" : "Архивирани табли",
|
||||
"Shared with you" : "Споделено со тебе",
|
||||
"Deck settings" : "Deck параметри",
|
||||
"Use bigger card view" : "Користи поголем преглед на картици",
|
||||
"Show card ID badge" : "Прикажи ID на картиците",
|
||||
"Show boards in calendar/tasks" : "Прикажи ги таблите во календарнот",
|
||||
"Limit board creation to some groups" : "Ограничи го креирањето на нови табли само на овие групи",
|
||||
"Users outside of those groups will not be able to create their own boards, but will still be able to work on boards that have been shared with them." : "Корисниците кој што не се во овие групи нема да можат да прават нови таби, но ќе можат да работат на таблите кој ќе бидат споделени со нив.",
|
||||
"Cancel edit" : "Откажи ажурирање",
|
||||
"Save board" : "Зачувај табла",
|
||||
"Board {0} deleted" : "Таблата {0} е избришана",
|
||||
"All cards" : "Сите картици",
|
||||
"Only assigned cards" : "Само доделени картици",
|
||||
"No reminder" : "Нема потсетник",
|
||||
"An error occurred" : "Настана грешка",
|
||||
"Are you sure you want to delete the board {title}? This will delete all the data of this board including archived cards." : "Дали сте сигурени дека сакате да ја избришете оваа табла {title}? Ова ќе ги избрише и сите податоци во таблата и архивираните картици.",
|
||||
"Delete the board?" : "Бришење на таблата?",
|
||||
"Exporting board..." : "Извоз на табла...",
|
||||
"Board details" : "Детали за таблата",
|
||||
"Edit board" : "Измени табла",
|
||||
"Clone board" : "Клонирај табла",
|
||||
"Unarchive board" : "Врати табла од архива",
|
||||
"Archive board" : "Архивирај табла",
|
||||
"Export board" : "Извези табла",
|
||||
"Turn on due date reminders" : "Вклучи потсетници за крајните рокови",
|
||||
"Turn off due date reminders" : "Исклучи потсетници за крајните рокови",
|
||||
"Due date reminders" : "Потсетници за крајните рокови",
|
||||
"Assigned cards" : "Доделени картици",
|
||||
"No notifications" : "Нема известувања",
|
||||
"Delete board" : "Избриши табла",
|
||||
"Importing board..." : "Увезување табла...",
|
||||
"Board imported successfully" : "Таблата е успешно увезена",
|
||||
"Import board" : "Увези табла",
|
||||
"Clone {boardTitle}" : "Клонирај {boardTitle}",
|
||||
"Clone cards" : "Клинирај картици",
|
||||
"Clone assignments" : "Клонирај задачи",
|
||||
"Clone labels" : "Клонирај ознаки",
|
||||
"Clone due dates" : "Клонирај крајни рокови",
|
||||
"Advanced options" : "Напредни опции",
|
||||
"Move all cards to the first list" : "Помести ги сите картици во првата листа",
|
||||
"Restore archived cards" : "Врати архивирани картици",
|
||||
"Clone" : "Клонирај",
|
||||
"Export {boardTitle}" : "Извези {boardTitle}",
|
||||
"Export as JSON" : "Извези како JSON",
|
||||
"Export as CSV" : "Извези како CSV",
|
||||
"Note: Only the JSON format is supported for importing back into the Deck app." : "Забелешка: Поддржан е само JSON формат за увоз назад во апликацијата Deck.",
|
||||
"Export" : "Извези",
|
||||
"Loading filtered view" : "Вчитување на филтриран поглед",
|
||||
"Search for {searchQuery} in other boards" : "Барај {searchQuery} во други табли",
|
||||
"Search for {searchQuery} in all boards" : "Барај {searchQuery} во сите табли",
|
||||
"No results found" : "Нема пронајдено резултати",
|
||||
"Deck board {name}\n* Last modified on {lastMod}" : "Табла {name}\n* Последна промена на {lastMod}",
|
||||
"* Created on {created}\n* Last modified on {lastMod}\n* {nbAttachments} attachments\n* {nbComments} comments" : "* Креирана на {created}\n* Последна промена на {lastMod}\n* {nbAttachments} прилози\n* {nbComments} коментари",
|
||||
"{nbCards} cards" : "{nbCards} картици",
|
||||
"Due on {date}" : "Истекува на {date}",
|
||||
"{stack} in {board}" : "{stack} во {board}",
|
||||
"Click to expand description" : "Кликнни за проширување на опис",
|
||||
"Click to expand comment" : "Кликнни за проширување на коментарот",
|
||||
"Create card" : "Креирајте картица",
|
||||
"Create a new card" : "Креирајте нова картица",
|
||||
"Card title" : "Наслов на картицата",
|
||||
"Creating the new card …" : "Креирање нова картица ...",
|
||||
"Card \"{card}\" was added to \"{board}\"" : "Картицата \"{card}\" е додадена во \"{board}\"",
|
||||
"Open card" : "Отвори картица",
|
||||
"Close" : "Затвори",
|
||||
"No upcoming cards" : "Нема престојни картици",
|
||||
"upcoming cards today" : "престојни картици за денес",
|
||||
"upcoming cards tomorrow" : "престојни картици за утре",
|
||||
"upcoming cards" : "престојни картици",
|
||||
"New card" : "Нова картица",
|
||||
"Link to a board" : "Линк до табла",
|
||||
"Link to a card" : "Линк до картица",
|
||||
"Create a card" : "Креирајте картица",
|
||||
@@ -402,7 +273,6 @@ OC.L10N.register(
|
||||
"Something went wrong" : "Нешто не е во ред",
|
||||
"Failed to upload {name}" : "Неуспешно прикачување {name}",
|
||||
"Maximum file size of {size} exceeded" : "Максималната големина на датотека од {size} е достигната",
|
||||
"Assigned users" : "Доделени корисници",
|
||||
"Due date" : "До датум",
|
||||
"Error creating the share" : "Грешка при креирање на споделување",
|
||||
"Share with a Deck card" : "Споделено со Deck картица",
|
||||
|
||||
140
l10n/mk.json
140
l10n/mk.json
@@ -10,7 +10,7 @@
|
||||
"You have removed {acl} from the board {board}" : "Го избришавте {acl} од таблата {board}",
|
||||
"{user} has removed {acl} from the board {board}" : "{user} го избриша {acl} од таблата {board}",
|
||||
"You have renamed the board {before} to {board}" : "Ја преименувавте таблата {before} во {board}",
|
||||
"{user} has renamed the board {before} to {board}" : "{user} ја преименуваше таблата {before} во {board}",
|
||||
"{user} has renamed the board {before} to {board}" : "{user} ја преименување таблата {before} во {board}",
|
||||
"You have archived the board {board}" : "Ја архивиравте таблата {board}",
|
||||
"{user} has archived the board {before}" : "{user} ја архивирање таблата {before}",
|
||||
"You have unarchived the board {board}" : "Ја вративте од архива таблата {board}",
|
||||
@@ -18,7 +18,7 @@
|
||||
"You have created a new list {stack} on board {board}" : "Креиравте нова листа {stack} на таблата {board}",
|
||||
"{user} has created a new list {stack} on board {board}" : "{user} креирање нова листа {stack} на таблата {board}",
|
||||
"You have renamed list {before} to {stack} on board {board}" : "Ја преименувавте листа {before} во {stack} на таблата {board}",
|
||||
"{user} has renamed list {before} to {stack} on board {board}" : "{user} ја преименуваше листата {before} во {stack} на таблата {board}",
|
||||
"{user} has renamed list {before} to {stack} on board {board}" : "{user} ја преименување листата {before} во {stack} на таблата {board}",
|
||||
"You have deleted list {stack} on board {board}" : "Ја избришавте листата {stack} од таблата {board}",
|
||||
"{user} has deleted list {stack} on board {board}" : "{user} ја избриша листата {stack} од таблата {board}",
|
||||
"You have created card {card} in list {stack} on board {board}" : "Креиравте картица {card} во листата {stack} на таблата {board}",
|
||||
@@ -26,7 +26,7 @@
|
||||
"You have deleted card {card} in list {stack} on board {board}" : "Избришавте картица {card} во листата {stack} на таблата {board}",
|
||||
"{user} has deleted card {card} in list {stack} on board {board}" : "{user} избриша картица {card} во листата {stack} на таблата {board}",
|
||||
"You have renamed the card {before} to {card}" : "Ја преименувавте картицата {before} во {card}",
|
||||
"{user} has renamed the card {before} to {card}" : "{user} ја преименуваше картицата {before} во {card}",
|
||||
"{user} has renamed the card {before} to {card}" : "{user} ја преименување картицата {before} во {card}",
|
||||
"You have added a description to card {card} in list {stack} on board {board}" : "Додадовте опис на картицата {card} во листата {stack} на таблата {board}",
|
||||
"{user} has added a description to card {card} in list {stack} on board {board}" : "{user} додаде опис на картицата {card} во листата {stack} на таблата {board}",
|
||||
"You have updated the description of card {card} in list {stack} on board {board}" : "Го ажуриравте описот на картицата {card} во листата {stack} на таблата {board}",
|
||||
@@ -35,10 +35,6 @@
|
||||
"{user} has archived card {card} in list {stack} on board {board}" : "{user} ја архивираше картицата {card} во листата {stack} на таблата {board}",
|
||||
"You have unarchived card {card} in list {stack} on board {board}" : "Ја вративте од архива картицата {card} во листата {stack} на таблата {board}",
|
||||
"{user} has unarchived card {card} in list {stack} on board {board}" : "{user} ја врати од архива картицата {card} во листата {stack} на таблата {board}",
|
||||
"You have marked the card {card} as done in list {stack} on board {board}" : "Ја означивте картицата {card} како завршена во листата {stack} на таблата {board}",
|
||||
"{user} has marked card {card} as done in list {stack} on board {board}" : "{user} ја означи картичката {card} како завршена во листата {stack} на таблата {board}",
|
||||
"You have marked the card {card} as undone in list {stack} on board {board}" : "Ја означивте картицата {card} како не-завршена во листата {stack} на таблата {board}",
|
||||
"{user} has marked the card {card} as undone in list {stack} on board {board}" : "{user} ја означи картичката {card} како не-завршена во листата {stack} на таблата {board}",
|
||||
"You have removed the due date of card {card}" : "Го избришавте датумот на истекување на картицата {card}",
|
||||
"{user} has removed the due date of card {card}" : "{user} го избриша датумот на истекување на картицата {card}",
|
||||
"You have set the due date of card {card} to {after}" : "Поставивте датум на истекување на картицата {card}",
|
||||
@@ -67,9 +63,7 @@
|
||||
"{user} has commented on card {card}" : "{user} коментирање на картицата {card}",
|
||||
"Deck" : "Deck",
|
||||
"Changes in the <strong>Deck app</strong>" : "Промени во <strong>апликацијата Deck</strong>",
|
||||
"A <strong>board, list or card</strong> was changed" : "Променета е <strong>табла, листа или картица</strong>",
|
||||
"A <strong>comment</strong> was created on a card" : "<strong>Коментар</strong> е креиран на картица",
|
||||
"A <strong>card description</strong> has been changed" : "Променет е <strong>опис на картица</strong> ",
|
||||
"The file was uploaded" : "Датотеката е прикачена",
|
||||
"The uploaded file exceeds the upload_max_filesize directive in php.ini" : "Подигнатата датотека ја надминува upload_max_filesize директивата во php.ini",
|
||||
"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" : "Големината на датотеката ја надминува MAX_FILE_SIZE директивата која беше специфицирана во HTML формата",
|
||||
@@ -79,66 +73,35 @@
|
||||
"Could not write file to disk" : "Неможе да се запишува на дискот",
|
||||
"A PHP extension stopped the file upload" : "PHP додаток го стопираше прикачувањето на датотеката",
|
||||
"No file uploaded or file size exceeds maximum of %s" : "Нема прикачена дадотека или големината го надмминува максимумот од %s",
|
||||
"Invalid file type. Only JSON files are allowed." : "Невалиден тип на датотека. Дозволени се само JSON датотеки.",
|
||||
"Invalid JSON data" : "Невалидни JSON податоци",
|
||||
"Failed to import board" : "Неуспешен увоз на табла",
|
||||
"Cards due today" : "Картици со рок до денес",
|
||||
"Cards due tomorrow" : "Картици со рок до утре",
|
||||
"Upcoming cards" : "Престојни картици",
|
||||
"Load more" : "Вчитај повеќе",
|
||||
"Welcome to Nextcloud Deck!" : "Добредојдовте во Nextcloud Deck!",
|
||||
"The card \"%s\" on \"%s\" has been assigned to you by %s." : "Картицата \"%s\" на \"%s\" ти е доделена од %s.",
|
||||
"{user} has assigned the card {deck-card} on {deck-board} to you." : "{user} ти ја додели картицата {deck-card} на {deck-board}.",
|
||||
"The card \"%s\" on \"%s\" has reached its due date." : "Картицата \"%s\" на \"%s\" го достигна датумот на истекување.",
|
||||
"The card {deck-card} on {deck-board} has reached its due date." : "Картицата {deck-card} на {deck-board} го достигна рокот.",
|
||||
"%s has mentioned you in a comment on \"%s\"." : "%s те спомна во коментар на \"%s\".",
|
||||
"{user} has mentioned you in a comment on {deck-card}." : "{user} те спомна во коментар на {deck-card}.",
|
||||
"The board \"%s\" has been shared with you by %s." : "Таблата \"%s\" ја сподли со тебе %s.",
|
||||
"{user} has shared {deck-board} with you." : "{user} сподели {deck-board} со вас.",
|
||||
"Deck board" : "Табла",
|
||||
"Owned by %1$s" : "Сопственик %1$s",
|
||||
"Deck boards, cards and comments" : "Табли, картици и коментари",
|
||||
"From %1$s, in %2$s/%3$s, owned by %4$s" : "Од %1$s, во %2$s/%3$s, сопственик %4$s",
|
||||
"Create a new deck card" : "Креирај нова картица",
|
||||
"Card comments" : "Коментари на картица",
|
||||
"%s on %s" : "%s на %s",
|
||||
"Deck boards and cards" : "Табли и картици",
|
||||
"No data was provided to create an attachment." : "Нема податоци за креирање на прилог.",
|
||||
"Finished" : "Завршено",
|
||||
"To review" : "На ревизија",
|
||||
"Action needed" : "Потребна е акција",
|
||||
"Later" : "Покасно",
|
||||
"copy" : "копирај",
|
||||
"Read more inside" : "Прочитај повеќе",
|
||||
"Custom lists - click to rename!" : "Прилагодени листи – кликнете за преименување!",
|
||||
"To Do" : "За правење",
|
||||
"In Progress" : "Во тек",
|
||||
"Done" : "Готово",
|
||||
"1. Open to learn more about boards and cards" : "1. Отворете за да дознаете повеќе за таблите и картичките",
|
||||
"2. Drag cards left and right, up and down" : "2. Влечете ги картичките лево и десно, горе и долу",
|
||||
"3. Apply rich formatting and link content" : "3. Применете богато форматирање и поврзете содржина",
|
||||
"4. Share, comment and collaborate!" : "4. Споделувајте, коментирајте и соработувајте!",
|
||||
"Create your first card!" : "Креирајте ја вашата прва картичка!",
|
||||
"This comment has more than %s characters.\nAdded as an attachment to the card with name %s.\nAccessible on URL: %s." : "Коментарот има повеќе од %s карактери.\nДодаден е како пролог на картицата со име %s.\nДостапен е на линк: %s.",
|
||||
"Attachments" : "Прилози",
|
||||
"File" : "Датотека",
|
||||
"date" : "датум",
|
||||
"Card not found" : "Картицата не е пронајдена",
|
||||
"Path is already shared with this card" : "Патеката веќе е споделена со оваа картица",
|
||||
"Invalid date, date format must be YYYY-MM-DD" : "Невалиден датум, форматот мора да биде ГГГГ-ММ-ДД",
|
||||
"Personal planning and team project organization" : "Персонален планер и тимски проект организер",
|
||||
"Deck is a kanban style organization tool aimed at personal planning and project organization for teams integrated with Nextcloud.\n\n\n- 📥 Add your tasks to cards and put them in order\n- 📄 Write down additional notes in Markdown\n- 🔖 Assign labels for even better organization\n- 👥 Share with your team, friends or family\n- 📎 Attach files and embed them in your Markdown description\n- 💬 Discuss with your team using comments\n- ⚡ Keep track of changes in the activity stream\n- 🚀 Get your project organized" : "Deck е алатка за организација во стил на kanban, наменета за лични планови и организација на проекти за тимови интегрирани со Nextcloud.\n\n\n📥 Додај ги задачите на картички и подреди ги\n📄 Запиши дополнителни белешки во Markdown\n🔖 Додели етикети за уште подобра организација\n👥 Сподели со твојот тим, пријатели или семејство\n📎 Прикачи датотеки и вметни ги во Markdown описот\n💬 Дискутирај со твојот тим преку коментари\n⚡ Следи ги промените во активностите\n🚀 Организирај го твојот проект",
|
||||
"Add board" : "Додади табла",
|
||||
"Card details" : "Детали за картица",
|
||||
"Select the board to link to a project" : "Избери табла за поврзување со проект",
|
||||
"Search by board title" : "Барај по име на табла",
|
||||
"Select board" : "Избери табла",
|
||||
"Move/copy card" : "Премести/копирај картица",
|
||||
"Select a board" : "Избери табла",
|
||||
"No lists available" : "Нема достапни листи",
|
||||
"Select a list" : "Избери листа",
|
||||
"Move card" : "Премести картица",
|
||||
"Copy card" : "Копирај картица",
|
||||
"Select the card to link to a project" : "Избери картица за поврзување со проект",
|
||||
"Link to card" : "Линк до картица",
|
||||
"Select a card" : "Избери картица",
|
||||
@@ -159,8 +122,6 @@
|
||||
"Filter by tag" : "Филтрирај по ознака",
|
||||
"Filter by assigned user" : "Филтрирај по назначени корисници",
|
||||
"Unassigned" : "Неназначени",
|
||||
"Filter by status" : "Филтрирај по статус",
|
||||
"Open and completed" : "Отворени и завршени",
|
||||
"Open" : "Отвори",
|
||||
"Completed" : "Завршено",
|
||||
"Filter by due date" : "Филтрирај по краен рок",
|
||||
@@ -170,17 +131,12 @@
|
||||
"Next 30 days" : "Следни 30 дена",
|
||||
"No due date" : "Нема краен рок",
|
||||
"Clear filter" : "Исчисти филтри",
|
||||
"View Modes" : "Режими на приказ",
|
||||
"Toggle View Modes" : "Промени режими на приказ",
|
||||
"Hide archived cards" : "Сокриј ги архивираните картици",
|
||||
"Show archived cards" : "Прикажи ги архивираните картици",
|
||||
"Toggle compact mode" : "Вклучи компактен мод",
|
||||
"Hide card cover images" : "Сокриј насловни слики на картици",
|
||||
"Show card cover images" : "Прикажи насловни слики на картици",
|
||||
"Open details" : "Отвори детали",
|
||||
"Details" : "Детали",
|
||||
"Currently present people" : "Моментално приситни корисници",
|
||||
"Loading board" : "Вчитување на табла",
|
||||
"Loading board" : "Вчирување на табла",
|
||||
"Board not found" : "Таблата не е пронајдена",
|
||||
"Create a new list to add cards to this board" : "Додадете нова листа за да додадете картици на таблата",
|
||||
"Sharing" : "Споделување",
|
||||
@@ -191,29 +147,19 @@
|
||||
"Undo" : "Врати",
|
||||
"Deleted cards" : "Избришани картици",
|
||||
"Failed to create share with {displayName}" : "Неможе да се сподели со {displayName}",
|
||||
"Are you sure you want to transfer the board {title} to {user}?" : "Дали сте сигурни дека сакате да ја префрлите таблата {title} на {user}?",
|
||||
"Transfer the board." : "Префрли табла.",
|
||||
"Transfer" : "Трансфер",
|
||||
"The board has been transferred to {user}" : "Таблата е префрлена на {user}",
|
||||
"Failed to transfer the board to {user}" : "Неуспешно префрлање на таблата на {user}",
|
||||
"Share board with a user, group or team …" : "Сподели табла со корисник, група или тим...",
|
||||
"Searching for users, groups and teams …" : "Пребарување на корисници, групи или тимови...",
|
||||
"No participants found" : "Не се пронајдени учесници",
|
||||
"Board owner" : "Сопственик на таблата",
|
||||
"(Group)" : "(Група)",
|
||||
"(Team)" : "(Тим)",
|
||||
"Can edit" : "Може да се уредува",
|
||||
"Can share" : "Can share",
|
||||
"Can manage" : "Може да ја менаџира",
|
||||
"Owner" : "Сопственик",
|
||||
"Delete" : "Избриши",
|
||||
"List deleted" : "Листата е избришана",
|
||||
"Edit list title" : "Удери наслов на листата",
|
||||
"Archive all cards" : "Архивирај ги сите картици",
|
||||
"Unarchive all cards" : "Врати ги од архива сите картици",
|
||||
"Delete list" : "Избриши листа",
|
||||
"Archive all cards in this list" : "Архивирај ги сите картици во листата",
|
||||
"Unarchive all cards in this list" : "Врати ги од архива сите картици во оваа листа",
|
||||
"Add a new card" : "Додади нова картица",
|
||||
"Card name" : "Име на картицата",
|
||||
"title and color value must be provided" : "Мора да се внесе наслов и боја",
|
||||
@@ -221,39 +167,32 @@
|
||||
"Add a new tag" : "Додади нова ознака",
|
||||
"Board name" : "Име на табла",
|
||||
"Members" : "Членови",
|
||||
"Assign to users/groups/team" : "Додели на корисници/групи/тимови",
|
||||
"Assign a user to this card…" : "Додели корисник на оваа картица...",
|
||||
"Select a user to assign to this card…" : "Избери на кого да се додели оваа картица…",
|
||||
"File to share" : "Датотека за споделување",
|
||||
"Invalid path selected" : "Избрана невалидна патека",
|
||||
"Upload new files" : "Прикачи нови датотеки",
|
||||
"Share from Files" : "Сподели од датотеките",
|
||||
"Pending share" : "Споделување на чекање",
|
||||
"Add this attachment" : "Додади го овој прилог",
|
||||
"Show in Files" : "Прикажи во датотеките",
|
||||
"Download" : "Преземи",
|
||||
"Remove attachment" : "Отстрани прилог",
|
||||
"Delete Attachment" : "Избриши прилог",
|
||||
"Restore Attachment" : "Врати прилог",
|
||||
"Modified" : "Изменето",
|
||||
"Created" : "Креирано",
|
||||
"The title cannot be empty." : "Насловот неможе да биде празен.",
|
||||
"Cannot close unsaved card!" : "Неможе да се затвори незачувана картица!",
|
||||
"Open in sidebar view" : "Отвори страничен поглед",
|
||||
"Open in bigger view" : "Отвори на голем екран",
|
||||
"Comments" : "Коментари",
|
||||
"Failed to load comments" : "Неуспешно вчитување на коментари",
|
||||
"No comments yet. Begin the discussion!" : "Сеуште нема коментари. Започни дискусија!",
|
||||
"The comment cannot be empty." : "Коментарот неможе да биде празен.",
|
||||
"The comment cannot be longer than 1000 characters." : "Коментарот неможе да биде поголем од 1000 карактери.",
|
||||
"Save" : "Зачувај",
|
||||
"Created:" : "Создадено:",
|
||||
"In reply to" : "Како одговор на",
|
||||
"Cancel reply" : "Откажи одговор",
|
||||
"Reply" : "Одговор",
|
||||
"Update" : "Ажурирај",
|
||||
"Write a description …" : "Напиши опис ...",
|
||||
"Could not save description" : "Неможе да се зачува описот",
|
||||
"Description" : "Опис",
|
||||
"(Unsaved)" : "(Незачувано)",
|
||||
"(Saving…)" : "(Снимање…)",
|
||||
@@ -264,135 +203,67 @@
|
||||
"Choose attachment" : "Избери прилог",
|
||||
"Select Date" : "Избери датум",
|
||||
"Later today – {timeLocale}" : "Денес покасно – {timeLocale}",
|
||||
"Set due date for later today" : "Постави краен рок за денес подоцна",
|
||||
"Tomorrow – {timeLocale}" : "Утре – {timeLocale}",
|
||||
"Set due date for tomorrow" : "Постави краен рок за утре",
|
||||
"This weekend – {timeLocale}" : "Овој викенд – {timeLocale}",
|
||||
"Set due date for this weekend" : "Постави краен рок за овој викенд",
|
||||
"Next week – {timeLocale}" : "Следна недела – {timeLocale}",
|
||||
"Set due date for next week" : "Постави краен рок за следната недела",
|
||||
"Set due date for this weekend" : "Постави рок за овој викенд",
|
||||
"Assign a due date to this card…" : "Додели рок за оваа картица…",
|
||||
"Set a due date" : "Постави краен рок",
|
||||
"Add due date" : "Додади краен рок",
|
||||
"Choose a date" : "Избери датум",
|
||||
"Remove due date" : "Отстрани краен рок",
|
||||
"Mark as done" : "Означи како готово",
|
||||
"Due at:" : "Краен рок:",
|
||||
"Not done" : "Не е завршено",
|
||||
"Unarchive card" : "Врати картица од архива",
|
||||
"Archive card" : "Архивирај картица",
|
||||
"Assign a tag to this card…" : "Додади ознака на оваа картица...",
|
||||
"Select or create a tag…" : "Избери или креирај ознака...",
|
||||
"Create a new tag:" : "Направи нова ознака:",
|
||||
"(group)" : "(group)",
|
||||
"{count} comments, {unread} unread" : "{count} коментари, {unread} непрочитани",
|
||||
"Todo items" : "Задачи",
|
||||
"Edit card title" : "Измени наслов на картица",
|
||||
"Open link" : "Отвори линк",
|
||||
"Card deleted" : "Картицата е избришана",
|
||||
"Edit title" : "Удери наслов",
|
||||
"Assign to me" : "Доделени мене",
|
||||
"Unassign myself" : "Откажи се",
|
||||
"Mark as not done" : "Означи како не-готово",
|
||||
"Delete card" : "Избриши картица",
|
||||
"seconds ago" : "пред неколку секунди",
|
||||
"Keyboard shortcuts" : "Кратенки преку тастатура",
|
||||
"Boost your productivity using Deck with keyboard shortcuts." : "Зголеми ја продуктивноста со користење на кратенки преку тастатура.",
|
||||
"Board actions" : "Акции за табла",
|
||||
"Keyboard shortcut" : "Кратенка преку тастатура",
|
||||
"Action" : "Акција",
|
||||
"Shift" : "Shift",
|
||||
"Scroll" : "Scroll",
|
||||
"Scroll sideways" : "Лизгај странично",
|
||||
"Navigate between cards" : "Навигација помеѓу картиците",
|
||||
"Esc" : "Esc",
|
||||
"Close card details" : "Затвори детали на картица",
|
||||
"Ctrl" : "Ctrl",
|
||||
"Search" : "Барај",
|
||||
"Show card filters" : "Прикажи филтри за картици",
|
||||
"Clear card filters" : "Исчисти филтри за картици",
|
||||
"Show help dialog" : "Прикажи дијалог за помош",
|
||||
"Card actions" : "Акции за картици",
|
||||
"The following actions can be triggered on the currently highlighted card" : "Следните акции можат да се активираат на моментално обележаната картичка",
|
||||
"Enter" : "Ентер",
|
||||
"Space" : "Празно место",
|
||||
"Open card details" : "Отвори детали на картица",
|
||||
"Edit the card title" : "Измени наслов на картица",
|
||||
"Assign yourself to the current card" : "Доделете се себеси на тековната картица",
|
||||
"Archive/unarchive the current card" : "Архивирај/одархивирај тековната картица",
|
||||
"Mark card as completed/not completed" : "Означи ја картицата како завршена/незавршена",
|
||||
"Open card menu" : "Отвори мени на картица",
|
||||
"All boards" : "Сите табли",
|
||||
"Archived boards" : "Архивирани табли",
|
||||
"Shared with you" : "Споделено со тебе",
|
||||
"Deck settings" : "Deck параметри",
|
||||
"Use bigger card view" : "Користи поголем преглед на картици",
|
||||
"Show card ID badge" : "Прикажи ID на картиците",
|
||||
"Show boards in calendar/tasks" : "Прикажи ги таблите во календарнот",
|
||||
"Limit board creation to some groups" : "Ограничи го креирањето на нови табли само на овие групи",
|
||||
"Users outside of those groups will not be able to create their own boards, but will still be able to work on boards that have been shared with them." : "Корисниците кој што не се во овие групи нема да можат да прават нови таби, но ќе можат да работат на таблите кој ќе бидат споделени со нив.",
|
||||
"Cancel edit" : "Откажи ажурирање",
|
||||
"Save board" : "Зачувај табла",
|
||||
"Board {0} deleted" : "Таблата {0} е избришана",
|
||||
"All cards" : "Сите картици",
|
||||
"Only assigned cards" : "Само доделени картици",
|
||||
"No reminder" : "Нема потсетник",
|
||||
"An error occurred" : "Настана грешка",
|
||||
"Are you sure you want to delete the board {title}? This will delete all the data of this board including archived cards." : "Дали сте сигурени дека сакате да ја избришете оваа табла {title}? Ова ќе ги избрише и сите податоци во таблата и архивираните картици.",
|
||||
"Delete the board?" : "Бришење на таблата?",
|
||||
"Exporting board..." : "Извоз на табла...",
|
||||
"Board details" : "Детали за таблата",
|
||||
"Edit board" : "Измени табла",
|
||||
"Clone board" : "Клонирај табла",
|
||||
"Unarchive board" : "Врати табла од архива",
|
||||
"Archive board" : "Архивирај табла",
|
||||
"Export board" : "Извези табла",
|
||||
"Turn on due date reminders" : "Вклучи потсетници за крајните рокови",
|
||||
"Turn off due date reminders" : "Исклучи потсетници за крајните рокови",
|
||||
"Due date reminders" : "Потсетници за крајните рокови",
|
||||
"Assigned cards" : "Доделени картици",
|
||||
"No notifications" : "Нема известувања",
|
||||
"Delete board" : "Избриши табла",
|
||||
"Importing board..." : "Увезување табла...",
|
||||
"Board imported successfully" : "Таблата е успешно увезена",
|
||||
"Import board" : "Увези табла",
|
||||
"Clone {boardTitle}" : "Клонирај {boardTitle}",
|
||||
"Clone cards" : "Клинирај картици",
|
||||
"Clone assignments" : "Клонирај задачи",
|
||||
"Clone labels" : "Клонирај ознаки",
|
||||
"Clone due dates" : "Клонирај крајни рокови",
|
||||
"Advanced options" : "Напредни опции",
|
||||
"Move all cards to the first list" : "Помести ги сите картици во првата листа",
|
||||
"Restore archived cards" : "Врати архивирани картици",
|
||||
"Clone" : "Клонирај",
|
||||
"Export {boardTitle}" : "Извези {boardTitle}",
|
||||
"Export as JSON" : "Извези како JSON",
|
||||
"Export as CSV" : "Извези како CSV",
|
||||
"Note: Only the JSON format is supported for importing back into the Deck app." : "Забелешка: Поддржан е само JSON формат за увоз назад во апликацијата Deck.",
|
||||
"Export" : "Извези",
|
||||
"Loading filtered view" : "Вчитување на филтриран поглед",
|
||||
"Search for {searchQuery} in other boards" : "Барај {searchQuery} во други табли",
|
||||
"Search for {searchQuery} in all boards" : "Барај {searchQuery} во сите табли",
|
||||
"No results found" : "Нема пронајдено резултати",
|
||||
"Deck board {name}\n* Last modified on {lastMod}" : "Табла {name}\n* Последна промена на {lastMod}",
|
||||
"* Created on {created}\n* Last modified on {lastMod}\n* {nbAttachments} attachments\n* {nbComments} comments" : "* Креирана на {created}\n* Последна промена на {lastMod}\n* {nbAttachments} прилози\n* {nbComments} коментари",
|
||||
"{nbCards} cards" : "{nbCards} картици",
|
||||
"Due on {date}" : "Истекува на {date}",
|
||||
"{stack} in {board}" : "{stack} во {board}",
|
||||
"Click to expand description" : "Кликнни за проширување на опис",
|
||||
"Click to expand comment" : "Кликнни за проширување на коментарот",
|
||||
"Create card" : "Креирајте картица",
|
||||
"Create a new card" : "Креирајте нова картица",
|
||||
"Card title" : "Наслов на картицата",
|
||||
"Creating the new card …" : "Креирање нова картица ...",
|
||||
"Card \"{card}\" was added to \"{board}\"" : "Картицата \"{card}\" е додадена во \"{board}\"",
|
||||
"Open card" : "Отвори картица",
|
||||
"Close" : "Затвори",
|
||||
"No upcoming cards" : "Нема престојни картици",
|
||||
"upcoming cards today" : "престојни картици за денес",
|
||||
"upcoming cards tomorrow" : "престојни картици за утре",
|
||||
"upcoming cards" : "престојни картици",
|
||||
"New card" : "Нова картица",
|
||||
"Link to a board" : "Линк до табла",
|
||||
"Link to a card" : "Линк до картица",
|
||||
"Create a card" : "Креирајте картица",
|
||||
@@ -400,7 +271,6 @@
|
||||
"Something went wrong" : "Нешто не е во ред",
|
||||
"Failed to upload {name}" : "Неуспешно прикачување {name}",
|
||||
"Maximum file size of {size} exceeded" : "Максималната големина на датотека од {size} е достигната",
|
||||
"Assigned users" : "Доделени корисници",
|
||||
"Due date" : "До датум",
|
||||
"Error creating the share" : "Грешка при креирање на споделување",
|
||||
"Share with a Deck card" : "Споделено со Deck картица",
|
||||
|
||||
@@ -266,7 +266,6 @@ OC.L10N.register(
|
||||
"{count} comments, {unread} unread" : "{count} reacties, {unread} ongelezen",
|
||||
"Todo items" : "Te doen onderwerpen",
|
||||
"Edit card title" : "Wijzig de titel van de kaart",
|
||||
"Open link" : "Open link",
|
||||
"Card deleted" : "Kaart verwijderd",
|
||||
"Edit title" : "Titel bewerken",
|
||||
"Assign to me" : "Aan mij toewijzen",
|
||||
@@ -280,7 +279,6 @@ OC.L10N.register(
|
||||
"Shift" : "Shift",
|
||||
"Ctrl" : "Ctrl",
|
||||
"Search" : "Zoeken",
|
||||
"Enter" : "Enter",
|
||||
"All boards" : "Alle borden",
|
||||
"Archived boards" : "Gearchiveerde borden",
|
||||
"Shared with you" : "Deelde met jou",
|
||||
|
||||
@@ -264,7 +264,6 @@
|
||||
"{count} comments, {unread} unread" : "{count} reacties, {unread} ongelezen",
|
||||
"Todo items" : "Te doen onderwerpen",
|
||||
"Edit card title" : "Wijzig de titel van de kaart",
|
||||
"Open link" : "Open link",
|
||||
"Card deleted" : "Kaart verwijderd",
|
||||
"Edit title" : "Titel bewerken",
|
||||
"Assign to me" : "Aan mij toewijzen",
|
||||
@@ -278,7 +277,6 @@
|
||||
"Shift" : "Shift",
|
||||
"Ctrl" : "Ctrl",
|
||||
"Search" : "Zoeken",
|
||||
"Enter" : "Enter",
|
||||
"All boards" : "Alle borden",
|
||||
"Archived boards" : "Gearchiveerde borden",
|
||||
"Shared with you" : "Deelde met jou",
|
||||
|
||||
@@ -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($this->request->getParam('cardId'), $stackId, $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('*')
|
||||
|
||||
@@ -107,11 +107,11 @@ class AssignmentMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
|
||||
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 +123,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 +141,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) {
|
||||
}
|
||||
@@ -134,7 +135,7 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
* @return Card[]
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findAll($stackId, ?int $limit = null, int $offset = 0, int $since = -1) {
|
||||
public function findAll($stackId, ?int $limit = null, ?int $offset = null, int $since = -1) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
->from('deck_cards')
|
||||
@@ -154,7 +155,7 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
* @return array<int, null|Card[]>
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findAllForStacks(array $stackIds, ?int $limit = null, int $offset = 0, int $since = -1): array {
|
||||
public function findAllForStacks(array $stackIds, ?int $limit = null, ?int $offset = null, int $since = -1): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
->from('deck_cards')
|
||||
@@ -193,10 +194,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 +205,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 +215,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 +270,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 +287,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 +309,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 +321,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 +329,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 +363,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 +406,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 +502,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 +555,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 +567,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 +604,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 +634,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,16 +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 int getOrder()
|
||||
* @method Card[] getCards()
|
||||
*/
|
||||
class Stack extends RelationalEntity {
|
||||
|
||||
@@ -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,11 @@ class StackMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param numeric $boardId
|
||||
* @return Stack[]
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findAll(int $boardId, ?int $limit = null, int $offset = 0): array {
|
||||
public function findAll($boardId, ?int $limit = null, ?int $offset = null): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
->from($this->getTableName())
|
||||
@@ -88,9 +93,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 +125,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 +142,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 +163,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())) {
|
||||
|
||||
@@ -77,7 +77,7 @@ class Notifier implements INotifier {
|
||||
*/
|
||||
public function prepare(INotification $notification, string $languageCode): INotification {
|
||||
$l = $this->l10nFactory->get('deck', $languageCode);
|
||||
if ($notification->getApp() !== 'deck' || $notification->getObjectType() === 'activity_notification') {
|
||||
if ($notification->getApp() !== 'deck') {
|
||||
throw new UnknownNotificationException();
|
||||
}
|
||||
$notification->setIcon($this->url->getAbsoluteURL($this->url->imagePath('deck', 'deck-dark.svg')));
|
||||
|
||||
@@ -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($id, $stackId, $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;
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ class StackService {
|
||||
|
||||
/** @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);
|
||||
$cardsByStackId = $this->cardMapper->findAllForStacks(array_map(fn (Stack $stack) => $stack->getId(), $stacks), null, null, $since);
|
||||
|
||||
foreach ($cardsByStackId as $stackId => $cards) {
|
||||
if (!$cards) {
|
||||
@@ -95,11 +95,18 @@ class StackService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 +127,17 @@ class StackService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $boardId
|
||||
*
|
||||
* @return Stack[]
|
||||
* @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 +145,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 +155,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 +164,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 +189,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 +226,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);
|
||||
@@ -235,13 +256,20 @@ class StackService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 +297,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 +327,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);
|
||||
|
||||
278
package-lock.json
generated
278
package-lock.json
generated
@@ -3636,9 +3636,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@nextcloud/dialogs": {
|
||||
"version": "6.3.2",
|
||||
"resolved": "https://registry.npmjs.org/@nextcloud/dialogs/-/dialogs-6.3.2.tgz",
|
||||
"integrity": "sha512-ioZ483wmKdNX1HdSJ1EG7ewTSyQAqlmbBALkhT4guZdR9JG8VIdnijX15qwKgAWITG2y36PWoi9Rimb3dDf+7A==",
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@nextcloud/dialogs/-/dialogs-6.3.1.tgz",
|
||||
"integrity": "sha512-lklTssGdphRZKoR07pYU88btqguEKcQjEpKYom342i1eiMPiejgmoPZEignWJvJhpaN9CT5FoGndCrqqS3BswA==",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@mdi/js": "^7.4.47",
|
||||
@@ -3661,11 +3661,11 @@
|
||||
"webdav": "^5.8.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.0.0 || ^22.0.0 || ^24.0.0",
|
||||
"npm": "^10.5.1"
|
||||
"node": "^20.0.0",
|
||||
"npm": "^10.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@nextcloud/vue": "^8.24.0",
|
||||
"@nextcloud/vue": "^8.23.1",
|
||||
"vue": "^2.7.16"
|
||||
}
|
||||
},
|
||||
@@ -5402,11 +5402,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0"
|
||||
@@ -6441,13 +6440,13 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.12.2",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz",
|
||||
"integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==",
|
||||
"version": "1.8.2",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.8.2.tgz",
|
||||
"integrity": "sha512-ls4GYBm5aig9vWx8AWDSGLpnpDQRtWAfrjU+EuytuODrFBkqesN2RkOQCBzrA1RQNHw1SmRMSDDDSwzNAYQ6Rg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.6",
|
||||
"form-data": "^4.0.4",
|
||||
"form-data": "^4.0.0",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
},
|
||||
@@ -6854,6 +6853,16 @@
|
||||
"npm": "1.2.8000 || >= 1.4.16"
|
||||
}
|
||||
},
|
||||
"node_modules/body-parser/node_modules/bytes": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
||||
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/body-parser/node_modules/debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
@@ -6890,9 +6899,7 @@
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.12",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||
"version": "1.1.11",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -7236,11 +7243,10 @@
|
||||
"integrity": "sha512-ovBpjmsgd/teRmgcPh23d4gJvxDoXtAzEL9xTfMU8Yc2kqCDb7L9jAG0XHl1nzuGl+h3ebCIF1i62UFyA9V/2Q=="
|
||||
},
|
||||
"node_modules/bytes": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
||||
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
|
||||
"integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
@@ -7278,6 +7284,7 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
|
||||
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
@@ -7444,43 +7451,16 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/cipher-base": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.7.tgz",
|
||||
"integrity": "sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA==",
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
|
||||
"integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"inherits": "^2.0.4",
|
||||
"safe-buffer": "^5.2.1",
|
||||
"to-buffer": "^1.2.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.10"
|
||||
"inherits": "^2.0.1",
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/cipher-base/node_modules/safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/cjs-module-lexer": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz",
|
||||
@@ -7755,19 +7735,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/compression": {
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz",
|
||||
"integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==",
|
||||
"version": "1.7.4",
|
||||
"resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz",
|
||||
"integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"bytes": "3.1.2",
|
||||
"compressible": "~2.0.18",
|
||||
"accepts": "~1.3.5",
|
||||
"bytes": "3.0.0",
|
||||
"compressible": "~2.0.16",
|
||||
"debug": "2.6.9",
|
||||
"negotiator": "~0.6.4",
|
||||
"on-headers": "~1.1.0",
|
||||
"safe-buffer": "5.2.1",
|
||||
"on-headers": "~1.0.2",
|
||||
"safe-buffer": "5.1.2",
|
||||
"vary": "~1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
@@ -7791,39 +7770,6 @@
|
||||
"dev": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/compression/node_modules/negotiator": {
|
||||
"version": "0.6.4",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz",
|
||||
"integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/compression/node_modules/safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"dev": true,
|
||||
@@ -9069,6 +9015,7 @@
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.1",
|
||||
@@ -9137,11 +9084,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/editorconfig/node_modules/brace-expansion": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
@@ -9417,6 +9363,7 @@
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
||||
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
@@ -9426,6 +9373,7 @@
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
||||
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
@@ -9440,6 +9388,7 @@
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
|
||||
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0"
|
||||
@@ -9449,15 +9398,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/es-set-tostringtag": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
|
||||
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
|
||||
"license": "MIT",
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz",
|
||||
"integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
"get-intrinsic": "^1.2.6",
|
||||
"has-tostringtag": "^1.0.2",
|
||||
"hasown": "^2.0.2"
|
||||
"get-intrinsic": "^1.1.3",
|
||||
"has": "^1.0.3",
|
||||
"has-tostringtag": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
@@ -10977,15 +10926,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
|
||||
"integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
|
||||
"license": "MIT",
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"es-set-tostringtag": "^2.1.0",
|
||||
"hasown": "^2.0.2",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
@@ -11089,6 +11035,7 @@
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
||||
"dev": true,
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
@@ -11142,6 +11089,7 @@
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
||||
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.2",
|
||||
@@ -11175,6 +11123,7 @@
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"dunder-proto": "^1.0.1",
|
||||
@@ -11397,6 +11346,7 @@
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
||||
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
@@ -11482,6 +11432,7 @@
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
|
||||
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
@@ -11494,7 +11445,9 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
||||
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"has-symbols": "^1.0.3"
|
||||
},
|
||||
@@ -11539,6 +11492,7 @@
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
||||
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"function-bind": "^1.1.2"
|
||||
},
|
||||
@@ -14433,11 +14387,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/js-beautify/node_modules/brace-expansion": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
@@ -15108,6 +15061,7 @@
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
||||
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
@@ -16381,11 +16335,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/on-headers": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz",
|
||||
"integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==",
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
|
||||
"integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
@@ -17470,6 +17423,16 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/raw-body/node_modules/bytes": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
||||
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/react-is": {
|
||||
"version": "18.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
|
||||
@@ -18571,49 +18534,19 @@
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/sha.js": {
|
||||
"version": "2.4.12",
|
||||
"resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz",
|
||||
"integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==",
|
||||
"version": "2.4.11",
|
||||
"resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
|
||||
"integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
|
||||
"dev": true,
|
||||
"license": "(MIT AND BSD-3-Clause)",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"inherits": "^2.0.4",
|
||||
"safe-buffer": "^5.2.1",
|
||||
"to-buffer": "^1.2.0"
|
||||
"inherits": "^2.0.1",
|
||||
"safe-buffer": "^5.0.1"
|
||||
},
|
||||
"bin": {
|
||||
"sha.js": "bin.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/sha.js/node_modules/safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/shallow-clone": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
|
||||
@@ -19727,10 +19660,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/tar-fs": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz",
|
||||
"integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==",
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.3.tgz",
|
||||
"integrity": "sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"chownr": "^1.1.1",
|
||||
"mkdirp-classic": "^0.5.2",
|
||||
@@ -19952,11 +19886,10 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/tmp": {
|
||||
"version": "0.2.5",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz",
|
||||
"integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==",
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz",
|
||||
"integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=14.14"
|
||||
}
|
||||
@@ -19968,9 +19901,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/to-buffer": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz",
|
||||
"integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==",
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.1.tgz",
|
||||
"integrity": "sha512-tB82LpAIWjhLYbqjx3X4zEeHN6M8CiuOEy2JY8SEQVdYRe3CCHOFaqrBW1doLDrfpWhplcW7BL+bO3/6S3pcDQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
@@ -20910,9 +20843,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/vue-at": {
|
||||
"version": "2.5.2",
|
||||
"resolved": "https://registry.npmjs.org/vue-at/-/vue-at-2.5.2.tgz",
|
||||
"integrity": "sha512-06FFK8V/VIS3appZf/l65H9ijmoVDrL1GHm/O/zRpHADGUulmOLa7OP3O3u6ab49n4HNJySQqYedPGqJz8EpQw==",
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/vue-at/-/vue-at-2.5.1.tgz",
|
||||
"integrity": "sha512-c17Rn8vVTXp/rvWV76jNB2PVx534eqIAP5/Tv1twCt0ebtRPIgNaJJwSaoRVISQ6vM6m3+owmtpAG1qr5g9fyQ==",
|
||||
"engines": {
|
||||
"node": ">= 14.x"
|
||||
},
|
||||
@@ -21241,10 +21174,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/webdav/node_modules/brace-expansion": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||
"license": "MIT",
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
|
||||
@@ -70,8 +70,8 @@
|
||||
"extends @nextcloud/browserslist-config"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^22.0.0",
|
||||
"npm": "^10.5.0"
|
||||
"node": "^20.0.0",
|
||||
"npm": "^10.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nextcloud/babel-config": "^1.2.0",
|
||||
|
||||
12
psalm.xml
12
psalm.xml
@@ -6,9 +6,7 @@
|
||||
xmlns="https://getpsalm.org/schema/config"
|
||||
xsi:schemaLocation="https://getpsalm.org/schema/config"
|
||||
errorBaseline="tests/psalm-baseline.xml"
|
||||
findUnusedBaselineEntry="true"
|
||||
findUnusedCode="false"
|
||||
phpVersion="8.2"
|
||||
phpVersion="8.1"
|
||||
>
|
||||
<stubs>
|
||||
<file name="tests/stub.phpstub" preloadClasses="true"/>
|
||||
@@ -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\*" />
|
||||
|
||||
@@ -107,10 +107,6 @@ export default {
|
||||
this.$store.dispatch('loadSharees')
|
||||
},
|
||||
mounted() {
|
||||
// Redirect to cleaner URL (without /index.php) if RewriteBase is enabled
|
||||
if (this.$route.path.startsWith('/index.php')) {
|
||||
window.location.href = this.$route.fullPath.replace('/index.php', '')
|
||||
}
|
||||
// Set navigation to initial state and update in case it gets toggled
|
||||
emit('toggle-navigation', { open: !this.isMobile && this.navShown, _initial: true })
|
||||
this.$nextTick(() => {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
<template>
|
||||
<div class="attachments-drag-zone"
|
||||
@dragover.prevent="!isDraggingOver && (isDraggingOver = true)"
|
||||
@dragover.prevent="handleDragOver"
|
||||
@dragleave.prevent="isDraggingOver && (isDraggingOver = false)"
|
||||
@drop.prevent="handleDropFiles">
|
||||
<slot />
|
||||
@@ -83,6 +83,13 @@ export default {
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
handleDragOver(event) {
|
||||
if (!event.dataTransfer || event.dataTransfer.items?.length <= 0) {
|
||||
return
|
||||
}
|
||||
!this.isDraggingOver && (this.isDraggingOver = true)
|
||||
},
|
||||
|
||||
handleDropFiles(event) {
|
||||
event.dataTransfer.dropEffect = 'copy'
|
||||
this.isDraggingOver = false
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user