From 046e7eceab824bd4eae83b40d51a743bad0e5ff1 Mon Sep 17 00:00:00 2001 From: Florian Steffens Date: Thu, 12 Oct 2023 14:40:38 +0200 Subject: [PATCH] enh(api): renew API docs and setup API v2 - adjust setup to make use of the new API extractor - add all needed types to extract API v1 - setup structure and first endpoints for API v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit add selection column description and test it Signed-off-by: Florian Steffens fix php 7.4 backwards compatibility Signed-off-by: Florian Steffens add tests for basic column creations Signed-off-by: Florian Steffens add a endpoint to request column objects Signed-off-by: Florian Steffens update openapi.json Signed-off-by: Florian Steffens make psalm return type more precise Signed-off-by: Florian Steffens fix psalm types recognition Signed-off-by: Florian Steffens fix route Signed-off-by: Florian Steffens cleanup debug info Signed-off-by: Florian Steffens Cleanup annotations Signed-off-by: Florian Steffens Hide sensitive data from showing to the users. Signed-off-by: Florian Steffens Refactor OCS-API-Controller to abstract class Signed-off-by: Florian Steffens Update lib/Db/Column.php Co-authored-by: Julius Härtl Signed-off-by: Florian Update lib/Controller/ApiGeneralController.php Co-authored-by: Julius Härtl Signed-off-by: Florian Update lib/Controller/ApiTablesController.php Co-authored-by: Julius Härtl Signed-off-by: Florian Update lib/Controller/ApiTablesController.php Co-authored-by: Julius Härtl Signed-off-by: Florian Update lib/Controller/MyOCSController.php Co-authored-by: Julius Härtl Signed-off-by: Florian add specific endpoints to create different columns by type - fix error handling in ColumnService.php Signed-off-by: Florian Steffens add basic integration tests for the api v2 table endpoints Signed-off-by: Florian Steffens fix api routes & update API docs Signed-off-by: Florian Steffens cypress fix typo Signed-off-by: Florian Steffens initial new API setup - introduce api v2 - organise API methods in own controllers - Add virtual version tag to the names in docs - use OCS routes and controllers Signed-off-by: Florian Steffens Setup skeleton to keep old api v1 and setup v2 with integration testing Signed-off-by: Florian Steffens try to use php8.1 for over all CI Signed-off-by: Florian Steffens add openapi.json Signed-off-by: Florian Steffens CI settings Signed-off-by: Florian Steffens Make use of automated API doc generating - add annotations for API routed methods - refactor to ensure type safety - add psalm types and usage - correct API return codes ⚡️breaking changes ⚡️ Signed-off-by: Florian Steffens --- .github/workflows/cypress.yml | 5 +- .github/workflows/integration.yml | 9 +- .github/workflows/lint-php-cs.yml | 2 +- .github/workflows/phpunit-mysql.yml | 4 +- APIv1.yaml | 1409 ---- Makefile | 8 + appinfo/routes.php | 24 +- composer.json | 13 +- composer.lock | 1769 ++--- cypress/integration/api-v2/tables.spec.js | 0 lib/Capabilities.php | 3 + lib/Controller/AOCSController.php | 62 + lib/Controller/Api1Controller.php | 1050 ++- lib/Controller/ApiColumnsController.php | 309 + lib/Controller/ApiGeneralController.php | 61 + lib/Controller/ApiTablesController.php | 144 + lib/Controller/PageController.php | 1 + lib/Db/Column.php | 7 + lib/Db/Share.php | 7 + lib/Db/ShareMapper.php | 1 + lib/Db/Table.php | 6 + lib/Db/View.php | 7 + lib/ResponseDefinitions.php | 129 + lib/Service/ColumnService.php | 194 +- lib/Service/PermissionsService.php | 4 + lib/Service/ShareService.php | 97 +- lib/Service/TableService.php | 215 +- lib/Service/ViewService.php | 54 +- openapi.json | 6916 +++++++++++++++++ tests/integration/composer.json | 8 +- tests/integration/composer.lock | 1024 +-- .../{api/tablesapi.feature => APIv1.feature} | 13 +- tests/integration/features/APIv2.feature | 66 + .../features/bootstrap/CommandLineTrait.php | 190 - .../features/bootstrap/FeatureContext.php | 313 +- 35 files changed, 10235 insertions(+), 3889 deletions(-) delete mode 100644 APIv1.yaml create mode 100644 cypress/integration/api-v2/tables.spec.js create mode 100644 lib/Controller/AOCSController.php create mode 100644 lib/Controller/ApiColumnsController.php create mode 100644 lib/Controller/ApiGeneralController.php create mode 100644 lib/Controller/ApiTablesController.php create mode 100644 lib/ResponseDefinitions.php create mode 100644 openapi.json rename tests/integration/features/{api/tablesapi.feature => APIv1.feature} (99%) create mode 100644 tests/integration/features/APIv2.feature delete mode 100644 tests/integration/features/bootstrap/CommandLineTrait.php diff --git a/.github/workflows/cypress.yml b/.github/workflows/cypress.yml index e4d6c4bd1..f9285e948 100644 --- a/.github/workflows/cypress.yml +++ b/.github/workflows/cypress.yml @@ -25,12 +25,9 @@ jobs: matrix: node-version: [ 16 ] databases: [ 'mysql' ] - server-versions: [ 'stable25', 'master' ] + server-versions: [ 'stable25', 'stable27', 'master' ] include: - php-versions: 8.1 - - server-versions: 'stable25' - php-versions: 7.4 - services: mysql: diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index bc91e3aa0..c6bf6946c 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -26,17 +26,12 @@ jobs: strategy: fail-fast: false matrix: - server-versions: ['stable25', 'stable26', 'stable27', 'master'] + server-versions: ['stable25', 'stable27', 'master'] include: - - php-versions: '8.2' + - php-versions: '8.1' - server-versions: 'stable25' - php-versions: '7.4' databases: 'sqlite' - - server-versions: 'stable26' - php-versions: '8.1' - databases: 'mysql' - server-versions: 'stable27' - php-versions: '8.1' databases: 'mysql' - server-versions: 'master' databases: 'sqlite' diff --git a/.github/workflows/lint-php-cs.yml b/.github/workflows/lint-php-cs.yml index 140f40dc2..c0dc07df0 100644 --- a/.github/workflows/lint-php-cs.yml +++ b/.github/workflows/lint-php-cs.yml @@ -27,7 +27,7 @@ jobs: - name: Set up php uses: shivammathur/setup-php@c5fc0d8281aba02c7fda07d3a70cc5371548067d # v2 with: - php-version: 8.0 + php-version: 8.1 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 diff --git a/.github/workflows/phpunit-mysql.yml b/.github/workflows/phpunit-mysql.yml index a43720741..2d10af909 100644 --- a/.github/workflows/phpunit-mysql.yml +++ b/.github/workflows/phpunit-mysql.yml @@ -38,11 +38,9 @@ jobs: strategy: matrix: - server-versions: ['stable25', 'master'] + server-versions: ['stable25', 'stable27', 'master'] include: - php-versions: 8.1 - - server-versions: 'stable25' - php-versions: 7.4 services: mysql: diff --git a/APIv1.yaml b/APIv1.yaml deleted file mode 100644 index 10f6ac3bd..000000000 --- a/APIv1.yaml +++ /dev/null @@ -1,1409 +0,0 @@ -openapi: 3.0.3 -info: - title: Nextcloud tables API v1 - description: Nextcloud tables API v1 - version: 1.0.0 -servers: - - url: 'http://nextcloud.local/index.php/apps/tables/api/1/' -paths: - /tables: - get: - summary: Get a list of tables - description: You can filter by a keyword, limit and offset. Shipped with v0.3.0. - tags: - - Tables - operationId: listTables - security: - - basicAuth: [] - parameters: - - name: keyword - in: query - description: Term to look for - required: false - schema: - type: string - maximum: 255 - - name: limit - in: query - description: Limit the results - required: false - schema: - type: integer - - name: offset - in: query - description: Set an offset for pagination - required: false - schema: - type: integer - responses: - '200': - description: Json array with table objects - content: - application/json: - schema: - $ref: "#/components/schemas/Tables" - '401': - description: Not authorized - '403': - description: Not allowed - '404': - description: Not found - post: - summary: Create a new table - description: Shipped with v0.4.0. - tags: - - Tables - operationId: createTable - security: - - basicAuth: [] - parameters: - - name: values - in: query - description: object of key-value pairs - required: true - schema: - type: object - required: - - title - properties: - title: - type: string - required: true - emoji: - type: string - format: utf8 emoji - template: - type: string - description: set if you want to create the table definition from a template - responses: - '200': - description: Table created - content: - application/json: - schema: - $ref: "#/components/schemas/Table" - '401': - description: Not authorized - '403': - description: Not allowed - - /tables/{tableId}: - get: - summary: Get a table - description: Changed and shipped with v0.4.0. - tags: - - Tables - operationId: getTable - security: - - basicAuth: [] - parameters: - - name: tableId - in: path - description: ID for the requested table - required: true - schema: - type: integer - responses: - '200': - description: Table object - content: - application/json: - schema: - $ref: "#/components/schemas/Table" - '401': - description: Not authorized - '403': - description: Not allowed - '404': - description: Not found - put: - summary: Update a table - description: Shipped with v0.4.0. - tags: - - Tables - operationId: updateTable - security: - - basicAuth: [] - parameters: - - name: tableId - in: path - description: ID for the requested table - required: true - schema: - type: integer - - name: values - in: query - description: object of key-value pairs - required: true - schema: - type: object - properties: - title: - type: string - emoji: - type: string - format: utf8 emoji - responses: - '200': - description: Updated table object - content: - application/json: - $ref: "#/components/schemas/Table" - schema: - '401': - description: Not authorized - '403': - description: Not allowed - '404': - description: Not found - delete: - summary: Delete a table - description: Shipped with v0.4.0. - tags: - - Tables - operationId: deleteTable - security: - - basicAuth: [] - parameters: - - name: tableId - in: path - description: ID for the requested table - required: true - schema: - type: integer - responses: - '200': - description: Deleted table object - content: - application/json: - schema: - $ref: "#/components/schemas/Table" - '401': - description: Not authorized - '403': - description: Not allowed - '404': - description: Not found - - - /tables/{tableId}/columns: - get: - summary: Get a list of columns for a given table - description: Shipped with v0.4.0. - tags: - - Columns - operationId: listTableColumns - security: - - basicAuth: [] - parameters: - - name: tableId - in: path - description: Table ID - required: true - schema: - type: integer - responses: - '200': - description: Json array with column objects - content: - application/json: - schema: - $ref: "#/components/schemas/Columns" - '401': - description: Not authorized - '403': - description: Not allowed - '404': - description: Not found - post: - summary: Create a column for given table - description: Shipped with v0.4.0. - tags: - - Columns - operationId: createTableColumn - security: - - basicAuth: [] - parameters: - - name: tableId - in: path - description: ID for the table that should be shared - required: true - example: 5 - schema: - type: integer - - name: values - in: query - description: object of key-value pairs - required: true - schema: - - $ref: "#/components/schemas/columnProperties" - - type: - type: string - required: true - - subtype: - type: string - - responses: - '200': - description: Column object - content: - application/json: - schema: - $ref: "#/components/schemas/Column" - '401': - description: Not authorized - '403': - description: Not allowed - - /tables/{tableId}/views: - get: - summary: Get a list of views for a given table - description: Shipped with v0.6.0. - tags: - - Views - operationId: listTableViews - security: - - basicAuth: [] - parameters: - - name: tableId - in: path - description: Table ID - required: true - schema: - type: integer - responses: - '200': - description: Json array with view objects - content: - application/json: - schema: - $ref: "#/components/schemas/Views" - '401': - description: Not authorized - '403': - description: Not allowed - '404': - description: Not found - post: - summary: Create a view for given table - description: Shipped with v0.6.0. - tags: - - Views - operationId: createTableView - security: - - basicAuth: [] - parameters: - - name: tableId - in: path - description: Related table ID - required: true - example: 5 - schema: - type: integer - - name: title - in: query - description: Title for the view - required: true - schema: - type: string - - name: emoji - in: query - description: Emoji for the view - required: false - schema: - type: string - responses: - '200': - description: View object - content: - application/json: - schema: - $ref: "#/components/schemas/View" - '401': - description: Not authorized - '403': - description: Not allowed - - /views/{viewId}: - get: - summary: Get a view - description: Shipped with v0.6.0. - tags: - - Views - operationId: getView - security: - - basicAuth: [] - parameters: - - name: viewId - in: path - description: View ID - required: true - schema: - type: integer - responses: - '200': - description: Json view object - content: - application/json: - schema: - $ref: "#/components/schemas/View" - '401': - description: Not authorized - '403': - description: Not allowed - '404': - description: Not found - put: - summary: Update a view - description: Shipped with v0.6.0. - tags: - - Views - operationId: updateView - security: - - basicAuth: [] - parameters: - - name: viewId - in: path - description: ID for the view - required: true - schema: - type: integer - - name: values - in: query - description: object of key-value pairs as json-string - required: true - schema: - $ref: "#/components/schemas/viewProperties" - responses: - '200': - description: Updated view object - content: - application/json: - schema: - $ref: "#/components/schemas/View" - '401': - description: Not authorized - '403': - description: Not allowed - '404': - description: Not found - delete: - summary: Delete a view - description: Shipped with v0.6.0. - tags: - - Views - operationId: deleteView - security: - - basicAuth: [] - parameters: - - name: viewId - in: path - description: ID for the requested view - required: true - schema: - type: integer - responses: - '200': - description: Deleted view object - content: - application/json: - schema: - $ref: "#/components/schemas/View" - '401': - description: Not authorized - '403': - description: Not allowed - '404': - description: Not found - - /column/{columnId}: - get: - summary: Get a column - description: Shipped with v0.4.0. - tags: - - Columns - operationId: getColumn - security: - - basicAuth: [] - parameters: - - name: columnId - in: path - description: ID for the requested column - required: true - schema: - type: integer - responses: - '200': - description: Column object - content: - application/json: - schema: - $ref: "#/components/schemas/Column" - '401': - description: Not authorized - '403': - description: Not allowed - '404': - description: Not found - put: - summary: Update a column - description: Shipped with v0.4.0. - tags: - - Columns - operationId: updateColumn - security: - - basicAuth: [] - parameters: - - name: columnId - in: path - description: ID for the column - required: true - schema: - type: integer - - name: values - in: query - description: object of key-value pairs - required: true - schema: - $ref: "#/components/schemas/columnProperties" - responses: - '200': - description: Updated column object - content: - application/json: - $ref: "#/components/schemas/Column" - '401': - description: Not authorized - '403': - description: Not allowed - '404': - description: Not found - delete: - summary: Delete a column - description: Shipped with v0.4.0. - tags: - - Columns - operationId: deleteColumn - security: - - basicAuth: [] - parameters: - - name: columnId - in: path - description: ID for the requested column - required: true - schema: - type: integer - responses: - '200': - description: Deleted column object - content: - application/json: - schema: - $ref: "#/components/schemas/Column" - '401': - description: Not authorized - '403': - description: Not allowed - '404': - description: Not found - - - /tables/{tableId}/shares: - get: - summary: Get shares for a table - description: Shipped with v0.4.0. - tags: - - Sharing - operationId: listTableShares - security: - - basicAuth: [] - parameters: - - name: tableId - in: path - description: ID for the table context - required: true - schema: - type: integer - responses: - '200': - description: Share node objects - content: - application/json: - schema: - $ref: "#/components/schemas/Shares" - '401': - description: Not authorized - '403': - description: Not allowed - '404': - description: Not found - post: - summary: Share a table - description: Shipped with v0.4.0. - tags: - - Sharing - operationId: createTableShare - security: - - basicAuth: [] - parameters: - - name: tableId - in: path - description: ID for the table that should be shared - required: true - example: 5 - schema: - type: integer - - name: receiverType - in: query - description: Type of receiver ('user' or 'group') - required: true - example: 'user' - schema: - type: string - - name: receiver - in: query - description: name for receiver - required: true - example: 'Klaus' - schema: - type: string - - name: permissionRead - in: query - description: Set if sharee can read data - required: true - schema: - type: boolean - - name: permissionCreate - in: query - description: Set if sharee can create data - required: true - schema: - type: boolean - - name: permissionUpdate - in: query - description: Set if sharee can update data - required: true - schema: - type: boolean - - name: permissionDelete - in: query - description: Set if sharee can delete data - required: true - schema: - type: boolean - - name: permissionManage - in: query - description: Set if sharee can manage permissions the shared node - required: true - schema: - type: boolean - responses: - '200': - description: Share node object - content: - application/json: - schema: - $ref: "#/components/schemas/Share" - '401': - description: Not authorized - '403': - description: Not allowed - '404': - description: Not found - - /share/{shareId}: - get: - summary: Get a share node object - description: Shipped with v0.4.0. - tags: - - Sharing - operationId: getShare - security: - - basicAuth: [ ] - parameters: - - name: shareId - in: path - description: ID for the share - required: true - example: 5 - schema: - type: integer - responses: - '200': - description: Share node object - content: - application/json: - schema: - $ref: "#/components/schemas/Share" - '401': - description: Not authorized - '403': - description: Not allowed - '404': - description: Not found - put: - summary: Update permission - description: Shipped with v0.4.0. - tags: - - Sharing - operationId: updateSharePermission - security: - - basicAuth: [ ] - parameters: - - name: shareId - in: path - description: Share ID - required: true - example: 5 - schema: - type: integer - - name: permissionType - in: query - description: Permission type (read, create, update, delete, manage) - required: true - schema: - type: string - - name: permissionValue - in: query - description: Value for the permission type - required: true - schema: - type: boolean - responses: - '200': - description: Share node object - content: - application/json: - schema: - $ref: "#/components/schemas/Share" - '401': - description: Not authorized - '403': - description: Not allowed - '404': - description: Not found - delete: - summary: Unshare - description: Shipped with v0.4.0. - tags: - - Sharing - operationId: deleteShare - security: - - basicAuth: [ ] - parameters: - - name: shareId - in: path - description: ID for the share - required: true - schema: - type: integer - responses: - '200': - description: Deleted share node object - content: - application/json: - schema: - $ref: "#/components/schemas/Share" - '401': - description: Not authorized - '403': - description: Not allowed - '404': - description: Not found - - - /tables/{tableId}/rows/simple: - get: - summary: Get an array of row values with header row - description: The first row contains the column titles. There is a default row limit by 1000 rows. If you need more (or want to limit less), you can set a limit on your own. Additionally set an offset if needed, would be good for lazy loading etc. Shipped with v0.3.0. - tags: - - Rows - operationId: listRowsSimple - security: - - basicAuth: [] - parameters: - - name: tableId - in: path - description: Table ID - required: true - schema: - type: integer - - name: limit - in: query - description: Limit the rows - required: false - schema: - type: integer - - name: offset - in: query - description: Set the startng pointer - required: false - schema: - type: integer - responses: - '200': - description: Json array with row values - '401': - description: Not authorized - '403': - description: Not allowed - '404': - description: Not found - - /tables/{tableId}/rows: - get: - summary: Get an array of rows - description: There is a default row limit by 1000 rows. If you need more (or want to limit less), you can set a limit on your own. Additionally set an offset if needed, would be good for lazy loading etc. Shipped with v0.4.0. - tags: - - Rows - operationId: listRows - security: - - basicAuth: [] - parameters: - - name: tableId - in: path - description: Table ID - required: true - schema: - type: integer - - name: limit - in: query - description: Limit the rows - required: false - schema: - type: integer - - name: offset - in: query - description: Set the startng pointer - required: false - schema: - type: integer - responses: - '200': - description: Json array with row objects - content: - application/json: - schema: - $ref: "#/components/schemas/Rows" - '401': - description: Not authorized - '403': - description: Not allowed - '404': - description: Not found - post: - summary: Create a row - description: Shipped with v0.4.0. - tags: - - Rows - operationId: createRow - security: - - basicAuth: [] - parameters: - - name: tableId - in: path - description: ID for the table - required: true - schema: - type: integer - - name: data - in: query - description: json object with key-value pairs, keys are the columnIds - required: true - schema: - type: string - responses: - '200': - description: Row object - content: - application/json: - schema: - $ref: "#/components/schemas/Row" - '401': - description: Not authorized - '403': - description: Not allowed - '404': - description: Not found - - /rows/{rowId}: - get: - summary: Get row - description: Shipped with v0.4.0 - tags: - - Rows - operationId: getRow - security: - - basicAuth: [] - parameters: - - name: rowId - in: path - description: Row ID - required: true - schema: - type: integer - responses: - '200': - description: Row object - content: - application/json: - schema: - $ref: "#/components/schemas/Row" - '401': - description: Not authorized - '403': - description: Not allowed - '404': - description: Not found - put: - summary: Update row - description: Shipped with v0.4.0. - tags: - - Rows - operationId: updateRow - security: - - basicAuth: [ ] - parameters: - - name: rowId - in: path - description: Row ID - required: true - schema: - type: integer - - name: values - in: query - description: object of key-value pairs, keys are the columnIds - required: true - schema: - type: object - responses: - '200': - description: Row object - content: - application/json: - schema: - $ref: "#/components/schemas/Row" - '401': - description: Not authorized - '403': - description: Not allowed - '404': - description: Not found - delete: - summary: Delete row - description: Shipped with v0.4.0. - tags: - - Rows - operationId: deleteRow - security: - - basicAuth: [ ] - parameters: - - name: rowId - in: path - description: ID for the row - required: true - schema: - type: integer - responses: - '200': - description: Deleted row object - content: - application/json: - schema: - $ref: "#/components/schemas/Row" - '401': - description: Not authorized - '403': - description: Not allowed - '404': - description: Not found - - /import/table/{tableId}: - post: - summary: Import from file - description: Shipped with v0.5.0. File has to be stored in nextcloud for given user. - tags: - - Import - operationId: importRows - security: - - basicAuth: [] - parameters: - - name: tableId - in: path - description: ID for the table - required: true - schema: - type: integer - - name: path - in: query - description: Path is relative to the root of the user context. Begin with a / for the root folder. - required: true - schema: - type: string - - name: createMissingColumns - in: query - description: Set to 1 if missing columns should be created. (Column type will be text-line.) - required: false - schema: - type: boolean - responses: - '200': - description: Statistic information - content: - application/json: - schema: - type: object - properties: - found columns: - type: integer - created columns: - type: integer - inserted rows: - type: integer - errors (see logs): - type: integer - - '401': - description: Not authorized - '403': - description: Not allowed - '404': - description: Not found - - -components: - securitySchemes: - basicAuth: - type: http - scheme: basic - schemas: - Tables: - type: array - maxItems: 1000 - items: - $ref: "#/components/schemas/Table" - Table: - type: object - required: - - id - - title - properties: - id: - type: integer - format: int64 - title: - type: string - nullable: false - emoji: - type: string - nullable: true - ownership: - type: string - ownerDisplayName: - type: string - createdBy: - type: string - createdAt: - type: string - nullable: false - pattern: "^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}$" - lastEditBy: - type: string - lastEditAt: - type: string - nullable: false - pattern: "^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}$" - isShared: - type: boolean - nullable: false - description: "Whether the table is shared with the requesting user" - hasShares: - type: boolean - nullable: false - description: "Whether the table is shared with ANY user" - onSharePermissions: - type: object - properties: - read: - type: boolean - create: - type: boolean - update: - type: boolean - delete: - type: boolean - manage: - type: boolean - rowsCount: - type: integer - nullable: false - columnsCount: - type: integer - nullable: false - views: - type: array - Shares: - type: array - maxItems: 1000 - items: - $ref: "#/components/schemas/Share" - Share: - type: object - required: - - id - - nodeId - - nodeType - properties: - id: - type: integer - nullable: false - nodeId: - type: integer - nullable: false - nodeType: - type: string - nullable: false - permissionRead: - type: boolean - nullable: false - permissionCreate: - type: boolean - nullable: false - permissionUpdate: - type: boolean - nullable: false - permissionDelete: - type: boolean - nullable: false - permissionManage: - type: boolean - nullable: false - sender: - type: string - receiver: - type: string - nullable: false - receiverDisplayName: - type: string - receiverType: - type: string - nullable: false - pattern: "^(user)|(group)$" - createdAt: - type: string - nullable: false - pattern: "^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}$" - lastEditAt: - type: string - nullable: false - pattern: "^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}$" - Columns: - type: array - maxItems: 1000 - items: - $ref: "#/components/schemas/Column" - Column: - type: object - required: - - id - - title - - tableId - - mandatory - - type - properties: - id: - type: integer - nullable: false - title: - type: string - nullable: false - tableId: - type: integer - nullable: false - createdBy: - type: string - createdAt: - type: string - nullable: false - pattern: "^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}$" - lastEditBy: - type: string - lastEditAt: - type: string - nullable: false - pattern: "^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}$" - type: - type: string - nullable: false - subtype: - type: string - nullable: false - description: "subtype or an empty string" - mandatory: - type: boolean - nullable: false - description: - type: string - orderWeight: - type: integer - description: "Deprecated" - numberDefault: - type: number - numberMin: - type: number - numberMax: - type: number - numberDecimals: - type: integer - numberPrefix: - type: string - nullable: false - description: "prefix or an empty string" - numberSuffix: - type: string - nullable: false - description: "suffix or an empty string" - textDefault: - type: string - textAllowedPattern: - type: string - textMaxLength: - type: integer - selectionOptions: - type: string - nullable: false - selectionDefault: - type: integer - datetimeDefault: - type: string - Views: - type: array - maxItems: 1000 - items: - $ref: "#/components/schemas/View" - View: - type: object - required: - - id - - title - - tableId - - ownership - properties: - id: - type: integer - nullable: false - title: - type: string - nullable: false - tableId: - type: integer - nullable: false - createdBy: - type: string - nullable: true - createdAt: - type: string - nullable: false - pattern: "^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}$" - lastEditBy: - type: string - nullable: true - lastEditAt: - type: string - nullable: false - pattern: "^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}$" - description: - type: string - nullable: false - emoji: - type: string - nullable: true - columns: - type: array - items: - type: integer - sort: - $ref: "#/components/schemas/Sorting" - isShared: - type: boolean - onSharePermissions: - type: object - properties: - read: - type: boolean - create: - type: boolean - update: - type: boolean - delete: - type: boolean - manage: - type: boolean - hasShares: - type: boolean - nullable: false - rowsCount: - type: integer - nullable: false - ownerDisplayName: - type: string - filter: - $ref: "#/components/schemas/Filters" - Filters: - type: array - maxItems: 1000 - items: - $ref: "#/components/schemas/FilterGroups" - FilterGroups: - type: array - description: Definition of filter groups that are combined with logical OR. - maxItems: 1000 - items: - $ref: "#/components/schemas/Filter" - Filter: - type: object - description: Definition of filter that are combined with logical AND. - required: - - columnId - - operator - - value - properties: - columnId: - type: integer - operator: - type: string - enum: - - contains - - begins-with - - ends-with - - is-equal - - is-greater-than - - is-greater-than-or-equal - - is-lower-than - - is-lower-than-or-equal - - is-empty - value: - type: string - RowsSimple: - type: array - maxItems: 1000 - items: - $ref: "#/components/schemas/RowSimple" - RowSimple: - type: array - description: Values depending on the table definition. - items: {} - Rows: - type: array - maxItems: 1000 - items: - $ref: "#/components/schemas/Row" - Row: - type: object - description: Object with row metadata. The values are inside of the property 'data'. - required: - - id - - tableId - properties: - id: - type: integer - nullable: false - tableId: - type: integer - nullable: false - createdBy: - type: string - nullable: false - createdAt: - type: string - nullable: false - pattern: "^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}$" - lastEditBy: - type: string - nullable: false - lastEditAt: - type: string - nullable: false - pattern: "^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}$" - data: - type: array - nullable: false - items: - type: object - properties: - columnId: - type: integer - value: - type: string - columnProperties: - type: object - properties: - title: - type: string - required: true - mandatory: - type: boolean - required: true - numberPrefix: - type: string - numberSuffix: - type: string - description: - type: string - textDefault: - type: string - textAllowedPattern: - type: string - textMaxLength: - type: integer - numberDefault: - type: number - numberMin: - type: number - numberMax: - type: number - numberDecimals: - type: integer - selectionOptions: - type: string - selectionDefault: - type: integer - orderWeight: - type: integer - datetimeDefault: - type: string - viewProperties: - type: object - properties: - title: - type: string - required: true - emoji: - type: boolean - required: true - description: - type: string - columns: - type: array - items: - type: integer - sort: - $ref: "#/components/schemas/Sorting" - filter: - $ref: "#/components/schemas/Filters" - Sorting: - type: array - maxItems: 1000 - items: - $ref: "#/components/schemas/Sort" - Sort: - type: object - description: Object with sorting definition - properties: - columnId: - type: integer - mode: - type: string - enum: - - ASC - - DESC diff --git a/Makefile b/Makefile index 460a63a1b..a800b7610 100644 --- a/Makefile +++ b/Makefile @@ -151,3 +151,11 @@ clean: clean-dev: rm -rf node_modules rm -rf vendor + +###### API generation + +api: + composer exec generate-spec + +api-fast: + composer exec generate-spec -- --allow-missing-docs --continue-on-error diff --git a/appinfo/routes.php b/appinfo/routes.php index 4c21e7784..2a09cd157 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -3,15 +3,17 @@ return [ 'routes' => [ - // enable CORS for api calls (API version 1) + // enable CORS for api calls ['name' => 'api1#preflighted_cors', 'url' => '/api/1/{path}', 'verb' => 'OPTIONS', 'requirements' => ['path' => '.+']], + ['name' => 'api2#preflighted_cors', 'url' => '/api/2/{path}', + 'verb' => 'OPTIONS', 'requirements' => ['path' => '.+']], ['name' => 'page#index', 'url' => '/', 'verb' => 'GET'], ['name' => 'tableTemplate#list', 'url' => '/table/templates', 'verb' => 'GET'], - // API + // API v1 // -> tables ['name' => 'api1#index', 'url' => '/api/1/tables', 'verb' => 'GET'], ['name' => 'api1#createTable', 'url' => '/api/1/tables', 'verb' => 'POST'], @@ -55,7 +57,6 @@ ['name' => 'api1#importInTable', 'url' => '/api/1/import/table/{tableId}', 'verb' => 'POST'], ['name' => 'api1#importInView', 'url' => '/api/1/import/views/{viewId}', 'verb' => 'POST'], - // table ['name' => 'table#index', 'url' => '/table', 'verb' => 'GET'], ['name' => 'table#show', 'url' => '/table/{id}', 'verb' => 'GET'], @@ -104,5 +105,22 @@ // search ['name' => 'search#all', 'url' => '/search/all', 'verb' => 'GET'], + ], + 'ocs' => [ + // API v2 + ['name' => 'ApiGeneral#index', 'url' => '/api/2/init', 'verb' => 'GET'], + // -> tables + ['name' => 'ApiTables#index', 'url' => '/api/2/tables', 'verb' => 'GET'], + ['name' => 'ApiTables#show', 'url' => '/api/2/tables/{id}', 'verb' => 'GET'], + ['name' => 'ApiTables#create', 'url' => '/api/2/tables', 'verb' => 'POST'], + ['name' => 'ApiTables#update', 'url' => '/api/2/tables/{id}', 'verb' => 'PUT'], + ['name' => 'ApiTables#destroy', 'url' => '/api/2/tables/{id}', 'verb' => 'DELETE'], + + ['name' => 'ApiColumns#index', 'url' => '/api/2/columns/{nodeType}/{nodeId}', 'verb' => 'GET'], + ['name' => 'ApiColumns#show', 'url' => '/api/2/columns/{id}', 'verb' => 'GET'], + ['name' => 'ApiColumns#createNumberColumn', 'url' => '/api/2/columns/number', 'verb' => 'POST'], + ['name' => 'ApiColumns#createTextColumn', 'url' => '/api/2/columns/text', 'verb' => 'POST'], + ['name' => 'ApiColumns#createSelectionColumn', 'url' => '/api/2/columns/selection', 'verb' => 'POST'], + ['name' => 'ApiColumns#createDatetimeColumn', 'url' => '/api/2/columns/datetime', 'verb' => 'POST'], ] ]; diff --git a/composer.json b/composer.json index 5765ee0f0..111c8c3a4 100644 --- a/composer.json +++ b/composer.json @@ -9,19 +9,26 @@ "email": "florian@nextcloud.com" } ], - "require-dev": { + "repositories": [ + { + "type": "vcs", + "url": "https://github.com/nextcloud/openapi-extractor" + } + ], + "require-dev": { "nextcloud/coding-standard": "^v1.0.0", "vimeo/psalm": "^5.6.0", "nextcloud/ocp": "dev-master", "phan/phan": "5.x", "staabm/annotate-pull-request-from-checkstyle": "^1.8", - "phpunit/phpunit": "^9" + "phpunit/phpunit": "^9", + "nextcloud/openapi-extractor": "dev-main" }, "config": { "optimize-autoloader": true, "classmap-authoritative": true, "platform": { - "php": "7.4" + "php": "8.1" } }, "scripts": { diff --git a/composer.lock b/composer.lock index 6ad147b83..203077ede 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "31f97082e55f7861568fe4e5c3b70827", + "content-hash": "39aa65c0c406f05534af3c1dc4b18d23", "packages": [ { "name": "ezyang/htmlpurifier", @@ -69,32 +69,35 @@ }, { "name": "maennchen/zipstream-php", - "version": "2.2.6", + "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/maennchen/ZipStream-PHP.git", - "reference": "30ad6f93cf3efe4192bc7a4c9cad11ff8f4f237f" + "reference": "b8174494eda667f7d13876b4a7bfef0f62a7c0d1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/30ad6f93cf3efe4192bc7a4c9cad11ff8f4f237f", - "reference": "30ad6f93cf3efe4192bc7a4c9cad11ff8f4f237f", + "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/b8174494eda667f7d13876b4a7bfef0f62a7c0d1", + "reference": "b8174494eda667f7d13876b4a7bfef0f62a7c0d1", "shasum": "" }, "require": { - "myclabs/php-enum": "^1.5", - "php": "^7.4 || ^8.0", - "psr/http-message": "^1.0", - "symfony/polyfill-mbstring": "^1.0" + "ext-mbstring": "*", + "ext-zlib": "*", + "php-64bit": "^8.1" }, "require-dev": { "ext-zip": "*", - "friendsofphp/php-cs-fixer": "^3.9", - "guzzlehttp/guzzle": "^6.5.3 || ^7.2.0", + "friendsofphp/php-cs-fixer": "^3.16", + "guzzlehttp/guzzle": "^7.5", "mikey179/vfsstream": "^1.6", - "php-coveralls/php-coveralls": "^2.4", - "phpunit/phpunit": "^8.5.8 || ^9.4.2", - "vimeo/psalm": "^4.1" + "php-coveralls/php-coveralls": "^2.5", + "phpunit/phpunit": "^10.0", + "vimeo/psalm": "^5.0" + }, + "suggest": { + "guzzlehttp/psr7": "^2.4", + "psr/http-message": "^2.0" }, "type": "library", "autoload": { @@ -131,7 +134,7 @@ ], "support": { "issues": "https://github.com/maennchen/ZipStream-PHP/issues", - "source": "https://github.com/maennchen/ZipStream-PHP/tree/2.2.6" + "source": "https://github.com/maennchen/ZipStream-PHP/tree/3.1.0" }, "funding": [ { @@ -143,7 +146,7 @@ "type": "open_collective" } ], - "time": "2022-11-25T18:57:19+00:00" + "time": "2023-06-21T14:59:35+00:00" }, { "name": "markbaker/complex", @@ -252,81 +255,18 @@ }, "time": "2022-12-02T22:17:43+00:00" }, - { - "name": "myclabs/php-enum", - "version": "1.8.4", - "source": { - "type": "git", - "url": "https://github.com/myclabs/php-enum.git", - "reference": "a867478eae49c9f59ece437ae7f9506bfaa27483" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/myclabs/php-enum/zipball/a867478eae49c9f59ece437ae7f9506bfaa27483", - "reference": "a867478eae49c9f59ece437ae7f9506bfaa27483", - "shasum": "" - }, - "require": { - "ext-json": "*", - "php": "^7.3 || ^8.0" - }, - "require-dev": { - "phpunit/phpunit": "^9.5", - "squizlabs/php_codesniffer": "1.*", - "vimeo/psalm": "^4.6.2" - }, - "type": "library", - "autoload": { - "psr-4": { - "MyCLabs\\Enum\\": "src/" - }, - "classmap": [ - "stubs/Stringable.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP Enum contributors", - "homepage": "https://github.com/myclabs/php-enum/graphs/contributors" - } - ], - "description": "PHP Enum implementation", - "homepage": "http://github.com/myclabs/php-enum", - "keywords": [ - "enum" - ], - "support": { - "issues": "https://github.com/myclabs/php-enum/issues", - "source": "https://github.com/myclabs/php-enum/tree/1.8.4" - }, - "funding": [ - { - "url": "https://github.com/mnapoli", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/myclabs/php-enum", - "type": "tidelift" - } - ], - "time": "2022-08-04T09:53:51+00:00" - }, { "name": "phpoffice/phpspreadsheet", - "version": "1.28.0", + "version": "1.29.0", "source": { "type": "git", "url": "https://github.com/PHPOffice/PhpSpreadsheet.git", - "reference": "6e81cf39bbd93ebc3a4e8150444c41e8aa9b769a" + "reference": "fde2ccf55eaef7e86021ff1acce26479160a0fa0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/6e81cf39bbd93ebc3a4e8150444c41e8aa9b769a", - "reference": "6e81cf39bbd93ebc3a4e8150444c41e8aa9b769a", + "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/fde2ccf55eaef7e86021ff1acce26479160a0fa0", + "reference": "fde2ccf55eaef7e86021ff1acce26479160a0fa0", "shasum": "" }, "require": { @@ -344,7 +284,7 @@ "ext-zip": "*", "ext-zlib": "*", "ezyang/htmlpurifier": "^4.15", - "maennchen/zipstream-php": "^2.1", + "maennchen/zipstream-php": "^2.1 || ^3.0", "markbaker/complex": "^3.0", "markbaker/matrix": "^3.0", "php": "^7.4 || ^8.0", @@ -356,12 +296,12 @@ "dealerdirect/phpcodesniffer-composer-installer": "dev-main", "dompdf/dompdf": "^1.0 || ^2.0", "friendsofphp/php-cs-fixer": "^3.2", - "mitoteam/jpgraph": "^10.2.4", + "mitoteam/jpgraph": "^10.3", "mpdf/mpdf": "^8.1.1", "phpcompatibility/php-compatibility": "^9.3", "phpstan/phpstan": "^1.1", "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^8.5 || ^9.0", + "phpunit/phpunit": "^8.5 || ^9.0 || ^10.0", "squizlabs/php_codesniffer": "^3.7", "tecnickcom/tcpdf": "^6.5" }, @@ -416,22 +356,22 @@ ], "support": { "issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues", - "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.28.0" + "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.29.0" }, - "time": "2023-02-25T12:24:49+00:00" + "time": "2023-06-14T22:48:31+00:00" }, { "name": "psr/http-client", - "version": "1.0.2", + "version": "1.0.3", "source": { "type": "git", "url": "https://github.com/php-fig/http-client.git", - "reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31" + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-client/zipball/0955afe48220520692d2d09f7ab7e0f93ffd6a31", - "reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", "shasum": "" }, "require": { @@ -468,9 +408,9 @@ "psr-18" ], "support": { - "source": "https://github.com/php-fig/http-client/tree/1.0.2" + "source": "https://github.com/php-fig/http-client" }, - "time": "2023-04-10T20:12:12+00:00" + "time": "2023-09-23T14:17:50+00:00" }, { "name": "psr/http-factory", @@ -529,16 +469,16 @@ }, { "name": "psr/http-message", - "version": "1.1", + "version": "2.0", "source": { "type": "git", "url": "https://github.com/php-fig/http-message.git", - "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba" + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba", - "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", "shasum": "" }, "require": { @@ -547,7 +487,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -562,7 +502,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interface for HTTP messages", @@ -576,31 +516,31 @@ "response" ], "support": { - "source": "https://github.com/php-fig/http-message/tree/1.1" + "source": "https://github.com/php-fig/http-message/tree/2.0" }, - "time": "2023-04-04T09:50:52+00:00" + "time": "2023-04-04T09:54:51+00:00" }, { "name": "psr/simple-cache", - "version": "1.0.1", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/php-fig/simple-cache.git", - "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", - "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=8.0.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "3.0.x-dev" } }, "autoload": { @@ -615,7 +555,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interfaces for simple caching", @@ -627,49 +567,36 @@ "simple-cache" ], "support": { - "source": "https://github.com/php-fig/simple-cache/tree/master" + "source": "https://github.com/php-fig/simple-cache/tree/3.0.0" }, - "time": "2017-10-23T01:57:42+00:00" - }, + "time": "2021-10-29T13:26:27+00:00" + } + ], + "packages-dev": [ { - "name": "symfony/polyfill-mbstring", - "version": "v1.27.0", + "name": "adhocore/cli", + "version": "v1.6.1", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534" + "url": "https://github.com/adhocore/php-cli.git", + "reference": "25b5a93e5eebcdb70e20ee33313a011ea3a4f770" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534", - "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "url": "https://api.github.com/repos/adhocore/php-cli/zipball/25b5a93e5eebcdb70e20ee33313a011ea3a4f770", + "reference": "25b5a93e5eebcdb70e20ee33313a011ea3a4f770", "shasum": "" }, "require": { - "php": ">=7.1" - }, - "provide": { - "ext-mbstring": "*" + "php": ">=8.0" }, - "suggest": { - "ext-mbstring": "For best performance" + "require-dev": { + "phpunit/phpunit": "^9.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, "autoload": { - "files": [ - "bootstrap.php" - ], "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" + "Ahc\\Cli\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -678,44 +605,44 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Jitendra Adhikari", + "email": "jiten.adhikary@gmail.com" } ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", + "description": "Command line interface library for PHP", "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" + "argument-parser", + "argv-parser", + "cli", + "cli-action", + "cli-app", + "cli-color", + "cli-option", + "cli-writer", + "command", + "console", + "console-app", + "php-cli", + "php8", + "stream-input", + "stream-output" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0" + "issues": "https://github.com/adhocore/php-cli/issues", + "source": "https://github.com/adhocore/php-cli/tree/v1.6.1" }, "funding": [ { - "url": "https://symfony.com/sponsor", + "url": "https://paypal.me/ji10", "type": "custom" }, { - "url": "https://github.com/fabpot", + "url": "https://github.com/adhocore", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" - } - ], - "packages-dev": [ + "time": "2023-06-26T09:55:29+00:00" + }, { "name": "amphp/amp", "version": "v2.6.2", @@ -884,16 +811,16 @@ }, { "name": "composer/pcre", - "version": "3.1.0", + "version": "3.1.1", "source": { "type": "git", "url": "https://github.com/composer/pcre.git", - "reference": "4bff79ddd77851fe3cdd11616ed3f92841ba5bd2" + "reference": "00104306927c7a0919b4ced2aaa6782c1e61a3c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/4bff79ddd77851fe3cdd11616ed3f92841ba5bd2", - "reference": "4bff79ddd77851fe3cdd11616ed3f92841ba5bd2", + "url": "https://api.github.com/repos/composer/pcre/zipball/00104306927c7a0919b4ced2aaa6782c1e61a3c9", + "reference": "00104306927c7a0919b4ced2aaa6782c1e61a3c9", "shasum": "" }, "require": { @@ -935,7 +862,7 @@ ], "support": { "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/3.1.0" + "source": "https://github.com/composer/pcre/tree/3.1.1" }, "funding": [ { @@ -951,20 +878,20 @@ "type": "tidelift" } ], - "time": "2022-11-17T09:50:14+00:00" + "time": "2023-10-11T07:11:09+00:00" }, { "name": "composer/semver", - "version": "3.3.2", + "version": "3.4.0", "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9" + "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/3953f23262f2bff1919fc82183ad9acb13ff62c9", - "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9", + "url": "https://api.github.com/repos/composer/semver/zipball/35e8d0af4486141bc745f23a29cc2091eb624a32", + "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32", "shasum": "" }, "require": { @@ -1014,9 +941,9 @@ "versioning" ], "support": { - "irc": "irc://irc.freenode.org/composer", + "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.3.2" + "source": "https://github.com/composer/semver/tree/3.4.0" }, "funding": [ { @@ -1032,7 +959,7 @@ "type": "tidelift" } ], - "time": "2022-04-01T19:23:25+00:00" + "time": "2023-08-31T09:50:34+00:00" }, { "name": "composer/xdebug-handler", @@ -1137,103 +1064,31 @@ }, "time": "2019-12-04T15:06:13+00:00" }, - { - "name": "doctrine/annotations", - "version": "2.0.1", - "source": { - "type": "git", - "url": "https://github.com/doctrine/annotations.git", - "reference": "e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f", - "reference": "e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f", - "shasum": "" - }, - "require": { - "doctrine/lexer": "^2 || ^3", - "ext-tokenizer": "*", - "php": "^7.2 || ^8.0", - "psr/cache": "^1 || ^2 || ^3" - }, - "require-dev": { - "doctrine/cache": "^2.0", - "doctrine/coding-standard": "^10", - "phpstan/phpstan": "^1.8.0", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "symfony/cache": "^5.4 || ^6", - "vimeo/psalm": "^4.10" - }, - "suggest": { - "php": "PHP 8.0 or higher comes with attributes, a native replacement for annotations" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Docblock Annotations Parser", - "homepage": "https://www.doctrine-project.org/projects/annotations.html", - "keywords": [ - "annotations", - "docblock", - "parser" - ], - "support": { - "issues": "https://github.com/doctrine/annotations/issues", - "source": "https://github.com/doctrine/annotations/tree/2.0.1" - }, - "time": "2023-02-02T22:02:53+00:00" - }, { "name": "doctrine/deprecations", - "version": "v1.0.0", + "version": "1.1.2", "source": { "type": "git", "url": "https://github.com/doctrine/deprecations.git", - "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de" + "reference": "4f2d4f2836e7ec4e7a8625e75c6aa916004db931" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de", - "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/4f2d4f2836e7ec4e7a8625e75c6aa916004db931", + "reference": "4f2d4f2836e7ec4e7a8625e75c6aa916004db931", "shasum": "" }, "require": { - "php": "^7.1|^8.0" + "php": "^7.1 || ^8.0" }, "require-dev": { "doctrine/coding-standard": "^9", - "phpunit/phpunit": "^7.5|^8.5|^9.5", - "psr/log": "^1|^2|^3" + "phpstan/phpstan": "1.4.10 || 1.10.15", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "0.18.4", + "psr/log": "^1 || ^2 || ^3", + "vimeo/psalm": "4.30.0 || 5.12.0" }, "suggest": { "psr/log": "Allows logging deprecations via PSR-3 logger implementation" @@ -1252,36 +1107,36 @@ "homepage": "https://www.doctrine-project.org/", "support": { "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/v1.0.0" + "source": "https://github.com/doctrine/deprecations/tree/1.1.2" }, - "time": "2022-05-02T15:47:09+00:00" + "time": "2023-09-27T20:04:15+00:00" }, { "name": "doctrine/instantiator", - "version": "1.5.0", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", - "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "php": "^8.1" }, "require-dev": { - "doctrine/coding-standard": "^9 || ^11", + "doctrine/coding-standard": "^11", "ext-pdo": "*", "ext-phar": "*", - "phpbench/phpbench": "^0.16 || ^1", - "phpstan/phpstan": "^1.4", - "phpstan/phpstan-phpunit": "^1", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.30 || ^5.4" + "phpbench/phpbench": "^1.2", + "phpstan/phpstan": "^1.9.4", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.5.27", + "vimeo/psalm": "^5.4" }, "type": "library", "autoload": { @@ -1308,7 +1163,7 @@ ], "support": { "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.5.0" + "source": "https://github.com/doctrine/instantiator/tree/2.0.0" }, "funding": [ { @@ -1324,85 +1179,7 @@ "type": "tidelift" } ], - "time": "2022-12-30T00:15:36+00:00" - }, - { - "name": "doctrine/lexer", - "version": "2.1.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/lexer.git", - "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", - "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", - "shasum": "" - }, - "require": { - "doctrine/deprecations": "^1.0", - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^9 || ^10", - "phpstan/phpstan": "^1.3", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "psalm/plugin-phpunit": "^0.18.3", - "vimeo/psalm": "^4.11 || ^5.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Lexer\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", - "homepage": "https://www.doctrine-project.org/projects/lexer.html", - "keywords": [ - "annotations", - "docblock", - "lexer", - "parser", - "php" - ], - "support": { - "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/2.1.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", - "type": "tidelift" - } - ], - "time": "2022-12-14T08:49:07+00:00" + "time": "2022-12-30T00:23:10+00:00" }, { "name": "felixfbecker/advanced-json-rpc", @@ -1567,66 +1344,31 @@ "time": "2022-12-24T12:35:10+00:00" }, { - "name": "friendsofphp/php-cs-fixer", - "version": "v3.16.0", + "name": "microsoft/tolerant-php-parser", + "version": "v0.1.2", "source": { "type": "git", - "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "d40f9436e1c448d309fa995ab9c14c5c7a96f2dc" + "url": "https://github.com/microsoft/tolerant-php-parser.git", + "reference": "3eccfd273323aaf69513e2f1c888393f5947804b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/d40f9436e1c448d309fa995ab9c14c5c7a96f2dc", - "reference": "d40f9436e1c448d309fa995ab9c14c5c7a96f2dc", + "url": "https://api.github.com/repos/microsoft/tolerant-php-parser/zipball/3eccfd273323aaf69513e2f1c888393f5947804b", + "reference": "3eccfd273323aaf69513e2f1c888393f5947804b", "shasum": "" }, "require": { - "composer/semver": "^3.3", - "composer/xdebug-handler": "^3.0.3", - "doctrine/annotations": "^2", - "doctrine/lexer": "^2 || ^3", - "ext-json": "*", - "ext-tokenizer": "*", - "php": "^7.4 || ^8.0", - "sebastian/diff": "^4.0 || ^5.0", - "symfony/console": "^5.4 || ^6.0", - "symfony/event-dispatcher": "^5.4 || ^6.0", - "symfony/filesystem": "^5.4 || ^6.0", - "symfony/finder": "^5.4 || ^6.0", - "symfony/options-resolver": "^5.4 || ^6.0", - "symfony/polyfill-mbstring": "^1.27", - "symfony/polyfill-php80": "^1.27", - "symfony/polyfill-php81": "^1.27", - "symfony/process": "^5.4 || ^6.0", - "symfony/stopwatch": "^5.4 || ^6.0" + "php": ">=7.2" }, "require-dev": { - "justinrainbow/json-schema": "^5.2", - "keradus/cli-executor": "^2.0", - "mikey179/vfsstream": "^1.6.11", - "php-coveralls/php-coveralls": "^2.5.3", - "php-cs-fixer/accessible-object": "^1.1", - "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.2", - "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.2.1", - "phpspec/prophecy": "^1.16", - "phpspec/prophecy-phpunit": "^2.0", - "phpunit/phpunit": "^9.5", - "phpunitgoodpractices/polyfill": "^1.6", - "phpunitgoodpractices/traits": "^1.9.2", - "symfony/phpunit-bridge": "^6.2.3", - "symfony/yaml": "^5.4 || ^6.0" - }, - "suggest": { - "ext-dom": "For handling output formats in XML", - "ext-mbstring": "For handling non-UTF8 characters." + "phpunit/phpunit": "^8.5.15" }, - "bin": [ - "php-cs-fixer" - ], - "type": "application", + "type": "library", "autoload": { "psr-4": { - "PhpCsFixer\\": "src/" + "Microsoft\\PhpParser\\": [ + "src/" + ] } }, "notification-url": "https://packagist.org/downloads/", @@ -1635,75 +1377,14 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Dariusz Rumiński", - "email": "dariusz.ruminski@gmail.com" + "name": "Rob Lourens", + "email": "roblou@microsoft.com" } ], - "description": "A tool to automatically fix PHP code style", - "keywords": [ - "Static code analysis", - "fixer", - "standards", - "static analysis" - ], + "description": "Tolerant PHP-to-AST parser designed for IDE usage scenarios", "support": { - "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.16.0" - }, - "funding": [ - { - "url": "https://github.com/keradus", - "type": "github" - } - ], - "time": "2023-04-02T19:30:06+00:00" - }, - { - "name": "microsoft/tolerant-php-parser", - "version": "v0.1.2", - "source": { - "type": "git", - "url": "https://github.com/microsoft/tolerant-php-parser.git", - "reference": "3eccfd273323aaf69513e2f1c888393f5947804b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/microsoft/tolerant-php-parser/zipball/3eccfd273323aaf69513e2f1c888393f5947804b", - "reference": "3eccfd273323aaf69513e2f1c888393f5947804b", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "require-dev": { - "phpunit/phpunit": "^8.5.15" - }, - "type": "library", - "autoload": { - "psr-4": { - "Microsoft\\PhpParser\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Rob Lourens", - "email": "roblou@microsoft.com" - } - ], - "description": "Tolerant PHP-to-AST parser designed for IDE usage scenarios", - "support": { - "issues": "https://github.com/microsoft/tolerant-php-parser/issues", - "source": "https://github.com/microsoft/tolerant-php-parser/tree/v0.1.2" + "issues": "https://github.com/microsoft/tolerant-php-parser/issues", + "source": "https://github.com/microsoft/tolerant-php-parser/tree/v0.1.2" }, "time": "2022-10-05T17:30:19+00:00" }, @@ -1819,21 +1500,21 @@ }, { "name": "nextcloud/coding-standard", - "version": "v1.1.0", + "version": "v1.1.1", "source": { "type": "git", "url": "https://github.com/nextcloud/coding-standard.git", - "reference": "20efa30db5240a5f078e03b04c685735a89dfc9e" + "reference": "55def702fb9a37a219511e1d8c6fe8e37164c1fb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nextcloud/coding-standard/zipball/20efa30db5240a5f078e03b04c685735a89dfc9e", - "reference": "20efa30db5240a5f078e03b04c685735a89dfc9e", + "url": "https://api.github.com/repos/nextcloud/coding-standard/zipball/55def702fb9a37a219511e1d8c6fe8e37164c1fb", + "reference": "55def702fb9a37a219511e1d8c6fe8e37164c1fb", "shasum": "" }, "require": { - "friendsofphp/php-cs-fixer": "^3.9", - "php": "^7.3|^8.0" + "php": "^7.3|^8.0", + "php-cs-fixer/shim": "^3.17" }, "type": "library", "autoload": { @@ -1854,9 +1535,9 @@ "description": "Nextcloud coding standards for the php cs fixer", "support": { "issues": "https://github.com/nextcloud/coding-standard/issues", - "source": "https://github.com/nextcloud/coding-standard/tree/v1.1.0" + "source": "https://github.com/nextcloud/coding-standard/tree/v1.1.1" }, - "time": "2023-04-13T10:52:46+00:00" + "time": "2023-06-01T12:05:01+00:00" }, { "name": "nextcloud/ocp", @@ -1864,26 +1545,26 @@ "source": { "type": "git", "url": "https://github.com/nextcloud-deps/ocp.git", - "reference": "baf13f74c7bad9e134b8b95fbea945d5bee1d98d" + "reference": "fa7ed9794598fa62f13cc4a6c4cafd25af4b6c3e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nextcloud-deps/ocp/zipball/baf13f74c7bad9e134b8b95fbea945d5bee1d98d", - "reference": "baf13f74c7bad9e134b8b95fbea945d5bee1d98d", + "url": "https://api.github.com/repos/nextcloud-deps/ocp/zipball/fa7ed9794598fa62f13cc4a6c4cafd25af4b6c3e", + "reference": "fa7ed9794598fa62f13cc4a6c4cafd25af4b6c3e", "shasum": "" }, "require": { - "php": "^7.4 || ~8.0 || ~8.1", + "php": "~8.0 || ~8.1 || ~8.2", "psr/clock": "^1.0", - "psr/container": "^1.1.1", + "psr/container": "^2.0.2", "psr/event-dispatcher": "^1.0", - "psr/log": "^1.1" + "psr/log": "^1.1.4" }, "default-branch": true, "type": "library", "extra": { "branch-alias": { - "dev-master": "26.0.0-dev" + "dev-master": "28.0.0-dev" } }, "notification-url": "https://packagist.org/downloads/", @@ -1901,20 +1582,58 @@ "issues": "https://github.com/nextcloud-deps/ocp/issues", "source": "https://github.com/nextcloud-deps/ocp/tree/master" }, - "time": "2023-05-13T00:33:05+00:00" + "time": "2023-10-24T00:31:30+00:00" + }, + { + "name": "nextcloud/openapi-extractor", + "version": "dev-main", + "source": { + "type": "git", + "url": "https://github.com/nextcloud/openapi-extractor.git", + "reference": "05efabc561dbf253d251b3c2455e0857aa0ce577" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nextcloud/openapi-extractor/zipball/05efabc561dbf253d251b3c2455e0857aa0ce577", + "reference": "05efabc561dbf253d251b3c2455e0857aa0ce577", + "shasum": "" + }, + "require": { + "adhocore/cli": "^v1.6", + "ext-simplexml": "*", + "nikic/php-parser": "^4.16", + "php": "^8.1", + "phpstan/phpdoc-parser": "^1.23" + }, + "default-branch": true, + "bin": [ + "generate-spec", + "merge-specs" + ], + "type": "library", + "autoload": { + "psr-4": { + "OpenAPIExtractor\\": "src" + } + }, + "support": { + "source": "https://github.com/nextcloud/openapi-extractor/tree/main", + "issues": "https://github.com/nextcloud/openapi-extractor/issues" + }, + "time": "2023-10-23T15:50:09+00:00" }, { "name": "nikic/php-parser", - "version": "v4.15.4", + "version": "v4.17.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "6bb5176bc4af8bcb7d926f88718db9b96a2d4290" + "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/6bb5176bc4af8bcb7d926f88718db9b96a2d4290", - "reference": "6bb5176bc4af8bcb7d926f88718db9b96a2d4290", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", + "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", "shasum": "" }, "require": { @@ -1955,9 +1674,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.4" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1" }, - "time": "2023-03-05T19:49:14+00:00" + "time": "2023-08-13T19:53:39+00:00" }, { "name": "phan/phan", @@ -2149,6 +1868,58 @@ }, "time": "2022-02-21T01:04:05+00:00" }, + { + "name": "php-cs-fixer/shim", + "version": "v3.35.1", + "source": { + "type": "git", + "url": "https://github.com/PHP-CS-Fixer/shim.git", + "reference": "39dc3830797e107a21f8cfaca99fd0838950f8c2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHP-CS-Fixer/shim/zipball/39dc3830797e107a21f8cfaca99fd0838950f8c2", + "reference": "39dc3830797e107a21f8cfaca99fd0838950f8c2", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-tokenizer": "*", + "php": "^7.4 || ^8.0" + }, + "replace": { + "friendsofphp/php-cs-fixer": "self.version" + }, + "suggest": { + "ext-dom": "For handling output formats in XML", + "ext-mbstring": "For handling non-UTF8 characters." + }, + "bin": [ + "php-cs-fixer", + "php-cs-fixer.phar" + ], + "type": "application", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Dariusz Rumiński", + "email": "dariusz.ruminski@gmail.com" + } + ], + "description": "A tool to automatically fix PHP code style", + "support": { + "issues": "https://github.com/PHP-CS-Fixer/shim/issues", + "source": "https://github.com/PHP-CS-Fixer/shim/tree/v3.35.1" + }, + "time": "2023-10-12T13:48:08+00:00" + }, { "name": "phpdocumentor/reflection-common", "version": "2.2.0", @@ -2261,16 +2032,16 @@ }, { "name": "phpdocumentor/type-resolver", - "version": "1.7.1", + "version": "1.7.3", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "dfc078e8af9c99210337325ff5aa152872c98714" + "reference": "3219c6ee25c9ea71e3d9bbaf39c67c9ebd499419" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/dfc078e8af9c99210337325ff5aa152872c98714", - "reference": "dfc078e8af9c99210337325ff5aa152872c98714", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/3219c6ee25c9ea71e3d9bbaf39c67c9ebd499419", + "reference": "3219c6ee25c9ea71e3d9bbaf39c67c9ebd499419", "shasum": "" }, "require": { @@ -2313,28 +2084,30 @@ "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "support": { "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.7.1" + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.7.3" }, - "time": "2023-03-27T19:02:04+00:00" + "time": "2023-08-12T11:01:26+00:00" }, { "name": "phpstan/phpdoc-parser", - "version": "1.20.4", + "version": "1.24.2", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "7d568c87a9df9c5f7e8b5f075fc469aa8cb0a4cd" + "reference": "bcad8d995980440892759db0c32acae7c8e79442" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/7d568c87a9df9c5f7e8b5f075fc469aa8cb0a4cd", - "reference": "7d568c87a9df9c5f7e8b5f075fc469aa8cb0a4cd", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/bcad8d995980440892759db0c32acae7c8e79442", + "reference": "bcad8d995980440892759db0c32acae7c8e79442", "shasum": "" }, "require": { "php": "^7.2 || ^8.0" }, "require-dev": { + "doctrine/annotations": "^2.0", + "nikic/php-parser": "^4.15", "php-parallel-lint/php-parallel-lint": "^1.2", "phpstan/extension-installer": "^1.0", "phpstan/phpstan": "^1.5", @@ -2358,22 +2131,22 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.20.4" + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.24.2" }, - "time": "2023-05-02T09:19:37+00:00" + "time": "2023-09-26T12:28:12+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "9.2.26", + "version": "9.2.29", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "443bc6912c9bd5b409254a40f4b0f4ced7c80ea1" + "reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/443bc6912c9bd5b409254a40f4b0f4ced7c80ea1", - "reference": "443bc6912c9bd5b409254a40f4b0f4ced7c80ea1", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6a3a87ac2bbe33b25042753df8195ba4aa534c76", + "reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76", "shasum": "" }, "require": { @@ -2429,7 +2202,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.26" + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.29" }, "funding": [ { @@ -2437,7 +2211,7 @@ "type": "github" } ], - "time": "2023-03-06T12:58:08+00:00" + "time": "2023-09-19T04:57:46+00:00" }, { "name": "phpunit/php-file-iterator", @@ -2682,16 +2456,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.8", + "version": "9.6.13", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "17d621b3aff84d0c8b62539e269e87d8d5baa76e" + "reference": "f3d767f7f9e191eab4189abe41ab37797e30b1be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/17d621b3aff84d0c8b62539e269e87d8d5baa76e", - "reference": "17d621b3aff84d0c8b62539e269e87d8d5baa76e", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f3d767f7f9e191eab4189abe41ab37797e30b1be", + "reference": "f3d767f7f9e191eab4189abe41ab37797e30b1be", "shasum": "" }, "require": { @@ -2706,7 +2480,7 @@ "phar-io/manifest": "^2.0.3", "phar-io/version": "^3.0.2", "php": ">=7.3", - "phpunit/php-code-coverage": "^9.2.13", + "phpunit/php-code-coverage": "^9.2.28", "phpunit/php-file-iterator": "^3.0.5", "phpunit/php-invoker": "^3.1.1", "phpunit/php-text-template": "^2.0.3", @@ -2765,7 +2539,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.8" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.13" }, "funding": [ { @@ -2781,56 +2555,7 @@ "type": "tidelift" } ], - "time": "2023-05-11T05:14:45+00:00" - }, - { - "name": "psr/cache", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/php-fig/cache.git", - "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", - "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Cache\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for caching libraries", - "keywords": [ - "cache", - "psr", - "psr-6" - ], - "support": { - "source": "https://github.com/php-fig/cache/tree/master" - }, - "time": "2016-08-06T20:24:11+00:00" + "time": "2023-09-19T05:39:22+00:00" }, { "name": "psr/clock", @@ -2882,22 +2607,27 @@ }, { "name": "psr/container", - "version": "1.1.2", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/container.git", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", "shasum": "" }, "require": { "php": ">=7.4.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, "autoload": { "psr-4": { "Psr\\Container\\": "src/" @@ -2924,9 +2654,9 @@ ], "support": { "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/1.1.2" + "source": "https://github.com/php-fig/container/tree/2.0.2" }, - "time": "2021-11-05T16:50:12+00:00" + "time": "2021-11-05T16:47:00+00:00" }, { "name": "psr/event-dispatcher", @@ -3600,16 +3330,16 @@ }, { "name": "sebastian/global-state", - "version": "5.0.5", + "version": "5.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2" + "reference": "bde739e7565280bda77be70044ac1047bc007e34" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bde739e7565280bda77be70044ac1047bc007e34", + "reference": "bde739e7565280bda77be70044ac1047bc007e34", "shasum": "" }, "require": { @@ -3652,7 +3382,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5" + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.6" }, "funding": [ { @@ -3660,7 +3390,7 @@ "type": "github" } ], - "time": "2022-02-14T08:28:10+00:00" + "time": "2023-08-02T09:26:13+00:00" }, { "name": "sebastian/lines-of-code", @@ -4060,26 +3790,25 @@ }, { "name": "spatie/array-to-xml", - "version": "2.17.1", + "version": "3.2.0", "source": { "type": "git", "url": "https://github.com/spatie/array-to-xml.git", - "reference": "5cbec9c6ab17e320c58a259f0cebe88bde4a7c46" + "reference": "f9ab39c808500c347d5a8b6b13310bd5221e39e7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/5cbec9c6ab17e320c58a259f0cebe88bde4a7c46", - "reference": "5cbec9c6ab17e320c58a259f0cebe88bde4a7c46", + "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/f9ab39c808500c347d5a8b6b13310bd5221e39e7", + "reference": "f9ab39c808500c347d5a8b6b13310bd5221e39e7", "shasum": "" }, "require": { "ext-dom": "*", - "php": "^7.4|^8.0" + "php": "^8.0" }, "require-dev": { "mockery/mockery": "^1.2", "pestphp/pest": "^1.21", - "phpunit/phpunit": "^9.0", "spatie/pest-plugin-snapshots": "^1.1" }, "type": "library", @@ -4108,7 +3837,7 @@ "xml" ], "support": { - "source": "https://github.com/spatie/array-to-xml/tree/2.17.1" + "source": "https://github.com/spatie/array-to-xml/tree/3.2.0" }, "funding": [ { @@ -4120,7 +3849,7 @@ "type": "github" } ], - "time": "2022-12-26T08:22:07+00:00" + "time": "2023-07-19T18:30:26+00:00" }, { "name": "staabm/annotate-pull-request-from-checkstyle", @@ -4176,52 +3905,43 @@ }, { "name": "symfony/console", - "version": "v5.4.23", + "version": "v6.3.4", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "90f21e27d0d88ce38720556dd164d4a1e4c3934c" + "reference": "eca495f2ee845130855ddf1cf18460c38966c8b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/90f21e27d0d88ce38720556dd164d4a1e4c3934c", - "reference": "90f21e27d0d88ce38720556dd164d4a1e4c3934c", + "url": "https://api.github.com/repos/symfony/console/zipball/eca495f2ee845130855ddf1cf18460c38966c8b6", + "reference": "eca495f2ee845130855ddf1cf18460c38966c8b6", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php73": "^1.9", - "symfony/polyfill-php80": "^1.16", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/string": "^5.1|^6.0" + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^5.4|^6.0" }, "conflict": { - "psr/log": ">=3", - "symfony/dependency-injection": "<4.4", - "symfony/dotenv": "<5.1", - "symfony/event-dispatcher": "<4.4", - "symfony/lock": "<4.4", - "symfony/process": "<4.4" + "symfony/dependency-injection": "<5.4", + "symfony/dotenv": "<5.4", + "symfony/event-dispatcher": "<5.4", + "symfony/lock": "<5.4", + "symfony/process": "<5.4" }, "provide": { - "psr/log-implementation": "1.0|2.0" + "psr/log-implementation": "1.0|2.0|3.0" }, "require-dev": { - "psr/log": "^1|^2", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/event-dispatcher": "^4.4|^5.0|^6.0", - "symfony/lock": "^4.4|^5.0|^6.0", - "symfony/process": "^4.4|^5.0|^6.0", - "symfony/var-dumper": "^4.4|^5.0|^6.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/lock": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0", + "symfony/var-dumper": "^5.4|^6.0" }, "type": "library", "autoload": { @@ -4255,7 +3975,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.4.23" + "source": "https://github.com/symfony/console/tree/v6.3.4" }, "funding": [ { @@ -4271,29 +3991,29 @@ "type": "tidelift" } ], - "time": "2023-04-24T18:47:29+00:00" + "time": "2023-08-16T10:10:12+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v2.5.2", + "version": "v3.3.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66" + "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66", - "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", + "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=8.1" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.5-dev" + "dev-main": "3.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -4322,7 +4042,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.2" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.3.0" }, "funding": [ { @@ -4338,53 +4058,31 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:53:40+00:00" + "time": "2023-05-23T14:45:45+00:00" }, { - "name": "symfony/event-dispatcher", - "version": "v5.4.22", + "name": "symfony/filesystem", + "version": "v6.3.1", "source": { "type": "git", - "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "1df20e45d56da29a4b1d8259dd6e950acbf1b13f" + "url": "https://github.com/symfony/filesystem.git", + "reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/1df20e45d56da29a4b1d8259dd6e950acbf1b13f", - "reference": "1df20e45d56da29a4b1d8259dd6e950acbf1b13f", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/edd36776956f2a6fcf577edb5b05eb0e3bdc52ae", + "reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/event-dispatcher-contracts": "^2|^3", - "symfony/polyfill-php80": "^1.16" - }, - "conflict": { - "symfony/dependency-injection": "<4.4" - }, - "provide": { - "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "2.0" - }, - "require-dev": { - "psr/log": "^1|^2|^3", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/http-foundation": "^4.4|^5.0|^6.0", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/stopwatch": "^4.4|^5.0|^6.0" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" + "php": ">=8.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8" }, "type": "library", "autoload": { "psr-4": { - "Symfony\\Component\\EventDispatcher\\": "" + "Symfony\\Component\\Filesystem\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -4404,10 +4102,10 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", + "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v5.4.22" + "source": "https://github.com/symfony/filesystem/tree/v6.3.1" }, "funding": [ { @@ -4423,42 +4121,47 @@ "type": "tidelift" } ], - "time": "2023-03-17T11:31:58+00:00" + "time": "2023-06-01T08:30:39+00:00" }, { - "name": "symfony/event-dispatcher-contracts", - "version": "v2.5.2", + "name": "symfony/polyfill-ctype", + "version": "v1.28.0", "source": { "type": "git", - "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "f98b54df6ad059855739db6fcbc2d36995283fe1" + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/f98b54df6ad059855739db6fcbc2d36995283fe1", - "reference": "f98b54df6ad059855739db6fcbc2d36995283fe1", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", + "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", "shasum": "" }, "require": { - "php": ">=7.2.5", - "psr/event-dispatcher": "^1" + "php": ">=7.1" + }, + "provide": { + "ext-ctype": "*" }, "suggest": { - "symfony/event-dispatcher-implementation": "" + "ext-ctype": "For best performance" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.5-dev" + "dev-main": "1.28-dev" }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { + "files": [ + "bootstrap.php" + ], "psr-4": { - "Symfony\\Contracts\\EventDispatcher\\": "" + "Symfony\\Polyfill\\Ctype\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -4467,26 +4170,24 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Generic abstractions related to dispatching event", + "description": "Symfony polyfill for ctype functions", "homepage": "https://symfony.com", "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" + "compatibility", + "ctype", + "polyfill", + "portable" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.5.2" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0" }, "funding": [ { @@ -4502,36 +4203,45 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:53:40+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { - "name": "symfony/filesystem", - "version": "v5.4.23", + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.28.0", "source": { "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "b2f79d86cd9e7de0fff6d03baa80eaed7a5f38b5" + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "875e90aeea2777b6f135677f618529449334a612" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/b2f79d86cd9e7de0fff6d03baa80eaed7a5f38b5", - "reference": "b2f79d86cd9e7de0fff6d03baa80eaed7a5f38b5", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/875e90aeea2777b6f135677f618529449334a612", + "reference": "875e90aeea2777b6f135677f618529449334a612", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.8", - "symfony/polyfill-php80": "^1.16" + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.28-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, "autoload": { + "files": [ + "bootstrap.php" + ], "psr-4": { - "Symfony\\Component\\Filesystem\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -4539,18 +4249,26 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Provides basic utilities for the filesystem", + "description": "Symfony polyfill for intl's grapheme_* functions", "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], "support": { - "source": "https://github.com/symfony/filesystem/tree/v5.4.23" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.28.0" }, "funding": [ { @@ -4566,327 +4284,32 @@ "type": "tidelift" } ], - "time": "2023-03-02T11:38:35+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { - "name": "symfony/finder", - "version": "v5.4.21", + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.28.0", "source": { "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "078e9a5e1871fcfe6a5ce421b539344c21afef19" + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/078e9a5e1871fcfe6a5ce421b539344c21afef19", - "reference": "078e9a5e1871fcfe6a5ce421b539344c21afef19", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", + "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php80": "^1.16" + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" }, "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Finder\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Finds files and directories via an intuitive fluent interface", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/finder/tree/v5.4.21" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-02-16T09:33:00+00:00" - }, - { - "name": "symfony/options-resolver", - "version": "v5.4.21", - "source": { - "type": "git", - "url": "https://github.com/symfony/options-resolver.git", - "reference": "4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9", - "reference": "4fe5cf6ede71096839f0e4b4444d65dd3a7c1eb9", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php73": "~1.0", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\OptionsResolver\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides an improved replacement for the array_replace PHP function", - "homepage": "https://symfony.com", - "keywords": [ - "config", - "configuration", - "options" - ], - "support": { - "source": "https://github.com/symfony/options-resolver/tree/v5.4.21" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-02-14T08:03:56+00:00" - }, - { - "name": "symfony/polyfill-ctype", - "version": "v1.27.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "5bbc823adecdae860bb64756d639ecfec17b050a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a", - "reference": "5bbc823adecdae860bb64756d639ecfec17b050a", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "provide": { - "ext-ctype": "*" - }, - "suggest": { - "ext-ctype": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for ctype functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ], - "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-11-03T14:55:06+00:00" - }, - { - "name": "symfony/polyfill-intl-grapheme", - "version": "v1.27.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "511a08c03c1960e08a883f4cffcacd219b758354" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354", - "reference": "511a08c03c1960e08a883f4cffcacd219b758354", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Intl\\Grapheme\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for intl's grapheme_* functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "grapheme", - "intl", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-11-03T14:55:06+00:00" - }, - { - "name": "symfony/polyfill-intl-normalizer", - "version": "v1.27.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6", - "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.27-dev" + "extra": { + "branch-alias": { + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -4929,7 +4352,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.0" }, "funding": [ { @@ -4945,29 +4368,35 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { - "name": "symfony/polyfill-php73", - "version": "v1.27.0", + "name": "symfony/polyfill-mbstring", + "version": "v1.28.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9" + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "42292d99c55abe617799667f454222c54c60e229" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/9e8ecb5f92152187c4799efd3c96b78ccab18ff9", - "reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", + "reference": "42292d99c55abe617799667f454222c54c60e229", "shasum": "" }, "require": { "php": ">=7.1" }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -4979,11 +4408,8 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Php73\\": "" - }, - "classmap": [ - "Resources/stubs" - ] + "Symfony\\Polyfill\\Mbstring\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -4999,16 +4425,17 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "description": "Symfony polyfill for the Mbstring extension", "homepage": "https://symfony.com", "keywords": [ "compatibility", + "mbstring", "polyfill", "portable", "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" }, "funding": [ { @@ -5024,20 +4451,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-07-28T09:04:16+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936" + "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", - "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5", + "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5", "shasum": "" }, "require": { @@ -5046,7 +4473,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -5091,7 +4518,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.28.0" }, "funding": [ { @@ -5107,178 +4534,33 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" - }, - { - "name": "symfony/polyfill-php81", - "version": "v1.27.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/707403074c8ea6e2edaf8794b0157a0bfa52157a", - "reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php81\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.27.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-11-03T14:55:06+00:00" - }, - { - "name": "symfony/process", - "version": "v5.4.23", - "source": { - "type": "git", - "url": "https://github.com/symfony/process.git", - "reference": "4b842fc4b61609e0a155a114082bd94e31e98287" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/4b842fc4b61609e0a155a114082bd94e31e98287", - "reference": "4b842fc4b61609e0a155a114082bd94e31e98287", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Process\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Executes commands in sub-processes", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/process/tree/v5.4.23" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-04-18T13:50:24+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/service-contracts", - "version": "v2.5.2", + "version": "v3.3.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c" + "reference": "40da9cc13ec349d9e4966ce18b5fbcd724ab10a4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c", - "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/40da9cc13ec349d9e4966ce18b5fbcd724ab10a4", + "reference": "40da9cc13ec349d9e4966ce18b5fbcd724ab10a4", "shasum": "" }, "require": { - "php": ">=7.2.5", - "psr/container": "^1.1", - "symfony/deprecation-contracts": "^2.1|^3" + "php": ">=8.1", + "psr/container": "^2.0" }, "conflict": { "ext-psr": "<1.1|>=2" }, - "suggest": { - "symfony/service-implementation": "" - }, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.5-dev" + "dev-main": "3.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -5288,7 +4570,10 @@ "autoload": { "psr-4": { "Symfony\\Contracts\\Service\\": "" - } + }, + "exclude-from-classmap": [ + "/Test/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -5315,69 +4600,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v2.5.2" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-05-30T19:17:29+00:00" - }, - { - "name": "symfony/stopwatch", - "version": "v5.4.21", - "source": { - "type": "git", - "url": "https://github.com/symfony/stopwatch.git", - "reference": "f83692cd869a6f2391691d40a01e8acb89e76fee" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/f83692cd869a6f2391691d40a01e8acb89e76fee", - "reference": "f83692cd869a6f2391691d40a01e8acb89e76fee", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/service-contracts": "^1|^2|^3" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Stopwatch\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides a way to profile code", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/stopwatch/tree/v5.4.21" + "source": "https://github.com/symfony/service-contracts/tree/v3.3.0" }, "funding": [ { @@ -5393,38 +4616,38 @@ "type": "tidelift" } ], - "time": "2023-02-14T08:03:56+00:00" + "time": "2023-05-23T14:45:45+00:00" }, { "name": "symfony/string", - "version": "v5.4.22", + "version": "v6.3.5", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "8036a4c76c0dd29e60b6a7cafcacc50cf088ea62" + "reference": "13d76d0fb049051ed12a04bef4f9de8715bea339" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/8036a4c76c0dd29e60b6a7cafcacc50cf088ea62", - "reference": "8036a4c76c0dd29e60b6a7cafcacc50cf088ea62", + "url": "https://api.github.com/repos/symfony/string/zipball/13d76d0fb049051ed12a04bef4f9de8715bea339", + "reference": "13d76d0fb049051ed12a04bef4f9de8715bea339", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.1", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-grapheme": "~1.0", "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "~1.15" + "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/translation-contracts": ">=3.0" + "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/http-client": "^4.4|^5.0|^6.0", - "symfony/translation-contracts": "^1.1|^2", - "symfony/var-exporter": "^4.4|^5.0|^6.0" + "symfony/error-handler": "^5.4|^6.0", + "symfony/http-client": "^5.4|^6.0", + "symfony/intl": "^6.2", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^5.4|^6.0" }, "type": "library", "autoload": { @@ -5463,7 +4686,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.4.22" + "source": "https://github.com/symfony/string/tree/v6.3.5" }, "funding": [ { @@ -5479,7 +4702,7 @@ "type": "tidelift" } ], - "time": "2023-03-14T06:11:53+00:00" + "time": "2023-09-18T10:38:32+00:00" }, { "name": "theseer/tokenizer", @@ -5595,16 +4818,16 @@ }, { "name": "vimeo/psalm", - "version": "5.11.0", + "version": "5.15.0", "source": { "type": "git", "url": "https://github.com/vimeo/psalm.git", - "reference": "c9b192ab8400fdaf04b2b13d110575adc879aa90" + "reference": "5c774aca4746caf3d239d9c8cadb9f882ca29352" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vimeo/psalm/zipball/c9b192ab8400fdaf04b2b13d110575adc879aa90", - "reference": "c9b192ab8400fdaf04b2b13d110575adc879aa90", + "url": "https://api.github.com/repos/vimeo/psalm/zipball/5c774aca4746caf3d239d9c8cadb9f882ca29352", + "reference": "5c774aca4746caf3d239d9c8cadb9f882ca29352", "shasum": "" }, "require": { @@ -5625,13 +4848,16 @@ "felixfbecker/language-server-protocol": "^1.5.2", "fidry/cpu-core-counter": "^0.4.1 || ^0.5.1", "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", - "nikic/php-parser": "^4.14", - "php": "^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0", + "nikic/php-parser": "^4.16", + "php": "^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0", "sebastian/diff": "^4.0 || ^5.0", "spatie/array-to-xml": "^2.17.0 || ^3.0", "symfony/console": "^4.1.6 || ^5.0 || ^6.0", "symfony/filesystem": "^5.4 || ^6.0" }, + "conflict": { + "nikic/php-parser": "4.17.0" + }, "provide": { "psalm/psalm": "self.version" }, @@ -5695,9 +4921,9 @@ ], "support": { "issues": "https://github.com/vimeo/psalm/issues", - "source": "https://github.com/vimeo/psalm/tree/5.11.0" + "source": "https://github.com/vimeo/psalm/tree/5.15.0" }, - "time": "2023-05-04T21:35:44+00:00" + "time": "2023-08-20T23:07:30+00:00" }, { "name": "webmozart/assert", @@ -5761,14 +4987,15 @@ "aliases": [], "minimum-stability": "stable", "stability-flags": { - "nextcloud/ocp": 20 + "nextcloud/ocp": 20, + "nextcloud/openapi-extractor": 20 }, "prefer-stable": false, "prefer-lowest": false, "platform": [], "platform-dev": [], "platform-overrides": { - "php": "7.4" + "php": "8.1" }, "plugin-api-version": "2.3.0" } diff --git a/cypress/integration/api-v2/tables.spec.js b/cypress/integration/api-v2/tables.spec.js new file mode 100644 index 000000000..e69de29bb diff --git a/lib/Capabilities.php b/lib/Capabilities.php index d45cd4b6c..2d7573ad2 100644 --- a/lib/Capabilities.php +++ b/lib/Capabilities.php @@ -45,6 +45,9 @@ public function __construct(IAppManager $appManager, LoggerInterface $logger, IC } /** + * + * @return array{tables: array{enabled: bool, version: string, apiVersions: string[], column_types: string[]}} + * * @inheritDoc */ public function getCapabilities(): array { diff --git a/lib/Controller/AOCSController.php b/lib/Controller/AOCSController.php new file mode 100644 index 000000000..3ad870fcb --- /dev/null +++ b/lib/Controller/AOCSController.php @@ -0,0 +1,62 @@ +logger = $logger; + $this->userId = $userId; + $this->n = $n; + } + + /** + * @param Exception|InternalError $e + * @return DataResponse + */ + protected function handleError($e): DataResponse { + $this->logger->warning('An internal error or exception occurred: ['. $e->getCode() . ']' . $e->getMessage()); + return new DataResponse(['message' => $this->n->t('An unexpected error occurred. More details can be found in the logs. Please reach out to your administrator.')], Http::STATUS_INTERNAL_SERVER_ERROR); + } + + /** + * @param PermissionError $e + * @return DataResponse + */ + protected function handlePermissionError(PermissionError $e): DataResponse { + $this->logger->warning('A permission error occurred: ['. $e->getCode() . ']' . $e->getMessage()); + return new DataResponse(['message' => $this->n->t('An permission error occurred. More details can be found in the logs. Please reach out to your administrator.')], Http::STATUS_FORBIDDEN); + } + + /** + * @param NotFoundError $e + * @return DataResponse + */ + protected function handleNotFoundError(NotFoundError $e): DataResponse { + $this->logger->warning('A not found error occurred: ['. $e->getCode() . ']' . $e->getMessage()); + return new DataResponse(['message' => $this->n->t('An not found error occurred. More details can be found in the logs. Please reach out to your administrator.')], Http::STATUS_NOT_FOUND); + } + +} diff --git a/lib/Controller/Api1Controller.php b/lib/Controller/Api1Controller.php index 09b719b04..13d1f7bff 100644 --- a/lib/Controller/Api1Controller.php +++ b/lib/Controller/Api1Controller.php @@ -4,9 +4,14 @@ namespace OCA\Tables\Controller; +use Exception; use OCA\Tables\Api\V1Api; use OCA\Tables\AppInfo\Application; use OCA\Tables\Db\ViewMapper; +use OCA\Tables\Errors\InternalError; +use OCA\Tables\Errors\NotFoundError; +use OCA\Tables\Errors\PermissionError; +use OCA\Tables\ResponseDefinitions; use OCA\Tables\Service\ColumnService; use OCA\Tables\Service\ImportService; use OCA\Tables\Service\RowService; @@ -14,12 +19,22 @@ use OCA\Tables\Service\TableService; use OCA\Tables\Service\ViewService; use OCP\AppFramework\ApiController; +use OCP\AppFramework\Db\DoesNotExistException; +use OCP\AppFramework\Db\MultipleObjectsReturnedException; use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; use OCP\IL10N; use OCP\IRequest; use Psr\Log\LoggerInterface; +/** + * @psalm-import-type TablesTable from ResponseDefinitions + * @psalm-import-type TablesView from ResponseDefinitions + * @psalm-import-type TablesShare from ResponseDefinitions + * @psalm-import-type TablesColumn from ResponseDefinitions + * @psalm-import-type TablesRow from ResponseDefinitions + * @psalm-import-type TablesImportState from ResponseDefinitions + */ class Api1Controller extends ApiController { private TableService $tableService; private ShareService $shareService; @@ -70,213 +85,591 @@ public function __construct( // Tables /** + * Returns all Tables + * * @NoAdminRequired * @CORS * @NoCSRFRequired + * + * @return DataResponse|DataResponse + * + * 200: Tables returned */ public function index(): DataResponse { - return $this->handleError(function () { - return $this->tableService->findAll($this->userId); - }); + try { + return new DataResponse($this->tableService->formatTables($this->tableService->findAll($this->userId))); + } catch (InternalError|Exception $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } } /** + * Create a new table and return it + * * @NoAdminRequired * @CORS * @NoCSRFRequired + * + * @param string $title Title of the table + * @param string|null $emoji Emoji for the table + * @param string $template Template to use if wanted + * + * @return DataResponse|DataResponse + * + * 200: Tables returned */ public function createTable(string $title, ?string $emoji, string $template = 'custom'): DataResponse { - return $this->handleError(function () use ($title, $emoji, $template) { - return $this->tableService->create($title, $template, $emoji); - }); + try { + return new DataResponse($this->tableService->create($title, $template, $emoji)->jsonSerialize()); + } catch (InternalError|Exception $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } } /** + * Get a table object + * * @NoAdminRequired * @CORS * @NoCSRFRequired + * + * @param int $tableId Table ID + * @return DataResponse|DataResponse + * + * 200: Table returned + * 403: No permissions + * 404: Not found */ public function getTable(int $tableId): DataResponse { - return $this->handleError(function () use ($tableId) { - return $this->tableService->find($tableId); - }); + try { + return new DataResponse($this->tableService->find($tableId)->jsonSerialize()); + } catch (PermissionError $e) { + $this->logger->warning('A permission error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_FORBIDDEN); + } catch (NotFoundError $e) { + $this->logger->warning('A not found error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_NOT_FOUND); + } catch (InternalError|Exception $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } } /** + * Update tables properties + * * @NoAdminRequired * @CORS * @NoCSRFRequired + * + * @param int $tableId Table ID + * @param string|null $title New table title + * @param string|null $emoji New table emoji + * @return DataResponse|DataResponse + * + * 200: Tables returned + * 403: No permissions + * 404: Not found */ public function updateTable(int $tableId, string $title = null, string $emoji = null): DataResponse { - return $this->handleError(function () use ($tableId, $title, $emoji) { - return $this->tableService->update($tableId, $title, $emoji, $this->userId); - }); + try { + return new DataResponse($this->tableService->update($tableId, $title, $emoji, $this->userId)->jsonSerialize()); + } catch (PermissionError $e) { + $this->logger->warning('A permission error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_FORBIDDEN); + } catch (NotFoundError $e) { + $this->logger->warning('A not found error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_NOT_FOUND); + } catch (InternalError|Exception $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } } /** + * Delete a table + * * @NoAdminRequired * @CORS * @NoCSRFRequired + * + * @param int $tableId Table ID + * @return DataResponse|DataResponse + * + * 200: Deleted table returned + * 403: No permissions + * 404: Not found */ public function deleteTable(int $tableId): DataResponse { - return $this->handleError(function () use ($tableId) { - return $this->tableService->delete($tableId); - }); + try { + return new DataResponse($this->tableService->delete($tableId)->jsonSerialize()); + } catch (PermissionError $e) { + $this->logger->warning('A permission error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_FORBIDDEN); + } catch (NotFoundError $e) { + $this->logger->warning('A not found error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_NOT_FOUND); + } catch (InternalError|Exception $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } } // Views /** + * Get all views for a table + * * @NoAdminRequired * @CORS * @NoCSRFRequired + * + * @param int $tableId Table ID + * @return DataResponse|DataResponse + * + * 200: Views returned + * 403: No permissions + * 404: Not found */ public function indexViews(int $tableId): DataResponse { - return $this->handleError(function () use ($tableId) { - return $this->viewService->findAll($this->tableService->find($tableId)); - }); + try { + return new DataResponse($this->viewService->formatViews($this->viewService->findAll($this->tableService->find($tableId)))); + } catch (PermissionError $e) { + $this->logger->warning('A permission error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_FORBIDDEN); + } catch (NotFoundError $e) { + $this->logger->warning('A not found error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_NOT_FOUND); + } catch (InternalError|Exception $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } } /** + * Create a new view for a table + * * @NoAdminRequired * @CORS * @NoCSRFRequired + * + * @param int $tableId Table ID that will hold the view + * @param string $title Title for the view + * @param string|null $emoji Emoji for the view + * + * @return DataResponse|DataResponse + * + * 200: View created + * 403: No permissions + * 404: Not found */ public function createView(int $tableId, string $title, ?string $emoji): DataResponse { - return $this->handleError(function () use ($tableId, $title, $emoji) { - return $this->viewService->create($title, $emoji, $this->tableService->find($tableId)); - }); + try { + return new DataResponse($this->viewService->create($title, $emoji, $this->tableService->find($tableId))->jsonSerialize()); + } catch (PermissionError $e) { + $this->logger->warning('A permission error occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_FORBIDDEN); + } catch (InternalError|Exception $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } } /** + * Get a view object + * * @NoAdminRequired * @CORS * @NoCSRFRequired + * + * @param int $viewId View ID + * @return DataResponse|DataResponse + * + * 200: View returned + * 403: No permissions + * 404: Not found */ public function getView(int $viewId): DataResponse { - return $this->handleError(function () use ($viewId) { - return $this->viewService->find($viewId); - }); + try { + return new DataResponse($this->viewService->find($viewId)->jsonSerialize()); + } catch (PermissionError $e) { + $this->logger->warning('A permission error occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_FORBIDDEN); + } catch (InternalError $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } catch (NotFoundError $e) { + $this->logger->warning('A not found error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_NOT_FOUND); + } } /** + * Update a view via key-value sets + * * @NoAdminRequired * @CORS * @NoCSRFRequired + * + * @param int $viewId View ID + * @param array{key: 'title'|'emoji'|'description', value: string}|array{key: 'columns', value: int[]}|array{key: 'sort', value: array{columnId: int, mode: 'ASC'|'DESC'}}|array{key: 'filter', value: array{columnId: int, operator: 'begins-with'|'ends-with'|'contains'|'is-equal'|'is-greater-than'|'is-greater-than-or-equal'|'is-lower-than'|'is-lower-than-or-equal'|'is-empty', value: string|int|float}} $data key-value pairs + * @return DataResponse|DataResponse + * + * 200: View updated + * 403: No permissions + * 404: Not found */ public function updateView(int $viewId, array $data): DataResponse { - return $this->handleError(function () use ($viewId, $data) { - return $this->viewService->update($viewId, $data); - }); + try { + return new DataResponse($this->viewService->update($viewId, $data)->jsonSerialize()); + } catch (PermissionError $e) { + $this->logger->warning('A permission error occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_FORBIDDEN); + } catch (InternalError|Exception $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } } /** + * Delete a view + * * @NoAdminRequired * @CORS * @NoCSRFRequired + * + * @param int $viewId View ID + * @return DataResponse|DataResponse + * + * 200: View deleted + * 403: No permissions + * 404: Not found */ public function deleteView(int $viewId): DataResponse { - return $this->handleError(function () use ($viewId) { - return $this->viewService->delete($viewId); - }); + try { + return new DataResponse($this->viewService->delete($viewId)->jsonSerialize()); + } catch (PermissionError $e) { + $this->logger->warning('A permission error occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_FORBIDDEN); + } catch (InternalError $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } catch (NotFoundError $e) { + $this->logger->warning('A not found error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_NOT_FOUND); + } } // Shares /** + * Get a share object + * * @NoAdminRequired * @CORS * @NoCSRFRequired + * + * @param int $shareId Share ID + * @return DataResponse|DataResponse + * + * 200: Share returned + * 403: No permissions + * 404: Not found */ public function getShare(int $shareId): DataResponse { - return $this->handleError(function () use ($shareId) { - return $this->shareService->find($shareId); - }); + try { + return new DataResponse($this->shareService->find($shareId)->jsonSerialize()); + } catch (PermissionError $e) { + $this->logger->warning('A permission error occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_FORBIDDEN); + } catch (InternalError $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } catch (NotFoundError $e) { + $this->logger->warning('A not found error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_NOT_FOUND); + } } /** + * Get all shares for a view + * Will be empty if view does not exist + * * @NoAdminRequired * @CORS * @NoCSRFRequired + * + * @param int $viewId View ID + * @return DataResponse|DataResponse + * + * 200: Shares returned */ public function indexViewShares(int $viewId): DataResponse { - return $this->handleError(function () use ($viewId) { - return $this->shareService->findAll('view', $viewId); - }); + try { + return new DataResponse($this->shareService->formatShares($this->shareService->findAll('view', $viewId))); + } catch (InternalError $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } } /** + * Get all shares for a table + * Will be empty if table does not exist + * * @NoAdminRequired * @CORS * @NoCSRFRequired + * + * @param int $tableId Table ID + * @return DataResponse|DataResponse + * + * 200: Shares returned */ public function indexTableShares(int $tableId): DataResponse { - return $this->handleError(function () use ($tableId) { - return $this->shareService->findAll('table', $tableId); - }); + try { + return new DataResponse($this->shareService->formatShares($this->shareService->findAll('table', $tableId))); + } catch (InternalError $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } } /** + * Create a new share + * * @NoAdminRequired * @CORS * @NoCSRFRequired + * + * @param int $nodeId Node ID + * @param 'table'|'view' $nodeType Node type + * @param string $receiver Receiver ID + * @param 'user'|'group' $receiverType Receiver type + * @param bool $permissionRead Permission if receiver can read data + * @param bool $permissionCreate Permission if receiver can create data + * @param bool $permissionUpdate Permission if receiver can update data + * @param bool $permissionDelete Permission if receiver can delete data + * @param bool $permissionManage Permission if receiver can manage node + * @return DataResponse|DataResponse + * + * 200: Share returned + * 403: No permissions + * 404: Not found */ public function createShare(int $nodeId, string $nodeType, string $receiver, string $receiverType, bool $permissionRead = false, bool $permissionCreate = false, bool $permissionUpdate = false, bool $permissionDelete = false, bool $permissionManage = false): DataResponse { - return $this->handleError(function () use ($nodeId, $nodeType, $receiver, $receiverType, $permissionRead, $permissionCreate, $permissionUpdate, $permissionDelete, $permissionManage) { - return $this->shareService->create($nodeId, $nodeType, $receiver, $receiverType, $permissionRead, $permissionCreate, $permissionUpdate, $permissionDelete, $permissionManage); - }); + try { + return new DataResponse($this->shareService->create($nodeId, $nodeType, $receiver, $receiverType, $permissionRead, $permissionCreate, $permissionUpdate, $permissionDelete, $permissionManage)->jsonSerialize()); + } catch (PermissionError $e) { + $this->logger->warning('A permission error occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_FORBIDDEN); + } catch (InternalError $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } catch (NotFoundError $e) { + $this->logger->warning('A not found error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_NOT_FOUND); + } } /** + * Delete a share + * * @NoAdminRequired * @CORS * @NoCSRFRequired + * + * @param int $shareId Share ID + * @return DataResponse|DataResponse + * + * 200: View deleted + * 403: No permissions + * 404: Not found */ public function deleteShare(int $shareId): DataResponse { - return $this->handleError(function () use ($shareId) { - return $this->shareService->delete($shareId); - }); + try { + return new DataResponse($this->shareService->delete($shareId)->jsonSerialize()); + } catch (PermissionError $e) { + $this->logger->warning('A permission error occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_FORBIDDEN); + } catch (InternalError $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } catch (NotFoundError $e) { + $this->logger->warning('A not found error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_NOT_FOUND); + } } /** + * Update a share permission + * * @NoAdminRequired * @CORS * @NoCSRFRequired + * + * @param int $shareId Share ID + * @param string $permissionType Permission type that should be changed + * @param bool $permissionValue New permission value + * @return DataResponse|DataResponse + * + * 200: View deleted + * 403: No permissions + * 404: Not found */ public function updateSharePermissions(int $shareId, string $permissionType, bool $permissionValue): DataResponse { - return $this->handleError(function () use ($shareId, $permissionType, $permissionValue) { - return $this->shareService->updatePermission($shareId, $permissionType, $permissionValue); - }); + try { + return new DataResponse($this->shareService->updatePermission($shareId, $permissionType, $permissionValue)->jsonSerialize()); + } catch (PermissionError $e) { + $this->logger->warning('A permission error occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_FORBIDDEN); + } catch (InternalError $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } catch (NotFoundError $e) { + $this->logger->warning('A not found error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_NOT_FOUND); + } } // Columns /** + * Get all columns for a table or a underlying view + * Return an empty array if no columns were found + * * @NoAdminRequired * @CORS * @NoCSRFRequired + * + * @param int $tableId Table ID + * @param int|null $viewId View ID + * @return DataResponse|DataResponse + * + * 200: View deleted + * 403: No permissions + * 404: Not found */ public function indexTableColumns(int $tableId, ?int $viewId): DataResponse { - return $this->handleError(function () use ($tableId, $viewId) { - return $this->columnService->findAllByTable($tableId, $viewId); - }); + try { + return new DataResponse($this->columnService->formatColumns($this->columnService->findAllByTable($tableId, $viewId))); + } catch (PermissionError $e) { + $this->logger->warning('A permission error occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_FORBIDDEN); + } catch (InternalError $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } } /** + * Get all columns for a view + * Return an empty array if no columns were found + * * @NoAdminRequired * @CORS * @NoCSRFRequired + * + * @param int $viewId View ID + * @return DataResponse|DataResponse + * + * 200: View deleted + * 403: No permissions + * 404: Not found */ public function indexViewColumns(int $viewId): DataResponse { - return $this->handleError(function () use ($viewId) { - return $this->columnService->findAllByView($viewId); - }); + try { + return new DataResponse($this->columnService->formatColumns($this->columnService->findAllByView($viewId))); + } catch (PermissionError $e) { + $this->logger->warning('A permission error occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_FORBIDDEN); + } catch (InternalError $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } catch (NotFoundError $e) { + $this->logger->warning('A not found error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_NOT_FOUND); + } } /** + * Create a column + * * @NoAdminRequired * @CORS * @NoCSRFRequired + * + * @param int|null $tableId Table ID + * @param int|null $viewId View ID + * @param string $title Title + * @param 'text'|'number'|'datetime'|'select' $type Column main type + * @param string|null $subtype Column sub type + * @param bool $mandatory Is the column mandatory + * @param string|null $description Description + * @param string|null $numberPrefix Prefix if the column is a number field + * @param string|null $numberSuffix Suffix if the column is a number field + * @param float|null $numberDefault Default number, if column is a number + * @param float|null $numberMin Min value, if column is a number + * @param float|null $numberMax Max number, if column is a number + * @param int|null $numberDecimals Number of decimals, if column is a number + * @param string|null $textDefault Default text, if column is a text + * @param string|null $textAllowedPattern Allowed pattern (regex) for text columns (not yet implemented) + * @param int|null $textMaxLength Max length, if column is a text + * @param string|null $selectionOptions Options for a selection (json array{id: int, label: string}) + * @param string|null $selectionDefault Default option IDs for a selection (json int[]) + * @param string|null $datetimeDefault Default value, if column is datetime + * @param int[]|null $selectedViewIds View IDs where this column should be added to be presented + * + * @return DataResponse|DataResponse + * + * 200: Column created + * 403: No permissions + * 404: Not found */ public function createColumn( ?int $tableId, @@ -286,7 +679,6 @@ public function createColumn( ?string $subtype, bool $mandatory, ?string $description, - ?string $numberPrefix, ?string $numberSuffix, ?float $numberDefault, @@ -304,33 +696,8 @@ public function createColumn( ?string $datetimeDefault = '', ?array $selectedViewIds = [] ): DataResponse { - return $this->handleError(function () use ( - $tableId, - $viewId, - $type, - $subtype, - $title, - $mandatory, - $description, - - $textDefault, - $textAllowedPattern, - $textMaxLength, - - $numberPrefix, - $numberSuffix, - $numberDefault, - $numberMin, - $numberMax, - $numberDecimals, - - $selectionOptions, - $selectionDefault, - - $datetimeDefault, - $selectedViewIds - ) { - return $this->columnService->create( + try { + return new DataResponse($this->columnService->create( $this->userId, $tableId, $viewId, @@ -356,14 +723,50 @@ public function createColumn( $datetimeDefault, $selectedViewIds - ); - }); + )->jsonSerialize()); + } catch (PermissionError $e) { + $this->logger->warning('A permission error occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_FORBIDDEN); + } catch (InternalError $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } catch (DoesNotExistException $e) { + $this->logger->warning('A not found error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_NOT_FOUND); + } } /** + * Update a column + * * @NoAdminRequired * @CORS * @NoCSRFRequired + * + * @param int $columnId Column ID that will be updated + * @param string|null $title Title + * @param string|null $subtype Column sub type + * @param bool $mandatory Is the column mandatory + * @param string|null $description Description + * @param string|null $numberPrefix Prefix if the column is a number field + * @param string|null $numberSuffix Suffix if the column is a number field + * @param float|null $numberDefault Default number, if column is a number + * @param float|null $numberMin Min value, if column is a number + * @param float|null $numberMax Max number, if column is a number + * @param int|null $numberDecimals Number of decimals, if column is a number + * @param string|null $textDefault Default text, if column is a text + * @param string|null $textAllowedPattern Allowed pattern (regex) for text columns (not yet implemented) + * @param int|null $textMaxLength Max length, if column is a text + * @param string|null $selectionOptions Options for a selection (json array{id: int, label: string}) + * @param string|null $selectionDefault Default option IDs for a selection (json int[]) + * @param string|null $datetimeDefault Default value, if column is datetime + * + * @return DataResponse|DataResponse + * + * 200: Updated column */ public function updateColumn( int $columnId, @@ -388,30 +791,8 @@ public function updateColumn( ?string $datetimeDefault ): DataResponse { - return $this->handleError(function () use ( - $columnId, - $title, - $subtype, - $mandatory, - $description, - - $textDefault, - $textAllowedPattern, - $textMaxLength, - - $numberPrefix, - $numberSuffix, - $numberDefault, - $numberMin, - $numberMax, - $numberDecimals, - - $selectionOptions, - $selectionDefault, - - $datetimeDefault - ) { - return $this->columnService->update( + try { + $item = $this->columnService->update( $columnId, null, $this->userId, @@ -436,70 +817,181 @@ public function updateColumn( $selectionDefault, $datetimeDefault ); - }); + return new DataResponse($item->jsonSerialize()); + } catch (InternalError $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } } /** + * Returns a column object + * * @NoAdminRequired * @CORS * @NoCSRFRequired + * + * @param int $columnId Wanted Column ID + * @return DataResponse|DataResponse + * + * 200: Column returned + * 403: No permissions + * 404: Not found */ public function getColumn(int $columnId): DataResponse { - return $this->handleError(function () use ($columnId) { - return $this->columnService->find($columnId); - }); + try { + return new DataResponse($this->columnService->find($columnId)->jsonSerialize()); + } catch (PermissionError $e) { + $this->logger->warning('A permission error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_FORBIDDEN); + } catch (NotFoundError $e) { + $this->logger->warning('A not found error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_NOT_FOUND); + } catch (InternalError|Exception $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } } /** + * Delete a column + * * @NoAdminRequired * @CORS * @NoCSRFRequired + * + * @param int $columnId Wanted Column ID + * @return DataResponse|DataResponse + * + * 200: Deleted column returned + * 403: No permissions + * 404: Not found */ public function deleteColumn(int $columnId): DataResponse { - return $this->handleError(function () use ($columnId) { - return $this->columnService->delete($columnId); - }); + try { + return new DataResponse($this->columnService->delete($columnId)->jsonSerialize()); + } catch (PermissionError $e) { + $this->logger->warning('A permission error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_FORBIDDEN); + } catch (NotFoundError $e) { + $this->logger->warning('A not found error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_NOT_FOUND); + } catch (InternalError|Exception $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } } /** + * List all rows values for a table, first row are the column titles + * * @NoAdminRequired * @CORS * @NoCSRFRequired + * + * @param int $tableId Table ID + * @param int|null $limit Limit + * @param int|null $offset Offset + * @return DataResponse|DataResponse + * + * 200: Row values returned + * 403: No permissions + * 404: Not found */ public function indexTableRowsSimple(int $tableId, ?int $limit, ?int $offset): DataResponse { - return $this->handleError(function () use ($tableId, $limit, $offset) { - return $this->v1Api->getData($tableId, $limit, $offset, $this->userId, 'table'); - }); + try { + return new DataResponse($this->v1Api->getData($tableId, $limit, $offset, $this->userId)); + } catch (PermissionError $e) { + $this->logger->warning('A permission error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_FORBIDDEN); + } catch (InternalError|Exception $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } } /** + * List all rows for a table + * * @NoAdminRequired * @CORS * @NoCSRFRequired + * + * @param int $tableId Table ID + * @param int|null $limit Limit + * @param int|null $offset Offset + * @return DataResponse|DataResponse + * + * 200: Rows returned + * 403: No permissions + * 404: Not found */ public function indexTableRows(int $tableId, ?int $limit, ?int $offset): DataResponse { - return $this->handleError(function () use ($tableId, $limit, $offset) { - return $this->rowService->findAllByTable($tableId, $this->userId, $limit, $offset); - }); + try { + return new DataResponse($this->rowService->findAllByTable($tableId, $this->userId, $limit, $offset)); + } catch (PermissionError $e) { + $this->logger->warning('A permission error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_FORBIDDEN); + } catch (InternalError|Exception $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } } /** + * List all rows for a view + * * @NoAdminRequired * @CORS * @NoCSRFRequired + * + * @param int $viewId View ID + * @param int|null $limit Limit + * @param int|null $offset Offset + * @return DataResponse|DataResponse + * + * 200: Rows returned + * 403: No permissions + * 404: Not found */ public function indexViewRows(int $viewId, ?int $limit, ?int $offset): DataResponse { - return $this->handleError(function () use ($viewId, $limit, $offset) { - return $this->rowService->findAllByView($viewId, $this->userId, $limit, $offset); - }); + try { + return new DataResponse($this->rowService->findAllByView($viewId, $this->userId, $limit, $offset)); + } catch (PermissionError $e) { + $this->logger->warning('A permission error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_FORBIDDEN); + } catch (InternalError|Exception $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } } /** + * Create a row within a view + * * @NoAdminRequired * @CORS * @NoCSRFRequired * - * @param array|string $data + * @param int $viewId View ID + * @param string|array{columnId: int, value: mixed} $data Data as key - value store + * @return DataResponse|DataResponse + * + * 200: Row returned + * 403: No permissions */ public function createRowInView(int $viewId, $data): DataResponse { if(is_string($data)) { @@ -519,17 +1011,33 @@ public function createRowInView(int $viewId, $data): DataResponse { ]; } - return $this->handleError(function () use ($viewId, $dataNew) { - return $this->rowService->create(null, $viewId, $dataNew); - }); + try { + return new DataResponse($this->rowService->create(null, $viewId, $dataNew)->jsonSerialize()); + } catch (PermissionError $e) { + $this->logger->warning('A permission error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_FORBIDDEN); + } catch (InternalError|Exception $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } } /** + * Create a row within a table + * * @NoAdminRequired * @CORS * @NoCSRFRequired * - * @param array|string $data + * @param int $tableId Table ID + * @param string|array{columnId: int, value: mixed} $data Data as key - value store + * @return DataResponse|DataResponse + * + * 200: Row returned + * 403: No permissions + * 404: Not found */ public function createRowInTable(int $tableId, $data): DataResponse { if(is_string($data)) { @@ -549,28 +1057,67 @@ public function createRowInTable(int $tableId, $data): DataResponse { ]; } - return $this->handleError(function () use ($tableId, $dataNew) { - return $this->rowService->create($tableId, null, $dataNew); - }); + try { + return new DataResponse($this->rowService->create($tableId, null, $dataNew)->jsonSerialize()); + } catch (PermissionError $e) { + $this->logger->warning('A permission error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_FORBIDDEN); + } catch (InternalError|Exception $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } } /** + * Get a row + * * @NoAdminRequired * @CORS * @NoCSRFRequired + * + * @param int $rowId Row ID + * @return DataResponse|DataResponse + * + * 200: Row returned + * 403: No permissions + * 404: Not found */ public function getRow(int $rowId): DataResponse { - return $this->handleError(function () use ($rowId) { - return $this->rowService->find($rowId); - }); + try { + return new DataResponse($this->rowService->find($rowId)->jsonSerialize()); + } catch (PermissionError $e) { + $this->logger->warning('A permission error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_FORBIDDEN); + } catch (InternalError $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } catch (NotFoundError $e) { + $this->logger->warning('A not found error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_NOT_FOUND); + } } /** + * Update a row + * * @NoAdminRequired * @CORS * @NoCSRFRequired * - * @param array|string $data + * @param int $rowId Row ID + * @param int|null $viewId View ID + * @param string|array{columnId: int, value: mixed} $data Data as key - value store + * + * @return DataResponse|DataResponse + * + * 200: Updated row returned + * 403: No permissions + * 404: Not found */ public function updateRow(int $rowId, ?int $viewId, $data): DataResponse { if(is_string($data)) { @@ -588,72 +1135,221 @@ public function updateRow(int $rowId, ?int $viewId, $data): DataResponse { 'value' => $value ]; } - return $this->handleError(function () use ($rowId, $viewId, $dataNew) { - return $this->rowService->updateSet($rowId, $viewId, $dataNew, $this->userId); - }); + + try { + return new DataResponse($this->rowService->updateSet($rowId, $viewId, $dataNew, $this->userId)->jsonSerialize()); + } catch (InternalError $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } } /** + * Delete a row + * * @NoAdminRequired * @CORS * @NoCSRFRequired + * + * @param int $rowId Row ID + * + * @return DataResponse|DataResponse + * + * 200: Deleted row returned + * 403: No permissions + * 404: Not found */ public function deleteRow(int $rowId): DataResponse { - return $this->handleError(function () use ($rowId) { - return $this->rowService->delete($rowId, null, $this->userId); - }); + try { + return new DataResponse($this->rowService->delete($rowId, null, $this->userId)->jsonSerialize()); + } catch (PermissionError $e) { + $this->logger->warning('A permission error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_FORBIDDEN); + } catch (InternalError $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } catch (NotFoundError $e) { + $this->logger->warning('A not found error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_NOT_FOUND); + } } /** + * Delete a row within a view + * * @NoAdminRequired * @CORS * @NoCSRFRequired + * + * @param int $rowId Row ID + * @param int $viewId View ID + * @return DataResponse|DataResponse + * + * 200: Deleted row returned + * 403: No permissions + * 404: Not found */ public function deleteRowByView(int $rowId, int $viewId): DataResponse { - return $this->handleError(function () use ($rowId, $viewId) { - return $this->rowService->delete($rowId, $viewId, $this->userId); - }); + try { + return new DataResponse($this->rowService->delete($rowId, $viewId, $this->userId)->jsonSerialize()); + } catch (PermissionError $e) { + $this->logger->warning('A permission error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_FORBIDDEN); + } catch (InternalError $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } catch (NotFoundError $e) { + $this->logger->warning('A not found error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_NOT_FOUND); + } } /** + * Import from file in to a table + * * @NoAdminRequired * @CORS * @NoCSRFRequired + * @param int $tableId Table ID + * @param string $path Path to file + * @param bool $createMissingColumns Create missing columns + * @return DataResponse|DataResponse + * + * 200: Import status returned + * 403: No permissions + * 404: Not found */ public function importInTable(int $tableId, string $path, bool $createMissingColumns = true): DataResponse { - return $this->handleError(function () use ($tableId, $path, $createMissingColumns) { - return $this->importService->import($tableId, null, $path, $createMissingColumns); - }); + try { + return new DataResponse($this->importService->import($tableId, null, $path, $createMissingColumns)); + } catch (PermissionError $e) { + $this->logger->warning('A permission error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_FORBIDDEN); + } catch (InternalError|MultipleObjectsReturnedException $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } catch (NotFoundError|DoesNotExistException $e) { + $this->logger->warning('A not found error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_NOT_FOUND); + } } /** + * Import from file in to a table + * * @NoAdminRequired * @CORS * @NoCSRFRequired + * @param int $viewId View ID + * @param string $path Path to file + * @param bool $createMissingColumns Create missing columns + * @return DataResponse|DataResponse + * + * 200: Import status returned + * 403: No permissions + * 404: Not found */ public function importInView(int $viewId, string $path, bool $createMissingColumns = true): DataResponse { - return $this->handleError(function () use ($viewId, $path, $createMissingColumns) { - return $this->importService->import(null, $viewId, $path, $createMissingColumns); - }); + try { + return new DataResponse($this->importService->import(null, $viewId, $path, $createMissingColumns)); + } catch (PermissionError $e) { + $this->logger->warning('A permission error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_FORBIDDEN); + } catch (InternalError|MultipleObjectsReturnedException $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } catch (NotFoundError|DoesNotExistException $e) { + $this->logger->warning('A not found error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_NOT_FOUND); + } } // Api Function for backward compatibility /** + * Create a share for a table + * * @NoAdminRequired * @CORS * @NoCSRFRequired + * + * @param int $tableId Table ID + * @param string $receiver Receiver ID + * @param 'user'|'group' $receiverType Receiver type + * @param bool $permissionRead Permission if receiver can read data + * @param bool $permissionCreate Permission if receiver can create data + * @param bool $permissionUpdate Permission if receiver can update data + * @param bool $permissionDelete Permission if receiver can delete data + * @param bool $permissionManage Permission if receiver can manage table + * @return DataResponse|DataResponse + * + * 200: View deleted + * 403: No permissions + * 404: Not found */ public function createTableShare(int $tableId, string $receiver, string $receiverType, bool $permissionRead, bool $permissionCreate, bool $permissionUpdate, bool $permissionDelete, bool $permissionManage): DataResponse { - return $this->handleError(function () use ($tableId, $receiver, $receiverType, $permissionRead, $permissionCreate, $permissionUpdate, $permissionDelete, $permissionManage) { - return $this->shareService->create($tableId, 'table', $receiver, $receiverType, $permissionRead, $permissionCreate, $permissionUpdate, $permissionDelete, $permissionManage); - }); + try { + return new DataResponse($this->shareService->create($tableId, 'table', $receiver, $receiverType, $permissionRead, $permissionCreate, $permissionUpdate, $permissionDelete, $permissionManage)->jsonSerialize()); + } catch (PermissionError $e) { + $this->logger->warning('A permission error occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_FORBIDDEN); + } catch (InternalError $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } catch (NotFoundError $e) { + $this->logger->warning('A not found error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_NOT_FOUND); + } } /** + * Create a new column for a table + * * @NoAdminRequired * @CORS * @NoCSRFRequired + * + * @param int $tableId Table ID + * @param string $title Title + * @param 'text'|'number'|'datetime'|'select' $type Column main type + * @param string|null $subtype Column sub type + * @param bool $mandatory Is the column mandatory + * @param string|null $description Description + * @param string|null $numberPrefix Prefix if the column is a number field + * @param string|null $numberSuffix Suffix if the column is a number field + * @param float|null $numberDefault Default number, if column is a number + * @param float|null $numberMin Min value, if column is a number + * @param float|null $numberMax Max number, if column is a number + * @param int|null $numberDecimals Number of decimals, if column is a number + * @param string|null $textDefault Default text, if column is a text + * @param string|null $textAllowedPattern Allowed pattern (regex) for text columns (not yet implemented) + * @param int|null $textMaxLength Max length, if column is a text + * @param string|null $selectionOptions Options for a selection (json array{id: int, label: string}) + * @param string|null $selectionDefault Default option IDs for a selection (json int[]) + * @param string|null $datetimeDefault Default value, if column is datetime + * @param int[]|null $selectedViewIds View IDs where this column should be added to be presented + * + * @return DataResponse|DataResponse + * + * 200: Column created + * 403: No permissions + * 404: Not found */ public function createTableColumn( int $tableId, @@ -680,32 +1376,8 @@ public function createTableColumn( ?string $datetimeDefault = '', ?array $selectedViewIds = [] ): DataResponse { - return $this->handleError(function () use ( - $tableId, - $type, - $subtype, - $title, - $mandatory, - $description, - - $textDefault, - $textAllowedPattern, - $textMaxLength, - - $numberPrefix, - $numberSuffix, - $numberDefault, - $numberMin, - $numberMax, - $numberDecimals, - - $selectionOptions, - $selectionDefault, - - $datetimeDefault, - $selectedViewIds - ) { - return $this->columnService->create( + try { + $item = $this->columnService->create( $this->userId, $tableId, null, @@ -732,6 +1404,22 @@ public function createTableColumn( $datetimeDefault, $selectedViewIds ); - }); + return new DataResponse($item->jsonSerialize()); + } catch (PermissionError $e) { + $this->logger->warning('A permission error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_FORBIDDEN); + } catch (InternalError $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } catch (DoesNotExistException $e) { + $this->logger->warning('A not found error occurred: ' . $e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_NOT_FOUND); + } + + + } } diff --git a/lib/Controller/ApiColumnsController.php b/lib/Controller/ApiColumnsController.php new file mode 100644 index 000000000..8792af687 --- /dev/null +++ b/lib/Controller/ApiColumnsController.php @@ -0,0 +1,309 @@ +service = $service; + } + + /** + * [api v2] Get all columns for a table or a view + * + * Return an empty array if no columns were found + * + * @NoAdminRequired + * + * @param int $nodeId Node ID + * @param 'table'|'view' $nodeType Node type + * @return DataResponse|DataResponse + * + * 200: View deleted + * 403: No permissions + * 404: Not found + */ + public function index(int $nodeId, string $nodeType): DataResponse { + try { + if($nodeType === 'table') { + $columns = $this->service->findAllByTable($nodeId); + } elseif ($nodeType === 'view') { + $columns = $this->service->findAllByView($nodeId); + } else { + $columns = null; + } + return new DataResponse($this->service->formatColumns($columns)); + } catch (PermissionError $e) { + return $this->handlePermissionError($e); + } catch (InternalError $e) { + return $this->handleError($e); + } catch (NotFoundError $e) { + return $this->handleNotFoundError($e); + } + } + + /** + * [api v2] Get a column object + * + * @NoAdminRequired + * + * @param int $id Column ID + * @return DataResponse|DataResponse + * + * 200: Column returned + * 403: No permissions + * 404: Not found + */ + public function show(int $id): DataResponse { + try { + return new DataResponse($this->service->find($id)->jsonSerialize()); + } catch (PermissionError $e) { + return $this->handlePermissionError($e); + } catch (InternalError $e) { + return $this->handleError($e); + } catch (NotFoundError $e) { + return $this->handleNotFoundError($e); + } + } + + /** + * [api v2] Create new numbered column + * + * Specify a subtype to use any special numbered column + * + * @NoAdminRequired + * + * @param int $baseNodeId Context of the column creation + * @param string $title Title + * @param boolean $mandatory Is mandatory + * @param 'table'|'view' $baseNodeType Context type of the column creation + * @param float|null $numberDefault Default value for new rows + * @param int|null $numberDecimals Decimals + * @param string|null $numberPrefix Prefix + * @param string|null $numberSuffix Suffix + * @param float|null $numberMin Min + * @param float|null $numberMax Max + * @param 'progress'|'stars'|null $subtype Subtype for the new column + * @param string|null $description Description + * @param int[]|null $selectedViewIds View IDs where this columns should be added + * @return DataResponse|DataResponse + * + * 200: Column created + * 403: No permission + * 404: Not found + * @throws InternalError + * @throws NotFoundError + * @throws PermissionError + */ + public function createNumberColumn(int $baseNodeId, string $title, ?float $numberDefault, ?int $numberDecimals, ?string $numberPrefix, ?string $numberSuffix, ?float $numberMin, ?float $numberMax, string $subtype = null, string $description = null, ?array $selectedViewIds = null, bool $mandatory = false, string $baseNodeType = 'table'): DataResponse { + $tableId = $baseNodeType === 'table' ? $baseNodeId : null; + $viewId = $baseNodeType === 'view' ? $baseNodeId : null; + $column = $this->service->create( + $this->userId, + $tableId, + $viewId, + 'number', + $subtype, + $title, + $mandatory, + $description, + null, + null, + null, + $numberPrefix, + $numberSuffix, + $numberDefault, + $numberMin, + $numberMax, + $numberDecimals, + null, + null, + null, + $selectedViewIds + ); + return new DataResponse($column->jsonSerialize()); + } + + /** + * [api v2] Create new text column + * + * Specify a subtype to use any special text column + * + * @NoAdminRequired + * + * @param int $baseNodeId Context of the column creation + * @param string $title Title + * @param string|null $textDefault Default + * @param string|null $textAllowedPattern Allowed regex pattern + * @param int|null $textMaxLength Max raw text length + * @param 'progress'|'stars'|null $subtype Subtype for the new column + * @param string|null $description Description + * @param int[]|null $selectedViewIds View IDs where this columns should be added + * @param boolean $mandatory Is mandatory + * @param 'table'|'view' $baseNodeType Context type of the column creation + * @return DataResponse|DataResponse + * + * 200: Column created + * 403: No permission + * 404: Not found + * @throws InternalError + * @throws NotFoundError + * @throws PermissionError + */ + public function createTextColumn(int $baseNodeId, string $title, ?string $textDefault, ?string $textAllowedPattern, ?int $textMaxLength, string $subtype = null, string $description = null, ?array $selectedViewIds = null, bool $mandatory = false, string $baseNodeType = 'table'): DataResponse { + $tableId = $baseNodeType === 'table' ? $baseNodeId : null; + $viewId = $baseNodeType === 'view' ? $baseNodeId : null; + $column = $this->service->create( + $this->userId, + $tableId, + $viewId, + 'text', + $subtype, + $title, + $mandatory, + $description, + $textDefault, + $textAllowedPattern, + $textMaxLength, + null, + null, + null, + null, + null, + null, + null, + null, + null, + $selectedViewIds + ); + return new DataResponse($column->jsonSerialize()); + } + + /** + * [api v2] Create new selection column + * + * Specify a subtype to use any special selection column + * + * @NoAdminRequired + * + * @param int $baseNodeId Context of the column creation + * @param string $title Title + * @param string $selectionOptions Json array{id: int, label: string} with options that can be selected, eg [{"id": 1, "label": "first"},{"id": 2, "label": "second"}] + * @param string|null $selectionDefault Json int|int[] for default selected option(s), eg 5 or ["1", "8"] + * @param 'progress'|'stars'|null $subtype Subtype for the new column + * @param string|null $description Description + * @param int[]|null $selectedViewIds View IDs where this columns should be added + * @param boolean $mandatory Is mandatory + * @param 'table'|'view' $baseNodeType Context type of the column creation + * @return DataResponse|DataResponse + * + * 200: Column created + * 403: No permission + * 404: Not found + * @throws InternalError + * @throws NotFoundError + * @throws PermissionError + */ + public function createSelectionColumn(int $baseNodeId, string $title, string $selectionOptions, ?string $selectionDefault, string $subtype = null, string $description = null, ?array $selectedViewIds = [], bool $mandatory = false, string $baseNodeType = 'table'): DataResponse { + $tableId = $baseNodeType === 'table' ? $baseNodeId : null; + $viewId = $baseNodeType === 'view' ? $baseNodeId : null; + $column = $this->service->create( + $this->userId, + $tableId, + $viewId, + 'selection', + $subtype, + $title, + $mandatory, + $description, + null, + null, + null, + null, + null, + null, + null, + null, + null, + $selectionOptions, + $selectionDefault, + null, + $selectedViewIds + ); + return new DataResponse($column->jsonSerialize()); + } + + /** + * [api v2] Create new datetime column + * + * Specify a subtype to use any special datetime column + * + * @NoAdminRequired + * + * @param int $baseNodeId Context of the column creation + * @param string $title Title + * @param 'today'|'now'|null $datetimeDefault For a subtype 'date' you can set 'today'. For a main type or subtype 'time' you can set to 'now'. + * @param 'progress'|'stars'|null $subtype Subtype for the new column + * @param string|null $description Description + * @param int[]|null $selectedViewIds View IDs where this columns should be added + * @param boolean $mandatory Is mandatory + * @param 'table'|'view' $baseNodeType Context type of the column creation + * @return DataResponse|DataResponse + * + * 200: Column created + * 403: No permission + * 404: Not found + * @throws InternalError + * @throws NotFoundError + * @throws PermissionError + */ + public function createDatetimeColumn(int $baseNodeId, string $title, ?string $datetimeDefault, string $subtype = null, string $description = null, ?array $selectedViewIds = null, bool $mandatory = false, string $baseNodeType = 'table'): DataResponse { + $tableId = $baseNodeType === 'table' ? $baseNodeId : null; + $viewId = $baseNodeType === 'view' ? $baseNodeId : null; + $column = $this->service->create( + $this->userId, + $tableId, + $viewId, + 'text', + $subtype, + $title, + $mandatory, + $description, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + $datetimeDefault, + $selectedViewIds + ); + return new DataResponse($column->jsonSerialize()); + } +} diff --git a/lib/Controller/ApiGeneralController.php b/lib/Controller/ApiGeneralController.php new file mode 100644 index 000000000..cd782a258 --- /dev/null +++ b/lib/Controller/ApiGeneralController.php @@ -0,0 +1,61 @@ +tableService = $tableService; + $this->viewService = $viewService; + } + + + /** + * [api v2] Returns all main resources + * + * Tables and views incl. shares + * + * @NoAdminRequired + * + * @return DataResponse|DataResponse + * + * 200: Index returned + */ + public function index(): DataResponse { + try { + $tables = $this->tableService->formatTables($this->tableService->findAll($this->userId)); + $views = $this->viewService->formatViews($this->viewService->findSharedViewsWithMe($this->userId)); + return new DataResponse([ 'tables' => $tables, 'views' => $views ]); + } catch (InternalError|Exception $e) { + $this->logger->warning('An internal error or exception occurred: '.$e->getMessage()); + $message = ['message' => $e->getMessage()]; + return new DataResponse($message, Http::STATUS_INTERNAL_SERVER_ERROR); + } + } +} diff --git a/lib/Controller/ApiTablesController.php b/lib/Controller/ApiTablesController.php new file mode 100644 index 000000000..366935814 --- /dev/null +++ b/lib/Controller/ApiTablesController.php @@ -0,0 +1,144 @@ +service = $service; + } + + /** + * [api v2] Returns all Tables + * + * @NoAdminRequired + * + * @return DataResponse|DataResponse + * + * 200: Tables returned + */ + public function index(): DataResponse { + try { + return new DataResponse($this->service->formatTables($this->service->findAll($this->userId))); + } catch (InternalError|Exception $e) { + return $this->handleError($e); + } + } + + /** + * [api v2] Get a table object + * + * @NoAdminRequired + * + * @param int $id Table ID + * @return DataResponse|DataResponse + * + * 200: Table returned + * 403: No permissions + * 404: Not found + */ + public function show(int $id): DataResponse { + try { + return new DataResponse($this->service->find($id)->jsonSerialize()); + } catch (PermissionError $e) { + return $this->handlePermissionError($e); + } catch (InternalError $e) { + return $this->handleError($e); + } catch (NotFoundError $e) { + return $this->handleNotFoundError($e); + } + } + + /** + * [api v2] Create a new table and return it + * + * @NoAdminRequired + * + * @param string $title Title of the table + * @param string|null $emoji Emoji for the table + * @param string $template Template to use if wanted + * + * @return DataResponse|DataResponse + * + * 200: Tables returned + */ + public function create(string $title, ?string $emoji, string $template = 'custom'): DataResponse { + try { + return new DataResponse($this->service->create($title, $template, $emoji)->jsonSerialize()); + } catch (InternalError|Exception $e) { + return $this->handleError($e); + } + } + + /** + * [api v2] Update tables properties + * + * @NoAdminRequired + * + * @param int $id Table ID + * @param string|null $title New table title + * @param string|null $emoji New table emoji + * @return DataResponse|DataResponse + * + * 200: Tables returned + * 403: No permissions + * 404: Not found + */ + public function update(int $id, string $title = null, string $emoji = null): DataResponse { + try { + return new DataResponse($this->service->update($id, $title, $emoji, $this->userId)->jsonSerialize()); + } catch (PermissionError $e) { + return $this->handlePermissionError($e); + } catch (InternalError $e) { + return $this->handleError($e); + } catch (NotFoundError $e) { + return $this->handleNotFoundError($e); + } + } + + /** + * [api v2] Delete a table + * + * @NoAdminRequired + * + * @param int $id Table ID + * @return DataResponse|DataResponse + * + * 200: Deleted table returned + * 403: No permissions + * 404: Not found + */ + public function destroy(int $id): DataResponse { + try { + return new DataResponse($this->service->delete($id)->jsonSerialize()); + } catch (PermissionError $e) { + return $this->handlePermissionError($e); + } catch (InternalError $e) { + return $this->handleError($e); + } catch (NotFoundError $e) { + return $this->handleNotFoundError($e); + } + } +} diff --git a/lib/Controller/PageController.php b/lib/Controller/PageController.php index b73916044..3af24e2bb 100644 --- a/lib/Controller/PageController.php +++ b/lib/Controller/PageController.php @@ -21,6 +21,7 @@ public function __construct(IRequest $request, IEventDispatcher $eventDispatcher /** * @NoAdminRequired * @NoCSRFRequired + * @IgnoreOpenAPI * * Render default template */ diff --git a/lib/Db/Column.php b/lib/Db/Column.php index ba75d874c..d54df2d4c 100644 --- a/lib/Db/Column.php +++ b/lib/Db/Column.php @@ -4,10 +4,14 @@ use JsonSerializable; +use OCA\Tables\ResponseDefinitions; use OCP\AppFramework\Db\Entity; /** * @psalm-suppress PropertyNotSetInConstructor + * + * @psalm-import-type TablesColumn from ResponseDefinitions + * * @method getTitle(): string * @method setTitle(string $title) * @method getTableId(): int @@ -115,6 +119,9 @@ public function setSelectionOptionsArray(array $array):void { $this->setSelectionOptions($json); } + /** + * @psalm-return TablesColumn + */ public function jsonSerialize(): array { return [ 'id' => $this->id, diff --git a/lib/Db/Share.php b/lib/Db/Share.php index 1216a6b2f..a106ef23f 100644 --- a/lib/Db/Share.php +++ b/lib/Db/Share.php @@ -4,10 +4,14 @@ use JsonSerializable; +use OCA\Tables\ResponseDefinitions; use OCP\AppFramework\Db\Entity; /** + * @psalm-import-type TablesShare from ResponseDefinitions + * * @psalm-suppress PropertyNotSetInConstructor + * * @method getSender(): string * @method setSender(string $sender) * @method getReceiver(): string @@ -63,6 +67,9 @@ public function __construct() { $this->addType('permissionManage', 'boolean'); } + /** + * @psalm-return TablesShare + */ public function jsonSerialize(): array { return [ 'id' => $this->id, diff --git a/lib/Db/ShareMapper.php b/lib/Db/ShareMapper.php index b4c1267de..1a2beb8a5 100644 --- a/lib/Db/ShareMapper.php +++ b/lib/Db/ShareMapper.php @@ -101,6 +101,7 @@ public function findAllSharesFor(string $nodeType, string $receiver, string $use * @throws Exception */ public function findAllSharesForNode(string $nodeType, int $nodeId, string $sender): array { + // TODO filter for sender... $qb = $this->db->getQueryBuilder(); $qb->select('*') ->from($this->table) diff --git a/lib/Db/Table.php b/lib/Db/Table.php index 867c477ac..df74ed56c 100644 --- a/lib/Db/Table.php +++ b/lib/Db/Table.php @@ -3,11 +3,14 @@ namespace OCA\Tables\Db; use JsonSerializable; +use OCA\Tables\ResponseDefinitions; use OCP\AppFramework\Db\Entity; /** * @psalm-suppress PropertyNotSetInConstructor * + * @psalm-import-type TablesTable from ResponseDefinitions + * * @method getTitle(): string * @method setTitle(string $title) * @method getEmoji(): string @@ -61,6 +64,9 @@ public function __construct() { $this->addType('id', 'integer'); } + /** + * @psalm-return TablesTable + */ public function jsonSerialize(): array { return [ 'id' => $this->id, diff --git a/lib/Db/View.php b/lib/Db/View.php index e2eff3dd6..9c10fc38d 100644 --- a/lib/Db/View.php +++ b/lib/Db/View.php @@ -4,10 +4,14 @@ use JsonSerializable; +use OCA\Tables\ResponseDefinitions; use OCP\AppFramework\Db\Entity; /** * @psalm-suppress PropertyNotSetInConstructor + * + * @psalm-import-type TablesView from ResponseDefinitions + * * @method getTitle(): string * @method setTitle(string $title) * @method getTableId(): int @@ -94,6 +98,9 @@ public function setFilterArray(array $array):void { $this->setFilter(\json_encode($array)); } + /** + * @psalm-return TablesView + */ public function jsonSerialize(): array { $serialisedJson = [ 'id' => $this->id, diff --git a/lib/ResponseDefinitions.php b/lib/ResponseDefinitions.php new file mode 100644 index 000000000..132bba2c6 --- /dev/null +++ b/lib/ResponseDefinitions.php @@ -0,0 +1,129 @@ +permissionsService->canReadColumnsByTableId($tableId, $userId) || ($viewId != null && $this->permissionsService->canReadColumnsByViewId($viewId, $userId))) { + if ($this->permissionsService->canReadColumnsByTableId($tableId, $userId) || ($viewId != null && $this->permissionsService->canReadColumnsByViewId($viewId, $userId))) { + try { return $this->mapper->findAllByTable($tableId); - } else { - throw new PermissionError('no read access to table id = '.$tableId); + } catch (\OCP\DB\Exception $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new InternalError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); } - } catch (\OCP\DB\Exception $e) { - $this->logger->error($e->getMessage()); - throw new InternalError($e->getMessage()); + } else { + throw new PermissionError('no read access to table id = '.$tableId); } } @@ -67,39 +71,50 @@ public function findAllByTable(int $tableId, ?int $viewId = null, ?string $userI * @param int $viewId * @param string|null $userId * @return array - * @throws DoesNotExistException - * @throws InternalError - * @throws MultipleObjectsReturnedException * @throws NotFoundError * @throws PermissionError + * @throws InternalError */ public function findAllByView(int $viewId, ?string $userId = null): array { + // No need to check for columns outside the view since they cannot be addressed try { - // No need to check for columns outside the view since they cannot be addressed $view = $this->viewService->find($viewId, true, $userId); - $viewColumnIds = $view->getColumnsArray(); - $viewColumns = []; - foreach ($viewColumnIds as $viewColumnId) { - if ($viewColumnId < 0) { - continue; - } - try { - $viewColumns[] = $this->mapper->find($viewColumnId); - } catch (DoesNotExistException $e) { - $this->logger->warning($e->getMessage()); - throw new NotFoundError($e->getMessage()); - } catch (MultipleObjectsReturnedException $e) { - $this->logger->error($e->getMessage()); - throw new InternalError($e->getMessage()); - } + } catch (InternalError|MultipleObjectsReturnedException $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new InternalError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } catch (PermissionError $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new PermissionError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } catch (DoesNotExistException $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new NotFoundError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } + $viewColumnIds = $view->getColumnsArray(); + $viewColumns = []; + foreach ($viewColumnIds as $viewColumnId) { + if ($viewColumnId < 0) { + continue; + } + try { + $viewColumns[] = $this->mapper->find($viewColumnId); + } catch (DoesNotExistException $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new NotFoundError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } catch (MultipleObjectsReturnedException|\OCP\DB\Exception $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new InternalError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); } - return $viewColumns; - } catch (\OCP\DB\Exception $e) { - $this->logger->error($e->getMessage()); - throw new InternalError($e->getMessage()); } + return $viewColumns; } + /** + * @param Column[] $columns + * @return TablesColumn[] + */ + public function formatColumns(array $columns): array { + return array_map(fn (Column $item) => $item->jsonSerialize(), $columns); + } /** * @throws NotFoundError @@ -129,7 +144,8 @@ public function find(int $id, string $userId = null): Column { * @noinspection DuplicatedCode * * @param string|null $userId - * @param int $viewId + * @param int|null $tableId + * @param int|null $viewId * @param string $type * @param string|null $subtype * @param string $title @@ -150,11 +166,8 @@ public function find(int $id, string $userId = null): Column { * @param array|null $selectedViewIds * @return Column * - * @throws DoesNotExistException * @throws InternalError - * @throws MultipleObjectsReturnedException - * @throws PermissionError - * @throws \OCP\DB\Exception + * @throws PermissionError|NotFoundError */ public function create( ?string $userId, @@ -181,20 +194,46 @@ public function create( ?string $selectionDefault, ?string $datetimeDefault, - ?array $selectedViewIds + ?array $selectedViewIds = [] ):Column { // security if ($viewId) { - $view = $this->viewService->find($viewId); - $table = $this->tableMapper->find($view->getTableId()); + try { + $view = $this->viewService->find($viewId); + } catch (InternalError|MultipleObjectsReturnedException $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new InternalError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } catch (PermissionError $e) { + throw new PermissionError('Can not load given view, no permission.'); + } catch (DoesNotExistException $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new NotFoundError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } + try { + $table = $this->tableMapper->find($view->getTableId()); + } catch (DoesNotExistException $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new NotFoundError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } catch (MultipleObjectsReturnedException|\OCP\DB\Exception $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new InternalError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } } elseif ($tableId) { - $table = $this->tableMapper->find($tableId); + try { + $table = $this->tableMapper->find($tableId); + } catch (DoesNotExistException $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new NotFoundError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } catch (MultipleObjectsReturnedException|\OCP\DB\Exception $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new InternalError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } } else { - throw new InternalError('Cannot update row without table or view in context'); + throw new InternalError('Cannot create column without table or view in context'); } if (!$this->permissionsService->canCreateColumns($table)) { - throw new PermissionError('create column at the table id = '.$table->getId().' is not allowed.'); + throw new PermissionError('create column for the table id = '.$table->getId().' is not allowed.'); } $time = new DateTime(); @@ -221,21 +260,32 @@ public function create( $item->setSelectionOptions($selectionOptions); $item->setSelectionDefault($selectionDefault); $item->setDatetimeDefault($datetimeDefault); + try { $entity = $this->mapper->insert($item); - if($viewId) { - // Add columns to view(s) - $this->viewService->update($view->getId(), ['columns' => json_encode(array_merge($view->getColumnsArray(), [$entity->getId()]))], $userId, true); - } - foreach ($selectedViewIds as $viewId) { + } catch (\OCP\DB\Exception $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new InternalError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } + if($viewId) { + // Add columns to view(s) + $this->viewService->update($view->getId(), ['columns' => json_encode(array_merge($view->getColumnsArray(), [$entity->getId()]))], $userId, true); + } + foreach ($selectedViewIds as $viewId) { + try { $view = $this->viewService->find($viewId); - $this->viewService->update($viewId, ['columns' => json_encode(array_merge($view->getColumnsArray(), [$entity->getId()]))], $userId, true); + } catch (InternalError|MultipleObjectsReturnedException $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new InternalError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } catch (PermissionError $e) { + throw new PermissionError('Can not add column to view, no permission.'); + } catch (DoesNotExistException $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new NotFoundError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); } - return $entity; - } catch (\OCP\DB\Exception $e) { - $this->logger->error($e->getMessage()); - throw new InternalError($e->getMessage()); + $this->viewService->update($viewId, ['columns' => json_encode(array_merge($view->getColumnsArray(), [$entity->getId()]))], $userId, true); } + return $entity; } /** @@ -367,28 +417,48 @@ public function update( * @param null|string $userId * @return Column * @throws InternalError + * @throws NotFoundError + * @throws PermissionError */ public function delete(int $id, bool $skipRowCleanup = false, ?string $userId = null): Column { try { $item = $this->mapper->find($id); + } catch (DoesNotExistException $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new NotFoundError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } catch (MultipleObjectsReturnedException|\OCP\DB\Exception $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new InternalError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } - // security - if (!$this->permissionsService->canDeleteColumnsByTableId($item->getTableId(), $userId)) { - throw new PermissionError('delete column id = '.$id.' is not allowed.'); - } + // security + if (!$this->permissionsService->canDeleteColumnsByTableId($item->getTableId(), $userId)) { + throw new PermissionError('delete column id = '.$id.' is not allowed.'); + } - if (!$skipRowCleanup) { + if (!$skipRowCleanup) { + try { $this->rowService->deleteColumnDataFromRows($id); + } catch (PermissionError|\OCP\DB\Exception $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new InternalError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } + try { $table = $this->tableMapper->find($item->getTableId()); - $this->viewService->deleteColumnDataFromViews($id, $table); + } catch (DoesNotExistException|MultipleObjectsReturnedException|\OCP\DB\Exception $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new InternalError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); } + $this->viewService->deleteColumnDataFromViews($id, $table); + } + try { $this->mapper->delete($item); - return $item; - } catch (Exception $e) { - $this->logger->error($e->getMessage()); - throw new InternalError($e->getMessage()); + } catch (\OCP\DB\Exception $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new InternalError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); } + return $item; } /** @@ -402,10 +472,8 @@ public function delete(int $id, bool $skipRowCleanup = false, ?string $userId = * @return array with column object or null for given columns * @throws DoesNotExistException * @throws InternalError - * @throws MultipleObjectsReturnedException * @throws NotFoundError * @throws PermissionError - * @throws \OCP\DB\Exception */ public function findOrCreateColumnsByTitleForTableAsArray(?int $tableId, ?int $viewId, array $titles, ?string $userId, bool $createUnknownColumns, int &$countCreatedColumns, int &$countMatchingColumns): array { $result = []; diff --git a/lib/Service/PermissionsService.php b/lib/Service/PermissionsService.php index 5399ec8af..0670db951 100644 --- a/lib/Service/PermissionsService.php +++ b/lib/Service/PermissionsService.php @@ -43,6 +43,10 @@ public function __construct(LoggerInterface $logger, ?string $userId, TableMappe /** + * @param string|null $userId + * @param bool $canBeEmpty + * @return string + * * @throws InternalError */ public function preCheckUserId(string $userId = null, bool $canBeEmpty = true): string { diff --git a/lib/Service/ShareService.php b/lib/Service/ShareService.php index d10a91b5c..f9fb2c700 100644 --- a/lib/Service/ShareService.php +++ b/lib/Service/ShareService.php @@ -1,9 +1,10 @@ $item->jsonSerialize(), $items); + } /** * @param int $id @@ -178,6 +190,9 @@ public function getSharedPermissionsIfSharedWithMe(int $elementId, ?string $elem * @throws InternalError */ public function create(int $nodeId, string $nodeType, string $receiver, string $receiverType, bool $permissionRead, bool $permissionCreate, bool $permissionUpdate, bool $permissionDelete, bool $permissionManage):Share { + // TODO Do we need to check if create is allowed for requested nodeId?! + // should also return not found if share_node could not be found + // should also return no permission if sender don't have permission to create a share for node $time = new DateTime(); $item = new Share(); $item->setSender($this->userId); @@ -207,68 +222,88 @@ public function create(int $nodeId, string $nodeType, string $receiver, string $ * @param bool $value * @return Share * @throws InternalError + * @throws NotFoundError + * @throws PermissionError */ public function updatePermission(int $id, string $permission, bool $value): Share { try { $item = $this->mapper->find($id); + } catch (DoesNotExistException $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new NotFoundError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } catch (MultipleObjectsReturnedException|\OCP\DB\Exception $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new InternalError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } - // security - if (!$this->permissionsService->canManageElementById($item->getNodeId(), $item->getNodeType())) { - throw new PermissionError('PermissionError: can not update share with id '.$id); - } + // security + if (!$this->permissionsService->canManageElementById($item->getNodeId(), $item->getNodeType())) { + throw new PermissionError('PermissionError: can not update share with id '.$id); + } - $time = new DateTime(); + $time = new DateTime(); - if ($permission === "read") { - $item->setPermissionRead($value); - } + if ($permission === "read") { + $item->setPermissionRead($value); + } - if ($permission === "create") { - $item->setPermissionCreate($value); - } + if ($permission === "create") { + $item->setPermissionCreate($value); + } - if ($permission === "update") { - $item->setPermissionUpdate($value); - } + if ($permission === "update") { + $item->setPermissionUpdate($value); + } - if ($permission === "delete") { - $item->setPermissionDelete($value); - } + if ($permission === "delete") { + $item->setPermissionDelete($value); + } - if ($permission === "manage") { - $item->setPermissionManage($value); - } + if ($permission === "manage") { + $item->setPermissionManage($value); + } - $item->setLastEditAt($time->format('Y-m-d H:i:s')); + $item->setLastEditAt($time->format('Y-m-d H:i:s')); + try { $share = $this->mapper->update($item); - return $this->addReceiverDisplayName($share); - } catch (Exception $e) { - $this->logger->error($e->getMessage()); - throw new InternalError($e->getMessage()); + } catch (\OCP\DB\Exception $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new InternalError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); } + return $this->addReceiverDisplayName($share); } /** * @param int $id * @return Share * @throws InternalError + * @throws NotFoundError + * @throws PermissionError */ public function delete(int $id): Share { try { $item = $this->mapper->find($id); + } catch (DoesNotExistException $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new NotFoundError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } catch (MultipleObjectsReturnedException|\OCP\DB\Exception $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new InternalError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } - // security + // security if (!$this->permissionsService->canManageElementById($item->getNodeId(), $item->getNodeType())) { throw new PermissionError('PermissionError: can not delete share with id '.$id); } + try { $this->mapper->delete($item); - return $this->addReceiverDisplayName($item); - } catch (Exception $e) { - $this->logger->error($e->getMessage()); - throw new InternalError($e->getMessage()); + } catch (\OCP\DB\Exception $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new InternalError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); } + return $this->addReceiverDisplayName($item); } /** diff --git a/lib/Service/TableService.php b/lib/Service/TableService.php index 01cbbbf60..3f5e8df9e 100644 --- a/lib/Service/TableService.php +++ b/lib/Service/TableService.php @@ -1,5 +1,7 @@ - * @throws DoesNotExistException * @throws InternalError - * @throws MultipleObjectsReturnedException - * @throws NotFoundError - * @throws PermissionError */ public function findAll(?string $userId = null, bool $skipTableEnhancement = false, bool $skipSharedTables = false, bool $createTutorial = true): array { /** @var string $userId */ $userId = $this->permissionsService->preCheckUserId($userId); // $userId can be set or '' - $allTables = []; try { $allTables = $this->mapper->findAll($userId); // get own tables + } catch (OcpDbException $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new InternalError($e->getMessage()); + } - // if there are no own tables found, create the tutorial table - if (count($allTables) === 0 && $createTutorial) { + // if there are no own tables found, create the tutorial table + if (count($allTables) === 0 && $createTutorial) { + try { $allTables = [$this->create($this->l->t('Tutorial'), 'tutorial', '🚀')]; + } catch (InternalError|PermissionError|DoesNotExistException|MultipleObjectsReturnedException|OcpDbException $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new InternalError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); } + } - if (!$skipSharedTables && $userId !== '') { - $sharedTables = $this->shareService->findTablesSharedWithMe($userId); - - // clean duplicates - foreach ($sharedTables as $sharedTable) { - $found = false; - foreach ($allTables as $table) { - if ($sharedTable->getId() === $table->getId()) { - $found = true; - break; - } - } - if (!$found) { - $allTables[] = $sharedTable; + if (!$skipSharedTables && $userId !== '') { + $sharedTables = $this->shareService->findTablesSharedWithMe($userId); + + // clean duplicates + foreach ($sharedTables as $sharedTable) { + $found = false; + foreach ($allTables as $table) { + if ($sharedTable->getId() === $table->getId()) { + $found = true; + break; } } + if (!$found) { + $allTables[] = $sharedTable; + } } - } catch (\OCP\DB\Exception|InternalError $e) { - $this->logger->error($e->getMessage(), ['exception' => $e]); - throw new InternalError($e->getMessage()); - } catch (PermissionError $e) { - $this->logger->debug('permission error during looking for tables', ['exception' => $e]); } // enhance table objects with additional data if (!$skipTableEnhancement) { foreach ($allTables as $table) { /** @var string $userId */ - $this->enhanceTable($table, $userId); + try { + $this->enhanceTable($table, $userId); + } catch (InternalError|PermissionError $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new InternalError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } // if the table is shared with me, there are no other shares // will avoid showing the shared icon in the FE nav if($table->getIsShared()) { @@ -129,6 +139,14 @@ public function findAll(?string $userId = null, bool $skipTableEnhancement = fal return $allTables; } + /** + * @param Table[] $tables + * @return TablesTable[] + */ + public function formatTables(array $tables): array { + return array_map(fn (Table $table) => $table->jsonSerialize(), $tables); + } + /** * add some basic values related to this table in context * @@ -155,14 +173,14 @@ private function enhanceTable(Table $table, string $userId): void { // add the rows count try { $table->setRowsCount($this->rowService->getRowsCount($table->getId())); - } catch (InternalError|PermissionError $e) { + } catch (PermissionError $e) { $table->setRowsCount(0); } // add the column count try { $table->setColumnsCount($this->columnService->getColumnsCount($table->getId())); - } catch (InternalError|PermissionError $e) { + } catch (PermissionError $e) { $table->setColumnsCount(0); } @@ -213,7 +231,7 @@ public function find(int $id, bool $skipTableEnhancement = false, ?string $userI } catch (DoesNotExistException $e) { $this->logger->warning($e->getMessage()); throw new NotFoundError($e->getMessage()); - } catch (MultipleObjectsReturnedException|\OCP\DB\Exception $e) { + } catch (MultipleObjectsReturnedException|OcpDbException $e) { $this->logger->error($e->getMessage()); throw new InternalError($e->getMessage()); } @@ -225,15 +243,11 @@ public function find(int $id, bool $skipTableEnhancement = false, ?string $userI * @param string|null $emoji * @param string|null $userId * @return Table - * @throws DoesNotExistException * @throws InternalError - * @throws MultipleObjectsReturnedException - * @throws PermissionError - * @throws \OCP\DB\Exception + * @noinspection DuplicatedCode */ public function create(string $title, string $template, ?string $emoji, ?string $userId = null): Table { - /** @var string $userId */ - $userId = $this->permissionsService->preCheckUserId($userId, false); // $userId is set + $userId = $this->permissionsService->preCheckUserId($userId, false); // we can assume that the $userId is set $time = new DateTime(); $item = new Table(); @@ -248,17 +262,27 @@ public function create(string $title, string $template, ?string $emoji, ?string $item->setLastEditAt($time->format('Y-m-d H:i:s')); try { $newTable = $this->mapper->insert($item); - } catch (\OCP\DB\Exception $e) { + } catch (OcpDbException $e) { $this->logger->error($e->getMessage()); throw new InternalError($e->getMessage()); } if ($template !== 'custom') { - $table = $this->tableTemplateService->makeTemplate($newTable, $template); + try { + $table = $this->tableTemplateService->makeTemplate($newTable, $template); + } catch (InternalError|PermissionError|DoesNotExistException|MultipleObjectsReturnedException|OcpDbException $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new InternalError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } } else { $table = $this->addOwnerDisplayName($newTable); } - $this->enhanceTable($table, $userId); + try { + $this->enhanceTable($table, $userId); + } catch (InternalError|PermissionError $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new InternalError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } return $table; } @@ -309,45 +333,73 @@ public function setOwner(int $id, string $newOwnerUserId, ?string $userId = null * @param null|string $userId * @return Table * @throws InternalError + * @throws NotFoundError + * @throws PermissionError */ public function delete(int $id, ?string $userId = null): Table { - /** @var string $userId */ - $userId = $this->permissionsService->preCheckUserId($userId); // $userId is set or '' + $userId = $this->permissionsService->preCheckUserId($userId); // assume that $userId is set or '' try { $item = $this->mapper->find($id); + } catch (DoesNotExistException $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new NotFoundError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } catch (MultipleObjectsReturnedException|OcpDbException $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new InternalError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } - // security - if (!$this->permissionsService->canManageTable($item, $userId)) { - throw new PermissionError('PermissionError: can not delete table with id '.$id); - } + // security + if (!$this->permissionsService->canManageTable($item, $userId)) { + throw new PermissionError('PermissionError: can not delete table with id '.$id); + } - // delete all rows for that table + // delete all rows for that table + try { $this->rowService->deleteAllByTable($id, $userId); + } catch (PermissionError|OcpDbException $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new InternalError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } - // delete all columns for that table + // delete all columns for that table + try { $columns = $this->columnService->findAllByTable($id, null, $userId); - foreach ($columns as $column) { + } catch (InternalError|PermissionError $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new InternalError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } + foreach ($columns as $column) { + try { $this->columnService->delete($column->id, true, $userId); + } catch (InternalError $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new InternalError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); } + } - // delete all views for that table + // delete all views for that table + try { $this->viewService->deleteAllByTable($item, $userId); + } catch (InternalError|PermissionError $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new InternalError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } - // delete all shares for that table - $this->shareService->deleteAllForTable($item); + // delete all shares for that table + $this->shareService->deleteAllForTable($item); - // delete table + // delete table + try { $this->mapper->delete($item); - return $item; - } catch (Exception $e) { - $this->logger->error($e->getMessage()); - throw new InternalError($e->getMessage()); + } catch (OcpDbException $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new InternalError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); } + return $item; } /** - * @noinspection PhpUndefinedMethodInspection * * @param int $id $userId * @param string|null $title @@ -355,34 +407,49 @@ public function delete(int $id, ?string $userId = null): Table { * @param string|null $userId * @return Table * @throws InternalError + * @throws NotFoundError + * @throws PermissionError */ public function update(int $id, ?string $title, ?string $emoji, ?string $userId = null): Table { $userId = $this->permissionsService->preCheckUserId($userId); try { $table = $this->mapper->find($id); + } catch (DoesNotExistException $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new NotFoundError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } catch (MultipleObjectsReturnedException|OcpDbException $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new InternalError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } - // security - if (!$this->permissionsService->canUpdateTable($table, $userId)) { - throw new PermissionError('PermissionError: can not update table with id '.$id); - } + // security + if (!$this->permissionsService->canUpdateTable($table, $userId)) { + throw new PermissionError('PermissionError: can not update table with id '.$id); + } - $time = new DateTime(); - if ($title !== null) { - $table->setTitle($title); - } - if ($emoji !== null) { - $table->setEmoji($emoji); - } - $table->setLastEditBy($userId); - $table->setLastEditAt($time->format('Y-m-d H:i:s')); + $time = new DateTime(); + if ($title !== null) { + $table->setTitle($title); + } + if ($emoji !== null) { + $table->setEmoji($emoji); + } + $table->setLastEditBy($userId); + $table->setLastEditAt($time->format('Y-m-d H:i:s')); + try { $table = $this->mapper->update($table); + } catch (OcpDbException $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new InternalError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } + try { $this->enhanceTable($table, $userId); - return $table; - } catch (Exception $e) { + } catch (InternalError|PermissionError $e) { $this->logger->error($e->getMessage(), ['exception' => $e]); - throw new InternalError($e->getMessage()); + throw new InternalError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); } + return $table; } /** @@ -401,7 +468,7 @@ public function search(string $term, int $limit = 100, int $offset = 0, ?string $this->enhanceTable($table, $userId); } return $tables; - } catch (InternalError | PermissionError | \OCP\DB\Exception $e) { + } catch (InternalError | PermissionError |OcpDbException $e) { return []; } } diff --git a/lib/Service/ViewService.php b/lib/Service/ViewService.php index b00a940f6..15ac49692 100644 --- a/lib/Service/ViewService.php +++ b/lib/Service/ViewService.php @@ -16,11 +16,15 @@ use OCA\Tables\Errors\NotFoundError; use OCA\Tables\Errors\PermissionError; use OCA\Tables\Helper\UserHelper; +use OCA\Tables\ResponseDefinitions; use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Db\MultipleObjectsReturnedException; use OCP\IL10N; use Psr\Log\LoggerInterface; +/** + * @psalm-import-type TablesView from ResponseDefinitions + */ class ViewService extends SuperService { private ViewMapper $mapper; @@ -81,15 +85,22 @@ public function findAll(Table $table, ?string $userId = null): array { } } + /** + * @param View[] $items + * @return TablesView[] + */ + public function formatViews(array $items): array { + return array_map(fn (View $item) => $item->jsonSerialize(), $items); + } + /** * @param int $id * @param bool $skipEnhancement * @param string|null $userId (null -> take from session, '' -> no user in context) * @return View - * @throws DoesNotExistException * @throws InternalError - * @throws MultipleObjectsReturnedException * @throws PermissionError + * @throws NotFoundError */ public function find(int $id, bool $skipEnhancement = false, ?string $userId = null): View { /** @var string $userId */ @@ -97,9 +108,12 @@ public function find(int $id, bool $skipEnhancement = false, ?string $userId = n try { $view = $this->mapper->find($id); - } catch (\OCP\DB\Exception $e) { - $this->logger->error($e->getMessage()); - throw new InternalError($e->getMessage()); + } catch (InternalError|\OCP\DB\Exception|MultipleObjectsReturnedException $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new InternalError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } catch (DoesNotExistException $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new NotFoundError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); } // security @@ -191,6 +205,7 @@ public function updateSingle(int $id, string $key, ?string $value, ?string $user * @param bool $skipTableEnhancement * @return View * @throws InternalError + * @throws PermissionError */ public function update(int $id, array $data, ?string $userId = null, bool $skipTableEnhancement = false): View { $userId = $this->permissionsService->preCheckUserId($userId); @@ -231,24 +246,33 @@ public function update(int $id, array $data, ?string $userId = null, bool $skipT * @param string|null $userId * @return View * @throws InternalError + * @throws PermissionError + * @throws NotFoundError */ public function delete(int $id, ?string $userId = null): View { - /** @var string $userId */ - $userId = $this->permissionsService->preCheckUserId($userId); // $userId is set or '' + $userId = $this->permissionsService->preCheckUserId($userId); // assume $userId is set or '' try { $view = $this->mapper->find($id); + } catch (InternalError|MultipleObjectsReturnedException|\OCP\DB\Exception $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new InternalError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } catch (DoesNotExistException $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new NotFoundError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); + } - // security - if (!$this->permissionsService->canManageView($view, $userId)) { - throw new PermissionError('PermissionError: can not delete view with id '.$id); - } - $this->shareService->deleteAllForView($view); + // security + if (!$this->permissionsService->canManageView($view, $userId)) { + throw new PermissionError('PermissionError: can not delete view with id '.$id); + } + $this->shareService->deleteAllForView($view); + try { return $this->mapper->delete($view); - } catch (Exception $e) { - $this->logger->error($e->getMessage()); - throw new InternalError($e->getMessage()); + } catch (\OCP\DB\Exception $e) { + $this->logger->error($e->getMessage(), ['exception' => $e]); + throw new InternalError(get_class($this) . ' - ' . __FUNCTION__ . ': '.$e->getMessage()); } } diff --git a/openapi.json b/openapi.json new file mode 100644 index 000000000..d0eaa9f4c --- /dev/null +++ b/openapi.json @@ -0,0 +1,6916 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "tables", + "version": "0.0.1", + "description": "Manage data the way you need it.", + "license": { + "name": "agpl" + } + }, + "components": { + "securitySchemes": { + "basic_auth": { + "type": "http", + "scheme": "basic" + }, + "bearer_auth": { + "type": "http", + "scheme": "bearer" + } + }, + "schemas": { + "Capabilities": { + "type": "object", + "required": [ + "tables" + ], + "properties": { + "tables": { + "type": "object", + "required": [ + "enabled", + "version", + "apiVersions", + "column_types" + ], + "properties": { + "enabled": { + "type": "boolean" + }, + "version": { + "type": "string" + }, + "apiVersions": { + "type": "array", + "items": { + "type": "string" + } + }, + "column_types": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, + "Column": { + "type": "object", + "required": [ + "id", + "title", + "tableId", + "createdBy", + "createdAt", + "lastEditBy", + "lastEditAt", + "type", + "subtype", + "mandatory", + "description", + "orderWeight", + "numberDefault", + "numberMin", + "numberMax", + "numberDecimals", + "numberPrefix", + "numberSuffix", + "textDefault", + "textAllowedPattern", + "textMaxLength", + "selectionOptions", + "selectionDefault", + "datetimeDefault" + ], + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "title": { + "type": "string" + }, + "tableId": { + "type": "integer", + "format": "int64" + }, + "createdBy": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "lastEditBy": { + "type": "string" + }, + "lastEditAt": { + "type": "string" + }, + "type": { + "type": "string" + }, + "subtype": { + "type": "string" + }, + "mandatory": { + "type": "boolean" + }, + "description": { + "type": "string" + }, + "orderWeight": { + "type": "integer", + "format": "int64" + }, + "numberDefault": { + "type": "number", + "format": "float" + }, + "numberMin": { + "type": "number", + "format": "float" + }, + "numberMax": { + "type": "number", + "format": "float" + }, + "numberDecimals": { + "type": "integer", + "format": "int64" + }, + "numberPrefix": { + "type": "string" + }, + "numberSuffix": { + "type": "string" + }, + "textDefault": { + "type": "string" + }, + "textAllowedPattern": { + "type": "string" + }, + "textMaxLength": { + "type": "integer", + "format": "int64" + }, + "selectionOptions": { + "type": "string" + }, + "selectionDefault": { + "type": "string" + }, + "datetimeDefault": { + "type": "string" + } + } + }, + "ImportState": { + "type": "object", + "required": [ + "found_columns_count", + "matching_columns_count", + "created_columns_count", + "inserted_rows_count", + "errors_parsing_count", + "errors_count" + ], + "properties": { + "found_columns_count": { + "type": "integer", + "format": "int64" + }, + "matching_columns_count": { + "type": "integer", + "format": "int64" + }, + "created_columns_count": { + "type": "integer", + "format": "int64" + }, + "inserted_rows_count": { + "type": "integer", + "format": "int64" + }, + "errors_parsing_count": { + "type": "integer", + "format": "int64" + }, + "errors_count": { + "type": "integer", + "format": "int64" + } + } + }, + "Index": { + "type": "object", + "required": [ + "tables", + "views" + ], + "properties": { + "tables": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Table" + } + }, + "views": { + "type": "array", + "items": { + "$ref": "#/components/schemas/View" + } + } + } + }, + "OCSMeta": { + "type": "object", + "required": [ + "status", + "statuscode" + ], + "properties": { + "status": { + "type": "string" + }, + "statuscode": { + "type": "integer" + }, + "message": { + "type": "string" + }, + "totalitems": { + "type": "string" + }, + "itemsperpage": { + "type": "string" + } + } + }, + "Row": { + "type": "object", + "required": [ + "id", + "tableId", + "createdBy", + "createdAt", + "lastEditBy", + "lastEditAt", + "data" + ], + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "tableId": { + "type": "integer", + "format": "int64" + }, + "createdBy": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "lastEditBy": { + "type": "string" + }, + "lastEditAt": { + "type": "string" + }, + "data": { + "type": "object", + "nullable": true, + "required": [ + "columnId", + "value" + ], + "properties": { + "columnId": { + "type": "integer", + "format": "int64" + }, + "value": { + "type": "object" + } + } + } + } + }, + "Share": { + "type": "object", + "required": [ + "id", + "sender", + "receiver", + "receiverDisplayName", + "receiverType", + "nodeId", + "nodeType", + "permissionRead", + "permissionCreate", + "permissionUpdate", + "permissionDelete", + "permissionManage", + "createdAt", + "createdBy" + ], + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "sender": { + "type": "string" + }, + "receiver": { + "type": "string" + }, + "receiverDisplayName": { + "type": "string" + }, + "receiverType": { + "type": "string" + }, + "nodeId": { + "type": "integer", + "format": "int64" + }, + "nodeType": { + "type": "string" + }, + "permissionRead": { + "type": "boolean" + }, + "permissionCreate": { + "type": "boolean" + }, + "permissionUpdate": { + "type": "boolean" + }, + "permissionDelete": { + "type": "boolean" + }, + "permissionManage": { + "type": "boolean" + }, + "createdAt": { + "type": "string" + }, + "createdBy": { + "type": "string" + } + } + }, + "Table": { + "type": "object", + "required": [ + "id", + "title", + "emoji", + "ownership", + "ownerDisplayName", + "createdBy", + "createdAt", + "lastEditBy", + "lastEditAt", + "isShared", + "onSharePermissions", + "hasShares", + "rowsCount", + "views" + ], + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "title": { + "type": "string" + }, + "emoji": { + "type": "string" + }, + "ownership": { + "type": "string" + }, + "ownerDisplayName": { + "type": "string" + }, + "createdBy": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "lastEditBy": { + "type": "string" + }, + "lastEditAt": { + "type": "string" + }, + "isShared": { + "type": "boolean" + }, + "onSharePermissions": { + "type": "object", + "nullable": true, + "required": [ + "read", + "create", + "update", + "delete", + "manage" + ], + "properties": { + "read": { + "type": "boolean" + }, + "create": { + "type": "boolean" + }, + "update": { + "type": "boolean" + }, + "delete": { + "type": "boolean" + }, + "manage": { + "type": "boolean" + } + } + }, + "hasShares": { + "type": "boolean" + }, + "rowsCount": { + "type": "integer", + "format": "int64" + }, + "views": { + "type": "array", + "items": { + "$ref": "#/components/schemas/View" + } + } + } + }, + "View": { + "type": "object", + "required": [ + "id", + "title", + "emoji", + "tableId", + "ownership", + "ownerDisplayName", + "createdBy", + "createdAt", + "lastEditBy", + "lastEditAt", + "description", + "columns", + "sort", + "filter", + "isShared", + "onSharePermissions", + "hasShares", + "rowsCount" + ], + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "title": { + "type": "string" + }, + "emoji": { + "type": "string" + }, + "tableId": { + "type": "integer", + "format": "int64" + }, + "ownership": { + "type": "string" + }, + "ownerDisplayName": { + "type": "string" + }, + "createdBy": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "lastEditBy": { + "type": "string" + }, + "lastEditAt": { + "type": "string" + }, + "description": { + "type": "string" + }, + "columns": { + "type": "array", + "nullable": true, + "items": { + "type": "integer", + "format": "int64" + } + }, + "sort": { + "type": "object", + "nullable": true, + "required": [ + "columnId", + "mode" + ], + "properties": { + "columnId": { + "type": "integer", + "format": "int64" + }, + "mode": { + "type": "string", + "enum": [ + "ASC", + "DESC" + ] + } + } + }, + "filter": { + "type": "object", + "nullable": true, + "required": [ + "columnId", + "operator", + "value" + ], + "properties": { + "columnId": { + "type": "integer", + "format": "int64" + }, + "operator": { + "type": "string", + "enum": [ + "begins-with", + "ends-with", + "contains", + "is-equal", + "is-greater-than", + "is-greater-than-or-equal", + "is-lower-than", + "is-lower-than-or-equal", + "is-empty" + ] + }, + "value": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer", + "format": "int64" + }, + { + "type": "number", + "format": "float" + } + ] + } + } + }, + "isShared": { + "type": "boolean" + }, + "onSharePermissions": { + "type": "object", + "nullable": true, + "required": [ + "read", + "create", + "update", + "delete", + "manage" + ], + "properties": { + "read": { + "type": "boolean" + }, + "create": { + "type": "boolean" + }, + "update": { + "type": "boolean" + }, + "delete": { + "type": "boolean" + }, + "manage": { + "type": "boolean" + } + } + }, + "hasShares": { + "type": "boolean" + }, + "rowsCount": { + "type": "integer", + "format": "int64" + } + } + } + } + }, + "paths": { + "/index.php/apps/tables/api/1/tables": { + "get": { + "operationId": "api1-list", + "summary": "Returns all Tables", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "responses": { + "200": { + "description": "Tables returned", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Table" + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "post": { + "operationId": "api1-create-table", + "summary": "Create a new table and return it", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "title", + "in": "query", + "description": "Title of the table", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "emoji", + "in": "query", + "description": "Emoji for the table", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "template", + "in": "query", + "description": "Template to use if wanted", + "schema": { + "type": "string", + "default": "custom" + } + } + ], + "responses": { + "200": { + "description": "Tables returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Table" + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/tables/{tableId}": { + "put": { + "operationId": "api1-update-table", + "summary": "Update tables properties", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "title", + "in": "query", + "description": "New table title", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "emoji", + "in": "query", + "description": "New table emoji", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "tableId", + "in": "path", + "description": "Table ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Tables returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Table" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "get": { + "operationId": "api1-get-table", + "summary": "Get a table object", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "tableId", + "in": "path", + "description": "Table ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Table returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Table" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "api1-delete-table", + "summary": "Delete a table", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "tableId", + "in": "path", + "description": "Table ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Deleted table returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Table" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/tables/{tableId}/views": { + "get": { + "operationId": "api1-list-views", + "summary": "Get all views for a table", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "tableId", + "in": "path", + "description": "Table ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Views returned", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/View" + } + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "post": { + "operationId": "api1-create-view", + "summary": "Create a new view for a table", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "title", + "in": "query", + "description": "Title for the view", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "emoji", + "in": "query", + "description": "Emoji for the view", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "tableId", + "in": "path", + "description": "Table ID that will hold the view", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "View created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/View" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/views/{viewId}": { + "get": { + "operationId": "api1-get-view", + "summary": "Get a view object", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "viewId", + "in": "path", + "description": "View ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "View returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/View" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "put": { + "operationId": "api1-update-view", + "summary": "Update a view via key-value sets", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "data", + "in": "query", + "description": "key-value pairs", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "viewId", + "in": "path", + "description": "View ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "View updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/View" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "api1-delete-view", + "summary": "Delete a view", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "viewId", + "in": "path", + "description": "View ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "View deleted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/View" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/shares/{shareId}": { + "get": { + "operationId": "api1-get-share", + "summary": "Get a share object", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "shareId", + "in": "path", + "description": "Share ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Share returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Share" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "api1-delete-share", + "summary": "Delete a share", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "shareId", + "in": "path", + "description": "Share ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "View deleted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Share" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "put": { + "operationId": "api1-update-share-permissions", + "summary": "Update a share permission", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "permissionType", + "in": "query", + "description": "Permission type that should be changed", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "permissionValue", + "in": "query", + "description": "New permission value", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "shareId", + "in": "path", + "description": "Share ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "View deleted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Share" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/views/{viewId}/shares": { + "get": { + "operationId": "api1-list-view-shares", + "summary": "Get all shares for a view Will be empty if view does not exist", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "viewId", + "in": "path", + "description": "View ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Shares returned", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Share" + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/tables/{tableId}/shares": { + "get": { + "operationId": "api1-list-table-shares", + "summary": "Get all shares for a table Will be empty if table does not exist", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "tableId", + "in": "path", + "description": "Table ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Shares returned", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Share" + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "post": { + "operationId": "api1-create-table-share", + "summary": "Create a share for a table", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "receiver", + "in": "query", + "description": "Receiver ID", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "receiverType", + "in": "query", + "description": "Receiver type", + "required": true, + "schema": { + "type": "string", + "enum": [ + "user", + "group" + ] + } + }, + { + "name": "permissionRead", + "in": "query", + "description": "Permission if receiver can read data", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "permissionCreate", + "in": "query", + "description": "Permission if receiver can create data", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "permissionUpdate", + "in": "query", + "description": "Permission if receiver can update data", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "permissionDelete", + "in": "query", + "description": "Permission if receiver can delete data", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "permissionManage", + "in": "query", + "description": "Permission if receiver can manage table", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "tableId", + "in": "path", + "description": "Table ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "View deleted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Share" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/shares": { + "post": { + "operationId": "api1-create-share", + "summary": "Create a new share", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "nodeId", + "in": "query", + "description": "Node ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "nodeType", + "in": "query", + "description": "Node type", + "required": true, + "schema": { + "type": "string", + "enum": [ + "table", + "view" + ] + } + }, + { + "name": "receiver", + "in": "query", + "description": "Receiver ID", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "receiverType", + "in": "query", + "description": "Receiver type", + "required": true, + "schema": { + "type": "string", + "enum": [ + "user", + "group" + ] + } + }, + { + "name": "permissionRead", + "in": "query", + "description": "Permission if receiver can read data", + "schema": { + "type": "integer", + "default": 0 + } + }, + { + "name": "permissionCreate", + "in": "query", + "description": "Permission if receiver can create data", + "schema": { + "type": "integer", + "default": 0 + } + }, + { + "name": "permissionUpdate", + "in": "query", + "description": "Permission if receiver can update data", + "schema": { + "type": "integer", + "default": 0 + } + }, + { + "name": "permissionDelete", + "in": "query", + "description": "Permission if receiver can delete data", + "schema": { + "type": "integer", + "default": 0 + } + }, + { + "name": "permissionManage", + "in": "query", + "description": "Permission if receiver can manage node", + "schema": { + "type": "integer", + "default": 0 + } + } + ], + "responses": { + "200": { + "description": "Share returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Share" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/tables/{tableId}/columns": { + "get": { + "operationId": "api1-list-table-columns", + "summary": "Get all columns for a table or a underlying view Return an empty array if no columns were found", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "viewId", + "in": "query", + "description": "View ID", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "tableId", + "in": "path", + "description": "Table ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "View deleted", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Column" + } + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "post": { + "operationId": "api1-create-table-column", + "summary": "Create a new column for a table", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "title", + "in": "query", + "description": "Title", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "type", + "in": "query", + "description": "Column main type", + "required": true, + "schema": { + "type": "string", + "enum": [ + "text", + "number", + "datetime", + "select" + ] + } + }, + { + "name": "subtype", + "in": "query", + "description": "Column sub type", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "mandatory", + "in": "query", + "description": "Is the column mandatory", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "description", + "in": "query", + "description": "Description", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "numberPrefix", + "in": "query", + "description": "Prefix if the column is a number field", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "numberSuffix", + "in": "query", + "description": "Suffix if the column is a number field", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "numberDefault", + "in": "query", + "description": "Default number, if column is a number", + "schema": { + "type": "number", + "format": "float", + "nullable": true + } + }, + { + "name": "numberMin", + "in": "query", + "description": "Min value, if column is a number", + "schema": { + "type": "number", + "format": "float", + "nullable": true + } + }, + { + "name": "numberMax", + "in": "query", + "description": "Max number, if column is a number", + "schema": { + "type": "number", + "format": "float", + "nullable": true + } + }, + { + "name": "numberDecimals", + "in": "query", + "description": "Number of decimals, if column is a number", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "textDefault", + "in": "query", + "description": "Default text, if column is a text", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "textAllowedPattern", + "in": "query", + "description": "Allowed pattern (regex) for text columns (not yet implemented)", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "textMaxLength", + "in": "query", + "description": "Max length, if column is a text", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "selectionOptions", + "in": "query", + "description": "Options for a selection (json array{id: int, label: string})", + "schema": { + "type": "string", + "nullable": true, + "default": "" + } + }, + { + "name": "selectionDefault", + "in": "query", + "description": "Default option IDs for a selection (json int[])", + "schema": { + "type": "string", + "nullable": true, + "default": "" + } + }, + { + "name": "datetimeDefault", + "in": "query", + "description": "Default value, if column is datetime", + "schema": { + "type": "string", + "nullable": true, + "default": "" + } + }, + { + "name": "selectedViewIds[]", + "in": "query", + "description": "View IDs where this column should be added to be presented", + "schema": { + "type": "array", + "nullable": true, + "default": [], + "items": { + "type": "integer", + "format": "int64" + } + } + }, + { + "name": "tableId", + "in": "path", + "description": "Table ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Column created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Column" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/views/{viewId}/columns": { + "get": { + "operationId": "api1-list-view-columns", + "summary": "Get all columns for a view Return an empty array if no columns were found", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "viewId", + "in": "path", + "description": "View ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "View deleted", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Column" + } + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/columns": { + "post": { + "operationId": "api1-create-column", + "summary": "Create a column", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "tableId", + "in": "query", + "description": "Table ID", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "viewId", + "in": "query", + "description": "View ID", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "title", + "in": "query", + "description": "Title", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "type", + "in": "query", + "description": "Column main type", + "required": true, + "schema": { + "type": "string", + "enum": [ + "text", + "number", + "datetime", + "select" + ] + } + }, + { + "name": "subtype", + "in": "query", + "description": "Column sub type", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "mandatory", + "in": "query", + "description": "Is the column mandatory", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "description", + "in": "query", + "description": "Description", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "numberPrefix", + "in": "query", + "description": "Prefix if the column is a number field", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "numberSuffix", + "in": "query", + "description": "Suffix if the column is a number field", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "numberDefault", + "in": "query", + "description": "Default number, if column is a number", + "schema": { + "type": "number", + "format": "float", + "nullable": true + } + }, + { + "name": "numberMin", + "in": "query", + "description": "Min value, if column is a number", + "schema": { + "type": "number", + "format": "float", + "nullable": true + } + }, + { + "name": "numberMax", + "in": "query", + "description": "Max number, if column is a number", + "schema": { + "type": "number", + "format": "float", + "nullable": true + } + }, + { + "name": "numberDecimals", + "in": "query", + "description": "Number of decimals, if column is a number", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "textDefault", + "in": "query", + "description": "Default text, if column is a text", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "textAllowedPattern", + "in": "query", + "description": "Allowed pattern (regex) for text columns (not yet implemented)", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "textMaxLength", + "in": "query", + "description": "Max length, if column is a text", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "selectionOptions", + "in": "query", + "description": "Options for a selection (json array{id: int, label: string})", + "schema": { + "type": "string", + "nullable": true, + "default": "" + } + }, + { + "name": "selectionDefault", + "in": "query", + "description": "Default option IDs for a selection (json int[])", + "schema": { + "type": "string", + "nullable": true, + "default": "" + } + }, + { + "name": "datetimeDefault", + "in": "query", + "description": "Default value, if column is datetime", + "schema": { + "type": "string", + "nullable": true, + "default": "" + } + }, + { + "name": "selectedViewIds[]", + "in": "query", + "description": "View IDs where this column should be added to be presented", + "schema": { + "type": "array", + "nullable": true, + "default": [], + "items": { + "type": "integer", + "format": "int64" + } + } + } + ], + "responses": { + "200": { + "description": "Column created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Column" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/columns/{columnId}": { + "put": { + "operationId": "api1-update-column", + "summary": "Update a column", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "title", + "in": "query", + "description": "Title", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "subtype", + "in": "query", + "description": "Column sub type", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "mandatory", + "in": "query", + "description": "Is the column mandatory", + "required": true, + "schema": { + "type": "integer" + } + }, + { + "name": "description", + "in": "query", + "description": "Description", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "numberPrefix", + "in": "query", + "description": "Prefix if the column is a number field", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "numberSuffix", + "in": "query", + "description": "Suffix if the column is a number field", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "numberDefault", + "in": "query", + "description": "Default number, if column is a number", + "schema": { + "type": "number", + "format": "float", + "nullable": true + } + }, + { + "name": "numberMin", + "in": "query", + "description": "Min value, if column is a number", + "schema": { + "type": "number", + "format": "float", + "nullable": true + } + }, + { + "name": "numberMax", + "in": "query", + "description": "Max number, if column is a number", + "schema": { + "type": "number", + "format": "float", + "nullable": true + } + }, + { + "name": "numberDecimals", + "in": "query", + "description": "Number of decimals, if column is a number", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "textDefault", + "in": "query", + "description": "Default text, if column is a text", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "textAllowedPattern", + "in": "query", + "description": "Allowed pattern (regex) for text columns (not yet implemented)", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "textMaxLength", + "in": "query", + "description": "Max length, if column is a text", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "selectionOptions", + "in": "query", + "description": "Options for a selection (json array{id: int, label: string})", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "selectionDefault", + "in": "query", + "description": "Default option IDs for a selection (json int[])", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "datetimeDefault", + "in": "query", + "description": "Default value, if column is datetime", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "columnId", + "in": "path", + "description": "Column ID that will be updated", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Updated column", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Column" + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "get": { + "operationId": "api1-get-column", + "summary": "Returns a column object", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "columnId", + "in": "path", + "description": "Wanted Column ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Column returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Column" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "api1-delete-column", + "summary": "Delete a column", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "columnId", + "in": "path", + "description": "Wanted Column ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Deleted column returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Column" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/tables/{tableId}/rows/simple": { + "get": { + "operationId": "api1-list-table-rows-simple", + "summary": "List all rows values for a table, first row are the column titles", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "limit", + "in": "query", + "description": "Limit", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "offset", + "in": "query", + "description": "Offset", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "tableId", + "in": "path", + "description": "Table ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Row values returned", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/tables/{tableId}/rows": { + "get": { + "operationId": "api1-list-table-rows", + "summary": "List all rows for a table", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "limit", + "in": "query", + "description": "Limit", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "offset", + "in": "query", + "description": "Offset", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "tableId", + "in": "path", + "description": "Table ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Rows returned", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Row" + } + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "post": { + "operationId": "api1-create-row-in-table", + "summary": "Create a row within a table", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "data", + "in": "query", + "description": "Data as key - value store", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "tableId", + "in": "path", + "description": "Table ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Row returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Row" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/views/{viewId}/rows": { + "get": { + "operationId": "api1-list-view-rows", + "summary": "List all rows for a view", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "limit", + "in": "query", + "description": "Limit", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "offset", + "in": "query", + "description": "Offset", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "viewId", + "in": "path", + "description": "View ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Rows returned", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Row" + } + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "post": { + "operationId": "api1-create-row-in-view", + "summary": "Create a row within a view", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "data", + "in": "query", + "description": "Data as key - value store", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "viewId", + "in": "path", + "description": "View ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Row returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Row" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/rows/{rowId}": { + "get": { + "operationId": "api1-get-row", + "summary": "Get a row", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "rowId", + "in": "path", + "description": "Row ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Row returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Row" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "put": { + "operationId": "api1-update-row", + "summary": "Update a row", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "viewId", + "in": "query", + "description": "View ID", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "data", + "in": "query", + "description": "Data as key - value store", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "rowId", + "in": "path", + "description": "Row ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Updated row returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Row" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "api1-delete-row", + "summary": "Delete a row", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "rowId", + "in": "path", + "description": "Row ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Deleted row returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Row" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/views/{viewId}/rows/{rowId}": { + "delete": { + "operationId": "api1-delete-row-by-view", + "summary": "Delete a row within a view", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "viewId", + "in": "path", + "description": "View ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "rowId", + "in": "path", + "description": "Row ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Deleted row returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Row" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/import/table/{tableId}": { + "post": { + "operationId": "api1-import-in-table", + "summary": "Import from file in to a table", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "path", + "in": "query", + "description": "Path to file", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "createMissingColumns", + "in": "query", + "description": "Create missing columns", + "schema": { + "type": "integer", + "default": 1 + } + }, + { + "name": "tableId", + "in": "path", + "description": "Table ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Import status returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ImportState" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/index.php/apps/tables/api/1/import/views/{viewId}": { + "post": { + "operationId": "api1-import-in-view", + "summary": "Import from file in to a table", + "tags": [ + "api1" + ], + "security": [ + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "path", + "in": "query", + "description": "Path to file", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "createMissingColumns", + "in": "query", + "description": "Create missing columns", + "schema": { + "type": "integer", + "default": 1 + } + }, + { + "name": "viewId", + "in": "path", + "description": "View ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "Import status returned", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ImportState" + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/tables/api/2/init": { + "get": { + "operationId": "api_general-list", + "summary": "[api v2] Returns all main resources", + "description": "Tables and views incl. shares", + "tags": [ + "api_general" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "200": { + "description": "Index returned", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "$ref": "#/components/schemas/Index" + } + } + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/tables/api/2/tables": { + "get": { + "operationId": "api_tables-list", + "summary": "[api v2] Returns all Tables", + "tags": [ + "api_tables" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "200": { + "description": "Tables returned", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Table" + } + } + } + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + }, + "post": { + "operationId": "api_tables-create", + "summary": "[api v2] Create a new table and return it", + "tags": [ + "api_tables" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "title", + "in": "query", + "description": "Title of the table", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "emoji", + "in": "query", + "description": "Emoji for the table", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "template", + "in": "query", + "description": "Template to use if wanted", + "schema": { + "type": "string", + "default": "custom" + } + }, + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "200": { + "description": "Tables returned", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "$ref": "#/components/schemas/Table" + } + } + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/tables/api/2/tables/{id}": { + "get": { + "operationId": "api_tables-show", + "summary": "[api v2] Get a table object", + "tags": [ + "api_tables" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "Table ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "200": { + "description": "Table returned", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "$ref": "#/components/schemas/Table" + } + } + } + } + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + }, + "put": { + "operationId": "api_tables-update", + "summary": "[api v2] Update tables properties", + "tags": [ + "api_tables" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "title", + "in": "query", + "description": "New table title", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "emoji", + "in": "query", + "description": "New table emoji", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "id", + "in": "path", + "description": "Table ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "200": { + "description": "Tables returned", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "$ref": "#/components/schemas/Table" + } + } + } + } + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + }, + "delete": { + "operationId": "api_tables-destroy", + "summary": "[api v2] Delete a table", + "tags": [ + "api_tables" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "Table ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "200": { + "description": "Deleted table returned", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "$ref": "#/components/schemas/Table" + } + } + } + } + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/tables/api/2/columns/{nodeType}/{nodeId}": { + "get": { + "operationId": "api_columns-list", + "summary": "[api v2] Get all columns for a table or a view", + "description": "Return an empty array if no columns were found", + "tags": [ + "api_columns" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "nodeType", + "in": "path", + "description": "Node type", + "required": true, + "schema": { + "type": "string", + "enum": [ + "table", + "view" + ] + } + }, + { + "name": "nodeId", + "in": "path", + "description": "Node ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "200": { + "description": "View deleted", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Column" + } + } + } + } + } + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/tables/api/2/columns/{id}": { + "get": { + "operationId": "api_columns-show", + "summary": "[api v2] Get a column object", + "tags": [ + "api_columns" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "id", + "in": "path", + "description": "Column ID", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "200": { + "description": "Column returned", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "$ref": "#/components/schemas/Column" + } + } + } + } + } + } + } + }, + "403": { + "description": "No permissions", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/tables/api/2/columns/number": { + "post": { + "operationId": "api_columns-create-number-column", + "summary": "[api v2] Create new numbered column", + "description": "Specify a subtype to use any special numbered column", + "tags": [ + "api_columns" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "baseNodeId", + "in": "query", + "description": "Context of the column creation", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "title", + "in": "query", + "description": "Title", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "numberDefault", + "in": "query", + "description": "Default value for new rows", + "schema": { + "type": "number", + "format": "float", + "nullable": true + } + }, + { + "name": "numberDecimals", + "in": "query", + "description": "Decimals", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "numberPrefix", + "in": "query", + "description": "Prefix", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "numberSuffix", + "in": "query", + "description": "Suffix", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "numberMin", + "in": "query", + "description": "Min", + "schema": { + "type": "number", + "format": "float", + "nullable": true + } + }, + { + "name": "numberMax", + "in": "query", + "description": "Max", + "schema": { + "type": "number", + "format": "float", + "nullable": true + } + }, + { + "name": "subtype", + "in": "query", + "description": "Subtype for the new column", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "description", + "in": "query", + "description": "Description", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "selectedViewIds[]", + "in": "query", + "description": "View IDs where this columns should be added", + "schema": { + "type": "array", + "nullable": true, + "items": { + "type": "integer", + "format": "int64" + } + } + }, + { + "name": "mandatory", + "in": "query", + "description": "Is mandatory", + "schema": { + "type": "integer", + "default": 0 + } + }, + { + "name": "baseNodeType", + "in": "query", + "description": "Context type of the column creation", + "schema": { + "type": "string", + "default": "table", + "enum": [ + "table", + "view" + ] + } + }, + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "200": { + "description": "Column created", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "$ref": "#/components/schemas/Column" + } + } + } + } + } + } + } + }, + "403": { + "description": "No permission", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "text/plain": { + "schema": { + "type": "string" + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/tables/api/2/columns/text": { + "post": { + "operationId": "api_columns-create-text-column", + "summary": "[api v2] Create new text column", + "description": "Specify a subtype to use any special text column", + "tags": [ + "api_columns" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "baseNodeId", + "in": "query", + "description": "Context of the column creation", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "title", + "in": "query", + "description": "Title", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "textDefault", + "in": "query", + "description": "Default", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "textAllowedPattern", + "in": "query", + "description": "Allowed regex pattern", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "textMaxLength", + "in": "query", + "description": "Max raw text length", + "schema": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + { + "name": "subtype", + "in": "query", + "description": "Subtype for the new column", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "description", + "in": "query", + "description": "Description", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "selectedViewIds[]", + "in": "query", + "description": "View IDs where this columns should be added", + "schema": { + "type": "array", + "nullable": true, + "items": { + "type": "integer", + "format": "int64" + } + } + }, + { + "name": "mandatory", + "in": "query", + "description": "Is mandatory", + "schema": { + "type": "integer", + "default": 0 + } + }, + { + "name": "baseNodeType", + "in": "query", + "description": "Context type of the column creation", + "schema": { + "type": "string", + "default": "table", + "enum": [ + "table", + "view" + ] + } + }, + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "200": { + "description": "Column created", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "$ref": "#/components/schemas/Column" + } + } + } + } + } + } + } + }, + "403": { + "description": "No permission", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "text/plain": { + "schema": { + "type": "string" + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/tables/api/2/columns/selection": { + "post": { + "operationId": "api_columns-create-selection-column", + "summary": "[api v2] Create new selection column", + "description": "Specify a subtype to use any special selection column", + "tags": [ + "api_columns" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "baseNodeId", + "in": "query", + "description": "Context of the column creation", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "title", + "in": "query", + "description": "Title", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "selectionOptions", + "in": "query", + "description": "Json array{id: int, label: string} with options that can be selected, eg [{\"id\": 1, \"label\": \"first\"},{\"id\": 2, \"label\": \"second\"}]", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "selectionDefault", + "in": "query", + "description": "Json int|int[] for default selected option(s), eg 5 or [\"1\", \"8\"]", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "subtype", + "in": "query", + "description": "Subtype for the new column", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "description", + "in": "query", + "description": "Description", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "selectedViewIds[]", + "in": "query", + "description": "View IDs where this columns should be added", + "schema": { + "type": "array", + "nullable": true, + "default": [], + "items": { + "type": "integer", + "format": "int64" + } + } + }, + { + "name": "mandatory", + "in": "query", + "description": "Is mandatory", + "schema": { + "type": "integer", + "default": 0 + } + }, + { + "name": "baseNodeType", + "in": "query", + "description": "Context type of the column creation", + "schema": { + "type": "string", + "default": "table", + "enum": [ + "table", + "view" + ] + } + }, + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "200": { + "description": "Column created", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "$ref": "#/components/schemas/Column" + } + } + } + } + } + } + } + }, + "403": { + "description": "No permission", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "text/plain": { + "schema": { + "type": "string" + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "/ocs/v2.php/apps/tables/api/2/columns/datetime": { + "post": { + "operationId": "api_columns-create-datetime-column", + "summary": "[api v2] Create new datetime column", + "description": "Specify a subtype to use any special datetime column", + "tags": [ + "api_columns" + ], + "security": [ + { + "bearer_auth": [] + }, + { + "basic_auth": [] + } + ], + "parameters": [ + { + "name": "baseNodeId", + "in": "query", + "description": "Context of the column creation", + "required": true, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "title", + "in": "query", + "description": "Title", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "datetimeDefault", + "in": "query", + "description": "For a subtype 'date' you can set 'today'. For a main type or subtype 'time' you can set to 'now'.", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "subtype", + "in": "query", + "description": "Subtype for the new column", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "description", + "in": "query", + "description": "Description", + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "selectedViewIds[]", + "in": "query", + "description": "View IDs where this columns should be added", + "schema": { + "type": "array", + "nullable": true, + "items": { + "type": "integer", + "format": "int64" + } + } + }, + { + "name": "mandatory", + "in": "query", + "description": "Is mandatory", + "schema": { + "type": "integer", + "default": 0 + } + }, + { + "name": "baseNodeType", + "in": "query", + "description": "Context type of the column creation", + "schema": { + "type": "string", + "default": "table", + "enum": [ + "table", + "view" + ] + } + }, + { + "name": "OCS-APIRequest", + "in": "header", + "description": "Required to be true for the API request to pass", + "required": true, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "200": { + "description": "Column created", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "$ref": "#/components/schemas/Column" + } + } + } + } + } + } + } + }, + "403": { + "description": "No permission", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + }, + "text/plain": { + "schema": { + "type": "string" + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "ocs" + ], + "properties": { + "ocs": { + "type": "object", + "required": [ + "meta", + "data" + ], + "properties": { + "meta": { + "$ref": "#/components/schemas/OCSMeta" + }, + "data": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + "tags": [] +} \ No newline at end of file diff --git a/tests/integration/composer.json b/tests/integration/composer.json index d3c0fe1bf..50d8bd9a8 100644 --- a/tests/integration/composer.json +++ b/tests/integration/composer.json @@ -1,14 +1,14 @@ { "config": { "platform": { - "php": "8.0" + "php": "8.1" }, "sort-packages": true }, "require-dev": { - "behat/behat": "^3.12.0", - "guzzlehttp/guzzle": "^7.5.0", + "behat/behat": "^3.13.0", + "guzzlehttp/guzzle": "^7.8.0", "jarnaiz/behat-junit-formatter": "^1.3.2", - "phpunit/phpunit": "^9.5.28" + "phpunit/phpunit": "^9.6.13" } } diff --git a/tests/integration/composer.lock b/tests/integration/composer.lock index ad850de0e..8e09b1f26 100644 --- a/tests/integration/composer.lock +++ b/tests/integration/composer.lock @@ -4,21 +4,21 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "75b6547f816073e534adf3fa05d500f7", + "content-hash": "293db70f52dbc14d626b7ff0581ccef0", "packages": [], "packages-dev": [ { "name": "behat/behat", - "version": "v3.12.0", + "version": "v3.13.0", "source": { "type": "git", "url": "https://github.com/Behat/Behat.git", - "reference": "2f059c9172764ba1f1759b3679aca499b665330a" + "reference": "9dd7cdb309e464ddeab095cd1a5151c2dccba4ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Behat/Behat/zipball/2f059c9172764ba1f1759b3679aca499b665330a", - "reference": "2f059c9172764ba1f1759b3679aca499b665330a", + "url": "https://api.github.com/repos/Behat/Behat/zipball/9dd7cdb309e464ddeab095cd1a5151c2dccba4ab", + "reference": "9dd7cdb309e464ddeab095cd1a5151c2dccba4ab", "shasum": "" }, "require": { @@ -90,9 +90,9 @@ ], "support": { "issues": "https://github.com/Behat/Behat/issues", - "source": "https://github.com/Behat/Behat/tree/v3.12.0" + "source": "https://github.com/Behat/Behat/tree/v3.13.0" }, - "time": "2022-11-29T15:30:11+00:00" + "time": "2023-04-18T15:40:53+00:00" }, { "name": "behat/gherkin", @@ -208,30 +208,30 @@ }, { "name": "doctrine/instantiator", - "version": "1.5.0", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", - "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "php": "^8.1" }, "require-dev": { - "doctrine/coding-standard": "^9 || ^11", + "doctrine/coding-standard": "^11", "ext-pdo": "*", "ext-phar": "*", - "phpbench/phpbench": "^0.16 || ^1", - "phpstan/phpstan": "^1.4", - "phpstan/phpstan-phpunit": "^1", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.30 || ^5.4" + "phpbench/phpbench": "^1.2", + "phpstan/phpstan": "^1.9.4", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.5.27", + "vimeo/psalm": "^5.4" }, "type": "library", "autoload": { @@ -258,7 +258,7 @@ ], "support": { "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.5.0" + "source": "https://github.com/doctrine/instantiator/tree/2.0.0" }, "funding": [ { @@ -274,26 +274,26 @@ "type": "tidelift" } ], - "time": "2022-12-30T00:15:36+00:00" + "time": "2022-12-30T00:23:10+00:00" }, { "name": "guzzlehttp/guzzle", - "version": "7.5.0", + "version": "7.8.0", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "b50a2a1251152e43f6a37f0fa053e730a67d25ba" + "reference": "1110f66a6530a40fe7aea0378fe608ee2b2248f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/b50a2a1251152e43f6a37f0fa053e730a67d25ba", - "reference": "b50a2a1251152e43f6a37f0fa053e730a67d25ba", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/1110f66a6530a40fe7aea0378fe608ee2b2248f9", + "reference": "1110f66a6530a40fe7aea0378fe608ee2b2248f9", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^1.5", - "guzzlehttp/psr7": "^1.9 || ^2.4", + "guzzlehttp/promises": "^1.5.3 || ^2.0.1", + "guzzlehttp/psr7": "^1.9.1 || ^2.5.1", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0", "symfony/deprecation-contracts": "^2.2 || ^3.0" @@ -304,7 +304,8 @@ "require-dev": { "bamarni/composer-bin-plugin": "^1.8.1", "ext-curl": "*", - "php-http/client-integration-tests": "^3.0", + "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", + "php-http/message-factory": "^1.1", "phpunit/phpunit": "^8.5.29 || ^9.5.23", "psr/log": "^1.1 || ^2.0 || ^3.0" }, @@ -318,9 +319,6 @@ "bamarni-bin": { "bin-links": true, "forward-command": false - }, - "branch-alias": { - "dev-master": "7.5-dev" } }, "autoload": { @@ -386,7 +384,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.5.0" + "source": "https://github.com/guzzle/guzzle/tree/7.8.0" }, "funding": [ { @@ -402,38 +400,37 @@ "type": "tidelift" } ], - "time": "2022-08-28T15:39:27+00:00" + "time": "2023-08-27T10:20:53+00:00" }, { "name": "guzzlehttp/promises", - "version": "1.5.2", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "b94b2807d85443f9719887892882d0329d1e2598" + "reference": "111166291a0f8130081195ac4556a5587d7f1b5d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/b94b2807d85443f9719887892882d0329d1e2598", - "reference": "b94b2807d85443f9719887892882d0329d1e2598", + "url": "https://api.github.com/repos/guzzle/promises/zipball/111166291a0f8130081195ac4556a5587d7f1b5d", + "reference": "111166291a0f8130081195ac4556a5587d7f1b5d", "shasum": "" }, "require": { - "php": ">=5.5" + "php": "^7.2.5 || ^8.0" }, "require-dev": { - "symfony/phpunit-bridge": "^4.4 || ^5.1" + "bamarni/composer-bin-plugin": "^1.8.1", + "phpunit/phpunit": "^8.5.29 || ^9.5.23" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "1.5-dev" + "bamarni-bin": { + "bin-links": true, + "forward-command": false } }, "autoload": { - "files": [ - "src/functions_include.php" - ], "psr-4": { "GuzzleHttp\\Promise\\": "src/" } @@ -470,7 +467,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/1.5.2" + "source": "https://github.com/guzzle/promises/tree/2.0.1" }, "funding": [ { @@ -486,26 +483,26 @@ "type": "tidelift" } ], - "time": "2022-08-28T14:55:35+00:00" + "time": "2023-08-03T15:11:55+00:00" }, { "name": "guzzlehttp/psr7", - "version": "2.4.3", + "version": "2.6.1", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "67c26b443f348a51926030c83481b85718457d3d" + "reference": "be45764272e8873c72dbe3d2edcfdfcc3bc9f727" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/67c26b443f348a51926030c83481b85718457d3d", - "reference": "67c26b443f348a51926030c83481b85718457d3d", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/be45764272e8873c72dbe3d2edcfdfcc3bc9f727", + "reference": "be45764272e8873c72dbe3d2edcfdfcc3bc9f727", "shasum": "" }, "require": { "php": "^7.2.5 || ^8.0", "psr/http-factory": "^1.0", - "psr/http-message": "^1.0", + "psr/http-message": "^1.1 || ^2.0", "ralouphie/getallheaders": "^3.0" }, "provide": { @@ -525,9 +522,6 @@ "bamarni-bin": { "bin-links": true, "forward-command": false - }, - "branch-alias": { - "dev-master": "2.4-dev" } }, "autoload": { @@ -589,7 +583,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.4.3" + "source": "https://github.com/guzzle/psr7/tree/2.6.1" }, "funding": [ { @@ -605,7 +599,7 @@ "type": "tidelift" } ], - "time": "2022-10-26T14:07:24+00:00" + "time": "2023-08-27T10:13:57+00:00" }, { "name": "jarnaiz/behat-junit-formatter", @@ -652,16 +646,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.11.0", + "version": "1.11.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614" + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614", - "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", "shasum": "" }, "require": { @@ -699,7 +693,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.11.0" + "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" }, "funding": [ { @@ -707,20 +701,20 @@ "type": "tidelift" } ], - "time": "2022-03-03T13:19:32+00:00" + "time": "2023-03-08T13:26:56+00:00" }, { "name": "nikic/php-parser", - "version": "v4.15.3", + "version": "v4.17.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "570e980a201d8ed0236b0a62ddf2c9cbb2034039" + "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/570e980a201d8ed0236b0a62ddf2c9cbb2034039", - "reference": "570e980a201d8ed0236b0a62ddf2c9cbb2034039", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", + "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", "shasum": "" }, "require": { @@ -761,9 +755,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.3" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1" }, - "time": "2023-01-16T22:05:37+00:00" + "time": "2023-08-13T19:53:39+00:00" }, { "name": "phar-io/manifest", @@ -878,16 +872,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "9.2.25", + "version": "9.2.29", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "0e2b40518197a8c0d4b08bc34dfff1c99c508954" + "reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/0e2b40518197a8c0d4b08bc34dfff1c99c508954", - "reference": "0e2b40518197a8c0d4b08bc34dfff1c99c508954", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6a3a87ac2bbe33b25042753df8195ba4aa534c76", + "reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76", "shasum": "" }, "require": { @@ -909,8 +903,8 @@ "phpunit/phpunit": "^9.3" }, "suggest": { - "ext-pcov": "*", - "ext-xdebug": "*" + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, "type": "library", "extra": { @@ -943,7 +937,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.25" + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.29" }, "funding": [ { @@ -951,7 +946,7 @@ "type": "github" } ], - "time": "2023-02-25T05:32:00+00:00" + "time": "2023-09-19T04:57:46+00:00" }, { "name": "phpunit/php-file-iterator", @@ -1196,16 +1191,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.4", + "version": "9.6.13", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "9125ee085b6d95e78277dc07aa1f46f9e0607b8d" + "reference": "f3d767f7f9e191eab4189abe41ab37797e30b1be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/9125ee085b6d95e78277dc07aa1f46f9e0607b8d", - "reference": "9125ee085b6d95e78277dc07aa1f46f9e0607b8d", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f3d767f7f9e191eab4189abe41ab37797e30b1be", + "reference": "f3d767f7f9e191eab4189abe41ab37797e30b1be", "shasum": "" }, "require": { @@ -1220,7 +1215,7 @@ "phar-io/manifest": "^2.0.3", "phar-io/version": "^3.0.2", "php": ">=7.3", - "phpunit/php-code-coverage": "^9.2.13", + "phpunit/php-code-coverage": "^9.2.28", "phpunit/php-file-iterator": "^3.0.5", "phpunit/php-invoker": "^3.1.1", "phpunit/php-text-template": "^2.0.3", @@ -1238,8 +1233,8 @@ "sebastian/version": "^3.0.2" }, "suggest": { - "ext-soap": "*", - "ext-xdebug": "*" + "ext-soap": "To be able to generate mocks based on WSDL files", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, "bin": [ "phpunit" @@ -1278,7 +1273,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.4" + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.13" }, "funding": [ { @@ -1294,26 +1290,31 @@ "type": "tidelift" } ], - "time": "2023-02-27T13:06:37+00:00" + "time": "2023-09-19T05:39:22+00:00" }, { "name": "psr/container", - "version": "1.1.2", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/container.git", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", "shasum": "" }, "require": { "php": ">=7.4.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, "autoload": { "psr-4": { "Psr\\Container\\": "src/" @@ -1340,9 +1341,9 @@ ], "support": { "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/1.1.2" + "source": "https://github.com/php-fig/container/tree/2.0.2" }, - "time": "2021-11-05T16:50:12+00:00" + "time": "2021-11-05T16:47:00+00:00" }, { "name": "psr/event-dispatcher", @@ -1396,21 +1397,21 @@ }, { "name": "psr/http-client", - "version": "1.0.1", + "version": "1.0.3", "source": { "type": "git", "url": "https://github.com/php-fig/http-client.git", - "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", - "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", "shasum": "" }, "require": { "php": "^7.0 || ^8.0", - "psr/http-message": "^1.0" + "psr/http-message": "^1.0 || ^2.0" }, "type": "library", "extra": { @@ -1430,7 +1431,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interface for HTTP clients", @@ -1442,27 +1443,27 @@ "psr-18" ], "support": { - "source": "https://github.com/php-fig/http-client/tree/master" + "source": "https://github.com/php-fig/http-client" }, - "time": "2020-06-29T06:28:15+00:00" + "time": "2023-09-23T14:17:50+00:00" }, { "name": "psr/http-factory", - "version": "1.0.1", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/http-factory.git", - "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be" + "reference": "e616d01114759c4c489f93b099585439f795fe35" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be", - "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", + "reference": "e616d01114759c4c489f93b099585439f795fe35", "shasum": "" }, "require": { "php": ">=7.0.0", - "psr/http-message": "^1.0" + "psr/http-message": "^1.0 || ^2.0" }, "type": "library", "extra": { @@ -1482,7 +1483,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interfaces for PSR-7 HTTP message factories", @@ -1497,31 +1498,31 @@ "response" ], "support": { - "source": "https://github.com/php-fig/http-factory/tree/master" + "source": "https://github.com/php-fig/http-factory/tree/1.0.2" }, - "time": "2019-04-30T12:38:16+00:00" + "time": "2023-04-10T20:10:41+00:00" }, { "name": "psr/http-message", - "version": "1.0.1", + "version": "2.0", "source": { "type": "git", "url": "https://github.com/php-fig/http-message.git", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": "^7.2 || ^8.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -1536,7 +1537,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interface for HTTP messages", @@ -1550,9 +1551,9 @@ "response" ], "support": { - "source": "https://github.com/php-fig/http-message/tree/master" + "source": "https://github.com/php-fig/http-message/tree/2.0" }, - "time": "2016-08-06T14:39:51+00:00" + "time": "2023-04-04T09:54:51+00:00" }, { "name": "ralouphie/getallheaders", @@ -1898,16 +1899,16 @@ }, { "name": "sebastian/diff", - "version": "4.0.4", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" + "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131", + "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131", "shasum": "" }, "require": { @@ -1952,7 +1953,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.5" }, "funding": [ { @@ -1960,7 +1961,7 @@ "type": "github" } ], - "time": "2020-10-26T13:10:38+00:00" + "time": "2023-05-07T05:35:17+00:00" }, { "name": "sebastian/environment", @@ -2104,16 +2105,16 @@ }, { "name": "sebastian/global-state", - "version": "5.0.5", + "version": "5.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2" + "reference": "bde739e7565280bda77be70044ac1047bc007e34" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bde739e7565280bda77be70044ac1047bc007e34", + "reference": "bde739e7565280bda77be70044ac1047bc007e34", "shasum": "" }, "require": { @@ -2156,7 +2157,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5" + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.6" }, "funding": [ { @@ -2164,7 +2165,7 @@ "type": "github" } ], - "time": "2022-02-14T08:28:10+00:00" + "time": "2023-08-02T09:26:13+00:00" }, { "name": "sebastian/lines-of-code", @@ -2564,38 +2565,34 @@ }, { "name": "symfony/config", - "version": "v5.4.21", + "version": "v6.3.2", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "2a6b1111d038adfa15d52c0871e540f3b352d1e4" + "reference": "b47ca238b03e7b0d7880ffd1cf06e8d637ca1467" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/2a6b1111d038adfa15d52c0871e540f3b352d1e4", - "reference": "2a6b1111d038adfa15d52c0871e540f3b352d1e4", + "url": "https://api.github.com/repos/symfony/config/zipball/b47ca238b03e7b0d7880ffd1cf06e8d637ca1467", + "reference": "b47ca238b03e7b0d7880ffd1cf06e8d637ca1467", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/filesystem": "^4.4|^5.0|^6.0", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-php80": "^1.16", - "symfony/polyfill-php81": "^1.22" + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/filesystem": "^5.4|^6.0", + "symfony/polyfill-ctype": "~1.8" }, "conflict": { - "symfony/finder": "<4.4" + "symfony/finder": "<5.4", + "symfony/service-contracts": "<2.5" }, "require-dev": { - "symfony/event-dispatcher": "^4.4|^5.0|^6.0", - "symfony/finder": "^4.4|^5.0|^6.0", - "symfony/messenger": "^4.4|^5.0|^6.0", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/yaml": "^4.4|^5.0|^6.0" - }, - "suggest": { - "symfony/yaml": "To use the yaml reference dumper" + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/finder": "^5.4|^6.0", + "symfony/messenger": "^5.4|^6.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/yaml": "^5.4|^6.0" }, "type": "library", "autoload": { @@ -2623,7 +2620,7 @@ "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/config/tree/v5.4.21" + "source": "https://github.com/symfony/config/tree/v6.3.2" }, "funding": [ { @@ -2639,56 +2636,47 @@ "type": "tidelift" } ], - "time": "2023-02-14T08:03:56+00:00" + "time": "2023-07-19T20:22:16+00:00" }, { "name": "symfony/console", - "version": "v5.4.21", + "version": "v6.3.4", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "c77433ddc6cdc689caf48065d9ea22ca0853fbd9" + "reference": "eca495f2ee845130855ddf1cf18460c38966c8b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/c77433ddc6cdc689caf48065d9ea22ca0853fbd9", - "reference": "c77433ddc6cdc689caf48065d9ea22ca0853fbd9", + "url": "https://api.github.com/repos/symfony/console/zipball/eca495f2ee845130855ddf1cf18460c38966c8b6", + "reference": "eca495f2ee845130855ddf1cf18460c38966c8b6", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php73": "^1.9", - "symfony/polyfill-php80": "^1.16", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/string": "^5.1|^6.0" + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^5.4|^6.0" }, "conflict": { - "psr/log": ">=3", - "symfony/dependency-injection": "<4.4", - "symfony/dotenv": "<5.1", - "symfony/event-dispatcher": "<4.4", - "symfony/lock": "<4.4", - "symfony/process": "<4.4" + "symfony/dependency-injection": "<5.4", + "symfony/dotenv": "<5.4", + "symfony/event-dispatcher": "<5.4", + "symfony/lock": "<5.4", + "symfony/process": "<5.4" }, "provide": { - "psr/log-implementation": "1.0|2.0" + "psr/log-implementation": "1.0|2.0|3.0" }, "require-dev": { - "psr/log": "^1|^2", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/event-dispatcher": "^4.4|^5.0|^6.0", - "symfony/lock": "^4.4|^5.0|^6.0", - "symfony/process": "^4.4|^5.0|^6.0", - "symfony/var-dumper": "^4.4|^5.0|^6.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/lock": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0", + "symfony/var-dumper": "^5.4|^6.0" }, "type": "library", "autoload": { @@ -2717,12 +2705,12 @@ "homepage": "https://symfony.com", "keywords": [ "cli", - "command line", + "command-line", "console", "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.4.21" + "source": "https://github.com/symfony/console/tree/v6.3.4" }, "funding": [ { @@ -2738,52 +2726,44 @@ "type": "tidelift" } ], - "time": "2023-02-25T16:59:41+00:00" + "time": "2023-08-16T10:10:12+00:00" }, { "name": "symfony/dependency-injection", - "version": "v5.4.21", + "version": "v6.3.5", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "5bc403d96622cf0091abd92c939eadecd4d07f94" + "reference": "2ed62b3bf98346e1f45529a7b6be2196739bb993" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/5bc403d96622cf0091abd92c939eadecd4d07f94", - "reference": "5bc403d96622cf0091abd92c939eadecd4d07f94", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/2ed62b3bf98346e1f45529a7b6be2196739bb993", + "reference": "2ed62b3bf98346e1f45529a7b6be2196739bb993", "shasum": "" }, "require": { - "php": ">=7.2.5", - "psr/container": "^1.1.1", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php80": "^1.16", - "symfony/polyfill-php81": "^1.22", - "symfony/service-contracts": "^1.1.6|^2" + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/service-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^6.2.10" }, "conflict": { "ext-psr": "<1.1|>=2", - "symfony/config": "<5.3", - "symfony/finder": "<4.4", - "symfony/proxy-manager-bridge": "<4.4", - "symfony/yaml": "<4.4.26" + "symfony/config": "<6.1", + "symfony/finder": "<5.4", + "symfony/proxy-manager-bridge": "<6.3", + "symfony/yaml": "<5.4" }, "provide": { - "psr/container-implementation": "1.0", - "symfony/service-implementation": "1.0|2.0" + "psr/container-implementation": "1.1|2.0", + "symfony/service-implementation": "1.1|2.0|3.0" }, "require-dev": { - "symfony/config": "^5.3|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/yaml": "^4.4.26|^5.0|^6.0" - }, - "suggest": { - "symfony/config": "", - "symfony/expression-language": "For using expressions in service container configuration", - "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required", - "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them", - "symfony/yaml": "" + "symfony/config": "^6.1", + "symfony/expression-language": "^5.4|^6.0", + "symfony/yaml": "^5.4|^6.0" }, "type": "library", "autoload": { @@ -2811,7 +2791,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v5.4.21" + "source": "https://github.com/symfony/dependency-injection/tree/v6.3.5" }, "funding": [ { @@ -2827,29 +2807,29 @@ "type": "tidelift" } ], - "time": "2023-02-16T09:33:00+00:00" + "time": "2023-09-25T16:46:40+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v2.5.2", + "version": "v3.3.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66" + "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66", - "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", + "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=8.1" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.5-dev" + "dev-main": "3.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -2878,7 +2858,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.2" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.3.0" }, "funding": [ { @@ -2894,48 +2874,43 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:53:40+00:00" + "time": "2023-05-23T14:45:45+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v5.4.21", + "version": "v6.3.2", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "f0ae1383a8285dfc6752b8d8602790953118ff5a" + "reference": "adb01fe097a4ee930db9258a3cc906b5beb5cf2e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/f0ae1383a8285dfc6752b8d8602790953118ff5a", - "reference": "f0ae1383a8285dfc6752b8d8602790953118ff5a", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/adb01fe097a4ee930db9258a3cc906b5beb5cf2e", + "reference": "adb01fe097a4ee930db9258a3cc906b5beb5cf2e", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/event-dispatcher-contracts": "^2|^3", - "symfony/polyfill-php80": "^1.16" + "php": ">=8.1", + "symfony/event-dispatcher-contracts": "^2.5|^3" }, "conflict": { - "symfony/dependency-injection": "<4.4" + "symfony/dependency-injection": "<5.4", + "symfony/service-contracts": "<2.5" }, "provide": { "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "2.0" + "symfony/event-dispatcher-implementation": "2.0|3.0" }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/http-foundation": "^4.4|^5.0|^6.0", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/stopwatch": "^4.4|^5.0|^6.0" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/error-handler": "^5.4|^6.0", + "symfony/expression-language": "^5.4|^6.0", + "symfony/http-foundation": "^5.4|^6.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/stopwatch": "^5.4|^6.0" }, "type": "library", "autoload": { @@ -2963,7 +2938,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v5.4.21" + "source": "https://github.com/symfony/event-dispatcher/tree/v6.3.2" }, "funding": [ { @@ -2979,33 +2954,30 @@ "type": "tidelift" } ], - "time": "2023-02-14T08:03:56+00:00" + "time": "2023-07-06T06:56:43+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v2.5.2", + "version": "v3.3.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "f98b54df6ad059855739db6fcbc2d36995283fe1" + "reference": "a76aed96a42d2b521153fb382d418e30d18b59df" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/f98b54df6ad059855739db6fcbc2d36995283fe1", - "reference": "f98b54df6ad059855739db6fcbc2d36995283fe1", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/a76aed96a42d2b521153fb382d418e30d18b59df", + "reference": "a76aed96a42d2b521153fb382d418e30d18b59df", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.1", "psr/event-dispatcher": "^1" }, - "suggest": { - "symfony/event-dispatcher-implementation": "" - }, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.5-dev" + "dev-main": "3.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -3042,7 +3014,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.5.2" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.3.0" }, "funding": [ { @@ -3058,27 +3030,26 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:53:40+00:00" + "time": "2023-05-23T14:45:45+00:00" }, { "name": "symfony/filesystem", - "version": "v5.4.21", + "version": "v6.3.1", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "e75960b1bbfd2b8c9e483e0d74811d555ca3de9f" + "reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/e75960b1bbfd2b8c9e483e0d74811d555ca3de9f", - "reference": "e75960b1bbfd2b8c9e483e0d74811d555ca3de9f", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/edd36776956f2a6fcf577edb5b05eb0e3bdc52ae", + "reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.1", "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.8", - "symfony/polyfill-php80": "^1.16" + "symfony/polyfill-mbstring": "~1.8" }, "type": "library", "autoload": { @@ -3106,7 +3077,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v5.4.21" + "source": "https://github.com/symfony/filesystem/tree/v6.3.1" }, "funding": [ { @@ -3122,20 +3093,20 @@ "type": "tidelift" } ], - "time": "2023-02-14T08:03:56+00:00" + "time": "2023-06-01T08:30:39+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "5bbc823adecdae860bb64756d639ecfec17b050a" + "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a", - "reference": "5bbc823adecdae860bb64756d639ecfec17b050a", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", + "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", "shasum": "" }, "require": { @@ -3150,7 +3121,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -3188,7 +3159,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0" }, "funding": [ { @@ -3204,20 +3175,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "511a08c03c1960e08a883f4cffcacd219b758354" + "reference": "875e90aeea2777b6f135677f618529449334a612" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354", - "reference": "511a08c03c1960e08a883f4cffcacd219b758354", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/875e90aeea2777b6f135677f618529449334a612", + "reference": "875e90aeea2777b6f135677f618529449334a612", "shasum": "" }, "require": { @@ -3229,7 +3200,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -3269,7 +3240,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.28.0" }, "funding": [ { @@ -3285,20 +3256,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6" + "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6", - "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", + "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", "shasum": "" }, "require": { @@ -3310,7 +3281,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -3353,7 +3324,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.0" }, "funding": [ { @@ -3369,20 +3340,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534" + "reference": "42292d99c55abe617799667f454222c54c60e229" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534", - "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", + "reference": "42292d99c55abe617799667f454222c54c60e229", "shasum": "" }, "require": { @@ -3397,7 +3368,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -3436,248 +3407,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-11-03T14:55:06+00:00" - }, - { - "name": "symfony/polyfill-php73", - "version": "v1.27.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/9e8ecb5f92152187c4799efd3c96b78ccab18ff9", - "reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php73\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.27.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-11-03T14:55:06+00:00" - }, - { - "name": "symfony/polyfill-php80", - "version": "v1.27.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", - "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-11-03T14:55:06+00:00" - }, - { - "name": "symfony/polyfill-php81", - "version": "v1.27.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/707403074c8ea6e2edaf8794b0157a0bfa52157a", - "reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php81\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" }, "funding": [ { @@ -3693,37 +3423,33 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-07-28T09:04:16+00:00" }, { "name": "symfony/service-contracts", - "version": "v2.5.2", + "version": "v3.3.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c" + "reference": "40da9cc13ec349d9e4966ce18b5fbcd724ab10a4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c", - "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/40da9cc13ec349d9e4966ce18b5fbcd724ab10a4", + "reference": "40da9cc13ec349d9e4966ce18b5fbcd724ab10a4", "shasum": "" }, "require": { - "php": ">=7.2.5", - "psr/container": "^1.1", - "symfony/deprecation-contracts": "^2.1|^3" + "php": ">=8.1", + "psr/container": "^2.0" }, "conflict": { "ext-psr": "<1.1|>=2" }, - "suggest": { - "symfony/service-implementation": "" - }, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.5-dev" + "dev-main": "3.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -3733,7 +3459,10 @@ "autoload": { "psr-4": { "Symfony\\Contracts\\Service\\": "" - } + }, + "exclude-from-classmap": [ + "/Test/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -3760,7 +3489,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v2.5.2" + "source": "https://github.com/symfony/service-contracts/tree/v3.3.0" }, "funding": [ { @@ -3776,38 +3505,38 @@ "type": "tidelift" } ], - "time": "2022-05-30T19:17:29+00:00" + "time": "2023-05-23T14:45:45+00:00" }, { "name": "symfony/string", - "version": "v5.4.21", + "version": "v6.3.5", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "edac10d167b78b1d90f46a80320d632de0bd9f2f" + "reference": "13d76d0fb049051ed12a04bef4f9de8715bea339" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/edac10d167b78b1d90f46a80320d632de0bd9f2f", - "reference": "edac10d167b78b1d90f46a80320d632de0bd9f2f", + "url": "https://api.github.com/repos/symfony/string/zipball/13d76d0fb049051ed12a04bef4f9de8715bea339", + "reference": "13d76d0fb049051ed12a04bef4f9de8715bea339", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.1", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-grapheme": "~1.0", "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "~1.15" + "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/translation-contracts": ">=3.0" + "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/http-client": "^4.4|^5.0|^6.0", - "symfony/translation-contracts": "^1.1|^2", - "symfony/var-exporter": "^4.4|^5.0|^6.0" + "symfony/error-handler": "^5.4|^6.0", + "symfony/http-client": "^5.4|^6.0", + "symfony/intl": "^6.2", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^5.4|^6.0" }, "type": "library", "autoload": { @@ -3846,7 +3575,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.4.21" + "source": "https://github.com/symfony/string/tree/v6.3.5" }, "funding": [ { @@ -3862,57 +3591,55 @@ "type": "tidelift" } ], - "time": "2023-02-22T08:00:55+00:00" + "time": "2023-09-18T10:38:32+00:00" }, { "name": "symfony/translation", - "version": "v5.4.21", + "version": "v6.3.3", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "6996affeea65705086939894b77110e9a7f80874" + "reference": "3ed078c54bc98bbe4414e1e9b2d5e85ed5a5c8bd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/6996affeea65705086939894b77110e9a7f80874", - "reference": "6996affeea65705086939894b77110e9a7f80874", + "url": "https://api.github.com/repos/symfony/translation/zipball/3ed078c54bc98bbe4414e1e9b2d5e85ed5a5c8bd", + "reference": "3ed078c54bc98bbe4414e1e9b2d5e85ed5a5c8bd", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "^1.16", - "symfony/translation-contracts": "^2.3" + "symfony/translation-contracts": "^2.5|^3.0" }, "conflict": { - "symfony/config": "<4.4", - "symfony/console": "<5.3", - "symfony/dependency-injection": "<5.0", - "symfony/http-kernel": "<5.0", - "symfony/twig-bundle": "<5.0", - "symfony/yaml": "<4.4" + "symfony/config": "<5.4", + "symfony/console": "<5.4", + "symfony/dependency-injection": "<5.4", + "symfony/http-client-contracts": "<2.5", + "symfony/http-kernel": "<5.4", + "symfony/service-contracts": "<2.5", + "symfony/twig-bundle": "<5.4", + "symfony/yaml": "<5.4" }, "provide": { - "symfony/translation-implementation": "2.3" + "symfony/translation-implementation": "2.3|3.0" }, "require-dev": { + "nikic/php-parser": "^4.13", "psr/log": "^1|^2|^3", - "symfony/config": "^4.4|^5.0|^6.0", + "symfony/config": "^5.4|^6.0", "symfony/console": "^5.4|^6.0", - "symfony/dependency-injection": "^5.0|^6.0", - "symfony/finder": "^4.4|^5.0|^6.0", - "symfony/http-client-contracts": "^1.1|^2.0|^3.0", - "symfony/http-kernel": "^5.0|^6.0", - "symfony/intl": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/finder": "^5.4|^6.0", + "symfony/http-client-contracts": "^2.5|^3.0", + "symfony/http-kernel": "^5.4|^6.0", + "symfony/intl": "^5.4|^6.0", "symfony/polyfill-intl-icu": "^1.21", - "symfony/service-contracts": "^1.1.2|^2|^3", - "symfony/yaml": "^4.4|^5.0|^6.0" - }, - "suggest": { - "psr/log-implementation": "To use logging capability in translator", - "symfony/config": "", - "symfony/yaml": "" + "symfony/routing": "^5.4|^6.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/yaml": "^5.4|^6.0" }, "type": "library", "autoload": { @@ -3943,7 +3670,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v5.4.21" + "source": "https://github.com/symfony/translation/tree/v6.3.3" }, "funding": [ { @@ -3959,32 +3686,29 @@ "type": "tidelift" } ], - "time": "2023-02-21T19:46:44+00:00" + "time": "2023-07-31T07:08:24+00:00" }, { "name": "symfony/translation-contracts", - "version": "v2.5.2", + "version": "v3.3.0", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "136b19dd05cdf0709db6537d058bcab6dd6e2dbe" + "reference": "02c24deb352fb0d79db5486c0c79905a85e37e86" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/136b19dd05cdf0709db6537d058bcab6dd6e2dbe", - "reference": "136b19dd05cdf0709db6537d058bcab6dd6e2dbe", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/02c24deb352fb0d79db5486c0c79905a85e37e86", + "reference": "02c24deb352fb0d79db5486c0c79905a85e37e86", "shasum": "" }, "require": { - "php": ">=7.2.5" - }, - "suggest": { - "symfony/translation-implementation": "" + "php": ">=8.1" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.5-dev" + "dev-main": "3.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -3994,7 +3718,10 @@ "autoload": { "psr-4": { "Symfony\\Contracts\\Translation\\": "" - } + }, + "exclude-from-classmap": [ + "/Test/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -4021,7 +3748,81 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v2.5.2" + "source": "https://github.com/symfony/translation-contracts/tree/v3.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-05-30T17:17:10+00:00" + }, + { + "name": "symfony/var-exporter", + "version": "v6.3.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-exporter.git", + "reference": "df1f8aac5751871b83d30bf3e2c355770f8f0691" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/df1f8aac5751871b83d30bf3e2c355770f8f0691", + "reference": "df1f8aac5751871b83d30bf3e2c355770f8f0691", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "symfony/var-dumper": "^5.4|^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\VarExporter\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Allows exporting any serializable PHP data structure to plain PHP code", + "homepage": "https://symfony.com", + "keywords": [ + "clone", + "construct", + "export", + "hydrate", + "instantiate", + "lazy-loading", + "proxy", + "serialize" + ], + "support": { + "source": "https://github.com/symfony/var-exporter/tree/v6.3.4" }, "funding": [ { @@ -4037,35 +3838,32 @@ "type": "tidelift" } ], - "time": "2022-06-27T16:58:25+00:00" + "time": "2023-08-16T18:14:47+00:00" }, { "name": "symfony/yaml", - "version": "v5.4.21", + "version": "v6.3.3", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "3713e20d93e46e681e51605d213027e48dab3469" + "reference": "e23292e8c07c85b971b44c1c4b87af52133e2add" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/3713e20d93e46e681e51605d213027e48dab3469", - "reference": "3713e20d93e46e681e51605d213027e48dab3469", + "url": "https://api.github.com/repos/symfony/yaml/zipball/e23292e8c07c85b971b44c1c4b87af52133e2add", + "reference": "e23292e8c07c85b971b44c1c4b87af52133e2add", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-ctype": "^1.8" }, "conflict": { - "symfony/console": "<5.3" + "symfony/console": "<5.4" }, "require-dev": { - "symfony/console": "^5.3|^6.0" - }, - "suggest": { - "symfony/console": "For validating YAML files using the lint command" + "symfony/console": "^5.4|^6.0" }, "bin": [ "Resources/bin/yaml-lint" @@ -4096,7 +3894,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v5.4.21" + "source": "https://github.com/symfony/yaml/tree/v6.3.3" }, "funding": [ { @@ -4112,7 +3910,7 @@ "type": "tidelift" } ], - "time": "2023-02-21T19:46:44+00:00" + "time": "2023-07-31T07:08:24+00:00" }, { "name": "theseer/tokenizer", @@ -4173,7 +3971,7 @@ "platform": [], "platform-dev": [], "platform-overrides": { - "php": "8.0" + "php": "8.1" }, "plugin-api-version": "2.3.0" } diff --git a/tests/integration/features/api/tablesapi.feature b/tests/integration/features/APIv1.feature similarity index 99% rename from tests/integration/features/api/tablesapi.feature rename to tests/integration/features/APIv1.feature index 764877934..c92f90e2a 100644 --- a/tests/integration/features/api/tablesapi.feature +++ b/tests/integration/features/APIv1.feature @@ -1,4 +1,4 @@ -Feature: api/tablesapi +Feature: APIv1 Background: Given user "participant1" exists Given user "participant2" exists @@ -6,10 +6,12 @@ Feature: api/tablesapi And user "participant1" is member of group "phoenix" And user "participant2" is member of group "phoenix" + @api1 Scenario: User has initial table Then user "participant1" has the following tables | Tutorial | + @api1 Scenario: User creates, rename and delete a table Given table "my new awesome table" with emoji "🤓" exists for user "participant1" as "base1" Then user "participant1" has the following tables @@ -20,6 +22,7 @@ Feature: api/tablesapi Then user "participant1" has the following tables | Tutorial | + @api1 Scenario: Table sharing with a user Given table "Ready to share" with emoji "🥪" exists for user "participant1" as "base1" Then user "participant1" shares table with user "participant2" @@ -45,6 +48,7 @@ Feature: api/tablesapi Then user "participant2" has the following tables | Tutorial | + @api1 Scenario: Table sharing with a group Given table "Ready to share" with emoji "🥪" exists for user "participant1" as "base1" Then user "participant1" shares table with group "phoenix" @@ -56,6 +60,7 @@ Feature: api/tablesapi Then user "participant2" has the following tables | Tutorial | + @api1 Scenario: Create and check columns Given table "Column test" with emoji "🥶" exists for user "participant1" as "base1" Then table has at least following columns @@ -99,7 +104,7 @@ Feature: api/tablesapi | First column | Then user "participant1" deletes table with keyword "Column test" - @rows + @api1 @rows Scenario: Create, modify and delete rows Given table "Rows check" with emoji "👨🏻‍💻" exists for user "participant1" as "base1" Then column "one" exists with following properties @@ -135,7 +140,7 @@ Feature: api/tablesapi Then user deletes last created row Then user "participant1" deletes table with keyword "Rows check" - @rows + @api1 @rows Scenario: Create, modify and delete rows (legacy interface) Given table "Rows check legacy" with emoji "👨🏻‍💻" exists for user "participant1" as "base1" Then column "one" exists with following properties @@ -172,6 +177,7 @@ Feature: api/tablesapi Then user "participant1" deletes table with keyword "Rows check" + @api1 Scenario: Import csv table Given file "/import.csv" exists for user "participant1" with following data | Col1 | Col2 | Col3 | num | emoji | special | @@ -196,6 +202,7 @@ Feature: api/tablesapi | Val1 | Val2 | Val3 | 1 | 💙 | Ä | | great | news | here | 99 | ⚠️ | Ö | + @api1 Scenario: Create, edit and delete views Given table "View test" with emoji "👨🏻‍💻" exists for user "participant1" as "view-test" # Then print register diff --git a/tests/integration/features/APIv2.feature b/tests/integration/features/APIv2.feature new file mode 100644 index 000000000..843f4d685 --- /dev/null +++ b/tests/integration/features/APIv2.feature @@ -0,0 +1,66 @@ +Feature: APIv2 + Background: + Given user "participant1-v2" exists + + @api2 + Scenario: Test initial setup + Then user "participant1-v2" has the following tables via v2 + | Tutorial | + Then user "participant1-v2" has the following resources via v2 + | Tutorial | + + @api2 + Scenario: Basic table actions + Given table "Table 1 via api v2" with emoji "👋" exists for user "participant1-v2" as "t1" via v2 + Then user "participant1-v2" has the following tables via v2 + | Table 1 via api v2 | + Then user "participant1-v2" updates table "t1" set title "updated title" and emoji "⛵︎" via v2 + Then user "participant1-v2" has the following tables via v2 + | updated title | + Then user "participant1-v2" deletes table "t1" via v2 + + @api2 + Scenario: Basic column actions + Given table "Table 2" with emoji "👋" exists for user "participant1-v2" as "t2" via v2 + Then column from main type "text" for node type "table" and node name "t2" exists with name "c1" and following properties via v2 + | subtype | line | + | title | Beautiful text column | + | mandatory | 0 | + | description | This is a description! | + Then column from main type "text" for node type "table" and node name "t2" exists with name "c2" and following properties via v2 + | subtype | rich | + | title | Rich is cool | + | mandatory | 1 | + | description | Another description | + Then column from main type "number" for node type "table" and node name "t2" exists with name "c3" and following properties via v2 + | title | Counter | + | mandatory | 0 | + Then column from main type "number" for node type "table" and node name "t2" exists with name "c4" and following properties via v2 + | subtype | progress | + | title | Progress | + Then column from main type "number" for node type "table" and node name "t2" exists with name "c5" and following properties via v2 + | subtype | check | + | title | Checking | + Then column from main type "datetime" for node type "table" and node name "t2" exists with name "c6" and following properties via v2 + | subtype | date | + | title | A single date | + | datetimeDefault | today | + Then node with node type "table" and node name "t2" has the following columns via v2 + | Beautiful text column | Rich is cool | Counter | Progress | Checking | A single date | + Then print register + + @api2selection + Scenario: Create selection columns + Given table "Table 3" with emoji "👋" exists for user "participant1-v2" as "t3" via v2 + Then column from main type "selection" for node type "table" and node name "t3" exists with name "sel-c1" and following properties via v2 + | title | sel single | + | selectionOptions | [{"id": 1, "label": "first"},{"id": 2, "label": "second"}] | + | selectionDefault | 2 | + Then column from main type "selection" for node type "table" and node name "t3" exists with name "sel-c2" and following properties via v2 + | title | sel multi | + | subtype | multi | + | selectionOptions | [{"id": 1, "label": "first"},{"id": 2, "label": "second"}] | + | selectionDefault | ["1","2"] | + Then node with node type "table" and node name "t3" has the following columns via v2 + | sel single | sel multi | + Then print register diff --git a/tests/integration/features/bootstrap/CommandLineTrait.php b/tests/integration/features/bootstrap/CommandLineTrait.php deleted file mode 100644 index 1c9a3d30b..000000000 --- a/tests/integration/features/bootstrap/CommandLineTrait.php +++ /dev/null @@ -1,190 +0,0 @@ - - * @author Lukas Reschke - * @author Robin Appelman - * @author Vincent Petry - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see - * - */ - -use PHPUnit\Framework\Assert; - -require __DIR__ . '/../../vendor/autoload.php'; - -trait CommandLineTrait { - /** @var int return code of last command */ - private $lastCode; - /** @var string stdout of last command */ - private $lastStdOut; - /** @var string stderr of last command */ - private $lastStdErr; - - /** @var string */ - protected $ocPath = '../../../..'; - - /** - * Invokes an OCC command - * - * @param []string $args OCC command, the part behind "occ". For example: "files:transfer-ownership" - * @param []string $env environment variables - * @return int exit code - */ - public function runOcc($args = [], $env = null) { - // Set UTF-8 locale to ensure that escapeshellarg will not strip - // multibyte characters. - setlocale(LC_CTYPE, "C.UTF-8"); - - $args = array_map(function ($arg) { - return escapeshellarg($arg); - }, $args); - $args[] = '--no-ansi'; - $args = implode(' ', $args); - - $descriptor = [ - 0 => ['pipe', 'r'], - 1 => ['pipe', 'w'], - 2 => ['pipe', 'w'], - ]; - $process = proc_open('php console.php ' . $args, $descriptor, $pipes, $this->ocPath, $env); - $this->lastStdOut = stream_get_contents($pipes[1]); - $this->lastStdErr = stream_get_contents($pipes[2]); - $this->lastCode = proc_close($process); - - // Clean opcode cache - $client = new GuzzleHttp\Client(); - $client->request('GET', 'http://localhost:8080/apps/testing/clean_opcode_cache.php'); - - return $this->lastCode; - } - - /** - * @Given /^invoking occ with "([^"]*)"$/ - */ - public function invokingTheCommand($cmd) { - if (preg_match('/room-name:(?P\w+)/', $cmd, $matches)) { - if (array_key_exists($matches['token'], self::$identifierToToken)) { - $cmd = preg_replace('/room-name:(\w+)/', self::$identifierToToken[$matches['token']], $cmd); - } - } - $args = explode(' ', $cmd); - $this->runOcc($args); - } - - /** - * Find exception texts in stderr - */ - public function findExceptions() { - $exceptions = []; - $captureNext = false; - // the exception text usually appears after an "[Exception"] row - foreach (explode("\n", $this->lastStdErr) as $line) { - if (preg_match('/\[Exception\]/', $line)) { - $captureNext = true; - continue; - } - if ($captureNext) { - $exceptions[] = trim($line); - $captureNext = false; - } - } - - return $exceptions; - } - - /** - * @Then /^the command was successful$/ - */ - public function theCommandWasSuccessful() { - $exceptions = $this->findExceptions(); - if ($this->lastCode !== 0) { - echo $this->lastStdErr; - - $msg = 'The command was not successful, exit code was ' . $this->lastCode . '.'; - if (!empty($exceptions)) { - $msg .= ' Exceptions: ' . implode(', ', $exceptions); - } - throw new \Exception($msg); - } elseif (!empty($exceptions)) { - $msg = 'The command was successful but triggered exceptions: ' . implode(', ', $exceptions); - throw new \Exception($msg); - } - } - - /** - * @Then /^the command failed with exit code ([0-9]+)$/ - */ - public function theCommandFailedWithExitCode($exitCode) { - Assert::assertEquals($exitCode, $this->lastCode, 'The commands exit code did not match'); - } - - /** - * @Then /^the command failed with exception text "([^"]*)"$/ - */ - public function theCommandFailedWithException($exceptionText) { - $exceptions = $this->findExceptions(); - if (empty($exceptions)) { - throw new \Exception('The command did not throw any exceptions'); - } - - if (!in_array($exceptionText, $exceptions)) { - throw new \Exception('The command did not throw any exception with the text "' . $exceptionText . '"'); - } - } - - /** - * @Then /^the command output contains the text "([^"]*)"$/ - */ - public function theCommandOutputContainsTheText($text) { - if ($this->lastStdOut === '' && $this->lastStdErr !== '') { - Assert::assertStringContainsString($text, $this->lastStdErr, 'The command did not output the expected text on stdout'); - Assert::assertTrue(false, 'The command did not output the expected text on stdout but stderr'); - } - - Assert::assertStringContainsString($text, $this->lastStdOut, 'The command did not output the expected text on stdout'); - } - - /** - * @Then /^the command output contains the list entry '([^']*)' with value '([^']*)'$/ - */ - public function theCommandOutputContainsTheListEntry(string $key, string $value): void { - if (preg_match('/^"ROOM\(([^"]+)\)"$/', $key, $matches)) { - $key = '"' . self::$identifierToToken[$matches[1]] . '"'; - } - $text = '- ' . $key . ': ' . $value; - - if ($this->lastStdOut === '' && $this->lastStdErr !== '') { - Assert::assertStringContainsString($text, $this->lastStdErr, 'The command did not output the expected text on stdout'); - Assert::assertTrue(false, 'The command did not output the expected text on stdout but stderr'); - } - - Assert::assertStringContainsString($text, $this->lastStdOut, 'The command did not output the expected text on stdout'); - } - - /** - * @Then /^the command error output contains the text "([^"]*)"$/ - */ - public function theCommandErrorOutputContainsTheText($text) { - if ($this->lastStdErr === '' && $this->lastStdOut !== '') { - Assert::assertStringContainsString($text, $this->lastStdOut, 'The command did not output the expected text on stdout'); - Assert::assertTrue(false, 'The command did not output the expected text on stdout but stderr'); - } - - Assert::assertStringContainsString($text, $this->lastStdErr, 'The command did not output the expected text on stderr'); - } -} diff --git a/tests/integration/features/bootstrap/FeatureContext.php b/tests/integration/features/bootstrap/FeatureContext.php index 8f2a252ae..de9ea4f76 100644 --- a/tests/integration/features/bootstrap/FeatureContext.php +++ b/tests/integration/features/bootstrap/FeatureContext.php @@ -1,28 +1,27 @@ - * @author Thomas Müller * - * @copyright Copyright (c) 2016, ownCloud, Inc. - * @license AGPL-3.0 + * @copyright Copyright (c) 2023, Florian Steffens (flost-dev@mailbox.org) * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . * */ require __DIR__ . '/../../vendor/autoload.php'; use Behat\Behat\Context\Context; -use Behat\Behat\Context\SnippetAcceptingContext; use Behat\Gherkin\Node\TableNode; use GuzzleHttp\Client; use GuzzleHttp\Cookie\CookieJar; @@ -34,7 +33,7 @@ /** * Defines application features from the specific context. */ -class FeatureContext implements Context, SnippetAcceptingContext { +class FeatureContext implements Context { public const TEST_PASSWORD = '123456'; /** @var string */ @@ -69,8 +68,9 @@ class FeatureContext implements Context, SnippetAcceptingContext { // example for a table: 'test-table' -> 5 private array $tableIds = []; private array $viewIds = []; + private array $columnIds = []; - use CommandLineTrait; + // use CommandLineTrait; /** * FeatureContext constructor. @@ -101,6 +101,289 @@ public function cleanupUsers() { } + /** + * @Given table :table with emoji :emoji exists for user :user as :tableName via v2 + * + * @param string $user + * @param string $title + * @param string $tableName + * @param string|null $emoji + * @throws Exception + */ + public function createTableV2(string $user, string $title, string $tableName, string $emoji = null): void { + $this->setCurrentUser($user); + $this->sendOcsRequest('post', '/apps/tables/api/2/tables', + [ + 'title' => $title, + 'emoji' => $emoji + ] + ); + + $newTable = $this->getDataFromResponse($this->response)['ocs']['data']; + $this->tableIds[$tableName] = $newTable['id']; + + Assert::assertEquals(200, $this->response->getStatusCode()); + Assert::assertEquals($newTable['title'], $title); + Assert::assertEquals($newTable['emoji'], $emoji); + Assert::assertEquals($newTable['ownership'], $user); + + $this->sendOcsRequest( + 'GET', + '/apps/tables/api/2/tables/'.$newTable['id'], + ); + + $tableToVerify = $this->getDataFromResponse($this->response)['ocs']['data']; + Assert::assertEquals(200, $this->response->getStatusCode()); + Assert::assertEquals($tableToVerify['title'], $title); + Assert::assertEquals($tableToVerify['emoji'], $emoji); + Assert::assertEquals($tableToVerify['ownership'], $user); + } + + /** + * @Then user :user has the following tables via v2 + * + * @param string $user + * @param TableNode|null $body + * @throws Exception + */ + public function userTablesV2(string $user, TableNode $body = null): void { + $this->setCurrentUser($user); + $this->sendOcsRequest( + 'GET', + '/apps/tables/api/2/tables' + ); + + $data = $this->getDataFromResponse($this->response)['ocs']['data']; + Assert::assertEquals(200, $this->response->getStatusCode()); + + // check if tables are empty + if ($body === null) { + Assert::assertCount(0, $data); + return; + } + + // check if given tables exists + $titles = []; + foreach ($data as $d) { + $titles[] = $d['title']; + } + foreach ($body->getRows()[0] as $tableTitle) { + Assert::assertTrue(in_array($tableTitle, $titles, true)); + } + } + + /** + * @Then user :user has the following resources via v2 + * + * first row contains tables, second views + * | first table | second table | + * | first shared view | second shared view | + * + * @param string $user + * @param TableNode|null $body + * @throws Exception + */ + public function initialResourcesV2(string $user, TableNode $body = null): void { + $this->setCurrentUser($user); + $this->sendOcsRequest( + 'GET', + '/apps/tables/api/2/init' + ); + + $data = $this->getDataFromResponse($this->response)['ocs']['data']; + Assert::assertEquals(200, $this->response->getStatusCode()); + + // check if table is empty + if ($body === null) { + Assert::assertCount(0, $data); + return; + } + + // check if given tables exists + $tableTitles = []; + foreach ($data['tables'] as $d) { + $tableTitles[] = $d['title']; + } + $viewTitles = []; + foreach ($data['views'] as $d) { + $tableTitles[] = $d['title']; + } + + if (@$body->getRows()[0]) { + foreach ($body->getRows()[0] as $tableTitle) { + Assert::assertTrue(in_array($tableTitle, $tableTitles, true)); + } + } + if (@$body->getRows()[1]) { + foreach ($body->getRows()[1] as $viewTitle) { + Assert::assertTrue(in_array($viewTitle, $viewTitles, true)); + } + } + } + + /** + * @Then user :user updates table :tableName set title :title and emoji :emoji via v2 + * + * @param string $user + * @param string $title + * @param string|null $emoji + * @param string $tableName + * @throws Exception + */ + public function updateTableV2(string $user, string $title, ?string $emoji, string $tableName): void { + $this->setCurrentUser($user); + + $data = ['title' => $title]; + if ($emoji !== null) { + $data['emoji'] = $emoji; + } + + $this->sendOcsRequest( + 'PUT', + '/apps/tables/api/2/tables/'.$this->tableIds[$tableName], + $data + ); + + $updatedTable = $this->getDataFromResponse($this->response)['ocs']['data']; + + Assert::assertEquals(200, $this->response->getStatusCode()); + Assert::assertEquals($updatedTable['title'], $title); + Assert::assertEquals($updatedTable['emoji'], $emoji); + Assert::assertEquals($updatedTable['ownership'], $user); + + $this->sendOcsRequest( + 'GET', + '/apps/tables/api/2/tables/'.$updatedTable['id'], + ); + + $tableToVerify = $this->getDataFromResponse($this->response)['ocs']['data']; + Assert::assertEquals(200, $this->response->getStatusCode()); + Assert::assertEquals($tableToVerify['title'], $title); + Assert::assertEquals($tableToVerify['emoji'], $emoji); + Assert::assertEquals($tableToVerify['ownership'], $user); + } + + /** + * @Then user :user deletes table :tableName via v2 + * + * @param string $user + * @param string $tableName + * @throws Exception + */ + public function deleteTableV2(string $user, string $tableName): void { + $this->setCurrentUser($user); + + $this->sendOcsRequest( + 'DELETE', + '/apps/tables/api/2/tables/'.$this->tableIds[$tableName] + ); + + $deletedTable = $this->getDataFromResponse($this->response)['ocs']['data']; + Assert::assertEquals(200, $this->response->getStatusCode()); + Assert::assertEquals($deletedTable['id'], $this->tableIds[$tableName]); + + $this->sendOcsRequest( + 'GET', + '/apps/tables/api/2/tables/'.$deletedTable['id'], + ); + Assert::assertEquals(404, $this->response->getStatusCode()); + + unset($this->tableIds[$tableName]); + } + + /** + * @Then column from main type :columnType for node type :nodeType and node name :nodeName exists with name :columnName and following properties via v2 + * + * @param string $nodeType + * @param string $nodeName + * @param string $columnType + * @param string $columnName + * @param TableNode|null $properties + */ + public function createColumnV2(string $nodeType, string $nodeName, string $columnType, string $columnName, TableNode $properties = null): void { + $props = [ + 'baseNodeType' => $nodeType, + ]; + if($nodeType === 'table') { + $props['baseNodeId'] = $this->tableIds[$nodeName]; + } + if($nodeType === 'view') { + $props['baseNodeId'] = $this->viewIds[$nodeName]; + } + $title = null; + foreach ($properties->getRows() as $row) { + if($row[0] === 'title') { + $title = $row[1]; + } + $props[$row[0]] = $row[1]; + } + + $this->sendOcsRequest( + 'POST', + '/apps/tables/api/2/columns/'.$columnType, + $props + ); + + $newColumn = $this->getDataFromResponse($this->response)['ocs']['data']; + $this->columnIds[$columnName] = $newColumn['id']; + + Assert::assertEquals(200, $this->response->getStatusCode()); + + $this->sendOcsRequest( + 'GET', + '/apps/tables/api/2/columns/'.$newColumn['id'], + ); + + $columnToVerify = $this->getDataFromResponse($this->response)['ocs']['data']; + Assert::assertEquals(200, $this->response->getStatusCode()); + Assert::assertEquals($columnToVerify['title'], $title); + } + + /** + * @Then node with node type :nodeType and node name :nodeName has the following columns via v2 + * + * @param string $nodeType + * @param string $nodeName + * @param TableNode|null $body + */ + public function columnsForNodeV2(string $nodeType, string $nodeName, TableNode $body = null): void { + $nodeId = null; + if($nodeType === 'table') { + $nodeId = $this->tableIds[$nodeName]; + } + if($nodeType === 'view') { + $nodeId = $this->viewIds[$nodeName]; + } + + $this->sendOcsRequest( + 'GET', + '/apps/tables/api/2/columns/'.$nodeType.'/'.$nodeId + ); + + $data = $this->getDataFromResponse($this->response)['ocs']['data']; + Assert::assertEquals(200, $this->response->getStatusCode()); + + // check if tables are empty + if ($body === null) { + Assert::assertCount(0, $data); + return; + } + + // check if given tables exists + $titles = []; + foreach ($data as $d) { + $titles[] = $d['title']; + } + foreach ($body->getRows()[0] as $tableTitle) { + Assert::assertTrue(in_array($tableTitle, $titles, true)); + } + } + + // (((((((((((((((((((((((((((( END API v2 ))))))))))))))))))))))))))))))))))) + + + + // IMPORT -------------------------- @@ -176,6 +459,8 @@ public function printRegister(): void { print_r($this->tableIds); echo "Views --------------------\n"; print_r($this->viewIds); + echo "Columns --------------------\n"; + print_r($this->columnIds); } /** @@ -482,7 +767,7 @@ public function deleteView(string $user, string $viewName): void { $this->sendRequest( 'GET', - '/apps/tables/api/1/tables/'.$deletedItem['id'], + '/apps/tables/api/1/views/'.$deletedItem['id'], ); Assert::assertEquals(404, $this->response->getStatusCode());