diff --git a/.github/workflows/appstore-build-publish.yml b/.github/workflows/appstore-build-publish.yml index 338a567f..b468cee5 100644 --- a/.github/workflows/appstore-build-publish.yml +++ b/.github/workflows/appstore-build-publish.yml @@ -23,7 +23,7 @@ jobs: if: ${{ github.repository_owner == 'nextcloud-releases' }} steps: - - uses: cachix/install-nix-action@02a151ada4993995686f9ed4f1be7cfbb229e56f # v31 + - uses: cachix/install-nix-action@fc6e360bedc9ee72d75e701397f0bb30dce77568 # v31.5.2 - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 with: name: notify-push @@ -41,7 +41,7 @@ jobs: echo "APP_VERSION=${GITHUB_REF##*/}" >> $GITHUB_ENV - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false path: ${{ env.APP_NAME }} @@ -49,7 +49,7 @@ jobs: - name: Get app version number id: app-version - uses: skjnldsv/xpath-action@f5b036e9d973f42c86324833fd00be90665fbf77 # master + uses: skjnldsv/xpath-action@f5b036e9d973f42c86324833fd00be90665fbf77 # v1.0.0 with: filename: ${{ env.APP_NAME }}/appinfo/info.xml expression: "//info//version/text()" @@ -60,7 +60,7 @@ jobs: - name: Get appinfo data id: appinfo - uses: skjnldsv/xpath-action@f5b036e9d973f42c86324833fd00be90665fbf77 # master + uses: skjnldsv/xpath-action@f5b036e9d973f42c86324833fd00be90665fbf77 # v1.0.0 with: filename: ${{ env.APP_NAME }}/appinfo/info.xml expression: "//info//dependencies//nextcloud/@min-version" @@ -78,7 +78,7 @@ jobs: - name: Set up node ${{ steps.versions.outputs.nodeVersion }} # Skip if no package.json if: ${{ steps.versions.outputs.nodeVersion }} - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: ${{ steps.versions.outputs.nodeVersion }} @@ -94,7 +94,7 @@ jobs: filename: ${{ env.APP_NAME }}/appinfo/info.xml - name: Set up php ${{ steps.php-versions.outputs.php-min }} - uses: shivammathur/setup-php@9e72090525849c5e82e596468b86eb55e9cc5401 # v2.32.0 + uses: shivammathur/setup-php@ccf2c627fe61b1b4d924adfcbd19d661a18133a0 # v2.35.2 with: php-version: ${{ steps.php-versions.outputs.php-min }} coverage: none @@ -156,7 +156,7 @@ jobs: unzip latest-$NCVERSION.zip - name: Checkout server master fallback - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 if: ${{ steps.server-checkout.outcome != 'success' }} with: persist-credentials: false @@ -180,7 +180,7 @@ jobs: tar -zcvf ${{ env.APP_NAME }}.tar.gz ${{ env.APP_NAME }} - name: Attach tarball to github release - uses: svenstaro/upload-release-action@04733e069f2d7f7f0b4aebc4fbdbce8613b03ccd # v2 + uses: svenstaro/upload-release-action@81c65b7cd4de9b2570615ce3aad67a41de5b1a13 # v2.11.2 id: attach_to_release with: repo_token: ${{ secrets.GITHUB_TOKEN }} @@ -190,7 +190,7 @@ jobs: overwrite: true - name: Upload app to Nextcloud appstore - uses: nextcloud-releases/nextcloud-appstore-push-action@a011fe619bcf6e77ddebc96f9908e1af4071b9c1 # v1 + uses: nextcloud-releases/nextcloud-appstore-push-action@a011fe619bcf6e77ddebc96f9908e1af4071b9c1 # v1.0.3 with: app_name: ${{ env.APP_NAME }} appstore_token: ${{ secrets.APPSTORE_TOKEN }} diff --git a/.github/workflows/appstore-build-publish.yml.patch b/.github/workflows/appstore-build-publish.yml.patch index cead0770..5915354f 100644 --- a/.github/workflows/appstore-build-publish.yml.patch +++ b/.github/workflows/appstore-build-publish.yml.patch @@ -6,7 +6,7 @@ index 316ba14..3cb9983 100644 if: ${{ github.repository_owner == 'nextcloud-releases' }} steps: -+ - uses: cachix/install-nix-action@02a151ada4993995686f9ed4f1be7cfbb229e56f # v31 ++ - uses: cachix/install-nix-action@fc6e360bedc9ee72d75e701397f0bb30dce77568 # v31.5.2 + - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 + with: + name: notify-push diff --git a/.github/workflows/lint-info-xml.yml b/.github/workflows/lint-info-xml.yml index 25b65504..78610590 100644 --- a/.github/workflows/lint-info-xml.yml +++ b/.github/workflows/lint-info-xml.yml @@ -24,7 +24,7 @@ jobs: name: info.xml lint steps: - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false diff --git a/.github/workflows/lint-php-cs.yml b/.github/workflows/lint-php-cs.yml index 681ecca6..b2d8b7b2 100644 --- a/.github/workflows/lint-php-cs.yml +++ b/.github/workflows/lint-php-cs.yml @@ -25,7 +25,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false @@ -34,7 +34,7 @@ jobs: uses: icewind1991/nextcloud-version-matrix@58becf3b4bb6dc6cef677b15e2fd8e7d48c0908f # v1.3.1 - name: Set up php${{ steps.versions.outputs.php-min }} - uses: shivammathur/setup-php@9e72090525849c5e82e596468b86eb55e9cc5401 # v2.32.0 + uses: shivammathur/setup-php@ccf2c627fe61b1b4d924adfcbd19d661a18133a0 # v2.35.2 with: php-version: ${{ steps.versions.outputs.php-min }} extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite @@ -45,7 +45,7 @@ jobs: - name: Install dependencies run: | - composer remove nextcloud/ocp --dev + composer remove nextcloud/ocp --dev --no-scripts composer i - name: Lint diff --git a/.github/workflows/lint-php.yml b/.github/workflows/lint-php.yml index cdb2ba45..119aa32a 100644 --- a/.github/workflows/lint-php.yml +++ b/.github/workflows/lint-php.yml @@ -24,7 +24,7 @@ jobs: php-versions: ${{ steps.versions.outputs.php-versions }} steps: - name: Checkout app - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false @@ -43,12 +43,12 @@ jobs: steps: - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false - name: Set up php ${{ matrix.php-versions }} - uses: shivammathur/setup-php@9e72090525849c5e82e596468b86eb55e9cc5401 # v2.32.0 + uses: shivammathur/setup-php@ccf2c627fe61b1b4d924adfcbd19d661a18133a0 # v2.35.2 with: php-version: ${{ matrix.php-versions }} extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite diff --git a/.github/workflows/phpunit-mysql.yml b/.github/workflows/phpunit-mysql.yml deleted file mode 100644 index c53d2984..00000000 --- a/.github/workflows/phpunit-mysql.yml +++ /dev/null @@ -1,200 +0,0 @@ -# This workflow is provided via the organization template repository -# -# https://github.com/nextcloud/.github -# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization -# -# SPDX-FileCopyrightText: 2022-2024 Nextcloud GmbH and Nextcloud contributors -# SPDX-License-Identifier: MIT - -name: PHPUnit MySQL - -on: pull_request - -permissions: - contents: read - -concurrency: - group: phpunit-mysql-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -jobs: - matrix: - runs-on: ubuntu-latest-low - outputs: - matrix: ${{ steps.versions.outputs.sparse-matrix }} - steps: - - name: Checkout app - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: false - - - name: Get version matrix - id: versions - uses: icewind1991/nextcloud-version-matrix@58becf3b4bb6dc6cef677b15e2fd8e7d48c0908f # v1.3.1 - with: - matrix: '{"mysql-versions": ["8.4"]}' - - changes: - runs-on: ubuntu-latest-low - permissions: - contents: read - pull-requests: read - - outputs: - src: ${{ steps.changes.outputs.src}} - - steps: - - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 - id: changes - continue-on-error: true - with: - filters: | - src: - - '.github/workflows/**' - - 'appinfo/**' - - 'lib/**' - - 'templates/**' - - 'tests/**' - - 'vendor/**' - - 'vendor-bin/**' - - '.php-cs-fixer.dist.php' - - 'composer.json' - - 'composer.lock' - - phpunit-mysql: - runs-on: ubuntu-latest - - needs: [changes, matrix] - if: needs.changes.outputs.src != 'false' - - strategy: - matrix: ${{ fromJson(needs.matrix.outputs.matrix) }} - - name: MySQL ${{ matrix.mysql-versions }} PHP ${{ matrix.php-versions }} Nextcloud ${{ matrix.server-versions }} - - services: - mysql: - image: ghcr.io/nextcloud/continuous-integration-mysql-${{ matrix.mysql-versions }}:latest - ports: - - 4444:3306/tcp - env: - MYSQL_ROOT_PASSWORD: rootpassword - options: --health-cmd="mysqladmin ping" --health-interval 5s --health-timeout 2s --health-retries 10 - - steps: - - name: Set app env - if: ${{ env.APP_NAME == '' }} - run: | - # Split and keep last - echo "APP_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV - - - name: Checkout server - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: false - submodules: true - repository: nextcloud/server - ref: ${{ matrix.server-versions }} - - - name: Checkout app - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: false - path: apps/${{ env.APP_NAME }} - - - name: Set up php ${{ matrix.php-versions }} - uses: shivammathur/setup-php@9e72090525849c5e82e596468b86eb55e9cc5401 # v2.32.0 - with: - php-version: ${{ matrix.php-versions }} - # https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation - extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, mysql, pdo_mysql - coverage: none - ini-file: development - # Temporary workaround for missing pcntl_* in PHP 8.3 - ini-values: disable_functions= - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Enable ONLY_FULL_GROUP_BY MySQL option - run: | - echo "SET GLOBAL sql_mode=(SELECT CONCAT(@@sql_mode,',ONLY_FULL_GROUP_BY'));" | mysql -h 127.0.0.1 -P 4444 -u root -prootpassword - echo 'SELECT @@sql_mode;' | mysql -h 127.0.0.1 -P 4444 -u root -prootpassword - - - name: Check composer file existence - id: check_composer - uses: andstor/file-existence-action@076e0072799f4942c8bc574a82233e1e4d13e9d6 # v3.0.0 - with: - files: apps/${{ env.APP_NAME }}/composer.json - - - name: Set up dependencies - # Only run if phpunit config file exists - if: steps.check_composer.outputs.files_exists == 'true' - working-directory: apps/${{ env.APP_NAME }} - run: | - composer remove nextcloud/ocp --dev - composer i - - - name: Set up Nextcloud - env: - DB_PORT: 4444 - run: | - mkdir data - ./occ maintenance:install --verbose --database=mysql --database-name=nextcloud --database-host=127.0.0.1 --database-port=$DB_PORT --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass admin - ./occ app:enable --force ${{ env.APP_NAME }} - - - name: Check PHPUnit script is defined - id: check_phpunit - continue-on-error: true - working-directory: apps/${{ env.APP_NAME }} - run: | - composer run --list | grep '^ test:unit ' | wc -l | grep 1 - - - name: PHPUnit - # Only run if phpunit config file exists - if: steps.check_phpunit.outcome == 'success' - working-directory: apps/${{ env.APP_NAME }} - run: composer run test:unit - - - name: Check PHPUnit integration script is defined - id: check_integration - continue-on-error: true - working-directory: apps/${{ env.APP_NAME }} - run: | - composer run --list | grep '^ test:integration ' | wc -l | grep 1 - - - name: Run Nextcloud - # Only run if phpunit integration config file exists - if: steps.check_integration.outcome == 'success' - run: php -S localhost:8080 & - - - name: PHPUnit integration - # Only run if phpunit integration config file exists - if: steps.check_integration.outcome == 'success' - working-directory: apps/${{ env.APP_NAME }} - run: composer run test:integration - - - name: Print logs - if: always() - run: | - cat data/nextcloud.log - - - name: Skipped - # Fail the action when neither unit nor integration tests ran - if: steps.check_phpunit.outcome == 'failure' && steps.check_integration.outcome == 'failure' - run: | - echo 'Neither PHPUnit nor PHPUnit integration tests are specified in composer.json scripts' - exit 1 - - summary: - permissions: - contents: none - runs-on: ubuntu-latest-low - needs: [changes, phpunit-mysql] - - if: always() - - name: phpunit-mysql-summary - - steps: - - name: Summary status - run: if ${{ needs.changes.outputs.src != 'false' && needs.phpunit-mysql.result != 'success' }}; then exit 1; fi diff --git a/.github/workflows/phpunit-oci.yml b/.github/workflows/phpunit-oci.yml deleted file mode 100644 index 743afb3a..00000000 --- a/.github/workflows/phpunit-oci.yml +++ /dev/null @@ -1,208 +0,0 @@ -# This workflow is provided via the organization template repository -# -# https://github.com/nextcloud/.github -# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization -# -# SPDX-FileCopyrightText: 2022-2024 Nextcloud GmbH and Nextcloud contributors -# SPDX-License-Identifier: MIT - -name: PHPUnit OCI - -on: pull_request - -permissions: - contents: read - -concurrency: - group: phpunit-oci-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -jobs: - matrix: - runs-on: ubuntu-latest-low - outputs: - php-version: ${{ steps.versions.outputs.php-available-list }} - server-max: ${{ steps.versions.outputs.branches-max-list }} - steps: - - name: Checkout app - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: false - - - name: Get version matrix - id: versions - uses: icewind1991/nextcloud-version-matrix@58becf3b4bb6dc6cef677b15e2fd8e7d48c0908f # v1.3.1 - - changes: - runs-on: ubuntu-latest-low - permissions: - contents: read - pull-requests: read - - outputs: - src: ${{ steps.changes.outputs.src }} - - steps: - - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 - id: changes - continue-on-error: true - with: - filters: | - src: - - '.github/workflows/**' - - 'appinfo/**' - - 'lib/**' - - 'templates/**' - - 'tests/**' - - 'vendor/**' - - 'vendor-bin/**' - - '.php-cs-fixer.dist.php' - - 'composer.json' - - 'composer.lock' - - phpunit-oci: - runs-on: ubuntu-latest - - needs: [changes, matrix] - if: needs.changes.outputs.src != 'false' - - strategy: - matrix: - php-versions: ${{ fromJson(needs.matrix.outputs.php-version) }} - server-versions: ${{ fromJson(needs.matrix.outputs.server-max) }} - - name: OCI PHP ${{ matrix.php-versions }} Nextcloud ${{ matrix.server-versions }} - - services: - oracle: - image: ghcr.io/gvenzl/oracle-xe:11 - - # Provide passwords and other environment variables to container - env: - ORACLE_RANDOM_PASSWORD: true - APP_USER: autotest - APP_USER_PASSWORD: owncloud - - # Forward Oracle port - ports: - - 1521:1521/tcp - - # Provide healthcheck script options for startup - options: >- - --health-cmd healthcheck.sh - --health-interval 10s - --health-timeout 5s - --health-retries 10 - - steps: - - name: Set app env - if: ${{ env.APP_NAME == '' }} - run: | - # Split and keep last - echo "APP_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV - - - name: Checkout server - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: false - submodules: true - repository: nextcloud/server - ref: ${{ matrix.server-versions }} - - - name: Checkout app - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: false - path: apps/${{ env.APP_NAME }} - - - name: Set up php ${{ matrix.php-versions }} - uses: shivammathur/setup-php@9e72090525849c5e82e596468b86eb55e9cc5401 # v2.32.0 - with: - php-version: ${{ matrix.php-versions }} - # https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation - extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, oci8 - coverage: none - ini-file: development - # Temporary workaround for missing pcntl_* in PHP 8.3 - ini-values: disable_functions= - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Check composer file existence - id: check_composer - uses: andstor/file-existence-action@076e0072799f4942c8bc574a82233e1e4d13e9d6 # v3.0.0 - with: - files: apps/${{ env.APP_NAME }}/composer.json - - - name: Set up dependencies - # Only run if phpunit config file exists - if: steps.check_composer.outputs.files_exists == 'true' - working-directory: apps/${{ env.APP_NAME }} - run: | - composer remove nextcloud/ocp --dev - composer i - - - name: Set up Nextcloud - env: - DB_PORT: 1521 - run: | - mkdir data - ./occ maintenance:install --verbose --database=oci --database-name=XE --database-host=127.0.0.1 --database-port=$DB_PORT --database-user=autotest --database-pass=owncloud --admin-user admin --admin-pass admin - ./occ app:enable --force ${{ env.APP_NAME }} - - - name: Check PHPUnit script is defined - id: check_phpunit - continue-on-error: true - working-directory: apps/${{ env.APP_NAME }} - run: | - composer run --list | grep '^ test:unit ' | wc -l | grep 1 - - - name: PHPUnit - # Only run if phpunit config file exists - if: steps.check_phpunit.outcome == 'success' - working-directory: apps/${{ env.APP_NAME }} - run: composer run test:unit - - - name: Check PHPUnit integration script is defined - id: check_integration - continue-on-error: true - working-directory: apps/${{ env.APP_NAME }} - run: | - composer run --list | grep '^ test:integration ' | wc -l | grep 1 - - - name: Run Nextcloud - # Only run if phpunit integration config file exists - if: steps.check_integration.outcome == 'success' - run: php -S localhost:8080 & - - - name: PHPUnit integration - # Only run if phpunit integration config file exists - if: steps.check_integration.outcome == 'success' - working-directory: apps/${{ env.APP_NAME }} - run: composer run test:integration - - - name: Print logs - if: always() - run: | - cat data/nextcloud.log - - - name: Skipped - # Fail the action when neither unit nor integration tests ran - if: steps.check_phpunit.outcome == 'failure' && steps.check_integration.outcome == 'failure' - run: | - echo 'Neither PHPUnit nor PHPUnit integration tests are specified in composer.json scripts' - exit 1 - - summary: - permissions: - contents: none - runs-on: ubuntu-latest-low - needs: [changes, phpunit-oci] - - if: always() - - name: phpunit-oci-summary - - steps: - - name: Summary status - run: if ${{ needs.changes.outputs.src != 'false' && needs.phpunit-oci.result != 'success' }}; then exit 1; fi diff --git a/.github/workflows/phpunit-pgsql.yml b/.github/workflows/phpunit-pgsql.yml deleted file mode 100644 index 320dc19c..00000000 --- a/.github/workflows/phpunit-pgsql.yml +++ /dev/null @@ -1,198 +0,0 @@ -# This workflow is provided via the organization template repository -# -# https://github.com/nextcloud/.github -# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization -# -# SPDX-FileCopyrightText: 2022-2024 Nextcloud GmbH and Nextcloud contributors -# SPDX-License-Identifier: MIT - -name: PHPUnit PostgreSQL - -on: pull_request - -permissions: - contents: read - -concurrency: - group: phpunit-pgsql-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -jobs: - matrix: - runs-on: ubuntu-latest-low - outputs: - php-version: ${{ steps.versions.outputs.php-available-list }} - server-max: ${{ steps.versions.outputs.branches-max-list }} - steps: - - name: Checkout app - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: false - - - name: Get version matrix - id: versions - uses: icewind1991/nextcloud-version-matrix@58becf3b4bb6dc6cef677b15e2fd8e7d48c0908f # v1.3.1 - - changes: - runs-on: ubuntu-latest-low - permissions: - contents: read - pull-requests: read - - outputs: - src: ${{ steps.changes.outputs.src }} - - steps: - - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 - id: changes - continue-on-error: true - with: - filters: | - src: - - '.github/workflows/**' - - 'appinfo/**' - - 'lib/**' - - 'templates/**' - - 'tests/**' - - 'vendor/**' - - 'vendor-bin/**' - - '.php-cs-fixer.dist.php' - - 'composer.json' - - 'composer.lock' - - phpunit-pgsql: - runs-on: ubuntu-latest - - needs: [changes, matrix] - if: needs.changes.outputs.src != 'false' - - strategy: - matrix: - php-versions: ${{ fromJson(needs.matrix.outputs.php-version) }} - server-versions: ${{ fromJson(needs.matrix.outputs.server-max) }} - - name: PostgreSQL PHP ${{ matrix.php-versions }} Nextcloud ${{ matrix.server-versions }} - - services: - postgres: - image: ghcr.io/nextcloud/continuous-integration-postgres-14:latest - ports: - - 4444:5432/tcp - env: - POSTGRES_USER: root - POSTGRES_PASSWORD: rootpassword - POSTGRES_DB: nextcloud - options: --health-cmd pg_isready --health-interval 5s --health-timeout 2s --health-retries 5 - - steps: - - name: Set app env - if: ${{ env.APP_NAME == '' }} - run: | - # Split and keep last - echo "APP_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV - - - name: Checkout server - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: false - submodules: true - repository: nextcloud/server - ref: ${{ matrix.server-versions }} - - - name: Checkout app - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - persist-credentials: false - path: apps/${{ env.APP_NAME }} - - - name: Set up php ${{ matrix.php-versions }} - uses: shivammathur/setup-php@9e72090525849c5e82e596468b86eb55e9cc5401 # v2.32.0 - with: - php-version: ${{ matrix.php-versions }} - # https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation - extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, pgsql, pdo_pgsql - coverage: none - ini-file: development - # Temporary workaround for missing pcntl_* in PHP 8.3 - ini-values: disable_functions= - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Check composer file existence - id: check_composer - uses: andstor/file-existence-action@076e0072799f4942c8bc574a82233e1e4d13e9d6 # v3.0.0 - with: - files: apps/${{ env.APP_NAME }}/composer.json - - - name: Set up dependencies - # Only run if phpunit config file exists - if: steps.check_composer.outputs.files_exists == 'true' - working-directory: apps/${{ env.APP_NAME }} - run: | - composer remove nextcloud/ocp --dev - composer i - - - name: Set up Nextcloud - env: - DB_PORT: 4444 - run: | - mkdir data - ./occ maintenance:install --verbose --database=pgsql --database-name=nextcloud --database-host=127.0.0.1 --database-port=$DB_PORT --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass admin - ./occ app:enable --force ${{ env.APP_NAME }} - - - name: Check PHPUnit script is defined - id: check_phpunit - continue-on-error: true - working-directory: apps/${{ env.APP_NAME }} - run: | - composer run --list | grep '^ test:unit ' | wc -l | grep 1 - - - name: PHPUnit - # Only run if phpunit config file exists - if: steps.check_phpunit.outcome == 'success' - working-directory: apps/${{ env.APP_NAME }} - run: composer run test:unit - - - name: Check PHPUnit integration script is defined - id: check_integration - continue-on-error: true - working-directory: apps/${{ env.APP_NAME }} - run: | - composer run --list | grep '^ test:integration ' | wc -l | grep 1 - - - name: Run Nextcloud - # Only run if phpunit integration config file exists - if: steps.check_integration.outcome == 'success' - run: php -S localhost:8080 & - - - name: PHPUnit integration - # Only run if phpunit integration config file exists - if: steps.check_integration.outcome == 'success' - working-directory: apps/${{ env.APP_NAME }} - run: composer run test:integration - - - name: Print logs - if: always() - run: | - cat data/nextcloud.log - - - name: Skipped - # Fail the action when neither unit nor integration tests ran - if: steps.check_phpunit.outcome == 'failure' && steps.check_integration.outcome == 'failure' - run: | - echo 'Neither PHPUnit nor PHPUnit integration tests are specified in composer.json scripts' - exit 1 - - summary: - permissions: - contents: none - runs-on: ubuntu-latest-low - needs: [changes, phpunit-pgsql] - - if: always() - - name: phpunit-pgsql-summary - - steps: - - name: Summary status - run: if ${{ needs.changes.outputs.src != 'false' && needs.phpunit-pgsql.result != 'success' }}; then exit 1; fi diff --git a/.github/workflows/phpunit-sqlite.yml b/.github/workflows/phpunit-sqlite.yml index a61dc4cd..71b6c38b 100644 --- a/.github/workflows/phpunit-sqlite.yml +++ b/.github/workflows/phpunit-sqlite.yml @@ -25,7 +25,7 @@ jobs: server-max: ${{ steps.versions.outputs.branches-max-list }} steps: - name: Checkout app - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false @@ -66,6 +66,17 @@ jobs: needs: [changes, matrix] if: needs.changes.outputs.src != 'false' + services: + redis: + image: redis + options: >- + --health-cmd "redis-cli ping" + --health-interval 10s + --health-timeout 5s + --health-retries 5 + ports: + - 6379:6379 + strategy: matrix: php-versions: ${{ fromJson(needs.matrix.outputs.php-version) }} @@ -81,7 +92,7 @@ jobs: echo "APP_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV - name: Checkout server - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false submodules: true @@ -89,13 +100,13 @@ jobs: ref: ${{ matrix.server-versions }} - name: Checkout app - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false path: apps/${{ env.APP_NAME }} - name: Set up php ${{ matrix.php-versions }} - uses: shivammathur/setup-php@9e72090525849c5e82e596468b86eb55e9cc5401 # v2.32.0 + uses: shivammathur/setup-php@ccf2c627fe61b1b4d924adfcbd19d661a18133a0 # v2.35.2 with: php-version: ${{ matrix.php-versions }} # https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation @@ -118,7 +129,7 @@ jobs: if: steps.check_composer.outputs.files_exists == 'true' working-directory: apps/${{ env.APP_NAME }} run: | - composer remove nextcloud/ocp --dev + composer remove nextcloud/ocp --dev --no-scripts composer i - name: Set up Nextcloud diff --git a/.github/workflows/pr-feedback.yml b/.github/workflows/pr-feedback.yml index 98e9fada..f4c0477c 100644 --- a/.github/workflows/pr-feedback.yml +++ b/.github/workflows/pr-feedback.yml @@ -36,7 +36,7 @@ jobs: blocklist=$(curl https://raw.githubusercontent.com/nextcloud/.github/master/non-community-usernames.txt | paste -s -d, -) echo "blocklist=$blocklist" >> "$GITHUB_OUTPUT" - - uses: nextcloud/pr-feedback-action@1883b38a033fb16f576875e0cf45f98b857655c4 # main + - uses: nextcloud/pr-feedback-action@f0cab224dea8e1f282f9451de322f323c78fc7a5 # main with: feedback-message: | Hello there, @@ -50,6 +50,6 @@ jobs: (If you believe you should not receive this message, you can add yourself to the [blocklist](https://github.com/nextcloud/.github/blob/master/non-community-usernames.txt).) days-before-feedback: 14 - start-date: '2024-04-30' + start-date: '2025-06-12' exempt-authors: '${{ steps.blocklist.outputs.blocklist }},${{ steps.scrape.outputs.users }}' exempt-bots: true diff --git a/.github/workflows/psalm-matrix.yml b/.github/workflows/psalm-matrix.yml index 033a6444..e0f19269 100644 --- a/.github/workflows/psalm-matrix.yml +++ b/.github/workflows/psalm-matrix.yml @@ -24,7 +24,7 @@ jobs: ocp-matrix: ${{ steps.versions.outputs.ocp-matrix }} steps: - name: Checkout app - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false @@ -46,15 +46,15 @@ jobs: name: static-psalm-analysis ${{ matrix.ocp-version }} steps: - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false - - name: Set up php${{ matrix.php-versions }} - uses: shivammathur/setup-php@9e72090525849c5e82e596468b86eb55e9cc5401 # v2.32.0 + - name: Set up php${{ matrix.php-min }} + uses: shivammathur/setup-php@ccf2c627fe61b1b4d924adfcbd19d661a18133a0 # v2.35.2 with: - php-version: ${{ matrix.php-versions }} - extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite + php-version: ${{ matrix.php-min }} + extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite, redis coverage: none ini-file: development # Temporary workaround for missing pcntl_* in PHP 8.3 @@ -64,9 +64,11 @@ jobs: - name: Install dependencies run: | - composer remove nextcloud/ocp --dev + composer remove nextcloud/ocp --dev --no-scripts composer i + - name: Check for vulnerable PHP dependencies + run: composer require --dev roave/security-advisories:dev-latest - name: Install dependencies # zizmor: ignore[template-injection] run: composer require --dev 'nextcloud/ocp:${{ matrix.ocp-version }}' --ignore-platform-reqs --with-dependencies diff --git a/.github/workflows/reuse.yml b/.github/workflows/reuse.yml index 0d8e1962..ec4ad71c 100644 --- a/.github/workflows/reuse.yml +++ b/.github/workflows/reuse.yml @@ -16,10 +16,10 @@ permissions: jobs: reuse-compliance-check: - runs-on: ubuntu-latest + runs-on: ubuntu-latest-low steps: - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 60bb945d..caa42ba7 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -15,6 +15,7 @@ ->ignoreVCSIgnored(true) ->notPath('build') ->notPath('l10n') + ->notPath('tests/stubs') ->notPath('lib/Vendor') ->notPath('src') ->notPath('tests/configs') diff --git a/REUSE.toml b/REUSE.toml index bcd2cbd2..d76c9152 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -28,3 +28,9 @@ path = ["vendor-bin/**"] precedence = "aggregate" SPDX-FileCopyrightText = "2024 Nextcloud GmbH and Nextcloud contributors" SPDX-License-Identifier = "AGPL-3.0-or-later" + +[[annotations]] +path = ["tests/stubs/symfony_component_**"] +precedence = "aggregate" +SPDX-FileCopyrightText = "none" +SPDX-License-Identifier = "MIT" diff --git a/appinfo/info.xml b/appinfo/info.xml index 521ee0d3..186eca25 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -11,7 +11,7 @@ - 1.1.1 + 1.2.0 agpl Robin Appelman NotifyPush @@ -27,7 +27,7 @@ Once the app is installed, the push binary needs to be setup. You can either use https://github.com/nextcloud/notify_push/issues - + diff --git a/psalm.xml b/psalm.xml index 970727d4..55758e1b 100644 --- a/psalm.xml +++ b/psalm.xml @@ -21,5 +21,14 @@ + + + + + + + + + diff --git a/tests/stubs/symfony_component_console_command_command.php b/tests/stubs/symfony_component_console_command_command.php new file mode 100644 index 00000000..59094f71 --- /dev/null +++ b/tests/stubs/symfony_component_console_command_command.php @@ -0,0 +1,442 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Command; + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Attribute\AsCommand; +use Symfony\Component\Console\Completion\CompletionInput; +use Symfony\Component\Console\Completion\CompletionSuggestions; +use Symfony\Component\Console\Completion\Suggestion; +use Symfony\Component\Console\Exception\ExceptionInterface; +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\LogicException; +use Symfony\Component\Console\Helper\HelperInterface; +use Symfony\Component\Console\Helper\HelperSet; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Base class for all commands. + * + * @author Fabien Potencier + */ +class Command +{ + // see https://tldp.org/LDP/abs/html/exitcodes.html + public const SUCCESS = 0; + public const FAILURE = 1; + public const INVALID = 2; + + /** + * @var string|null The default command name + * + * @deprecated since Symfony 6.1, use the AsCommand attribute instead + */ + protected static $defaultName; + + /** + * @var string|null The default command description + * + * @deprecated since Symfony 6.1, use the AsCommand attribute instead + */ + protected static $defaultDescription; + + public static function getDefaultName(): ?string + { + } + + public static function getDefaultDescription(): ?string + { + } + + /** + * @param string|null $name The name of the command; passing null means it must be set in configure() + * + * @throws LogicException When the command name is empty + */ + public function __construct(?string $name = null) + { + } + + /** + * Ignores validation errors. + * + * This is mainly useful for the help command. + * + * @return void + */ + public function ignoreValidationErrors() + { + } + + /** + * @return void + */ + public function setApplication(?Application $application = null) + { + } + + /** + * @return void + */ + public function setHelperSet(HelperSet $helperSet) + { + } + + /** + * Gets the helper set. + */ + public function getHelperSet(): ?HelperSet + { + } + + /** + * Gets the application instance for this command. + */ + public function getApplication(): ?Application + { + } + + /** + * Checks whether the command is enabled or not in the current environment. + * + * Override this to check for x or y and return false if the command cannot + * run properly under the current conditions. + * + * @return bool + */ + public function isEnabled() + { + } + + /** + * Configures the current command. + * + * @return void + */ + protected function configure() + { + } + + /** + * Executes the current command. + * + * This method is not abstract because you can use this class + * as a concrete class. In this case, instead of defining the + * execute() method, you set the code to execute by passing + * a Closure to the setCode() method. + * + * @return int 0 if everything went fine, or an exit code + * + * @throws LogicException When this abstract method is not implemented + * + * @see setCode() + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + } + + /** + * Interacts with the user. + * + * This method is executed before the InputDefinition is validated. + * This means that this is the only place where the command can + * interactively ask for values of missing required arguments. + * + * @return void + */ + protected function interact(InputInterface $input, OutputInterface $output) + { + } + + /** + * Initializes the command after the input has been bound and before the input + * is validated. + * + * This is mainly useful when a lot of commands extends one main command + * where some things need to be initialized based on the input arguments and options. + * + * @see InputInterface::bind() + * @see InputInterface::validate() + * + * @return void + */ + protected function initialize(InputInterface $input, OutputInterface $output) + { + } + + /** + * Runs the command. + * + * The code to execute is either defined directly with the + * setCode() method or by overriding the execute() method + * in a sub-class. + * + * @return int The command exit code + * + * @throws ExceptionInterface When input binding fails. Bypass this by calling {@link ignoreValidationErrors()}. + * + * @see setCode() + * @see execute() + */ + public function run(InputInterface $input, OutputInterface $output): int + { + } + + /** + * Adds suggestions to $suggestions for the current completion input (e.g. option or argument). + */ + public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void + { + } + + /** + * Sets the code to execute when running this command. + * + * If this method is used, it overrides the code defined + * in the execute() method. + * + * @param callable $code A callable(InputInterface $input, OutputInterface $output) + * + * @return $this + * + * @throws InvalidArgumentException + * + * @see execute() + */ + public function setCode(callable $code): static + { + } + + /** + * Merges the application definition with the command definition. + * + * This method is not part of public API and should not be used directly. + * + * @param bool $mergeArgs Whether to merge or not the Application definition arguments to Command definition arguments + * + * @internal + */ + public function mergeApplicationDefinition(bool $mergeArgs = true): void + { + } + + /** + * Sets an array of argument and option instances. + * + * @return $this + */ + public function setDefinition(array|InputDefinition $definition): static + { + } + + /** + * Gets the InputDefinition attached to this Command. + */ + public function getDefinition(): InputDefinition + { + } + + /** + * Gets the InputDefinition to be used to create representations of this Command. + * + * Can be overridden to provide the original command representation when it would otherwise + * be changed by merging with the application InputDefinition. + * + * This method is not part of public API and should not be used directly. + */ + public function getNativeDefinition(): InputDefinition + { + } + + /** + * Adds an argument. + * + * @param $mode The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL + * @param $default The default value (for InputArgument::OPTIONAL mode only) + * @param array|\Closure(CompletionInput,CompletionSuggestions):list $suggestedValues The values used for input completion + * + * @return $this + * + * @throws InvalidArgumentException When argument mode is not valid + */ + public function addArgument(string $name, ?int $mode = null, string $description = '', mixed $default = null): static + { + } + + /** + * Adds an option. + * + * @param $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts + * @param $mode The option mode: One of the InputOption::VALUE_* constants + * @param $default The default value (must be null for InputOption::VALUE_NONE) + * @param array|\Closure(CompletionInput,CompletionSuggestions):list $suggestedValues The values used for input completion + * + * @return $this + * + * @throws InvalidArgumentException If option mode is invalid or incompatible + */ + public function addOption(string $name, string|array|null $shortcut = null, ?int $mode = null, string $description = '', mixed $default = null): static + { + } + + /** + * Sets the name of the command. + * + * This method can set both the namespace and the name if + * you separate them by a colon (:) + * + * $command->setName('foo:bar'); + * + * @return $this + * + * @throws InvalidArgumentException When the name is invalid + */ + public function setName(string $name): static + { + } + + /** + * Sets the process title of the command. + * + * This feature should be used only when creating a long process command, + * like a daemon. + * + * @return $this + */ + public function setProcessTitle(string $title): static + { + } + + /** + * Returns the command name. + */ + public function getName(): ?string + { + } + + /** + * @param bool $hidden Whether or not the command should be hidden from the list of commands + * + * @return $this + */ + public function setHidden(bool $hidden = true): static + { + } + + /** + * @return bool whether the command should be publicly shown or not + */ + public function isHidden(): bool + { + } + + /** + * Sets the description for the command. + * + * @return $this + */ + public function setDescription(string $description): static + { + } + + /** + * Returns the description for the command. + */ + public function getDescription(): string + { + } + + /** + * Sets the help for the command. + * + * @return $this + */ + public function setHelp(string $help): static + { + } + + /** + * Returns the help for the command. + */ + public function getHelp(): string + { + } + + /** + * Returns the processed help for the command replacing the %command.name% and + * %command.full_name% patterns with the real values dynamically. + */ + public function getProcessedHelp(): string + { + } + + /** + * Sets the aliases for the command. + * + * @param string[] $aliases An array of aliases for the command + * + * @return $this + * + * @throws InvalidArgumentException When an alias is invalid + */ + public function setAliases(iterable $aliases): static + { + } + + /** + * Returns the aliases for the command. + */ + public function getAliases(): array + { + } + + /** + * Returns the synopsis for the command. + * + * @param bool $short Whether to show the short version of the synopsis (with options folded) or not + */ + public function getSynopsis(bool $short = false): string + { + } + + /** + * Add a command usage example, it'll be prefixed with the command name. + * + * @return $this + */ + public function addUsage(string $usage): static + { + } + + /** + * Returns alternative usages of the command. + */ + public function getUsages(): array + { + } + + /** + * Gets a helper instance by name. + * + * @return HelperInterface + * + * @throws LogicException if no HelperSet is defined + * @throws InvalidArgumentException if the helper is not defined + */ + public function getHelper(string $name): mixed + { + } +} diff --git a/tests/stubs/symfony_component_console_helper_table.php b/tests/stubs/symfony_component_console_helper_table.php new file mode 100644 index 00000000..373b3fff --- /dev/null +++ b/tests/stubs/symfony_component_console_helper_table.php @@ -0,0 +1,218 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\RuntimeException; +use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Formatter\WrappableOutputFormatterInterface; +use Symfony\Component\Console\Output\ConsoleSectionOutput; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Provides helpers to display a table. + * + * @author Fabien Potencier + * @author Саша Стаменковић + * @author Abdellatif Ait boudad + * @author Max Grigorian + * @author Dany Maillard + */ +class Table +{ + private const SEPARATOR_TOP = 0; + private const SEPARATOR_TOP_BOTTOM = 1; + private const SEPARATOR_MID = 2; + private const SEPARATOR_BOTTOM = 3; + private const BORDER_OUTSIDE = 0; + private const BORDER_INSIDE = 1; + private const DISPLAY_ORIENTATION_DEFAULT = 'default'; + private const DISPLAY_ORIENTATION_HORIZONTAL = 'horizontal'; + private const DISPLAY_ORIENTATION_VERTICAL = 'vertical'; + + public function __construct(OutputInterface $output) + { + } + + /** + * Sets a style definition. + * + * @return void + */ + public static function setStyleDefinition(string $name, TableStyle $style) + { + } + + /** + * Gets a style definition by name. + */ + public static function getStyleDefinition(string $name): TableStyle + { + } + + /** + * Sets table style. + * + * @return $this + */ + public function setStyle(TableStyle|string $name): static + { + } + + /** + * Gets the current table style. + */ + public function getStyle(): TableStyle + { + } + + /** + * Sets table column style. + * + * @param TableStyle|string $name The style name or a TableStyle instance + * + * @return $this + */ + public function setColumnStyle(int $columnIndex, TableStyle|string $name): static + { + } + + /** + * Gets the current style for a column. + * + * If style was not set, it returns the global table style. + */ + public function getColumnStyle(int $columnIndex): TableStyle + { + } + + /** + * Sets the minimum width of a column. + * + * @return $this + */ + public function setColumnWidth(int $columnIndex, int $width): static + { + } + + /** + * Sets the minimum width of all columns. + * + * @return $this + */ + public function setColumnWidths(array $widths): static + { + } + + /** + * Sets the maximum width of a column. + * + * Any cell within this column which contents exceeds the specified width will be wrapped into multiple lines, while + * formatted strings are preserved. + * + * @return $this + */ + public function setColumnMaxWidth(int $columnIndex, int $width): static + { + } + + /** + * @return $this + */ + public function setHeaders(array $headers): static + { + } + + /** + * @return $this + */ + public function setRows(array $rows) + { + } + + /** + * @return $this + */ + public function addRows(array $rows): static + { + } + + /** + * @return $this + */ + public function addRow(TableSeparator|array $row): static + { + } + + /** + * Adds a row to the table, and re-renders the table. + * + * @return $this + */ + public function appendRow(TableSeparator|array $row): static + { + } + + /** + * @return $this + */ + public function setRow(int|string $column, array $row): static + { + } + + /** + * @return $this + */ + public function setHeaderTitle(?string $title): static + { + } + + /** + * @return $this + */ + public function setFooterTitle(?string $title): static + { + } + + /** + * @return $this + */ + public function setHorizontal(bool $horizontal = true): static + { + } + + /** + * @return $this + */ + public function setVertical(bool $vertical = true): static + { + } + + /** + * Renders table to output. + * + * Example: + * + * +---------------+-----------------------+------------------+ + * | ISBN | Title | Author | + * +---------------+-----------------------+------------------+ + * | 99921-58-10-7 | Divine Comedy | Dante Alighieri | + * | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | + * | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien | + * +---------------+-----------------------+------------------+ + * + * @return void + */ + public function render() + { + } +} diff --git a/tests/stubs/symfony_component_console_input_inputargument.php b/tests/stubs/symfony_component_console_input_inputargument.php new file mode 100644 index 00000000..8a106813 --- /dev/null +++ b/tests/stubs/symfony_component_console_input_inputargument.php @@ -0,0 +1,107 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Input; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Completion\CompletionInput; +use Symfony\Component\Console\Completion\CompletionSuggestions; +use Symfony\Component\Console\Completion\Suggestion; +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\LogicException; + +/** + * Represents a command line argument. + * + * @author Fabien Potencier + */ +class InputArgument +{ + public const REQUIRED = 1; + public const OPTIONAL = 2; + public const IS_ARRAY = 4; + + /** + * @param string $name The argument name + * @param int|null $mode The argument mode: a bit mask of self::REQUIRED, self::OPTIONAL and self::IS_ARRAY + * @param string $description A description text + * @param string|bool|int|float|array|null $default The default value (for self::OPTIONAL mode only) + * @param array|\Closure(CompletionInput,CompletionSuggestions):list $suggestedValues The values used for input completion + * + * @throws InvalidArgumentException When argument mode is not valid + */ + public function __construct(string $name, ?int $mode = null, string $description = '', string|bool|int|float|array|null $default = null, \Closure|array $suggestedValues = []) + { + } + + /** + * Returns the argument name. + */ + public function getName(): string + { + } + + /** + * Returns true if the argument is required. + * + * @return bool true if parameter mode is self::REQUIRED, false otherwise + */ + public function isRequired(): bool + { + } + + /** + * Returns true if the argument can take multiple values. + * + * @return bool true if mode is self::IS_ARRAY, false otherwise + */ + public function isArray(): bool + { + } + + /** + * Sets the default value. + * + * @return void + * + * @throws LogicException When incorrect default value is given + */ + public function setDefault(string|bool|int|float|array|null $default = null) + { + } + + /** + * Returns the default value. + */ + public function getDefault(): string|bool|int|float|array|null + { + } + + public function hasCompletion(): bool + { + } + + /** + * Adds suggestions to $suggestions for the current completion input. + * + * @see Command::complete() + */ + public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void + { + } + + /** + * Returns the description text. + */ + public function getDescription(): string + { + } +} diff --git a/tests/stubs/symfony_component_console_input_inputinterface.php b/tests/stubs/symfony_component_console_input_inputinterface.php new file mode 100644 index 00000000..352937c6 --- /dev/null +++ b/tests/stubs/symfony_component_console_input_inputinterface.php @@ -0,0 +1,180 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Input; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\RuntimeException; + +/** + * InputInterface is the interface implemented by all input classes. + * + * @author Fabien Potencier + * + * @method string __toString() Returns a stringified representation of the args passed to the command. + * InputArguments MUST be escaped as well as the InputOption values passed to the command. + */ +interface InputInterface +{ + /** + * Returns the first argument from the raw parameters (not parsed). + */ + public function getFirstArgument(): ?string + { + } + + /** + * Returns true if the raw parameters (not parsed) contain a value. + * + * This method is to be used to introspect the input parameters + * before they have been validated. It must be used carefully. + * Does not necessarily return the correct result for short options + * when multiple flags are combined in the same option. + * + * @param string|array $values The values to look for in the raw parameters (can be an array) + * @param bool $onlyParams Only check real parameters, skip those following an end of options (--) signal + */ + public function hasParameterOption(string|array $values, bool $onlyParams = false): bool + { + } + + /** + * Returns the value of a raw option (not parsed). + * + * This method is to be used to introspect the input parameters + * before they have been validated. It must be used carefully. + * Does not necessarily return the correct result for short options + * when multiple flags are combined in the same option. + * + * @param string|array $values The value(s) to look for in the raw parameters (can be an array) + * @param string|bool|int|float|array|null $default The default value to return if no result is found + * @param bool $onlyParams Only check real parameters, skip those following an end of options (--) signal + * + * @return mixed + */ + public function getParameterOption(string|array $values, string|bool|int|float|array|null $default = false, bool $onlyParams = false) + { + } + + /** + * Binds the current Input instance with the given arguments and options. + * + * @return void + * + * @throws RuntimeException + */ + public function bind(InputDefinition $definition) + { + } + + /** + * Validates the input. + * + * @return void + * + * @throws RuntimeException When not enough arguments are given + */ + public function validate() + { + } + + /** + * Returns all the given arguments merged with the default values. + * + * @return array + */ + public function getArguments(): array + { + } + + /** + * Returns the argument value for a given argument name. + * + * @return mixed + * + * @throws InvalidArgumentException When argument given doesn't exist + */ + public function getArgument(string $name) + { + } + + /** + * Sets an argument value by name. + * + * @return void + * + * @throws InvalidArgumentException When argument given doesn't exist + */ + public function setArgument(string $name, mixed $value) + { + } + + /** + * Returns true if an InputArgument object exists by name or position. + */ + public function hasArgument(string $name): bool + { + } + + /** + * Returns all the given options merged with the default values. + * + * @return array + */ + public function getOptions(): array + { + } + + /** + * Returns the option value for a given option name. + * + * @return mixed + * + * @throws InvalidArgumentException When option given doesn't exist + */ + public function getOption(string $name) + { + } + + /** + * Sets an option value by name. + * + * @return void + * + * @throws InvalidArgumentException When option given doesn't exist + */ + public function setOption(string $name, mixed $value) + { + } + + /** + * Returns true if an InputOption object exists by name. + */ + public function hasOption(string $name): bool + { + } + + /** + * Is this input means interactive? + */ + public function isInteractive(): bool + { + } + + /** + * Sets the input interactivity. + * + * @return void + */ + public function setInteractive(bool $interactive) + { + } +} diff --git a/tests/stubs/symfony_component_console_input_inputoption.php b/tests/stubs/symfony_component_console_input_inputoption.php new file mode 100644 index 00000000..ab5680e5 --- /dev/null +++ b/tests/stubs/symfony_component_console_input_inputoption.php @@ -0,0 +1,159 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Input; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Completion\CompletionInput; +use Symfony\Component\Console\Completion\CompletionSuggestions; +use Symfony\Component\Console\Completion\Suggestion; +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\LogicException; + +/** + * Represents a command line option. + * + * @author Fabien Potencier + */ +class InputOption +{ + /** + * Do not accept input for the option (e.g. --yell). This is the default behavior of options. + */ + public const VALUE_NONE = 1; + + /** + * A value must be passed when the option is used (e.g. --iterations=5 or -i5). + */ + public const VALUE_REQUIRED = 2; + + /** + * The option may or may not have a value (e.g. --yell or --yell=loud). + */ + public const VALUE_OPTIONAL = 4; + + /** + * The option accepts multiple values (e.g. --dir=/foo --dir=/bar). + */ + public const VALUE_IS_ARRAY = 8; + + /** + * The option may have either positive or negative value (e.g. --ansi or --no-ansi). + */ + public const VALUE_NEGATABLE = 16; + + /** + * @param string|array|null $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts + * @param int|null $mode The option mode: One of the VALUE_* constants + * @param string|bool|int|float|array|null $default The default value (must be null for self::VALUE_NONE) + * @param array|\Closure(CompletionInput,CompletionSuggestions):list $suggestedValues The values used for input completion + * + * @throws InvalidArgumentException If option mode is invalid or incompatible + */ + public function __construct(string $name, string|array|null $shortcut = null, ?int $mode = null, string $description = '', string|bool|int|float|array|null $default = null, array|\Closure $suggestedValues = []) + { + } + + /** + * Returns the option shortcut. + */ + public function getShortcut(): ?string + { + } + + /** + * Returns the option name. + */ + public function getName(): string + { + } + + /** + * Returns true if the option accepts a value. + * + * @return bool true if value mode is not self::VALUE_NONE, false otherwise + */ + public function acceptValue(): bool + { + } + + /** + * Returns true if the option requires a value. + * + * @return bool true if value mode is self::VALUE_REQUIRED, false otherwise + */ + public function isValueRequired(): bool + { + } + + /** + * Returns true if the option takes an optional value. + * + * @return bool true if value mode is self::VALUE_OPTIONAL, false otherwise + */ + public function isValueOptional(): bool + { + } + + /** + * Returns true if the option can take multiple values. + * + * @return bool true if mode is self::VALUE_IS_ARRAY, false otherwise + */ + public function isArray(): bool + { + } + + public function isNegatable(): bool + { + } + + /** + * @return void + */ + public function setDefault(string|bool|int|float|array|null $default = null) + { + } + + /** + * Returns the default value. + */ + public function getDefault(): string|bool|int|float|array|null + { + } + + /** + * Returns the description text. + */ + public function getDescription(): string + { + } + + public function hasCompletion(): bool + { + } + + /** + * Adds suggestions to $suggestions for the current completion input. + * + * @see Command::complete() + */ + public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void + { + } + + /** + * Checks whether the given option equals this one. + */ + public function equals(self $option): bool + { + } +} diff --git a/tests/stubs/symfony_component_console_output_outputinterface.php b/tests/stubs/symfony_component_console_output_outputinterface.php new file mode 100644 index 00000000..f0b0b2f1 --- /dev/null +++ b/tests/stubs/symfony_component_console_output_outputinterface.php @@ -0,0 +1,135 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Output; + +use Symfony\Component\Console\Formatter\OutputFormatterInterface; + +/** + * OutputInterface is the interface implemented by all Output classes. + * + * @author Fabien Potencier + */ +interface OutputInterface +{ + public const VERBOSITY_QUIET = 16; + public const VERBOSITY_NORMAL = 32; + public const VERBOSITY_VERBOSE = 64; + public const VERBOSITY_VERY_VERBOSE = 128; + public const VERBOSITY_DEBUG = 256; + + public const OUTPUT_NORMAL = 1; + public const OUTPUT_RAW = 2; + public const OUTPUT_PLAIN = 4; + + /** + * Writes a message to the output. + * + * @param bool $newline Whether to add a newline + * @param int $options A bitmask of options (one of the OUTPUT or VERBOSITY constants), + * 0 is considered the same as self::OUTPUT_NORMAL | self::VERBOSITY_NORMAL + * + * @return void + */ + public function write(string|iterable $messages, bool $newline = false, int $options = 0) + { + } + + /** + * Writes a message to the output and adds a newline at the end. + * + * @param int $options A bitmask of options (one of the OUTPUT or VERBOSITY constants), + * 0 is considered the same as self::OUTPUT_NORMAL | self::VERBOSITY_NORMAL + * + * @return void + */ + public function writeln(string|iterable $messages, int $options = 0) + { + } + + /** + * Sets the verbosity of the output. + * + * @param self::VERBOSITY_* $level + * + * @return void + */ + public function setVerbosity(int $level) + { + } + + /** + * Gets the current verbosity of the output. + * + * @return self::VERBOSITY_* + */ + public function getVerbosity(): int + { + } + + /** + * Returns whether verbosity is quiet (-q). + */ + public function isQuiet(): bool + { + } + + /** + * Returns whether verbosity is verbose (-v). + */ + public function isVerbose(): bool + { + } + + /** + * Returns whether verbosity is very verbose (-vv). + */ + public function isVeryVerbose(): bool + { + } + + /** + * Returns whether verbosity is debug (-vvv). + */ + public function isDebug(): bool + { + } + + /** + * Sets the decorated flag. + * + * @return void + */ + public function setDecorated(bool $decorated) + { + } + + /** + * Gets the decorated flag. + */ + public function isDecorated(): bool + { + } + + /** + * @return void + */ + public function setFormatter(OutputFormatterInterface $formatter) + { + } + + /** + * Returns current output formatter instance. + */ + public function getFormatter(): OutputFormatterInterface + { + } +} diff --git a/tests/stubs/symfony_component_console_question_confirmationquestion.php b/tests/stubs/symfony_component_console_question_confirmationquestion.php new file mode 100644 index 00000000..0db6fe2f --- /dev/null +++ b/tests/stubs/symfony_component_console_question_confirmationquestion.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Question; + +/** + * Represents a yes/no question. + * + * @author Fabien Potencier + */ +class ConfirmationQuestion extends Question +{ + /** + * @param string $question The question to ask to the user + * @param bool $default The default answer to return, true or false + * @param string $trueAnswerRegex A regex to match the "yes" answer + */ + public function __construct(string $question, bool $default = true, string $trueAnswerRegex = '/^y/i') + { + } +} diff --git a/tests/stubs/symfony_component_console_question_question.php b/tests/stubs/symfony_component_console_question_question.php new file mode 100644 index 00000000..c04b412b --- /dev/null +++ b/tests/stubs/symfony_component_console_question_question.php @@ -0,0 +1,207 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Question; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\LogicException; + +/** + * Represents a Question. + * + * @author Fabien Potencier + */ +class Question +{ + /** + * @param string $question The question to ask to the user + * @param string|bool|int|float|null $default The default answer to return if the user enters nothing + */ + public function __construct(string $question, string|bool|int|float|null $default = null) + { + } + + /** + * Returns the question. + */ + public function getQuestion(): string + { + } + + /** + * Returns the default answer. + */ + public function getDefault(): string|bool|int|float|null + { + } + + /** + * Returns whether the user response accepts newline characters. + */ + public function isMultiline(): bool + { + } + + /** + * Sets whether the user response should accept newline characters. + * + * @return $this + */ + public function setMultiline(bool $multiline): static + { + } + + /** + * Returns whether the user response must be hidden. + */ + public function isHidden(): bool + { + } + + /** + * Sets whether the user response must be hidden or not. + * + * @return $this + * + * @throws LogicException In case the autocompleter is also used + */ + public function setHidden(bool $hidden): static + { + } + + /** + * In case the response cannot be hidden, whether to fallback on non-hidden question or not. + */ + public function isHiddenFallback(): bool + { + } + + /** + * Sets whether to fallback on non-hidden question if the response cannot be hidden. + * + * @return $this + */ + public function setHiddenFallback(bool $fallback): static + { + } + + /** + * Gets values for the autocompleter. + */ + public function getAutocompleterValues(): ?iterable + { + } + + /** + * Sets values for the autocompleter. + * + * @return $this + * + * @throws LogicException + */ + public function setAutocompleterValues(?iterable $values): static + { + } + + /** + * Gets the callback function used for the autocompleter. + */ + public function getAutocompleterCallback(): ?callable + { + } + + /** + * Sets the callback function used for the autocompleter. + * + * The callback is passed the user input as argument and should return an iterable of corresponding suggestions. + * + * @return $this + */ + public function setAutocompleterCallback(?callable $callback = null): static + { + } + + /** + * Sets a validator for the question. + * + * @return $this + */ + public function setValidator(?callable $validator = null): static + { + } + + /** + * Gets the validator for the question. + */ + public function getValidator(): ?callable + { + } + + /** + * Sets the maximum number of attempts. + * + * Null means an unlimited number of attempts. + * + * @return $this + * + * @throws InvalidArgumentException in case the number of attempts is invalid + */ + public function setMaxAttempts(?int $attempts): static + { + } + + /** + * Gets the maximum number of attempts. + * + * Null means an unlimited number of attempts. + */ + public function getMaxAttempts(): ?int + { + } + + /** + * Sets a normalizer for the response. + * + * The normalizer can be a callable (a string), a closure or a class implementing __invoke. + * + * @return $this + */ + public function setNormalizer(callable $normalizer): static + { + } + + /** + * Gets the normalizer for the response. + * + * The normalizer can ba a callable (a string), a closure or a class implementing __invoke. + */ + public function getNormalizer(): ?callable + { + } + + /** + * @return bool + */ + protected function isAssoc(array $array) + { + } + + public function isTrimmable(): bool + { + } + + /** + * @return $this + */ + public function setTrimmable(bool $trimmable): static + { + } +}