diff --git a/.github/workflows/command-rebase.yml b/.github/workflows/command-rebase.yml new file mode 100644 index 00000000..ec95ccbb --- /dev/null +++ b/.github/workflows/command-rebase.yml @@ -0,0 +1,51 @@ +# This workflow is provided via the organization template repository +# +# https://github.com/nextcloud/.github +# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization + +name: Rebase command + +on: + issue_comment: + types: created + +permissions: + contents: read + +jobs: + rebase: + runs-on: ubuntu-latest + permissions: + contents: none + + # On pull requests and if the comment starts with `/rebase` + if: github.event.issue.pull_request != '' && startsWith(github.event.comment.body, '/rebase') + + steps: + - name: Add reaction on start + uses: peter-evans/create-or-update-comment@ca08ebd5dc95aa0cd97021e9708fcd6b87138c9b # v3.0.1 + with: + token: ${{ secrets.COMMAND_BOT_PAT }} + repository: ${{ github.event.repository.full_name }} + comment-id: ${{ github.event.comment.id }} + reaction-type: "+1" + + - name: Checkout the latest code + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + with: + fetch-depth: 0 + token: ${{ secrets.COMMAND_BOT_PAT }} + + - name: Automatic Rebase + uses: cirrus-actions/rebase@b87d48154a87a85666003575337e27b8cd65f691 # 1.8 + env: + GITHUB_TOKEN: ${{ secrets.COMMAND_BOT_PAT }} + + - name: Add reaction on failure + uses: peter-evans/create-or-update-comment@ca08ebd5dc95aa0cd97021e9708fcd6b87138c9b # v3.0.1 + if: failure() + with: + token: ${{ secrets.COMMAND_BOT_PAT }} + repository: ${{ github.event.repository.full_name }} + comment-id: ${{ github.event.comment.id }} + reaction-type: "-1" diff --git a/.github/workflows/lint-info-xml.yml b/.github/workflows/lint-info-xml.yml new file mode 100644 index 00000000..84d5a878 --- /dev/null +++ b/.github/workflows/lint-info-xml.yml @@ -0,0 +1,39 @@ +# This workflow is provided via the organization template repository +# +# https://github.com/nextcloud/.github +# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization + +name: Lint info.xml + +on: + pull_request: + push: + branches: + - main + - master + - stable* + +permissions: + contents: read + +concurrency: + group: lint-info-xml-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + xml-linters: + runs-on: ubuntu-latest + + name: info.xml lint + steps: + - name: Checkout + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + + - name: Download schema + run: wget https://raw.githubusercontent.com/nextcloud/appstore/master/nextcloudappstore/api/v1/release/info.xsd + + - name: Lint info.xml + uses: ChristophWurst/xmllint-action@39155a91429af431d65fafc21fa52ba5c4f5cb71 # v1.1 + with: + xml-file: ./appinfo/info.xml + xml-schema-file: ./info.xsd diff --git a/.github/workflows/lint-php-cs.yml b/.github/workflows/lint-php-cs.yml new file mode 100644 index 00000000..0fdb3ebf --- /dev/null +++ b/.github/workflows/lint-php-cs.yml @@ -0,0 +1,40 @@ +# This workflow is provided via the organization template repository +# +# https://github.com/nextcloud/.github +# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization + +name: Lint php-cs + +on: pull_request + +permissions: + contents: read + +concurrency: + group: lint-php-cs-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + lint: + runs-on: ubuntu-latest + + name: php-cs + + steps: + - name: Checkout + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + + - name: Set up php + uses: shivammathur/setup-php@4bd44f22a98a19e0950cbad5f31095157cc9621b # v2 + with: + php-version: 8.1 + coverage: none + ini-file: development + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Install dependencies + run: composer i + + - name: Lint + run: composer run cs:check || ( echo 'Please run `composer run cs:fix` to format your code' && exit 1 ) diff --git a/.github/workflows/lint-php.yml b/.github/workflows/lint-php.yml new file mode 100644 index 00000000..22f86124 --- /dev/null +++ b/.github/workflows/lint-php.yml @@ -0,0 +1,60 @@ +# This workflow is provided via the organization template repository +# +# https://github.com/nextcloud/.github +# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization + +name: Lint php + +on: + pull_request: + push: + branches: + - main + - master + - stable* + +permissions: + contents: read + +concurrency: + group: lint-php-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + php-lint: + runs-on: ubuntu-latest + strategy: + matrix: + php-versions: [ "8.0", "8.1", "8.2" ] + + name: php-lint + + steps: + - name: Checkout + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + + - name: Set up php ${{ matrix.php-versions }} + uses: shivammathur/setup-php@4bd44f22a98a19e0950cbad5f31095157cc9621b # v2 + with: + php-version: ${{ matrix.php-versions }} + coverage: none + ini-file: development + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Lint + run: composer run lint + + summary: + permissions: + contents: none + runs-on: ubuntu-latest + needs: php-lint + + if: always() + + name: php-lint-summary + + steps: + - name: Summary status + run: if ${{ needs.php-lint.result != 'success' && needs.php-lint.result != 'skipped' }}; then exit 1; fi diff --git a/.github/workflows/phpunit-mysql.yml b/.github/workflows/phpunit-mysql.yml new file mode 100644 index 00000000..988010b6 --- /dev/null +++ b/.github/workflows/phpunit-mysql.yml @@ -0,0 +1,162 @@ +# This workflow is provided via the organization template repository +# +# https://github.com/nextcloud/.github +# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization + +name: PHPUnit mysql + +on: + pull_request: + paths: + - '.github/workflows/**' + - 'appinfo/**' + - 'lib/**' + - 'templates/**' + - 'tests/**' + - 'vendor/**' + - 'vendor-bin/**' + - '.php-cs-fixer.dist.php' + - 'composer.json' + - 'composer.lock' + + push: + branches: + - main + - master + - stable* + +permissions: + contents: read + +concurrency: + group: phpunit-mysql-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + phpunit-mysql: + runs-on: ubuntu-latest + + strategy: + matrix: + php-versions: ['8.0', '8.1', '8.2'] + server-versions: ['master'] + + services: + mysql: + image: ghcr.io/nextcloud/continuous-integration-mariadb-10.6:latest + ports: + - 4444:3306/tcp + env: + MYSQL_ROOT_PASSWORD: rootpassword + options: --health-cmd="mysqladmin ping" --health-interval 5s --health-timeout 2s --health-retries 5 + + steps: + - name: Set app env + run: | + # Split and keep last + echo "APP_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV + + - name: Checkout server + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + with: + submodules: true + repository: nextcloud/server + ref: ${{ matrix.server-versions }} + + - name: Checkout app + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + with: + path: apps/${{ env.APP_NAME }} + + - name: Set up php ${{ matrix.php-versions }} + uses: shivammathur/setup-php@4bd44f22a98a19e0950cbad5f31095157cc9621b # v2 + 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 + 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@20b4d2e596410855db8f9ca21e96fbe18e12930b # v2 + 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 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 + needs: phpunit-mysql + + if: always() + + name: phpunit-mysql-summary + + steps: + - name: Summary status + run: if ${{ needs.phpunit-mysql.result != 'success' }}; then exit 1; fi diff --git a/.github/workflows/phpunit-oci.yml b/.github/workflows/phpunit-oci.yml new file mode 100644 index 00000000..9b6d693b --- /dev/null +++ b/.github/workflows/phpunit-oci.yml @@ -0,0 +1,169 @@ +# This workflow is provided via the organization template repository +# +# https://github.com/nextcloud/.github +# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization + +name: PHPUnit OCI + +on: + pull_request: + paths: + - '.github/workflows/**' + - 'appinfo/**' + - 'lib/**' + - 'templates/**' + - 'tests/**' + - 'vendor/**' + - 'vendor-bin/**' + - '.php-cs-fixer.dist.php' + - 'composer.json' + - 'composer.lock' + + push: + branches: + - main + - master + - stable* + +permissions: + contents: read + +concurrency: + group: phpunit-oci-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + phpunit-oci: + runs-on: ubuntu-latest + + strategy: + matrix: + php-versions: ['8.0'] + server-versions: ['master'] + + 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 + run: | + # Split and keep last + echo "APP_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV + + - name: Checkout server + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + with: + submodules: true + repository: nextcloud/server + ref: ${{ matrix.server-versions }} + + - name: Checkout app + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + with: + path: apps/${{ env.APP_NAME }} + + - name: Set up php ${{ matrix.php-versions }} + uses: shivammathur/setup-php@c5fc0d8281aba02c7fda07d3a70cc5371548067d # v2 + 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 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Check composer file existence + id: check_composer + uses: andstor/file-existence-action@20b4d2e596410855db8f9ca21e96fbe18e12930b # v2 + 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 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 + needs: phpunit-oci + + if: always() + + name: phpunit-oci-summary + + steps: + - name: Summary status + run: if ${{ needs.phpunit-oci.result != 'success' }}; then exit 1; fi diff --git a/.github/workflows/phpunit-pgsql.yml b/.github/workflows/phpunit-pgsql.yml new file mode 100644 index 00000000..c944d35c --- /dev/null +++ b/.github/workflows/phpunit-pgsql.yml @@ -0,0 +1,159 @@ +# This workflow is provided via the organization template repository +# +# https://github.com/nextcloud/.github +# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization + +name: PHPUnit pgsql + +on: + pull_request: + paths: + - '.github/workflows/**' + - 'appinfo/**' + - 'lib/**' + - 'templates/**' + - 'tests/**' + - 'vendor/**' + - 'vendor-bin/**' + - '.php-cs-fixer.dist.php' + - 'composer.json' + - 'composer.lock' + + push: + branches: + - main + - master + - stable* + +permissions: + contents: read + +concurrency: + group: phpunit-pgsql-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + phpunit-pgsql: + runs-on: ubuntu-latest + + strategy: + matrix: + php-versions: ['8.0'] + server-versions: ['master'] + + 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 + run: | + # Split and keep last + echo "APP_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV + + - name: Checkout server + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + with: + submodules: true + repository: nextcloud/server + ref: ${{ matrix.server-versions }} + + - name: Checkout app + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + with: + path: apps/${{ env.APP_NAME }} + + - name: Set up php ${{ matrix.php-versions }} + uses: shivammathur/setup-php@4bd44f22a98a19e0950cbad5f31095157cc9621b # v2 + 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 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Check composer file existence + id: check_composer + uses: andstor/file-existence-action@20b4d2e596410855db8f9ca21e96fbe18e12930b # v2 + 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 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 + needs: phpunit-pgsql + + if: always() + + name: phpunit-pgsql-summary + + steps: + - name: Summary status + run: if ${{ needs.phpunit-pgsql.result != 'success' }}; then exit 1; fi diff --git a/.github/workflows/phpunit-sqlite.yml b/.github/workflows/phpunit-sqlite.yml new file mode 100644 index 00000000..35463b0d --- /dev/null +++ b/.github/workflows/phpunit-sqlite.yml @@ -0,0 +1,148 @@ +# This workflow is provided via the organization template repository +# +# https://github.com/nextcloud/.github +# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization + +name: PHPUnit sqlite + +on: + pull_request: + paths: + - '.github/workflows/**' + - 'appinfo/**' + - 'lib/**' + - 'templates/**' + - 'tests/**' + - 'vendor/**' + - 'vendor-bin/**' + - '.php-cs-fixer.dist.php' + - 'composer.json' + - 'composer.lock' + + push: + branches: + - main + - master + - stable* + +permissions: + contents: read + +concurrency: + group: phpunit-sqlite-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + phpunit-sqlite: + runs-on: ubuntu-latest + + strategy: + matrix: + php-versions: ['8.0'] + server-versions: ['master'] + + steps: + - name: Set app env + run: | + # Split and keep last + echo "APP_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV + + - name: Checkout server + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + with: + submodules: true + repository: nextcloud/server + ref: ${{ matrix.server-versions }} + + - name: Checkout app + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + with: + path: apps/${{ env.APP_NAME }} + + - name: Set up php ${{ matrix.php-versions }} + uses: shivammathur/setup-php@4bd44f22a98a19e0950cbad5f31095157cc9621b # v2 + with: + php-version: ${{ matrix.php-versions }} + # https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation + extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite + coverage: none + ini-file: development + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Check composer file existence + id: check_composer + uses: andstor/file-existence-action@20b4d2e596410855db8f9ca21e96fbe18e12930b # v2 + 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 i + + - name: Set up Nextcloud + env: + DB_PORT: 4444 + run: | + mkdir data + ./occ maintenance:install --verbose --database=sqlite --database-name=nextcloud --database-host=127.0.0.1 --database-port=$DB_PORT --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass admin + ./occ app:enable --force ${{ env.APP_NAME }} + + - name: Check PHPUnit script is defined + id: check_phpunit + continue-on-error: true + working-directory: apps/${{ env.APP_NAME }} + run: | + composer run --list | grep "^ test:unit " | wc -l | grep 1 + + - name: PHPUnit + # Only run if phpunit config file exists + if: steps.check_phpunit.outcome == 'success' + working-directory: apps/${{ env.APP_NAME }} + run: composer run test:unit + + - name: Check PHPUnit integration script is defined + id: check_integration + continue-on-error: true + working-directory: apps/${{ env.APP_NAME }} + run: | + composer run --list | grep "^ test:integration " | wc -l | grep 1 + + - name: Run Nextcloud + # Only run if phpunit integration config file exists + if: steps.check_integration.outcome == 'success' + run: php -S localhost:8080 & + + - name: PHPUnit integration + # Only run if phpunit integration config file exists + if: steps.check_integration.outcome == 'success' + working-directory: apps/${{ env.APP_NAME }} + run: composer run test:integration + + - name: Print logs + if: always() + run: | + cat data/nextcloud.log + + - name: Skipped + # Fail the action when neither unit nor integration tests ran + if: steps.check_phpunit.outcome == 'failure' && steps.check_integration.outcome == 'failure' + run: | + echo 'Neither PHPUnit nor PHPUnit integration tests are specified in composer.json scripts' + exit 1 + + summary: + permissions: + contents: none + runs-on: ubuntu-latest + needs: phpunit-sqlite + + if: always() + + name: phpunit-sqlite-summary + + steps: + - name: Summary status + run: if ${{ needs.phpunit-sqlite.result != 'success' }}; then exit 1; fi diff --git a/.github/workflows/phpunit-summary-when-unrelated.yml b/.github/workflows/phpunit-summary-when-unrelated.yml new file mode 100644 index 00000000..484fdbb5 --- /dev/null +++ b/.github/workflows/phpunit-summary-when-unrelated.yml @@ -0,0 +1,68 @@ +# This workflow is provided via the organization template repository +# +# https://github.com/nextcloud/.github +# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization + +name: PHPUnit summary + +on: + pull_request: + paths-ignore: + - '.github/workflows/**' + - 'appinfo/**' + - 'lib/**' + - 'templates/**' + - 'tests/**' + - 'vendor/**' + - 'vendor-bin/**' + - '.php-cs-fixer.dist.php' + - 'composer.json' + - 'composer.lock' + +permissions: + contents: read + +jobs: + summary-mysql: + permissions: + contents: none + runs-on: ubuntu-latest + + name: phpunit-mysql-summary + + steps: + - name: Summary status + run: 'echo "No PHP files changed, skipped PHPUnit"' + + summary-oci: + permissions: + contents: none + runs-on: ubuntu-latest + + name: phpunit-oci-summary + + steps: + - name: Summary status + run: 'echo "No PHP files changed, skipped PHPUnit"' + + summary-pgsql: + permissions: + contents: none + runs-on: ubuntu-latest + + name: phpunit-pgsql-summary + + steps: + - name: Summary status + run: 'echo "No PHP files changed, skipped PHPUnit"' + + summary-sqlite: + permissions: + contents: none + runs-on: ubuntu-latest + + name: phpunit-sqlite-summary + + steps: + - name: Summary status + run: 'echo "No PHP files changed, skipped PHPUnit"' diff --git a/.github/workflows/phpunit.yml b/.github/workflows/phpunit.yml new file mode 100644 index 00000000..161105ed --- /dev/null +++ b/.github/workflows/phpunit.yml @@ -0,0 +1,69 @@ +name: PHPUnit + +on: + pull_request: + push: + branches: + - master + - stable* + +env: + APP_NAME: fulltextsearch + +jobs: + php: + runs-on: ubuntu-latest + + strategy: + # do not stop on another job's failure + fail-fast: false + matrix: + php-versions: ['8.0'] + databases: ['sqlite'] + server-versions: ['master'] + + name: php${{ matrix.php-versions }}-${{ matrix.databases }}-${{ matrix.server-versions }} + + steps: + - name: Checkout server + uses: actions/checkout@v2 + with: + repository: nextcloud/server + ref: ${{ matrix.server-versions }} + + - name: Checkout submodules + shell: bash + run: | + auth_header="$(git config --local --get http.https://github.com/.extraheader)" + git submodule sync --recursive + git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1 + + - name: Checkout app + uses: actions/checkout@v2 + with: + path: apps/${{ env.APP_NAME }} + + - name: Set up php ${{ matrix.php-versions }} + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + tools: phpunit + extensions: ctype, curl, dom, fileinfo, gd, intl, json, mbstring, openssl, pdo_sqlite, posix, sqlite, xml, zip + coverage: none + + - name: Set up PHPUnit + working-directory: apps/${{ env.APP_NAME }} + run: composer i + + - name: Set up Nextcloud + env: + DB_PORT: 4444 + run: | + mkdir data + ./occ maintenance:install --verbose --database=${{ matrix.databases }} --database-name=nextcloud --database-host=127.0.0.1 --database-port=$DB_PORT --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass password + ./occ app:enable --force ${{ env.APP_NAME }} + php -S localhost:8080 & + + - name: PHPUnit + working-directory: apps/${{ env.APP_NAME }} + run: ./vendor/phpunit/phpunit/phpunit -c tests/unit/phpunit.xml diff --git a/.github/workflows/psalm.yml b/.github/workflows/psalm.yml new file mode 100644 index 00000000..bc5430b2 --- /dev/null +++ b/.github/workflows/psalm.yml @@ -0,0 +1,42 @@ +# This workflow is provided via the organization template repository +# +# https://github.com/nextcloud/.github +# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization + +name: Static analysis + +on: + pull_request: + push: + branches: + - master + - main + - stable* + +concurrency: + group: psalm-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + static-analysis: + runs-on: ubuntu-latest + + name: Nextcloud + steps: + - name: Checkout + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + + - name: Set up php + uses: shivammathur/setup-php@4bd44f22a98a19e0950cbad5f31095157cc9621b # v2 + with: + php-version: 8.1 + coverage: none + ini-file: development + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Install dependencies + run: composer i + + - name: Run coding standards check + run: composer run psalm diff --git a/.gitignore b/.gitignore index 3a41ca6d..19bbb5a4 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ \.idea/ build/ vendor/ + +.php-cs-fixer.cache diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php new file mode 100644 index 00000000..8a0cb43c --- /dev/null +++ b/.php-cs-fixer.dist.php @@ -0,0 +1,17 @@ +getFinder() + ->notPath('build') + ->notPath('l10n') + ->notPath('src') + ->notPath('vendor') + ->in(__DIR__); +return $config; diff --git a/appinfo/routes.php b/appinfo/routes.php index 5b56710b..d465c4d2 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -1,4 +1,5 @@ 'Templates#getNavigationPanels', 'url' => '/navigation/panels', 'verb' => 'GET'] ] ]; - - diff --git a/composer.json b/composer.json index 8253a431..5f5af90c 100644 --- a/composer.json +++ b/composer.json @@ -6,7 +6,10 @@ "config": { "optimize-autoloader": true, "classmap-authoritative": true, - "autoloader-suffix": "FullTextSearch" + "autoloader-suffix": "FullTextSearch", + "platform": { + "php": "8.0" + } }, "authors": [ { @@ -19,7 +22,28 @@ "OCA\\FullTextSearch\\": "lib/" } }, - "require": { - "artificial-owl/my-small-php-tools": "~23" + "scripts": { + "cs:check": "php-cs-fixer fix --dry-run --diff", + "cs:fix": "php-cs-fixer fix", + "psalm": "psalm", + "psalm:update-baseline": "psalm --threads=1 --update-baseline", + "psalm:clear": "psalm --clear-cache && psalm --clear-global-cache", + "psalm:fix": "psalm --alter --issues=InvalidReturnType,InvalidNullableReturnType,MissingParamType,InvalidFalsableReturnType", + "test": [ + "@test:unit" + ], + "test:unit": "echo 'Only testing installation of the app'", + "lint": "find . -name \\*.php -not -path './vendor/*' -print0 | xargs -0 -n1 php -l" + }, + "require-dev": { + "phpunit/phpunit": "^9.6.9", + "vimeo/psalm": "^4.22", + "nextcloud/coding-standard": "^1.1", + "nextcloud/ocp": "dev-master" + }, + "autoload-dev": { + "psr-4": { + "OCP\\": "vendor/nextcloud/ocp/OCP" + } } } diff --git a/composer.lock b/composer.lock index 16163b46..84315853 100644 --- a/composer.lock +++ b/composer.lock @@ -4,56 +4,3588 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b52d6a5c9fb9be09368e44333c380806", - "packages": [ + "content-hash": "8817de0b7f74cb5b85d2a2c7320765bd", + "packages": [], + "packages-dev": [ { - "name": "artificial-owl/my-small-php-tools", - "version": "v23.0.2", + "name": "amphp/amp", + "version": "v2.6.2", "source": { "type": "git", - "url": "https://github.com/ArtificialOwl/my-small-php-tools.git", - "reference": "0246b20ebffabcb1e929c71d3b0f221086f72db1" + "url": "https://github.com/amphp/amp.git", + "reference": "9d5100cebffa729aaffecd3ad25dc5aeea4f13bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ArtificialOwl/my-small-php-tools/zipball/0246b20ebffabcb1e929c71d3b0f221086f72db1", - "reference": "0246b20ebffabcb1e929c71d3b0f221086f72db1", + "url": "https://api.github.com/repos/amphp/amp/zipball/9d5100cebffa729aaffecd3ad25dc5aeea4f13bb", + "reference": "9d5100cebffa729aaffecd3ad25dc5aeea4f13bb", "shasum": "" }, "require": { + "php": ">=7.1" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "dev-master", + "amphp/phpunit-util": "^1", + "ext-json": "*", + "jetbrains/phpstorm-stubs": "^2019.3", + "phpunit/phpunit": "^7 | ^8 | ^9", + "psalm/phar": "^3.11@dev", + "react/promise": "^2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "files": [ + "lib/functions.php", + "lib/Internal/functions.php" + ], + "psr-4": { + "Amp\\": "lib" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Lowrey", + "email": "rdlowrey@php.net" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Bob Weinand", + "email": "bobwei9@hotmail.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "A non-blocking concurrency framework for PHP applications.", + "homepage": "https://amphp.org/amp", + "keywords": [ + "async", + "asynchronous", + "awaitable", + "concurrency", + "event", + "event-loop", + "future", + "non-blocking", + "promise" + ], + "support": { + "irc": "irc://irc.freenode.org/amphp", + "issues": "https://github.com/amphp/amp/issues", + "source": "https://github.com/amphp/amp/tree/v2.6.2" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2022-02-20T17:52:18+00:00" + }, + { + "name": "amphp/byte-stream", + "version": "v1.8.1", + "source": { + "type": "git", + "url": "https://github.com/amphp/byte-stream.git", + "reference": "acbd8002b3536485c997c4e019206b3f10ca15bd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/byte-stream/zipball/acbd8002b3536485c997c4e019206b3f10ca15bd", + "reference": "acbd8002b3536485c997c4e019206b3f10ca15bd", + "shasum": "" + }, + "require": { + "amphp/amp": "^2", + "php": ">=7.1" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "dev-master", + "amphp/phpunit-util": "^1.4", + "friendsofphp/php-cs-fixer": "^2.3", + "jetbrains/phpstorm-stubs": "^2019.3", + "phpunit/phpunit": "^6 || ^7 || ^8", + "psalm/phar": "^3.11.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "files": [ + "lib/functions.php" + ], + "psr-4": { + "Amp\\ByteStream\\": "lib" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "A stream abstraction to make working with non-blocking I/O simple.", + "homepage": "http://amphp.org/byte-stream", + "keywords": [ + "amp", + "amphp", + "async", + "io", + "non-blocking", + "stream" + ], + "support": { + "irc": "irc://irc.freenode.org/amphp", + "issues": "https://github.com/amphp/byte-stream/issues", + "source": "https://github.com/amphp/byte-stream/tree/v1.8.1" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2021-03-30T17:13:30+00:00" + }, + { + "name": "composer/package-versions-deprecated", + "version": "1.11.99.5", + "source": { + "type": "git", + "url": "https://github.com/composer/package-versions-deprecated.git", + "reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/b4f54f74ef3453349c24a845d22392cd31e65f1d", + "reference": "b4f54f74ef3453349c24a845d22392cd31e65f1d", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.1.0 || ^2.0", + "php": "^7 || ^8" + }, + "replace": { + "ocramius/package-versions": "1.11.99" + }, + "require-dev": { + "composer/composer": "^1.9.3 || ^2.0@dev", + "ext-zip": "^1.13", + "phpunit/phpunit": "^6.5 || ^7" + }, + "type": "composer-plugin", + "extra": { + "class": "PackageVersions\\Installer", + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "PackageVersions\\": "src/PackageVersions" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be" + } + ], + "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", + "support": { + "issues": "https://github.com/composer/package-versions-deprecated/issues", + "source": "https://github.com/composer/package-versions-deprecated/tree/1.11.99.5" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2022-01-17T14:14:24+00:00" + }, + { + "name": "composer/pcre", + "version": "3.1.0", + "source": { + "type": "git", + "url": "https://github.com/composer/pcre.git", + "reference": "4bff79ddd77851fe3cdd11616ed3f92841ba5bd2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/pcre/zipball/4bff79ddd77851fe3cdd11616ed3f92841ba5bd2", + "reference": "4bff79ddd77851fe3cdd11616ed3f92841ba5bd2", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.3", + "phpstan/phpstan-strict-rules": "^1.1", + "symfony/phpunit-bridge": "^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Pcre\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", + "keywords": [ + "PCRE", + "preg", + "regex", + "regular expression" + ], + "support": { + "issues": "https://github.com/composer/pcre/issues", + "source": "https://github.com/composer/pcre/tree/3.1.0" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2022-11-17T09:50:14+00:00" + }, + { + "name": "composer/semver", + "version": "3.3.2", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/3953f23262f2bff1919fc82183ad9acb13ff62c9", + "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.4", + "symfony/phpunit-bridge": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/3.3.2" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2022-04-01T19:23:25+00:00" + }, + { + "name": "composer/xdebug-handler", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "ced299686f41dce890debac69273b47ffe98a40c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ced299686f41dce890debac69273b47ffe98a40c", + "reference": "ced299686f41dce890debac69273b47ffe98a40c", + "shasum": "" + }, + "require": { + "composer/pcre": "^1 || ^2 || ^3", + "php": "^7.2.5 || ^8.0", + "psr/log": "^1 || ^2 || ^3" + }, + "require-dev": { + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-strict-rules": "^1.1", + "symfony/phpunit-bridge": "^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without Xdebug.", + "keywords": [ + "Xdebug", + "performance" + ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/xdebug-handler/issues", + "source": "https://github.com/composer/xdebug-handler/tree/3.0.3" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2022-02-25T21:32:43+00:00" + }, + { + "name": "dnoegel/php-xdg-base-dir", + "version": "v0.1.1", + "source": { + "type": "git", + "url": "https://github.com/dnoegel/php-xdg-base-dir.git", + "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dnoegel/php-xdg-base-dir/zipball/8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", + "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "~7.0|~6.0|~5.0|~4.8.35" + }, + "type": "library", + "autoload": { + "psr-4": { + "XdgBaseDir\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "implementation of xdg base directory specification for php", + "support": { + "issues": "https://github.com/dnoegel/php-xdg-base-dir/issues", + "source": "https://github.com/dnoegel/php-xdg-base-dir/tree/v0.1.1" + }, + "time": "2019-12-04T15:06:13+00:00" + }, + { + "name": "doctrine/deprecations", + "version": "v1.1.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/deprecations.git", + "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/612a3ee5ab0d5dd97b7cf3874a6efe24325efac3", + "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9", + "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" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", + "support": { + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/v1.1.1" + }, + "time": "2023-06-03T09:27:29+00:00" + }, + { + "name": "doctrine/instantiator", + "version": "1.5.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9 || ^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" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "https://ocramius.github.io/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", + "keywords": [ + "constructor", + "instantiate" + ], + "support": { + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/1.5.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%2Finstantiator", + "type": "tidelift" + } + ], + "time": "2022-12-30T00:15:36+00:00" + }, + { + "name": "felixfbecker/advanced-json-rpc", + "version": "v3.2.1", + "source": { + "type": "git", + "url": "https://github.com/felixfbecker/php-advanced-json-rpc.git", + "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/felixfbecker/php-advanced-json-rpc/zipball/b5f37dbff9a8ad360ca341f3240dc1c168b45447", + "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447", + "shasum": "" + }, + "require": { + "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", + "php": "^7.1 || ^8.0", + "phpdocumentor/reflection-docblock": "^4.3.4 || ^5.0.0" + }, + "require-dev": { + "phpunit/phpunit": "^7.0 || ^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "AdvancedJsonRpc\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "ISC" + ], + "authors": [ + { + "name": "Felix Becker", + "email": "felix.b@outlook.com" + } + ], + "description": "A more advanced JSONRPC implementation", + "support": { + "issues": "https://github.com/felixfbecker/php-advanced-json-rpc/issues", + "source": "https://github.com/felixfbecker/php-advanced-json-rpc/tree/v3.2.1" + }, + "time": "2021-06-11T22:34:44+00:00" + }, + { + "name": "felixfbecker/language-server-protocol", + "version": "v1.5.2", + "source": { + "type": "git", + "url": "https://github.com/felixfbecker/php-language-server-protocol.git", + "reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/felixfbecker/php-language-server-protocol/zipball/6e82196ffd7c62f7794d778ca52b69feec9f2842", + "reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "phpstan/phpstan": "*", + "squizlabs/php_codesniffer": "^3.1", + "vimeo/psalm": "^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "LanguageServerProtocol\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "ISC" + ], + "authors": [ + { + "name": "Felix Becker", + "email": "felix.b@outlook.com" + } + ], + "description": "PHP classes for the Language Server Protocol", + "keywords": [ + "language", + "microsoft", + "php", + "server" + ], + "support": { + "issues": "https://github.com/felixfbecker/php-language-server-protocol/issues", + "source": "https://github.com/felixfbecker/php-language-server-protocol/tree/v1.5.2" + }, + "time": "2022-03-02T22:36:06+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.11.1", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3,<3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2023-03-08T13:26:56+00:00" + }, + { + "name": "netresearch/jsonmapper", + "version": "v4.2.0", + "source": { + "type": "git", + "url": "https://github.com/cweiske/jsonmapper.git", + "reference": "f60565f8c0566a31acf06884cdaa591867ecc956" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/f60565f8c0566a31acf06884cdaa591867ecc956", + "reference": "f60565f8c0566a31acf06884cdaa591867ecc956", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-spl": "*", + "php": ">=7.1" + }, + "require-dev": { + "phpunit/phpunit": "~7.5 || ~8.0 || ~9.0", + "squizlabs/php_codesniffer": "~3.5" + }, + "type": "library", + "autoload": { + "psr-0": { + "JsonMapper": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "OSL-3.0" + ], + "authors": [ + { + "name": "Christian Weiske", + "email": "cweiske@cweiske.de", + "homepage": "http://github.com/cweiske/jsonmapper/", + "role": "Developer" + } + ], + "description": "Map nested JSON structures onto PHP classes", + "support": { + "email": "cweiske@cweiske.de", + "issues": "https://github.com/cweiske/jsonmapper/issues", + "source": "https://github.com/cweiske/jsonmapper/tree/v4.2.0" + }, + "time": "2023-04-09T17:37:40+00:00" + }, + { + "name": "nextcloud/coding-standard", + "version": "v1.1.1", + "source": { + "type": "git", + "url": "https://github.com/nextcloud/coding-standard.git", + "reference": "55def702fb9a37a219511e1d8c6fe8e37164c1fb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nextcloud/coding-standard/zipball/55def702fb9a37a219511e1d8c6fe8e37164c1fb", + "reference": "55def702fb9a37a219511e1d8c6fe8e37164c1fb", + "shasum": "" + }, + "require": { + "php": "^7.3|^8.0", + "php-cs-fixer/shim": "^3.17" + }, + "type": "library", + "autoload": { + "psr-4": { + "Nextcloud\\CodingStandard\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christoph Wurst", + "email": "christoph@winzerhof-wurst.at" + } + ], + "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.1" + }, + "time": "2023-06-01T12:05:01+00:00" + }, + { + "name": "nextcloud/ocp", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/nextcloud-deps/ocp.git", + "reference": "8088698ae770c2655906850fc57112a316a991b0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nextcloud-deps/ocp/zipball/8088698ae770c2655906850fc57112a316a991b0", + "reference": "8088698ae770c2655906850fc57112a316a991b0", + "shasum": "" + }, + "require": { + "php": "~8.0 || ~8.1 || ~8.2", + "psr/clock": "^1.0", + "psr/container": "^2.0.2", + "psr/event-dispatcher": "^1.0", + "psr/log": "^1.1.4" + }, + "default-branch": true, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "28.0.0-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "AGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Christoph Wurst", + "email": "christoph@winzerhof-wurst.at" + } + ], + "description": "Composer package containing Nextcloud's public API (classes, interfaces)", + "support": { + "issues": "https://github.com/nextcloud-deps/ocp/issues", + "source": "https://github.com/nextcloud-deps/ocp/tree/master" + }, + "time": "2023-06-27T00:43:31+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v4.16.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "19526a33fb561ef417e822e85f08a00db4059c17" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/19526a33fb561ef417e822e85f08a00db4059c17", + "reference": "19526a33fb561ef417e822e85f08a00db4059c17", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", "php": ">=7.0" }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v4.16.0" + }, + "time": "2023-06-25T14:52:30+00:00" + }, + { + "name": "openlss/lib-array2xml", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/nullivex/lib-array2xml.git", + "reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nullivex/lib-array2xml/zipball/a91f18a8dfc69ffabe5f9b068bc39bb202c81d90", + "reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "type": "library", + "autoload": { + "psr-0": { + "LSS": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Bryan Tong", + "email": "bryan@nullivex.com", + "homepage": "https://www.nullivex.com" + }, + { + "name": "Tony Butler", + "email": "spudz76@gmail.com", + "homepage": "https://www.nullivex.com" + } + ], + "description": "Array2XML conversion library credit to lalit.org", + "homepage": "https://www.nullivex.com", + "keywords": [ + "array", + "array conversion", + "xml", + "xml conversion" + ], + "support": { + "issues": "https://github.com/nullivex/lib-array2xml/issues", + "source": "https://github.com/nullivex/lib-array2xml/tree/master" + }, + "time": "2019-03-29T20:06:56+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.3" + }, + "time": "2021-07-20T11:28:43+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "php-cs-fixer/shim", + "version": "v3.20.0", + "source": { + "type": "git", + "url": "https://github.com/PHP-CS-Fixer/shim.git", + "reference": "3253acf5cdb96383bb37ce7052e5dbf49a660f1e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHP-CS-Fixer/shim/zipball/3253acf5cdb96383bb37ce7052e5dbf49a660f1e", + "reference": "3253acf5cdb96383bb37ce7052e5dbf49a660f1e", + "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.20.0" + }, + "time": "2023-06-27T20:23:49+00:00" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-2.x": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", + "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" + }, + "time": "2020-06-27T09:03:43+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "5.3.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", + "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", + "shasum": "" + }, + "require": { + "ext-filter": "*", + "php": "^7.2 || ^8.0", + "phpdocumentor/reflection-common": "^2.2", + "phpdocumentor/type-resolver": "^1.3", + "webmozart/assert": "^1.9.1" + }, + "require-dev": { + "mockery/mockery": "~1.3.2", + "psalm/phar": "^4.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "account@ijaap.nl" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0" + }, + "time": "2021-10-19T17:43:47+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "1.7.2", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "b2fe4d22a5426f38e014855322200b97b5362c0d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/b2fe4d22a5426f38e014855322200b97b5362c0d", + "reference": "b2fe4d22a5426f38e014855322200b97b5362c0d", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.0", + "php": "^7.4 || ^8.0", + "phpdocumentor/reflection-common": "^2.0", + "phpstan/phpdoc-parser": "^1.13" + }, + "require-dev": { + "ext-tokenizer": "*", + "phpbench/phpbench": "^1.2", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpunit/phpunit": "^9.5", + "rector/rector": "^0.13.9", + "vimeo/psalm": "^4.25" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-1.x": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "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.2" + }, + "time": "2023-05-30T18:13:47+00:00" + }, + { + "name": "phpstan/phpdoc-parser", + "version": "1.22.0", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "ec58baf7b3c7f1c81b3b00617c953249fb8cf30c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/ec58baf7b3c7f1c81b3b00617c953249fb8cf30c", + "reference": "ec58baf7b3c7f1c81b3b00617c953249fb8cf30c", + "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", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.0", + "phpunit/phpunit": "^9.5", + "symfony/process": "^5.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "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.22.0" + }, + "time": "2023-06-01T12:35:21+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "9.2.26", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "443bc6912c9bd5b409254a40f4b0f4ced7c80ea1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/443bc6912c9bd5b409254a40f4b0f4ced7c80ea1", + "reference": "443bc6912c9bd5b409254a40f4b0f4ced7c80ea1", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^4.15", + "php": ">=7.3", + "phpunit/php-file-iterator": "^3.0.3", + "phpunit/php-text-template": "^2.0.2", + "sebastian/code-unit-reverse-lookup": "^2.0.2", + "sebastian/complexity": "^2.0", + "sebastian/environment": "^5.1.2", + "sebastian/lines-of-code": "^1.0.3", + "sebastian/version": "^3.0.1", + "theseer/tokenizer": "^1.2.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "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": { + "branch-alias": { + "dev-master": "9.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.26" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-03-06T12:58:08+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "3.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2021-12-02T12:48:52+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "3.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:58:55+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T05:33:50+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "5.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:16:10+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "9.6.9", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "a9aceaf20a682aeacf28d582654a1670d8826778" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a9aceaf20a682aeacf28d582654a1670d8826778", + "reference": "a9aceaf20a682aeacf28d582654a1670d8826778", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.3.1 || ^2", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.10.1", + "phar-io/manifest": "^2.0.3", + "phar-io/version": "^3.0.2", + "php": ">=7.3", + "phpunit/php-code-coverage": "^9.2.13", + "phpunit/php-file-iterator": "^3.0.5", + "phpunit/php-invoker": "^3.1.1", + "phpunit/php-text-template": "^2.0.3", + "phpunit/php-timer": "^5.0.2", + "sebastian/cli-parser": "^1.0.1", + "sebastian/code-unit": "^1.0.6", + "sebastian/comparator": "^4.0.8", + "sebastian/diff": "^4.0.3", + "sebastian/environment": "^5.1.3", + "sebastian/exporter": "^4.0.5", + "sebastian/global-state": "^5.0.1", + "sebastian/object-enumerator": "^4.0.3", + "sebastian/resource-operations": "^3.0.3", + "sebastian/type": "^3.2", + "sebastian/version": "^3.0.2" + }, + "suggest": { + "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" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.6-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "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.9" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2023-06-11T06:13:56+00:00" + }, + { + "name": "psr/clock", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/clock.git", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Clock\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for reading the clock.", + "homepage": "https://github.com/php-fig/clock", + "keywords": [ + "clock", + "now", + "psr", + "psr-20", + "time" + ], + "support": { + "issues": "https://github.com/php-fig/clock/issues", + "source": "https://github.com/php-fig/clock/tree/1.0.0" + }, + "time": "2022-11-25T14:36:26+00:00" + }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "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/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" + }, + { + "name": "psr/log", + "version": "1.1.4", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/1.1.4" + }, + "time": "2021-05-03T11:20:27+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:08:49+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "1.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:08:54+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:30:19+00:00" + }, + { + "name": "sebastian/comparator", + "version": "4.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/diff": "^4.0", + "sebastian/exporter": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-09-14T12:41:17+00:00" + }, + { + "name": "sebastian/complexity", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", + "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.7", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T15:52:27+00:00" + }, + { + "name": "sebastian/diff", + "version": "4.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131", + "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-05-07T05:35:17+00:00" + }, + { + "name": "sebastian/environment", + "version": "5.1.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:03:51+00:00" + }, + { + "name": "sebastian/exporter", + "version": "4.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-09-14T06:03:37+00:00" + }, + { + "name": "sebastian/global-state", + "version": "5.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2", + "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-02-14T08:28:10+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", + "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.6", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-28T06:42:11+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:12:34+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:14:26+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "4.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:07:39+00:00" + }, + { + "name": "sebastian/resource-operations", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "support": { + "issues": "https://github.com/sebastianbergmann/resource-operations/issues", + "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:45:17+00:00" + }, + { + "name": "sebastian/type", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:13:03+00:00" + }, + { + "name": "sebastian/version", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c6c1022351a901512170118436c764e473f6de8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", + "reference": "c6c1022351a901512170118436c764e473f6de8c", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:39:44+00:00" + }, + { + "name": "symfony/console", + "version": "v3.4.47", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "a10b1da6fc93080c180bba7219b5ff5b7518fe81" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/a10b1da6fc93080c180bba7219b5ff5b7518fe81", + "reference": "a10b1da6fc93080c180bba7219b5ff5b7518fe81", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "symfony/debug": "~2.8|~3.0|~4.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/dependency-injection": "<3.4", + "symfony/process": "<3.3" + }, + "provide": { + "psr/log-implementation": "1.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~3.3|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/event-dispatcher": "~2.8|~3.0|~4.0", + "symfony/lock": "~3.4|~4.0", + "symfony/process": "~3.3|~4.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "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": "Symfony Console Component", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/console/tree/v3.4.47" + }, + "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": "2020-10-24T10:57:07+00:00" + }, + { + "name": "symfony/debug", + "version": "v4.4.44", + "source": { + "type": "git", + "url": "https://github.com/symfony/debug.git", + "reference": "1a692492190773c5310bc7877cb590c04c2f05be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/debug/zipball/1a692492190773c5310bc7877cb590c04c2f05be", + "reference": "1a692492190773c5310bc7877cb590c04c2f05be", + "shasum": "" + }, + "require": { + "php": ">=7.1.3", + "psr/log": "^1|^2|^3" + }, + "conflict": { + "symfony/http-kernel": "<3.4" + }, + "require-dev": { + "symfony/http-kernel": "^3.4|^4.0|^5.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Debug\\": "" + }, + "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 tools to ease debugging PHP code", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/debug/tree/v4.4.44" + }, + "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" + } + ], + "abandoned": "symfony/error-handler", + "time": "2022-07-28T16:29:46+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "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": { - "ArtificialOwl\\MySmallPhpTools\\": "lib/" + "Symfony\\Polyfill\\Mbstring\\": "" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "AGPL-3.0-or-later" + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "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-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": "theseer/tokenizer", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.1" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2021-07-28T10:34:58+00:00" + }, + { + "name": "vimeo/psalm", + "version": "4.30.0", + "source": { + "type": "git", + "url": "https://github.com/vimeo/psalm.git", + "reference": "d0bc6e25d89f649e4f36a534f330f8bb4643dd69" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vimeo/psalm/zipball/d0bc6e25d89f649e4f36a534f330f8bb4643dd69", + "reference": "d0bc6e25d89f649e4f36a534f330f8bb4643dd69", + "shasum": "" + }, + "require": { + "amphp/amp": "^2.4.2", + "amphp/byte-stream": "^1.5", + "composer/package-versions-deprecated": "^1.8.0", + "composer/semver": "^1.4 || ^2.0 || ^3.0", + "composer/xdebug-handler": "^1.1 || ^2.0 || ^3.0", + "dnoegel/php-xdg-base-dir": "^0.1.1", + "ext-ctype": "*", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-simplexml": "*", + "ext-tokenizer": "*", + "felixfbecker/advanced-json-rpc": "^3.0.3", + "felixfbecker/language-server-protocol": "^1.5", + "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", + "nikic/php-parser": "^4.13", + "openlss/lib-array2xml": "^1.0", + "php": "^7.1|^8", + "sebastian/diff": "^3.0 || ^4.0", + "symfony/console": "^3.4.17 || ^4.1.6 || ^5.0 || ^6.0", + "symfony/polyfill-php80": "^1.25", + "webmozart/path-util": "^2.3" + }, + "provide": { + "psalm/psalm": "self.version" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.2", + "brianium/paratest": "^4.0||^6.0", + "ext-curl": "*", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpdocumentor/reflection-docblock": "^5", + "phpmyadmin/sql-parser": "5.1.0||dev-master", + "phpspec/prophecy": ">=1.9.0", + "phpstan/phpdoc-parser": "1.2.* || 1.6.4", + "phpunit/phpunit": "^9.0", + "psalm/plugin-phpunit": "^0.16", + "slevomat/coding-standard": "^7.0", + "squizlabs/php_codesniffer": "^3.5", + "symfony/process": "^4.3 || ^5.0 || ^6.0", + "weirdan/prophecy-shim": "^1.0 || ^2.0" + }, + "suggest": { + "ext-curl": "In order to send data to shepherd", + "ext-igbinary": "^2.0.5 is required, used to serialize caching data" + }, + "bin": [ + "psalm", + "psalm-language-server", + "psalm-plugin", + "psalm-refactor", + "psalter" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev", + "dev-3.x": "3.x-dev", + "dev-2.x": "2.x-dev", + "dev-1.x": "1.x-dev" + } + }, + "autoload": { + "files": [ + "src/functions.php", + "src/spl_object_id.php" + ], + "psr-4": { + "Psalm\\": "src/Psalm/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matthew Brown" + } + ], + "description": "A static analysis tool for finding errors in PHP applications", + "keywords": [ + "code", + "inspection", + "php" + ], + "support": { + "issues": "https://github.com/vimeo/psalm/issues", + "source": "https://github.com/vimeo/psalm/tree/4.30.0" + }, + "time": "2022-11-06T20:37:08+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "php": "^7.2 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.11.0" + }, + "time": "2022-06-03T18:03:27+00:00" + }, + { + "name": "webmozart/path-util", + "version": "2.3.0", + "source": { + "type": "git", + "url": "https://github.com/webmozart/path-util.git", + "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/path-util/zipball/d939f7edc24c9a1bb9c0dee5cb05d8e859490725", + "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "webmozart/assert": "~1.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.6", + "sebastian/version": "^1.0.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.3-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\PathUtil\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" ], "authors": [ { - "name": "Maxence Lange", - "email": "maxence@artificial-owl.com" + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" } ], - "description": "My small PHP Tools", + "description": "A robust cross-platform utility for normalizing, comparing and modifying file paths.", "support": { - "issues": "https://github.com/ArtificialOwl/my-small-php-tools/issues", - "source": "https://github.com/ArtificialOwl/my-small-php-tools/tree/v23.0.2" + "issues": "https://github.com/webmozart/path-util/issues", + "source": "https://github.com/webmozart/path-util/tree/2.3.0" }, - "time": "2021-07-26T12:32:51+00:00" + "abandoned": "symfony/filesystem", + "time": "2015-12-17T08:42:14+00:00" } ], - "packages-dev": [], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "nextcloud/ocp": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": [], "platform-dev": [], - "plugin-api-version": "2.0.0" + "platform-overrides": { + "php": "8.0" + }, + "plugin-api-version": "2.3.0" } diff --git a/lib/ACommandBase.php b/lib/ACommandBase.php index 56d5129f..1457ecee 100644 --- a/lib/ACommandBase.php +++ b/lib/ACommandBase.php @@ -1,4 +1,5 @@ get(IURLGenerator::class); return [ - 'id' => self::APP_ID, + 'id' => self::APP_ID, 'order' => 5, - 'href' => $urlGen->linkToRoute(self::APP_ID . '.Navigation.navigate'), - 'icon' => $urlGen->imagePath(self::APP_ID, 'fulltextsearch.svg'), - 'name' => 'Search' + 'href' => $urlGen->linkToRoute(self::APP_ID . '.Navigation.navigate'), + 'icon' => $urlGen->imagePath(self::APP_ID, 'fulltextsearch.svg'), + 'name' => 'Search' ]; } } - diff --git a/lib/Capabilities.php b/lib/Capabilities.php index d662ae84..571b3f6c 100644 --- a/lib/Capabilities.php +++ b/lib/Capabilities.php @@ -1,4 +1,5 @@ [ - 'remote' => true, + 'remote' => true, 'providers' => $this->providerService->serialize($providers) ] ]; @@ -89,7 +88,3 @@ public function getCapabilities(): array { } - - - - diff --git a/lib/Command/Check.php b/lib/Command/Check.php index 385561e3..f581e011 100644 --- a/lib/Command/Check.php +++ b/lib/Command/Check.php @@ -1,4 +1,5 @@ getPlatform(); $platform->loadPlatform(); $resultPlatform[] = [ - 'class' => $platformWrapper->getClass(), + 'class' => $platformWrapper->getClass(), 'version' => $platformWrapper->getVersion(), - 'config' => $platform->getConfiguration() + 'config' => $platform->getConfiguration() ]; } @@ -146,7 +145,7 @@ private function displayAsJson(): array { $provider = $providerWrapper->getProvider(); $resultProviders[$provider->getId()] = [ 'version' => $providerWrapper->getVersion(), - 'config' => $provider->getConfiguration() + 'config' => $provider->getConfiguration() ]; } } catch (Exception $e) { @@ -156,10 +155,10 @@ private function displayAsJson(): array { return [ 'fulltextsearch' => [ 'version' => $this->configService->getAppValue('installed_version'), - 'config' => $this->configService->getConfig() + 'config' => $this->configService->getConfig() ], - 'platform' => $resultPlatform, + 'platform' => $resultPlatform, 'providers' => $resultProviders ]; @@ -224,4 +223,3 @@ private function displayProviders(OutputInterface $output) { } } - diff --git a/lib/Command/CollectionDelete.php b/lib/Command/CollectionDelete.php index 98b0a239..3e1a004f 100644 --- a/lib/Command/CollectionDelete.php +++ b/lib/Command/CollectionDelete.php @@ -1,4 +1,5 @@ collectionService->confirmCollectionString($collection); $runner = new Runner($this->runningService, 'commandIndex', ['nextStep' => 'n']); -// $runner->sourceIsCommandLine($this, $output); + // $runner->sourceIsCommandLine($this, $output); $this->collectionService->setRunner($runner); $this->cliService->setRunner($runner); $this->cliService->createPanel( 'collection', [ - '┌─ Collection ' . $collection . ' ────', - '│ ProviderId, UserId: %providerId% / %userId%', - '│ Chunk: %chunkCurr:3s%/%chunkTotal%', - '│ Document: %documentCurr:6s%/%documentChunk%', - '│', - '│ Total Document: %documentTotal%', - '│ Index initiated: %indexCount%', - '└──' - ] + '┌─ Collection ' . $collection . ' ────', + '│ ProviderId, UserId: %providerId% / %userId%', + '│ Chunk: %chunkCurr:3s%/%chunkTotal%', + '│ Document: %documentCurr:6s%/%documentChunk%', + '│', + '│ Total Document: %documentTotal%', + '│ Index initiated: %indexCount%', + '└──' + ] ); $runner->setInfoArray([ - 'providerId' => '', - 'userId' => '', - 'chunkCurr' => '', - 'chunkTotal' => '', - 'documentCurr' => '', - 'documentChunk' => '', - 'documentTotal' => '', - 'indexCount' => 0 - ]); + 'providerId' => '', + 'userId' => '', + 'chunkCurr' => '', + 'chunkTotal' => '', + 'documentCurr' => '', + 'documentChunk' => '', + 'documentTotal' => '', + 'indexCount' => 0 + ]); $this->cliService->initDisplay(); $this->cliService->displayPanel('run', 'collection'); diff --git a/lib/Command/CollectionList.php b/lib/Command/CollectionList.php index c267107c..e637a12c 100644 --- a/lib/Command/CollectionList.php +++ b/lib/Command/CollectionList.php @@ -1,4 +1,5 @@ 'document will never be indexed', - 'INDEX' => 'document will be indexed', - 'DONE' => 'document is well indexed', + 'INDEX' => 'document will be indexed', + 'DONE' => 'document is well indexed', 'REMOVE' => 'document will be removed', 'FAILED' => 'index had fail' ]; @@ -157,11 +157,11 @@ private function statusConvertToString(int $status): string { case IIndex::INDEX_META: case IIndex::INDEX_CONTENT: - case IIndex:: INDEX_PARTS: - case IIndex:: INDEX_FULL: + case IIndex::INDEX_PARTS: + case IIndex::INDEX_FULL: return 'INDEX'; - case IIndex:: INDEX_REMOVE: + case IIndex::INDEX_REMOVE: return 'REMOVE'; case IIndex::INDEX_FAILED: @@ -187,10 +187,10 @@ private function statusConvertFromString(string $status): int { return IIndex::INDEX_IGNORE; case 'INDEX': - return IIndex:: INDEX_FULL; + return IIndex::INDEX_FULL; case 'REMOVE': - return IIndex:: INDEX_REMOVE; + return IIndex::INDEX_REMOVE; case 'FAILED': return IIndex::INDEX_FAILED; @@ -200,4 +200,3 @@ private function statusConvertFromString(string $status): int { } } - diff --git a/lib/Command/Index.php b/lib/Command/Index.php index 1508769d..06fcb806 100644 --- a/lib/Command/Index.php +++ b/lib/Command/Index.php @@ -1,4 +1,5 @@ %providerName:-20s% Account: %userId%'; - const PANEL_INDEX_LINE_ACTION = '│ Action: %action%'; - const PANEL_INDEX_LINE_DOCUMENT = '│ Document: %documentId%'; - const PANEL_INDEX_LINE_INFO = '│ Info: %info%'; - const PANEL_INDEX_LINE_TITLE = '│ Title: %title%'; - const PANEL_INDEX_LINE_CONTENT = '│ Content size: %content%'; - const PANEL_INDEX_LINE_CHUNK = '│ Chunk: %chunkCurrent:6s%/%chunkTotal%'; - const PANEL_INDEX_LINE_PROGRESS = '│ Progress: %documentCurrent:6s%/%documentTotal%'; - const PANEL_INDEX_LINE_FOOTER = '└──'; - - const PANEL_RESULT = 'result'; - const PANEL_RESULT_LINE_HEADER = '┌─ Results ────'; - const PANEL_RESULT_LINE_RESULT = '│ Result: %resultCurrent:6s%/%resultTotal%'; - const PANEL_RESULT_LINE_INDEX = '│ Index: %resultIndex%'; - const PANEL_RESULT_LINE_STATUS = '│ Status: %resultStatusColored%'; - const PANEL_RESULT_LINE_MESSAGE1 = '│ Message: %resultMessageA%'; - const PANEL_RESULT_LINE_MESSAGE2 = '│ %resultMessageB%'; - const PANEL_RESULT_LINE_MESSAGE3 = '│ %resultMessageC%'; - const PANEL_RESULT_LINE_FOOTER = '└──'; - - const PANEL_ERRORS = 'errors'; - const PANEL_ERRORS_LINE_HEADER = '┌─ Errors ────'; - const PANEL_ERRORS_LINE_ERRORS = '│ Error: %errorCurrent:6s%/%errorTotal%'; - const PANEL_ERRORS_LINE_ERROR_INDEX = '│ Index: %errorIndex%'; - const PANEL_ERRORS_LINE_ERROR_EXCEPTION = '│ Exception: %errorException%'; - const PANEL_ERRORS_LINE_ERROR_MESSAGE1 = '│ Message: %errorMessageA%'; - const PANEL_ERRORS_LINE_ERROR_MESSAGE2 = '│ %errorMessageB%'; - const PANEL_ERRORS_LINE_ERROR_MESSAGE3 = '│ %errorMessageC%'; - const PANEL_ERRORS_LINE_FOOTER = '└──'; - - const PANEL_COMMANDS_ROOT = 'root'; - const PANEL_COMMANDS_ROOT_LINE = '## q:quit ## p:pause '; - const PANEL_COMMANDS_PAUSED = 'paused'; - const PANEL_COMMANDS_PAUSED_LINE = '## q:quit ## u:unpause ## n:next step'; - const PANEL_COMMANDS_DONE = 'done'; - const PANEL_COMMANDS_DONE_LINE = '## q:quit'; - const PANEL_COMMANDS_NAVIGATION = 'navigation'; - const PANEL_COMMANDS_ERRORS_LINE = '## f:first error ## h/j:prec/next error ## d:delete error ## l:last error'; - const PANEL_COMMANDS_RESULTS_LINE = '## x:first result ## c/v:prec/next result ## b:last result'; + public const INDEX_OPTION_NO_READLINE = '_no-readline'; + + // '%job:1s%%message:-40s%%current:6s%/%max:6s% [%bar%] %percent:3s%% \n %duration% %infos:-12s% %jvm:-30s% ' + public const PANEL_RUN = 'run'; + public const PANEL_RUN_LINE_OPTIONS = 'Options: %options%'; + public const PANEL_RUN_LINE_MEMORY = 'Memory: %_memory%'; + + public const PANEL_INDEX = 'indexing'; + public const PANEL_INDEX_LINE_HEADER = '┌─ Indexing %_paused% ────'; + public const PANEL_INDEX_LINE_ACCOUNT = '│ Provider: %providerName:-20s% Account: %userId%'; + public const PANEL_INDEX_LINE_ACTION = '│ Action: %action%'; + public const PANEL_INDEX_LINE_DOCUMENT = '│ Document: %documentId%'; + public const PANEL_INDEX_LINE_INFO = '│ Info: %info%'; + public const PANEL_INDEX_LINE_TITLE = '│ Title: %title%'; + public const PANEL_INDEX_LINE_CONTENT = '│ Content size: %content%'; + public const PANEL_INDEX_LINE_CHUNK = '│ Chunk: %chunkCurrent:6s%/%chunkTotal%'; + public const PANEL_INDEX_LINE_PROGRESS = '│ Progress: %documentCurrent:6s%/%documentTotal%'; + public const PANEL_INDEX_LINE_FOOTER = '└──'; + + public const PANEL_RESULT = 'result'; + public const PANEL_RESULT_LINE_HEADER = '┌─ Results ────'; + public const PANEL_RESULT_LINE_RESULT = '│ Result: %resultCurrent:6s%/%resultTotal%'; + public const PANEL_RESULT_LINE_INDEX = '│ Index: %resultIndex%'; + public const PANEL_RESULT_LINE_STATUS = '│ Status: %resultStatusColored%'; + public const PANEL_RESULT_LINE_MESSAGE1 = '│ Message: %resultMessageA%'; + public const PANEL_RESULT_LINE_MESSAGE2 = '│ %resultMessageB%'; + public const PANEL_RESULT_LINE_MESSAGE3 = '│ %resultMessageC%'; + public const PANEL_RESULT_LINE_FOOTER = '└──'; + + public const PANEL_ERRORS = 'errors'; + public const PANEL_ERRORS_LINE_HEADER = '┌─ Errors ────'; + public const PANEL_ERRORS_LINE_ERRORS = '│ Error: %errorCurrent:6s%/%errorTotal%'; + public const PANEL_ERRORS_LINE_ERROR_INDEX = '│ Index: %errorIndex%'; + public const PANEL_ERRORS_LINE_ERROR_EXCEPTION = '│ Exception: %errorException%'; + public const PANEL_ERRORS_LINE_ERROR_MESSAGE1 = '│ Message: %errorMessageA%'; + public const PANEL_ERRORS_LINE_ERROR_MESSAGE2 = '│ %errorMessageB%'; + public const PANEL_ERRORS_LINE_ERROR_MESSAGE3 = '│ %errorMessageC%'; + public const PANEL_ERRORS_LINE_FOOTER = '└──'; + + public const PANEL_COMMANDS_ROOT = 'root'; + public const PANEL_COMMANDS_ROOT_LINE = '## q:quit ## p:pause '; + public const PANEL_COMMANDS_PAUSED = 'paused'; + public const PANEL_COMMANDS_PAUSED_LINE = '## q:quit ## u:unpause ## n:next step'; + public const PANEL_COMMANDS_DONE = 'done'; + public const PANEL_COMMANDS_DONE_LINE = '## q:quit'; + public const PANEL_COMMANDS_NAVIGATION = 'navigation'; + public const PANEL_COMMANDS_ERRORS_LINE = '## f:first error ## h/j:prec/next error ## d:delete error ## l:last error'; + public const PANEL_COMMANDS_RESULTS_LINE = '## x:first result ## c/v:prec/next result ## b:last result'; /** @var IUserManager */ private $userManager; @@ -201,8 +200,8 @@ protected function configure() { ->setDescription('Index files') ->addArgument('options', InputArgument::OPTIONAL, 'options') ->addOption( - 'no-readline', 'r', InputOption::VALUE_NONE, - 'disable readline - non interactive mode' + 'no-readline', 'r', InputOption::VALUE_NONE, + 'disable readline - non interactive mode' ); } @@ -224,7 +223,7 @@ protected function execute(InputInterface $input, OutputInterface $output) { try { readline_callback_handler_install( '', function () { - } + } ); } catch (Throwable $t) { $this->miscService->log($t->getMessage() . ' -- ' . $t->getTraceAsString()); @@ -236,9 +235,9 @@ protected function execute(InputInterface $input, OutputInterface $output) { $this->terminal = new Terminal(); -// $outputStyle = new OutputFormatterStyle('white', 'black', ['bold']); -// $output->getFormatter() -// ->setStyle('char', $outputStyle); + // $outputStyle = new OutputFormatterStyle('white', 'black', ['bold']); + // $output->getFormatter() + // ->setStyle('char', $outputStyle); $this->runner = new Runner($this->runningService, 'commandIndex', ['nextStep' => 'n']); $this->runner->onKeyPress([$this, 'onKeyPressed']); @@ -287,18 +286,18 @@ protected function execute(InputInterface $input, OutputInterface $output) { $this->runner->setInfo('documentCurrent', 'all'); $this->runner->stop(); -// while (true) { -// $this->runner->updateAction('_indexOver', true); -// $pressed = strtolower($this->updateAction('')); -// if ($pressed === $this->keys['nextStep']) { -// $this->pauseRunning(false); -// break; -// } -// usleep(300000); -// } + // while (true) { + // $this->runner->updateAction('_indexOver', true); + // $pressed = strtolower($this->updateAction('')); + // if ($pressed === $this->keys['nextStep']) { + // $this->pauseRunning(false); + // break; + // } + // usleep(300000); + // } -// $output->writeLn(''); + // $output->writeLn(''); return 0; } @@ -502,62 +501,62 @@ private function generatePanels(IndexOptions $options) { $this->cliService->createPanel( self::PANEL_INDEX, [ - self::PANEL_INDEX_LINE_HEADER, - self::PANEL_INDEX_LINE_ACTION, - self::PANEL_INDEX_LINE_ACCOUNT, - self::PANEL_INDEX_LINE_DOCUMENT, - self::PANEL_INDEX_LINE_INFO, - self::PANEL_INDEX_LINE_TITLE, - self::PANEL_INDEX_LINE_CONTENT, - self::PANEL_INDEX_LINE_CHUNK, - self::PANEL_INDEX_LINE_PROGRESS, - self::PANEL_INDEX_LINE_FOOTER, - ] + self::PANEL_INDEX_LINE_HEADER, + self::PANEL_INDEX_LINE_ACTION, + self::PANEL_INDEX_LINE_ACCOUNT, + self::PANEL_INDEX_LINE_DOCUMENT, + self::PANEL_INDEX_LINE_INFO, + self::PANEL_INDEX_LINE_TITLE, + self::PANEL_INDEX_LINE_CONTENT, + self::PANEL_INDEX_LINE_CHUNK, + self::PANEL_INDEX_LINE_PROGRESS, + self::PANEL_INDEX_LINE_FOOTER, + ] ); $this->cliService->createPanel( self::PANEL_RESULT, [ - self::PANEL_RESULT_LINE_HEADER, - self::PANEL_RESULT_LINE_RESULT, - self::PANEL_RESULT_LINE_INDEX, - self::PANEL_RESULT_LINE_STATUS, - self::PANEL_RESULT_LINE_MESSAGE1, - self::PANEL_RESULT_LINE_MESSAGE2, - self::PANEL_RESULT_LINE_MESSAGE3, - self::PANEL_RESULT_LINE_FOOTER, - ] + self::PANEL_RESULT_LINE_HEADER, + self::PANEL_RESULT_LINE_RESULT, + self::PANEL_RESULT_LINE_INDEX, + self::PANEL_RESULT_LINE_STATUS, + self::PANEL_RESULT_LINE_MESSAGE1, + self::PANEL_RESULT_LINE_MESSAGE2, + self::PANEL_RESULT_LINE_MESSAGE3, + self::PANEL_RESULT_LINE_FOOTER, + ] ); $this->cliService->createPanel( self::PANEL_ERRORS, [ - self::PANEL_ERRORS_LINE_HEADER, - self::PANEL_ERRORS_LINE_ERRORS, - self::PANEL_ERRORS_LINE_ERROR_INDEX, - self::PANEL_ERRORS_LINE_ERROR_EXCEPTION, - self::PANEL_ERRORS_LINE_ERROR_MESSAGE1, - self::PANEL_ERRORS_LINE_ERROR_MESSAGE2, - self::PANEL_ERRORS_LINE_ERROR_MESSAGE3, - self::PANEL_ERRORS_LINE_FOOTER, - ] + self::PANEL_ERRORS_LINE_HEADER, + self::PANEL_ERRORS_LINE_ERRORS, + self::PANEL_ERRORS_LINE_ERROR_INDEX, + self::PANEL_ERRORS_LINE_ERROR_EXCEPTION, + self::PANEL_ERRORS_LINE_ERROR_MESSAGE1, + self::PANEL_ERRORS_LINE_ERROR_MESSAGE2, + self::PANEL_ERRORS_LINE_ERROR_MESSAGE3, + self::PANEL_ERRORS_LINE_FOOTER, + ] ); $this->cliService->createPanel( self::PANEL_COMMANDS_PAUSED, [ - self::PANEL_COMMANDS_PAUSED_LINE - ] + self::PANEL_COMMANDS_PAUSED_LINE + ] ); $this->cliService->createPanel( self::PANEL_COMMANDS_ROOT, [ - self::PANEL_COMMANDS_ROOT_LINE - ] + self::PANEL_COMMANDS_ROOT_LINE + ] ); $this->cliService->createPanel( self::PANEL_COMMANDS_NAVIGATION, [ - self::PANEL_COMMANDS_RESULTS_LINE, - self::PANEL_COMMANDS_ERRORS_LINE - ] + self::PANEL_COMMANDS_RESULTS_LINE, + self::PANEL_COMMANDS_ERRORS_LINE + ] ); $this->cliService->initDisplay(); @@ -888,4 +887,3 @@ public function abort() { } - diff --git a/lib/Command/Live.php b/lib/Command/Live.php index 79684ca5..6120e8a0 100644 --- a/lib/Command/Live.php +++ b/lib/Command/Live.php @@ -1,4 +1,5 @@ %providerName:-20s% Account: %userId%'; - const PANEL_INDEX_LINE_ACTION = '│ Action: %action%'; - const PANEL_INDEX_LINE_DOCUMENT = '│ Document: %documentId%'; - const PANEL_INDEX_LINE_INFO = '│ Info: %info%'; - const PANEL_INDEX_LINE_TITLE = '│ Title: %title%'; - const PANEL_INDEX_LINE_CONTENT = '│ Content size: %content%'; - const PANEL_INDEX_LINE_FOOTER = '└──'; - - const PANEL_RESULT = 'result'; - const PANEL_RESULT_LINE_HEADER = '┌─ Results ────'; - const PANEL_RESULT_LINE_RESULT = '│ Result: %resultCurrent:6s%/%resultTotal%'; - const PANEL_RESULT_LINE_INDEX = '│ Index: %resultIndex%'; - const PANEL_RESULT_LINE_STATUS = '│ Status: %resultStatusColored%'; - const PANEL_RESULT_LINE_MESSAGE1 = '│ Message: %resultMessageA%'; - const PANEL_RESULT_LINE_MESSAGE2 = '│ %resultMessageB%'; - const PANEL_RESULT_LINE_MESSAGE3 = '│ %resultMessageC%'; - const PANEL_RESULT_LINE_FOOTER = '└──'; - - const PANEL_ERRORS = 'errors'; - const PANEL_ERRORS_LINE_HEADER = '┌─ Errors ────'; - const PANEL_ERRORS_LINE_ERRORS = '│ Error: %errorCurrent:6s%/%errorTotal%'; - const PANEL_ERRORS_LINE_ERROR_INDEX = '│ Index: %errorIndex%'; - const PANEL_ERRORS_LINE_ERROR_EXCEPTION = '│ Exception: %errorException%'; - const PANEL_ERRORS_LINE_ERROR_MESSAGE1 = '│ Message: %errorMessageA%'; - const PANEL_ERRORS_LINE_ERROR_MESSAGE2 = '│ %errorMessageB%'; - const PANEL_ERRORS_LINE_ERROR_MESSAGE3 = '│ %errorMessageC%'; - const PANEL_ERRORS_LINE_FOOTER = '└──'; - - const PANEL_COMMANDS_ROOT = 'root'; - const PANEL_COMMANDS_ROOT_LINE = '## q:quit ## p:pause '; - const PANEL_COMMANDS_PAUSED = 'paused'; - const PANEL_COMMANDS_PAUSED_LINE = '## q:quit ## u:unpause ## n:next step'; - const PANEL_COMMANDS_DONE = 'done'; - const PANEL_COMMANDS_DONE_LINE = '## q:quit'; - const PANEL_COMMANDS_NAVIGATION = 'navigation'; - const PANEL_COMMANDS_ERRORS_LINE = '## f:first error ## h/j:prec/next error ## d:delete error ## l:last error'; - const PANEL_COMMANDS_RESULTS_LINE = '## x:first result ## c/v:prec/next result ## b:last result'; + public const INDEX_OPTION_NO_READLINE = '_no-readline'; + + public const CYCLE_DELAY = 3000000; + + public const PANEL_RUN = 'run'; + public const PANEL_RUN_LINE_MEMORY = 'Memory: %_memory%'; + + public const PANEL_INDEX = 'indexing'; + public const PANEL_INDEX_LINE_HEADER = '┌─ Indexing %_paused% ────'; + public const PANEL_INDEX_LINE_ACCOUNT = '│ Provider: %providerName:-20s% Account: %userId%'; + public const PANEL_INDEX_LINE_ACTION = '│ Action: %action%'; + public const PANEL_INDEX_LINE_DOCUMENT = '│ Document: %documentId%'; + public const PANEL_INDEX_LINE_INFO = '│ Info: %info%'; + public const PANEL_INDEX_LINE_TITLE = '│ Title: %title%'; + public const PANEL_INDEX_LINE_CONTENT = '│ Content size: %content%'; + public const PANEL_INDEX_LINE_FOOTER = '└──'; + + public const PANEL_RESULT = 'result'; + public const PANEL_RESULT_LINE_HEADER = '┌─ Results ────'; + public const PANEL_RESULT_LINE_RESULT = '│ Result: %resultCurrent:6s%/%resultTotal%'; + public const PANEL_RESULT_LINE_INDEX = '│ Index: %resultIndex%'; + public const PANEL_RESULT_LINE_STATUS = '│ Status: %resultStatusColored%'; + public const PANEL_RESULT_LINE_MESSAGE1 = '│ Message: %resultMessageA%'; + public const PANEL_RESULT_LINE_MESSAGE2 = '│ %resultMessageB%'; + public const PANEL_RESULT_LINE_MESSAGE3 = '│ %resultMessageC%'; + public const PANEL_RESULT_LINE_FOOTER = '└──'; + + public const PANEL_ERRORS = 'errors'; + public const PANEL_ERRORS_LINE_HEADER = '┌─ Errors ────'; + public const PANEL_ERRORS_LINE_ERRORS = '│ Error: %errorCurrent:6s%/%errorTotal%'; + public const PANEL_ERRORS_LINE_ERROR_INDEX = '│ Index: %errorIndex%'; + public const PANEL_ERRORS_LINE_ERROR_EXCEPTION = '│ Exception: %errorException%'; + public const PANEL_ERRORS_LINE_ERROR_MESSAGE1 = '│ Message: %errorMessageA%'; + public const PANEL_ERRORS_LINE_ERROR_MESSAGE2 = '│ %errorMessageB%'; + public const PANEL_ERRORS_LINE_ERROR_MESSAGE3 = '│ %errorMessageC%'; + public const PANEL_ERRORS_LINE_FOOTER = '└──'; + + public const PANEL_COMMANDS_ROOT = 'root'; + public const PANEL_COMMANDS_ROOT_LINE = '## q:quit ## p:pause '; + public const PANEL_COMMANDS_PAUSED = 'paused'; + public const PANEL_COMMANDS_PAUSED_LINE = '## q:quit ## u:unpause ## n:next step'; + public const PANEL_COMMANDS_DONE = 'done'; + public const PANEL_COMMANDS_DONE_LINE = '## q:quit'; + public const PANEL_COMMANDS_NAVIGATION = 'navigation'; + public const PANEL_COMMANDS_ERRORS_LINE = '## f:first error ## h/j:prec/next error ## d:delete error ## l:last error'; + public const PANEL_COMMANDS_RESULTS_LINE = '## x:first result ## c/v:prec/next result ## b:last result'; /** @var IUserManager */ @@ -196,12 +195,12 @@ protected function configure() { $this->setName('fulltextsearch:live') ->setDescription('Index files') ->addOption( - 'no-readline', 'r', InputOption::VALUE_NONE, - 'disable readline - non interactive mode' + 'no-readline', 'r', InputOption::VALUE_NONE, + 'disable readline - non interactive mode' ) ->addOption( - 'service', 's', InputOption::VALUE_NONE, - 'disable interface' + 'service', 's', InputOption::VALUE_NONE, + 'disable interface' ); } @@ -218,8 +217,8 @@ protected function execute(InputInterface $input, OutputInterface $output) { try { /** do not get stuck while waiting interactive input */ readline_callback_handler_install( - '', function() { - } + '', function () { + } ); } catch (Throwable $t) { throw new Exception('Please install php-readline, or use --no-readline'); @@ -409,60 +408,60 @@ private function generatePanels(bool $commands) { $this->cliService->createPanel( self::PANEL_INDEX, [ - self::PANEL_INDEX_LINE_HEADER, - self::PANEL_INDEX_LINE_ACTION, - self::PANEL_INDEX_LINE_ACCOUNT, - self::PANEL_INDEX_LINE_DOCUMENT, - self::PANEL_INDEX_LINE_INFO, - self::PANEL_INDEX_LINE_TITLE, - self::PANEL_INDEX_LINE_CONTENT, - self::PANEL_INDEX_LINE_FOOTER, - ] + self::PANEL_INDEX_LINE_HEADER, + self::PANEL_INDEX_LINE_ACTION, + self::PANEL_INDEX_LINE_ACCOUNT, + self::PANEL_INDEX_LINE_DOCUMENT, + self::PANEL_INDEX_LINE_INFO, + self::PANEL_INDEX_LINE_TITLE, + self::PANEL_INDEX_LINE_CONTENT, + self::PANEL_INDEX_LINE_FOOTER, + ] ); $this->cliService->createPanel( self::PANEL_RESULT, [ - self::PANEL_RESULT_LINE_HEADER, - self::PANEL_RESULT_LINE_RESULT, - self::PANEL_RESULT_LINE_INDEX, - self::PANEL_RESULT_LINE_STATUS, - self::PANEL_RESULT_LINE_MESSAGE1, - self::PANEL_RESULT_LINE_MESSAGE2, - self::PANEL_RESULT_LINE_MESSAGE3, - self::PANEL_RESULT_LINE_FOOTER, - ] + self::PANEL_RESULT_LINE_HEADER, + self::PANEL_RESULT_LINE_RESULT, + self::PANEL_RESULT_LINE_INDEX, + self::PANEL_RESULT_LINE_STATUS, + self::PANEL_RESULT_LINE_MESSAGE1, + self::PANEL_RESULT_LINE_MESSAGE2, + self::PANEL_RESULT_LINE_MESSAGE3, + self::PANEL_RESULT_LINE_FOOTER, + ] ); $this->cliService->createPanel( self::PANEL_ERRORS, [ - self::PANEL_ERRORS_LINE_HEADER, - self::PANEL_ERRORS_LINE_ERRORS, - self::PANEL_ERRORS_LINE_ERROR_INDEX, - self::PANEL_ERRORS_LINE_ERROR_EXCEPTION, - self::PANEL_ERRORS_LINE_ERROR_MESSAGE1, - self::PANEL_ERRORS_LINE_ERROR_MESSAGE2, - self::PANEL_ERRORS_LINE_ERROR_MESSAGE3, - self::PANEL_ERRORS_LINE_FOOTER, - ] + self::PANEL_ERRORS_LINE_HEADER, + self::PANEL_ERRORS_LINE_ERRORS, + self::PANEL_ERRORS_LINE_ERROR_INDEX, + self::PANEL_ERRORS_LINE_ERROR_EXCEPTION, + self::PANEL_ERRORS_LINE_ERROR_MESSAGE1, + self::PANEL_ERRORS_LINE_ERROR_MESSAGE2, + self::PANEL_ERRORS_LINE_ERROR_MESSAGE3, + self::PANEL_ERRORS_LINE_FOOTER, + ] ); $this->cliService->createPanel( self::PANEL_COMMANDS_ROOT, [ - self::PANEL_COMMANDS_ROOT_LINE - ] + self::PANEL_COMMANDS_ROOT_LINE + ] ); $this->cliService->createPanel( self::PANEL_COMMANDS_PAUSED, [ - self::PANEL_COMMANDS_PAUSED_LINE - ] + self::PANEL_COMMANDS_PAUSED_LINE + ] ); $this->cliService->createPanel( self::PANEL_COMMANDS_NAVIGATION, [ - self::PANEL_COMMANDS_RESULTS_LINE, - self::PANEL_COMMANDS_ERRORS_LINE - ] + self::PANEL_COMMANDS_RESULTS_LINE, + self::PANEL_COMMANDS_ERRORS_LINE + ] ); $this->cliService->initDisplay(); @@ -482,32 +481,32 @@ private function generatePanels(bool $commands) { $this->runner->setInfoArray( [ - 'userId' => '', - 'providerName' => '', - '_memory' => '', - 'documentId' => '', - 'action' => '', - 'info' => '', - 'title' => '', - '_paused' => '', - 'resultIndex' => '', - 'resultCurrent' => '', - 'resultTotal' => '', - 'resultMessageA' => '', - 'resultMessageB' => '', - 'resultMessageC' => '', - 'resultStatus' => '', + 'userId' => '', + 'providerName' => '', + '_memory' => '', + 'documentId' => '', + 'action' => '', + 'info' => '', + 'title' => '', + '_paused' => '', + 'resultIndex' => '', + 'resultCurrent' => '', + 'resultTotal' => '', + 'resultMessageA' => '', + 'resultMessageB' => '', + 'resultMessageC' => '', + 'resultStatus' => '', 'resultStatusColored' => '', - 'content' => '', - 'statusColored' => '', - 'progressStatus' => '', - 'errorCurrent' => '0', - 'errorTotal' => '0', - 'errorMessageA' => '', - 'errorMessageB' => '', - 'errorMessageC' => '', - 'errorException' => '', - 'errorIndex' => '' + 'content' => '', + 'statusColored' => '', + 'progressStatus' => '', + 'errorCurrent' => '0', + 'errorTotal' => '0', + 'errorMessageA' => '', + 'errorMessageB' => '', + 'errorMessageC' => '', + 'errorException' => '', + 'errorIndex' => '' ] ); } @@ -522,10 +521,10 @@ private function generateIndexErrors() { foreach ($indexes as $index) { foreach ($index->getErrors() as $error) { $this->errors[] = [ - 'index' => $index, - 'message' => $error['message'], + 'index' => $index, + 'message' => $error['message'], 'exception' => $error['exception'], - 'severity' => $error['severity'] + 'severity' => $error['severity'] ]; } @@ -544,7 +543,7 @@ private function displayResult(int $pos = 0) { $this->runner->setInfoArray( [ 'resultCurrent' => 0, - 'resultTotal' => 0, + 'resultTotal' => 0, ] ); @@ -580,13 +579,13 @@ private function displayResult(int $pos = 0) { $this->runner->setInfoArray( [ - 'resultCurrent' => $current, - 'resultTotal' => $total, + 'resultCurrent' => $current, + 'resultTotal' => $total, 'resultMessageA' => trim($msg1), 'resultMessageB' => trim($msg2), 'resultMessageC' => trim($msg3), - 'resultStatus' => $status, - 'resultIndex' => $resultIndex + 'resultStatus' => $status, + 'resultIndex' => $resultIndex ] ); $this->runner->setInfoColored('resultStatus', $type); @@ -602,7 +601,7 @@ private function displayError(int $pos = 0) { $this->runner->setInfoArray( [ 'errorCurrent' => 0, - 'errorTotal' => 0, + 'errorTotal' => 0, ] ); @@ -632,13 +631,13 @@ private function displayError(int $pos = 0) { $this->runner->setInfoArray( [ - 'errorCurrent' => $current, - 'errorTotal' => $total, - 'errorMessageA' => trim($err1), - 'errorMessageB' => trim($err2), - 'errorMessageC' => trim($err3), + 'errorCurrent' => $current, + 'errorTotal' => $total, + 'errorMessageA' => trim($err1), + 'errorMessageB' => trim($err2), + 'errorMessageC' => trim($err3), 'errorException' => $this->get('exception', $error, ''), - 'errorIndex' => $errorIndex + 'errorIndex' => $errorIndex ] ); } @@ -736,11 +735,11 @@ private function deleteError() { $this->runner->setInfoArray( [ - 'errorMessageA' => '', - 'errorMessageB' => '', - 'errorMessageC' => '', + 'errorMessageA' => '', + 'errorMessageB' => '', + 'errorMessageC' => '', 'errorException' => '', - 'errorIndex' => '' + 'errorIndex' => '' ] ); @@ -788,4 +787,3 @@ public function abort() { } - diff --git a/lib/Command/Migration24.php b/lib/Command/Migration24.php index 0d9a8991..bee7cee5 100644 --- a/lib/Command/Migration24.php +++ b/lib/Command/Migration24.php @@ -1,4 +1,5 @@ importFromArray( [ 'providers' => 'all', - 'search' => $input->getArgument('string') + 'search' => $input->getArgument('string') ] ); @@ -138,6 +137,3 @@ private function displaySearchResult(ISearchResult $searchResult) { } - - - diff --git a/lib/Command/Stop.php b/lib/Command/Stop.php index d39eab54..4fa730fa 100644 --- a/lib/Command/Stop.php +++ b/lib/Command/Stop.php @@ -1,4 +1,5 @@ setDescription('Testing the platform setup') ->addOption('json', 'j', InputOption::VALUE_NONE, 'return result as JSON') ->addOption( - 'platform_delay', 'd', InputOption::VALUE_REQUIRED, - 'change DELAY_STABILIZE_PLATFORM' + 'platform_delay', 'd', InputOption::VALUE_REQUIRED, + 'change DELAY_STABILIZE_PLATFORM' ); } @@ -301,7 +300,7 @@ private function testLoadingPlatform(OutputInterface $output): IFullTextSearchPl $this->output($output, 'Testing search platform.'); if (!$testPlatform->testPlatform()) { - throw new Exception ('Search platform (' . $testPlatform->getName() . ') down ?'); + throw new Exception('Search platform (' . $testPlatform->getName() . ') down ?'); } $this->outputResult($output, true); @@ -440,7 +439,7 @@ private function testSearchSimple( ); $this->search( $output, $testPlatform, $testProvider, $access, 'document is a simple test', -// [TestService::DOCUMENT_TYPE_SIMPLE] + // [TestService::DOCUMENT_TYPE_SIMPLE] [TestService::DOCUMENT_TYPE_SIMPLE, TestService::DOCUMENT_TYPE_LICENSE] ); $this->search( @@ -500,7 +499,7 @@ private function testUpdatingDocumentsAccess( $this->output($output, 'Updating documents access.'); $options = new IndexOptions( [ - 'provider' => TestProvider::TEST_PROVIDER_ID, + 'provider' => TestProvider::TEST_PROVIDER_ID, TestService::DOCUMENT_INDEXING_OPTION => TestService::DOCUMENT_INDEXING_ACCESS ] ); @@ -717,4 +716,3 @@ public function abort() { } } - diff --git a/lib/Controller/ApiController.php b/lib/Controller/ApiController.php index 989a7bf7..601816d5 100644 --- a/lib/Controller/ApiController.php +++ b/lib/Controller/ApiController.php @@ -1,6 +1,6 @@ userSession = $userSession; - $this->searchService = $searchService; - $this->configService = $configService; - $this->miscService = $miscService; } @@ -103,7 +65,6 @@ public function search(string $request): DataResponse { return $this->searchDocuments(SearchRequest::fromJSON($request)); } - /** * @NoAdminRequired * @NoSubAdminRequired @@ -117,7 +78,6 @@ public function searchFromRemote(string $request): DataResponse { return $this->searchDocuments(SearchRequest::fromJSON($request)); } - /** * @param SearchRequest $request * @@ -126,25 +86,17 @@ public function searchFromRemote(string $request): DataResponse { private function searchDocuments(SearchRequest $request): DataResponse { try { $user = $this->userSession->getUser(); - $result = $this->searchService->search($user->getUID(), $request); + $data = [ + 'result' => $this->searchService->search($user->getUID(), $request), + 'status' => 1 + ]; - return $this->success( - $result, - [ - 'request' => $request, - 'version' => $this->configService->getAppValue('installed_version') - ] - ); + return new DataResponse($data, Http::STATUS_OK); } catch (Exception $e) { - return $this->fail( - $e, - [ - 'request' => $request, - 'version' => $this->configService->getAppValue('installed_version') - ] - ); + $data = ['status' => -1, 'message' => $e->getMessage()]; + $this->logger->warning('issue while searchDocuments', ['exception' => $e, 'request' => $request]); + + return new DataResponse($data, Http::STATUS_INTERNAL_SERVER_ERROR); } } - } - diff --git a/lib/Controller/CollectionController.php b/lib/Controller/CollectionController.php index 26f7f1ae..ff338cc3 100644 --- a/lib/Controller/CollectionController.php +++ b/lib/Controller/CollectionController.php @@ -1,4 +1,5 @@ collectionService->getQueue($collection, $length)); } catch (\Exception $e) { -// $this->e($e, ['circleId' => $circleId]); + // $this->e($e, ['circleId' => $circleId]); throw new OCSException($e->getMessage(), $e->getCode()); } } @@ -161,4 +160,3 @@ private function displayDocument(IIndexDocument $document): array { } } - diff --git a/lib/Controller/NavigationController.php b/lib/Controller/NavigationController.php index 26627faa..acb096c5 100644 --- a/lib/Controller/NavigationController.php +++ b/lib/Controller/NavigationController.php @@ -1,4 +1,5 @@ $searchTemplate->getPanelOptions(), + 'options' => $searchTemplate->getPanelOptions(), 'template' => $template ]; @@ -141,10 +140,10 @@ public function getNavigationPanels(): DataResponse { $ret[$providerAppId] = [ 'provider' => $provider->getId(), - 'title' => $provider->getName(), - 'options' => $searchTemplate->getNavigationOptions(), - 'css' => $searchTemplate->getCss(), - 'icon' => $searchTemplate->getIcon() + 'title' => $provider->getName(), + 'options' => $searchTemplate->getNavigationOptions(), + 'css' => $searchTemplate->getCss(), + 'icon' => $searchTemplate->getIcon() ]; } diff --git a/lib/Cron/Index.php b/lib/Cron/Index.php index 49374fe6..ebc7d801 100644 --- a/lib/Cron/Index.php +++ b/lib/Cron/Index.php @@ -1,4 +1,5 @@ status = $status; - } else if (!$this->isStatus($status)) { + } elseif (!$this->isStatus($status)) { $this->status += $status; } @@ -385,11 +384,11 @@ public function getLastIndex(): int { public function asSitemap(IURLGenerator $urlGenerator): array { return [ 'url' => $urlGenerator->linkToOCSRouteAbsolute('fulltextsearch.Collection.indexDocument', - [ - 'collection' => $this->getCollection(), - 'providerId' => $this->getProviderId(), - 'documentId' => $this->getDocumentId() - ] + [ + 'collection' => $this->getCollection(), + 'providerId' => $this->getProviderId(), + 'documentId' => $this->getDocumentId() + ] ), 'status' => $this->getStatus() ]; diff --git a/lib/Model/IndexOptions.php b/lib/Model/IndexOptions.php index 6d548765..1db30262 100644 --- a/lib/Model/IndexOptions.php +++ b/lib/Model/IndexOptions.php @@ -1,4 +1,5 @@ options; } } - diff --git a/lib/Model/PlatformWrapper.php b/lib/Model/PlatformWrapper.php index 6f9f84c5..e7c011bd 100644 --- a/lib/Model/PlatformWrapper.php +++ b/lib/Model/PlatformWrapper.php @@ -1,4 +1,5 @@ wildcardFields; } -// -// /** -// * @param array $query -// * -// * @return ISearchRequest -// */ -// public function addWildcardQuery($query) { -// $this->addWildcardQueries([$query]); -// -// return $this; -// } -// -// /** -// * @param array $query -// * -// * @return ISearchRequest -// */ -// public function addWildcardQueries($query) { -// array_push($this->wildcardQueries, $query); -// -// return $this; -// } -// -// /** -// * @return array -// */ -// public function getWildcardQueries() { -// return $this->wildcardQueries; -// } + // + // /** + // * @param array $query + // * + // * @return ISearchRequest + // */ + // public function addWildcardQuery($query) { + // $this->addWildcardQueries([$query]); + // + // return $this; + // } + // + // /** + // * @param array $query + // * + // * @return ISearchRequest + // */ + // public function addWildcardQueries($query) { + // array_push($this->wildcardQueries, $query); + // + // return $this; + // } + // + // /** + // * @return array + // */ + // public function getWildcardQueries() { + // return $this->wildcardQueries; + // } /** @@ -758,7 +757,7 @@ public function importFromArray($arr): SearchRequest { } // END TODO -// $this->setEmptySearch($this->getBool('empty_search', $arr, false)); + // $this->setEmptySearch($this->getBool('empty_search', $arr, false)); $this->setPage($this->getInt('page', $arr, 0)); $this->setParts($this->getArray('parts', $arr, [])); $this->setSize($this->getInt('size', $arr, 10)); diff --git a/lib/Model/SearchResult.php b/lib/Model/SearchResult.php index 4d0a9668..804d31b0 100644 --- a/lib/Model/SearchResult.php +++ b/lib/Model/SearchResult.php @@ -1,4 +1,5 @@ $providerObj->getId(), + 'id' => $providerObj->getId(), 'name' => $providerObj->getName() ]; } @@ -320,22 +319,22 @@ public function jsonSerialize(): array { $platform = []; if ($platformObj !== null) { $platform = [ - 'id' => $platformObj->getId(), + 'id' => $platformObj->getId(), 'name' => $platformObj->getName() ]; } return [ - 'provider' => $provider, - 'platform' => $platform, + 'provider' => $provider, + 'platform' => $platform, 'documents' => $this->getDocuments(), - 'info' => $this->getInfosAll(), - 'meta' => + 'info' => $this->getInfosAll(), + 'meta' => [ 'timedOut' => $this->isTimedOut(), - 'time' => $this->getTime(), - 'count' => $this->getCount(), - 'total' => $this->getTotal(), + 'time' => $this->getTime(), + 'count' => $this->getCount(), + 'total' => $this->getTotal(), 'maxScore' => $this->getMaxScore() ] ]; @@ -353,4 +352,3 @@ public function getInfosAll(): array { return []; } } - diff --git a/lib/Model/Tick.php b/lib/Model/Tick.php index fada00a8..00962590 100644 --- a/lib/Model/Tick.php +++ b/lib/Model/Tick.php @@ -1,4 +1,5 @@ setProviders(['all']); $searchRequest->setSearch($query->getTerm()); @@ -208,4 +208,3 @@ private function convertSearchResult(array $searchResult): array { } } - diff --git a/lib/Search/UnifiedSearchResult.php b/lib/Search/UnifiedSearchResult.php index de47a23b..f6642627 100644 --- a/lib/Search/UnifiedSearchResult.php +++ b/lib/Search/UnifiedSearchResult.php @@ -1,4 +1,5 @@ displayedPanel[] = [ 'slot' => $panelSlot, - 'id' => $panelId + 'id' => $panelId ]; } @@ -138,7 +137,7 @@ public function currentPanel(string $panelSlot): string { */ public function switchPanel(string $panelSlot, string $panelId) { $this->displayedPanel = array_map( - function($item) use ($panelId, $panelSlot) { + function ($item) use ($panelId, $panelSlot) { if ($item['slot'] === $panelSlot) { $item['id'] = $panelId; } @@ -233,4 +232,3 @@ public function onInfoUpdated(array $info) { } } - diff --git a/lib/Service/CollectionService.php b/lib/Service/CollectionService.php index 1e87a0fc..1f523106 100644 --- a/lib/Service/CollectionService.php +++ b/lib/Service/CollectionService.php @@ -1,4 +1,5 @@ onResettingIndex($platform); + // $provider->onResettingIndex($platform); $platform->resetIndex($provider->getId()); $this->providerService->setProviderAsIndexed($provider->getId(), false); diff --git a/lib/Service/MigrationService.php b/lib/Service/MigrationService.php index 4b3c7934..15082a07 100644 --- a/lib/Service/MigrationService.php +++ b/lib/Service/MigrationService.php @@ -1,4 +1,5 @@ dbConnection->getQueryBuilder(); $create->insert('fulltextsearch_index') ->values( - [ - 'owner_id' => $create->createParameter('owner_id'), - 'provider_id' => $create->createParameter('provider_id'), - 'collection' => $create->createParameter('collection'), - 'document_id' => $create->createParameter('document_id'), - 'source' => $create->createParameter('source'), - 'err' => $create->createParameter('err'), - 'message' => $create->createParameter('message'), - 'status' => $create->createParameter('status'), - 'options' => $create->createParameter('options'), - 'indexed' => $create->createParameter('indexed') - ] + [ + 'owner_id' => $create->createParameter('owner_id'), + 'provider_id' => $create->createParameter('provider_id'), + 'collection' => $create->createParameter('collection'), + 'document_id' => $create->createParameter('document_id'), + 'source' => $create->createParameter('source'), + 'err' => $create->createParameter('err'), + 'message' => $create->createParameter('message'), + 'status' => $create->createParameter('status'), + 'options' => $create->createParameter('options'), + 'indexed' => $create->createParameter('indexed') + ] ); while ($row = $oldData->fetch()) { diff --git a/lib/Service/MiscService.php b/lib/Service/MiscService.php index e606f0ca..c0132588 100644 --- a/lib/Service/MiscService.php +++ b/lib/Service/MiscService.php @@ -1,4 +1,5 @@ Application::APP_ID, + 'app' => Application::APP_ID, 'level' => $level ); @@ -70,4 +69,3 @@ public function log(string $message, int $level = 2) { } } - diff --git a/lib/Service/PlatformService.php b/lib/Service/PlatformService.php index 4591f9e9..3ded6ab1 100644 --- a/lib/Service/PlatformService.php +++ b/lib/Service/PlatformService.php @@ -1,4 +1,5 @@ miscService->log('Could not determine if provider with id \'' . $providerId . '\' was properly indexed because the corresponding provider-option could not be found.' - . ' Make sure the initial indexing process has been completed successfully.' - , 0); + . ' Make sure the initial indexing process has been completed successfully.', 0); return false; } diff --git a/lib/Service/RunningService.php b/lib/Service/RunningService.php index 2359a44c..d337ba06 100644 --- a/lib/Service/RunningService.php +++ b/lib/Service/RunningService.php @@ -1,4 +1,5 @@ userId = $userId; - $this->appManager = $appManager; - $this->userManager = $userManager; - $this->groupManager = $groupManager; - $this->configService = $configService; - $this->providerService = $providerService; - $this->platformService = $platformService; - $this->miscService = $miscService; - - $this->setup('app', Application::APP_ID); } diff --git a/lib/Service/SettingsService.php b/lib/Service/SettingsService.php index e6b73538..2efbe18a 100644 --- a/lib/Service/SettingsService.php +++ b/lib/Service/SettingsService.php @@ -1,4 +1,5 @@ $this->completeSettingsPlatforms(), - 'providers_all' => $this->completeSettingsProviders() - ] + 'platforms_all' => $this->completeSettingsPlatforms(), + 'providers_all' => $this->completeSettingsProviders() + ] ); } @@ -105,7 +104,7 @@ private function completeSettingsPlatforms(): array { foreach ($platforms as $wrapper) { $platform = $wrapper->getPlatform(); $list[$wrapper->getClass()] = [ - 'id' => $platform->getId(), + 'id' => $platform->getId(), 'name' => $platform->getName() ]; } diff --git a/lib/Service/TestService.php b/lib/Service/TestService.php index d9179cdf..01d80e9b 100644 --- a/lib/Service/TestService.php +++ b/lib/Service/TestService.php @@ -1,4 +1,5 @@ + * @copyright 2022 + * @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 + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + + +namespace OCA\FullTextSearch\Tools\Db; + +use DateInterval; +use DateTime; +use Doctrine\DBAL\Query\QueryBuilder as DBALQueryBuilder; +use Exception; +use OC\DB\ConnectionAdapter; +use OC\DB\QueryBuilder\QueryBuilder; +use OC\SystemConfig; +use OCA\FullTextSearch\Tools\Exceptions\DateTimeException; +use OCA\FullTextSearch\Tools\Exceptions\InvalidItemException; +use OCA\FullTextSearch\Tools\Exceptions\RowNotFoundException; +use OCA\FullTextSearch\Tools\Traits\TArrayTools; +use OCP\DB\QueryBuilder\ICompositeExpression; +use OCP\DB\QueryBuilder\IQueryBuilder; +use OCP\Server; +use Psr\Log\LoggerInterface; + +class ExtendedQueryBuilder extends QueryBuilder { + use TArrayTools; + + private string $defaultSelectAlias = ''; + private array $defaultValues = []; + + + public function __construct() { + parent::__construct( + Server::get(ConnectionAdapter::class), + Server::get(SystemConfig::class), + Server::get(LoggerInterface::class) + ); + } + + + /** + * @param string $alias + * + * @return self + */ + public function setDefaultSelectAlias(string $alias): self { + $this->defaultSelectAlias = $alias; + + return $this; + } + + /** + * @return string + */ + public function getDefaultSelectAlias(): string { + return $this->defaultSelectAlias; + } + + + /** + * @return array + */ + public function getDefaultValues(): array { + return $this->defaultValues; + } + + /** + * @param string $key + * @param string $value + * + * @return $this + */ + public function addDefaultValue(string $key, string $value): self { + $this->defaultValues[$key] = $value; + + return $this; + } + + /** + * @param int $size + * @param int $page + */ + public function paginate(int $size, int $page = 0): void { + if ($page < 0) { + $page = 0; + } + + $this->chunk($page * $size, $size); + } + + /** + * @param int $offset + * @param int $limit + */ + public function chunk(int $offset, int $limit): void { + if ($offset > -1) { + $this->setFirstResult($offset); + } + + if ($limit > 0) { + $this->setMaxResults($limit); + } + } + + + /** + * Limit the request to the Id + * + * @param int $id + */ + public function limitToId(int $id): void { + $this->limitInt('id', $id); + } + + /** + * @param array $ids + */ + public function limitToIds(array $ids): void { + $this->limitArray('id', $ids); + } + + /** + * @param string $id + */ + public function limitToIdString(string $id): void { + $this->limit('id', $id); + } + + /** + * @param string $userId + */ + public function limitToUserId(string $userId): void { + $this->limit('user_id', $userId); + } + + /** + * @param string $uniqueId + */ + public function limitToUniqueId(string $uniqueId): void { + $this->limit('unique_id', $uniqueId); + } + + /** + * @param string $memberId + */ + public function limitToMemberId(string $memberId): void { + $this->limit('member_id', $memberId); + } + + /** + * @param string $status + */ + public function limitToStatus(string $status): void { + $this->limit('status', $status, '', false); + } + + /** + * @param int $type + */ + public function limitToType(int $type): void { + $this->limitInt('type', $type); + } + + /** + * @param string $type + */ + public function limitToTypeString(string $type): void { + $this->limit('type', $type, '', false); + } + + /** + * @param string $token + */ + public function limitToToken(string $token): void { + $this->limit('token', $token); + } + + + /** + * Limit the request to the creation + * + * @param int $delay + * + * @return self + * @throws Exception + */ + public function limitToCreation(int $delay = 0): self { + $date = new DateTime('now'); + $date->sub(new DateInterval('PT' . $delay . 'M')); + + $this->limitToDBFieldDateTime('creation', $date, true); + + return $this; + } + + + /** + * @param string $field + * @param DateTime $date + * @param bool $orNull + */ + public function limitToDBFieldDateTime(string $field, DateTime $date, bool $orNull = false): void { + $expr = $this->expr(); + $pf = ($this->getType() === DBALQueryBuilder::SELECT) ? $this->getDefaultSelectAlias() + . '.' : ''; + $field = $pf . $field; + + $orX = $expr->orX(); + $orX->add( + $expr->lte($field, $this->createNamedParameter($date, IQueryBuilder::PARAM_DATE)) + ); + + if ($orNull === true) { + $orX->add($expr->isNull($field)); + } + + $this->andWhere($orX); + } + + + /** + * @param int $timestamp + * @param string $field + * + * @throws DateTimeException + */ + public function limitToSince(int $timestamp, string $field): void { + try { + $dTime = new DateTime(); + $dTime->setTimestamp($timestamp); + } catch (Exception $e) { + throw new DateTimeException($e->getMessage()); + } + + $expr = $this->expr(); + $pf = ($this->getType() === DBALQueryBuilder::SELECT) ? $this->getDefaultSelectAlias() . '.' : ''; + $field = $pf . $field; + + $orX = $expr->orX(); + $orX->add( + $expr->gte($field, $this->createNamedParameter($dTime, IQueryBuilder::PARAM_DATE)) + ); + + $this->andWhere($orX); + } + + + /** + * @param string $field + * @param string $value + */ + public function searchInDBField(string $field, string $value): void { + $expr = $this->expr(); + + $pf = ($this->getType() === DBALQueryBuilder::SELECT) ? $this->getDefaultSelectAlias() . '.' : ''; + $field = $pf . $field; + + $this->andWhere($expr->iLike($field, $this->createNamedParameter($value))); + } + + + /** + * @param string $field + * @param string $value + * @param string $alias + * @param bool $cs + */ + public function like(string $field, string $value, string $alias = '', bool $cs = true): void { + $this->andWhere($this->exprLike($field, $value, $alias, $cs)); + } + + + /** + * @param string $field + * @param string $value + * @param string $alias + * @param bool $cs + */ + public function limit(string $field, string $value, string $alias = '', bool $cs = true): void { + $this->andWhere($this->exprLimit($field, $value, $alias, $cs)); + } + + /** + * @param string $field + * @param int $value + * @param string $alias + */ + public function limitInt(string $field, int $value, string $alias = ''): void { + $this->andWhere($this->exprLimitInt($field, $value, $alias)); + } + + /** + * @param string $field + * @param bool $value + * @param string $alias + */ + public function limitBool(string $field, bool $value, string $alias = ''): void { + $this->andWhere($this->exprLimitBool($field, $value, $alias)); + } + + /** + * @param string $field + * @param bool $orNull + * @param string $alias + */ + public function limitEmpty(string $field, bool $orNull = false, string $alias = ''): void { + $this->andWhere($this->exprLimitEmpty($field, $orNull, $alias)); + } + + /** + * @param string $field + * @param bool $orEmpty + * @param string $alias + */ + public function limitNull(string $field, bool $orEmpty = false, string $alias = ''): void { + $this->andWhere($this->exprLimitNull($field, $orEmpty, $alias)); + } + + /** + * @param string $field + * @param array $value + * @param string $alias + * @param bool $cs + */ + public function limitArray(string $field, array $value, string $alias = '', bool $cs = true): void { + $this->andWhere($this->exprLimitArray($field, $value, $alias, $cs)); + } + + /** + * @param string $field + * @param array $value + * @param string $alias + */ + public function limitInArray(string $field, array $value, string $alias = ''): void { + $this->andWhere($this->exprLimitInArray($field, $value, $alias)); + } + + /** + * @param string $field + * @param int $flag + * @param string $alias + */ + public function limitBitwise(string $field, int $flag, string $alias = ''): void { + $this->andWhere($this->exprLimitBitwise($field, $flag, $alias)); + } + + /** + * @param string $field + * @param int $value + * @param bool $gte + * @param string $alias + */ + public function gt(string $field, int $value, bool $gte = false, string $alias = ''): void { + $this->andWhere($this->exprGt($field, $value, $gte, $alias)); + } + + /** + * @param string $field + * @param int $value + * @param bool $lte + * @param string $alias + */ + public function lt(string $field, int $value, bool $lte = false, string $alias = ''): void { + $this->andWhere($this->exprLt($field, $value, $lte, $alias)); + } + + + /** + * @param string $field + * @param string $value + * @param string $alias + * @param bool $cs + * + * @return string + */ + public function exprLike(string $field, string $value, string $alias = '', bool $cs = true): string { + if ($this->getType() === DBALQueryBuilder::SELECT) { + $field = (($alias === '') ? $this->getDefaultSelectAlias() : $alias) . '.' . $field; + } + + $expr = $this->expr(); + if ($cs) { + return $expr->like($field, $this->createNamedParameter($value)); + } else { + return $expr->iLike($field, $this->createNamedParameter($value)); + } + } + + public function exprLimit(string $field, string $value, string $alias = '', bool $cs = true): string { + if ($this->getType() === DBALQueryBuilder::SELECT) { + $field = (($alias === '') ? $this->getDefaultSelectAlias() : $alias) . '.' . $field; + } + + $expr = $this->expr(); + if ($value === '') { + return $expr->emptyString($field); + } + if ($cs) { + return $expr->eq($field, $this->createNamedParameter($value)); + } else { + $func = $this->func(); + + return $expr->eq($func->lower($field), $func->lower($this->createNamedParameter($value))); + } + } + + public function exprLimitInt(string $field, int $value, string $alias = ''): string { + if ($this->getType() === DBALQueryBuilder::SELECT) { + $field = (($alias === '') ? $this->getDefaultSelectAlias() : $alias) . '.' . $field; + } + + $expr = $this->expr(); + + return $expr->eq($field, $this->createNamedParameter($value, IQueryBuilder::PARAM_INT)); + } + + + /** + * @param string $field + * @param bool $value + * @param string $alias + * + * @return string + */ + public function exprLimitBool(string $field, bool $value, string $alias = ''): string { + if ($this->getType() === DBALQueryBuilder::SELECT) { + $field = (($alias === '') ? $this->getDefaultSelectAlias() : $alias) . '.' . $field; + } + + $expr = $this->expr(); + + return $expr->eq($field, $this->createNamedParameter($value, IQueryBuilder::PARAM_BOOL)); + } + + /** + * @param string $field + * @param bool $orNull + * @param string $alias + * + * @return ICompositeExpression + */ + public function exprLimitEmpty( + string $field, + bool $orNull = false, + string $alias = '' + ): ICompositeExpression { + if ($this->getType() === DBALQueryBuilder::SELECT) { + $field = (($alias === '') ? $this->getDefaultSelectAlias() : $alias) . '.' . $field; + } + + $expr = $this->expr(); + $orX = $expr->orX(); + $orX->add($expr->emptyString($field)); + if ($orNull) { + $orX->add($expr->isNull($field)); + } + + return $orX; + } + + /** + * @param string $field + * @param bool $orEmpty + * @param string $alias + * + * @return ICompositeExpression + */ + public function exprLimitNull( + string $field, + bool $orEmpty = false, + string $alias = '' + ): ICompositeExpression { + if ($this->getType() === DBALQueryBuilder::SELECT) { + $field = (($alias === '') ? $this->getDefaultSelectAlias() : $alias) . '.' . $field; + } + + $expr = $this->expr(); + $orX = $expr->orX(); + $orX->add($expr->isNull($field)); + if ($orEmpty) { + $orX->add($expr->emptyString($field)); + } + + return $orX; + } + + + /** + * @param string $field + * @param array $values + * @param string $alias + * @param bool $cs + * + * @return ICompositeExpression + */ + public function exprLimitArray( + string $field, + array $values, + string $alias = '', + bool $cs = true + ): ICompositeExpression { + if ($this->getType() === DBALQueryBuilder::SELECT) { + $field = (($alias === '') ? $this->getDefaultSelectAlias() : $alias) . '.' . $field; + } + + $andX = $this->expr()->andX(); + foreach ($values as $value) { + if (is_integer($value)) { + $andX->add($this->exprLimitInt($field, $value, $alias)); + } else { + $andX->add($this->exprLimit($field, $value, $alias, $cs)); + } + } + + return $andX; + } + + + /** + * @param string $field + * @param array $values + * @param string $alias + * + * @return string + */ + public function exprLimitInArray(string $field, array $values, string $alias = ''): string { + if ($this->getType() === DBALQueryBuilder::SELECT) { + $field = (($alias === '') ? $this->getDefaultSelectAlias() : $alias) . '.' . $field; + } + + $expr = $this->expr(); + + return $expr->in( + $field, $this->createNamedParameter($values, IQueryBuilder::PARAM_STR_ARRAY) + ); + } + + + /** + * @param string $field + * @param int $flag + * @param string $alias + * + * @return string + */ + public function exprLimitBitwise(string $field, int $flag, string $alias = ''): string { + if ($this->getType() === DBALQueryBuilder::SELECT) { + $field = (($alias === '') ? $this->getDefaultSelectAlias() : $alias) . '.' . $field; + } + + $expr = $this->expr(); + + return $expr->gt( + $expr->bitwiseAnd($field, $flag), + $this->createNamedParameter(0, IQueryBuilder::PARAM_INT) + ); + } + + + /** + * @param string $field + * @param int $value + * @param bool $lte + * @param string $alias + * + * @return string + */ + public function exprLt(string $field, int $value, bool $lte = false, string $alias = ''): string { + if ($this->getType() === DBALQueryBuilder::SELECT) { + $field = (($alias === '') ? $this->getDefaultSelectAlias() : $alias) . '.' . $field; + } + + $expr = $this->expr(); + + if ($lte) { + return $expr->lte($field, $this->createNamedParameter($value, IQueryBuilder::PARAM_INT)); + } else { + return $expr->lt($field, $this->createNamedParameter($value, IQueryBuilder::PARAM_INT)); + } + } + + /** + * @param string $field + * @param int $value + * @param bool $gte + * @param string $alias + * + * @return string + */ + public function exprGt(string $field, int $value, bool $gte = false, string $alias = ''): string { + if ($this->getType() === DBALQueryBuilder::SELECT) { + $field = (($alias === '') ? $this->getDefaultSelectAlias() : $alias) . '.' . $field; + } + + $expr = $this->expr(); + + if ($gte) { + return $expr->gte($field, $this->createNamedParameter($value, IQueryBuilder::PARAM_INT)); + } else { + return $expr->gt($field, $this->createNamedParameter($value, IQueryBuilder::PARAM_INT)); + } + } + + + /** + * @param string $field + * @param string $value + * @param string $alias + * @param bool $cs + */ + public function unlike(string $field, string $value, string $alias = '', bool $cs = true): void { + $this->andWhere($this->exprUnlike($field, $value, $alias, $cs)); + } + + + /** + * @param string $field + * @param string $value + * @param string $alias + * @param bool $cs + */ + public function filter(string $field, string $value, string $alias = '', bool $cs = true): void { + $this->andWhere($this->exprFilter($field, $value, $alias, $cs)); + } + + /** + * @param string $field + * @param int $value + * @param string $alias + */ + public function filterInt(string $field, int $value, string $alias = ''): void { + $this->andWhere($this->exprFilterInt($field, $value, $alias)); + } + + /** + * @param string $field + * @param bool $value + * @param string $alias + */ + public function filterBool(string $field, bool $value, string $alias = ''): void { + $this->andWhere($this->exprFilterBool($field, $value, $alias)); + } + + /** + * @param string $field + * @param bool $norNull + * @param string $alias + */ + public function filterEmpty(string $field, bool $norNull = false, string $alias = ''): void { + $this->andWhere($this->exprFilterEmpty($field, $norNull, $alias)); + } + + /** + * @param string $field + * @param bool $norEmpty + * @param string $alias + */ + public function filterNull(string $field, bool $norEmpty = false, string $alias = ''): void { + $this->andWhere($this->exprFilterNull($field, $norEmpty, $alias)); + } + + /** + * @param string $field + * @param array $value + * @param string $alias + * @param bool $cs + */ + public function filterArray(string $field, array $value, string $alias = '', bool $cs = true): void { + $this->andWhere($this->exprFilterArray($field, $value, $alias, $cs)); + } + + /** + * @param string $field + * @param array $value + * @param string $alias + */ + public function filterInArray(string $field, array $value, string $alias = ''): void { + $this->andWhere($this->exprFilterInArray($field, $value, $alias)); + } + + /** + * @param string $field + * @param int $flag + * @param string $alias + */ + public function filterBitwise(string $field, int $flag, string $alias = ''): void { + $this->andWhere($this->exprFilterBitwise($field, $flag, $alias)); + } + + + /** + * @param string $field + * @param string $value + * @param string $alias + * @param bool $cs + * + * @return string + */ + public function exprUnlike(string $field, string $value, string $alias = '', bool $cs = true): string { + if ($this->getType() === DBALQueryBuilder::SELECT) { + $field = (($alias === '') ? $this->getDefaultSelectAlias() : $alias) . '.' . $field; + } + + $expr = $this->expr(); + if ($cs) { + return $expr->notLike($field, $this->createNamedParameter($value)); + } else { + $func = $this->func(); + + return $expr->notLike($func->lower($field), $func->lower($this->createNamedParameter($value))); + } + } + + + /** + * @param string $field + * @param string $value + * @param string $alias + * @param bool $cs + * + * @return string + */ + public function exprFilter(string $field, string $value, string $alias = '', bool $cs = true): string { + if ($this->getType() === DBALQueryBuilder::SELECT) { + $field = (($alias === '') ? $this->getDefaultSelectAlias() : $alias) . '.' . $field; + } + + $expr = $this->expr(); + if ($value === '') { + return $expr->nonEmptyString($field); + } + if ($cs) { + return $expr->neq($field, $this->createNamedParameter($value)); + } else { + $func = $this->func(); + + return $expr->neq($func->lower($field), $func->lower($this->createNamedParameter($value))); + } + } + + + /** + * @param string $field + * @param int $value + * @param string $alias + * + * @return string + */ + public function exprFilterInt(string $field, int $value, string $alias = ''): string { + if ($this->getType() === DBALQueryBuilder::SELECT) { + $field = (($alias === '') ? $this->getDefaultSelectAlias() : $alias) . '.' . $field; + } + + $expr = $this->expr(); + + return $expr->neq($field, $this->createNamedParameter($value, IQueryBuilder::PARAM_INT)); + } + + + /** + * @param string $field + * @param bool $value + * @param string $alias + * + * @return string + */ + public function exprFilterBool(string $field, bool $value, string $alias = ''): string { + if ($this->getType() === DBALQueryBuilder::SELECT) { + $field = (($alias === '') ? $this->getDefaultSelectAlias() : $alias) . '.' . $field; + } + + $expr = $this->expr(); + + return $expr->neq($field, $this->createNamedParameter($value, IQueryBuilder::PARAM_BOOL)); + } + + /** + * @param string $field + * @param bool $norNull + * @param string $alias + * + * @return ICompositeExpression + */ + public function exprFilterEmpty( + string $field, + bool $norNull = false, + string $alias = '' + ): ICompositeExpression { + if ($this->getType() === DBALQueryBuilder::SELECT) { + $field = (($alias === '') ? $this->getDefaultSelectAlias() : $alias) . '.' . $field; + } + + $expr = $this->expr(); + $andX = $expr->andX(); + $andX->add($expr->nonEmptyString($field)); + if ($norNull) { + $andX->add($expr->isNotNull($field)); + } + + return $andX; + } + + /** + * @param string $field + * @param bool $norEmpty + * @param string $alias + * + * @return ICompositeExpression + */ + public function exprFilterNull( + string $field, + bool $norEmpty = false, + string $alias = '' + ): ICompositeExpression { + if ($this->getType() === DBALQueryBuilder::SELECT) { + $field = (($alias === '') ? $this->getDefaultSelectAlias() : $alias) . '.' . $field; + } + + $expr = $this->expr(); + $andX = $expr->andX(); + $andX->add($expr->isNotNull($field)); + if ($norEmpty) { + $andX->add($expr->nonEmptyString($field)); + } + + return $andX; + } + + + /** + * @param string $field + * @param array $values + * @param string $alias + * @param bool $cs + * + * @return ICompositeExpression + */ + public function exprFilterArray( + string $field, + array $values, + string $alias = '', + bool $cs = true + ): ICompositeExpression { + if ($this->getType() === DBALQueryBuilder::SELECT) { + $field = (($alias === '') ? $this->getDefaultSelectAlias() : $alias) . '.' . $field; + } + + $orX = $this->expr()->orX(); + foreach ($values as $value) { + if (is_integer($value)) { + $orX->add($this->exprFilterInt($field, $value, $alias)); + } else { + $orX->add($this->exprFilter($field, $value, $alias, $cs)); + } + } + + return $orX; + } + + + /** + * @param string $field + * @param array $values + * @param string $alias + * + * @return string + */ + public function exprFilterInArray(string $field, array $values, string $alias = ''): string { + if ($this->getType() === DBALQueryBuilder::SELECT) { + $field = (($alias === '') ? $this->getDefaultSelectAlias() : $alias) . '.' . $field; + } + + $expr = $this->expr(); + + return $expr->notIn($field, $this->createNamedParameter($values, IQueryBuilder::PARAM_STR_ARRAY)); + } + + + /** + * @param string $field + * @param int $flag + * @param string $alias + * + * @return string + */ + public function exprFilterBitwise(string $field, int $flag, string $alias = ''): string { + if ($this->getType() === DBALQueryBuilder::SELECT) { + $field = (($alias === '') ? $this->getDefaultSelectAlias() : $alias) . '.' . $field; + } + + $expr = $this->expr(); + + return $expr->eq( + $expr->bitwiseAnd($field, $flag), + $this->createNamedParameter(0, IQueryBuilder::PARAM_INT) + ); + } + + + /** + * @param string $object + * @param array $params + * + * @return IQueryRow + * @throws RowNotFoundException + * @throws InvalidItemException + */ + public function asItem(string $object, array $params = []): IQueryRow { + return $this->getRow([$this, 'parseSimpleSelectSql'], $object, $params); + } + + /** + * @param string $object + * @param array $params + * + * @return IQueryRow[] + */ + public function asItems(string $object, array $params = []): array { + return $this->getRows([$this, 'parseSimpleSelectSql'], $object, $params); + } + + + /** + * @param string $field + * @param array $params + * + * @return IQueryRow + * @throws InvalidItemException + * @throws RowNotFoundException + */ + public function asItemFromField(string $field, array $params = []): IQueryRow { + $param['modelFromField'] = $field; + + return $this->getRow([$this, 'parseSimpleSelectSql'], '', $params); + } + + /** + * @param string $field + * @param array $params + * + * @return IQueryRow[] + */ + public function asItemsFromField(string $field, array $params = []): array { + $param['modelFromField'] = $field; + + return $this->getRows([$this, 'parseSimpleSelectSql'], $field, $params); + } + + + /** + * @param array $data + * @param ExtendedQueryBuilder $qb + * @param string $object + * @param array $params + * + * @return IQueryRow + * @throws InvalidItemException + */ + private function parseSimpleSelectSql( + array $data, + ExtendedQueryBuilder $qb, + string $object, + array $params + ): IQueryRow { + $fromField = $this->get('modelFromField', $params); + if ($fromField !== '') { + $object = $fromField; + } + + $item = new $object(); + if (!($item instanceof IQueryRow)) { + throw new InvalidItemException(); + } + + if (!empty($params)) { + $data['_params'] = $params; + } + + foreach ($qb->getDefaultValues() as $k => $v) { + if ($this->get($k, $data) === '') { + $data[$k] = $v; + } + } + + $data = array_merge($qb->getDefaultValues(), $data); + + $item->importFromDatabase($data); + + return $item; + } + + + /** + * @param callable $method + * @param string $object + * @param array $params + * + * @return IQueryRow + * @throws RowNotFoundException + */ + public function getRow(callable $method, string $object = '', array $params = []): IQueryRow { + $cursor = $this->execute(); + $data = $cursor->fetch(); + $cursor->closeCursor(); + + if ($data === false) { + throw new RowNotFoundException(); + } + + return $method($data, $this, $object, $params); + } + + + /** + * @param callable $method + * @param string $object + * @param array $params + * + * @return IQueryRow[] + */ + public function getRows(callable $method, string $object = '', array $params = []): array { + $rows = []; + $cursor = $this->execute(); + while ($data = $cursor->fetch()) { + try { + $rows[] = $method($data, $this, $object, $params); + } catch (Exception $e) { + } + } + $cursor->closeCursor(); + + return $rows; + } + + + /** + * @param string $table + * @param array $fields + * @param string $alias + * + * @return $this + */ + public function generateSelect( + string $table, + array $fields, + string $alias = '' + ): self { + if ($alias === '') { + $alias = $table; + } + + $selectFields = array_map( + function (string $item) use ($alias) { + return $alias . '.' . $item; + }, $fields + ); + + $this->select($selectFields) + ->from($table, $alias) + ->setDefaultSelectAlias($alias); + + return $this; + } + + + /** + * @param array $fields + * @param string $alias + * @param string $prefix + * @param array $default + * + * @return $this + */ + public function generateSelectAlias( + array $fields, + string $alias, + string $prefix, + array $default = [] + ): self { + $prefix = trim($prefix) . '_'; + foreach ($default as $k => $v) { + $this->addDefaultValue($prefix . $k, (string)$v); + } + + foreach ($fields as $field) { + $this->selectAlias($alias . '.' . $field, $prefix . $field); + } + + return $this; + } +} diff --git a/lib/Tools/Db/IQueryRow.php b/lib/Tools/Db/IQueryRow.php new file mode 100644 index 00000000..b10fa7fa --- /dev/null +++ b/lib/Tools/Db/IQueryRow.php @@ -0,0 +1,48 @@ + + * @copyright 2022 + * @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 + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + + +namespace OCA\FullTextSearch\Tools\Db; + +/** + * Interface IQueryRow + * + * @package OCA\FullTextSearch\Tools\Db + */ +interface IQueryRow { + /** + * import data to feed the model. + * + * @param array $data + * + * @return IQueryRow + */ + public function importFromDatabase(array $data): self; +} diff --git a/lib/Tools/Exceptions/ArrayNotFoundException.php b/lib/Tools/Exceptions/ArrayNotFoundException.php new file mode 100644 index 00000000..a1c7143c --- /dev/null +++ b/lib/Tools/Exceptions/ArrayNotFoundException.php @@ -0,0 +1,42 @@ + + * @copyright 2022 + * @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 + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + + +namespace OCA\FullTextSearch\Tools\Exceptions; + +use Exception; + +/** + * Class ArrayNotFoundException + * + * @package OCA\FullTextSearch\Tools\Exceptions + */ +class ArrayNotFoundException extends Exception { +} diff --git a/lib/Tools/Exceptions/DateTimeException.php b/lib/Tools/Exceptions/DateTimeException.php new file mode 100644 index 00000000..63a5b5d8 --- /dev/null +++ b/lib/Tools/Exceptions/DateTimeException.php @@ -0,0 +1,42 @@ + + * @copyright 2022 + * @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 + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + + +namespace OCA\FullTextSearch\Tools\Exceptions; + +use Exception; + +/** + * Class DateTimeException + * + * @package OCA\FullTextSearch\Tools\Exceptions + */ +class DateTimeException extends Exception { +} diff --git a/lib/Tools/Exceptions/InvalidItemException.php b/lib/Tools/Exceptions/InvalidItemException.php new file mode 100644 index 00000000..a1341c74 --- /dev/null +++ b/lib/Tools/Exceptions/InvalidItemException.php @@ -0,0 +1,42 @@ + + * @copyright 2022 + * @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 + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + + +namespace OCA\FullTextSearch\Tools\Exceptions; + +use Exception; + +/** + * Class InvalidItemException + * + * @package OCA\FullTextSearch\Tools\Exceptions + */ +class InvalidItemException extends Exception { +} diff --git a/lib/Tools/Exceptions/ItemNotFoundException.php b/lib/Tools/Exceptions/ItemNotFoundException.php new file mode 100644 index 00000000..15749793 --- /dev/null +++ b/lib/Tools/Exceptions/ItemNotFoundException.php @@ -0,0 +1,42 @@ + + * @copyright 2022 + * @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 + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + + +namespace OCA\FullTextSearch\Tools\Exceptions; + +use Exception; + +/** + * Class ItemNotFoundException + * + * @package OCA\FullTextSearch\Tools\Exceptions + */ +class ItemNotFoundException extends Exception { +} diff --git a/lib/Tools/Exceptions/MalformedArrayException.php b/lib/Tools/Exceptions/MalformedArrayException.php new file mode 100644 index 00000000..324edbf9 --- /dev/null +++ b/lib/Tools/Exceptions/MalformedArrayException.php @@ -0,0 +1,42 @@ + + * @copyright 2022 + * @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 + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + + +namespace OCA\FullTextSearch\Tools\Exceptions; + +use Exception; + +/** + * Class MalformedArrayException + * + * @package OCA\FullTextSearch\Tools\Exceptions + */ +class MalformedArrayException extends Exception { +} diff --git a/lib/Tools/Exceptions/RowNotFoundException.php b/lib/Tools/Exceptions/RowNotFoundException.php new file mode 100644 index 00000000..4ffb2dce --- /dev/null +++ b/lib/Tools/Exceptions/RowNotFoundException.php @@ -0,0 +1,42 @@ + + * @copyright 2022 + * @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 + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + + +namespace OCA\FullTextSearch\Tools\Exceptions; + +use Exception; + +/** + * Class RowNotFoundException + * + * @package OCA\FullTextSearch\Tools\Exceptions + */ +class RowNotFoundException extends Exception { +} diff --git a/lib/Tools/Exceptions/UnknownTypeException.php b/lib/Tools/Exceptions/UnknownTypeException.php new file mode 100644 index 00000000..4c08f6a6 --- /dev/null +++ b/lib/Tools/Exceptions/UnknownTypeException.php @@ -0,0 +1,42 @@ + + * @copyright 2022 + * @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 + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + + +namespace OCA\FullTextSearch\Tools\Exceptions; + +use Exception; + +/** + * Class UnknownTypeException + * + * @package OCA\FullTextSearch\Tools\Exceptions + */ +class UnknownTypeException extends Exception { +} diff --git a/lib/Tools/IDeserializable.php b/lib/Tools/IDeserializable.php new file mode 100644 index 00000000..deb4b1ae --- /dev/null +++ b/lib/Tools/IDeserializable.php @@ -0,0 +1,41 @@ + + * @copyright 2022 + * @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 + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + + +namespace OCA\FullTextSearch\Tools; + +interface IDeserializable { + /** + * @param array $data + * + * @return self + */ + public function import(array $data): self; +} diff --git a/lib/Tools/Traits/TArrayTools.php b/lib/Tools/Traits/TArrayTools.php new file mode 100644 index 00000000..7ab29b89 --- /dev/null +++ b/lib/Tools/Traits/TArrayTools.php @@ -0,0 +1,432 @@ + + * @copyright 2022 + * @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 + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + + +namespace OCA\FullTextSearch\Tools\Traits; + +use Exception; +use JsonSerializable; +use OCA\FullTextSearch\Tools\Exceptions\ArrayNotFoundException; +use OCA\FullTextSearch\Tools\Exceptions\ItemNotFoundException; +use OCA\FullTextSearch\Tools\Exceptions\MalformedArrayException; +use OCA\FullTextSearch\Tools\Exceptions\UnknownTypeException; + +trait TArrayTools { + public static $TYPE_NULL = 'Null'; + public static $TYPE_STRING = 'String'; + public static $TYPE_ARRAY = 'Array'; + public static $TYPE_BOOLEAN = 'Boolean'; + public static $TYPE_INTEGER = 'Integer'; + public static $TYPE_SERIALIZABLE = 'Serializable'; + + + /** + * @param string $k + * @param array $arr + * @param string $default + * + * @return string + */ + protected function get(string $k, array $arr, string $default = ''): string { + if (!array_key_exists($k, $arr)) { + $subs = explode('.', $k, 2); + if (sizeof($subs) > 1) { + if (!array_key_exists($subs[0], $arr)) { + return $default; + } + + $r = $arr[$subs[0]]; + if (!is_array($r)) { + return $default; + } + + return $this->get($subs[1], $r, $default); + } else { + return $default; + } + } + + if ($arr[$k] === null || !is_string($arr[$k]) && (!is_int($arr[$k]))) { + return $default; + } + + return (string)$arr[$k]; + } + + + /** + * @param string $k + * @param array $arr + * @param int $default + * + * @return int + */ + protected function getInt(string $k, array $arr, int $default = 0): int { + if (!array_key_exists($k, $arr)) { + $subs = explode('.', $k, 2); + if (sizeof($subs) > 1) { + if (!array_key_exists($subs[0], $arr)) { + return $default; + } + + $r = $arr[$subs[0]]; + if (!is_array($r)) { + return $default; + } + + return $this->getInt($subs[1], $r, $default); + } else { + return $default; + } + } + + if ($arr[$k] === null) { + return $default; + } + + return intval($arr[$k]); + } + + + /** + * @param string $k + * @param array $arr + * @param float $default + * + * @return float + */ + protected function getFloat(string $k, array $arr, float $default = 0): float { + if (!array_key_exists($k, $arr)) { + $subs = explode('.', $k, 2); + if (sizeof($subs) > 1) { + if (!array_key_exists($subs[0], $arr)) { + return $default; + } + + $r = $arr[$subs[0]]; + if (!is_array($r)) { + return $default; + } + + return $this->getFloat($subs[1], $r, $default); + } else { + return $default; + } + } + + if ($arr[$k] === null) { + return $default; + } + + return intval($arr[$k]); + } + + + /** + * @param string $k + * @param array $arr + * @param bool $default + * + * @return bool + */ + protected function getBool(string $k, array $arr, bool $default = false): bool { + if (!array_key_exists($k, $arr)) { + $subs = explode('.', $k, 2); + if (sizeof($subs) > 1) { + if (!array_key_exists($subs[0], $arr)) { + return $default; + } + + return $this->getBool($subs[1], $arr[$subs[0]], $default); + } else { + return $default; + } + } + + if ($arr[$k] === null) { + return $default; + } + + if (is_bool($arr[$k])) { + return $arr[$k]; + } + + $sk = (string)$arr[$k]; + if ($sk === '1' || strtolower($sk) === 'true') { + return true; + } + + if ($sk === '0' || strtolower($sk) === 'false') { + return false; + } + + return $default; + } + + + /** + * @param string $k + * @param array $arr + * @param JsonSerializable|null $default + * + * @return mixed + */ + protected function getObj(string $k, array $arr, ?JsonSerializable $default = null): ?JsonSerializable { + if (!array_key_exists($k, $arr)) { + $subs = explode('.', $k, 2); + if (sizeof($subs) > 1) { + if (!array_key_exists($subs[0], $arr)) { + return $default; + } + + return $this->getObj($subs[1], $arr[$subs[0]], $default); + } else { + return $default; + } + } + + return $arr[$k]; + } + + + /** + * @param string $k + * @param array $arr + * @param array $default + * + * @return array + */ + protected function getArray(string $k, array $arr, array $default = []): array { + if (!array_key_exists($k, $arr)) { + $subs = explode('.', $k, 2); + if (sizeof($subs) > 1) { + if (!array_key_exists($subs[0], $arr)) { + return $default; + } + + $r = $arr[$subs[0]]; + if (!is_array($r)) { + return $default; + } + + return $this->getArray($subs[1], $r, $default); + } else { + return $default; + } + } + + $r = $arr[$k]; + if (!is_array($r) && !is_string($r)) { + return $default; + } + + if (is_string($r)) { + $r = json_decode($r, true); + } + + if (!is_array($r)) { + return $default; + } + + return $r; + } + + + /** + * @param string $k + * @param array $arr + * + * @return bool + */ + public function validKey(string $k, array $arr): bool { + if (array_key_exists($k, $arr)) { + return true; + } + + $subs = explode('.', $k, 2); + if (sizeof($subs) > 1) { + if (!array_key_exists($subs[0], $arr)) { + return false; + } + + $r = $arr[$subs[0]]; + if (!is_array($r)) { + return false; + } + + return $this->validKey($subs[1], $r); + } + + return false; + } + + + /** + * @param string $k + * @param array $arr + * @param array $import + * @param array $default + * + * @return array + */ + protected function getList(string $k, array $arr, array $import, array $default = []): array { + $list = $this->getArray($k, $arr, $default); + + $r = []; + [$obj, $method] = $import; + foreach ($list as $item) { + try { + $o = new $obj(); + $o->$method($item); + + $r[] = $o; + } catch (Exception $e) { + } + } + + return $r; + } + + + /** + * @param string $k + * @param string $value + * @param array $list + * + * @return mixed + * @throws ArrayNotFoundException + */ + protected function extractArray(string $k, string $value, array $list) { + foreach ($list as $arr) { + if (!array_key_exists($k, $arr)) { + continue; + } + + if ($arr[$k] === $value) { + return $arr; + } + } + + throw new ArrayNotFoundException(); + } + + + /** + * @param string $key + * @param array $arr + * @param bool $root + * + * @return string + * @throws ItemNotFoundException + * @throws UnknownTypeException + */ + public function typeOf(string $key, array $arr, bool $root = true): string { + if (array_key_exists($key, $arr)) { + $item = $arr[$key]; + + if (is_null($item)) { + return self::$TYPE_NULL; + } + + if (is_string($item)) { + return self::$TYPE_STRING; + } + + if (is_array($item)) { + return self::$TYPE_ARRAY; + } + + if (is_bool($item)) { + return self::$TYPE_BOOLEAN; + } + + if (is_int($item)) { + return self::$TYPE_INTEGER; + } + + if ($item instanceof JsonSerializable) { + return self::$TYPE_SERIALIZABLE; + } + + throw new UnknownTypeException(); + } + + $subs = explode('.', $key, 2); + if (sizeof($subs) > 1) { + if (!array_key_exists($subs[0], $arr)) { + throw new ItemNotFoundException(); + } + + $r = $arr[$subs[0]]; + if (is_array($r)) { + return $this->typeOf($subs[1], $r); + } + } + + throw new ItemNotFoundException(); + } + + + /** + * @param array $keys + * @param array $arr + * + * @throws MalformedArrayException + */ + protected function mustContains(array $keys, array $arr): void { + foreach ($keys as $key) { + if (!array_key_exists($key, $arr)) { + throw new MalformedArrayException( + 'source: ' . json_encode($arr) . ' - missing key: ' . $key + ); + } + } + } + + + /** + * @param array $arr + */ + protected function cleanArray(array &$arr): void { + $arr = array_filter( + $arr, + function ($v) { + if (is_string($v)) { + return ($v !== ''); + } + if (is_array($v)) { + return !empty($v); + } + + return true; + } + ); + } +} diff --git a/lib/Tools/Traits/TDeserialize.php b/lib/Tools/Traits/TDeserialize.php new file mode 100644 index 00000000..dc2ac914 --- /dev/null +++ b/lib/Tools/Traits/TDeserialize.php @@ -0,0 +1,159 @@ + + * @copyright 2022 + * @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 + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + + +namespace OCA\FullTextSearch\Tools\Traits; + +use Exception; +use JsonSerializable; +use OCA\FullTextSearch\Tools\Exceptions\InvalidItemException; +use OCA\FullTextSearch\Tools\IDeserializable; +use ReflectionClass; + +trait TDeserialize { + /** + * @param JsonSerializable $model + * + * @return array + */ + public function serialize(JsonSerializable $model): array { + return json_decode(json_encode($model), true); + } + + /** + * @param array $data + * + * @return array + */ + public function serializeArray(array $data): array { + return json_decode(json_encode($data), true); + } + + + /** + * @param array $data + * @param string $class + * + * @return IDeserializable + * @throws InvalidItemException + */ + public function deserialize(array $data, string $class): IDeserializable { + try { + $test = new ReflectionClass($class); + } catch (\ReflectionException $e) { + throw new InvalidItemException('cannot ReflectionClass ' . $class); + } + + if (!in_array(IDeserializable::class, $test->getInterfaceNames())) { + throw new InvalidItemException($class . ' does not implement IDeserializable'); + } + + /** @var IDeserializable $item */ + $item = new $class; + $item->import($data); + + return $item; + } + + + /** + * force deserialize without checking for implementation of IDeserializable. + * quickest solution to deserialize model from other apps. + * + * @param string $json + * @param string $class + * + * @return array + */ + public function forceDeserializeArrayFromJson(string $json, string $class): array { + $data = json_decode($json, true); + if (!is_array($data)) { + return []; + } + + $arr = []; + foreach ($data as $entry) { + try { + $item = new $class; + $arr[] = $item->import($entry); + } catch (Exception $e) { + } + } + + return $arr; + } + + /** + * @param string $json + * @param string $class + * + * @return IDeserializable[] + */ + public function deserializeArrayFromJson(string $json, string $class): array { + $data = json_decode($json, true); + if (!is_array($data)) { + return []; + } + + return $this->deserializeArray($data, $class); + } + + /** + * @param array $data + * @param string $class + * + * @return array + */ + public function deserializeArray(array $data, string $class): array { + $arr = []; + foreach ($data as $entry) { + try { + $arr[] = $this->deserialize($entry, $class); + } catch (InvalidItemException $e) { + } + } + + return $arr; + } + + + /** + * @param string $json + * @param string $class + * + * @return IDeserializable + * @throws InvalidItemException + */ + public function deserializeJson(string $json, string $class): IDeserializable { + $data = json_decode($json, true); + + return $this->deserialize($data, $class); + } +} diff --git a/lib/Tools/Traits/TStringTools.php b/lib/Tools/Traits/TStringTools.php new file mode 100644 index 00000000..a0f83272 --- /dev/null +++ b/lib/Tools/Traits/TStringTools.php @@ -0,0 +1,258 @@ + + * @copyright 2022 + * @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 + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + + +namespace OCA\FullTextSearch\Tools\Traits; + +use DateTime; +use Exception; + +trait TStringTools { + use TArrayTools; + + + /** + * @param int $length + * + * @return string + */ + protected function token(int $length = 15): string { + $chars = 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890'; + + $str = ''; + $max = strlen($chars); + for ($i = 0; $i < $length; $i++) { + try { + $str .= $chars[random_int(0, $max - 2)]; + } catch (Exception $e) { + } + } + + return $str; + } + + + /** + * Generate uuid: 2b5a7a87-8db1-445f-a17b-405790f91c80 + * + * @param int $length + * + * @return string + */ + protected function uuid(int $length = 0): string { + $uuid = sprintf( + '%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), mt_rand(0, 0xffff), + mt_rand(0, 0xffff), mt_rand(0, 0xfff) | 0x4000, mt_rand(0, 0x3fff) | 0x8000, + mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff) + ); + + if ($length > 0) { + if ($length <= 16) { + $uuid = str_replace('-', '', $uuid); + } + + $uuid = substr($uuid, 0, $length); + } + + return $uuid; + } + + + /** + * @param string $line + * @param int $length + * + * @return string + */ + protected function cut(string $line, int $length): string { + if (strlen($line) < $length) { + return $line; + } + + return substr($line, 0, $length - 5) . ' (..)'; + } + + /** + * @param string $str1 + * @param string $str2 + * @param bool $cs case sensitive ? + * + * @return string + */ + protected function commonPart(string $str1, string $str2, bool $cs = true): string { + for ($i = 0; $i < strlen($str1) && $i < strlen($str2); $i++) { + $chr1 = $str1[$i]; + $chr2 = $str2[$i]; + + if (!$cs) { + $chr1 = strtolower($chr1); + $chr2 = strtolower($chr2); + } + + if ($chr1 !== $chr2) { + break; + } + } + + return substr($str1, 0, $i); + } + + + /** + * @param string $line + * @param array $params + * + * @return string + */ + protected function feedStringWithParams(string $line, array $params): string { + $ak = array_keys($params); + foreach ($ak as $k) { + $line = str_replace('{' . $k . '}', (string)$params[$k], $line); + } + + return $line; + } + + + /** + * @param int $words + * + * @return string + */ + public function generateRandomSentence(int $words = 5): string { + $sentence = []; + for ($i = 0; $i < $words; $i++) { + $sentence[] = $this->generateRandomWord(rand(2, 12)); + } + + return implode(' ', $sentence); + } + + + /** + * @param int $length + * + * @return string + */ + public function generateRandomWord(int $length = 8): string { + $c = ['b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'r', 's', 't', 'v']; + $v = ['a', 'e', 'i', 'o', 'u', 'y']; + + $word = []; + for ($i = 0; $i <= ($length / 2); $i++) { + $word[] = $c[array_rand($c)]; + $word[] = $v[array_rand($v)]; + } + + return implode('', $word); + } + + + /** + * @param int $bytes + * + * @return string + */ + public function humanReadable(int $bytes): string { + if ($bytes == 0) { + return '0.00 B'; + } + + $s = ['B', 'KB', 'MB', 'GB', 'TB', 'PB']; + $e = floor(log($bytes, 1024)); + + return round($bytes / pow(1024, $e), 2) . ' ' . $s[$e]; + } + + + /** + * @param int $first + * @param int $second + * @param bool $short + * + * @return string + * @throws Exception + */ + public function getDateDiff( + int $first, + int $second = 0, + bool $short = false, + array $words = [] + ): string { + if ($second === 0) { + $first = time() - $first; + $second = time(); + } + + $f = new DateTime('@' . $first); + $s = new DateTime('@' . $second); + $duration = $second - $first; + if ($short) { + $minutes = $this->get('minutes', $words, 'M'); + $hours = $this->get('hours', $words, 'H'); + $days = $this->get('days', $words, 'D'); + + if ($duration < 60) { + return $f->diff($s)->format('<1' . $minutes); + } + if ($duration < 3600) { + return $f->diff($s)->format('%i' . $minutes); + } + if ($duration < 86400) { + return $f->diff($s)->format('%h' . $hours . ', %i' . $minutes); + } + + return $f->diff($s)->format('%a' . $days . ', %h' . $hours . ', %i' . $minutes); + } + + $seconds = $this->get('seconds', $words, 'seconds'); + $minutes = $this->get('minutes', $words, 'minutes'); + $hours = $this->get('hours', $words, 'hours'); + $days = $this->get('days', $words, 'days'); + if ($duration < 60) { + return $f->diff($s)->format('%s ' . $seconds); + } + + if ($duration < 3600) { + return $f->diff($s)->format('%i ' . $minutes . ' and %s ' . $seconds); + } + + if ($duration < 86400) { + return $f->diff($s)->format('%h ' . $hours . ', %i ' . $minutes . ' and %s ' . $seconds); + } + + return $f->diff($s)->format( + '%a ' . $days . + ', %h ' . $hours . + ', %i ' . $minutes . + ' and %s ' . $seconds + ); + } +} diff --git a/psalm.xml b/psalm.xml new file mode 100644 index 00000000..1c8a13ad --- /dev/null +++ b/psalm.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/templates/navigate.php b/templates/navigate.php index 6a83d9ea..d057f12e 100644 --- a/templates/navigate.php +++ b/templates/navigate.php @@ -43,7 +43,7 @@
diff --git a/templates/settings.admin.php b/templates/settings.admin.php index 2bab35d1..0b35a696 100644 --- a/templates/settings.admin.php +++ b/templates/settings.admin.php @@ -31,7 +31,6 @@ use OCA\FullTextSearch\AppInfo\Application; use OCP\Util; - Util::addScript(Application::APP_ID, 'admin.elements'); Util::addScript(Application::APP_ID, 'admin.settings'); Util::addScript(Application::APP_ID, 'admin'); @@ -61,8 +60,8 @@ t('Search Platform')); ?>:
t('Select the app to index content and answer search queries.') - ); ?> + $l->t('Select the app to index content and answer search queries.') + ); ?>