diff --git a/.github/workflows/SQLite.yml b/.github/workflows/coding-styles.yml similarity index 55% rename from .github/workflows/SQLite.yml rename to .github/workflows/coding-styles.yml index 3a92cd3a..450c052c 100644 --- a/.github/workflows/SQLite.yml +++ b/.github/workflows/coding-styles.yml @@ -1,27 +1,17 @@ -name: SQLite Tests +name: "Coding Styles" -on: push +on: [push, pull_request] jobs: - sqlite-in-memory: - name: | - SQLite Tests - PHP ${{ matrix.php }} in memory + tests: + name: Coding Styles runs-on: ubuntu-latest - env: - DB_ADAPTER: pdo - DB_PDO_PROTOCOL: sqlite - DB_SQLITE_IN_MEMORY: true - strategy: - # if one of the matrix-entries break, all entries getting canceled. fail-fast: true matrix: php: - - 7.2 - - 7.3 - - 7.4 - - 8.0 + - 8.2 steps: - name: Checkout @@ -33,9 +23,13 @@ jobs: php-version: ${{ matrix.php }} coverage: xdebug ini-values: memory_limit=1G + tools: cs2pr + + - name: Validate Composer files + run: composer validate --no-check-all --strict - name: Install Composer dependencies run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader - - name: Tests - run: vendor/bin/phpunit + - name: Coding styles + run: php vendor/bin/php-cs-fixer fix --verbose --dry-run --format=checkstyle | cs2pr diff --git a/.github/workflows/mariadb-10.1.yml b/.github/workflows/mariadb-10.1.yml deleted file mode 100644 index de97808c..00000000 --- a/.github/workflows/mariadb-10.1.yml +++ /dev/null @@ -1,151 +0,0 @@ -name: MariaDB 10.1 Tests - -on: push - -jobs: - mysqli: - name: MariaDB 10.1 Tests - PHP ${{ matrix.php }} mysqli - runs-on: ubuntu-latest - - env: - DB_ADAPTER: mysqli - - strategy: - # if one of the matrix-entries break, all entries getting canceled. - fail-fast: true - matrix: - php: - - 7.2 - - 7.3 - - 7.4 - - 8.0 - - services: - testdb: - image: mariadb:10.1 - env: - MYSQL_ROOT_PASSWORD: Pass123 - MYSQL_DATABASE: arc2_test - MYSQL_ALLOW_EMPTY_PASSWORD: false - ports: - - 3306 - options: --health-cmd="mysqladmin ping" --health-interval=15s --health-timeout=3s --health-retries=4 - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Install PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - coverage: xdebug - ini-values: memory_limit=1G - - - name: Install Composer dependencies - run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader - - - name: Tests - run: | - vendor/bin/phpunit - env: - DB_PORT: ${{ job.services.testdb.ports[3306] }} - - pdo-mysql-no-cache: - name: MariaDB 10.1 Tests - PHP ${{ matrix.php }} PDO mysql no cache - runs-on: ubuntu-latest - - env: - DB_ADAPTER: pdo - DB_PDO_PROTOCOL: mysql - - strategy: - # if one of the matrix-entries break, all entries getting canceled. - fail-fast: true - matrix: - php: - - 7.2 - - 7.3 - - 7.4 - - 8.0 - - services: - testdb: - image: mariadb:10.1 - env: - MYSQL_ROOT_PASSWORD: Pass123 - MYSQL_DATABASE: arc2_test - MYSQL_ALLOW_EMPTY_PASSWORD: false - ports: - - 3306 - options: --health-cmd="mysqladmin ping" --health-interval=15s --health-timeout=3s --health-retries=4 - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Install PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - coverage: xdebug - ini-values: memory_limit=1G - - - name: Install Composer dependencies - run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader - - - name: Tests - run: | - vendor/bin/phpunit - env: - DB_PORT: ${{ job.services.testdb.ports[3306] }} - - pdo-mysql-cache: - name: MariaDB 10.1 Tests - PHP ${{ matrix.php }} PDO mysql cache - runs-on: ubuntu-latest - - env: - DB_ADAPTER: pdo - DB_PDO_PROTOCOL: mysql - CACHE_ENABLED: true - - strategy: - # if one of the matrix-entries break, all entries getting canceled. - fail-fast: true - matrix: - php: - - 7.2 - - 7.3 - - 7.4 - - 8.0 - - services: - testdb: - image: mariadb:10.1 - env: - MYSQL_ROOT_PASSWORD: Pass123 - MYSQL_DATABASE: arc2_test - MYSQL_ALLOW_EMPTY_PASSWORD: false - ports: - - 3306 - options: --health-cmd="mysqladmin ping" --health-interval=15s --health-timeout=3s --health-retries=4 - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Install PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - coverage: xdebug - ini-values: memory_limit=1G - - - name: Install Composer dependencies - run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader - - - name: Tests - run: | - vendor/bin/phpunit - env: - DB_PORT: ${{ job.services.testdb.ports[3306] }} diff --git a/.github/workflows/mariadb-10.10.yml b/.github/workflows/mariadb-10.10.yml new file mode 100644 index 00000000..303276e9 --- /dev/null +++ b/.github/workflows/mariadb-10.10.yml @@ -0,0 +1,52 @@ +name: MariaDB 10.10 Tests + +on: push + +jobs: + pdo-mysql: + name: MariaDB 10.10 Tests - PHP ${{ matrix.php }} PDO mysql + runs-on: ubuntu-latest + + env: + DB_ADAPTER: pdo + DB_PDO_PROTOCOL: mysql + + strategy: + # if one of the matrix-entries break, all entries getting canceled. + fail-fast: true + matrix: + php: + - 8.0 + - 8.1 + - 8.2 + - 8.3 + + services: + testdb: + image: mariadb:10.10 + env: + MYSQL_ROOT_PASSWORD: Pass123 + MYSQL_DATABASE: arc2_test + MYSQL_ALLOW_EMPTY_PASSWORD: false + ports: + - 3306 + options: --health-cmd="mysqladmin ping" --health-interval=15s --health-timeout=3s --health-retries=4 + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Install PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + ini-values: memory_limit=1G + + - name: Install Composer dependencies + run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader + + - name: Tests + run: | + vendor/bin/phpunit + env: + DB_PORT: ${{ job.services.testdb.ports[3306] }} diff --git a/.github/workflows/mariadb-10.11.yml b/.github/workflows/mariadb-10.11.yml new file mode 100644 index 00000000..c16a3ee0 --- /dev/null +++ b/.github/workflows/mariadb-10.11.yml @@ -0,0 +1,52 @@ +name: MariaDB 10.11 Tests + +on: push + +jobs: + pdo-mysql: + name: MariaDB 10.11 Tests - PHP ${{ matrix.php }} PDO mysql + runs-on: ubuntu-latest + + env: + DB_ADAPTER: pdo + DB_PDO_PROTOCOL: mysql + + strategy: + # if one of the matrix-entries break, all entries getting canceled. + fail-fast: true + matrix: + php: + - 8.0 + - 8.1 + - 8.2 + - 8.3 + + services: + testdb: + image: mariadb:10.11 + env: + MYSQL_ROOT_PASSWORD: Pass123 + MYSQL_DATABASE: arc2_test + MYSQL_ALLOW_EMPTY_PASSWORD: false + ports: + - 3306 + options: --health-cmd="mysqladmin ping" --health-interval=15s --health-timeout=3s --health-retries=4 + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Install PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + ini-values: memory_limit=1G + + - name: Install Composer dependencies + run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader + + - name: Tests + run: | + vendor/bin/phpunit + env: + DB_PORT: ${{ job.services.testdb.ports[3306] }} diff --git a/.github/workflows/mariadb-10.2.yml b/.github/workflows/mariadb-10.2.yml deleted file mode 100644 index 382b7c96..00000000 --- a/.github/workflows/mariadb-10.2.yml +++ /dev/null @@ -1,151 +0,0 @@ -name: MariaDB 10.2 Tests - -on: push - -jobs: - mysqli: - name: MariaDB 10.2 Tests - PHP ${{ matrix.php }} mysqli - runs-on: ubuntu-latest - - env: - DB_ADAPTER: mysqli - - strategy: - # if one of the matrix-entries break, all entries getting canceled. - fail-fast: true - matrix: - php: - - 7.2 - - 7.3 - - 7.4 - - 8.0 - - services: - testdb: - image: mariadb:10.2 - env: - MYSQL_ROOT_PASSWORD: Pass123 - MYSQL_DATABASE: arc2_test - MYSQL_ALLOW_EMPTY_PASSWORD: false - ports: - - 3306 - options: --health-cmd="mysqladmin ping" --health-interval=15s --health-timeout=3s --health-retries=4 - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Install PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - coverage: xdebug - ini-values: memory_limit=1G - - - name: Install Composer dependencies - run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader - - - name: Tests - run: | - vendor/bin/phpunit - env: - DB_PORT: ${{ job.services.testdb.ports[3306] }} - - pdo-mysql-no-cache: - name: MariaDB 10.2 Tests - PHP ${{ matrix.php }} PDO mysql no cache - runs-on: ubuntu-latest - - env: - DB_ADAPTER: pdo - DB_PDO_PROTOCOL: mysql - - strategy: - # if one of the matrix-entries break, all entries getting canceled. - fail-fast: true - matrix: - php: - - 7.2 - - 7.3 - - 7.4 - - 8.0 - - services: - testdb: - image: mariadb:10.2 - env: - MYSQL_ROOT_PASSWORD: Pass123 - MYSQL_DATABASE: arc2_test - MYSQL_ALLOW_EMPTY_PASSWORD: false - ports: - - 3306 - options: --health-cmd="mysqladmin ping" --health-interval=15s --health-timeout=3s --health-retries=4 - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Install PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - coverage: xdebug - ini-values: memory_limit=1G - - - name: Install Composer dependencies - run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader - - - name: Tests - run: | - vendor/bin/phpunit - env: - DB_PORT: ${{ job.services.testdb.ports[3306] }} - - pdo-mysql-cache: - name: MariaDB 10.2 Tests - PHP ${{ matrix.php }} PDO mysql cache - runs-on: ubuntu-latest - - env: - DB_ADAPTER: pdo - DB_PDO_PROTOCOL: mysql - CACHE_ENABLED: true - - strategy: - # if one of the matrix-entries break, all entries getting canceled. - fail-fast: true - matrix: - php: - - 7.2 - - 7.3 - - 7.4 - - 8.0 - - services: - testdb: - image: mariadb:10.2 - env: - MYSQL_ROOT_PASSWORD: Pass123 - MYSQL_DATABASE: arc2_test - MYSQL_ALLOW_EMPTY_PASSWORD: false - ports: - - 3306 - options: --health-cmd="mysqladmin ping" --health-interval=15s --health-timeout=3s --health-retries=4 - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Install PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - coverage: xdebug - ini-values: memory_limit=1G - - - name: Install Composer dependencies - run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader - - - name: Tests - run: | - vendor/bin/phpunit - env: - DB_PORT: ${{ job.services.testdb.ports[3306] }} diff --git a/.github/workflows/mariadb-10.3.yml b/.github/workflows/mariadb-10.3.yml deleted file mode 100644 index 31fe825d..00000000 --- a/.github/workflows/mariadb-10.3.yml +++ /dev/null @@ -1,151 +0,0 @@ -name: MariaDB 10.3 Tests - -on: push - -jobs: - mysqli: - name: MariaDB 10.3 Tests - PHP ${{ matrix.php }} mysqli - runs-on: ubuntu-latest - - env: - DB_ADAPTER: mysqli - - strategy: - # if one of the matrix-entries break, all entries getting canceled. - fail-fast: true - matrix: - php: - - 7.2 - - 7.3 - - 7.4 - - 8.0 - - services: - testdb: - image: mariadb:10.3 - env: - MYSQL_ROOT_PASSWORD: Pass123 - MYSQL_DATABASE: arc2_test - MYSQL_ALLOW_EMPTY_PASSWORD: false - ports: - - 3306 - options: --health-cmd="mysqladmin ping" --health-interval=15s --health-timeout=3s --health-retries=4 - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Install PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - coverage: xdebug - ini-values: memory_limit=1G - - - name: Install Composer dependencies - run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader - - - name: Tests - run: | - vendor/bin/phpunit - env: - DB_PORT: ${{ job.services.testdb.ports[3306] }} - - pdo-mysql-no-cache: - name: MariaDB 10.3 Tests - PHP ${{ matrix.php }} PDO mysql no cache - runs-on: ubuntu-latest - - env: - DB_ADAPTER: pdo - DB_PDO_PROTOCOL: mysql - - strategy: - # if one of the matrix-entries break, all entries getting canceled. - fail-fast: true - matrix: - php: - - 7.2 - - 7.3 - - 7.4 - - 8.0 - - services: - testdb: - image: mariadb:10.3 - env: - MYSQL_ROOT_PASSWORD: Pass123 - MYSQL_DATABASE: arc2_test - MYSQL_ALLOW_EMPTY_PASSWORD: false - ports: - - 3306 - options: --health-cmd="mysqladmin ping" --health-interval=15s --health-timeout=3s --health-retries=4 - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Install PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - coverage: xdebug - ini-values: memory_limit=1G - - - name: Install Composer dependencies - run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader - - - name: Tests - run: | - vendor/bin/phpunit - env: - DB_PORT: ${{ job.services.testdb.ports[3306] }} - - pdo-mysql-cache: - name: MariaDB 10.3 Tests - PHP ${{ matrix.php }} PDO mysql cache - runs-on: ubuntu-latest - - env: - DB_ADAPTER: pdo - DB_PDO_PROTOCOL: mysql - CACHE_ENABLED: true - - strategy: - # if one of the matrix-entries break, all entries getting canceled. - fail-fast: true - matrix: - php: - - 7.2 - - 7.3 - - 7.4 - - 8.0 - - services: - testdb: - image: mariadb:10.3 - env: - MYSQL_ROOT_PASSWORD: Pass123 - MYSQL_DATABASE: arc2_test - MYSQL_ALLOW_EMPTY_PASSWORD: false - ports: - - 3306 - options: --health-cmd="mysqladmin ping" --health-interval=15s --health-timeout=3s --health-retries=4 - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Install PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - coverage: xdebug - ini-values: memory_limit=1G - - - name: Install Composer dependencies - run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader - - - name: Tests - run: | - vendor/bin/phpunit - env: - DB_PORT: ${{ job.services.testdb.ports[3306] }} diff --git a/.github/workflows/mariadb-10.4.yml b/.github/workflows/mariadb-10.4.yml deleted file mode 100644 index e709a779..00000000 --- a/.github/workflows/mariadb-10.4.yml +++ /dev/null @@ -1,151 +0,0 @@ -name: MariaDB 10.4 Tests - -on: push - -jobs: - mysqli: - name: MariaDB 10.4 Tests - PHP ${{ matrix.php }} mysqli - runs-on: ubuntu-latest - - env: - DB_ADAPTER: mysqli - - strategy: - # if one of the matrix-entries break, all entries getting canceled. - fail-fast: true - matrix: - php: - - 7.2 - - 7.3 - - 7.4 - - 8.0 - - services: - testdb: - image: mariadb:10.4 - env: - MYSQL_ROOT_PASSWORD: Pass123 - MYSQL_DATABASE: arc2_test - MYSQL_ALLOW_EMPTY_PASSWORD: false - ports: - - 3306 - options: --health-cmd="mysqladmin ping" --health-interval=15s --health-timeout=3s --health-retries=4 - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Install PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - coverage: xdebug - ini-values: memory_limit=1G - - - name: Install Composer dependencies - run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader - - - name: Tests - run: | - vendor/bin/phpunit - env: - DB_PORT: ${{ job.services.testdb.ports[3306] }} - - pdo-mysql-no-cache: - name: MariaDB 10.4 Tests - PHP ${{ matrix.php }} PDO mysql no cache - runs-on: ubuntu-latest - - env: - DB_ADAPTER: pdo - DB_PDO_PROTOCOL: mysql - - strategy: - # if one of the matrix-entries break, all entries getting canceled. - fail-fast: true - matrix: - php: - - 7.2 - - 7.3 - - 7.4 - - 8.0 - - services: - testdb: - image: mariadb:10.4 - env: - MYSQL_ROOT_PASSWORD: Pass123 - MYSQL_DATABASE: arc2_test - MYSQL_ALLOW_EMPTY_PASSWORD: false - ports: - - 3306 - options: --health-cmd="mysqladmin ping" --health-interval=15s --health-timeout=3s --health-retries=4 - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Install PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - coverage: xdebug - ini-values: memory_limit=1G - - - name: Install Composer dependencies - run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader - - - name: Tests - run: | - vendor/bin/phpunit - env: - DB_PORT: ${{ job.services.testdb.ports[3306] }} - - pdo-mysql-cache: - name: MariaDB 10.4 Tests - PHP ${{ matrix.php }} PDO mysql cache - runs-on: ubuntu-latest - - env: - DB_ADAPTER: pdo - DB_PDO_PROTOCOL: mysql - CACHE_ENABLED: true - - strategy: - # if one of the matrix-entries break, all entries getting canceled. - fail-fast: true - matrix: - php: - - 7.2 - - 7.3 - - 7.4 - - 8.0 - - services: - testdb: - image: mariadb:10.4 - env: - MYSQL_ROOT_PASSWORD: Pass123 - MYSQL_DATABASE: arc2_test - MYSQL_ALLOW_EMPTY_PASSWORD: false - ports: - - 3306 - options: --health-cmd="mysqladmin ping" --health-interval=15s --health-timeout=3s --health-retries=4 - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Install PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - coverage: xdebug - ini-values: memory_limit=1G - - - name: Install Composer dependencies - run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader - - - name: Tests - run: | - vendor/bin/phpunit - env: - DB_PORT: ${{ job.services.testdb.ports[3306] }} diff --git a/.github/workflows/mariadb-10.5.yml b/.github/workflows/mariadb-10.5.yml index 907e6e0d..54064262 100644 --- a/.github/workflows/mariadb-10.5.yml +++ b/.github/workflows/mariadb-10.5.yml @@ -3,121 +3,23 @@ name: MariaDB 10.5 Tests on: push jobs: - mysqli: - name: MariaDB 10.5 Tests - PHP ${{ matrix.php }} mysqli - runs-on: ubuntu-latest - - env: - DB_ADAPTER: mysqli - - strategy: - # if one of the matrix-entries break, all entries getting canceled. - fail-fast: true - matrix: - php: - - 7.2 - - 7.3 - - 7.4 - - 8.0 - - services: - testdb: - image: mariadb:10.5 - env: - MYSQL_ROOT_PASSWORD: Pass123 - MYSQL_DATABASE: arc2_test - MYSQL_ALLOW_EMPTY_PASSWORD: false - ports: - - 3306 - options: --health-cmd="mysqladmin ping" --health-interval=15s --health-timeout=3s --health-retries=4 - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Install PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - coverage: xdebug - ini-values: memory_limit=1G - - - name: Install Composer dependencies - run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader - - - name: Tests - run: | - vendor/bin/phpunit - env: - DB_PORT: ${{ job.services.testdb.ports[3306] }} - - pdo-mysql-no-cache: - name: MariaDB 10.5 Tests - PHP ${{ matrix.php }} PDO mysql no cache - runs-on: ubuntu-latest - - env: - DB_ADAPTER: pdo - DB_PDO_PROTOCOL: mysql - - strategy: - # if one of the matrix-entries break, all entries getting canceled. - fail-fast: true - matrix: - php: - - 7.2 - - 7.3 - - 7.4 - - 8.0 - - services: - testdb: - image: mariadb:10.5 - env: - MYSQL_ROOT_PASSWORD: Pass123 - MYSQL_DATABASE: arc2_test - MYSQL_ALLOW_EMPTY_PASSWORD: false - ports: - - 3306 - options: --health-cmd="mysqladmin ping" --health-interval=15s --health-timeout=3s --health-retries=4 - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Install PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - coverage: xdebug - ini-values: memory_limit=1G - - - name: Install Composer dependencies - run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader - - - name: Tests - run: | - vendor/bin/phpunit - env: - DB_PORT: ${{ job.services.testdb.ports[3306] }} - - pdo-mysql-cache: - name: MariaDB 10.5 Tests - PHP ${{ matrix.php }} PDO mysql cache + pdo-mysql: + name: MariaDB 10.5 Tests - PHP ${{ matrix.php }} PDO mysql runs-on: ubuntu-latest env: DB_ADAPTER: pdo DB_PDO_PROTOCOL: mysql - CACHE_ENABLED: true strategy: # if one of the matrix-entries break, all entries getting canceled. fail-fast: true matrix: php: - - 7.2 - - 7.3 - - 7.4 - 8.0 + - 8.1 + - 8.2 + - 8.3 services: testdb: @@ -138,7 +40,6 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} - coverage: xdebug ini-values: memory_limit=1G - name: Install Composer dependencies diff --git a/.github/workflows/mariadb-10.6.yml b/.github/workflows/mariadb-10.6.yml new file mode 100644 index 00000000..5c18394f --- /dev/null +++ b/.github/workflows/mariadb-10.6.yml @@ -0,0 +1,52 @@ +name: MariaDB 10.6 Tests + +on: push + +jobs: + pdo-mysql: + name: MariaDB 10.6 Tests - PHP ${{ matrix.php }} PDO mysql + runs-on: ubuntu-latest + + env: + DB_ADAPTER: pdo + DB_PDO_PROTOCOL: mysql + + strategy: + # if one of the matrix-entries break, all entries getting canceled. + fail-fast: true + matrix: + php: + - 8.0 + - 8.1 + - 8.2 + - 8.3 + + services: + testdb: + image: mariadb:10.6 + env: + MYSQL_ROOT_PASSWORD: Pass123 + MYSQL_DATABASE: arc2_test + MYSQL_ALLOW_EMPTY_PASSWORD: false + ports: + - 3306 + options: --health-cmd="mysqladmin ping" --health-interval=15s --health-timeout=3s --health-retries=4 + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Install PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + ini-values: memory_limit=1G + + - name: Install Composer dependencies + run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader + + - name: Tests + run: | + vendor/bin/phpunit + env: + DB_PORT: ${{ job.services.testdb.ports[3306] }} diff --git a/.github/workflows/mariadb-10.9.yml b/.github/workflows/mariadb-10.9.yml new file mode 100644 index 00000000..ca96e64c --- /dev/null +++ b/.github/workflows/mariadb-10.9.yml @@ -0,0 +1,52 @@ +name: MariaDB 10.9 Tests + +on: push + +jobs: + pdo-mysql: + name: MariaDB 10.9 Tests - PHP ${{ matrix.php }} PDO mysql + runs-on: ubuntu-latest + + env: + DB_ADAPTER: pdo + DB_PDO_PROTOCOL: mysql + + strategy: + # if one of the matrix-entries break, all entries getting canceled. + fail-fast: true + matrix: + php: + - 8.0 + - 8.1 + - 8.2 + - 8.3 + + services: + testdb: + image: mariadb:10.9 + env: + MYSQL_ROOT_PASSWORD: Pass123 + MYSQL_DATABASE: arc2_test + MYSQL_ALLOW_EMPTY_PASSWORD: false + ports: + - 3306 + options: --health-cmd="mysqladmin ping" --health-interval=15s --health-timeout=3s --health-retries=4 + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Install PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + ini-values: memory_limit=1G + + - name: Install Composer dependencies + run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader + + - name: Tests + run: | + vendor/bin/phpunit + env: + DB_PORT: ${{ job.services.testdb.ports[3306] }} diff --git a/.github/workflows/mysql-5.5.yml b/.github/workflows/mysql-5.5.yml index 88de928a..eb3632b1 100644 --- a/.github/workflows/mysql-5.5.yml +++ b/.github/workflows/mysql-5.5.yml @@ -3,121 +3,23 @@ name: MySQL 5.5 Tests on: push jobs: - mysqli: - name: MySQL 5.5 Tests - PHP ${{ matrix.php }} mysqli - runs-on: ubuntu-latest - - env: - DB_ADAPTER: mysqli - - strategy: - # if one of the matrix-entries break, all entries getting canceled. - fail-fast: true - matrix: - php: - - 7.2 - - 7.3 - - 7.4 - - 8.0 - - services: - testdb: - image: mysql:5.5 - env: - MYSQL_ROOT_PASSWORD: Pass123 - MYSQL_DATABASE: arc2_test - MYSQL_ALLOW_EMPTY_PASSWORD: false - ports: - - 3306 - options: --health-cmd="mysqladmin ping" --health-interval=15s --health-timeout=3s --health-retries=4 - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Install PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - coverage: xdebug - ini-values: memory_limit=1G - - - name: Install Composer dependencies - run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader - - - name: Tests - run: | - vendor/bin/phpunit - env: - DB_PORT: ${{ job.services.testdb.ports[3306] }} - - pdo-mysql-no-cache: - name: MySQL 5.5 Tests - PHP ${{ matrix.php }} PDO mysql no cache - runs-on: ubuntu-latest - - env: - DB_ADAPTER: pdo - DB_PDO_PROTOCOL: mysql - - strategy: - # if one of the matrix-entries break, all entries getting canceled. - fail-fast: true - matrix: - php: - - 7.2 - - 7.3 - - 7.4 - - 8.0 - - services: - testdb: - image: mysql:5.5 - env: - MYSQL_ROOT_PASSWORD: Pass123 - MYSQL_DATABASE: arc2_test - MYSQL_ALLOW_EMPTY_PASSWORD: false - ports: - - 3306 - options: --health-cmd="mysqladmin ping" --health-interval=15s --health-timeout=3s --health-retries=4 - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Install PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - coverage: xdebug - ini-values: memory_limit=1G - - - name: Install Composer dependencies - run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader - - - name: Tests - run: | - vendor/bin/phpunit - env: - DB_PORT: ${{ job.services.testdb.ports[3306] }} - - pdo-mysql-cache: - name: MySQL 5.5 Tests - PHP ${{ matrix.php }} PDO mysql cache + pdo-mysql: + name: MySQL 5.5 Tests - PHP ${{ matrix.php }} PDO mysql runs-on: ubuntu-latest env: DB_ADAPTER: pdo DB_PDO_PROTOCOL: mysql - CACHE_ENABLED: true strategy: # if one of the matrix-entries break, all entries getting canceled. fail-fast: true matrix: php: - - 7.2 - - 7.3 - - 7.4 - 8.0 + - 8.1 + - 8.2 + - 8.3 services: testdb: @@ -138,7 +40,6 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} - coverage: xdebug ini-values: memory_limit=1G - name: Install Composer dependencies diff --git a/.github/workflows/mysql-5.6.yml b/.github/workflows/mysql-5.6.yml index 1640f5ec..903a6a4a 100644 --- a/.github/workflows/mysql-5.6.yml +++ b/.github/workflows/mysql-5.6.yml @@ -3,56 +3,8 @@ name: MySQL 5.6 Tests on: push jobs: - mysqli: - name: MySQL 5.6 Tests - PHP ${{ matrix.php }} mysqli - runs-on: ubuntu-latest - - env: - DB_ADAPTER: mysqli - - strategy: - # if one of the matrix-entries break, all entries getting canceled. - fail-fast: true - matrix: - php: - - 7.2 - - 7.3 - - 7.4 - - 8.0 - - services: - testdb: - image: mysql:5.6 - env: - MYSQL_ROOT_PASSWORD: Pass123 - MYSQL_DATABASE: arc2_test - MYSQL_ALLOW_EMPTY_PASSWORD: false - ports: - - 3306 - options: --health-cmd="mysqladmin ping" --health-interval=15s --health-timeout=3s --health-retries=4 - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Install PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - coverage: xdebug - ini-values: memory_limit=1G - - - name: Install Composer dependencies - run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader - - - name: Tests - run: | - vendor/bin/phpunit - env: - DB_PORT: ${{ job.services.testdb.ports[3306] }} - - pdo-mysql-no-cache: - name: MySQL 5.6 Tests - PHP ${{ matrix.php }} PDO mysql no cache + pdo-mysql: + name: MySQL 5.6 Tests - PHP ${{ matrix.php }} PDO mysql runs-on: ubuntu-latest env: @@ -64,61 +16,10 @@ jobs: fail-fast: true matrix: php: - - 7.2 - - 7.3 - - 7.4 - 8.0 - - services: - testdb: - image: mysql:5.6 - env: - MYSQL_ROOT_PASSWORD: Pass123 - MYSQL_DATABASE: arc2_test - MYSQL_ALLOW_EMPTY_PASSWORD: false - ports: - - 3306 - options: --health-cmd="mysqladmin ping" --health-interval=15s --health-timeout=3s --health-retries=4 - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Install PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - coverage: xdebug - ini-values: memory_limit=1G - - - name: Install Composer dependencies - run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader - - - name: Tests - run: | - vendor/bin/phpunit - env: - DB_PORT: ${{ job.services.testdb.ports[3306] }} - - pdo-mysql-cache: - name: MySQL 5.6 Tests - PHP ${{ matrix.php }} PDO mysql cache - runs-on: ubuntu-latest - - env: - DB_ADAPTER: pdo - DB_PDO_PROTOCOL: mysql - CACHE_ENABLED: true - - strategy: - # if one of the matrix-entries break, all entries getting canceled. - fail-fast: true - matrix: - php: - - 7.2 - - 7.3 - - 7.4 - - 8.0 - + - 8.1 + - 8.2 + - 8.3 services: testdb: image: mysql:5.6 @@ -138,7 +39,6 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} - coverage: xdebug ini-values: memory_limit=1G - name: Install Composer dependencies diff --git a/.github/workflows/mysql-5.7.yml b/.github/workflows/mysql-5.7.yml index cabd6ab9..be4d324f 100644 --- a/.github/workflows/mysql-5.7.yml +++ b/.github/workflows/mysql-5.7.yml @@ -3,121 +3,23 @@ name: MySQL 5.7 Tests on: push jobs: - mysqli: - name: MySQL 5.7 Tests - PHP ${{ matrix.php }} mysqli - runs-on: ubuntu-latest - - env: - DB_ADAPTER: mysqli - - strategy: - # if one of the matrix-entries break, all entries getting canceled. - fail-fast: true - matrix: - php: - - 7.2 - - 7.3 - - 7.4 - - 8.0 - - services: - testdb: - image: mysql:5.7 - env: - MYSQL_ROOT_PASSWORD: Pass123 - MYSQL_DATABASE: arc2_test - MYSQL_ALLOW_EMPTY_PASSWORD: false - ports: - - 3306 - options: --health-cmd="mysqladmin ping" --health-interval=15s --health-timeout=3s --health-retries=4 - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Install PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - coverage: xdebug - ini-values: memory_limit=1G - - - name: Install Composer dependencies - run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader - - - name: Tests - run: | - vendor/bin/phpunit - env: - DB_PORT: ${{ job.services.testdb.ports[3306] }} - - pdo-mysql-no-cache: - name: MySQL 5.7 Tests - PHP ${{ matrix.php }} PDO mysql no cache - runs-on: ubuntu-latest - - env: - DB_ADAPTER: pdo - DB_PDO_PROTOCOL: mysql - - strategy: - # if one of the matrix-entries break, all entries getting canceled. - fail-fast: true - matrix: - php: - - 7.2 - - 7.3 - - 7.4 - - 8.0 - - services: - testdb: - image: mysql:5.7 - env: - MYSQL_ROOT_PASSWORD: Pass123 - MYSQL_DATABASE: arc2_test - MYSQL_ALLOW_EMPTY_PASSWORD: false - ports: - - 3306 - options: --health-cmd="mysqladmin ping" --health-interval=15s --health-timeout=3s --health-retries=4 - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Install PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - coverage: xdebug - ini-values: memory_limit=1G - - - name: Install Composer dependencies - run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader - - - name: Tests - run: | - vendor/bin/phpunit - env: - DB_PORT: ${{ job.services.testdb.ports[3306] }} - - pdo-mysql-cache: - name: MySQL 5.7 Tests - PHP ${{ matrix.php }} PDO mysql cache + pdo-mysql: + name: MySQL 5.7 Tests - PHP ${{ matrix.php }} PDO mysql runs-on: ubuntu-latest env: DB_ADAPTER: pdo DB_PDO_PROTOCOL: mysql - CACHE_ENABLED: true strategy: # if one of the matrix-entries break, all entries getting canceled. fail-fast: true matrix: php: - - 7.2 - - 7.3 - - 7.4 - 8.0 + - 8.1 + - 8.2 + - 8.3 services: testdb: @@ -138,7 +40,6 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} - coverage: xdebug ini-values: memory_limit=1G - name: Install Composer dependencies diff --git a/.github/workflows/mysql-8.0.yml b/.github/workflows/mysql-8.0.yml new file mode 100644 index 00000000..556708b6 --- /dev/null +++ b/.github/workflows/mysql-8.0.yml @@ -0,0 +1,52 @@ +name: MySQL 8.0 Tests + +on: push + +jobs: + pdo-mysql: + name: MySQL 8.0 Tests - PHP ${{ matrix.php }} PDO mysql + runs-on: ubuntu-latest + + env: + DB_ADAPTER: pdo + DB_PDO_PROTOCOL: mysql + + strategy: + # if one of the matrix-entries break, all entries getting canceled. + fail-fast: true + matrix: + php: + - 8.0 + - 8.1 + - 8.2 + - 8.3 + + services: + testdb: + image: mysql:8.0 + env: + MYSQL_ROOT_PASSWORD: Pass123 + MYSQL_DATABASE: arc2_test + MYSQL_ALLOW_EMPTY_PASSWORD: false + ports: + - 3306 + options: --health-cmd="mysqladmin ping" --health-interval=15s --health-timeout=3s --health-retries=4 + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Install PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + ini-values: memory_limit=1G + + - name: Install Composer dependencies + run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader + + - name: Tests + run: | + vendor/bin/phpunit + env: + DB_PORT: ${{ job.services.testdb.ports[3306] }} diff --git a/.github/workflows/mysql-8.1.yml b/.github/workflows/mysql-8.1.yml new file mode 100644 index 00000000..c4ad52cd --- /dev/null +++ b/.github/workflows/mysql-8.1.yml @@ -0,0 +1,52 @@ +name: MySQL 8.1 Tests + +on: push + +jobs: + pdo-mysql: + name: MySQL 8.1 Tests - PHP ${{ matrix.php }} PDO mysql + runs-on: ubuntu-latest + + env: + DB_ADAPTER: pdo + DB_PDO_PROTOCOL: mysql + + strategy: + # if one of the matrix-entries break, all entries getting canceled. + fail-fast: true + matrix: + php: + - 8.1 + - 8.1 + - 8.2 + - 8.3 + + services: + testdb: + image: mysql:8.1 + env: + MYSQL_ROOT_PASSWORD: Pass123 + MYSQL_DATABASE: arc2_test + MYSQL_ALLOW_EMPTY_PASSWORD: false + ports: + - 3306 + options: --health-cmd="mysqladmin ping" --health-interval=15s --health-timeout=3s --health-retries=4 + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Install PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + ini-values: memory_limit=1G + + - name: Install Composer dependencies + run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader + + - name: Tests + run: | + vendor/bin/phpunit + env: + DB_PORT: ${{ job.services.testdb.ports[3306] }} diff --git a/.gitignore b/.gitignore index d657def0..7827c57a 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ triggers/* tests/coverage/* tests/config.php vendor/ +/.php-cs-fixer.cache diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php new file mode 100644 index 00000000..073b0f67 --- /dev/null +++ b/.php-cs-fixer.php @@ -0,0 +1,29 @@ +in(__DIR__.'/extractors') + ->in(__DIR__.'/parsers') + ->in(__DIR__.'/serializers') + ->in(__DIR__.'/sparqlscript') + ->in(__DIR__.'/src') + ->in(__DIR__.'/store') + ->in(__DIR__.'/tests') + ->in(__DIR__.'/') + ->name('*.php') +; + +$config = new Config(); +$config + ->setFinder($finder) + ->setRiskyAllowed(true) + ->setRules([ + '@Symfony' => true, + '@Symfony:risky' => true, + 'phpdoc_summary' => false, + ]) +; + +return $config; diff --git a/.php_cs b/.php_cs deleted file mode 100644 index 07c105e5..00000000 --- a/.php_cs +++ /dev/null @@ -1,35 +0,0 @@ -setRules( - [ - '@Symfony' => true, - '@Symfony:risky' => true, - 'align_multiline_comment' => true, - 'array_syntax' => ['syntax' => 'short'], - 'array_indentation' => true, - ] - ) - ->setRiskyAllowed(true) - ->setFinder( - PhpCsFixer\Finder::create() - ->files() - ->in(__DIR__.'/extractors') - ->in(__DIR__.'/parsers') - ->in(__DIR__.'/serializers') - ->in(__DIR__.'/sparqlscript') - ->in(__DIR__.'/src') - ->in(__DIR__.'/store') - ->in(__DIR__.'/tests') - ->name('*.php') - ->append([ - __FILE__, - __DIR__.'/ARC2.php', - __DIR__.'/ARC2_Class.php', - __DIR__.'/ARC2_getFormat.php', - __DIR__.'/ARC2_getPreferredFormat.php', - __DIR__.'/ARC2_Graph.php', - __DIR__.'/ARC2_Reader.php', - __DIR__.'/ARC2_Ressource.php', - ]) - ); diff --git a/ARC2.php b/ARC2.php index d586442b..5a8d371a 100644 --- a/ARC2.php +++ b/ARC2.php @@ -3,6 +3,7 @@ * ARC2 core class (static, not instantiated). * * @author Benjamin Nowack + * * @homepage */ @@ -128,8 +129,9 @@ public static function toUTF8($v) if (urlencode($v) === $v) { return $v; } - //if (utf8_decode($v) == $v) return $v; - $v = (false === strpos(utf8_decode(str_replace('?', '', $v)), '?')) ? utf8_decode($v) : $v; + $str = mb_convert_encoding(str_replace('?', '', $v), 'ISO-8859-1', 'UTF-8'); + $v = false === str_contains($str, '?') ? mb_convert_encoding($v, 'ISO-8859-1', 'UTF-8') : $v; + /* custom hacks, mainly caused by bugs in PHP's json_decode */ $mappings = [ '%18' => '‘', @@ -149,6 +151,7 @@ public static function toUTF8($v) $froms[$i] = urldecode($from); } $v = str_replace($froms, $tos, $v); + /* utf8 tweaks */ return preg_replace_callback('/([\x00-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xf7][\x80-\xbf]{3}|[\xf8-\xfb][\x80-\xbf]{4}|[\xfc-\xfd][\x80-\xbf]{5}|[^\x00-\x7f])/', ['ARC2', 'getUTF8Char'], $v); } @@ -157,7 +160,7 @@ public static function getUTF8Char($v) { $val = $v[1]; if (1 === strlen(trim($val))) { - return utf8_encode($val); + return mb_convert_encoding($val, 'UTF-8', mb_list_encodings()); } if (preg_match('/^([\x00-\x7f])(.+)/', $val, $m)) { return $m[1].self::toUTF8($m[2]); @@ -178,7 +181,7 @@ public static function splitURI($v) 'http://www.w3.org/1999/xhtml', ]; foreach ($specials as $ns) { - if (0 === strpos($v, $ns)) { + if (str_starts_with($v, $ns)) { $local_part = substr($v, strlen($ns)); if (!preg_match('/^[\/\#]/', $local_part)) { return [$ns, $local_part]; @@ -187,7 +190,7 @@ public static function splitURI($v) } } /* auto-splitting on / or # */ - //$re = '^(.*?)([A-Z_a-z][-A-Z_a-z0-9.]*)$'; + // $re = '^(.*?)([A-Z_a-z][-A-Z_a-z0-9.]*)$'; if (preg_match('/^(.*[\/\#])([^\/\#]+)$/', $v, $m)) { return [$m[1], $m[2]]; } @@ -362,7 +365,7 @@ public static function getStructType($v) return 'array'; } /* triples */ - //if (isset($v[0]) && isset($v[0]['s']) && isset($v[0]['p'])) return 'triples'; + // if (isset($v[0]) && isset($v[0]['s']) && isset($v[0]['p'])) return 'triples'; if (in_array('p', array_keys($v[0]))) { return 'triples'; } @@ -384,6 +387,7 @@ public static function getStructType($v) } } } + /* array */ return 'array'; } diff --git a/ARC2_Class.php b/ARC2_Class.php index f5e0dffb..05b57e89 100644 --- a/ARC2_Class.php +++ b/ARC2_Class.php @@ -4,11 +4,56 @@ * * @author Benjamin Nowack * @license W3C Software License and GPL + * * @homepage */ class ARC2_Class { - protected $db_object; + /** + * @var array + */ + public array $a = []; + + public int $adjust_utf8; + + public string $base; + + public $caller; + + public $db_object; + + /** + * @var array + */ + public array $errors = []; + + public $has_pcre_unicode; + + public string $inc_path; + + public int $max_errors; + + /** + * @var array + */ + public array $ns; + + public int $ns_count; + + /** + * @var array + */ + public array $nsp; + + /** + * @var array + */ + public array $used_ns = []; + + /** + * @var array + */ + public array $warnings = []; public function __construct($a, &$caller) { @@ -34,7 +79,7 @@ public function __init() $this->warnings = []; $this->adjust_utf8 = $this->v('adjust_utf8', 0, $this->a); $this->max_errors = $this->v('max_errors', 25, $this->a); - $this->has_pcre_unicode = @preg_match('/\pL/u', 'test'); /* \pL = block/point which is a Letter */ + $this->has_pcre_unicode = preg_match('/\pL/u', 'test'); /* \pL = block/point which is a Letter */ } public function v($name, $default = false, $o = false) @@ -146,7 +191,7 @@ public function addError($v) $this->errors[] = $v; } if ($this->caller && method_exists($this->caller, 'addError')) { - $glue = strpos($v, ' in ') ? ' via ' : ' in '; + $glue = str_contains((string) $v, ' in ') ? ' via ' : ' in '; $this->caller->addError($v.$glue.static::class); } if (count($this->errors) > $this->max_errors) { @@ -595,7 +640,8 @@ public function getDBObjectFromARC2Class($con = null) require __DIR__.'/src/ARC2/Store/Adapter/AdapterFactory.php'; } if (false == isset($this->a['db_adapter'])) { - $this->a['db_adapter'] = 'mysqli'; + $this->a['db_adapter'] = 'pdo'; + $this->a['db_pdo_protocol'] = 'mysql'; } $factory = new \ARC2\Store\Adapter\AdapterFactory(); $this->db_object = $factory->getInstanceFor($this->a['db_adapter'], $this->a); @@ -609,45 +655,6 @@ public function getDBObjectFromARC2Class($con = null) return $this->db_object; } - /** - * Dont use this function to directly query the database. It currently works only with mysqli DB adapter. - * - * @param string $sql SQL query - * @param mysqli $con Connection - * @param int $log_errors 1 if you want to log errors. Default is 0 - * - * @return mysqli Result - * - * @deprecated since 2.4.0 - */ - public function queryDB($sql, $con, $log_errors = 0) - { - $t1 = ARC2::mtime(); - - // create connection using an adapter, if not available yet - $this->getDBObjectFromARC2Class($con); - - $r = $this->db_object->mysqliQuery($sql); - - // TODO check if this is ever called. it seems not and therefore could be removed. - if (0) { - $t2 = ARC2::mtime() - $t1; - $call_obj = $this; - $call_path = ''; - while ($call_obj) { - $call_path = get_class($call_obj).' / '.$call_path; - $call_obj = isset($call_obj->caller) ? $call_obj->caller : false; - } - echo "\n".$call_path.' needed '.$t2.' secs for '.str_replace("\n", ' ', $sql); - } - - if ($log_errors && !empty($this->db_object->getErrorMessage())) { - $this->addError($this->db_object->getErrorMessage()); - } - - return $r; - } - /** * Shortcut method to create an RDF/XML backup dump from an RDF Store object. */ diff --git a/ARC2_Graph.php b/ARC2_Graph.php index be95d66f..75ca97af 100644 --- a/ARC2_Graph.php +++ b/ARC2_Graph.php @@ -4,6 +4,7 @@ * * @author Benjamin Nowack * @license W3C Software License + * * @homepage */ ARC2::inc('Class'); diff --git a/ARC2_Reader.php b/ARC2_Reader.php index f15fc950..3a26a138 100755 --- a/ARC2_Reader.php +++ b/ARC2_Reader.php @@ -4,6 +4,7 @@ * * @author Benjamin Nowack * @license W3C Software License and GPL + * * @homepage * * @version 2010-11-16 @@ -12,6 +13,35 @@ class ARC2_Reader extends ARC2_Class { + /** + * @var array + */ + public array $auth_infos; + public int $digest_auth; + public $format; + public string $http_accept_header; + public string $http_custom_headers; + public string $http_method; + public string $http_user_agent_header; + public int $max_redirects; + public string $message_body; + public int $ping_only; + + /** + * @var array + */ + public array $redirects; + + /** + * @var array + */ + public array $response_headers; + + public $stream; + public string $stream_id; + public int $timeout; + public string $uri; + public function __construct($a, &$caller) { parent::__construct($a, $caller); @@ -132,7 +162,7 @@ public function setBasicAuthCredentials($creds) $auth = 'Basic '.base64_encode($creds['user'].':'.$creds['pass']); $h = in_array('proxy', $creds) ? 'Proxy-Authorization' : 'Authorization'; $this->addCustomHeaders($h.': '.$auth); - //echo $h . ': ' . $auth . print_r($creds, 1); + // echo $h . ': ' . $auth . print_r($creds, 1); } public function setDigestAuthCredentials($creds, $url) @@ -190,7 +220,7 @@ public function useProxy($url) } $skips = $this->v1('proxy_skip', [], $this->a); foreach ($skips as $skip) { - if (false !== strpos($url, $skip)) { + if (str_contains($url, $skip)) { return false; } } @@ -272,7 +302,7 @@ public function getHTTPSocket($url, $redirs = 0, $prev_parts = '') stream_context_set_option($context, 'ssl', $m[1], $v); } } - $s = stream_socket_client('ssl://'.$parts['host'].':'.$parts['port'], $errno, $errstr, $this->timeout, STREAM_CLIENT_CONNECT, $context); + $s = stream_socket_client('ssl://'.$parts['host'].':'.$parts['port'], $errno, $errstr, $this->timeout, \STREAM_CLIENT_CONNECT, $context); } elseif ('https' == $parts['scheme']) { $s = @fsockopen('ssl://'.$parts['host'], $parts['port'], $errno, $errstr, $this->timeout); } elseif ('http' == $parts['scheme']) { @@ -285,7 +315,7 @@ public function getHTTPSocket($url, $redirs = 0, $prev_parts = '') fwrite($s, $h_code); /* timeout */ if ($this->timeout) { - //stream_set_blocking($s, false); + // stream_set_blocking($s, false); stream_set_timeout($s, $this->timeout); } /* response headers */ @@ -380,7 +410,7 @@ public function getURIPartsFromURIAndPreviousURIParts($uri, $previous_uri_parts) public function readStream($buffer_xml = true, $d_size = 1024) { - //if (!$s = $this->v('stream')) return ''; + // if (!$s = $this->v('stream')) return ''; if (!$s = $this->v('stream')) { return $this->addError('missing stream in "readStream" '.$this->uri); } diff --git a/ARC2_Resource.php b/ARC2_Resource.php index 9588ca1e..725e4650 100644 --- a/ARC2_Resource.php +++ b/ARC2_Resource.php @@ -4,147 +4,191 @@ * * @author Benjamin Nowack * @license W3C Software License and GPL + * * @homepage - * @package ARC2 + * * @version 2011-01-19 -*/ - + */ ARC2::inc('Class'); -class ARC2_Resource extends ARC2_Class { - - function __construct($a, &$caller) { - parent::__construct($a, $caller); - } - - function __init() { - parent::__init(); - $this->uri = ''; - $this->index = array(); - $this->fetched = array(); - $this->store = ''; - } - - /* */ - - function setURI($uri) { - $this->uri = $uri; - } - - function setIndex($index) { - $this->index = $index; - } - - function getIndex() { - return $this->index; - } - - function setProps($props, $s = '') { - if (!$s) $s = $this->uri; - $this->index[$s] = $props; - } - - function setProp($p, $os, $s = '') { - if (!$s) $s = $this->uri; - /* single plain value */ - if (!is_array($os)) $os = array('value' => $os, 'type' => 'literal'); - /* single array value */ - if (isset($os['value'])) $os = array($os); - /* list of values */ - foreach ($os as $i => $o) { - if (!is_array($o)) $os[$i] = array('value' => $o, 'type' => 'literal'); - } - $this->index[$s][$this->expandPName($p)] = $os; - } - - /* add a relation to a URI. Allows for instance $res->setRel('rdf:type', 'doap:Project') */ - function setRel($p, $r, $s = '') { - if(!is_array($r)) { - $uri = array ( - 'type' => 'uri', - 'value' => $this->expandPName($r)); - $this->setProp($p, $uri, $s); - } else { - if (!$s) $s = $this->uri; - foreach($r as $i => $x) { - if(!is_array($x)) { - $uri = array ( - 'type' => 'uri', - 'value' => $this->expandPName($x)); - $r[$i] = $uri; - } - } - $this->index[$s][$this->expandPName($p)] = $r; - } - } - - /* Specialize setProp to set an xsd:dateTime typed literal. Example : $res->setPropXSDdateTime('dcterms:created', date('c')) */ - function setPropXSDdateTime($p, $dt, $s = '') { - $datecreated=array('value' => $dt, - 'type' => 'literal', - 'datatype' => 'http://www.w3.org/2001/XMLSchema#dateTime'); - $this->setProp($p, $datecreated, $s); - } - - function setStore($store) { - $this->store = $store; - } - - /* */ - - function fetchData($uri = '') { - if (!$uri) $uri = $this->uri; - if (!$uri) return 0; - if (in_array($uri, $this->fetched)) return 0; - $this->index[$uri] = array(); - if ($this->store) { - $index = $this->store->query('CONSTRUCT { <' . $uri . '> ?p ?o . } WHERE { <' . $uri . '> ?p ?o . } ', 'raw'); - } - else { - $index = $this->toIndex($uri); - } - $this->index = ARC2::getMergedIndex($this->index, $index); - $this->fetched[] = $uri; - } - - /* */ - - function getProps($p = '', $s = '') { - if (!$s) $s = $this->uri; - if (!$s) return array(); - if (!isset($this->index[$s])) $this->fetchData($s); - if (!$p) return $this->index[$s]; - return $this->v($this->expandPName($p), array(), $this->index[$s]); - } - - function getProp($p, $s = '') { - $props = $this->getProps($p, $s); - return $props ? $props[0] : ''; - } - - function getPropValue($p, $s = '') { - $prop = $this->getProp($p, $s); - return $prop ? $prop['value'] : ''; - } - - function getPropValues($p, $s = '') { - $r = array(); - $props = $this->getProps($p, $s); - foreach ($props as $prop) { - $r[] = $prop['value']; - } - return $r; - } - - function hasPropValue($p, $o, $s = '') { - $props = $this->getProps($p, $s); - $o = $this->expandPName($o); - foreach ($props as $prop) { - if ($prop['value'] == $o) return 1; - } - return 0; - } - - /* */ +class ARC2_Resource extends ARC2_Class +{ + public string $uri; + public $index; + public $fetched; + public $store; + + public function __construct($a, &$caller) + { + parent::__construct($a, $caller); + } + + public function __init() + { + parent::__init(); + $this->uri = ''; + $this->index = []; + $this->fetched = []; + $this->store = ''; + } + + public function setURI($uri) + { + $this->uri = $uri; + } + + public function setIndex($index) + { + $this->index = $index; + } + + public function getIndex() + { + return $this->index; + } + + public function setProps($props, $s = '') + { + if (!$s) { + $s = $this->uri; + } + $this->index[$s] = $props; + } + + public function setProp($p, $os, $s = '') + { + if (!$s) { + $s = $this->uri; + } + /* single plain value */ + if (!is_array($os)) { + $os = ['value' => $os, 'type' => 'literal']; + } + /* single array value */ + if (isset($os['value'])) { + $os = [$os]; + } + /* list of values */ + foreach ($os as $i => $o) { + if (!is_array($o)) { + $os[$i] = ['value' => $o, 'type' => 'literal']; + } + } + $this->index[$s][$this->expandPName($p)] = $os; + } + + /* add a relation to a URI. Allows for instance $res->setRel('rdf:type', 'doap:Project') */ + public function setRel($p, $r, $s = '') + { + if (!is_array($r)) { + $uri = [ + 'type' => 'uri', + 'value' => $this->expandPName($r)]; + $this->setProp($p, $uri, $s); + } else { + if (!$s) { + $s = $this->uri; + } + foreach ($r as $i => $x) { + if (!is_array($x)) { + $uri = [ + 'type' => 'uri', + 'value' => $this->expandPName($x)]; + $r[$i] = $uri; + } + } + $this->index[$s][$this->expandPName($p)] = $r; + } + } + /* Specialize setProp to set an xsd:dateTime typed literal. Example : $res->setPropXSDdateTime('dcterms:created', date('c')) */ + public function setPropXSDdateTime($p, $dt, $s = '') + { + $datecreated = ['value' => $dt, + 'type' => 'literal', + 'datatype' => 'http://www.w3.org/2001/XMLSchema#dateTime']; + $this->setProp($p, $datecreated, $s); + } + + public function setStore($store) + { + $this->store = $store; + } + + public function fetchData($uri = '') + { + if (!$uri) { + $uri = $this->uri; + } + if (!$uri) { + return 0; + } + if (in_array($uri, $this->fetched)) { + return 0; + } + $this->index[$uri] = []; + if ($this->store) { + $index = $this->store->query('CONSTRUCT { <'.$uri.'> ?p ?o . } WHERE { <'.$uri.'> ?p ?o . } ', 'raw'); + } else { + $index = $this->toIndex($uri); + } + $this->index = ARC2::getMergedIndex($this->index, $index); + $this->fetched[] = $uri; + } + + public function getProps($p = '', $s = '') + { + if (!$s) { + $s = $this->uri; + } + if (!$s) { + return []; + } + if (!isset($this->index[$s])) { + $this->fetchData($s); + } + if (!$p) { + return $this->index[$s]; + } + + return $this->v($this->expandPName($p), [], $this->index[$s]); + } + + public function getProp($p, $s = '') + { + $props = $this->getProps($p, $s); + + return $props ? $props[0] : ''; + } + + public function getPropValue($p, $s = '') + { + $prop = $this->getProp($p, $s); + + return $prop ? $prop['value'] : ''; + } + + public function getPropValues($p, $s = '') + { + $r = []; + $props = $this->getProps($p, $s); + foreach ($props as $prop) { + $r[] = $prop['value']; + } + + return $r; + } + + public function hasPropValue($p, $o, $s = '') + { + $props = $this->getProps($p, $s); + $o = $this->expandPName($o); + foreach ($props as $prop) { + if ($prop['value'] == $o) { + return 1; + } + } + + return 0; + } } diff --git a/ARC2_getFormat.php b/ARC2_getFormat.php index 678766bc..45bfaa77 100755 --- a/ARC2_getFormat.php +++ b/ARC2_getFormat.php @@ -18,12 +18,12 @@ function ARC2_getFormat($v, $mtype = '', $ext = '') $r = (!$r && preg_match('/\/sparql-results\+xml/', $mtype)) ? 'sparqlxml' : $r; /* xml sniffing */ if ( - !$r && - /* starts with angle brackets */ - preg_match('/^\s*\<[^\s]/s', $v) && - /* has an xmlns:* declaration or a matching pair of tags */ - (preg_match('/\sxmlns\:?/', $v) || preg_match('/\<([^\s]+).+\<\/\\1\>/s', $v)) // && - ) { + !$r + /* starts with angle brackets */ + && preg_match('/^\s*\<[^\s]/s', $v) + /* has an xmlns:* declaration or a matching pair of tags */ + && (preg_match('/\sxmlns\:?/', $v) || preg_match('/\<([^\s]+).+\<\/\\1\>/s', $v)) // && + ) { while (preg_match('/^\s*\<\?xml[^\r\n]+\?\>\s*/s', $v)) { $v = preg_replace('/^\s*\<\?xml[^\r\n]+\?\>\s*/s', '', $v); } diff --git a/ARC2_getPreferredFormat.php b/ARC2_getPreferredFormat.php index e31ffb5f..653b411a 100755 --- a/ARC2_getPreferredFormat.php +++ b/ARC2_getPreferredFormat.php @@ -4,6 +4,7 @@ * * @author Benjamin Nowack * @license W3C Software License and GPL + * * @homepage * * @version 2010-11-16 diff --git a/README.md b/README.md index 7a3e93a8..d6dde39a 100644 --- a/README.md +++ b/README.md @@ -5,21 +5,24 @@ [![Latest Unstable Version](https://poser.pugx.org/semsol/arc2/v/unstable.svg)](https://packagist.org/packages/semsol/arc2) [![License](https://poser.pugx.org/semsol/arc2/license.svg)](https://packagist.org/packages/semsol/arc2) -ARC2 is a PHP 7.2+ library for working with RDF. It also provides a MySQL-based triplestore with SPARQL support. +ARC2 is a PHP 8.0+ library for working with RDF. +It also provides a MySQL-based triplestore with SPARQL support. Older versions of PHP may work, but are not longer tested. **Test status:** -| Database | Status | -|--------------|--------------------------------------------------------------------------------| -| MariaDB 10.1 | ![](https://github.com/semsol/arc2/workflows/MariaDB%2010.1%20Tests/badge.svg) | -| MariaDB 10.2 | ![](https://github.com/semsol/arc2/workflows/MariaDB%2010.2%20Tests/badge.svg) | -| MariaDB 10.3 | ![](https://github.com/semsol/arc2/workflows/MariaDB%2010.3%20Tests/badge.svg) | -| MariaDB 10.4 | ![](https://github.com/semsol/arc2/workflows/MariaDB%2010.4%20Tests/badge.svg) | -| MariaDB 10.5 | ![](https://github.com/semsol/arc2/workflows/MariaDB%2010.5%20Tests/badge.svg) | -| MySQL 5.5 | ![](https://github.com/semsol/arc2/workflows/MySQL%205.5%20Tests/badge.svg) | -| MySQL 5.6 | ![](https://github.com/semsol/arc2/workflows/MySQL%205.6%20Tests/badge.svg) | -| MySQL 5.7 | ![](https://github.com/semsol/arc2/workflows/MySQL%205.7%20Tests/badge.svg) | +| Database | Status | +|---------------|-----------------------------------------------------------------------------------------------------| +| MariaDB 10.5 | ![](https://github.com/semsol/arc2/workflows/MariaDB%2010.5%20Tests/badge.svg) | +| MariaDB 10.6 | ![](https://github.com/semsol/arc2/workflows/MariaDB%2010.6%20Tests/badge.svg) | +| MariaDB 10.9 | ![](https://github.com/semsol/arc2/workflows/MariaDB%2010.9%20Tests/badge.svg) | +| MariaDB 10.10 | ![](https://github.com/semsol/arc2/workflows/MariaDB%2010.10%20Tests/badge.svg) | +| MariaDB 10.11 | ![](https://github.com/semsol/arc2/workflows/MariaDB%2010.11%20Tests/badge.svg) | +| MySQL 5.5 | ![](https://github.com/semsol/arc2/workflows/MySQL%205.5%20Tests/badge.svg) | +| MySQL 5.6 | ![](https://github.com/semsol/arc2/workflows/MySQL%205.6%20Tests/badge.svg) | +| MySQL 5.7 | ![](https://github.com/semsol/arc2/workflows/MySQL%205.7%20Tests/badge.svg) | +| MySQL 8.0 | ![](https://github.com/semsol/arc2/workflows/MySQL%208.0%20Tests/badge.svg) - incomplete! see below | +| MySQL 8.1 | ![](https://github.com/semsol/arc2/workflows/MySQL%208.1%20Tests/badge.svg) - incomplete! see below | ## Documentation @@ -27,123 +30,31 @@ For the documentation, see the [Wiki](https://github.com/semsol/arc2/wiki#core-d ## Installation +Requires **PHP 8.0**+. + Package available on [Composer](https://packagist.org/packages/semsol/arc2). You should use Composer for installation: ```bash -composer require semsol/arc2:^2 +composer require semsol/arc2:^3 ``` Further information about Composer usage can be found [here](https://getcomposer.org/doc/01-basic-usage.md#autoloading), for instance about autoloading ARC2 classes. -## Requirements - -#### PHP - -| 7.2 | 7.3 | 7.4 | 8.0 | -|------|------|------|------| -| :+1: | :+1: | :+1: | :+1: | - -#### Database systems - -This section is relevant, if you wanna use database related functionality. - -**MySQL** - -| 5.5 | 5.6 | 5.7 | 8.0 | -|------|------|------|-----------------| -| :+1: | :+1: | :+1: | :collision: (1) | - -**MariaDB** - -| 10.0 | 10.1 | 10.2 | 10.3 | 10.4 | 10.5 | -|---------------|------|------|------|------|------| -| :question:(2) | :+1: | :+1: | :+1: | :+1: | :+1: | - -(1) As long as ARC2 uses mysqli, a connection to MySQL Server 8.0 is not possible. For more information, please look [here](https://github.com/semsol/arc2/commit/0ad48d61753b15ae02ff19f615b14aa52b6557f1). - -(2) Not tested anymore, because outdated version. - ## RDF triple store ### SPARQL support Please have a look into [SPARQL-support.md](doc/SPARQL-support.md) to see which SPARQL 1.0/1.1 features are currently supported. -### In-Memory store (SQLite-based) - -Using MySQL as database backend is the default way. -But you don't need MySQL, SQLite is enough to get a non-persistent in-memory store. -Use the following example code to get a ready-to-use store instance. - -```php -// get a working ARC2_Store instance (with SQLite adapter) -$store = ARC2::getStore(['db_adapter' => 'pdo', 'db_pdo_protocol' => 'sqlite']); - -// add 1 triple to the store -$store->query('INSERT INTO { "baz" . }'); - -// send a SPARQL query to the store -$result = $store->query('SELECT * FROM WHERE { ?o.}'); - -// you should get an array of array's with one entry in $result['result']['row']. -var_dump($result); - -// remember, after your script finished, all data in $store is gone -``` - -### Use cache - -The RDF store implementation provides a hash-based query cache. It works on two levels: SQL and SPARQL, which means, that it checks given SPARQL queries as well as internally generated SQL queries. - -To use it, just add the following to the database configuration: - -```php -$store = ARC2::getStore(array( - 'db_name' => 'testdb', - 'db_user' => 'root', - 'db_pwd' => '', - 'db_host' => '127.0.0.1', - // ... - 'cache_enabled' => true // <== activates cache -)); -``` - -Per default it uses a file based cache, which stores items in the default temp folder of the system (in Linux its usually `/tmp`). But you can use another cache solution, such as memcached. - -#### PSR-16 compatibility - -Our cache solution is [PSR-16](https://www.php-fig.org/psr/psr-16/) compatible, which means, that you can use your own cache instance. To do that, add the following to the database configuration: - -```php -$store = ARC2::getStore(array( - 'db_name' => 'testdb', - 'db_user' => 'root', - 'db_pwd' => '', - 'db_host' => '127.0.0.1', - // ... - 'cache_enabled' => true - 'cache_instance' => new ArrayCache() // <=== example Cache instance, managed by yourself -)); -``` - -ARC2 uses [Symfony Cache](https://symfony.com/doc/4.1/components/cache.html) , which provides many connectors out of the box ([Overview](https://github.com/symfony/cache/tree/master/Simple)). - -### Known problems/restrictions with database systems - -In this section you find known problems with MariaDB or MySQL, regarding certain features. E.g. MySQL 5.5 doesn't allow FULLTEXT indexes in InnoDB. We try to encapsulate any differences in the DB adapters, so that you don't have to care about them. In case you run into problems, this section might be of help. - -#### MySQL 8.0 and mysqli - -Using mysqli with MySQL 8.0 as backend throws the following exception: +### Known database problems -> mysqli_connect(): The server requested authentication method unknown to the client [caching_sha2_password] +#### MySQL 8.0+ -Based on this [source](https://mysqlserverteam.com/upgrading-to-mysql-8-0-default-authentication-plugin-considerations/), one has to change the my.cnf, adding the following entry: +The following error occurs when using a REGEX function inside a SELECT query. -> [mysqld] -> default-authentication-plugin=mysql_native_password +> General error: 3995 Character set 'utf8mb3_unicode_ci' cannot be used in conjunction with 'binary' in call to regexp_like. ## Internal information for developers diff --git a/composer.json b/composer.json index 64c1af9f..e58418a7 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "semsol/arc2", "type": "library", - "description": "ARC2 is a PHP 5.6+ library for working with RDF (It may be compatible with PHP 5.3+ but outdated versions are no longer tested). It also provides a MySQL-based triplestore with SPARQL support.", + "description": "ARC2 is a PHP library for working with RDF. It also provides a MySQL-based triplestore with SPARQL support.", "keywords": ["rdf","sparql"], "homepage": "https://github.com/semsol/arc2", "license": [ @@ -25,15 +25,12 @@ } ], "require": { - "php": ">=7.2", - "psr/simple-cache": "^1.0", - "symfony/cache": "^4.4", - "thingengineer/mysqli-database-class": "2.*" + "ext-mbstring": "*", + "php": "^8.0.0" }, "require-dev": { - "doctrine/instantiator": "^1.3", - "friendsofphp/php-cs-fixer": "*", - "phpunit/phpunit": "^8.0" + "friendsofphp/php-cs-fixer": "^3", + "phpunit/phpunit": "^9" }, "autoload": { "classmap": ["parsers/", "serializers/", "store/"], diff --git a/doc/developer.md b/doc/developer.md index aab3c96b..075e91a1 100644 --- a/doc/developer.md +++ b/doc/developer.md @@ -7,30 +7,29 @@ This document contains information about ARC2 internals which are relevant for m To run test environment execute: ```bash -make test +vendor/bin/phpunit ``` -Tests are split into different groups, currently: +Tests are split into different groups currently: * unit * db_adapter_depended You can run the `unit` group directly, but you need to set some environment variables for `db_adapter_depended`. -For more information please have a look into our `Makefile`. #### config.php -Currently, we use the following standard db credentials to connect with the database: +Currently, we use the following standard database credentials to connect with the database: ```php $dbConfig = array( 'db_name' => 'arc2_test', 'db_user' => 'root', - 'db_pwd' => '', + 'db_pwd' => 'Pass123', 'db_host' => '127.0.0.1', ); ``` -The is used in the travis environment. If you have different credentials, copy the `tests/config.php.dist` to `tests/config.php` and set your credentials. +If you have different credentials, copy the `tests/config.php.dist` to `tests/config.php` and set your credentials. ## Editor @@ -48,6 +47,9 @@ In your terminal go to `docker` folder and run `make`. It will build and start t ### Docker and Travis -We use a very wide range of software-combinations to test ARC2 ([Travis](https://travis-ci.org/semsol/arc2)). Currently, all combinations of supported versions of PHP and database systems (currently MySQL and MariaDB only) are checked. +We use a very wide range of software-combinations to test ARC2. +Currently, all combinations of supported versions of PHP and database systems (currently MySQL and MariaDB only) are checked. -Using a Docker setup for local development allows to switch the backend very easily. So, if a test with a certain DBS/PHP version combination fails on travis, its very likely that you can reproduce it locally. Dont forget to run `composer update` after a switch to make sure appropriate software is used. +Using a Docker setup for local development allows to switch the backend very easily. +So, if a test with a certain DBS/PHP version combination fails, its very likely that you can reproduce it locally. +Dont forget to run `composer update` after a switch to make sure appropriate software is used. diff --git a/docker/ARC2/Dockerfile b/docker/ARC2/Dockerfile index d94216b7..987eaa36 100644 --- a/docker/ARC2/Dockerfile +++ b/docker/ARC2/Dockerfile @@ -1,13 +1,12 @@ -FROM php:7.4-cli +FROM php:8.2-cli RUN apt-get update && apt-get install -y curl git gnupg libicu-dev libzip-dev make nano net-tools zip zlib1g-dev -RUN docker-php-ext-install intl mysqli pdo pdo_mysql zip \ - && docker-php-ext-enable intl mysqli pdo pdo_mysql zip +RUN docker-php-ext-install intl pdo pdo_mysql zip \ + && docker-php-ext-enable intl pdo pdo_mysql zip # install composer globally RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer -RUN composer selfupdate # add custom PHP.ini settings RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini" diff --git a/docker/docker-compose.yml-dist b/docker/docker-compose.yml-dist deleted file mode 100644 index 72069df4..00000000 --- a/docker/docker-compose.yml-dist +++ /dev/null @@ -1,42 +0,0 @@ -version: '2' -services: - db: - image: mysql:5.7 - environment: - MYSQL_DATABASE: arc2 - MYSQL_ROOT_PASSWORD: Pass123 - volumes: - # server is empty at the start because it uses RAM to store data - - data:/var/cache - - data:/var/lib/mysql - # for SQL commands to be run after the server starts - - ./sql:/docker-entrypoint-initdb.d - - phpmyadmin: - image: phpmyadmin/phpmyadmin - links: - - db:mysql - ports: - - 8022:80 - environment: - MYSQL_USERNAME: root - MYSQL_ROOT_PASSWORD: Pass123 - PMA_HOST: db - volumes: - # custom php.ini settings (change upload restrictions) - - ./ARC2/custom.ini:/usr/local/etc/php/conf.d/custom.ini - - arc2: - build: - ./ARC2 - volumes: - - /path/to/arc2:/var/www/html - links: - - db:mysql - command: tail -f /dev/null - -volumes: - data: - driver_opts: - type: tmpfs - device: tmpfs diff --git a/extractors/ARC2_ErdfExtractor.php b/extractors/ARC2_ErdfExtractor.php index 373a3b4c..075164db 100644 --- a/extractors/ARC2_ErdfExtractor.php +++ b/extractors/ARC2_ErdfExtractor.php @@ -69,7 +69,7 @@ public function getNamespaces() public function processNode($n, $ct) { /* context */ - //$ct['lang'] = $this->v('xml:lang', $ct['lang'], $n['a']); + // $ct['lang'] = $this->v('xml:lang', $ct['lang'], $n['a']); $ct['lang'] = ''; $ct['prop_uris'] = $this->getPropertyURIs($n, $ct); $ct['prev_res'] = $ct['cur_res']; diff --git a/extractors/ARC2_PoshRdfExtractor.php b/extractors/ARC2_PoshRdfExtractor.php index e4f486a3..19374cb5 100755 --- a/extractors/ARC2_PoshRdfExtractor.php +++ b/extractors/ARC2_PoshRdfExtractor.php @@ -100,7 +100,7 @@ public function processNode($n, $ct, $level, $pos) /* new s */ if ($this->hasClass($n, 'rdf-s')) { $lct['next_s'] = [$n['a']['class'], $this->getSubject($n, $lct)]; - //echo "\ns: " . print_r($lct['next_s'], 1); + // echo "\ns: " . print_r($lct['next_s'], 1); } /* p */ if ($this->hasClass($n, 'rdf-p') || $this->hasRel($n, 'rdf-p')) { @@ -139,6 +139,7 @@ public function getSubject($n, $ct) return $n['a'][$k]; } } + /* rpointer */ return $ct['base'].'#resource('.$ct['rpointer'].')'; } diff --git a/extractors/ARC2_RDFExtractor.php b/extractors/ARC2_RDFExtractor.php index b703790b..d5f6732c 100644 --- a/extractors/ARC2_RDFExtractor.php +++ b/extractors/ARC2_RDFExtractor.php @@ -178,7 +178,7 @@ public function getPlainContent($n, $trim = 1, $use_img_alt = 1) public function getContent($n, $outer = 0, $trim = 1) { - //echo '
' . htmlspecialchars(print_r($n, 1)) . '
'; + // echo '
' . htmlspecialchars(print_r($n, 1)) . '
'; if ('comment' == $n['tag']) { $r = ''; } elseif ('cdata' == $n['tag']) { @@ -235,7 +235,7 @@ public function normalize($v) $v = preg_replace('/[\W\s]+/is', '_', strip_tags(strtolower($v))); $v = preg_replace('/http/', '', $v); $v = preg_replace('/[\_]+/', '_', $v); - //$v = substr($v, 0, 30); + // $v = substr($v, 0, 30); $v = trim($v, '_'); return $v; diff --git a/extractors/ARC2_RdfaExtractor.php b/extractors/ARC2_RdfaExtractor.php index 8518f2c8..1c17c510 100644 --- a/extractors/ARC2_RdfaExtractor.php +++ b/extractors/ARC2_RdfaExtractor.php @@ -24,12 +24,12 @@ public function __init() public function extractRDF() { - //echo '
' . htmlspecialchars(print_r($this->nodes, 1)) . '
'; + // echo '
' . htmlspecialchars(print_r($this->nodes, 1)) . '
'; if (!isset($this->caller->detected_formats['rdfa'])) { return 0; } $root_node = $this->getRootNode(); - //$base = $this->v('xml:base', $this->getDocBase(), $root_node['a']); + // $base = $this->v('xml:base', $this->getDocBase(), $root_node['a']); $base = $this->getDocBase(); $context = [ 'base' => $base, @@ -68,7 +68,7 @@ public function processNode($n, $ct, $level) $lct['cur_o_res'] = ''; $lct['inco_ts'] = []; $lct['base'] = $ct['base']; - //$lct['base'] = $this->v('xml:base', $ct['base'], $n['a']); + // $lct['base'] = $this->v('xml:base', $ct['base'], $n['a']); /* step 2 */ $lct['ns'] = array_merge($ct['ns'], $this->v('xmlns', [], $n['a'])); /* step 3 */ @@ -90,7 +90,7 @@ public function processNode($n, $ct, $level) $lct['new_s'] = $this->createBnodeID(); } elseif ($ct['p_o']) { $lct['new_s'] = $ct['p_o']; - //$lct['skip'] = 1; + // $lct['skip'] = 1; if (!isset($n['a']['property'])) { $lct['skip'] = 1; } /* patch by masaka */ @@ -183,7 +183,7 @@ public function processNode($n, $ct, $level) } /* step 10 */ if (!$lct['skip'] && ($new_s = $lct['new_s'])) { - //if ($new_s = $lct['new_s']) { + // if ($new_s = $lct['new_s']) { if ($uris = $this->getAttributeURIs($n, $ct, $lct, 'property')) { foreach ($uris as $uri) { $lct['cur_o_lit'] = $this->getCurrentObjectLiteral($n, $lct, $ct); @@ -228,7 +228,7 @@ public function processNode($n, $ct, $level) /* step 12 (11) */ $other = 0; if ($ts_added || $complete_triples || ($lct['new_s'] && !preg_match('/^\_\:/', $lct['new_s'])) || (1 == $other)) { - //if (!$lct['skip'] && ($complete_triples || ($lct['new_s'] && !preg_match('/^\_\:/', $lct['new_s'])))) { + // if (!$lct['skip'] && ($complete_triples || ($lct['new_s'] && !preg_match('/^\_\:/', $lct['new_s'])))) { foreach ($ct['inco_ts'] as $inco_t) { if ('fwd' == $inco_t['dir']) { $this->addT([ @@ -288,7 +288,7 @@ public function getCurrentObjectLiteral($n, $lct, $ct) $xml_val = $this->getContent($n); $plain_val = $this->getPlainContent($n, 0, 0); if (function_exists('html_entity_decode')) { - $plain_val = html_entity_decode($plain_val, ENT_QUOTES); + $plain_val = html_entity_decode($plain_val, \ENT_QUOTES); } $dt = $this->v('datatype', '', $n['a']); list($dt_uri, $sub_v) = $this->xURI($dt, $lct['base'], $lct['ns'], '', $lct); @@ -297,7 +297,7 @@ public function getCurrentObjectLiteral($n, $lct, $ct) if (isset($n['a']['content'])) { $r['value'] = $n['a']['content']; if (function_exists('html_entity_decode')) { - $r['value'] = html_entity_decode($r['value'], ENT_QUOTES); + $r['value'] = html_entity_decode($r['value'], \ENT_QUOTES); } } elseif ($xml_val == $plain_val) { $r['value'] = $plain_val; @@ -314,7 +314,7 @@ public function getCurrentObjectLiteral($n, $lct, $ct) } public function injectXMLDeclarations($val, $ns, $lang) - {//@@todo proper node rebuilding */ + {// @@todo proper node rebuilding */ $lang_code = $lang ? ' xml:lang="'.$lang.'"' : ''; /* ns */ $val = preg_replace('/<([a-z0-9]+)([\>\s])/is', '<\\1 xmlns="http://www.w3.org/1999/xhtml"'.$lang_code.'\\2', $val); diff --git a/parsers/ARC2_AtomParser.php b/parsers/ARC2_AtomParser.php index 5e606e53..0d7feeb6 100644 --- a/parsers/ARC2_AtomParser.php +++ b/parsers/ARC2_AtomParser.php @@ -50,9 +50,9 @@ public function createBnodeID() public function addT($t) { - //if (!isset($t['o_datatype'])) + // if (!isset($t['o_datatype'])) if ($this->skip_dupes) { - //$h = md5(print_r($t, 1)); + // $h = md5(print_r($t, 1)); $h = md5(serialize($t)); if (!isset($this->added_triples[$h])) { $this->triples[$this->t_count] = $t; @@ -83,7 +83,7 @@ public function getSimpleIndex($flatten_objects = 1, $vals = '') public function extractRDF() { $index = $this->getNodeIndex(); - //print_r($index); + // print_r($index); $this->rdf = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'; $this->atom = 'http://www.w3.org/2005/Atom'; $this->rss = 'http://purl.org/rss/1.0/'; @@ -159,7 +159,7 @@ public function extractProps($els, $container) } else {/* qname */ $k = $this->expandPName($tag); } - //echo $k . "\n"; + // echo $k . "\n"; if (('channel' == $container) && ($k == $this->rss.'item')) { continue; } @@ -249,8 +249,8 @@ public function initXMLParser() if (!isset($this->xml_parser)) { $enc = preg_match('/^(utf\-8|iso\-8859\-1|us\-ascii)$/i', $this->getEncoding(), $m) ? $m[1] : 'UTF-8'; $parser = xml_parser_create($enc); - xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 0); - xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); + xml_parser_set_option($parser, \XML_OPTION_SKIP_WHITE, 0); + xml_parser_set_option($parser, \XML_OPTION_CASE_FOLDING, 0); xml_set_element_handler($parser, 'open', 'close'); xml_set_character_data_handler($parser, 'cData'); xml_set_start_namespace_decl_handler($parser, 'nsDecl'); diff --git a/parsers/ARC2_CBJSONParser.php b/parsers/ARC2_CBJSONParser.php index d1cbf5a8..4e1ff586 100755 --- a/parsers/ARC2_CBJSONParser.php +++ b/parsers/ARC2_CBJSONParser.php @@ -4,6 +4,7 @@ * * @author Benjamin Nowack * @license W3C Software License and GPL + * * @homepage * * @version 2010-11-16 @@ -163,7 +164,7 @@ public function extractResourceRDF($struct, $s, $pos = 0) $this->addT($s, 'http://www.w3.org/2000/01/rdf-schema#label', $v, $s_type, $o_type); } /* dc:identifier */ - //if ($k == 'permalink') $this->addT($s, 'http://purl.org/dc/elements/1.1/identifier', $v, $s_type, $o_type); + // if ($k == 'permalink') $this->addT($s, 'http://purl.org/dc/elements/1.1/identifier', $v, $s_type, $o_type); } /* structured, single v */ elseif (!$this->isFlatArray($v)) { @@ -318,7 +319,7 @@ public function extractUpdatedAtRDF($s, $s_type, $v) public function getAPIDateXSD($val) { - //Fri Jan 16 21:11:48 UTC 2009 + // Fri Jan 16 21:11:48 UTC 2009 if (preg_match('/^[a-z]+ ([a-z]+) ([0-9]+) ([0-9]{2}\:[0-9]{2}\:[0-9]{2}) UTC ([0-9]{4})/i', $val, $m)) { $months = ['Jan' => '01', 'Feb' => '02', 'Mar' => '03', 'Apr' => '04', 'May' => '05', 'Jun' => '06', 'Jul' => '07', 'Aug' => '08', 'Sep' => '09', 'Oct' => '10', 'Nov' => '11', 'Dec' => '12']; @@ -334,7 +335,7 @@ public function inferDate($prefix, $s, $struct) $r = ''; foreach (['year', 'month', 'day'] as $suffix) { $val = $this->v1($prefix.'_'.$suffix, '00', $struct); - $r .= ($r ? '-' : '').str_pad($val, 2, '0', STR_PAD_LEFT); + $r .= ($r ? '-' : '').str_pad($val, 2, '0', \STR_PAD_LEFT); } if ('00-00-00' != $r) { $this->addT($s, $this->getPropertyURI($prefix.'_date'), $r, $s_type, 'literal'); diff --git a/parsers/ARC2_JSONParser.php b/parsers/ARC2_JSONParser.php index 28021475..bafb335b 100755 --- a/parsers/ARC2_JSONParser.php +++ b/parsers/ARC2_JSONParser.php @@ -5,6 +5,7 @@ * * @author Benjamin Nowack * @license W3C Software License and GPL + * * @homepage * * @version 2010-11-16 @@ -135,7 +136,7 @@ public function extractValue($v) $val = preg_replace_callback('/\\\u(.{4})/', function ($matches) { return chr(hexdec($matches[1])); }, $val); - //$val = preg_replace_callback('/\\\u00(.{2})', function($matches) { return rawurldecode("%" . $matches[1]); }, $val); + // $val = preg_replace_callback('/\\\u00(.{2})', function($matches) { return rawurldecode("%" . $matches[1]); }, $val); /* other escaped chars */ $from = ['\\\\', '\r', '\t', '\n', '\"', '\b', '\f', '\/']; $to = ['\\', "\r", "\t", "\n", '"', "\b", "\f", '/']; @@ -166,7 +167,7 @@ public function countTriples() public function addT($s = '', $p = '', $o = '', $s_type = '', $o_type = '', $o_dt = '', $o_lang = '') { $o = $this->toUTF8($o); - //echo str_replace($this->base, '', "-----\n adding $s / $p / $o\n-----\n"); + // echo str_replace($this->base, '', "-----\n adding $s / $p / $o\n-----\n"); $t = ['s' => $s, 'p' => $p, 'o' => $o, 's_type' => $s_type, 'o_type' => $o_type, 'o_datatype' => $o_dt, 'o_lang' => $o_lang]; if ($this->skip_dupes) { $h = md5(serialize($t)); diff --git a/parsers/ARC2_LegacyXMLParser.php b/parsers/ARC2_LegacyXMLParser.php index 817e9795..43eae055 100644 --- a/parsers/ARC2_LegacyXMLParser.php +++ b/parsers/ARC2_LegacyXMLParser.php @@ -78,7 +78,7 @@ public function parse($path, $data = '', $iso_fallback = false) } $first = false; } - $this->target_encoding = xml_parser_get_option($this->xml_parser, XML_OPTION_TARGET_ENCODING); + $this->target_encoding = xml_parser_get_option($this->xml_parser, \XML_OPTION_TARGET_ENCODING); xml_parser_free($this->xml_parser); $this->reader->closeStream(); unset($this->reader); @@ -143,7 +143,7 @@ public function getSubNodes($n) public function getNodeContent($n, $outer = 0, $trim = 1) { - //echo '
' . htmlspecialchars(print_r($n, 1)) . '
'; + // echo '
' . htmlspecialchars(print_r($n, 1)) . '
'; if ('cdata' == $n['tag']) { $r = $n['a']['value']; } else { @@ -203,8 +203,8 @@ public function initXMLParser() if (!isset($this->xml_parser)) { $enc = preg_match('/^(utf\-8|iso\-8859\-1|us\-ascii)$/i', $this->getEncoding(), $m) ? $m[1] : 'UTF-8'; $parser = xml_parser_create_ns($enc, ''); - xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 0); - xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); + xml_parser_set_option($parser, \XML_OPTION_SKIP_WHITE, 0); + xml_parser_set_option($parser, \XML_OPTION_CASE_FOLDING, 0); xml_set_element_handler($parser, 'open', 'close'); xml_set_character_data_handler($parser, 'cData'); xml_set_start_namespace_decl_handler($parser, 'nsDecl'); @@ -216,8 +216,8 @@ public function initXMLParser() public function open($p, $t, $a) { $t_exact = $t; - //echo "
\n".'opening '.$t . ' ' . print_r($a, 1); flush(); - //echo "
\n".'opening '.$t; flush(); + // echo "
\n".'opening '.$t . ' ' . print_r($a, 1); flush(); + // echo "
\n".'opening '.$t; flush(); $t = strpos($t, ':') ? $t : strtolower($t); /* base check */ $base = ''; @@ -234,7 +234,7 @@ public function open($p, $t, $a) /* ns */ if ($a) { foreach ($a as $k => $v) { - if (0 === strpos($k, 'xmlns')) { + if (str_starts_with($k, 'xmlns')) { $this->nsDecl($p, trim(substr($k, 5), ':'), $v); } } @@ -264,7 +264,7 @@ public function open($p, $t, $a) } elseif ($prev_node['level'] > $l) { while ($prev_node['level'] > $l) { if (!isset($this->nodes[$prev_node['p_id']])) { - //$this->addError('nesting mismatch: tag is ' . $t . ', level is ' . $l . ', prev_level is ' . $prev_node['level'] . ', prev_node p_id is ' . $prev_node['p_id']); + // $this->addError('nesting mismatch: tag is ' . $t . ', level is ' . $l . ', prev_level is ' . $prev_node['level'] . ', prev_node p_id is ' . $prev_node['p_id']); break; } $prev_node = $this->nodes[$prev_node['p_id']]; @@ -281,7 +281,7 @@ public function open($p, $t, $a) public function close($p, $t, $empty = 0) { - //echo "
\n".'closing '.$t; flush(); + // echo "
\n".'closing '.$t; flush(); $node = $this->getCurNode($t); $node['state'] = 'closed'; $node['empty'] = $empty; @@ -291,7 +291,7 @@ public function close($p, $t, $empty = 0) public function cData($p, $d) { - //echo trim($d) ? "
\n".'cdata: ' . $d : ''; flush(); + // echo trim($d) ? "
\n".'cdata: ' . $d : ''; flush(); $node = $this->getCurNode(); if ('open' == $node['state']) { $node['cdata'] .= $d; diff --git a/parsers/ARC2_RDFParser.php b/parsers/ARC2_RDFParser.php index 75902f16..bda7d3d9 100755 --- a/parsers/ARC2_RDFParser.php +++ b/parsers/ARC2_RDFParser.php @@ -4,6 +4,7 @@ * * @author Benjamin Nowack * @license W3C Software License and GPL + * * @homepage * * @version 2010-11-16 @@ -12,6 +13,26 @@ class ARC2_RDFParser extends ARC2_Class { + /** + * @var array + */ + public array $added_triples; + + public int $bnode_id; + public string $bnode_prefix; + + public string $format; + public int $keep_time_limit; + public object $parser; + public object $reader; + public $skip_dupes; + public int $t_count; + + /** + * @var array + */ + public array $triples; + public function __construct($a, &$caller) { parent::__construct($a, $caller); diff --git a/parsers/ARC2_RDFXMLParser.php b/parsers/ARC2_RDFXMLParser.php index 02e8d6c6..961648a0 100644 --- a/parsers/ARC2_RDFXMLParser.php +++ b/parsers/ARC2_RDFXMLParser.php @@ -4,12 +4,38 @@ * * @author Benjamin Nowack * @license W3C Software License and GPL + * * @homepage */ ARC2::inc('RDFParser'); class ARC2_RDFXMLParser extends ARC2_RDFParser { + /** + * @var string|false + */ + public $encoding; + public string $rdf; + + public int $s_count = 0; + + /** + * @var array + */ + public array $s_stack; + + public int $state; + + /** + * @var string|false + */ + public $target_encoding; + public string $tmp_error; + public string $x_base; + public string $x_lang; + public string $xml; + public object $xml_parser; + public function __construct($a, &$caller) { parent::__construct($a, $caller); @@ -46,7 +72,7 @@ public function parse($path, $data = '', $iso_fallback = false) $first = true; while ($d = $this->reader->readStream()) { if (!$this->keep_time_limit) { - @set_time_limit($this->v('time_limit', 60, $this->a)); + set_time_limit($this->v('time_limit', 60, $this->a)); } if ($iso_fallback && $first) { $d = ''."\n".preg_replace('/^\<\?xml [^\>]+\?\>\s*/s', '', $d); @@ -71,7 +97,7 @@ public function parse($path, $data = '', $iso_fallback = false) } } } - $this->target_encoding = xml_parser_get_option($this->xml_parser, XML_OPTION_TARGET_ENCODING); + $this->target_encoding = xml_parser_get_option($this->xml_parser, \XML_OPTION_TARGET_ENCODING); xml_parser_free($this->xml_parser); $this->reader->closeStream(); unset($this->reader); @@ -84,8 +110,8 @@ public function initXMLParser() if (!isset($this->xml_parser)) { $enc = preg_match('/^(utf\-8|iso\-8859\-1|us\-ascii)$/i', $this->getEncoding(), $m) ? $m[1] : 'UTF-8'; $parser = xml_parser_create_ns($enc, ''); - xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 0); - xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); + xml_parser_set_option($parser, \XML_OPTION_SKIP_WHITE, 0); + xml_parser_set_option($parser, \XML_OPTION_CASE_FOLDING, 0); xml_set_element_handler($parser, 'open', 'close'); xml_set_character_data_handler($parser, 'cdata'); xml_set_start_namespace_decl_handler($parser, 'nsDecl'); @@ -162,7 +188,7 @@ public function getParentXLang() public function addT($s, $p, $o, $s_type, $o_type, $o_dt = '', $o_lang = '') { - //echo "-----\nadding $s / $p / $o\n-----\n"; + // echo "-----\nadding $s / $p / $o\n-----\n"; $t = ['s' => $s, 'p' => $p, 'o' => $o, 's_type' => $s_type, 'o_type' => $o_type, 'o_datatype' => $o_dt, 'o_lang' => $o_lang]; if ($this->skip_dupes) { $h = md5(serialize($t)); @@ -187,43 +213,43 @@ public function reify($t, $s, $p, $o, $s_type, $o_type, $o_dt = '', $o_lang = '' public function open($p, $t, $a) { - //echo "state is $this->state\n"; - //echo "opening $t\n"; + // echo "state is $this->state\n"; + // echo "opening $t\n"; switch ($this->state) { - case 0: return $this->h0Open($t, $a); - case 1: return $this->h1Open($t, $a); - case 2: return $this->h2Open($t, $a); - case 4: return $this->h4Open($t, $a); - case 5: return $this->h5Open($t, $a); - case 6: return $this->h6Open($t, $a); - default: $this->addError('open() called at state '.$this->state.' in '.$t); - } + case 0: return $this->h0Open($t, $a); + case 1: return $this->h1Open($t, $a); + case 2: return $this->h2Open($t, $a); + case 4: return $this->h4Open($t, $a); + case 5: return $this->h5Open($t, $a); + case 6: return $this->h6Open($t, $a); + default: $this->addError('open() called at state '.$this->state.' in '.$t); + } } public function close($p, $t) { - //echo "state is $this->state\n"; - //echo "closing $t\n"; + // echo "state is $this->state\n"; + // echo "closing $t\n"; switch ($this->state) { - case 1: return $this->h1Close($t); - case 2: return $this->h2Close($t); - case 3: return $this->h3Close($t); - case 4: return $this->h4Close($t); - case 5: return $this->h5Close($t); - case 6: return $this->h6Close($t); - default: $this->addError('close() called at state '.$this->state.' in '.$t); - } + case 1: return $this->h1Close($t); + case 2: return $this->h2Close($t); + case 3: return $this->h3Close($t); + case 4: return $this->h4Close($t); + case 5: return $this->h5Close($t); + case 6: return $this->h6Close($t); + default: $this->addError('close() called at state '.$this->state.' in '.$t); + } } public function cdata($p, $d) { - //echo "state is $this->state\n"; - //echo "cdata\n"; + // echo "state is $this->state\n"; + // echo "cdata\n"; switch ($this->state) { - case 4: return $this->h4Cdata($d); - case 6: return $this->h6Cdata($d); - default: return false; - } + case 4: return $this->h4Cdata($d); + case 6: return $this->h6Cdata($d); + default: return false; + } } public function nsDecl($p, $prf, $uri) @@ -303,7 +329,7 @@ public function h1Open($t, $a) } /* any other attrs (skip rdf and xml, except rdf:_, rdf:value, rdf:Seq) */ foreach ($a as $k => $v) { - if (((false === strpos($k, $this->xml)) && (false === strpos($k, $this->rdf))) || preg_match('/(\_[0-9]+|value|Seq|Bag|Alt|Statement|Property|List)$/', $k)) { + if (((!str_contains($k, $this->xml)) && (!str_contains($k, $this->rdf))) || preg_match('/(\_[0-9]+|value|Seq|Bag|Alt|Statement|Property|List)$/', $k)) { if (strpos($k, ':')) { $this->addT($s['value'], $k, $v, $s['type'], 'literal', '', $s['x_lang']); } @@ -407,7 +433,7 @@ public function h2Open($t, $a) } /* any other attrs (skip rdf and xml) */ foreach ($a as $k => $v) { - if (((false === strpos($k, $this->xml)) && (false === strpos($k, $this->rdf))) || preg_match('/(\_[0-9]+|value)$/', $k)) { + if (((!str_contains($k, $this->xml)) && (!str_contains($k, $this->rdf))) || preg_match('/(\_[0-9]+|value)$/', $k)) { if (strpos($k, ':')) { if (!$o['value']) { $o['value'] = $this->createBnodeID(); @@ -452,7 +478,7 @@ public function h6Open($t, $a) $name = $parts[1]; if (!isset($this->nsp[$ns_uri])) { foreach ($this->nsp as $tmp1 => $tmp2) { - if (0 === strpos($t, $tmp1)) { + if (str_starts_with($t, $tmp1)) { $ns_uri = $tmp1; $name = substr($t, strlen($tmp1)); break; @@ -524,7 +550,7 @@ public function h4Close($t) if (isset($s['is_coll']) && $s['is_coll']) { $this->addT($s['value'], $this->rdf.'rest', $this->rdf.'nil', $s['type'], 'uri'); /* back to collection start */ - while ((!isset($s['p']) || ($s['p'] != $t))) { + while (!isset($s['p']) || ($s['p'] != $t)) { $sub_s = $s; $this->popS(); $s = $this->getParentS(); @@ -581,7 +607,7 @@ public function h6Close($t) $name = $parts[1]; if (!isset($this->nsp[$ns_uri])) { foreach ($this->nsp as $tmp1 => $tmp2) { - if (0 === strpos($t, $tmp1)) { + if (str_starts_with($t, $tmp1)) { $ns_uri = $tmp1; $name = substr($t, strlen($tmp1)); break; @@ -613,7 +639,7 @@ public function h6Cdata($d) { if ($s = $this->getParentS()) { if (isset($s['o_xml_data']) || preg_match("/[\n\r]/", $d) || trim($d)) { - $d = htmlspecialchars($d, ENT_NOQUOTES); + $d = htmlspecialchars($d, \ENT_NOQUOTES); $s['o_xml_data'] = isset($s['o_xml_data']) ? $s['o_xml_data'].$d : $d; } $this->updateS($s); diff --git a/parsers/ARC2_RSSParser.php b/parsers/ARC2_RSSParser.php index b22c5218..2b950e63 100644 --- a/parsers/ARC2_RSSParser.php +++ b/parsers/ARC2_RSSParser.php @@ -50,7 +50,7 @@ public function createBnodeID() public function addT($t) { - //if (!isset($t['o_datatype'])) + // if (!isset($t['o_datatype'])) if ($this->skip_dupes) { $h = md5(serialize($t)); if (!isset($this->added_triples[$h])) { diff --git a/parsers/ARC2_SGAJSONParser.php b/parsers/ARC2_SGAJSONParser.php index 71357e08..ffb634af 100755 --- a/parsers/ARC2_SGAJSONParser.php +++ b/parsers/ARC2_SGAJSONParser.php @@ -12,6 +12,13 @@ class: ARC2 SG API JSON Parser class ARC2_SGAJSONParser extends ARC2_JSONParser { + public string $rdf; + + /** + * @var array + */ + public array $struct; + public function __construct($a, &$caller) { parent::__construct($a, $caller); diff --git a/parsers/ARC2_SPARQLParser.php b/parsers/ARC2_SPARQLParser.php index f34a537a..da88e4af 100644 --- a/parsers/ARC2_SPARQLParser.php +++ b/parsers/ARC2_SPARQLParser.php @@ -4,6 +4,7 @@ * * @author Benjamin Nowack * @license W3C Software License and GPL + * * @homepage * * @version 2010-11-16 @@ -12,6 +13,11 @@ class ARC2_SPARQLParser extends ARC2_TurtleParser { + /** + * @var array + */ + public array $bnode_pattern_index; + public function __construct($a, &$caller) { parent::__construct($a, $caller); @@ -673,7 +679,7 @@ public function xRelationalExpression($v) $sub_v = $sub_r[2]; $r['operator'] = $op; if ((list($sub_r, $sub_v) = $this->xAdditiveExpression($sub_v)) && $sub_r) { - //$sub_r['operator'] = $op; + // $sub_r['operator'] = $op; $r['patterns'][] = $sub_r; $proceed = 1; } @@ -707,7 +713,8 @@ public function xAdditiveExpression($v) } } } while ($proceed); - //return array($r, $sub_v); + + // return array($r, $sub_v); return 1 == count($r['patterns']) ? [$r['patterns'][0], $sub_v] : [$r, $sub_v]; } diff --git a/parsers/ARC2_SPARQLXMLResultParser.php b/parsers/ARC2_SPARQLXMLResultParser.php index 480a146a..52423052 100644 --- a/parsers/ARC2_SPARQLXMLResultParser.php +++ b/parsers/ARC2_SPARQLXMLResultParser.php @@ -12,6 +12,15 @@ class: ARC2 SPARQL Result XML Parser class ARC2_SPARQLXMLResultParser extends ARC2_LegacyXMLParser { + public int $allowCDataNodes; + + /** + * @var array + */ + public array $nodes; + public string $srx; + public string $xml; + public function __construct($a, &$caller) { parent::__construct($a, $caller); diff --git a/parsers/ARC2_SPOGParser.php b/parsers/ARC2_SPOGParser.php index de6bed69..258d60a7 100755 --- a/parsers/ARC2_SPOGParser.php +++ b/parsers/ARC2_SPOGParser.php @@ -4,6 +4,7 @@ * * @author Benjamin Nowack * @license W3C Software License and GPL + * * @homepage * * @version 2010-11-16 @@ -12,6 +13,23 @@ class ARC2_SPOGParser extends ARC2_RDFParser { + public string $binding; + public $encoding; + public int $prev_state; + public string $rdf; + public int $state; + + /** + * @var array + */ + public array $t; + public string $target_encoding; + public string $tmp_error; + public $x_base; + public string $xml; + public $xml_parser; + public string $xsd; + public function __construct($a, &$caller) { parent::__construct($a, $caller); @@ -67,7 +85,7 @@ public function parse($path, $data = '', $iso_fallback = false) } } } - $this->target_encoding = xml_parser_get_option($this->xml_parser, XML_OPTION_TARGET_ENCODING); + $this->target_encoding = xml_parser_get_option($this->xml_parser, \XML_OPTION_TARGET_ENCODING); xml_parser_free($this->xml_parser); $this->reader->closeStream(); unset($this->reader); @@ -80,8 +98,8 @@ public function initXMLParser() if (!isset($this->xml_parser)) { $enc = preg_match('/^(utf\-8|iso\-8859\-1|us\-ascii)$/i', $this->getEncoding(), $m) ? $m[1] : 'UTF-8'; $parser = xml_parser_create($enc); - xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 0); - xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); + xml_parser_set_option($parser, \XML_OPTION_SKIP_WHITE, 0); + xml_parser_set_option($parser, \XML_OPTION_CASE_FOLDING, 0); xml_set_element_handler($parser, 'open', 'close'); xml_set_character_data_handler($parser, 'cdata'); xml_set_start_namespace_decl_handler($parser, 'nsDecl'); @@ -118,7 +136,7 @@ public function addT($s = '', $p = '', $o = '', $s_type = '', $o_type = '', $o_d if (!($s && $p && $o)) { return 0; } - //echo "-----\nadding $s / $p / $o\n-----\n"; + // echo "-----\nadding $s / $p / $o\n-----\n"; $t = ['s' => $s, 'p' => $p, 'o' => $o, 's_type' => $s_type, 'o_type' => $o_type, 'o_datatype' => $o_dt, 'o_lang' => $o_lang, 'g' => $g]; if ($this->skip_dupes) { $h = md5(serialize($t)); @@ -159,15 +177,15 @@ public function close($p, $t) $this->state = ''; if ('result' == $t) { $this->addT( - $this->v('s', '', $this->t), - $this->v('p', '', $this->t), - $this->v('o', '', $this->t), - $this->v('s_type', '', $this->t), - $this->v('o_type', '', $this->t), - $this->v('o_dt', '', $this->t), - $this->v('o_lang', '', $this->t), - $this->v('g', '', $this->t) - ); + $this->v('s', '', $this->t), + $this->v('p', '', $this->t), + $this->v('o', '', $this->t), + $this->v('s_type', '', $this->t), + $this->v('o_type', '', $this->t), + $this->v('o_dt', '', $this->t), + $this->v('o_lang', '', $this->t), + $this->v('g', '', $this->t) + ); } } diff --git a/parsers/ARC2_SemHTMLParser.php b/parsers/ARC2_SemHTMLParser.php index dccc4476..effed8e8 100644 --- a/parsers/ARC2_SemHTMLParser.php +++ b/parsers/ARC2_SemHTMLParser.php @@ -12,6 +12,58 @@ class: ARC2 RDF/XML Parser class ARC2_SemHTMLParser extends ARC2_LegacyXMLParser { + /** + * @var array + */ + public array $added_triples; + public int $auto_extract; + public int $bnode_id; + public string $bnode_prefix; + + /** + * @var array + */ + public array $cache; + + public string $cur_tag; + + public string $default_sem_html_formats; + + /** + * @var array + */ + public array $detected_formats; + + public string $doc_url; + + /** + * @var array + */ + public array $extracted_formats; + + public int $keep_cdata_ws; + + public int $level; + public int $node_count; + public $node_index; + + /** + * @var array + */ + public array $nodes; + + public $reader; + public $skip_dupes; + public int $t_count; + public string $target_encoding; + + /** + * @var array + */ + public array $triples; + + public string $x_base; + public function __construct($a, &$caller) { parent::__construct($a, $caller); diff --git a/parsers/ARC2_TurtleParser.php b/parsers/ARC2_TurtleParser.php index 4614d267..80b247b2 100644 --- a/parsers/ARC2_TurtleParser.php +++ b/parsers/ARC2_TurtleParser.php @@ -4,6 +4,7 @@ * * @author Benjamin Nowack * @license W3C Software License and GPL + * * @homepage * * @version 2010-11-16 @@ -12,6 +13,24 @@ class ARC2_TurtleParser extends ARC2_RDFParser { + public int $max_parsing_loops; + + /** + * @var array + */ + public array $prefixes; + + /** + * @var array + */ + public array $r; + + public string $rdf; + public int $state; + public string $unparsed_code; + public string $xml; + public string $xsd; + public function __construct($a, &$caller) { parent::__construct($a, $caller); @@ -37,7 +56,7 @@ public function x($re, $v, $options = 'si') } return ARC2::x($re, $v, $options); - //$this->unparsed_code = ($sub_r && count($sub_r)) ? $sub_r[count($sub_r) - 1] : ''; + // $this->unparsed_code = ($sub_r && count($sub_r)) ? $sub_r[count($sub_r) - 1] : ''; } public function createBnodeID() @@ -647,7 +666,7 @@ public function xPrefixedName($v) return [0, $v]; } - /* 69.., 73.., 93, 94.. */ + /* 69.., 73.., 93, 94.. */ public function xBlankNode($v) { @@ -665,7 +684,7 @@ public function xBlankNode($v) public function xIRI_REF($v) { - //if ($r = $this->x('\<([^\<\>\"\{\}\|\^\'[:space:]]*)\>', $v)) { + // if ($r = $this->x('\<([^\<\>\"\{\}\|\^\'[:space:]]*)\>', $v)) { if (($r = $this->x('\<(\$\{[^\>]*\})\>', $v)) && ($sub_r = $this->xPlaceholder($r[1]))) { return [$r[1], $r[2]]; } elseif ($r = $this->x('\<\>', $v)) { @@ -895,14 +914,14 @@ public function xPN_LOCAL($v) public function unescapeNtripleUTF($v) { - if (false === strpos($v, '\\')) { + if (!str_contains($v, '\\')) { return $v; } $mappings = ['t' => "\t", 'n' => "\n", 'r' => "\r", '\"' => '"', '\'' => "'"]; foreach ($mappings as $in => $out) { $v = preg_replace('/\x5c(['.$in.'])/', $out, $v); } - if (false === strpos(strtolower($v), '\u')) { + if (!str_contains(strtolower($v), '\u')) { return $v; } while (preg_match('/\\\(U)([0-9A-F]{8})/', $v, $m) || preg_match('/\\\(u)([0-9A-F]{4})/', $v, $m)) { @@ -926,9 +945,9 @@ public function unescapeNtripleUTF($v) public function xPlaceholder($v) { - //if ($r = $this->x('(\?|\$)\{([^\}]+)\}', $v)) { + // if ($r = $this->x('(\?|\$)\{([^\}]+)\}', $v)) { if ($r = $this->x('(\?|\$)', $v)) { - if (preg_match('/(\{(?:[^{}]+|(?R))*\})/', $r[2], $m) && 0 === strpos(trim($r[2]), $m[1])) { + if (preg_match('/(\{(?:[^{}]+|(?R))*\})/', $r[2], $m) && str_starts_with(trim($r[2]), $m[1])) { $ph = substr($m[1], 1, -1); $rest = substr(trim($r[2]), strlen($m[1])); if (!isset($this->r['placeholders'])) { diff --git a/phpunit.xml b/phpunit.xml index af795381..487fa494 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,35 +1,23 @@ - - - - - - - - - ./tests - - - - - ./extractors - ./parsers - ./serializers - ./sparqlscript - ./src - ./store - - + + + + ./extractors + ./parsers + ./serializers + ./sparqlscript + ./src + ./store + + + + + + + + + + ./tests + + diff --git a/serializers/ARC2_JSONLDSerializer.php b/serializers/ARC2_JSONLDSerializer.php index 4ecde6e0..b0fd2ae1 100644 --- a/serializers/ARC2_JSONLDSerializer.php +++ b/serializers/ARC2_JSONLDSerializer.php @@ -4,12 +4,15 @@ * * @author John Walker * @license W3C Software License and GPL + * * @homepage */ ARC2::inc('RDFSerializer'); class ARC2_JSONLDSerializer extends ARC2_RDFSerializer { + public string $content_header; + public function __construct($a, &$caller) { parent::__construct($a, $caller); @@ -64,7 +67,7 @@ public function getSerializedIndex($index, $raw = 0) foreach ($index as $s => $ps) { $r .= $r ? ','.$nl.$nl : ''; $r .= ' { '.$nl.' "@id" : '.$this->getTerm($s); - //$first_p = 1; + // $first_p = 1; foreach ($ps as $p => $os) { $r .= ','.$nl; $r .= ' '.$this->getTerm($p).' : ['; diff --git a/serializers/ARC2_LegacyHTMLSerializer.php b/serializers/ARC2_LegacyHTMLSerializer.php index ce2ae2cd..0c2f1682 100755 --- a/serializers/ARC2_LegacyHTMLSerializer.php +++ b/serializers/ARC2_LegacyHTMLSerializer.php @@ -12,6 +12,8 @@ class: ARC2 Legacy XML Serializer class ARC2_LegacyHTMLSerializer extends ARC2_Class { + public string $content_header; + public function __construct($a, &$caller) { parent::__construct($a, $caller); @@ -87,7 +89,7 @@ public function getSerializedNode($index, $node, $level = 0, $raw = 0) $r .= $this->getSerializedNode($index, $sub_node, $level + 1, 1); } /* close tag */ - //$r .= str_pad("\n", $level + 1, " ") . ''; + // $r .= str_pad("\n", $level + 1, " ") . ''; $r .= ''; if (preg_match('/^(div|form|p|section)$/', $tag)) { $r .= str_pad("\n", $level + 1, ' '); diff --git a/serializers/ARC2_LegacyJSONSerializer.php b/serializers/ARC2_LegacyJSONSerializer.php index 6d0a04f3..86a7d838 100755 --- a/serializers/ARC2_LegacyJSONSerializer.php +++ b/serializers/ARC2_LegacyJSONSerializer.php @@ -12,6 +12,8 @@ class: ARC2 Legacy JSON Serializer class ARC2_LegacyJSONSerializer extends ARC2_Class { + public string $content_header; + public function __construct($a, &$caller) { parent::__construct($a, $caller); diff --git a/serializers/ARC2_LegacyXMLSerializer.php b/serializers/ARC2_LegacyXMLSerializer.php index ee07ad63..415e3a0e 100755 --- a/serializers/ARC2_LegacyXMLSerializer.php +++ b/serializers/ARC2_LegacyXMLSerializer.php @@ -12,6 +12,8 @@ class: ARC2 Legacy XML Serializer class ARC2_LegacyXMLSerializer extends ARC2_Class { + public string $content_header; + public function __construct($a, &$caller) { parent::__construct($a, $caller); diff --git a/serializers/ARC2_MicroRDFSerializer.php b/serializers/ARC2_MicroRDFSerializer.php index d8afc0ce..944aea18 100755 --- a/serializers/ARC2_MicroRDFSerializer.php +++ b/serializers/ARC2_MicroRDFSerializer.php @@ -4,6 +4,7 @@ * * @author Benjamin Nowack * @license W3C Software License and GPL + * * @homepage * * @version 2010-11-16 @@ -12,6 +13,9 @@ class ARC2_MicroRDFSerializer extends ARC2_RDFSerializer { + public string $content_header; + public $label_store; + public function __construct($a, &$caller) { parent::__construct($a, $caller); @@ -50,7 +54,7 @@ public function getSerializedIndex($index, $res = '') if ($res) { $index = [$res => $index[$res]]; } - //return Trice::dump($index); + // return Trice::dump($index); $types = $this->v($this->expandPName('rdf:type'), [], $index); $main_type = $types ? $types[0]['value'] : ''; foreach ($index as $s => $ps) { @@ -128,8 +132,8 @@ public function getURIObjectValue($o, $p) } return ''.$label.''; - //$label = $o['value']; - //$label = preg_replace('/^https?\:\/\/(www\.)?/', '', $label); + // $label = $o['value']; + // $label = preg_replace('/^https?\:\/\/(www\.)?/', '', $label); } public function getBNodeObjectValue($o, $p) diff --git a/serializers/ARC2_NTriplesSerializer.php b/serializers/ARC2_NTriplesSerializer.php index 1a52b75c..6e1652d2 100644 --- a/serializers/ARC2_NTriplesSerializer.php +++ b/serializers/ARC2_NTriplesSerializer.php @@ -4,12 +4,20 @@ * * @author Benjamin Nowack * @license W3C Software License and GPL + * * @homepage */ ARC2::inc('RDFSerializer'); class ARC2_NTriplesSerializer extends ARC2_RDFSerializer { + /** + * @var array + */ + public array $esc_chars; + + public int $raw; + public function __construct($a, &$caller) { parent::__construct($a, $caller); @@ -38,6 +46,7 @@ public function getTerm($v, $term = '') if (in_array($term, ['s', 'p'])) { return $this->getTerm(['value' => $v, 'type' => 'uri']); } + // assume literal return $this->getTerm(['type' => 'literal', 'value' => $v]); } @@ -69,7 +78,7 @@ public function getTerm($v, $term = '') } $suffix = isset($v['lang']) && $v['lang'] ? '@'.$v['lang'] : ''; $suffix = isset($v['datatype']) && $v['datatype'] ? '^^'.$this->getTerm($v['datatype']) : $suffix; - //return $quot . "object" . utf8_encode($v['value']) . $quot . $suffix; + return $quot.$this->escape($v['value']).$quot.$suffix; } @@ -100,7 +109,9 @@ public function escape($v) { $r = ''; // decode, if possible - $v = (false === strpos(utf8_decode(str_replace('?', '', $v)), '?')) ? utf8_decode($v) : $v; + $str = str_replace('?', '', $v); + $str = mb_convert_encoding($str, 'ISO-8859-1', 'UTF-8'); + $v = (false === str_contains($str, '?')) ? mb_convert_encoding($v, 'ISO-8859-1', 'UTF-8') : $v; if ($this->raw) { return $v; } // no further escaping wanted @@ -130,7 +141,7 @@ public function escapeChars($matches) elseif (function_exists('json_encode')) { $r = json_encode($v); if ('null' == $r) { - $r = json_encode(utf8_encode($v)); + $r = json_encode(mb_convert_encoding($v, 'UTF-8', mb_list_encodings())); } // remove boundary quotes if ('"' == substr($r, 0, 1)) { @@ -163,29 +174,29 @@ public function escapeChars($matches) public function getCharNo($c, $is_encoded = false) { - $c_utf = $is_encoded ? $c : utf8_encode($c); + $c_utf = $is_encoded ? $c : mb_convert_encoding($c, 'UTF-8', mb_list_encodings()); $bl = strlen($c_utf); /* binary length */ $r = 0; switch ($bl) { - case 1:/* 0####### (0-127) */ - $r = ord($c_utf); - break; - case 2:/* 110##### 10###### = 192+x 128+x */ - $r = ((ord($c_utf[0]) - 192) * 64) + (ord($c_utf[1]) - 128); - break; - case 3:/* 1110#### 10###### 10###### = 224+x 128+x 128+x */ - $r = ((ord($c_utf[0]) - 224) * 4096) + ((ord($c_utf[1]) - 128) * 64) + (ord($c_utf[2]) - 128); - break; - case 4:/* 1111#### 10###### 10###### 10###### = 240+x 128+x 128+x 128+x */ - $r = ((ord($c_utf[0]) - 240) * 262144) + ((ord($c_utf[1]) - 128) * 4096) + ((ord($c_utf[2]) - 128) * 64) + (ord($c_utf[3]) - 128); - break; - } + case 1:/* 0####### (0-127) */ + $r = ord($c_utf); + break; + case 2:/* 110##### 10###### = 192+x 128+x */ + $r = ((ord($c_utf[0]) - 192) * 64) + (ord($c_utf[1]) - 128); + break; + case 3:/* 1110#### 10###### 10###### = 224+x 128+x 128+x */ + $r = ((ord($c_utf[0]) - 224) * 4096) + ((ord($c_utf[1]) - 128) * 64) + (ord($c_utf[2]) - 128); + break; + case 4:/* 1111#### 10###### 10###### 10###### = 240+x 128+x 128+x 128+x */ + $r = ((ord($c_utf[0]) - 240) * 262144) + ((ord($c_utf[1]) - 128) * 4096) + ((ord($c_utf[2]) - 128) * 64) + (ord($c_utf[3]) - 128); + break; + } return $r; } public function getEscapedChar($c, $no) - {/*see http://www.w3.org/TR/rdf-testcases/#ntrip_strings */ + {/* see http://www.w3.org/TR/rdf-testcases/#ntrip_strings */ if ($no < 9) { return '\\u'.sprintf('%04X', $no); } /* #x0-#x8 (0-8) */ diff --git a/serializers/ARC2_POSHRDFSerializer.php b/serializers/ARC2_POSHRDFSerializer.php index 472d46f1..71aa59e5 100755 --- a/serializers/ARC2_POSHRDFSerializer.php +++ b/serializers/ARC2_POSHRDFSerializer.php @@ -12,6 +12,8 @@ class: ARC2 POSH RDF Serializer class ARC2_POSHRDFSerializer extends ARC2_RDFSerializer { + public string $content_header; + public function __construct($a, &$caller) { parent::__construct($a, $caller); @@ -47,7 +49,7 @@ public function getSerializedIndex($index, $res = '') if ($res) { $index = [$res => $index[$res]]; } - //return Trice::dump($index); + // return Trice::dump($index); foreach ($index as $s => $ps) { /* node */ $r .= ' diff --git a/serializers/ARC2_RDFJSONSerializer.php b/serializers/ARC2_RDFJSONSerializer.php index 3997a55e..210eb552 100644 --- a/serializers/ARC2_RDFJSONSerializer.php +++ b/serializers/ARC2_RDFJSONSerializer.php @@ -4,12 +4,15 @@ * * @author Benjamin Nowack * @license W3C Software License and GPL + * * @homepage */ ARC2::inc('RDFSerializer'); class ARC2_RDFJSONSerializer extends ARC2_RDFSerializer { + public string $content_header; + public function __construct($a, &$caller) { parent::__construct($a, $caller); diff --git a/serializers/ARC2_RDFSerializer.php b/serializers/ARC2_RDFSerializer.php index 21aea982..c0c4343a 100755 --- a/serializers/ARC2_RDFSerializer.php +++ b/serializers/ARC2_RDFSerializer.php @@ -4,6 +4,7 @@ * * @author Benjamin Nowack * @license W3C Software License and GPL + * * @homepage * * @version 2010-11-16 diff --git a/serializers/ARC2_RDFXMLSerializer.php b/serializers/ARC2_RDFXMLSerializer.php index f7ebcabb..ac8f52df 100644 --- a/serializers/ARC2_RDFXMLSerializer.php +++ b/serializers/ARC2_RDFXMLSerializer.php @@ -4,6 +4,7 @@ * * @author Benjamin Nowack * @license W3C Software License and GPL + * * @homepage * * @version 2010-11-16 @@ -12,6 +13,11 @@ class ARC2_RDFXMLSerializer extends ARC2_RDFSerializer { + public string $content_header; + public string $default_ns; + public string $pp_containers; + public int $type_nodes; + public function __construct($a, &$caller) { parent::__construct($a, $caller); @@ -76,7 +82,7 @@ public function getTerm($v, $type) public function getPName($v, $connector = ':') { - if ($this->default_ns && (0 === strpos($v, $this->default_ns))) { + if ($this->default_ns && str_starts_with($v, $this->default_ns)) { $pname = substr($v, strlen($this->default_ns)); if (!preg_match('/\//', $pname)) { return $pname; diff --git a/serializers/ARC2_RSS10Serializer.php b/serializers/ARC2_RSS10Serializer.php index 7a4c61cf..c96f3c6b 100755 --- a/serializers/ARC2_RSS10Serializer.php +++ b/serializers/ARC2_RSS10Serializer.php @@ -5,6 +5,7 @@ * @author Toby Inkster * @author Benjamin Nowack * @license W3C Software License and GPL + * * @homepage * * @version 2010-11-16 diff --git a/serializers/ARC2_TurtleSerializer.php b/serializers/ARC2_TurtleSerializer.php index 84e42321..ffe56f4d 100644 --- a/serializers/ARC2_TurtleSerializer.php +++ b/serializers/ARC2_TurtleSerializer.php @@ -4,6 +4,7 @@ * * @author Benjamin Nowack * @license W3C Software License and GPL + * * @homepage * * @version 2010-11-16 @@ -12,6 +13,8 @@ class ARC2_TurtleSerializer extends ARC2_RDFSerializer { + public string $content_header; + public function __construct($a, &$caller) { parent::__construct($a, $caller); @@ -33,10 +36,10 @@ public function getTerm($v, $term = '', $qualifier = '') return $pn; } if ( - ('o' === $term) && - in_array($qualifier, ['rdf:type', 'rdfs:domain', 'rdfs:range', 'rdfs:subClassOf']) && - ($pn = $this->getPName($v)) - ) { + ('o' === $term) + && in_array($qualifier, ['rdf:type', 'rdfs:domain', 'rdfs:range', 'rdfs:subClassOf']) + && ($pn = $this->getPName($v)) + ) { return $pn; } if (preg_match('/^[a-z0-9]+\:[^\s]*$/is'.($this->has_pcre_unicode ? 'u' : ''), $v)) { diff --git a/sparqlscript/ARC2_SPARQLScriptParser.php b/sparqlscript/ARC2_SPARQLScriptParser.php index 37eeb65d..7b916657 100755 --- a/sparqlscript/ARC2_SPARQLScriptParser.php +++ b/sparqlscript/ARC2_SPARQLScriptParser.php @@ -100,9 +100,9 @@ public function xScriptBlock($v) 'type' => 'query', 'query_type' => $r['type'], 'query' => $q, - //'prefixes' => $this->prefixes, + // 'prefixes' => $this->prefixes, 'base' => $this->base, - //'infos' => $r + // 'infos' => $r ]); return [$r, $v]; @@ -235,7 +235,7 @@ public function xReturn($v) return [0, $v]; } - /* s4 'IF' BrackettedExpression '{' Script '}' ( 'ELSE' '{' Script '}')? */ + /* s4 'IF' BrackettedExpression '{' Script '}' ( 'ELSE' '{' Script '}')? */ public function xIFBlock($v) { diff --git a/sparqlscript/ARC2_SPARQLScriptProcessor.php b/sparqlscript/ARC2_SPARQLScriptProcessor.php index fc6fd591..bceea4d0 100755 --- a/sparqlscript/ARC2_SPARQLScriptProcessor.php +++ b/sparqlscript/ARC2_SPARQLScriptProcessor.php @@ -100,7 +100,7 @@ public function replacePlaceholders($val, $context = '', $return_string = 1, $lo $old_val = $val; if (preg_match_all('/(\{(?:[^{}]+|(?R))*\})/', $val, $m)) { foreach ($m[1] as $match) { - if (false === strpos($val, '$'.$match)) {/* just some container brackets, recurse */ + if (!str_contains($val, '$'.$match)) {/* just some container brackets, recurse */ $val = str_replace($match, '{'.$this->replacePlaceholders(substr($match, 1, -1), $context, $return_string, $loop + 1).'}', $val); } else { $ph = substr($match, 1, -1); @@ -246,6 +246,7 @@ public function render($val, $src_format = '') return 'No rendering method found for "'.$src_format.'"'; } } + /* try RDF */ return $this->getArraySerialization($val); } @@ -278,6 +279,7 @@ public function getArraySerialization($v, $context) if (('triples' == $v_type) || ('index' == $v_type)) { $m = method_exists($this, 'to'.$pf) ? 'to'.$pf : ('query' == $context ? 'toNTriples' : 'toRDFXML'); } + /* else */ return $this->$m($v); } @@ -579,7 +581,7 @@ public function processFunctionCallBlock($block) { $uri = $this->replacePlaceholders($block['uri'], 'function_call'); /* built-ins */ - if (0 === strpos($uri, $this->a['ns']['sps'])) { + if (str_starts_with($uri, $this->a['ns']['sps'])) { return $this->processBuiltinFunctionCallBlock($block); } /* remote functions */ @@ -613,7 +615,7 @@ public function processEvalCall($block) if ('var' == $arg['type']) { $script = $this->getVarValue($arg['value']); } - //echo "\n" . $script . $arg['type']; + // echo "\n" . $script . $arg['type']; $this->processScript($script); } @@ -675,6 +677,7 @@ public function extractVars($pattern, $input = '') return 1; } + /* no placeholders */ return ($pattern == $input) ? 1 : 0; } diff --git a/src/ARC2/Store/Adapter/AbstractAdapter.php b/src/ARC2/Store/Adapter/AbstractAdapter.php index 3355d625..33e682fc 100644 --- a/src/ARC2/Store/Adapter/AbstractAdapter.php +++ b/src/ARC2/Store/Adapter/AbstractAdapter.php @@ -4,6 +4,7 @@ * @author Benjamin Nowack * @author Konrad Abicht * @license W3C Software License and GPL + * * @homepage */ @@ -27,7 +28,7 @@ abstract class AbstractAdapter protected $queries = []; /** - * @param array $configuration Default is array(). Only use, if you have your own mysqli connection. + * @param array $configuration default is array() */ public function __construct(array $configuration = []) { @@ -69,6 +70,11 @@ public function getQueries(): array abstract public function checkRequirements(); + /** + * Connect to server. + * + * It returns current object for the connection, such as an instance of \PDO. + */ abstract public function connect($existingConnection = null); abstract public function disconnect(); @@ -89,8 +95,6 @@ abstract public function getDBSName(); abstract public function getLastInsertId(); - abstract public function getServerInfo(); - abstract public function getErrorMessage(); abstract public function getNumberOfRows($sql); diff --git a/src/ARC2/Store/Adapter/AdapterFactory.php b/src/ARC2/Store/Adapter/AdapterFactory.php index dd349959..c8f22728 100644 --- a/src/ARC2/Store/Adapter/AdapterFactory.php +++ b/src/ARC2/Store/Adapter/AdapterFactory.php @@ -4,13 +4,12 @@ * @author Benjamin Nowack * @author Konrad Abicht * @license W3C Software License and GPL + * * @homepage */ namespace ARC2\Store\Adapter; -use Exception; - /** * It provides an adapter instance for requested adapter name. */ @@ -20,48 +19,22 @@ class AdapterFactory * @param string $adapterName * @param array $configuration Default is array() * - * @throws Exception if unknown adapter name was given + * @throws \Exception if unknown adapter name was given */ public function getInstanceFor($adapterName, $configuration = []) { if (\in_array($adapterName, $this->getSupportedAdapters())) { - /* - * mysqli - */ - if ('mysqli' == $adapterName) { - if (false == class_exists(mysqliAdapter::class)) { - require_once 'mysqliAdapter.php'; + if ('pdo' == $adapterName) { + // no cache + if (false == class_exists(PDOAdapter::class)) { + require_once 'PDOAdapter.php'; } - return new mysqliAdapter($configuration); - /* - * PDO - */ - } elseif ('pdo' == $adapterName) { - if (isset($configuration['cache_enabled']) && true === $configuration['cache_enabled']) { - // use cache? - if (false == class_exists(CachedPDOAdapter::class)) { - require_once 'CachedPDOAdapter.php'; - } - - return new CachedPDOAdapter($configuration); - } elseif ( - isset($configuration['db_pdo_protocol']) - && 'sqlite' == $configuration['db_pdo_protocol'] - ) { - return new PDOSQLiteAdapter($configuration); - } else { - // no cache - if (false == class_exists(PDOAdapter::class)) { - require_once 'PDOAdapter.php'; - } - - return new PDOAdapter($configuration); - } + return new PDOAdapter($configuration); } } - throw new Exception('Unknown adapter name given. Currently supported are: '.implode(', ', $this->getSupportedAdapters())); + throw new \Exception('Unknown adapter name given. Currently supported are: '.implode(', ', $this->getSupportedAdapters())); } /** @@ -69,6 +42,6 @@ public function getInstanceFor($adapterName, $configuration = []) */ public function getSupportedAdapters() { - return ['mysqli', 'pdo']; + return ['pdo']; } } diff --git a/src/ARC2/Store/Adapter/CachedPDOAdapter.php b/src/ARC2/Store/Adapter/CachedPDOAdapter.php deleted file mode 100644 index 33640e7e..00000000 --- a/src/ARC2/Store/Adapter/CachedPDOAdapter.php +++ /dev/null @@ -1,146 +0,0 @@ - - * @author Konrad Abicht - * @license W3C Software License and GPL - * @homepage - */ - -namespace ARC2\Store\Adapter; - -use Psr\SimpleCache\CacheInterface; -use Symfony\Component\Cache\Simple\FilesystemCache; - -/** - * PDO Adapter - Handles database operations using PDO. - */ -class CachedPDOAdapter extends PDOAdapter -{ - protected $cacheEnabled; - protected $cache; - - public function __construct(array $configuration = []) - { - parent::__construct($configuration); - - $this->initCache($configuration); - } - - protected function initCache(array $configuration) - { - $this->cacheEnabled = isset($configuration['cache_enabled']) - && true === $configuration['cache_enabled']; - - if ($this->cacheEnabled) { - // reuse existing cache instance, if it implements Psr\SimpleCache\CacheInterface - if (isset($configuration['cache_instance']) - && $configuration['cache_instance'] instanceof CacheInterface) { - $this->cache = $configuration['cache_instance']; - - // create new cache instance - } else { - // FYI: https://symfony.com/doc/current/components/cache/adapters/filesystem_adapter.html - $this->cache = new FilesystemCache('arc2', 0, null); - } - } else { - throw new \Exception('Cache not enabled, therefore CachedPDOAdapter can not be used.'); - } - } - - public function clearCache() - { - $this->cache->clear(); - } - - /** - * @param string $sql - * - * @return array - */ - public function fetchList($sql) - { - $key = hash('sha1', $sql); - - // sql query is known - if ($this->cache->has($key)) { - return $this->cache->get($key); - } else { - $result = parent::fetchList($sql); - $this->cache->set($key, $result); - - return $result; - } - } - - /** - * @param string $sql - * - * @return array - */ - public function fetchRow($sql) - { - $key = hash('sha1', $sql); - - // sql query is known - if ($this->cache->has($key)) { - return $this->cache->get($key); - } else { - $result = parent::fetchRow($sql); - $this->cache->set($key, $result); - - return $result; - } - } - - public function getCacheInstance() - { - return $this->cache; - } - - public function getNumberOfRows($sql) - { - $key = hash('sha1', $sql); - - // sql query is known - if ($this->cache->has($key)) { - return $this->cache->get($key); - } else { - $result = parent::getNumberOfRows($sql); - $this->cache->set($key, $result); - - return $result; - } - } - - /** - * catches the first part of the query - * we need that to determine if its an query which changes the DB in any way. - */ - protected function queryChangesDb($sql) - { - $sqlPart = substr(trim($sql), 0, 4); - - return true === \in_array($sqlPart, ['CREA', 'DROP', 'DELE', 'INSE', 'RENA', 'UPDA']); - } - - public function simpleQuery($sql) - { - if ($this->queryChangesDb($sql)) { - $this->cache->clear(); - } - - return parent::simpleQuery($sql); - } - - public function exec($sql) - { - if ($this->queryChangesDb($sql)) { - $this->cache->clear(); - } - - return parent::exec($sql); - } -} diff --git a/src/ARC2/Store/Adapter/MysqliDbExtended.php b/src/ARC2/Store/Adapter/MysqliDbExtended.php deleted file mode 100644 index 5bd60593..00000000 --- a/src/ARC2/Store/Adapter/MysqliDbExtended.php +++ /dev/null @@ -1,112 +0,0 @@ -mysqli()->affected_rows; - } - - /** - * If you ran a query using MysqliDbExtended::simpleQuery and an error occoured, you can - * get the error code with this function. - * - * @return int error code, if available - */ - public function getErrorCode() - { - return $this->mysqli()->errno; - } - - /** - * If you ran a query using MysqliDbExtended::simpleQuery and an error occoured, you can - * get the error message with this function. - * - * @return string non-empty string, if an error occoured, empty string otherwise - */ - public function getErrorMessage() - { - return $this->mysqli()->error; - } - - /** - * @return int - */ - public function getLastInsertId() - { - if (\is_object($this->last_result)) { - return $this->last_result->insert_id; - } - - return null; - } - - /** - * Executes a SQL statement and returns the number of rows. This function will return 0, - * regardless of errors in the query. - * - * @param string $sql query to execute - * - * @return int number of rows, if available, 0 otherwise - */ - public function getNumberOfRows($sql = null) - { - if (null != $sql) { - $result = $this->mysqli()->query($sql); - - return \is_object($result) ? $result->num_rows : 0; - } elseif (\is_object($this->last_result)) { - return $this->last_result->num_rows; - } - - return 0; - } - - /** - * Returns the server version. - * - * @return string - */ - public function getServerInfo() - { - return $this->mysqli()->server_info; - } - - /** - * For compatibility reasons. Executes a query using mysqli and returns the result. Dont use - * this function directly. It is only used once to make sure, ARC2 keeps its backward compatibility - * while in the 2.x branch. - * - * @param string $sql query to execute - * - * @return mysqli result|false - */ - public function mysqliQuery($sql) - { - return $this->mysqli()->query($sql); - } - - /** - * @param string $sql query to execute - * - * @return bool true if query runs without problems, false otherwise - */ - public function simpleQuery($sql, $num_rows = null) - { - $this->last_result = $this->mysqli()->query($sql, $num_rows); - - return $this->last_result ? true : false; - } -} diff --git a/src/ARC2/Store/Adapter/PDOAdapter.php b/src/ARC2/Store/Adapter/PDOAdapter.php index e5c5ef1e..02623d16 100644 --- a/src/ARC2/Store/Adapter/PDOAdapter.php +++ b/src/ARC2/Store/Adapter/PDOAdapter.php @@ -6,28 +6,25 @@ * @author Benjamin Nowack * @author Konrad Abicht * @license W3C Software License and GPL + * * @homepage */ namespace ARC2\Store\Adapter; -use Exception; - /** * PDO Adapter - Handles database operations using PDO. - * - * This adapter doesn't support SQLite, please use PDOSQLiteAdapter instead. */ class PDOAdapter extends AbstractAdapter { public function checkRequirements() { if (false == \extension_loaded('pdo_mysql')) { - throw new Exception('Extension pdo_mysql is not loaded.'); + throw new \Exception('Extension pdo_mysql is not loaded.'); } if ('mysql' != $this->configuration['db_pdo_protocol']) { - throw new Exception('Only "mysql" protocol is supported at the moment.'); + throw new \Exception('Only "mysql" protocol is supported at the moment.'); } } @@ -42,9 +39,9 @@ public function getAffectedRows(): int } /** - * Connect to server or storing a given connection. + * Connect to server. * - * @param EasyDB $existingConnection default is null + * @return \PDO */ public function connect($existingConnection = null) { @@ -53,7 +50,7 @@ public function connect($existingConnection = null) if (null !== $existingConnection) { $this->db = $existingConnection; - // create your own connection + // create your own connection } elseif (false === $this->db instanceof \PDO) { /* * build connection string @@ -84,8 +81,7 @@ public function connect($existingConnection = null) $this->db->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false); // errors DONT lead to exceptions - // set to false for compatibility reasons with mysqli. ARC2 using mysqli does not throw any - // exceptions, instead collects errors in a hidden array. + // ARC2 does not throw any exceptions, instead collects errors in a hidden array. $this->db->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); // default fetch mode is associative @@ -224,9 +220,9 @@ public function getDBSName() $clientVersion = strtolower($this->db->getAttribute(\PDO::ATTR_CLIENT_VERSION)); $serverVersion = strtolower($this->db->getAttribute(\PDO::ATTR_SERVER_VERSION)); - if (false !== strpos($clientVersion, 'mariadb') || false !== strpos($serverVersion, 'mariadb')) { + if (str_contains($clientVersion, 'mariadb') || str_contains($serverVersion, 'mariadb')) { $return = 'mariadb'; - } elseif (false !== strpos($clientVersion, 'mysql') || false !== strpos($serverVersion, 'mysql')) { + } elseif (str_contains($clientVersion, 'mysql') || str_contains($serverVersion, 'mysql')) { $return = 'mysql'; } else { $return = null; @@ -235,25 +231,16 @@ public function getDBSName() return $return; } - public function getServerInfo() - { - return $this->db->getAttribute(\constant('PDO::ATTR_CLIENT_VERSION')); - } - /** - * Returns the version of the database server like 05-00-12. + * Returns the version of the database server like 05.00.12 */ - public function getServerVersion() + public function getServerVersion(): string { - $res = preg_match( - "/([0-9]+)\.([0-9]+)\.([0-9]+)/", - $this->getServerInfo(), - $matches - ); - - return 1 == $res - ? sprintf('%02d-%02d-%02d', $matches[1], $matches[2], $matches[3]) - : '00-00-00'; + if ($this->db instanceof \PDO) { + return $this->db->query('select version()')->fetchColumn(); + } + + throw new \Exception('You need to connect to DB server first. Use connect() before this function.'); } public function getErrorCode() diff --git a/src/ARC2/Store/Adapter/PDOSQLiteAdapter.php b/src/ARC2/Store/Adapter/PDOSQLiteAdapter.php deleted file mode 100644 index baa508e9..00000000 --- a/src/ARC2/Store/Adapter/PDOSQLiteAdapter.php +++ /dev/null @@ -1,143 +0,0 @@ - - * @author Konrad Abicht - * @license W3C Software License and GPL - * @homepage - */ - -namespace ARC2\Store\Adapter; - -use Exception; -use PDO; - -/** - * PDO SQLite Adapter, which only supports SQLite running in memory. - */ -class PDOSQLiteAdapter extends PDOAdapter -{ - public function checkRequirements() - { - if (false == \extension_loaded('pdo_sqlite')) { - throw new Exception('Extension pdo_sqlite is not loaded.'); - } - } - - /** - * Connect to server or storing a given connection. - * - * @param PDO $existingConnection default is null - */ - public function connect($existingConnection = null) - { - // reuse a given existing connection. - // it assumes that $existingConnection is a PDO connection object - if (null !== $existingConnection) { - $this->db = $existingConnection; - - // create your own connection - } elseif (false === $this->db instanceof PDO) { - // set path to SQLite file - if ( - isset($this->configuration['db_name']) - && !empty($this->configuration['db_name']) - ) { - $dsn = 'sqlite:'.$this->configuration['db_name']; - } else { - // use in-memory - $dsn = 'sqlite::memory:'; - } - - $this->db = new PDO($dsn); - - $this->db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); - - // errors lead to exceptions - $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - - // default fetch mode is associative - $this->db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); - - /* - * define CONCAT function (otherwise SQLite will throw an exception) - */ - $this->db->sqliteCreateFunction('CONCAT', function ($pattern, $string) { - $result = ''; - - foreach (\func_get_args() as $str) { - $result .= $str; - } - - return $result; - }); - - /* - * define REGEXP function (otherwise SQLite will throw an exception) - */ - $this->db->sqliteCreateFunction('REGEXP', function ($pattern, $string) { - if (0 < preg_match('/'.$pattern.'/i', $string)) { - return true; - } - - return false; - }, 2); - } - - return $this->db; - } - - public function deleteAllTables(): void - { - $this->exec( - 'SELECT "drop table " || name || ";" - FROM sqlite_master - WHERE type = "table";' - ); - } - - /** - * It gets all tables from the current database. - */ - public function getAllTables(): array - { - $tables = $this->fetchList('SELECT name FROM sqlite_master WHERE type="table";'); - $result = []; - foreach ($tables as $table) { - // ignore SQLite tables - if (false !== strpos($table['name'], 'sqlite_')) { - continue; - } - $result[] = $table['name']; - } - - return $result; - } - - public function getCollation() - { - return ''; - } - - public function getConnectionId() - { - return null; - } - - public function getDBSName() - { - return 'sqlite'; - } - - public function getServerInfo() - { - return null; - } - - public function getServerVersion() - { - return $this->fetchRow('select sqlite_version()')['sqlite_version()']; - } -} diff --git a/src/ARC2/Store/Adapter/mysqliAdapter.php b/src/ARC2/Store/Adapter/mysqliAdapter.php deleted file mode 100644 index 96d14c27..00000000 --- a/src/ARC2/Store/Adapter/mysqliAdapter.php +++ /dev/null @@ -1,263 +0,0 @@ - - * @author Konrad Abicht - * @license W3C Software License and GPL - * @homepage - */ - -namespace ARC2\Store\Adapter; - -/** - * mysqli Adapter - Handles database operations using mysqli. - */ -class mysqliAdapter extends AbstractAdapter -{ - protected $last_result; - - public function checkRequirements() - { - if (false == \extension_loaded('mysqli') || false == \function_exists('mysqli_connect')) { - throw new \Exception('Extension mysqli is not loaded or function mysqli_connect is not available.'); - } - } - - public function getAdapterName() - { - return 'mysqli'; - } - - /** - * Connect to server or storing a given connection. - * - * @return string|MysqliDbExtended string if an error occoured, instance of MysqliDbExtended otherwise - */ - public function connect($existingConnection = null) - { - // reuse a given existing connection. - // it assumes that $existingConnection is a mysqli connection object - if (null !== $existingConnection) { - $this->db = new MysqliDbExtended($existingConnection); - - // create your own connection - } elseif (null == $this->db) { - // connect - try { - $this->db = new MysqliDbExtended( - $this->configuration['db_host'], - $this->configuration['db_user'], - $this->configuration['db_pwd'], - null, - $this->configuration['db_port'] ?? 3306 - ); - } catch (\Exception $e) { - return $e->getMessage(); - } - } - - if (isset($this->configuration['db_name']) - && true !== $this->db->simpleQuery('USE `'.$this->configuration['db_name'].'`')) { - $fixed = 0; - /* try to create it */ - if ($this->configuration['db_name']) { - $this->db->simpleQuery(' - CREATE DATABASE IF NOT EXISTS `'.$this->configuration['db_name'].'` - DEFAULT CHARACTER SET utf8 - DEFAULT COLLATE utf8_general_ci - ' - ); - if ($this->db->simpleQuery('USE `'.$this->configuration['db_name'].'`')) { - $this->db->simpleQuery("SET NAMES 'utf8'"); - $fixed = 1; - } - } - if (!$fixed) { - return $this->addError($this->db->getErrorMessage()); - } else { - if (preg_match('/^utf8/', $this->getCollation())) { - $this->db->simpleQuery("SET NAMES 'utf8'"); - } - // This is RDF, we may need many JOINs... - $this->db->simpleQuery('SET SESSION SQL_BIG_SELECTS=1'); - } - } - - return $this->db; - } - - public function disconnect() - { - return $this->db->disconnect(); - } - - public function escape($value) - { - return $this->db->escape($value); - } - - public function fetchList($sql) - { - return $this->db->rawQuery($sql); - } - - public function fetchRow($sql) - { - $row = $this->db->rawQueryOne($sql); - - return null != $row ? $row : false; - } - - public function getCollation() - { - $row = $this->fetchRow('SHOW TABLE STATUS LIKE "'.$this->getTablePrefix().'setting"'); - - if (isset($row['Collation'])) { - return $row['Collation']; - } else { - return ''; - } - } - - public function getConnectionId() - { - if (null != $this->db) { - return $this->db->mysqli()->thread_id; - } - } - - /** - * For backward compatibility reasons. Get mysqli connection object. - * - * @return mysqli - */ - public function getConnection() - { - return $this->db->mysqli(); - } - - public function getDBSName() - { - if (null == $this->db) { - return null; - } - - return false !== strpos($this->getServerInfo(), 'MariaDB') - ? 'mariadb' - : 'mysql'; - } - - public function getLastInsertId() - { - if (null != $this->db) { - return $this->db->getLastInsertId(); - } - - return 'No database connection (mysqliAdapter).'; - } - - public function getServerInfo() - { - $this->connect(); - - return $this->db->mysqli()->server_info; - } - - /** - * Returns the version of the database server like 05-00-12. - */ - public function getServerVersion() - { - $res = preg_match( - "/([0-9]+)\.([0-9]+)\.([0-9]+)/", - $this->getServerInfo(), - $matches - ); - - return 1 == $res - ? sprintf('%02d-%02d-%02d', $matches[1], $matches[2], $matches[3]) - : '00-00-00'; - } - - public function getErrorMessage() - { - return $this->db->getErrorMessage(); - } - - public function getErrorCode() - { - return $this->db->getErrorCode(); - } - - public function getNumberOfRows($sql) - { - return $this->db->getNumberOfRows($sql); - } - - public function getStoreName() - { - if (isset($this->configuration['store_name'])) { - return $this->configuration['store_name']; - } - - return 'arc'; - } - - public function getTablePrefix() - { - $prefix = ''; - if (isset($this->configuration['db_table_prefix'])) { - $prefix = $this->configuration['db_table_prefix'].'_'; - } - - $prefix .= $this->getStoreName().'_'; - - return $prefix; - } - - /** - * For compatibility reasons. Executes a query using mysqli and returns the result. Dont use - * this function directly. It is only used once to make sure, ARC2 keeps its backward compatibility - * while in the 2.x branch. - * - * @param string $sql query to execute - * - * @return mysqli result|false - */ - public function mysqliQuery($sql) - { - return $this->db->mysqliQuery($sql); - } - - /** - * @param string $sql Query - * - * @return bool true if query ran fine, false otherwise - */ - public function simpleQuery($sql) - { - if (null == $this->db) { - $this->connect(); - } - - return $this->db->simpleQuery($sql); - } - - /** - * @param string $sql Query with return of affected rows - * - * @return int number of affected rows - */ - public function exec($sql) - { - if (null == $this->db) { - $this->connect(); - } - - $this->db->simpleQuery($sql); - - return $this->db->getAffectedRows(); - } -} diff --git a/src/ARC2/Store/TableManager/SQLite.php b/src/ARC2/Store/TableManager/SQLite.php deleted file mode 100755 index 0cf31649..00000000 --- a/src/ARC2/Store/TableManager/SQLite.php +++ /dev/null @@ -1,111 +0,0 @@ - - * - * @version 2010-11-16 - */ - -namespace ARC2\Store\TableManager; - -use ARC2_Store; - -class SQLite extends ARC2_Store -{ - public function __construct($a, &$caller) - { - parent::__construct($a, $caller); - } - - public function createTables(): void - { - $this->createTripleTable(); - $this->createG2TTable(); - $this->createID2ValTable(); - $this->createS2ValTable(); - $this->createO2ValTable(); - $this->createSettingTable(); - } - - public function createTripleTable($suffix = 'triple'): void - { - $sql = 'CREATE TABLE IF NOT EXISTS '.$this->getTablePrefix().$suffix.' ( - t INTEGER UNSIGNED NOT NULL UNIQUE, - s INTEGER UNSIGNED NOT NULL, - p INTEGER UNSIGNED NOT NULL, - o INTEGER UNSIGNED NOT NULL, - o_lang_dt INTEGER UNSIGNED NOT NULL, - o_comp TEXT NOT NULL, -- normalized value for ORDER BY operations - s_type INTEGER UNSIGNED NOT NULL DEFAULT 0, -- uri/bnode => 0/1 - o_type INTEGER UNSIGNED NOT NULL DEFAULT 0, -- uri/bnode/literal => 0/1/2 - misc INTEGER NOT NULL DEFAULT 0 -- temporary flags - )'; - - $this->a['db_object']->exec($sql); - } - - public function createG2TTable(): void - { - $sql = 'CREATE TABLE IF NOT EXISTS '.$this->getTablePrefix().'g2t ( - g INTEGER UNSIGNED NOT NULL, - t INTEGER UNSIGNED NOT NULL, - UNIQUE (g,t) - )'; - - $this->a['db_object']->exec($sql); - } - - public function createID2ValTable(): void - { - $sql = 'CREATE TABLE IF NOT EXISTS '.$this->getTablePrefix().'id2val ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - misc INTEGER UNSIGNED NOT NULL DEFAULT 0, - val TEXT NOT NULL, - val_type INTEGER NOT NULL DEFAULT 0, -- uri/bnode/literal => 0/1/2 - UNIQUE (id,val_type) - )'; - - $this->a['db_object']->exec($sql); - } - - public function createS2ValTable(): void - { - $sql = 'CREATE TABLE IF NOT EXISTS '.$this->getTablePrefix().'s2val ( - id INTEGER UNSIGNED NOT NULL, - misc INTEGER NOT NULL DEFAULT 0, - val_hash TEXT NOT NULL, - val TEXT NOT NULL, - UNIQUE (id) - )'; - - $this->a['db_object']->exec($sql); - } - - public function createO2ValTable(): void - { - $sql = 'CREATE TABLE IF NOT EXISTS '.$this->getTablePrefix().'o2val ( - id INTEGER NOT NULL, - misc INTEGER UNSIGNED NOT NULL DEFAULT 0, - val_hash TEXT NOT NULL, - val TEXT NOT NULL, - UNIQUE (id) - )'; - - $this->a['db_object']->exec($sql); - } - - public function createSettingTable(): void - { - $sql = 'CREATE TABLE IF NOT EXISTS '.$this->getTablePrefix().'setting ( - k TEXT NOT NULL, - val TEXT NOT NULL, - UNIQUE (k) - )'; - - $this->a['db_object']->exec($sql); - } -} diff --git a/store/ARC2_MemStore.php b/store/ARC2_MemStore.php index ad419942..3821bf9e 100644 --- a/store/ARC2_MemStore.php +++ b/store/ARC2_MemStore.php @@ -149,7 +149,7 @@ public function runQuery($q, $qt = '') $mappings = ['rdfxml' => 'RDFXML', 'sparqlxml' => 'SPARQLXMLResult', 'turtle' => 'Turtle']; if (!$format || !isset($mappings[$format])) { return $resp; - //return $this->addError('No parser available for "' . $format . '" SPARQL result'); + // return $this->addError('No parser available for "' . $format . '" SPARQL result'); } /* format parser */ $suffix = $mappings[$format].'Parser'; @@ -161,9 +161,9 @@ public function runQuery($q, $qt = '') if (in_array($qt, ['ask', 'load', 'insert', 'delete'])) { $bid = $parser->getBooleanInsertedDeleted(); switch ($qt) { - case 'ask': return $bid['boolean']; - default: return $bid; - } + case 'ask': return $bid['boolean']; + default: return $bid; + } } /* select */ if (('select' == $qt) && !method_exists($parser, 'getRows')) { @@ -172,6 +172,7 @@ public function runQuery($q, $qt = '') if ('select' == $qt) { return ['rows' => $parser->getRows(), 'variables' => $parser->getVariables()]; } + /* any other */ return $parser->getSimpleIndex(0); } diff --git a/store/ARC2_RemoteStore.php b/store/ARC2_RemoteStore.php index 3377f397..b621d3a0 100755 --- a/store/ARC2_RemoteStore.php +++ b/store/ARC2_RemoteStore.php @@ -11,6 +11,14 @@ class ARC2_RemoteStore extends ARC2_Class { + public int $is_remote; + public $reader; + + /** + * @var array + */ + public array $resource_labels; + public function __construct($a, &$caller) { parent::__construct($a, $caller); @@ -149,7 +157,7 @@ public function runQuery($q, $qt = '', $infos = '') $mappings = ['rdfxml' => 'RDFXML', 'sparqlxml' => 'SPARQLXMLResult', 'turtle' => 'Turtle']; if (!$format || !isset($mappings[$format])) { return $resp; - //return $this->addError('No parser available for "' . $format . '" SPARQL result'); + // return $this->addError('No parser available for "' . $format . '" SPARQL result'); } /* format parser */ $suffix = $mappings[$format].'Parser'; diff --git a/store/ARC2_Store.php b/store/ARC2_Store.php index 4a84194a..4931278d 100644 --- a/store/ARC2_Store.php +++ b/store/ARC2_Store.php @@ -4,20 +4,49 @@ * * @author Benjamin Nowack * @license W3C Software License and GPL + * * @homepage */ use ARC2\Store\Adapter\AbstractAdapter; use ARC2\Store\Adapter\AdapterFactory; -use ARC2\Store\Adapter\PDOSQLiteAdapter; use ARC2\Store\TableManager\SQLite; ARC2::inc('Class'); +#[AllowDynamicProperties] class ARC2_Store extends ARC2_Class { - protected $cache; - protected $db; + public $cache; + public string $column_type; + public $db; + public string $db_version; + public int $has_fulltext_index; + public $is_win; + public int $max_split_tables; + public int $queue_queries; + + /** + * @var array + */ + public array $resource_labels; + + /** + * @var array + */ + public array $split_predicates; + public int $table_lock; + public string $tbl_prefix; + + /** + * @var array + */ + public array $term_id_cache; + + /** + * @var array + */ + public array $triggers; public function __construct($a, &$caller) { @@ -30,7 +59,7 @@ public function __init() $this->table_lock = 0; $this->triggers = $this->v('store_triggers', [], $this->a); $this->queue_queries = $this->v('store_queue_queries', 0, $this->a); - $this->is_win = ('win' == strtolower(substr(PHP_OS, 0, 3))) ? true : false; + $this->is_win = ('win' == strtolower(substr(\PHP_OS, 0, 3))) ? true : false; $this->max_split_tables = $this->v('store_max_split_tables', 10, $this->a); $this->split_predicates = $this->v('store_split_predicates', [], $this->a); @@ -43,7 +72,7 @@ public function __init() && $this->a['cache_instance'] instanceof \Psr\SimpleCache\CacheInterface) { $this->cache = $this->a['cache_instance']; - // create new cache instance + // create new cache instance } else { // FYI: https://symfony.com/doc/current/components/cache/adapters/filesystem_adapter.html $this->cache = new \Symfony\Component\Cache\Simple\FilesystemCache('arc2', 0, null); @@ -89,7 +118,8 @@ public function createDBCon() require __DIR__.'/../src/ARC2/Store/Adapter/AdapterFactory.php'; } if (false == isset($this->a['db_adapter'])) { - $this->a['db_adapter'] = 'mysqli'; + $this->a['db_adapter'] = 'pdo'; + $this->a['db_pdo_protocol'] = 'mysql'; } $factory = new AdapterFactory(); $this->db = $factory->getInstanceFor($this->a['db_adapter'], $this->a); @@ -102,10 +132,6 @@ public function createDBCon() return $this->addError($e->getMessage()); } - if ('mysqli' == $this->db->getAdapterName()) { - $this->a['db_con'] = $this->db->getConnection(); - } - $this->a['db_object'] = $this->db; return true; @@ -118,25 +144,16 @@ public function getDBObject(): ?AbstractAdapter /** * @param int $force 1 if you want to force a connection - * - * @return mysqli mysqli-connection, only if mysqli adapter was selected. null otherwise, - * because direct access to DB connection is not recommended. */ - public function getDBCon($force = 0) + public function getDBCon($force = 0): bool { if ($force || !isset($this->a['db_object'])) { - if (!$this->createDBCon()) { + if (false === $this->createDBCon()) { return false; } } - if ('mysqli' == $this->a['db_adapter']) { - // for backward compatibility reasons only. - // TODO remove that in 3.x - return $this->a['db_con']; - } else { - return true; - } + return true; } /** @@ -183,20 +200,15 @@ public function getCollation() public function getColumnType() { if (!$this->v('column_type')) { - // SQLite - if ($this->getDBObject() instanceof PDOSQLiteAdapter) { - $this->column_type = 'INTEGER'; - } else { - // MySQL - $tbl = $this->getTablePrefix().'g2t'; - - $row = $this->db->fetchRow('SHOW COLUMNS FROM '.$tbl.' LIKE "t"'); - if (null == $row) { - $row = ['Type' => 'mediumint']; - } + // MySQL + $tbl = $this->getTablePrefix().'g2t'; - $this->column_type = preg_match('/mediumint/', $row['Type']) ? 'mediumint' : 'int'; + $row = $this->db->fetchRow('SHOW COLUMNS FROM '.$tbl.' LIKE "t"'); + if (null == $row) { + $row = ['Type' => 'mediumint']; } + + $this->column_type = preg_match('/mediumint/', $row['Type']) ? 'mediumint' : 'int'; } return $this->column_type; @@ -208,15 +220,14 @@ public function hasHashColumn($tbl) if (!isset($this->$var_name)) { $tbl = $this->getTablePrefix().$tbl; - $value = true; - // only check if SQLite is NOT being used - if (false === $this->getDBObject() instanceof PDOSQLiteAdapter) { - $row = $this->db->fetchRow('SHOW COLUMNS FROM '.$tbl.' LIKE "val_hash"'); - $value = null !== $row; - } + $row = $this->db->fetchRow('SHOW COLUMNS FROM '.$tbl.' LIKE "val_hash"'); - $this->$var_name = $value; + // fix: $row doesn't return 'null' + $this->$var_name = null; + if ($row) { + $this->$var_name = true; + } } return $this->$var_name; @@ -224,10 +235,6 @@ public function hasHashColumn($tbl) public function hasFulltextIndex() { - if ($this->getDBObject() instanceof PDOSQLiteAdapter) { - return true; - } - if (!isset($this->has_fulltext_index)) { $this->has_fulltext_index = 0; $tbl = $this->getTablePrefix().'o2val'; @@ -250,10 +257,6 @@ public function hasFulltextIndex() public function enableFulltextSearch() { - if ($this->getDBObject() instanceof PDOSQLiteAdapter) { - return; - } - if ($this->hasFulltextIndex()) { return 1; } @@ -263,10 +266,6 @@ public function enableFulltextSearch() public function disableFulltextSearch() { - if ($this->getDBObject() instanceof PDOSQLiteAdapter) { - return; - } - if (!$this->hasFulltextIndex()) { return 1; } @@ -281,13 +280,7 @@ public function disableFulltextSearch() */ public function countDBProcesses(): int { - $amount = 1; - - if (false === $this->getDBObject() instanceof PDOSQLiteAdapter) { - $amount = $this->db->getNumberOfRows('SHOW PROCESSLIST'); - } - - return $amount; + return $this->db->getNumberOfRows('SHOW PROCESSLIST'); } /** @@ -315,7 +308,7 @@ public function killDBProcesses($needle = '', $runtime = 30) continue; } /* only from this store */ $kill = 0; - if ($needle && (false !== strpos($row['Info'], $needle))) { + if ($needle && str_contains($row['Info'], $needle)) { $kill = 1; } if (!$needle) { @@ -354,36 +347,25 @@ public function isSetUp() public function setUp($force = 0) { if (($force || !$this->isSetUp()) && false !== $this->getDBCon()) { - // PDO with SQLite - if ($this->a['db_object'] instanceof PDOSQLiteAdapter) { - (new SQLite($this->a, $this))->createTables(); - } else { - // default way - ARC2::inc('StoreTableManager'); - (new ARC2_StoreTableManager($this->a, $this))->createTables(); - } + // default way + ARC2::inc('StoreTableManager'); + (new ARC2_StoreTableManager($this->a, $this))->createTables(); } } public function extendColumns() { - $cfg = $this->getDBObject()->getConfiguration(); - - if (false === $this->getDBObject() instanceof PDOSQLiteAdapter) { - ARC2::inc('StoreTableManager'); - $mgr = new ARC2_StoreTableManager($this->a, $this); - $mgr->extendColumns(); - $this->column_type = 'int'; - } + ARC2::inc('StoreTableManager'); + $mgr = new ARC2_StoreTableManager($this->a, $this); + $mgr->extendColumns(); + $this->column_type = 'int'; } public function splitTables() { - if (false === $this->getDBObject() instanceof PDOSQLiteAdapter) { - ARC2::inc('StoreTableManager'); - $mgr = new ARC2_StoreTableManager($this->a, $this); - $mgr->splitTables(); - } + ARC2::inc('StoreTableManager'); + $mgr = new ARC2_StoreTableManager($this->a, $this); + $mgr->splitTables(); } public function hasSetting($k) @@ -494,11 +476,7 @@ public function reset($keep_settings = 0) if ($keep_settings && ('setting' == $tbl)) { continue; } - if ($this->getDBObject() instanceof PDOSQLiteAdapter) { - $this->db->simpleQuery('DELETE FROM '.$prefix.$tbl); - } else { - $this->db->simpleQuery('TRUNCATE '.$prefix.$tbl); - } + $this->db->simpleQuery('TRUNCATE '.$prefix.$tbl); } } @@ -567,11 +545,7 @@ public function renameTo($name) $new_prefix .= $new_prefix ? '_' : ''; $new_prefix .= $name.'_'; foreach ($tbls as $tbl) { - if ($this->getDBObject() instanceof PDOSQLiteAdapter) { - $sql = 'ALTER TABLE '.$old_prefix.$tbl.' RENAME TO '.$new_prefix.$tbl; - } else { - $sql = 'RENAME TABLE '.$old_prefix.$tbl.' TO '.$new_prefix.$tbl; - } + $sql = 'RENAME TABLE '.$old_prefix.$tbl.' TO '.$new_prefix.$tbl; $this->db->simpleQuery($sql); if (!empty($this->db->getErrorMessage())) { @@ -584,10 +558,6 @@ public function renameTo($name) public function replicateTo($name) { - if ($this->getDBObject() instanceof PDOSQLiteAdapter) { - throw new Exception('replicateTo not supported with SQLite as DB adapter yet.'); - } - $conf = array_merge($this->a, ['store_name' => $name]); $new_store = ARC2::getStore($conf); $new_store->setUp(); @@ -596,14 +566,7 @@ public function replicateTo($name) $old_prefix = $this->getTablePrefix(); $new_prefix = $new_store->getTablePrefix(); - /* - * Use appropriate INSERT syntax, depending on the DBS. - */ - if ($this->getDBObject() instanceof PDOSQLiteAdapter) { - $sqlHead = 'INSERT OR IGNORE INTO '; - } else { - $sqlHead = 'INSERT IGNORE INTO '; - } + $sqlHead = 'INSERT IGNORE INTO '; foreach ($tbls as $tbl) { $this->db->simpleQuery($sqlHead.$new_prefix.$tbl.' SELECT * FROM '.$old_prefix.$tbl); @@ -639,7 +602,7 @@ public function query($q, $result_format = '', $src = '', $keep_bnode_ids = 0, $ if ($this->cacheEnabled() && $this->cache->has($key.'_infos')) { $infos = $this->cache->get($key.'_infos'); $errors = $this->cache->get($key.'_errors'); - // no entry found + // no entry found } else { ARC2::inc('SPARQLPlusParser'); $p = new ARC2_SPARQLPlusParser($this->a, $this); @@ -803,17 +766,10 @@ public function getTermID($val, $term = '') } /* exact match */ else { - if ($this->getDBObject() instanceof PDOSQLiteAdapter) { - $sql = 'SELECT id - FROM '.$this->getTablePrefix().$tbl." - WHERE val = '".$this->db->escape($val)."' - LIMIT 1"; - } else { - $sql = 'SELECT id + $sql = 'SELECT id FROM '.$this->getTablePrefix().$tbl." WHERE val = BINARY '".$this->db->escape($val)."' LIMIT 1"; - } $row = $this->db->fetchRow($sql); @@ -843,15 +799,6 @@ public function getIDValue($id, $term = '') public function getLock($t_out = 10, $t_out_init = '') { - /* - * We assume locks are not required when using SQLite. - * Either its an in memory database, which has no concurrent reads - * or its a file and SQLite takes care of it. - */ - if ($this->getDBObject() instanceof PDOSQLiteAdapter) { - return 1; - } - if (!$t_out_init) { $t_out_init = $t_out; } @@ -879,15 +826,6 @@ public function getLock($t_out = 10, $t_out_init = '') public function releaseLock() { - /* - * We assume locks are not required when using SQLite. - * Either its an in memory database, which has no concurrent reads - * or its a file and SQLite takes care of it. - */ - if ($this->getDBObject() instanceof PDOSQLiteAdapter) { - return true; - } - $sql = 'DO RELEASE_LOCK("'.$this->a['db_name'].'.'.$this->getTablePrefix().'.write_lock")'; return $this->db->simpleQuery($sql); @@ -898,11 +836,6 @@ public function releaseLock() */ public function processTables($level = 2, $operation = 'optimize') { - // no processing required when using SQLite - if ($this->getDBObject() instanceof PDOSQLiteAdapter) { - return; - } - /* * level: * 1. triple + g2t diff --git a/store/ARC2_StoreAskQueryHandler.php b/store/ARC2_StoreAskQueryHandler.php index d79a5bc0..c52a35b0 100755 --- a/store/ARC2_StoreAskQueryHandler.php +++ b/store/ARC2_StoreAskQueryHandler.php @@ -4,6 +4,7 @@ * * @author Benjamin Nowack * @license W3C Software License and GPL + * * @homepage * * @version 2010-11-16 diff --git a/store/ARC2_StoreAtomLoader.php b/store/ARC2_StoreAtomLoader.php index 650fe5f8..f6608e83 100755 --- a/store/ARC2_StoreAtomLoader.php +++ b/store/ARC2_StoreAtomLoader.php @@ -12,6 +12,8 @@ class: ARC2 Store Atom(2) Loader class ARC2_StoreAtomLoader extends ARC2_AtomParser { + public int $t_count = 0; + public function __construct($a, &$caller) { parent::__construct($a, $caller); diff --git a/store/ARC2_StoreCBJSONLoader.php b/store/ARC2_StoreCBJSONLoader.php index 40f7c6d3..d759c9fa 100755 --- a/store/ARC2_StoreCBJSONLoader.php +++ b/store/ARC2_StoreCBJSONLoader.php @@ -4,6 +4,7 @@ * * @author Benjamin Nowack * @license W3C Software License and GPL + * * @homepage * * @version 2010-11-16 diff --git a/store/ARC2_StoreDeleteQueryHandler.php b/store/ARC2_StoreDeleteQueryHandler.php index 22ff5227..163a2894 100644 --- a/store/ARC2_StoreDeleteQueryHandler.php +++ b/store/ARC2_StoreDeleteQueryHandler.php @@ -4,15 +4,20 @@ * * @author Benjamin Nowack * @license W3C Software License and GPL + * * @homepage */ - -use ARC2\Store\Adapter\PDOSQLiteAdapter; - ARC2::inc('StoreQueryHandler'); class ARC2_StoreDeleteQueryHandler extends ARC2_StoreQueryHandler { + /** + * @var array + */ + public array $infos; + + public $refs_deleted; + public function __construct($a, &$caller) {/* caller has to be a store */ parent::__construct($a, $caller); @@ -103,7 +108,7 @@ public function deleteTriples() $skip = 0; foreach (['s', 'p', 'o'] as $term) { if (isset($t[$term.'_type']) && preg_match('/(var)/', $t[$term.'_type'])) { - //$skip = 1; + // $skip = 1; } else { $term_id = $this->getTermID($t[$term], $term); $q .= ($q ? ' AND ' : '').'T.'.$term.'='.$term_id; @@ -121,32 +126,16 @@ public function deleteTriples() continue; } if ($gq) { - if ($this->store->getDBObject() instanceof PDOSQLiteAdapter) { - $sql = 'DELETE FROM '.$tbl_prefix.'g2t WHERE t IN ('; - $sql .= ' SELECT G.t - FROM '.$tbl_prefix.'g2t G - JOIN '.$this->getTripleTable().' T ON T.t = G.t'.$gq.' - WHERE '.$q; - $sql .= ')'; - } else { - $sql = ($dbv < '04-01') ? 'DELETE '.$tbl_prefix.'g2t' : 'DELETE G'; - $sql .= ' - FROM '.$tbl_prefix.'g2t G - JOIN '.$this->getTripleTable().' T ON (T.t = G.t'.$gq.') - WHERE '.$q.' - '; - $this->refs_deleted = 1; - } + $sql = ($dbv < '04-01') ? 'DELETE '.$tbl_prefix.'g2t' : 'DELETE G'; + $sql .= ' + FROM '.$tbl_prefix.'g2t G + JOIN '.$this->getTripleTable().' T ON (T.t = G.t'.$gq.') + WHERE '.$q.' + '; + $this->refs_deleted = 1; } else {/* triples only */ - if ($this->store->getDBObject() instanceof PDOSQLiteAdapter) { - // it contains things like "T.s", but we can't use a table alias - // with SQLite when running DELETE queries. - $q = str_replace('T.', '', $q); - $sql = 'DELETE FROM '.$this->getTripleTable().' WHERE '.$q; - } else { - $sql = ($dbv < '04-01') ? 'DELETE '.$this->getTripleTable() : 'DELETE T'; - $sql .= ' FROM '.$this->getTripleTable().' T WHERE '.$q; - } + $sql = ($dbv < '04-01') ? 'DELETE '.$this->getTripleTable() : 'DELETE T'; + $sql .= ' FROM '.$this->getTripleTable().' T WHERE '.$q; } $r += $this->store->a['db_object']->exec($sql); if (!empty($this->store->a['db_object']->getErrorMessage())) { @@ -185,25 +174,15 @@ public function cleanTableReferences() $numRows = $this->store->a['db_object']->getNumberOfRows($sql); if (0 < $numRows) { /* delete unconnected triples */ - if ($this->store->getDBObject() instanceof PDOSQLiteAdapter) { - $sql = 'DELETE FROM '.$tbl_prefix.'triple WHERE t IN ('; - $sql .= ' SELECT T.t - FROM '.$tbl_prefix.'triple T - LEFT JOIN '.$tbl_prefix.'g2t G ON G.t = T.t - WHERE G.t IS NULL'; - $sql .= ')'; - } else { - $sql = ($dbv < '04-01') ? 'DELETE '.$tbl_prefix.'triple' : 'DELETE T'; - $sql .= ' - FROM '.$tbl_prefix.'triple T - LEFT JOIN '.$tbl_prefix.'g2t G ON (G.t = T.t) - WHERE G.t IS NULL - '; - } + $sql = 'DELETE T + FROM '.$tbl_prefix.'triple T + LEFT JOIN '.$tbl_prefix.'g2t G ON (G.t = T.t) + WHERE G.t IS NULL + '; $this->store->a['db_object']->simpleQuery($sql); } /* check for unconnected graph refs */ - if ((1 == rand(1, 10))) { + if (1 == rand(1, 10)) { $sql = ' SELECT G.g FROM '.$tbl_prefix.'g2t G LEFT JOIN '.$tbl_prefix.'triple T ON ( T.t = G.t ) WHERE T.t IS NULL LIMIT 1 diff --git a/store/ARC2_StoreDescribeQueryHandler.php b/store/ARC2_StoreDescribeQueryHandler.php index b76a710d..0a78e142 100644 --- a/store/ARC2_StoreDescribeQueryHandler.php +++ b/store/ARC2_StoreDescribeQueryHandler.php @@ -12,6 +12,28 @@ class: ARC2 Store DESCRIBE Query Handler class ARC2_StoreDescribeQueryHandler extends ARC2_StoreSelectQueryHandler { + /** + * @var array + */ + public array $added_triples; + + /** + * @var array + */ + public array $described_ids; + + public int $detect_labels; + + /** + * @var array + */ + public array $ids; + + /** + * @var array + */ + public array $r; + public function __construct($a, &$caller) {/* caller has to be a store */ parent::__construct($a, $caller); diff --git a/store/ARC2_StoreDumpQueryHandler.php b/store/ARC2_StoreDumpQueryHandler.php index f00025f0..6d6b09cb 100755 --- a/store/ARC2_StoreDumpQueryHandler.php +++ b/store/ARC2_StoreDumpQueryHandler.php @@ -12,6 +12,11 @@ class: ARC2 RDF Store DUMP Query Handler class ARC2_StoreDumpQueryHandler extends ARC2_StoreQueryHandler { + /** + * @var array + */ + public array $infos; + public function __construct($a, &$caller) {/* caller has to be a store */ parent::__construct($a, $caller); @@ -23,6 +28,11 @@ public function __init() $this->store = $this->caller; } + /** + * @param int $keep_bnode_ids Deprecated and value will be ignored! + * + * @return int Always returns 1 + */ public function runQuery($infos, $keep_bnode_ids = 0) { $this->infos = $infos; diff --git a/store/ARC2_StoreDumper.php b/store/ARC2_StoreDumper.php index 939d7226..20fbb3c7 100755 --- a/store/ARC2_StoreDumper.php +++ b/store/ARC2_StoreDumper.php @@ -4,6 +4,7 @@ * * @author Benjamin Nowack * @license W3C Software License and GPL + * * @homepage * * @version 2010-11-16 @@ -12,6 +13,10 @@ class ARC2_StoreDumper extends ARC2_Class { + public int $keep_time_limit; + public int $limit; + public $store; + public function __construct($a, &$caller) { parent::__construct($a, $caller); @@ -219,7 +224,7 @@ public function getSafeValue($val) $froms[$i] = urldecode($from); } $val = str_replace($froms, $tos, $val); - if (false !== strpos($val, '\n"; } else { $val = htmlspecialchars($val); diff --git a/store/ARC2_StoreEndpoint.php b/store/ARC2_StoreEndpoint.php index 0dea2933..bc9153f7 100755 --- a/store/ARC2_StoreEndpoint.php +++ b/store/ARC2_StoreEndpoint.php @@ -4,6 +4,7 @@ * * @author Benjamin Nowack * @license W3C Software License and GPL + * * @homepage * * @version 2010-11-16 @@ -12,6 +13,20 @@ class ARC2_StoreEndpoint extends ARC2_Store { + public int $allow_sql; + + /** + * @var array + */ + public array $headers; + + public int $is_dump; + public string $query_result; + public string $read_key; + public string $result; + public int $timeout; + public string $write_key; + public function __construct($a, &$caller) { parent::__construct($a, $caller); @@ -98,9 +113,9 @@ public function handleRequest($auto_setup = 0) $this->setHeader('content-type', 'Content-type: text/plain; charset=utf-8'); $this->result = 'Missing configuration or the endpoint store was not set up yet.'; } - } elseif (($img = $this->p('img'))) { + } elseif ($img = $this->p('img')) { $this->handleImgRequest($img); - } elseif (($q = $this->p('query'))) { + } elseif ($q = $this->p('query')) { $this->checkProcesses(); $this->handleQueryRequest($q); if ($this->p('show_inline')) { diff --git a/store/ARC2_StoreHelper.php b/store/ARC2_StoreHelper.php index 7355fde2..db5068fc 100755 --- a/store/ARC2_StoreHelper.php +++ b/store/ARC2_StoreHelper.php @@ -12,6 +12,8 @@ class: ARC2 RDF Store Helper class ARC2_StoreHelper extends ARC2_Class { + public $store; + public function __construct($a, &$caller) { parent::__construct($a, $caller); diff --git a/store/ARC2_StoreInsertQueryHandler.php b/store/ARC2_StoreInsertQueryHandler.php index 8f0bd729..69a97ef3 100644 --- a/store/ARC2_StoreInsertQueryHandler.php +++ b/store/ARC2_StoreInsertQueryHandler.php @@ -4,12 +4,18 @@ * * @author Benjamin Nowack * @license W3C Software License and GPL + * * @homepage */ ARC2::inc('StoreQueryHandler'); class ARC2_StoreInsertQueryHandler extends ARC2_StoreQueryHandler { + /** + * @var array + */ + public array $infos; + public function __construct($a, &$caller) {/* caller has to be a store */ parent::__construct($a, $caller); diff --git a/store/ARC2_StoreLoadQueryHandler.php b/store/ARC2_StoreLoadQueryHandler.php index c8221157..edf52d88 100644 --- a/store/ARC2_StoreLoadQueryHandler.php +++ b/store/ARC2_StoreLoadQueryHandler.php @@ -4,15 +4,74 @@ * * @author Benjamin Nowack * @license W3C Software License and GPL + * * @homepage */ - -use ARC2\Store\Adapter\PDOSQLiteAdapter; - ARC2::inc('StoreQueryHandler'); class ARC2_StoreLoadQueryHandler extends ARC2_StoreQueryHandler { + public string $column_type; + public string $fixed_target_graph; + public int $has_lock; + public int $keep_bnode_ids; + public int $log_inserts; + + /** + * @var array + */ + public array $inserts; + + /** + * @var array + */ + public array $insert_times; + + /** + * @var int + */ + public $max_term_id; + + /** + * @var int + */ + public $max_triple_id; + + public int $split_threshold; + + /** + * @var array + */ + public array $sql_buffers; + + public int $strip_mb_comp_str; + public string $target_graph; + + /** + * @var array + */ + public array $term_ids; + + /** + * @var array + */ + public array $triple_ids; + + public int $t_count; + public int $t_count_prev; + + /** + * @var string|float + */ + public $t_prev; + + /** + * @var string|float + */ + public $t_start; + + public int $write_buffer_size; + public function __construct($a, &$caller) { /* caller has to be a store */ @@ -105,7 +164,7 @@ public function runQuery($infos, $data = '', $keep_bnode_ids = 0) } $this->store->releaseLock(); - if ((1 == rand(1, 100))) { + if (1 == rand(1, 100)) { $this->store->optimizeTables(); } @@ -171,18 +230,7 @@ public function getMaxTermID() $sql = ''; foreach (['id2val', 's2val', 'o2val'] as $tbl) { $sql .= $sql ? ' UNION ' : ''; - - // if its NOT SQLite add ( and ) around each SELECT ... FROM ... part - if (false === $this->store->getDBObject() instanceof PDOSQLiteAdapter) { - $sql .= '('; - } - - $sql .= 'SELECT MAX(id) as id FROM '.$this->store->getTablePrefix().$tbl; - - // if its NOT SQLite add ( and ) around each SELECT ... FROM ... part - if (false === $this->store->getDBObject() instanceof PDOSQLiteAdapter) { - $sql .= ')'; - } + $sql .= '(SELECT MAX(id) as id FROM '.$this->store->getTablePrefix().$tbl.')'; } $r = 0; @@ -243,15 +291,9 @@ public function getStoredTermID($val, $type_id, $tbl) $id = 0; /* via hash */ if (preg_match('/^(s2val|o2val)$/', $sub_tbl) && $this->hasHashColumn($sub_tbl)) { - if ($this->store->getDBObject() instanceof PDOSQLiteAdapter) { - $sql = 'SELECT id, val - FROM '.$tbl_prefix.$sub_tbl.' - WHERE val_hash = "'.$this->getValueHash($val).'"'; - } else { - $sql = 'SELECT id, val + $sql = 'SELECT id, val FROM '.$tbl_prefix.$sub_tbl." WHERE val_hash = BINARY '".$this->getValueHash($val)."'"; - } $rows = $this->store->a['db_object']->fetchList($sql); if (is_array($rows)) { @@ -264,21 +306,12 @@ public function getStoredTermID($val, $type_id, $tbl) } } else { $binaryValue = $this->store->a['db_object']->escape($val); - if (false !== empty($binaryValue)) { - if ($this->store->getDBObject() instanceof PDOSQLiteAdapter) { - $sql = 'SELECT id - FROM '.$tbl_prefix.$sub_tbl." - WHERE val = '".$binaryValue."'"; - } else { - $sql = 'SELECT id - FROM '.$tbl_prefix.$sub_tbl." - WHERE val = BINARY '".$binaryValue."'"; - } - - $row = $this->store->a['db_object']->fetchRow($sql); - if (is_array($row) && isset($row['id'])) { - $id = $row['id']; - } + // Updated by Craig Dietrich 19 February 2020: + // Always let through, even if empty since the id2val is storing empty values, too + $sql = 'SELECT id AS `id` FROM '.$tbl_prefix.$sub_tbl." WHERE val = BINARY '".$binaryValue."'"; + $row = $this->store->a['db_object']->fetchRow($sql); + if (is_array($row) && isset($row['id'])) { + $id = $row['id']; } } if ($id) { @@ -399,14 +432,7 @@ public function bufferTripleSQL($t) $tbl = 'triple'; $sql = ', '; - /* - * Use appropriate INSERT syntax, depending on the DBS. - */ - if ($this->store->getDBObject() instanceof PDOSQLiteAdapter) { - $sqlHead = 'INSERT OR IGNORE INTO '; - } else { - $sqlHead = 'INSERT IGNORE INTO '; - } + $sqlHead = 'INSERT IGNORE INTO '; if (!isset($this->sql_buffers[$tbl])) { $this->sql_buffers[$tbl] = $sqlHead; @@ -427,14 +453,7 @@ public function bufferGraphSQL($g2t) $tbl = 'g2t'; $sql = ', '; - /* - * Use appropriate INSERT syntax, depending on the DBS. - */ - if ($this->store->getDBObject() instanceof PDOSQLiteAdapter) { - $sqlHead = 'INSERT OR IGNORE INTO '; - } else { - $sqlHead = 'INSERT IGNORE INTO '; - } + $sqlHead = 'INSERT IGNORE INTO '; if (!isset($this->sql_buffers[$tbl])) { $this->sql_buffers[$tbl] = $sqlHead.$this->store->getTablePrefix().$tbl.' (g, t) VALUES'; @@ -459,15 +478,7 @@ public function bufferIDSQL($tbl, $id, $val, $val_type) if (!isset($this->sql_buffers[$tbl])) { $this->sql_buffers[$tbl] = ''; - /* - * Use appropriate INSERT syntax, depending on the DBS. - */ - if ($this->store->getDBObject() instanceof PDOSQLiteAdapter) { - $sqlHead = 'INSERT OR IGNORE INTO '; - } else { - $sqlHead = 'INSERT IGNORE INTO '; - } - + $sqlHead = 'INSERT IGNORE INTO '; $sql = $sqlHead.$this->store->getTablePrefix().$tbl.'('.$cols.') VALUES '; } else { $sql = ', '; diff --git a/store/ARC2_StoreQueryHandler.php b/store/ARC2_StoreQueryHandler.php index 98f93d32..104bdea5 100755 --- a/store/ARC2_StoreQueryHandler.php +++ b/store/ARC2_StoreQueryHandler.php @@ -4,6 +4,7 @@ * * @author Benjamin Nowack * @license W3C Software License and GPL + * * @homepage * * @version 2010-11-16 @@ -12,6 +13,13 @@ class ARC2_StoreQueryHandler extends ARC2_Class { + public int $allow_extension_functions; + public int $keep_time_limit; + public string $handler_type; + public string $mrg_table_id; + public object $store; + public string $xsd; + public function __construct($a, &$caller) { parent::__construct($a, $caller); @@ -80,10 +88,11 @@ public function createMergeTable() $sql .= ','.$prefix.'triple_'.abs(crc32($p)); } $sql .= ')'; + // TODO whats about that? - //$sql .= ($v >= '04-00-00') ? " CHARACTER SET utf8" : ""; - //$sql .= ($v >= '04-01-00') ? " COLLATE utf8_unicode_ci" : ""; - //echo $sql; + // $sql .= ($v >= '04-00-00') ? " CHARACTER SET utf8" : ""; + // $sql .= ($v >= '04-01-00') ? " COLLATE utf8_unicode_ci" : ""; + // echo $sql; return $this->getDBObject()->query($sql); } @@ -92,7 +101,7 @@ public function dropMergeTable() return 1; // TODO triple_all table seems not used anymore, therefore this function can be removed? $sql = 'DROP TABLE IF EXISTS '.$this->store->getTablePrefix().'triple_all'; - //echo $sql; - //return $this->queryDB($sql, $this->store->getDBCon()); + // echo $sql; + // return $this->queryDB($sql, $this->store->getDBCon()); } } diff --git a/store/ARC2_StoreRSSLoader.php b/store/ARC2_StoreRSSLoader.php index d21ac86e..13f46166 100644 --- a/store/ARC2_StoreRSSLoader.php +++ b/store/ARC2_StoreRSSLoader.php @@ -12,6 +12,8 @@ class: ARC2 Store RSS(2) Loader class ARC2_StoreRSSLoader extends ARC2_RSSParser { + public int $t_count = 0; + public function __construct($a, &$caller) { parent::__construct($a, $caller); diff --git a/store/ARC2_StoreSPOGLoader.php b/store/ARC2_StoreSPOGLoader.php index 080c6896..6b1e760a 100755 --- a/store/ARC2_StoreSPOGLoader.php +++ b/store/ARC2_StoreSPOGLoader.php @@ -12,6 +12,8 @@ class: ARC2 Store SPOG Loader class ARC2_StoreSPOGLoader extends ARC2_SPOGParser { + public int $t_count = 0; + public function __construct($a, &$caller) { parent::__construct($a, $caller); diff --git a/store/ARC2_StoreSelectQueryHandler.php b/store/ARC2_StoreSelectQueryHandler.php index d5df57f0..2c2d45ff 100644 --- a/store/ARC2_StoreSelectQueryHandler.php +++ b/store/ARC2_StoreSelectQueryHandler.php @@ -4,17 +4,52 @@ * * @author Benjamin Nowack * @license W3C Software License and GPL + * * @homepage * * @version 2010-11-16 */ - -use ARC2\Store\Adapter\PDOSQLiteAdapter; - ARC2::inc('StoreQueryHandler'); class ARC2_StoreSelectQueryHandler extends ARC2_StoreQueryHandler { + public int $cache_results; + + /** + * @var array + */ + public array $dependency_log; + + public string $engine_type; + + /** + * @var array + */ + public array $index; + + /** + * @var array + */ + public array $indexes; + + /** + * @var array + */ + public array $initial_index; + + public int $is_union_query; + + /** + * @var array + */ + public array $infos; + + public $opt_sql; + + public int $opt_sql_pd_count; + + public int $pattern_order_offset; + public function __construct($a, &$caller) {/* caller has to be a store */ parent::__construct($a, $caller); @@ -25,7 +60,7 @@ public function __init() parent::__init(); $this->store = $this->caller; $this->handler_type = 'select'; - $this->engine_type = $this->v('store_engine_type', 'MyISAM', $this->a); + $this->engine_type = $this->v('store_engine_type', 'InnoDB', $this->a); $this->cache_results = $this->v('store_cache_results', 0, $this->a); } @@ -70,9 +105,7 @@ public function getSQL() $this->analyzeIndex($this->getPattern('0')); $sub_r = $this->getQuerySQL(); $r .= $r ? $nl.'UNION'.$this->getDistinctSQL().$nl : ''; - - $setBracket = $this->is_union_query && !$this->store->getDBObject() instanceof PDOSQLiteAdapter; - $r .= $setBracket ? '('.$sub_r.')' : $sub_r; + $r .= $this->is_union_query ? '('.$sub_r.')' : $sub_r; $this->indexes[$i] = $this->index; } @@ -134,15 +167,10 @@ public function createTempTable($q_sql) $tbl = 'Q'.md5($tbl); } - if ($this->store->getDBObject() instanceof PDOSQLiteAdapter) { - $tmp_sql = 'CREATE TABLE '.$tbl.' ( '; - $tmp_sql .= $this->getTempTableDefForSQLite($q_sql).')'; - } else { - $tmp_sql = 'CREATE TEMPORARY TABLE '.$tbl.' ( '; - $tmp_sql .= $this->getTempTableDefForMySQL($q_sql); - /* HEAP doesn't support AUTO_INCREMENT, and MySQL breaks on MEMORY sometimes */ - $tmp_sql .= ') ENGINE='.$this->engine_type; - } + $tmp_sql = 'CREATE TEMPORARY TABLE '.$tbl.' ( '; + $tmp_sql .= $this->getTempTableDefForMySQL($q_sql); + /* HEAP doesn't support AUTO_INCREMENT, and MySQL breaks on MEMORY sometimes */ + $tmp_sql .= ') ENGINE='.$this->engine_type; $tmpSql2 = str_replace('CREATE TEMPORARY', 'CREATE', $tmp_sql); @@ -267,7 +295,7 @@ public function getFinalQueryResult($q_sql, $tmp_tbl) in_array($var, $aggregate_vars) ? 'literal' : 'uri' - ); + ); if (isset($pre_row[$var.' lang_dt']) && ($lang_dt = $pre_row[$var.' lang_dt'])) { if (preg_match('/^([a-z]+(\-[a-z0-9]+)*)$/i', $lang_dt)) { $row[$var.' lang'] = $lang_dt; @@ -807,7 +835,7 @@ public function getJoinConditionSQL($id) } /* filters etc */ if ($sub_r = $this->getPatternSQL($pattern, 'join__T_'.$id)) { - $r .= $r ? $nl.' AND '.$sub_r : $nl.' '.'('.$sub_r.')'; + $r .= $r ? $nl.' AND '.$sub_r : $nl.' ('.$sub_r.')'; } return $r; @@ -860,7 +888,7 @@ public function joinDependsOn($id, $id2) return 1; } $d_tbls = $this->getDependentJoins($id2); - //echo $id . ' :: ' . $id2 . '=>' . print_r($d_tbls, 1); + // echo $id . ' :: ' . $id2 . '=>' . print_r($d_tbls, 1); foreach ($d_tbls as $d_tbl) { if (preg_match('/^T_'.$id.'\./', $d_tbl)) { return 1; @@ -1080,7 +1108,7 @@ public function getTriplePatternSQL($pattern, $context) } elseif ('var' == $type) { $val = $pattern[$term]; if (isset($vars[$val])) {/* repeated var in pattern */ - $sub_r = '(T_'.$id.'.'.$term.'='.'T_'.$id.'.'.$vars[$val].')'; + $sub_r = '(T_'.$id.'.'.$term.'=T_'.$id.'.'.$vars[$val].')'; } $vars[$val] = $term; if ($infos = $this->v($val, 0, $this->index['graph_vars'])) {/* graph var in triple pattern */ @@ -1391,22 +1419,6 @@ public function getRelationalExpressionSQL($pattern, $context, $val_type = '', $ $r .= $r ? ' '.$op.' '.$sub_r : $sub_r; } - /* - * SQLite related adaption for relational expressions like ?w < 100 - * - * We have to cast the variable behind ?w to a number otherwise we don't get - * meaningful results. - */ - if ($this->store->getDBObject() instanceof PDOSQLiteAdapter) { - // Regex to catch things like: ?w < 100, ?w > 20 - $regex = '/([T\_0-9]+\.o_comp)\s*[<>]{1}\s*[0-9]+/si'; - if (0 < preg_match_all($regex, $r, $matches)) { - foreach ($matches[1] as $variable) { - $r = str_replace($variable, 'CAST ('.$variable.' as float)', $r); - } - } - } - return $r ? '('.$r.')' : $r; } @@ -1477,7 +1489,7 @@ public function getVarExpressionSQL($pattern, $context, $val_type = '', $parent_ } elseif ( ('relational' == $parent_type) && 'o' == $col - && (preg_match('/[\<\>]/', $this->v('parent_op', '', $pattern)))) { + && preg_match('/[\<\>]/', $this->v('parent_op', '', $pattern))) { $tbl_alias = 'T_'.$tbl.'.o_comp'; } else { $tbl_alias = 'V_'.$tbl.'_'.$col.'.val'; @@ -1615,7 +1627,7 @@ public function getFunctionExpressionSQL($pattern, $context, $val_type = '', $pa /* any other: ignore */ } /* simple type conversions */ - if (0 === strpos($fnc_uri, 'http://www.w3.org/2001/XMLSchema#')) { + if (str_starts_with($fnc_uri, 'http://www.w3.org/2001/XMLSchema#')) { return $op.$this->getExpressionSQL($pattern['args'][0], $context, $val_type, $parent_type); } @@ -1761,8 +1773,7 @@ public function getLangmatchesCallSQL($pattern, $context) if (preg_match('/^([\"\'])([^\'\"]+)/', $sub_r_2, $m)) { if ('*' == $m[2]) { $r = '!' == $op - ? 'NOT ('.$sub_r_1.' REGEXP "^[a-zA-Z\-]+$"'.')' - : $sub_r_1.' REGEXP "^[a-zA-Z\-]+$"'; + ? 'NOT ('.$sub_r_1.' REGEXP "^[a-zA-Z\-]+$")' : $sub_r_1.' REGEXP "^[a-zA-Z\-]+$"'; } else { $r = ('!' == $op) ? $sub_r_1.' NOT LIKE '.$m[1].$m[2].'%'.$m[1] : $sub_r_1.' LIKE '.$m[1].$m[2].'%'.$m[1]; } @@ -1814,7 +1825,7 @@ public function getRegexCallSQL($pattern, $context) /* fulltext search (may have "|") */ if ($is_simple_search && $is_o_search && !$op && (strlen($m[2]) > 8) && $this->store->hasFulltextIndex()) { /* MATCH variations */ - if (($val_parts = preg_split('/\|/', $m[2]))) { + if ($val_parts = preg_split('/\|/', $m[2])) { return 'MATCH('.trim($sub_r_1, '()').') AGAINST("'.implode(' ', $val_parts).'")'; } else { return 'MATCH('.trim($sub_r_1, '()').') AGAINST("'.$m[2].'")'; @@ -1831,10 +1842,7 @@ public function getRegexCallSQL($pattern, $context) return $sub_r_1.$op.' LIKE "'.$sub_r_2.'"'; } /* REGEXP */ - $opt = ''; - if (!$this->store->getDBObject() instanceof PDOSQLiteAdapter) { - $opt = ('i' == $sub_r_3) ? '' : 'BINARY '; - } + $opt = ('i' == $sub_r_3) ? '' : 'BINARY '; return $sub_r_1.$op.' REGEXP '.$opt.$sub_r_2; } @@ -1938,7 +1946,7 @@ public function getValueSQL($q_tbl, $q_sql) if (in_array($col, ['s', 'o'])) { if (strpos($q_sql, '`'.$var_name.' type`')) { $r .= ', '.$nl.' TMP.`'.$var_name.' type` AS `'.$var_name.' type`'; - //$r .= ', ' . $nl . ' CASE TMP.`' . $var_name . ' type` WHEN 2 THEN "literal" WHEN 1 THEN "bnode" ELSE "uri" END AS `' . $var_name . ' type`'; + // $r .= ', ' . $nl . ' CASE TMP.`' . $var_name . ' type` WHEN 2 THEN "literal" WHEN 1 THEN "bnode" ELSE "uri" END AS `' . $var_name . ' type`'; } else { $r .= ', '.$nl.' NULL AS `'.$var_name.' type`'; } diff --git a/store/ARC2_StoreSemHTMLLoader.php b/store/ARC2_StoreSemHTMLLoader.php index 0b2b6a37..aa06afc8 100644 --- a/store/ARC2_StoreSemHTMLLoader.php +++ b/store/ARC2_StoreSemHTMLLoader.php @@ -12,6 +12,8 @@ class: ARC2 Store SemHTML Loader class ARC2_StoreSemHTMLLoader extends ARC2_SemHTMLParser { + public int $t_count = 0; + public function __construct($a, &$caller) { parent::__construct($a, $caller); diff --git a/store/ARC2_StoreTableManager.php b/store/ARC2_StoreTableManager.php index 6b10f43c..a32d2f55 100755 --- a/store/ARC2_StoreTableManager.php +++ b/store/ARC2_StoreTableManager.php @@ -7,9 +7,6 @@ * * @version 2010-11-16 */ - -use ARC2\Store\Adapter\PDOSQLiteAdapter; - ARC2::inc('Store'); /** @@ -17,6 +14,8 @@ */ class ARC2_StoreTableManager extends ARC2_Store { + protected string $engine_type; + public function __construct($a, &$caller) { parent::__construct($a, $caller); @@ -25,7 +24,7 @@ public function __construct($a, &$caller) public function __init() { parent::__init(); - $this->engine_type = $this->v('store_engine_type', 'MyISAM', $this->a); + $this->engine_type = $this->v('store_engine_type', 'InnoDB', $this->a); } public function getTableOptionsCode() @@ -152,7 +151,7 @@ public function extendId2valTableColumns($suffix = 'id2val') public function createS2ValTable() { - //$indexes = 'UNIQUE KEY (id), KEY vh (val_hash), KEY v (val(64))'; + // $indexes = 'UNIQUE KEY (id), KEY vh (val_hash), KEY v (val(64))'; $indexes = 'UNIQUE KEY (id), KEY vh (val_hash)'; $sql = ' CREATE TABLE IF NOT EXISTS '.$this->getTablePrefix().'s2val ( @@ -258,14 +257,7 @@ public function unsplitPredicate($p) $new_tbl = $this->getTablePrefix().'triple'; $p_id = $this->getTermID($p, 'p'); - /* - * Use appropriate INSERT syntax, depending on the DBS. - */ - if ($this->store->getDBObject() instanceof PDOSQLiteAdapter) { - $sqlHead = 'INSERT OR IGNORE INTO '; - } else { - $sqlHead = 'INSERT IGNORE INTO '; - } + $sqlHead = 'INSERT IGNORE INTO '; $sql = $sqlHead.$new_tbl.' SELECT * FROM '.$old_tbl.' WHERE '.$old_tbl.'.p = '.$p_id; if ($this->a['db_object']->simpleQuery($sql)) { @@ -285,14 +277,7 @@ public function splitPredicate($p) $new_tbl = $this->getTablePrefix().$suffix; $p_id = $this->getTermID($p, 'p'); - /* - * Use appropriate INSERT syntax, depending on the DBS. - */ - if ($this->store->getDBObject() instanceof PDOSQLiteAdapter) { - $sqlHead = 'INSERT OR IGNORE INTO '; - } else { - $sqlHead = 'INSERT IGNORE INTO '; - } + $sqlHead = 'INSERT IGNORE INTO '; $sql = $sqlHead.$new_tbl.'SELECT * FROM '.$old_tbl.' WHERE '.$old_tbl.'.p = '.$p_id; if ($this->a['db_object']->simpleQuery($sql)) { diff --git a/store/ARC2_StoreTurtleLoader.php b/store/ARC2_StoreTurtleLoader.php index 59f065b8..d3038308 100644 --- a/store/ARC2_StoreTurtleLoader.php +++ b/store/ARC2_StoreTurtleLoader.php @@ -12,6 +12,8 @@ class: ARC2 Store Turtle Loader class ARC2_StoreTurtleLoader extends ARC2_TurtleParser { + public int $t_count = 0; + public function __construct($a, &$caller) { parent::__construct($a, $caller); diff --git a/tests/ARC2_TestCase.php b/tests/ARC2_TestCase.php index a2682f23..82abb8b2 100644 --- a/tests/ARC2_TestCase.php +++ b/tests/ARC2_TestCase.php @@ -3,7 +3,6 @@ namespace Tests; use PHPUnit\Framework\TestCase; -use Psr\SimpleCache\CacheInterface; class ARC2_TestCase extends TestCase { @@ -16,36 +15,28 @@ class ARC2_TestCase extends TestCase /** * Subject under test. - * - * @var mixed */ protected $fixture; protected function setUp(): void { + parent::setUp(); + global $dbConfig; $this->dbConfig = $dbConfig; - - // in case we run with a cache, clear it - if ( - isset($this->dbConfig['cache_instance']) - && $this->dbConfig['cache_instance'] instanceof CacheInterface - ) { - $this->dbConfig['cache_instance']->clear(); - } } - protected function tearDown(): void + /** + * Depending on the DB config returns current table prefix. It consists of table prefix and store name, if available. + * + * @return string + */ + protected function getSqlTablePrefix() { - // in case we run with a cache, clear it - if ( - isset($this->dbConfig['cache_instance']) - && $this->dbConfig['cache_instance'] instanceof CacheInterface - ) { - $this->dbConfig['cache_instance']->clear(); - } - - parent::tearDown(); + $prefix = isset($this->dbConfig['db_table_prefix']) ? $this->dbConfig['db_table_prefix'].'_' : ''; + $prefix .= isset($this->dbConfig['store_name']) ? $this->dbConfig['store_name'].'_' : ''; + + return $prefix; } } diff --git a/tests/ARC2_TestHandler.php b/tests/ARC2_TestHandler.php index 296a4ab7..96ed5ec0 100644 --- a/tests/ARC2_TestHandler.php +++ b/tests/ARC2_TestHandler.php @@ -12,6 +12,10 @@ class: ARC2 DAWG Test Handler class ARC2_TestHandler extends ARC2_Class { + public $data_store; + public $reader; + public $store; + public function __construct($a, &$caller, &$data_store) {/* caller has to be a store */ parent::__construct($a, $caller); @@ -175,7 +179,7 @@ public function runQueryEvaluationTest($id) ${$var.'_value'} = $infos[$var.'_value'][0]; } if ($$var && ('-result' != $var)) { - //echo '
' . $$var . $nl . $nl . htmlspecialchars(${$var . '_value'}) . '

'; + // echo '
' . $$var . $nl . $nl . htmlspecialchars(${$var . '_value'}) . '

'; } } /* query infos */ @@ -224,7 +228,7 @@ public function runQueryEvaluationTest($id) $qr_result = $ser->getSerializedIndex($qr_result); } } - //echo '
query result: ' . $nl . htmlspecialchars(print_r($qr_result, 1)) . '
'; + // echo '
query result: ' . $nl . htmlspecialchars(print_r($qr_result, 1)) . '
'; if (!$query || $errors || $rest) { return ['pass' => 0, 'info' => 'query could not be parsed'.htmlspecialchars($query_value)]; } @@ -251,7 +255,7 @@ public function runQueryEvaluationTest($id) $info .= $pass ? '' : print_r($graph_data, 1).$nl.htmlspecialchars(print_r($graph_data_value, 1)).'
'; $info .= $pass ? '' : print_r($data, 1).$nl.htmlspecialchars(print_r($data_value, 1)).'
'; $info .= $pass ? '' : $query.$nl.htmlspecialchars($query_value).'
'; - $info .= $pass ? '' : '
query result: '.$nl.htmlspecialchars(print_r($qr_result, 1)).'
'.'
'; + $info .= $pass ? '' : '
query result: '.$nl.htmlspecialchars(print_r($qr_result, 1)).'

'; $info .= $pass ? '' : print_r($infos, 1); return ['pass' => $pass, 'info' => $info]; @@ -263,7 +267,7 @@ public function isSameSelectResult($qr, $result, $result_base) $parser = ARC2::getRDFParser($this->a); $parser->parse($result_base, $result); $index = $parser->getSimpleIndex(0); - //echo '
' . print_r($index, 1) .'
'; + // echo '
' . print_r($index, 1) .'
'; $valid_qr = $this->buildTurtleSelectQueryResult($index); } else { $parser = ARC2::getSPARQLXMLResultParser($this->a); @@ -293,7 +297,7 @@ public function isSameSelectResult($qr, $result, $result_base) $valid_index = $this->buildArrayHashIndex($valid_qr['rows']); if (($diff = array_diff($index, $valid_index)) || ($diff = array_diff($valid_index, $index))) { $pass = 0; - //echo '
' . print_r($diff, 1) . '
'; + // echo '
' . print_r($diff, 1) . '
'; } } } @@ -312,7 +316,7 @@ public function isSameConstructResult($qr, $result, $result_base, $test) $info = '
'.print_r($valid_triples, 1).'
'; $info = ''; - //echo '
' . print_r($index, 1) .'
'; + // echo '
' . print_r($index, 1) .'
'; $pass = 0; if (in_array($test, [/* manually checked 2007-09-21 */ 'http://www.w3.org/2001/sw/DataAccess/tests/data-r2/construct/manifest#construct-1', @@ -363,7 +367,7 @@ public function buildTurtleSelectQueryResult($index) $var = $index[$binding_id][$rs.'variable'][0]['value']; $val = $index[$binding_id][$rs.'value'][0]['value']; $val_type = $index[$binding_id][$rs.'value'][0]['type']; - //$val_type = preg_match('/literal/', $val_type) ? 'literal' : $val_type; + // $val_type = preg_match('/literal/', $val_type) ? 'literal' : $val_type; $row[$var] = $val; $row[$var.' type'] = $val_type; if ($dt = $this->v('datatype', 0, $index[$binding_id][$rs.'value'][0])) { diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 24220dc0..17b0dbb3 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -2,7 +2,7 @@ require_once __DIR__.'/../vendor/autoload.php'; -error_reporting(E_ALL); +error_reporting(\E_ALL); require 'ARC2_TestHandler.php'; @@ -13,69 +13,61 @@ /* * For local development only. * - * Copy config.php.dist to config.php, adapt your values - * and run PHPUnit. + * Copy config.php.dist to config.php, adapt your values and run PHPUnit. */ + if (file_exists(__DIR__.'/config.php')) { $dbConfig = require 'config.php'; -} else { +} elseif (isset($_SERVER['GITHUB_PATH'])) { /* - * For CI only. + * For CI Github workflow only. * * Parameter are set from outside using environment variables. * Please check YAML files in .github/workflows for details. */ + $dbConfig = [ + 'db_name' => 'arc2_test', + 'db_user' => 'root', + 'db_pwd' => 'Pass123', + 'db_host' => '127.0.0.1', + 'db_port' => $_SERVER['DB_PORT'] ?? 3306, + ]; + /* - * if SQLite in memory only: unset db_name to force it to use sqlite::memory: + * DB Adapter */ - $useSQLiteMemory = getenv('DB_SQLITE_IN_MEMORY') ?? $_SERVER['DB_SQLITE_IN_MEMORY']; - if ('true' == $useSQLiteMemory) { - $dbConfig = ['db_adapter' => 'pdo', 'db_pdo_protocol' => 'sqlite']; - } else { - /** - * Either one of: pdo (mysql, sqlite), mysqli. - */ - $dbConfig = [ - 'db_name' => 'arc2_test', - 'db_user' => 'root', - 'db_pwd' => 'Pass123', - 'db_host' => '127.0.0.1', - 'db_port' => $_SERVER['DB_PORT'] ?: 3306, - ]; + $dbConfig['db_adapter'] = getenv('DB_ADAPTER') ?? $_SERVER['DB_ADAPTER']; + if (false === $dbConfig['db_adapter']) { + $dbConfig['db_adapter'] = 'pdo'; + } - /* - * DB Adapter (PDO or mysqli) - */ - $dbConfig['db_adapter'] = getenv('DB_ADAPTER') ?? $_SERVER['DB_ADAPTER']; - if ('pdo' == $dbConfig['db_adapter']) { - $dbConfig['db_pdo_protocol'] = getenv('DB_PDO_PROTOCOL') ?? $_SERVER['DB_PDO_PROTOCOL']; + // in pre 3.x ARC2 supported mysqli too. because of that the switch is still there just in case + // another adapter will be added in the future - if (empty($dbConfig['db_pdo_protocol'])) { - throw new \Exception('Neither environment variable DB_PDO_PROTOCOL nor $_SERVER["DB_PDO_PROTOCOL"] are set.'.' Possible values are: mysql, sqlite'); - } - } elseif ('mysqli' == $dbConfig['db_adapter']) { - $dbConfig['db_adapter'] = 'mysqli'; - } else { - throw new Exception('Neither environment variable DB_ADAPTER nor $_SERVER["DB_ADAPTER"] are set.'); + if ('pdo' == $dbConfig['db_adapter']) { + $dbConfig['db_pdo_protocol'] = getenv('DB_PDO_PROTOCOL') ?? $_SERVER['DB_PDO_PROTOCOL']; + if (false === $dbConfig['db_pdo_protocol']) { + $dbConfig['db_pdo_protocol'] = 'mysql'; } - // set defaults for dbConfig entries - if (false == isset($dbConfig['store_name'])) { - $dbConfig['store_name'] = 'arc'; + if (is_string($dbConfig['db_pdo_protocol']) && '' !== $dbConfig['db_pdo_protocol']) { + // OK + } else { + $msg = 'Neither environment variable DB_PDO_PROTOCOL nor $_SERVER["DB_PDO_PROTOCOL"] are set.' + .' Possible values are: mysql'; + throw new \Exception($msg); } + } else { + throw new Exception('Neither environment variable DB_ADAPTER nor $_SERVER["DB_ADAPTER"] are set.'); + } - $dbConfig['db_table_prefix'] = $dbConfig['db_table_prefix'] ?? null; - - /* - * set cache enable - * - * if enabled, we use an instance of ArrayCache which is very fast - */ - $cacheEnabled = getenv('CACHE_ENABLED') ?? $_SERVER['CACHE_ENABLED']; - if (true === $cacheEnabled || 'true' == $cacheEnabled) { - $dbConfig['cache_enabled'] = true; - $dbConfig['cache_instance'] = new Symfony\Component\Cache\Simple\ArrayCache(); - } + // set defaults for dbConfig entries + if (false == isset($dbConfig['store_name'])) { + $dbConfig['store_name'] = 'arc'; } + + $dbConfig['db_table_prefix'] = $dbConfig['db_table_prefix'] ?? null; +} else { + $dbConfig = require 'config.php.dist'; } diff --git a/tests/config.php.dist b/tests/config.php.dist index 5859c5b8..5425dbd4 100644 --- a/tests/config.php.dist +++ b/tests/config.php.dist @@ -8,7 +8,7 @@ return array( 'db_name' => 'arc2_test', 'db_user' => 'root', 'db_pwd' => 'Pass123', - 'db_host' => '127.0.0.1', + 'db_host' => 'db', 'db_port' => 3306, 'db_adapter' => 'pdo', 'db_pdo_protocol' => 'mysql', diff --git a/tests/db_adapter_depended/ARC2_ClassTest.php b/tests/db_adapter_depended/ARC2_ClassTest.php deleted file mode 100644 index bd4c6898..00000000 --- a/tests/db_adapter_depended/ARC2_ClassTest.php +++ /dev/null @@ -1,67 +0,0 @@ -dbConfig['db_adapter']) { - $this->markTestSkipped('Db adapter is not mysqli, therefore skip tests with queryDB.'); - } - - $this->store = \ARC2::getStore($this->dbConfig); - $this->store->createDBCon(); - $this->store->setup(); - $this->dbConnection = $this->store->getDBCon(); - - $this->fixture = new \ARC2_Class($this->dbConfig, $this); - } - - /* - * Tests for queryDB - */ - - public function testQueryDB() - { - $this->store->createDBCon(); - $this->store->setup(); - - $result = $this->fixture->queryDB('SHOW TABLES', $this->dbConnection); - $this->assertEquals(1, $result->field_count); - $this->assertTrue(0 < $result->num_rows); - } - - public function testQueryDBInvalidQuery() - { - $result = $this->fixture->queryDB('invalid-query', $this->dbConnection); - $this->assertFalse($result); - } - - public function testQueryDBInvalidQueryWithLog() - { - $result = $this->fixture->queryDB('invalid-query', $this->dbConnection, true); - $this->assertFalse($result); - - if ('mysql' == $this->store->getDBSName()) { - $dbsName = 'MySQL'; - } else { - $dbsName = 'MariaDB'; - } - - $this->assertEquals( - [ - 'You have an error in your SQL syntax; check the manual that corresponds to your ' - .$dbsName.' server version for the right syntax to use near \'invalid-query\' at line 1', - ], - $this->fixture->errors - ); - } -} diff --git a/tests/db_adapter_depended/README.md b/tests/db_adapter_depended/README.md index aff4db3b..19038f88 100644 --- a/tests/db_adapter_depended/README.md +++ b/tests/db_adapter_depended/README.md @@ -2,4 +2,4 @@ All tests in this folder are dependend on what environment variables are set OR what `tests/config.php` contains. -If you wanna check certain database backends, adapt `tests/config.php` accordingly. +If you want to check certain database backends, adapt `tests/config.php` accordingly. diff --git a/tests/db_adapter_depended/sparql_1_1_tests/AggregatesTest.php b/tests/db_adapter_depended/sparql_1_1_tests/AggregatesTest.php index 885226a9..6f211a06 100644 --- a/tests/db_adapter_depended/sparql_1_1_tests/AggregatesTest.php +++ b/tests/db_adapter_depended/sparql_1_1_tests/AggregatesTest.php @@ -2,8 +2,6 @@ namespace Tests\db_adapter_depended\sparql_1_1_tests; -use ARC2\Store\Adapter\PDOSQLiteAdapter; - /** * Runs W3C tests from https://www.w3.org/2009/sparql/docs/tests/. * @@ -44,23 +42,15 @@ public function testAggAvg01() $actualResult = $this->store->query($testQuery); $actualResultAsXml = $this->getXmlVersionOfResult($actualResult); - if ($this->store->getDBObject() instanceof PDOSQLiteAdapter) { - // SQLite related - $this->assertEquals(2.22, (string) $actualResultAsXml->results->result->binding->literal[0]); - } else { - /* - * not SQLite - */ - $this->assertEquals( - '2', - (string) $actualResultAsXml->results->result->binding->literal[0] - ); - - // remember current behavior, but skip test anyway to show developer here is still a problem. - $this->markTestSkipped( - 'Rounding bug in AVG function (MySQL). See https://github.com/semsol/arc2/issues/99' - ); - } + $this->assertEquals( + '2', + (string) $actualResultAsXml->results->result->binding->literal[0] + ); + + // remember current behavior, but skip test anyway to show developer here is still a problem. + $this->markTestSkipped( + 'Rounding bug in AVG function (MySQL). See https://github.com/semsol/arc2/issues/99' + ); } public function testAggEmptyGroup() diff --git a/tests/db_adapter_depended/sparql_1_1_tests/ComplianceTest.php b/tests/db_adapter_depended/sparql_1_1_tests/ComplianceTest.php index fbd455cc..b21649a3 100644 --- a/tests/db_adapter_depended/sparql_1_1_tests/ComplianceTest.php +++ b/tests/db_adapter_depended/sparql_1_1_tests/ComplianceTest.php @@ -183,9 +183,9 @@ protected function getTestQuery($testUri) // add data graph information as FROM clause, because ARC2 can't handle default graph // queries. for more information see https://github.com/semsol/arc2/issues/72. - if (false !== strpos($query, 'ASK') - || false !== strpos($query, 'CONSTRUCT') - || false !== strpos($query, 'SELECT')) { + if (str_contains($query, 'ASK') + || str_contains($query, 'CONSTRUCT') + || str_contains($query, 'SELECT')) { $query = str_replace('WHERE', 'FROM <'.$this->dataGraphUri.'> WHERE', $query); } @@ -277,7 +277,7 @@ protected function getXmlVersionOfResult(array $result) $w->startElement('literal'); // its not part of the ARC2 result set, but expected later on - if (true === ctype_digit($row[$var])) { + if (true === ctype_digit((string) $row[$var])) { $w->writeAttribute('datatype', 'http://www.w3.org/2001/XMLSchema#integer'); } diff --git a/tests/db_adapter_depended/sparql_1_1_tests/SyntaxUpdate1Test.php b/tests/db_adapter_depended/sparql_1_1_tests/SyntaxUpdate1Test.php index ac770755..318aa435 100644 --- a/tests/db_adapter_depended/sparql_1_1_tests/SyntaxUpdate1Test.php +++ b/tests/db_adapter_depended/sparql_1_1_tests/SyntaxUpdate1Test.php @@ -209,7 +209,7 @@ public function testTest51() // check result $this->markTestSkipped( 'Query has to fail, but ARC2 returns an array as if query is considered valid. Query: ' - .PHP_EOL + .\PHP_EOL .$this->makeQueryA1Liner($query) ); } diff --git a/tests/db_adapter_depended/src/ARC2/Store/Adapter/CachedPDOAdapterTest.php b/tests/db_adapter_depended/src/ARC2/Store/Adapter/CachedPDOAdapterTest.php deleted file mode 100644 index 1b68193c..00000000 --- a/tests/db_adapter_depended/src/ARC2/Store/Adapter/CachedPDOAdapterTest.php +++ /dev/null @@ -1,93 +0,0 @@ -markTestSkipped('Test skipped, because extension pdo_mysql is not installed.'); - } - - parent::setUp(); - - // stop, if pdo_db_protocol is not set in dbConfig - if (!isset($this->dbConfig['db_pdo_protocol'])) { - $this->markTestSkipped('Test skipped, because db_pdo_protocol was not set.'); - } elseif ('mysql' != $this->dbConfig['db_pdo_protocol']) { - $this->markTestSkipped('Test skipped, because db_pdo_protocol is not "mysql".'); - } - - $this->dbConfig['cache_enabled'] = true; - - $this->fixture = new CachedPDOAdapter($this->dbConfig); - - // remove all tables - $this->fixture->deleteAllTables(); - } - - public function testFetchRow() - { - // create test data - $this->fixture->simpleQuery('CREATE TABLE users (id INT(6), name VARCHAR(30) NOT NULL)'); - $this->fixture->simpleQuery('INSERT INTO users (id, name) VALUE (1, "foobar");'); - $this->fixture->simpleQuery('INSERT INTO users (id, name) VALUE (2, "foobar2");'); - - $selectQuery = 'SELECT * FROM users WHERE id = 2'; - - // check that cache doesnt know $selectQuery yet. - $this->assertFalse($this->fixture->getCacheInstance()->has(hash('sha1', $selectQuery))); - - $user = $this->fixture->fetchRow($selectQuery); - - // check cache, that expected entry is available - $this->assertTrue($this->fixture->getCacheInstance()->has(hash('sha1', $selectQuery))); - - // check if $users is equal to the cached version - $this->assertEquals($user, $this->fixture->fetchRow($selectQuery)); - } - - public function testFetchList() - { - // create test data - $this->fixture->simpleQuery('CREATE TABLE users (id INT(6), name VARCHAR(30) NOT NULL)'); - $this->fixture->simpleQuery('INSERT INTO users (id, name) VALUE (1, "foobar");'); - $this->fixture->simpleQuery('INSERT INTO users (id, name) VALUE (2, "foobar2");'); - - $selectQuery = 'SELECT * FROM users'; - - // check that cache doesnt know $selectQuery yet. - $this->assertFalse($this->fixture->getCacheInstance()->has(hash('sha1', $selectQuery))); - - $users = $this->fixture->fetchList($selectQuery); - - // check cache, that expected entry is available - $this->assertTrue($this->fixture->getCacheInstance()->has(hash('sha1', $selectQuery))); - - // check if $users is equal to the cached version - $this->assertEquals($users, $this->fixture->fetchList($selectQuery)); - } - - public function testCacheInvalidationIfDBChanges() - { - // create test data - $this->fixture->simpleQuery('CREATE TABLE users (id INT(6), name VARCHAR(30) NOT NULL)'); - $this->fixture->simpleQuery('INSERT INTO users (id, name) VALUE (1, "foobar");'); - $this->fixture->simpleQuery('INSERT INTO users (id, name) VALUE (2, "foobar2");'); - - $selectQuery = 'SELECT * FROM users'; - - $users = $this->fixture->fetchList($selectQuery); - $this->assertTrue($this->fixture->getCacheInstance()->has(hash('sha1', $selectQuery))); - - // change table and therefore the DB => invalidation of the cache - $this->fixture->exec('DELETE FROM users WHERE id = 1'); - - $this->assertFalse($this->fixture->getCacheInstance()->has(hash('sha1', $selectQuery))); - } -} diff --git a/tests/db_adapter_depended/store/ARC2_StoreLoadQueryHandlerTest.php b/tests/db_adapter_depended/store/ARC2_StoreLoadQueryHandlerTest.php index 9c7e1147..18af0602 100644 --- a/tests/db_adapter_depended/store/ARC2_StoreLoadQueryHandlerTest.php +++ b/tests/db_adapter_depended/store/ARC2_StoreLoadQueryHandlerTest.php @@ -1,10 +1,7 @@ store->getDBObject()->deleteAllTables(); $this->store->setUp(); - $this->fixture = new ARC2_StoreLoadQueryHandler($this->store, $this); + $this->fixture = new \ARC2_StoreLoadQueryHandler($this->store, $this); } protected function tearDown(): void @@ -41,12 +38,9 @@ public function testExtendColumns(): void $this->assertEquals(16750001, $this->fixture->getStoredTermID('', '', '')); - // PDO + SQLite - if ($this->store->getDBObject() instanceof PDOSQLiteAdapter) { - } else { - // MySQL - $table_fields = $this->store->getDBObject()->fetchList('DESCRIBE arc_g2t'); - $this->assertEquals('int(10) unsigned', $table_fields[0]['Type']); - } + // MySQL + $table_fields = $this->store->getDBObject()->fetchList('DESCRIBE arc_g2t'); + $this->assertStringContainsString('int', $table_fields[0]['Type']); + $this->assertStringContainsString('unsigned', $table_fields[0]['Type']); } } diff --git a/tests/db_adapter_depended/store/ARC2_StoreTest.php b/tests/db_adapter_depended/store/ARC2_StoreTest.php index 31bf1677..ba605258 100644 --- a/tests/db_adapter_depended/store/ARC2_StoreTest.php +++ b/tests/db_adapter_depended/store/ARC2_StoreTest.php @@ -2,7 +2,6 @@ namespace Tests\db_adapter_depended\store; -use ARC2\Store\Adapter\PDOSQLiteAdapter; use Tests\ARC2_TestCase; class ARC2_StoreTest extends ARC2_TestCase @@ -143,7 +142,7 @@ public function testChangeNamespaceURIFilledStore() public function testCountDBProcesses() { - $this->assertTrue(\is_int($this->fixture->countDBProcesses())); + $this->assertTrue(0 < $this->fixture->countDBProcesses()); } /* @@ -260,7 +259,7 @@ public function testDump() ob_start(); $this->fixture->dump(); $dumpContent = ob_get_clean(); - error_reporting(E_ALL); + error_reporting(\E_ALL); $expectedXML = << @@ -299,17 +298,16 @@ public function testDump() public function testEnableFulltextSearch() { + if (str_starts_with($this->fixture->getDBObject()->getServerVersion(), '5.5.')) { + $this->markTestSkipped('InnoDB does not support fulltext in MySQL 5.5.x'); + } + $res1 = $this->fixture->enableFulltextSearch(); $res2 = $this->fixture->disableFulltextSearch(); $this->assertNull($res1); - if ($this->fixture->getDBObject() instanceof PDOSQLiteAdapter) { - // TODO remove that if else in the future, after ...FulltextSearch functions - // got more clear return values. - } else { - $this->assertEquals(1, $res2); - } + $this->assertEquals(1, $res2); $this->assertEquals(0, $this->fixture->a['db_object']->getErrorCode()); $this->assertEquals('', $this->fixture->a['db_object']->getErrorMessage()); @@ -322,15 +320,10 @@ public function testEnableFulltextSearch() // just check pattern public function testGetDBVersion() { - // SQLite - if ($this->fixture->getDBObject() instanceof PDOSQLiteAdapter) { - $pattern = '/[0-9]{1,}\.[0-9]{1,}\.[0-9]{1,}/'; - } else { - // MySQL - $pattern = '/[0-9]{2}-[0-9]{2}-[0-9]{2}/'; - } - $result = preg_match($pattern, $this->fixture->getDBVersion(), $match); - $this->assertEquals(1, $result); + $this->assertEquals( + $this->fixture->getDBObject()->getConnection()->query('select version()')->fetchColumn(), + $this->fixture->getDBVersion() + ); } /* @@ -584,7 +577,7 @@ public function testMultipleInsertQuerysInDifferentGraphs() { $this->markTestSkipped( 'Adding the same triple into two graphs does not work.' - .PHP_EOL.'Bug report: https://github.com/semsol/arc2/issues/114' + .\PHP_EOL.'Bug report: https://github.com/semsol/arc2/issues/114' ); /* @@ -639,7 +632,7 @@ public function testRenameTo() if (isset($this->dbConfig['db_table_prefix'])) { foreach ($this->fixture->getDBObject()->getAllTables() as $table) { - $this->assertTrue(false !== strpos($table, $this->dbConfig['db_table_prefix'].'_')); + $this->assertTrue(str_contains($table, $this->dbConfig['db_table_prefix'].'_')); } } @@ -657,7 +650,7 @@ public function testRenameTo() if ('sqlite_sequence' == $table) { continue; } - $this->assertTrue(false !== strpos($table, $prefix), 'Renaming failed for '.$table); + $this->assertTrue(str_contains($table, $prefix), 'Renaming failed for '.$table); } } @@ -723,13 +716,10 @@ public function testReplicateTo() { if ( '05-06' == substr($this->fixture->getDBVersion(), 0, 5) - && false === $this->fixture->getDBObject() instanceof PDOSQLiteAdapter ) { $this->markTestSkipped( 'With MySQL 5.6 ARC2_Store::replicateTo does not work. Tables keep their names.' ); - } elseif ($this->fixture->getDBObject() instanceof PDOSQLiteAdapter) { - $this->markTestSkipped('replicateTo not yet implemented when using SQLite.'); } // test data @@ -749,10 +739,10 @@ public function testReplicateTo() $foundArcPrefix = $foundReplicatePrefix = false; foreach ($tables as $table) { // check for original table - if (false !== strpos($table['Tables_in_'.$this->dbConfig['db_name']], $this->dbConfig['store_name'].'_')) { + if (str_contains($table['Tables_in_'.$this->dbConfig['db_name']], $this->dbConfig['store_name'].'_')) { $foundArcPrefix = true; - // check for replicated table - } elseif (false !== strpos($table['Tables_in_'.$this->dbConfig['db_name']], 'replicate_')) { + // check for replicated table + } elseif (str_contains($table['Tables_in_'.$this->dbConfig['db_name']], 'replicate_')) { $foundReplicatePrefix = true; } } @@ -774,4 +764,13 @@ public function testResetKeepSettings() $this->assertEquals(1, $this->fixture->hasSetting('foo')); } + + public function testMultipleInsertsSameStore() + { + $this->fixture->query('INSERT INTO { . }'); + $this->fixture->query('INSERT INTO { . }'); + + $res = $this->fixture->query('SELECT * FROM WHERE {?s ?p ?o.}'); + $this->assertEquals(2, \count($res['result']['rows'])); + } } diff --git a/tests/db_adapter_depended/store/query/InsertIntoQueryTest.php b/tests/db_adapter_depended/store/query/InsertIntoQueryTest.php index 36e3c529..110606fa 100644 --- a/tests/db_adapter_depended/store/query/InsertIntoQueryTest.php +++ b/tests/db_adapter_depended/store/query/InsertIntoQueryTest.php @@ -55,7 +55,7 @@ public function testInsertIntoAllKindsOfTriples() // e.g. file:///var/www/html/pier-and-peer/ARC2/vendor/phpunit/phpunit/phpunit# // therefore we build this prefix manually to check later $filePrefix = 'file://'.str_replace('tests/db_adapter_depended/store/query', '', __DIR__); - $filePrefix .= 'vendor/phpunit/phpunit/phpunit#'; + $filePrefix .= 'vendor/bin/phpunit#'; $this->assertEquals( [ @@ -379,9 +379,9 @@ public function testInsertIntoWhere() $this->markTestSkipped( 'ARC2 does not check the WHERE clause when inserting data. No data added at all.' - .PHP_EOL - .PHP_EOL.'FYI: https://www.w3.org/Submission/SPARQL-Update/#sec_examples and ' - .PHP_EOL.'https://github.com/semsol/arc2/wiki/SPARQL-#insert-example' + .\PHP_EOL + .\PHP_EOL.'FYI: https://www.w3.org/Submission/SPARQL-Update/#sec_examples and ' + .\PHP_EOL.'https://github.com/semsol/arc2/wiki/SPARQL-#insert-example' ); } } diff --git a/tests/db_adapter_depended/store/query/KnownNotWorkingSparqlQueriesTest.php b/tests/db_adapter_depended/store/query/KnownNotWorkingSparqlQueriesTest.php index a6ebaa09..1c83a16e 100644 --- a/tests/db_adapter_depended/store/query/KnownNotWorkingSparqlQueriesTest.php +++ b/tests/db_adapter_depended/store/query/KnownNotWorkingSparqlQueriesTest.php @@ -81,6 +81,11 @@ public function testSelectFilterLangMatchesWithStar() */ public function testSelectSameTerm() { + $this->markTestSkipped( + 'ARC2: solving sameterm does not work properly. The result contains elements multiple times. ' + .\PHP_EOL.'Expected behavior is described here: https://www.w3.org/TR/rdf-sparql-query/#func-sameTerm' + ); + // test data $this->fixture->query('INSERT INTO { "100" . @@ -109,15 +114,15 @@ public function testSelectSameTerm() 'c2 type' => 'uri', ], [ - 'c1' => 'http://container2', + 'c1' => 'http://container1', 'c1 type' => 'uri', - 'c2' => 'http://container1', + 'c2' => 'http://container2', 'c2 type' => 'uri', ], [ - 'c1' => 'http://container1', + 'c1' => 'http://container2', 'c1 type' => 'uri', - 'c2' => 'http://container2', + 'c2' => 'http://container1', 'c2 type' => 'uri', ], [ @@ -136,11 +141,6 @@ public function testSelectSameTerm() 10, true ); - - $this->markTestSkipped( - 'ARC2: solving sameterm does not work properly. The result contains elements multiple times. ' - .PHP_EOL.'Expected behavior is described here: https://www.w3.org/TR/rdf-sparql-query/#func-sameTerm' - ); } /** diff --git a/tests/db_adapter_depended/store/query/SelectQueryTest.php b/tests/db_adapter_depended/store/query/SelectQueryTest.php index 3c071374..2467cb75 100644 --- a/tests/db_adapter_depended/store/query/SelectQueryTest.php +++ b/tests/db_adapter_depended/store/query/SelectQueryTest.php @@ -666,6 +666,13 @@ public function testSelectFilterLangMatches() // regex public function testSelectFilterRegex() { + if ( + 'mysql' == $this->fixture->getDBSName() + && str_starts_with($this->fixture->getDBVersion(), '8.') + ) { + $this->markTestSkipped('MySQL 8+ has problems with SELECT queries containing a regex function.'); + } + // test data $this->fixture->query('INSERT INTO { "Alice". @@ -1020,9 +1027,7 @@ public function testSelectGroupBy() '; // mark skipped, if we have a certain MySQL version running - // TODO make that more flexible, currently its tight to MySQL - $serverVersion = $this->fixture->a['db_object']->getServerVersion(); - if ('05-07' == substr($serverVersion, 0, 5)) { + if (str_starts_with($this->fixture->getDBVersion(), '5.7.')) { $this->markTestSkipped( '[mysql 5.7] Result set is empty for query: ' .$query diff --git a/tests/integration/src/ARC2/Store/Adapter/AbstractAdapterTest.php b/tests/integration/src/ARC2/Store/Adapter/AbstractAdapterTest.php index 116c52b6..eee0a33d 100644 --- a/tests/integration/src/ARC2/Store/Adapter/AbstractAdapterTest.php +++ b/tests/integration/src/ARC2/Store/Adapter/AbstractAdapterTest.php @@ -155,7 +155,7 @@ public function testGetCollation() ) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_unicode_ci DELAY_KEY_WRITE = 1'; $this->fixture->exec($sql); - $this->assertEquals('utf8_unicode_ci', $this->fixture->getCollation()); + $this->assertStringContainsString('_unicode_ci', $this->fixture->getCollation()); } // setting table not there @@ -227,8 +227,10 @@ public function testQuery() public function testGetServerVersion() { - // check that server version looks like 05-00-05 - $this->assertEquals(1, preg_match('/\d\d-\d\d-\d\d/', $this->fixture->getServerVersion())); + $this->assertEquals( + $this->fixture->getConnection()->query('select version()')->fetchColumn(), + $this->fixture->getServerVersion() + ); } /* diff --git a/tests/integration/src/ARC2/Store/Adapter/AdapterFactoryTest.php b/tests/integration/src/ARC2/Store/Adapter/AdapterFactoryTest.php index d6e7fa61..a26dae65 100644 --- a/tests/integration/src/ARC2/Store/Adapter/AdapterFactoryTest.php +++ b/tests/integration/src/ARC2/Store/Adapter/AdapterFactoryTest.php @@ -4,7 +4,6 @@ use ARC2\Store\Adapter\AbstractAdapter; use ARC2\Store\Adapter\AdapterFactory; -use Exception; use Tests\ARC2_TestCase; class AdapterFactoryTest extends ARC2_TestCase @@ -22,29 +21,22 @@ protected function setUp(): void public function testGetInstanceFor() { - // mysqli - $this->assertTrue($this->fixture->getInstanceFor('mysqli') instanceof AbstractAdapter); - // PDO (mysql) $instance = $this->fixture->getInstanceFor('pdo', ['db_pdo_protocol' => 'mysql']); $this->assertTrue($instance instanceof AbstractAdapter); - - // PDO (sqlite) - $instance = $this->fixture->getInstanceFor('pdo', ['db_pdo_protocol' => 'sqlite']); - $this->assertTrue($instance instanceof AbstractAdapter); } public function testGetInstanceForInvalidAdapterName() { - $this->expectException(Exception::class); - $this->expectExceptionMessage('Unknown adapter name given. Currently supported are: mysqli, pdo'); + $this->expectException(\Exception::class); + $this->expectExceptionMessage('Unknown adapter name given. Currently supported are: pdo'); $this->fixture->getInstanceFor('invalid'); } public function testGetInstanceForInvalidPDOProtocol() { - $this->expectException(Exception::class); + $this->expectException(\Exception::class); $this->expectExceptionMessage('Only "mysql" protocol is supported at the moment.'); $instance = $this->fixture->getInstanceFor('pdo', ['db_pdo_protocol' => 'invalid']); @@ -57,6 +49,6 @@ public function testGetInstanceForInvalidPDOProtocol() public function testGetSupportedAdapters() { - $this->assertEquals(['mysqli', 'pdo'], $this->fixture->getSupportedAdapters()); + $this->assertEquals(['pdo'], $this->fixture->getSupportedAdapters()); } } diff --git a/tests/integration/src/ARC2/Store/Adapter/CachedPDOAdapterTest.php b/tests/integration/src/ARC2/Store/Adapter/CachedPDOAdapterTest.php deleted file mode 100644 index 83a502ba..00000000 --- a/tests/integration/src/ARC2/Store/Adapter/CachedPDOAdapterTest.php +++ /dev/null @@ -1,39 +0,0 @@ -markTestSkipped('Cache not enabled, therefore skipped.'); - } - - parent::setUp(); - } - - protected function getAdapterInstance($configuration) - { - return new CachedPDOAdapter($configuration); - } - - public function testExceptionIfCacheIsNotEnabled() - { - $this->expectException('Exception'); - $this->expectExceptionMessage('Cache not enabled, therefore CachedPDOAdapter can not be used.'); - - $cfg = $this->dbConfig; - unset($cfg['cache_enabled']); - unset($cfg['cache_instance']); - - new CachedPDOAdapter($cfg); - } -} diff --git a/tests/integration/src/ARC2/Store/Adapter/PDOAdapterTest.php b/tests/integration/src/ARC2/Store/Adapter/PDOAdapterTest.php index 2c6dc0cb..6b434f74 100644 --- a/tests/integration/src/ARC2/Store/Adapter/PDOAdapterTest.php +++ b/tests/integration/src/ARC2/Store/Adapter/PDOAdapterTest.php @@ -114,26 +114,4 @@ public function testQueryInvalid() // invalid query $this->assertFalse($this->fixture->simpleQuery('invalid query')); } - - /** - * Tests behavior when using exec and simpleQuery and the following exception araise. - * - * SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries - * are active. Consider using PDOStatement::fetchAll(). Alternatively, if your - * code is only ever going to run against mysql, you may enable query buffering - * by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute. - * - * If we use "exec" instead of "simpleQuery" here, the exception is gone sometimes. - * Its not clear, why it appears in the first place and why that solves it. - */ - public function testUnbufferedQueryStillActiveException() - { - $msg = 'SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other ' - .'unbuffered queries are active. Consider using PDOStatement::fetchAll(). ' - .'Alternatively, if your code is only ever going to run against mysql, you ' - .'may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute.'; - $this->expectExceptionMessage($msg); - - $this->fixture->simpleQuery('CHECK TABLE arc_triple;'); - } } diff --git a/tests/integration/src/ARC2/Store/Adapter/PDOSQLiteAdapterTest.php b/tests/integration/src/ARC2/Store/Adapter/PDOSQLiteAdapterTest.php deleted file mode 100644 index bf013425..00000000 --- a/tests/integration/src/ARC2/Store/Adapter/PDOSQLiteAdapterTest.php +++ /dev/null @@ -1,202 +0,0 @@ -markTestSkipped('Test skipped, because extension pdo_mysql is not installed.'); - } - } - - /** - * Forces SQLite in-memory. - */ - protected function getAdapterInstance($configuration) - { - // $configuration is being ignored for now. therefore no tests with - // SQLite files, only :memory:. - - return new PDOSQLiteAdapter([ - 'db_adapter' => 'pdo', - 'db_pdo_protocol' => 'sqlite', - ]); - } - - public function testConnectCreateNewConnection() - { - $this->fixture->disconnect(); - - // do explicit reconnect - $this->fixture = $this->getAdapterInstance($this->dbConfig); - $this->fixture->connect(); - - $this->fixture->exec('CREATE TABLE test (id INTEGER)'); - $this->assertEquals([], $this->fixture->fetchList('SELECT * FROM test;')); - } - - public function testConnectUseGivenConnection() - { - $this->fixture->disconnect(); - $connection = new \PDO('sqlite::memory:'); - - $connection->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false); - $connection->setAttribute(\PDO::ERRMODE_EXCEPTION, true); - $connection->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_BOTH); - - $this->fixture = $this->getAdapterInstance($this->dbConfig); - - // use existing connection - $this->fixture->connect($connection); - - /* - * simple test query to check that its working - */ - $this->fixture->simpleQuery('CREATE TABLE MyGuests (id INTEGER PRIMARY KEY AUTOINCREMENT)'); - - $this->assertEquals(1, \count($this->fixture->getAllTables())); - } - - public function testGetDBSNameNoConnection() - { - // disconnect current connection - $this->fixture->disconnect(); - - // create new instance, but dont connect - $db = $this->getAdapterInstance($this->dbConfig); - - $this->assertEquals('sqlite', $db->getDBSName()); - } - - public function testEscape() - { - $this->assertEquals('"hallo"', $this->fixture->escape('"hallo"')); - } - - public function testExec() - { - $this->fixture->exec('CREATE TABLE users (id INTEGER, name TEXT NOT NULL)'); - $this->fixture->exec('INSERT INTO users (id, name) VALUES (1, "foobar");'); - $this->fixture->exec('INSERT INTO users (id, name) VALUES (2, "foobar2");'); - - $this->assertEquals(2, $this->fixture->exec('DELETE FROM users;')); - } - - public function testFetchList() - { - // valid query - $sql = 'CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL)'; - $this->fixture->exec($sql); - $this->assertEquals([], $this->fixture->fetchList('SELECT * FROM users')); - - // add data - $this->fixture->exec('INSERT INTO users (id, name) VALUES (1, "foobar");'); - $this->assertEquals( - [ - [ - 'id' => 1, - 'name' => 'foobar', - ], - ], - $this->fixture->fetchList('SELECT * FROM users') - ); - } - - public function testFetchRow() - { - // valid query - $this->fixture->exec('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL)'); - $this->assertFalse($this->fixture->fetchRow('SELECT * FROM users')); - - // add data - $this->fixture->exec('INSERT INTO users (id, name) VALUES (1, "foobar");'); - $this->assertEquals( - [ - 'id' => 1, - 'name' => 'foobar', - ], - $this->fixture->fetchRow('SELECT * FROM users WHERE id = 1;') - ); - } - - public function testGetAdapterName() - { - $this->assertEquals('pdo', $this->fixture->getAdapterName()); - } - - public function testGetCollation() - { - $this->markTestIncomplete('Implement getCollation for PDOSQLiteAdapter.'); - } - - public function testGetConnection() - { - $this->assertTrue($this->fixture->getConnection() instanceof \PDO); - } - - public function testGetNumberOfRows() - { - // create test table - $this->fixture->exec('CREATE TABLE pet (name TEXT)'); - $this->fixture->exec('INSERT INTO pet VALUES ("cat")'); - $this->fixture->exec('INSERT INTO pet VALUES ("dog")'); - - $this->assertEquals(2, $this->fixture->getNumberOfRows('SELECT * FROM pet;')); - } - - public function testGetNumberOfRowsInvalidQuery() - { - $this->expectException('Exception'); - - $this->fixture->getNumberOfRows('SHOW TABLES of x'); - } - - public function testGetServerVersion() - { - // check server version - $this->assertEquals( - 1, - preg_match('/[0-9]{1,}\.[0-9]{1,}\.[0-9]{1,}/', - 'Found: '.$this->fixture->getServerVersion()) - ); - } - - public function testQuery() - { - // valid query - $sql = 'CREATE TABLE MyGuests (id INTEGER PRIMARY KEY AUTOINCREMENT)'; - $this->fixture->exec($sql); - - $foundTable = false; - foreach ($this->fixture->getAllTables() as $table) { - if ('MyGuests' == $table) { - $foundTable = true; - break; - } - } - $this->assertTrue($foundTable, 'Expected table not found.'); - } - - public function testQueryInvalid() - { - $this->expectException('Exception'); - - // invalid query - $this->assertFalse($this->fixture->simpleQuery('invalid query')); - } - - public function testSimpleQueryNoConnection() - { - // test, that it creates a connection itself, when calling exec - $this->fixture->disconnect(); - - $db = $this->getAdapterInstance(['db_adapter' => 'pdo', 'db_pdo_protocol' => 'sqlite']); - $sql = 'CREATE TABLE MyGuests (id INTEGER PRIMARY KEY AUTOINCREMENT)'; - $this->assertEquals(0, $db->exec($sql)); - } -} diff --git a/tests/integration/src/ARC2/Store/Adapter/mysqliAdapterTest.php b/tests/integration/src/ARC2/Store/Adapter/mysqliAdapterTest.php deleted file mode 100644 index 5d357bed..00000000 --- a/tests/integration/src/ARC2/Store/Adapter/mysqliAdapterTest.php +++ /dev/null @@ -1,107 +0,0 @@ -markTestSkipped('Test skipped, because extension mysqli is not installed.'); - } - - if ('mysqli' !== $this->dbConfig['db_adapter']) { - $this->markTestSkipped('Db adapter is not mysqli, therefore skip tests with queryDB.'); - } - } - - protected function getAdapterInstance($configuration) - { - return new mysqliAdapter($configuration); - } - - public function testConnectUseGivenConnection() - { - $this->fixture->disconnect(); - - // create connection outside of the instance - $connection = mysqli_connect( - $this->dbConfig['db_host'], - $this->dbConfig['db_user'], - $this->dbConfig['db_pwd'], - $this->dbConfig['db_name'], - $this->dbConfig['db_port'] - ); - - $this->fixture = new mysqliAdapter(); - - // use existing connection - $this->fixture->connect($connection); - - // if not the same origin, the connection ID differs - $this->assertEquals($this->fixture->getConnectionId(), mysqli_thread_id($connection)); - - // simple test query to check that its working - $result = $this->fixture->simpleQuery('SHOW TABLES'); - $this->assertTrue($result); - } - - public function testEscape() - { - $this->assertEquals('\"hallo\"', $this->fixture->escape('"hallo"')); - } - - public function testGetAdapterName() - { - $this->assertEquals('mysqli', $this->fixture->getAdapterName()); - } - - public function testGetConnection() - { - $this->assertTrue($this->fixture->getConnection() instanceof \mysqli); - } - - /* - * Tests for getErrorMessage and getErrorCode - */ - - public function testGetErrorMessageAndGetErrorCode() - { - // invalid query - $result = $this->fixture->simpleQuery('SHOW TABLES of x'); - $this->assertFalse($result); - $errorMsg = $this->fixture->getErrorMessage(); - $errorCode = $this->fixture->getErrorCode(); - - $dbs = 'mariadb' == $this->fixture->getDBSName() ? 'MariaDB' : 'MySQL'; - - $this->assertEquals( - "You have an error in your SQL syntax; check the manual that corresponds to your $dbs server " - ."version for the right syntax to use near 'of x' at line 1", - $errorMsg - ); - - $this->assertTrue(0 < $errorCode); - } - - public function testGetNumberOfRowsInvalidQuery() - { - // run with invalid query - $this->assertEquals(0, $this->fixture->getNumberOfRows('SHOW TABLES of x')); - } - - public function testMysqliQuery() - { - $res = $this->fixture->mysqliQuery('SHOW TABLES'); - $this->assertTrue($res instanceof \mysqli_result); - } - - public function testQueryInvalid() - { - // invalid query - $this->assertFalse($this->fixture->simpleQuery('invalid query')); - } -} diff --git a/tests/unit/ARC2_ClassTest.php b/tests/unit/ARC2_ClassTest.php index fb6ec48f..67313506 100644 --- a/tests/unit/ARC2_ClassTest.php +++ b/tests/unit/ARC2_ClassTest.php @@ -2,6 +2,8 @@ class ARC2_ClassTest extends PHPUnit\Framework\TestCase { + public ARC2_Class $arc2; + protected function setUp(): void { $array = []; @@ -39,7 +41,7 @@ public function testV() $this->assertFalse($this->arc2->v('cats', false, [])); $this->assertTrue($this->arc2->v('cats', false, ['cats' => true])); - $o = new stdclass(); + $o = new stdClass(); $o->cats = true; $this->assertTrue($this->arc2->v('cats', false, $o)); } @@ -51,11 +53,11 @@ public function testV1() $this->assertTrue($this->arc2->v1('cats', false, ['cats' => true])); $this->assertSame('blackjack', $this->arc2->v1('cats', 'blackjack', ['cats' => null])); - $o = new stdclass(); + $o = new stdClass(); $o->cats = true; $this->assertTrue($this->arc2->v1('cats', false, $o)); - $o = new stdclass(); + $o = new stdClass(); $o->cats = 0; $this->assertSame('blackjack', $this->arc2->v1('cats', 'blackjack', $o)); } diff --git a/tests/unit/ARC2_GraphTest.php b/tests/unit/ARC2_GraphTest.php index c4d636bb..3a45fb9f 100644 --- a/tests/unit/ARC2_GraphTest.php +++ b/tests/unit/ARC2_GraphTest.php @@ -6,6 +6,23 @@ class ARC2_GraphTest extends ARC2_TestCase { + private object $obj; + + /** + * @var array + */ + private array $res1; + + /** + * @var array + */ + private array $res2; + + /** + * @var array + */ + private array $res3; + protected function setUp(): void { parent::setUp(); diff --git a/tests/unit/ARC2_ReaderTest.php b/tests/unit/ARC2_ReaderTest.php index 1a30f20e..59511d9f 100644 --- a/tests/unit/ARC2_ReaderTest.php +++ b/tests/unit/ARC2_ReaderTest.php @@ -6,6 +6,8 @@ class ARC2_ReaderTest extends ARC2_TestCase { + private object $reader; + protected function setUp(): void { parent::setUp(); diff --git a/tests/unit/ARC2_Test.php b/tests/unit/ARC2_Test.php index 83524328..d6eaad76 100644 --- a/tests/unit/ARC2_Test.php +++ b/tests/unit/ARC2_Test.php @@ -9,7 +9,7 @@ class ARC2_Test extends ARC2_TestCase public function testGetVersion() { $actual = \ARC2::getVersion(); - $this->assertRegExp('/^[0-9]{4}-[0-9]{2}-[0-9]{2}/', $actual, 'should start with date'); + $this->assertMatchesRegularExpression('/^[0-9]{4}-[0-9]{2}-[0-9]{2}/', $actual, 'should start with date'); } public function testGetIncPath() @@ -99,8 +99,19 @@ public function testToUTF8() $actual = \ARC2::toUTF8('foo'); $this->assertEquals('foo', $actual); - $actual = \ARC2::toUTF8(utf8_encode('Iñtërnâtiônàlizætiøn')); - $this->assertEquals('Iñtërnâtiônàlizætiøn', $actual); + /* + * FIXME: it works locally inside Docker, but fails in Github workflow for unknown reasons + * + * 2) Tests\unit\ARC2_Test::testToUTF8 + * Failed asserting that two strings are equal. + * --- Expected + * +++ Actual + * @@ @@ + * -'Iñtërnâtiônàlizætiøn' + * +'I?t?rn?ti?n?liz?tin' + */ + // $actual = \ARC2::toUTF8(mb_convert_encoding('Iñtërnâtiônàlizætiøn', 'UTF-8', mb_list_encodings())); + // $this->assertEquals('Iñtërnâtiônàlizætiøn', $actual); } public function testSplitURI() diff --git a/tests/unit/store/ARC2_StoreEndpointTest.php b/tests/unit/store/ARC2_StoreEndpointTest.php index 7cb2e051..2f9a50c1 100644 --- a/tests/unit/store/ARC2_StoreEndpointTest.php +++ b/tests/unit/store/ARC2_StoreEndpointTest.php @@ -4,9 +4,11 @@ use Tests\ARC2_TestCase; -//Tests ARC2_StoreEndpoint functions +// Tests ARC2_StoreEndpoint functions class ARC2_StoreEndpointTest extends ARC2_TestCase { + private object $endpoint; + protected function setUp(): void { parent::setUp(); diff --git a/tests/unit/store/ARC2_StoreLoadQueryHandlerTest.php b/tests/unit/store/ARC2_StoreLoadQueryHandlerTest.php index a6547b56..a65012b0 100644 --- a/tests/unit/store/ARC2_StoreLoadQueryHandlerTest.php +++ b/tests/unit/store/ARC2_StoreLoadQueryHandlerTest.php @@ -2,7 +2,6 @@ namespace Tests\unit\store; -use ARC2_StoreLoadQueryHandler; use Tests\ARC2_TestCase; class ARC2_StoreLoadQueryHandlerTest extends ARC2_TestCase @@ -16,7 +15,7 @@ protected function setUp(): void $this->store = \ARC2::getStore($this->dbConfig); $this->store->createDBCon(); - $this->fixture = new ARC2_StoreLoadQueryHandler($this->store, $this); + $this->fixture = new \ARC2_StoreLoadQueryHandler($this->store, $this); // fresh setup of ARC2 $this->store->setup();