diff --git a/.editorconfig b/.editorconfig index 15d2c086..645a8f3e 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,10 +1,3 @@ -# In retrospect I'm less of a fan of tabs for indentation, because -# while they're better when they work, they're worse when they don't -# work, and so many people use terrible editors when they don't work -# that everything is inconsistent... but tabs are what Shimmie went -# with back in the 90's, so that's what we use now, and we deal with -# the pain of making sure everybody configures their editor properly - # top-most EditorConfig file root = true diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 3f9f0889..369765aa 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -12,44 +12,63 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 - + uses: actions/checkout@v3 - name: Set Up Cache - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: | vendor key: php-cs-fixer-${{ hashFiles('composer.lock') }} - - name: Validate composer.json and composer.lock run: composer validate - - name: Install PHP dependencies - run: composer update && composer install --prefer-dist --no-progress - + run: composer install --prefer-dist --no-progress - name: Set up PHP uses: shivammathur/setup-php@master with: - php-version: 7.4 + php-version: 8.1 + - name: Format + run: ./vendor/bin/php-cs-fixer fix && git diff --exit-code - - name: Check format - run: ./vendor/bin/php-cs-fixer fix --dry-run + static: + name: Static Analysis + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 2 + - name: Set Up Cache + uses: actions/cache@v3 + with: + path: | + vendor + key: phpstan-${{ hashFiles('composer.lock') }} + - name: Install PHP dependencies + run: composer install --prefer-dist --no-progress + - name: PHPStan + uses: php-actions/phpstan@v3 + with: + configuration: tests/phpstan.neon + memory_limit: 1G test: name: PHP ${{ matrix.php }} / DB ${{ matrix.database }} strategy: fail-fast: false matrix: - php: ['7.4', '8.0'] + php: ['8.1', '8.2'] database: ['pgsql', 'mysql', 'sqlite'] runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 + with: + fetch-depth: 2 - name: Set Up Cache - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: | vendor @@ -106,7 +125,6 @@ jobs: vendor/bin/phpunit --configuration tests/phpunit.xml --coverage-clover=data/coverage.clover - name: Upload coverage - if: matrix.php == '7.4' + if: matrix.php == '8.1' run: | - wget https://scrutinizer-ci.com/ocular.phar - php ocular.phar code-coverage:upload --format=php-clover data/coverage.clover + vendor/bin/ocular code-coverage:upload --format=php-clover data/coverage.clover diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index f2bd1ae1..8a4d93aa 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -1,19 +1,17 @@ exclude('ext/amazon_s3/lib') ->exclude('vendor') ->exclude('data') ->in(__DIR__) ; -$config = new PhpCsFixer\Config(); -return $config->setRules([ +$_phpcs_config = new PhpCsFixer\Config(); +return $_phpcs_config->setRules([ '@PSR12' => true, //'strict_param' => true, 'array_syntax' => ['syntax' => 'short'], ]) - ->setFinder($finder) -; - -?> + ->setFinder($_phpcs_finder) +; \ No newline at end of file diff --git a/.scrutinizer.yml b/.scrutinizer.yml index 8a3a5db6..3f425840 100644 --- a/.scrutinizer.yml +++ b/.scrutinizer.yml @@ -6,6 +6,7 @@ filter: excluded_paths: [ext/*/lib/*,ext/tagger/script.js,tests/*] build: + image: default-bionic nodes: analysis: tests: diff --git a/Dockerfile b/Dockerfile index 61ccbab6..944d0439 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,10 @@ +ARG PHP_VERSION=8.2 + # "Build" shimmie (composer install - done in its own stage so that we don't # need to include all the composer fluff in the final image) -FROM debian:stable AS app -RUN apt update && apt install -y composer php7.4-gd php7.4-dom php7.4-sqlite3 php-xdebug imagemagick +FROM debian:unstable AS app +RUN apt update && apt upgrade -y +RUN apt install -y composer php${PHP_VERSION}-gd php${PHP_VERSION}-xml php${PHP_VERSION}-sqlite3 php${PHP_VERSION}-xdebug imagemagick COPY composer.json composer.lock /app/ WORKDIR /app RUN composer install --no-dev @@ -10,8 +13,9 @@ COPY . /app/ # Tests in their own image. Really we should inherit from app and then # `composer install` phpunit on top of that; but for some reason # `composer install --no-dev && composer install` doesn't install dev -FROM debian:stable AS tests -RUN apt update && apt install -y composer php7.4-gd php7.4-dom php7.4-sqlite3 php-xdebug imagemagick +FROM debian:unstable AS tests +RUN apt update && apt upgrade -y +RUN apt install -y composer php${PHP_VERSION}-gd php${PHP_VERSION}-xml php${PHP_VERSION}-sqlite3 php${PHP_VERSION}-xdebug imagemagick COPY composer.json composer.lock /app/ WORKDIR /app RUN composer install @@ -25,22 +29,24 @@ RUN [ $RUN_TESTS = false ] || (\ echo '=== Cleaning ===' && rm -rf data) # Build su-exec so that our final image can be nicer -FROM debian:stable AS suexec -RUN apt-get update && apt-get install -y --no-install-recommends gcc libc-dev curl -RUN curl -k -o /usr/local/bin/su-exec.c https://raw.githubusercontent.com/ncopa/su-exec/master/su-exec.c; \ - gcc -Wall /usr/local/bin/su-exec.c -o/usr/local/bin/su-exec; \ - chown root:root /usr/local/bin/su-exec; \ - chmod 0755 /usr/local/bin/su-exec; +FROM debian:unstable AS suexec +RUN apt update && apt upgrade -y +RUN apt install -y --no-install-recommends gcc libc-dev curl +RUN curl -k -o /usr/local/bin/su-exec.c https://raw.githubusercontent.com/ncopa/su-exec/master/su-exec.c; \ + gcc -Wall /usr/local/bin/su-exec.c -o/usr/local/bin/su-exec; \ + chown root:root /usr/local/bin/su-exec; \ + chmod 0755 /usr/local/bin/su-exec; # Actually run shimmie -FROM debian:stable +FROM debian:unstable EXPOSE 8000 HEALTHCHECK --interval=1m --timeout=3s CMD curl --fail http://127.0.0.1:8000/ || exit 1 ENV UID=1000 \ GID=1000 -RUN apt update && apt install -y curl \ - php7.4-cli php7.4-gd php7.4-pgsql php7.4-mysql php7.4-sqlite3 php7.4-zip php7.4-dom php7.4-mbstring \ - imagemagick zip unzip && \ +RUN apt update && apt upgrade -y && apt install -y \ + php${PHP_VERSION}-cli php${PHP_VERSION}-gd php${PHP_VERSION}-zip php${PHP_VERSION}-xml php${PHP_VERSION}-mbstring \ + php${PHP_VERSION}-pgsql php${PHP_VERSION}-mysql php${PHP_VERSION}-sqlite3 \ + curl imagemagick ffmpeg zip unzip && \ rm -rf /var/lib/apt/lists/* COPY --from=app /app /app COPY --from=suexec /usr/local/bin/su-exec /usr/local/bin/su-exec diff --git a/composer.json b/composer.json index 1cb791ae..116bb6d8 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "config": { "platform": { - "php": "7.4.0" + "php": "8.1.0" } }, @@ -31,7 +31,7 @@ ], "require" : { - "php" : "^7.4 | ^8.0", + "php" : "^8.1", "ext-pdo": "*", "ext-json": "*", "ext-fileinfo": "*", @@ -39,28 +39,33 @@ "flexihash/flexihash" : "^2.0", "ifixit/php-akismet" : "^1.0", "google/recaptcha" : "^1.1", - "dapphp/securimage" : "^3.6", "shish/eventtracer-php" : "^2.0", "shish/ffsphp" : "^1.0", "shish/microcrud" : "^2.0", "shish/microhtml" : "^2.0", + "shish/gqla" : "dev-main", "enshrined/svg-sanitize" : "^0.15", "bower-asset/jquery" : "^1.12", "bower-asset/jquery-timeago" : "^1.5", - "bower-asset/js-cookie" : "^2.1" + "bower-asset/js-cookie" : "^2.1", + "psr/simple-cache" : "^1.0", + "sabre/cache" : "^2.0.1", + "naroga/redis-cache": "dev-master" }, "require-dev" : { "phpunit/phpunit" : "^9.0", - "friendsofphp/php-cs-fixer" : "^3.4" + "friendsofphp/php-cs-fixer" : "^3.12", + "scrutinizer/ocular": "dev-master", + "phpstan/phpstan": "1.10.x-dev" }, "suggest": { "ext-memcache": "memcache caching", "ext-memcached": "memcached caching", "ext-apc": "apc caching", + "ext-apcu": "apc caching", "ext-redis": "redis caching", - "ext-dom": "some extensions", "ext-curl": "some extensions", "ext-ctype": "some extensions", "ext-json": "some extensions", diff --git a/composer.lock b/composer.lock index b5bd335a..bf2bf72a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,14 +4,14 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "7fa1634834197de7e5325d494f20278e", + "content-hash": "605e247102c97c1320a4d1984a747c50", "packages": [ { "name": "bower-asset/jquery", "version": "1.12.4", "source": { "type": "git", - "url": "https://github.com/jquery/jquery-dist.git", + "url": "git@github.com:jquery/jquery-dist.git", "reference": "5e89585e0121e72ff47de177c5ef604f3089a53d" }, "dist": { @@ -50,7 +50,7 @@ "version": "v2.2.1", "source": { "type": "git", - "url": "https://github.com/js-cookie/js-cookie.git", + "url": "git@github.com:js-cookie/js-cookie.git", "reference": "54962f884e9ae33f93e13ac903ffaf1d5a523598" }, "dist": { @@ -63,72 +63,18 @@ "MIT" ] }, - { - "name": "dapphp/securimage", - "version": "3.6.8", - "source": { - "type": "git", - "url": "https://github.com/dapphp/securimage.git", - "reference": "5fc5953c4ffba1eb214cc83100672f238c184ca4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dapphp/securimage/zipball/5fc5953c4ffba1eb214cc83100672f238c184ca4", - "reference": "5fc5953c4ffba1eb214cc83100672f238c184ca4", - "shasum": "" - }, - "require": { - "ext-gd": "*", - "php": ">=5.4" - }, - "suggest": { - "ext-pdo": "For database storage support", - "ext-pdo_mysql": "For MySQL database support", - "ext-pdo_sqlite": "For SQLite3 database support" - }, - "type": "library", - "autoload": { - "classmap": [ - "securimage.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Drew Phillips", - "email": "drew@drew-phillips.com" - } - ], - "description": "PHP CAPTCHA Library", - "homepage": "https://www.phpcaptcha.org", - "keywords": [ - "Forms", - "anti-spam", - "captcha", - "security" - ], - "support": { - "issues": "https://github.com/dapphp/securimage/issues", - "source": "https://github.com/dapphp/securimage/tree/3.6.8" - }, - "abandoned": true, - "time": "2020-05-30T09:43:22+00:00" - }, { "name": "enshrined/svg-sanitize", - "version": "0.15.0", + "version": "0.15.4", "source": { "type": "git", "url": "https://github.com/darylldoyle/svg-sanitizer.git", - "reference": "17e12ba9c2881caa6b167d0fbea555c11207fbb0" + "reference": "e50b83a2f1f296ca61394fe88fbfe3e896a84cf4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/darylldoyle/svg-sanitizer/zipball/17e12ba9c2881caa6b167d0fbea555c11207fbb0", - "reference": "17e12ba9c2881caa6b167d0fbea555c11207fbb0", + "url": "https://api.github.com/repos/darylldoyle/svg-sanitizer/zipball/e50b83a2f1f296ca61394fe88fbfe3e896a84cf4", + "reference": "e50b83a2f1f296ca61394fe88fbfe3e896a84cf4", "shasum": "" }, "require": { @@ -137,7 +83,6 @@ "php": "^7.0 || ^8.0" }, "require-dev": { - "codeclimate/php-test-reporter": "^0.1.2", "phpunit/phpunit": "^6.5 || ^8.5" }, "type": "library", @@ -159,9 +104,9 @@ "description": "An SVG sanitizer for PHP", "support": { "issues": "https://github.com/darylldoyle/svg-sanitizer/issues", - "source": "https://github.com/darylldoyle/svg-sanitizer/tree/0.15.0" + "source": "https://github.com/darylldoyle/svg-sanitizer/tree/0.15.4" }, - "time": "2022-02-13T00:42:56+00:00" + "time": "2022-02-21T09:13:59+00:00" }, { "name": "flexihash/flexihash", @@ -226,27 +171,27 @@ "source": { "type": "git", "url": "https://github.com/google/recaptcha.git", - "reference": "ed5645e799e43afa9eb181f214dc52f22982682d" + "reference": "6ffa193021aa0e369a3c5b3909de2b4ed97ac359" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/google/recaptcha/zipball/ed5645e799e43afa9eb181f214dc52f22982682d", - "reference": "ed5645e799e43afa9eb181f214dc52f22982682d", + "url": "https://api.github.com/repos/google/recaptcha/zipball/6ffa193021aa0e369a3c5b3909de2b4ed97ac359", + "reference": "6ffa193021aa0e369a3c5b3909de2b4ed97ac359", "shasum": "" }, "require": { - "php": ">=5.5" + "php": ">=8" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^2.2.20|^2.15", - "php-coveralls/php-coveralls": "^2.1", - "phpunit/phpunit": "^4.8.36|^5.7.27|^6.59|^7.5.11" + "friendsofphp/php-cs-fixer": "^3.14", + "php-coveralls/php-coveralls": "^2.5", + "phpunit/phpunit": "^10" }, "default-branch": true, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2.x-dev" + "dev-master": "1.3.x-dev" } }, "autoload": { @@ -271,7 +216,7 @@ "issues": "https://github.com/google/recaptcha/issues", "source": "https://github.com/google/recaptcha" }, - "time": "2021-10-04T09:40:45+00:00" + "time": "2023-02-20T17:27:30+00:00" }, { "name": "ifixit/php-akismet", @@ -284,24 +229,257 @@ "type": "library" }, { - "name": "shish/eventtracer-php", - "version": "v2.0.1", + "name": "naroga/redis-cache", + "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/shish/eventtracer-php.git", - "reference": "6a17a1e29dad55558d300f0d3b1dd44628cfce55" + "url": "https://github.com/naroga/redis-cache.git", + "reference": "c32ee4ce2efcf8292cac6b6192c17c0306320d04" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/shish/eventtracer-php/zipball/6a17a1e29dad55558d300f0d3b1dd44628cfce55", - "reference": "6a17a1e29dad55558d300f0d3b1dd44628cfce55", + "url": "https://api.github.com/repos/naroga/redis-cache/zipball/c32ee4ce2efcf8292cac6b6192c17c0306320d04", + "reference": "c32ee4ce2efcf8292cac6b6192c17c0306320d04", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "predis/predis": "^1.1", + "psr/simple-cache": "~1.0" + }, + "require-dev": { + "phpunit/php-code-coverage": ">=2.2.4", + "phpunit/phpunit": ">=3.7.38", + "satooshi/php-coveralls": ">=1.0.1" + }, + "default-branch": true, + "type": "library", + "autoload": { + "psr-4": { + "Naroga\\RedisCache\\": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Pedro Cordeiro", + "email": "pedro.cordeiro@sympla.com.br" + } + ], + "description": "A Redis driver that implements PSR-16 (Simple Cache)", + "support": { + "issues": "https://github.com/naroga/redis-cache/issues", + "source": "https://github.com/naroga/redis-cache/tree/1.2" + }, + "time": "2021-01-25T13:15:08+00:00" + }, + { + "name": "predis/predis", + "version": "v1.x-dev", + "source": { + "type": "git", + "url": "https://github.com/predis/predis.git", + "reference": "bb8cce7bcf0d790dd17dde01922230d411efb99b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/predis/predis/zipball/bb8cce7bcf0d790dd17dde01922230d411efb99b", + "reference": "bb8cce7bcf0d790dd17dde01922230d411efb99b", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "require-dev": { + "phpunit/phpunit": "~4.8" + }, + "suggest": { + "ext-curl": "Allows access to Webdis when paired with phpiredis", + "ext-phpiredis": "Allows faster serialization and deserialization of the Redis protocol" + }, + "type": "library", + "autoload": { + "psr-4": { + "Predis\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniele Alessandri", + "email": "suppakilla@gmail.com", + "homepage": "http://clorophilla.net", + "role": "Creator & Maintainer" + }, + { + "name": "Till Krüss", + "homepage": "https://till.im", + "role": "Maintainer" + } + ], + "description": "Flexible and feature-complete Redis client for PHP and HHVM", + "homepage": "http://github.com/predis/predis", + "keywords": [ + "nosql", + "predis", + "redis" + ], + "support": { + "issues": "https://github.com/predis/predis/issues", + "source": "https://github.com/predis/predis/tree/v1.x" + }, + "funding": [ + { + "url": "https://github.com/sponsors/tillkruss", + "type": "github" + } + ], + "time": "2023-01-10T16:48:39+00:00" + }, + { + "name": "psr/simple-cache", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "support": { + "source": "https://github.com/php-fig/simple-cache/tree/master" + }, + "time": "2017-10-23T01:57:42+00:00" + }, + { + "name": "sabre/cache", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/sabre-io/cache.git", + "reference": "a843741b85025d8674bf4713121cae60172e6f86" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sabre-io/cache/zipball/a843741b85025d8674bf4713121cae60172e6f86", + "reference": "a843741b85025d8674bf4713121cae60172e6f86", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0", + "psr/simple-cache": "^1.0" + }, + "provide": { + "psr/simple-cache-implementation": "~1.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.14.0", + "phpstan/extension-installer": "^1.2", + "phpstan/phpstan": "^1.9", + "phpstan/phpstan-phpunit": "^1.3", + "phpstan/phpstan-strict-rules": "^1.4", + "phpunit/phpunit": "^9.6" + }, + "type": "library", + "autoload": { + "psr-4": { + "Sabre\\Cache\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Evert Pot", + "email": "me@evertpot.com", + "homepage": "https://evertpot.com/", + "role": "Developer" + } + ], + "description": "Simple cache abstraction layer implementing PSR-16", + "homepage": "http://sabre.io/dav/", + "keywords": [ + "apc", + "apcu", + "cache", + "memcache", + "memcached", + "psr-16", + "sabre", + "simple-cache" + ], + "support": { + "forum": "https://groups.google.com/group/sabredav-discuss", + "issues": "https://github.com/sabre-io/cache/issues", + "source": "https://github.com/fruux/sabre-skel" + }, + "time": "2023-02-09T23:47:10+00:00" + }, + { + "name": "shish/eventtracer-php", + "version": "v2.1.0", + "source": { + "type": "git", + "url": "https://github.com/shish/eventtracer-php.git", + "reference": "5dfe2c090c8b7df772e982520c36f44b33ead035" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/shish/eventtracer-php/zipball/5dfe2c090c8b7df772e982520c36f44b33ead035", + "reference": "5dfe2c090c8b7df772e982520c36f44b33ead035", "shasum": "" }, "require": { "ext-json": "*", - "php": "^7.3 | ^8.0" + "php": "^8.0" }, "require-dev": { + "friendsofphp/php-cs-fixer": "^3.12", + "phpstan/phpstan": "^1.9", "phpunit/phpunit": "^9.0" }, "type": "library", @@ -326,29 +504,31 @@ "homepage": "https://github.com/shish/eventtracer-php", "support": { "issues": "https://github.com/shish/eventtracer-php/issues", - "source": "https://github.com/shish/eventtracer-php/tree/v2.0.1" + "source": "https://github.com/shish/eventtracer-php/tree/v2.1.0" }, - "time": "2020-10-24T14:53:38+00:00" + "time": "2023-02-04T12:26:41+00:00" }, { "name": "shish/ffsphp", - "version": "v1.0.5", + "version": "v1.1.0", "source": { "type": "git", "url": "https://github.com/shish/ffsphp.git", - "reference": "76d30da4a0b1cf87ead53564ffdebefecc76385e" + "reference": "47d7e96a129502275fb8a4ae0c4f36bd3f59e95b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/shish/ffsphp/zipball/76d30da4a0b1cf87ead53564ffdebefecc76385e", - "reference": "76d30da4a0b1cf87ead53564ffdebefecc76385e", + "url": "https://api.github.com/repos/shish/ffsphp/zipball/47d7e96a129502275fb8a4ae0c4f36bd3f59e95b", + "reference": "47d7e96a129502275fb8a4ae0c4f36bd3f59e95b", "shasum": "" }, "require": { "ext-pdo": "*", - "php": "^7.3 | ^8.0" + "php": "^8.0" }, "require-dev": { + "friendsofphp/php-cs-fixer": "^3.12", + "phpstan/phpstan": "^1.9", "phpunit/phpunit": "^9.0" }, "type": "library", @@ -373,31 +553,86 @@ "homepage": "https://github.com/shish/ffsphp", "support": { "issues": "https://github.com/shish/ffsphp/issues", - "source": "https://github.com/shish/ffsphp/tree/v1.0.5" + "source": "https://github.com/shish/ffsphp/tree/v1.1.0" }, - "time": "2021-12-13T21:26:41+00:00" + "time": "2023-02-04T12:34:44+00:00" }, { - "name": "shish/microcrud", - "version": "v2.0.4", + "name": "shish/gqla", + "version": "dev-main", "source": { "type": "git", - "url": "https://github.com/shish/microcrud.git", - "reference": "c4be2183bb336c8c222d1badc81069ec0334b649" + "url": "https://github.com/shish/gqla.git", + "reference": "26bf0405445f4e32e68cd7f1ea2256e81c6c42cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/shish/microcrud/zipball/c4be2183bb336c8c222d1badc81069ec0334b649", - "reference": "c4be2183bb336c8c222d1badc81069ec0334b649", + "url": "https://api.github.com/repos/shish/gqla/zipball/26bf0405445f4e32e68cd7f1ea2256e81c6c42cb", + "reference": "26bf0405445f4e32e68cd7f1ea2256e81c6c42cb", + "shasum": "" + }, + "require": { + "php": "^8.1", + "webonyx/graphql-php": "^15.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.12", + "phpstan/phpstan": "^1.9", + "phpunit/phpunit": "^9.0" + }, + "default-branch": true, + "type": "library", + "autoload": { + "psr-4": { + "GQLA\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Shish", + "email": "webmaster@shishnet.org", + "homepage": "https://shish.io", + "role": "Developer" + } + ], + "description": "A set of annotations for generating graphql APIs", + "homepage": "https://github.com/shish/gqla", + "keywords": [ + "graphql" + ], + "support": { + "issues": "https://github.com/shish/gqla/issues", + "source": "https://github.com/shish/gqla/tree/main" + }, + "time": "2023-03-03T00:12:44+00:00" + }, + { + "name": "shish/microcrud", + "version": "v2.1.0", + "source": { + "type": "git", + "url": "https://github.com/shish/microcrud.git", + "reference": "c7398edf6b1ed0ee508769a73d656deca8f6a4be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/shish/microcrud/zipball/c7398edf6b1ed0ee508769a73d656deca8f6a4be", + "reference": "c7398edf6b1ed0ee508769a73d656deca8f6a4be", "shasum": "" }, "require": { "ext-pdo": "*", - "php": "^7.3 | ^8.0", + "php": "^8.0", "shish/ffsphp": "^1.0", "shish/microhtml": "^2.0.2" }, "require-dev": { + "friendsofphp/php-cs-fixer": "^3.12", + "phpstan/phpstan": "^1.9", "phpunit/phpunit": "^9.0" }, "type": "library", @@ -426,28 +661,30 @@ ], "support": { "issues": "https://github.com/shish/microcrud/issues", - "source": "https://github.com/shish/microcrud/tree/v2.0.4" + "source": "https://github.com/shish/microcrud/tree/v2.1.0" }, - "time": "2020-10-25T10:39:48+00:00" + "time": "2023-02-04T13:09:53+00:00" }, { "name": "shish/microhtml", - "version": "v2.0.3", + "version": "v2.1.0", "source": { "type": "git", "url": "https://github.com/shish/microhtml.git", - "reference": "e84506f7be7f8f2d315b188df5a96253a714acc1" + "reference": "afef3aac229b514ed5b4afbfb2d970d1419313c8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/shish/microhtml/zipball/e84506f7be7f8f2d315b188df5a96253a714acc1", - "reference": "e84506f7be7f8f2d315b188df5a96253a714acc1", + "url": "https://api.github.com/repos/shish/microhtml/zipball/afef3aac229b514ed5b4afbfb2d970d1419313c8", + "reference": "afef3aac229b514ed5b4afbfb2d970d1419313c8", "shasum": "" }, "require": { - "php": "^7.3 | ^8.0" + "php": "^8.0" }, "require-dev": { + "friendsofphp/php-cs-fixer": "^3.12", + "phpstan/phpstan": "^1.9", "phpunit/phpunit": "^9.0" }, "type": "library", @@ -476,9 +713,79 @@ ], "support": { "issues": "https://github.com/shish/microhtml/issues", - "source": "https://github.com/shish/microhtml/tree/v2.0.3" + "source": "https://github.com/shish/microhtml/tree/v2.1.0" }, - "time": "2020-10-24T14:48:32+00:00" + "time": "2023-02-04T13:02:26+00:00" + }, + { + "name": "webonyx/graphql-php", + "version": "v15.2.1", + "source": { + "type": "git", + "url": "https://github.com/webonyx/graphql-php.git", + "reference": "6b02da9313065889eb783d623567476500a572ef" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webonyx/graphql-php/zipball/6b02da9313065889eb783d623567476500a572ef", + "reference": "6b02da9313065889eb783d623567476500a572ef", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-mbstring": "*", + "php": "^7.4 || ^8" + }, + "require-dev": { + "amphp/amp": "^2.6", + "dms/phpunit-arraysubset-asserts": "^0.4", + "ergebnis/composer-normalize": "^2.28", + "mll-lab/php-cs-fixer-config": "^5.0", + "nyholm/psr7": "^1.5", + "phpbench/phpbench": "^1.2", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "1.10.3", + "phpstan/phpstan-phpunit": "1.3.8", + "phpstan/phpstan-strict-rules": "1.5.0", + "phpunit/phpunit": "^9.5", + "psr/http-message": "^1", + "react/http": "^1.6", + "react/promise": "^2.9", + "symfony/polyfill-php81": "^1.23", + "symfony/var-exporter": "^5 || ^6", + "thecodingmachine/safe": "^1.3 || ^2" + }, + "suggest": { + "psr/http-message": "To use standard GraphQL server", + "react/promise": "To leverage async resolving on React PHP platform" + }, + "type": "library", + "autoload": { + "psr-4": { + "GraphQL\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A PHP port of GraphQL reference implementation", + "homepage": "https://github.com/webonyx/graphql-php", + "keywords": [ + "api", + "graphql" + ], + "support": { + "issues": "https://github.com/webonyx/graphql-php/issues", + "source": "https://github.com/webonyx/graphql-php/tree/v15.2.1" + }, + "funding": [ + { + "url": "https://opencollective.com/webonyx-graphql-php", + "type": "open_collective" + } + ], + "time": "2023-02-28T13:00:18+00:00" } ], "packages-dev": [ @@ -488,27 +795,27 @@ "source": { "type": "git", "url": "https://github.com/composer/pcre.git", - "reference": "1bbc34bff31a65639963abbda90ce220e783cb2b" + "reference": "4bff79ddd77851fe3cdd11616ed3f92841ba5bd2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/1bbc34bff31a65639963abbda90ce220e783cb2b", - "reference": "1bbc34bff31a65639963abbda90ce220e783cb2b", + "url": "https://api.github.com/repos/composer/pcre/zipball/4bff79ddd77851fe3cdd11616ed3f92841ba5bd2", + "reference": "4bff79ddd77851fe3cdd11616ed3f92841ba5bd2", "shasum": "" }, "require": { - "php": "^5.3.2 || ^7.0 || ^8.0" + "php": "^7.4 || ^8.0" }, "require-dev": { - "phpstan/phpstan": "^1", + "phpstan/phpstan": "^1.3", "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^4.2 || ^5" + "symfony/phpunit-bridge": "^5" }, "default-branch": true, "type": "library", "extra": { "branch-alias": { - "dev-main": "1.x-dev" + "dev-main": "3.x-dev" } }, "autoload": { @@ -536,7 +843,7 @@ ], "support": { "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/main" + "source": "https://github.com/composer/pcre/tree/3.1.0" }, "funding": [ { @@ -552,7 +859,7 @@ "type": "tidelift" } ], - "time": "2021-12-06T20:05:46+00:00" + "time": "2022-11-17T09:50:14+00:00" }, { "name": "composer/semver", @@ -560,19 +867,19 @@ "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "83e511e247de329283478496f7a1e114c9517506" + "reference": "fa1ec24f0ab1efe642671ec15c51a3ab879f59bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/83e511e247de329283478496f7a1e114c9517506", - "reference": "83e511e247de329283478496f7a1e114c9517506", + "url": "https://api.github.com/repos/composer/semver/zipball/fa1ec24f0ab1efe642671ec15c51a3ab879f59bf", + "reference": "fa1ec24f0ab1efe642671ec15c51a3ab879f59bf", "shasum": "" }, "require": { "php": "^5.3.2 || ^7.0 || ^8.0" }, "require-dev": { - "phpstan/phpstan": "^0.12.54", + "phpstan/phpstan": "^1.4", "symfony/phpunit-bridge": "^4.2 || ^5" }, "default-branch": true, @@ -616,9 +923,9 @@ "versioning" ], "support": { - "irc": "irc://irc.freenode.org/composer", + "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.2.6" + "source": "https://github.com/composer/semver/tree/main" }, "funding": [ { @@ -634,31 +941,31 @@ "type": "tidelift" } ], - "time": "2021-10-25T11:34:17+00:00" + "time": "2023-01-13T15:47:53+00:00" }, { "name": "composer/xdebug-handler", - "version": "2.0.3", + "version": "3.0.3", "source": { "type": "git", "url": "https://github.com/composer/xdebug-handler.git", - "reference": "6555461e76962fd0379c444c46fd558a0fcfb65e" + "reference": "ced299686f41dce890debac69273b47ffe98a40c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6555461e76962fd0379c444c46fd558a0fcfb65e", - "reference": "6555461e76962fd0379c444c46fd558a0fcfb65e", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ced299686f41dce890debac69273b47ffe98a40c", + "reference": "ced299686f41dce890debac69273b47ffe98a40c", "shasum": "" }, "require": { - "composer/pcre": "^1", - "php": "^5.3.2 || ^7.0 || ^8.0", + "composer/pcre": "^1 || ^2 || ^3", + "php": "^7.2.5 || ^8.0", "psr/log": "^1 || ^2 || ^3" }, "require-dev": { "phpstan/phpstan": "^1.0", "phpstan/phpstan-strict-rules": "^1.1", - "symfony/phpunit-bridge": "^4.2 || ^5.0 || ^6.0" + "symfony/phpunit-bridge": "^6.0" }, "type": "library", "autoload": { @@ -684,7 +991,7 @@ "support": { "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/xdebug-handler/issues", - "source": "https://github.com/composer/xdebug-handler/tree/2.0.3" + "source": "https://github.com/composer/xdebug-handler/tree/3.0.3" }, "funding": [ { @@ -700,36 +1007,40 @@ "type": "tidelift" } ], - "time": "2021-12-08T13:07:32+00:00" + "time": "2022-02-25T21:32:43+00:00" }, { "name": "doctrine/annotations", - "version": "1.14.x-dev", + "version": "2.0.x-dev", "source": { "type": "git", "url": "https://github.com/doctrine/annotations.git", - "reference": "2da982ad3c26da81b91db8d7b54abf3a5922e73c" + "reference": "e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/2da982ad3c26da81b91db8d7b54abf3a5922e73c", - "reference": "2da982ad3c26da81b91db8d7b54abf3a5922e73c", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f", + "reference": "e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f", "shasum": "" }, "require": { - "doctrine/lexer": "1.*", + "doctrine/lexer": "^2 || ^3", "ext-tokenizer": "*", - "php": "^7.1 || ^8.0", + "php": "^7.2 || ^8.0", "psr/cache": "^1 || ^2 || ^3" }, "require-dev": { - "doctrine/cache": "^1.11 || ^2.0", - "doctrine/coding-standard": "^6.0 || ^8.1", - "phpstan/phpstan": "^0.12.20", - "phpunit/phpunit": "^7.5 || ^8.0 || ^9.1.5", - "symfony/cache": "^4.4 || ^5.2", + "doctrine/cache": "^2.0", + "doctrine/coding-standard": "^10", + "phpstan/phpstan": "^1.8.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "symfony/cache": "^5.4 || ^6", "vimeo/psalm": "^4.10" }, + "suggest": { + "php": "PHP 8.0 or higher comes with attributes, a native replacement for annotations" + }, + "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -771,9 +1082,52 @@ ], "support": { "issues": "https://github.com/doctrine/annotations/issues", - "source": "https://github.com/doctrine/annotations/tree/1.14.x" + "source": "https://github.com/doctrine/annotations/tree/2.0.1" }, - "time": "2021-10-15T21:17:00+00:00" + "time": "2023-02-02T22:02:53+00:00" + }, + { + "name": "doctrine/deprecations", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/deprecations.git", + "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de", + "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de", + "shasum": "" + }, + "require": { + "php": "^7.1|^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9", + "phpunit/phpunit": "^7.5|^8.5|^9.5", + "psr/log": "^1|^2|^3" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", + "support": { + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/v1.0.0" + }, + "time": "2022-05-02T15:47:09+00:00" }, { "name": "doctrine/instantiator", @@ -781,26 +1135,28 @@ "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "6410c4b8352cb64218641457cef64997e6b784fb" + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/6410c4b8352cb64218641457cef64997e6b784fb", - "reference": "6410c4b8352cb64218641457cef64997e6b784fb", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^8.0", + "doctrine/coding-standard": "^9 || ^11", "ext-pdo": "*", "ext-phar": "*", - "phpbench/phpbench": "^0.13 || 1.0.0-alpha2", - "phpstan/phpstan": "^0.12", - "phpstan/phpstan-phpunit": "^0.12", - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" + "phpbench/phpbench": "^0.16 || ^1", + "phpstan/phpstan": "^1.4", + "phpstan/phpstan-phpunit": "^1", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "vimeo/psalm": "^4.30 || ^5.4" }, + "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -826,7 +1182,7 @@ ], "support": { "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.4.x" + "source": "https://github.com/doctrine/instantiator/tree/1.5.0" }, "funding": [ { @@ -842,34 +1198,38 @@ "type": "tidelift" } ], - "time": "2020-11-10T19:05:51+00:00" + "time": "2022-12-30T00:15:36+00:00" }, { "name": "doctrine/lexer", - "version": "1.3.x-dev", + "version": "2.1.x-dev", "source": { "type": "git", "url": "https://github.com/doctrine/lexer.git", - "reference": "59bfb3b9be04237be4cd1afea9bbb58794c25ce8" + "reference": "e74756f7517d72c238b9163fcd1ed54eb1f92bd0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/59bfb3b9be04237be4cd1afea9bbb58794c25ce8", - "reference": "59bfb3b9be04237be4cd1afea9bbb58794c25ce8", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/e74756f7517d72c238b9163fcd1ed54eb1f92bd0", + "reference": "e74756f7517d72c238b9163fcd1ed54eb1f92bd0", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" + "doctrine/deprecations": "^1.0", + "php": "^7.1 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^8.0", - "phpstan/phpstan": "^0.12", - "phpunit/phpunit": "^8.2 || ^9.4" + "doctrine/coding-standard": "^9 || ^10", + "phpstan/phpstan": "^1.3", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "^0.18.3", + "vimeo/psalm": "^4.11 || ^5.0" }, + "default-branch": true, "type": "library", "autoload": { "psr-4": { - "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" + "Doctrine\\Common\\Lexer\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -901,7 +1261,7 @@ ], "support": { "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/1.3.x" + "source": "https://github.com/doctrine/lexer/tree/2.1.x" }, "funding": [ { @@ -917,56 +1277,57 @@ "type": "tidelift" } ], - "time": "2021-01-20T07:15:06+00:00" + "time": "2022-12-29T09:22:42+00:00" }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.4.0", + "version": "v3.14.4", "source": { "type": "git", - "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", - "reference": "47177af1cfb9dab5d1cc4daf91b7179c2efe7fad" + "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", + "reference": "1b3d9dba63d93b8a202c31e824748218781eae6b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/47177af1cfb9dab5d1cc4daf91b7179c2efe7fad", - "reference": "47177af1cfb9dab5d1cc4daf91b7179c2efe7fad", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/1b3d9dba63d93b8a202c31e824748218781eae6b", + "reference": "1b3d9dba63d93b8a202c31e824748218781eae6b", "shasum": "" }, "require": { - "composer/semver": "^3.2", - "composer/xdebug-handler": "^2.0", - "doctrine/annotations": "^1.12", + "composer/semver": "^3.3", + "composer/xdebug-handler": "^3.0.3", + "doctrine/annotations": "^2", + "doctrine/lexer": "^2 || ^3", "ext-json": "*", "ext-tokenizer": "*", - "php": "^7.2.5 || ^8.0", - "php-cs-fixer/diff": "^2.0", - "symfony/console": "^4.4.20 || ^5.1.3 || ^6.0", - "symfony/event-dispatcher": "^4.4.20 || ^5.0 || ^6.0", - "symfony/filesystem": "^4.4.20 || ^5.0 || ^6.0", - "symfony/finder": "^4.4.20 || ^5.0 || ^6.0", - "symfony/options-resolver": "^4.4.20 || ^5.0 || ^6.0", - "symfony/polyfill-mbstring": "^1.23", - "symfony/polyfill-php80": "^1.23", - "symfony/polyfill-php81": "^1.23", - "symfony/process": "^4.4.20 || ^5.0 || ^6.0", - "symfony/stopwatch": "^4.4.20 || ^5.0 || ^6.0" + "php": "^7.4 || ^8.0", + "sebastian/diff": "^4.0 || ^5.0", + "symfony/console": "^5.4 || ^6.0", + "symfony/event-dispatcher": "^5.4 || ^6.0", + "symfony/filesystem": "^5.4 || ^6.0", + "symfony/finder": "^5.4 || ^6.0", + "symfony/options-resolver": "^5.4 || ^6.0", + "symfony/polyfill-mbstring": "^1.27", + "symfony/polyfill-php80": "^1.27", + "symfony/polyfill-php81": "^1.27", + "symfony/process": "^5.4 || ^6.0", + "symfony/stopwatch": "^5.4 || ^6.0" }, "require-dev": { "justinrainbow/json-schema": "^5.2", - "keradus/cli-executor": "^1.5", - "mikey179/vfsstream": "^1.6.8", - "php-coveralls/php-coveralls": "^2.5.2", + "keradus/cli-executor": "^2.0", + "mikey179/vfsstream": "^1.6.11", + "php-coveralls/php-coveralls": "^2.5.3", "php-cs-fixer/accessible-object": "^1.1", "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.2", "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.2.1", - "phpspec/prophecy": "^1.15", - "phpspec/prophecy-phpunit": "^1.1 || ^2.0", - "phpunit/phpunit": "^8.5.21 || ^9.5", - "phpunitgoodpractices/polyfill": "^1.5", - "phpunitgoodpractices/traits": "^1.9.1", - "symfony/phpunit-bridge": "^5.2.4 || ^6.0", - "symfony/yaml": "^4.4.20 || ^5.0 || ^6.0" + "phpspec/prophecy": "^1.16", + "phpspec/prophecy-phpunit": "^2.0", + "phpunit/phpunit": "^9.5", + "phpunitgoodpractices/polyfill": "^1.6", + "phpunitgoodpractices/traits": "^1.9.2", + "symfony/phpunit-bridge": "^6.2.3", + "symfony/yaml": "^5.4 || ^6.0" }, "suggest": { "ext-dom": "For handling output formats in XML", @@ -997,8 +1358,8 @@ ], "description": "A tool to automatically fix PHP code style", "support": { - "issues": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/issues", - "source": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/tree/v3.4.0" + "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.14.4" }, "funding": [ { @@ -1006,7 +1367,503 @@ "type": "github" } ], - "time": "2021-12-11T16:25:08+00:00" + "time": "2023-02-09T21:49:13+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "8459341c16f96b9610dcdfe22bd3060d60c0da04" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/8459341c16f96b9610dcdfe22bd3060d60c0da04", + "reference": "8459341c16f96b9610dcdfe22bd3060d60c0da04", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/promises": "^1.5", + "guzzlehttp/psr7": "^1.9 || ^2.4", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.1", + "ext-curl": "*", + "php-http/client-integration-tests": "^3.0", + "phpunit/phpunit": "^8.5.29 || ^9.5.23", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" + }, + "default-branch": true, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + }, + "branch-alias": { + "dev-master": "7.5-dev" + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "psr-18", + "psr-7", + "rest", + "web service" + ], + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/master" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", + "type": "tidelift" + } + ], + "time": "2022-08-29T11:03:19+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "b94b2807d85443f9719887892882d0329d1e2598" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/b94b2807d85443f9719887892882d0329d1e2598", + "reference": "b94b2807d85443f9719887892882d0329d1e2598", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "symfony/phpunit-bridge": "^4.4 || ^5.1" + }, + "default-branch": true, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.5-dev" + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/1.5.2" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", + "type": "tidelift" + } + ], + "time": "2022-08-28T14:55:35+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "58d0734481de3fbc62f3d13da4d991e051521282" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/58d0734481de3fbc62f3d13da4d991e051521282", + "reference": "58d0734481de3fbc62f3d13da4d991e051521282", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0", + "ralouphie/getallheaders": "^3.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.1", + "http-interop/http-factory-tests": "^0.9", + "phpunit/phpunit": "^8.5.29 || ^9.5.23" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, + "default-branch": true, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + }, + "branch-alias": { + "dev-master": "2.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/master" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", + "type": "tidelift" + } + ], + "time": "2023-02-15T13:59:53+00:00" + }, + { + "name": "jms/metadata", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/schmittjoh/metadata.git", + "reference": "7ca240dcac0c655eb15933ee55736ccd2ea0d7a6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/metadata/zipball/7ca240dcac0c655eb15933ee55736ccd2ea0d7a6", + "reference": "7ca240dcac0c655eb15933ee55736ccd2ea0d7a6", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0" + }, + "require-dev": { + "doctrine/cache": "^1.0", + "doctrine/coding-standard": "^8.0", + "mikey179/vfsstream": "^1.6.7", + "phpunit/phpunit": "^8.5|^9.0", + "psr/container": "^1.0|^2.0", + "symfony/cache": "^3.1|^4.0|^5.0", + "symfony/dependency-injection": "^3.1|^4.0|^5.0" + }, + "default-branch": true, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Metadata\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Asmir Mustafic", + "email": "goetas@gmail.com" + } + ], + "description": "Class/method/property metadata management in PHP", + "keywords": [ + "annotations", + "metadata", + "xml", + "yaml" + ], + "support": { + "issues": "https://github.com/schmittjoh/metadata/issues", + "source": "https://github.com/schmittjoh/metadata/tree/2.8.0" + }, + "time": "2023-02-15T13:44:18+00:00" + }, + { + "name": "jms/serializer", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/schmittjoh/serializer.git", + "reference": "ac0b16ee5317d1aacc41deb91c6c325eae97c176" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/serializer/zipball/ac0b16ee5317d1aacc41deb91c6c325eae97c176", + "reference": "ac0b16ee5317d1aacc41deb91c6c325eae97c176", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.13 || ^2.0", + "doctrine/instantiator": "^1.0.3", + "doctrine/lexer": "^1.1 || ^2", + "jms/metadata": "^2.6", + "php": "^7.2||^8.0", + "phpstan/phpdoc-parser": "^0.4 || ^0.5 || ^1.0" + }, + "require-dev": { + "doctrine/coding-standard": "^8.1", + "doctrine/orm": "~2.1", + "doctrine/persistence": "^1.3.3|^2.0|^3.0", + "doctrine/phpcr-odm": "^1.3|^2.0", + "ext-pdo_sqlite": "*", + "jackalope/jackalope-doctrine-dbal": "^1.1.5", + "ocramius/proxy-manager": "^1.0|^2.0", + "phpbench/phpbench": "^1.0", + "phpstan/phpstan": "^1.0.2", + "phpunit/phpunit": "^8.5.21||^9.0", + "psr/container": "^1.0|^2.0", + "symfony/dependency-injection": "^3.0|^4.0|^5.0|^6.0", + "symfony/expression-language": "^3.2|^4.0|^5.0|^6.0", + "symfony/filesystem": "^3.0|^4.0|^5.0|^6.0", + "symfony/form": "^3.0|^4.0|^5.0|^6.0", + "symfony/translation": "^3.0|^4.0|^5.0|^6.0", + "symfony/uid": "^5.1|^6.0", + "symfony/validator": "^3.1.9|^4.0|^5.0|^6.0", + "symfony/yaml": "^3.3|^4.0|^5.0|^6.0", + "twig/twig": "~1.34|~2.4|^3.0" + }, + "suggest": { + "doctrine/collections": "Required if you like to use doctrine collection types as ArrayCollection.", + "symfony/cache": "Required if you like to use cache functionality.", + "symfony/uid": "Required if you'd like to serialize UID objects.", + "symfony/yaml": "Required if you'd like to use the YAML metadata format." + }, + "default-branch": true, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "JMS\\Serializer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Asmir Mustafic", + "email": "goetas@gmail.com" + } + ], + "description": "Library for (de-)serializing data of any complexity; supports XML, and JSON.", + "homepage": "http://jmsyst.com/libs/serializer", + "keywords": [ + "deserialization", + "jaxb", + "json", + "serialization", + "xml" + ], + "support": { + "issues": "https://github.com/schmittjoh/serializer/issues", + "source": "https://github.com/schmittjoh/serializer/tree/3.23.0" + }, + "funding": [ + { + "url": "https://github.com/goetas", + "type": "github" + } + ], + "time": "2023-02-17T17:40:48+00:00" }, { "name": "myclabs/deep-copy", @@ -1014,34 +1871,35 @@ "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220" + "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/776f831124e9c62e1a2c601ecc52e776d8bb7220", - "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614", + "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, - "replace": { - "myclabs/deep-copy": "self.version" + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3,<3.2.2" }, "require-dev": { - "doctrine/collections": "^1.0", - "doctrine/common": "^2.6", - "phpunit/phpunit": "^7.1" + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "default-branch": true, "type": "library", "autoload": { - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - }, "files": [ "src/DeepCopy/deep_copy.php" - ] + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1057,7 +1915,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.10.2" + "source": "https://github.com/myclabs/DeepCopy/tree/1.11.0" }, "funding": [ { @@ -1065,20 +1923,20 @@ "type": "tidelift" } ], - "time": "2020-11-13T09:40:50+00:00" + "time": "2022-03-03T13:19:32+00:00" }, { "name": "nikic/php-parser", - "version": "v4.13.2", + "version": "4.x-dev", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "210577fe3cf7badcc5814d99455df46564f3c077" + "reference": "570e980a201d8ed0236b0a62ddf2c9cbb2034039" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/210577fe3cf7badcc5814d99455df46564f3c077", - "reference": "210577fe3cf7badcc5814d99455df46564f3c077", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/570e980a201d8ed0236b0a62ddf2c9cbb2034039", + "reference": "570e980a201d8ed0236b0a62ddf2c9cbb2034039", "shasum": "" }, "require": { @@ -1089,6 +1947,7 @@ "ircmaxell/php-yacc": "^0.0.7", "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" }, + "default-branch": true, "bin": [ "bin/php-parse" ], @@ -1119,9 +1978,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.13.2" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.3" }, - "time": "2021-11-30T19:35:32+00:00" + "time": "2023-01-16T22:05:37+00:00" }, { "name": "phar-io/manifest", @@ -1129,16 +1988,17 @@ "source": { "type": "git", "url": "https://github.com/phar-io/manifest.git", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53" + "reference": "36d8a21e851a9512db2b086dc5ac2c61308f0138" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/36d8a21e851a9512db2b086dc5ac2c61308f0138", + "reference": "36d8a21e851a9512db2b086dc5ac2c61308f0138", "shasum": "" }, "require": { "ext-dom": "*", + "ext-libxml": "*", "ext-phar": "*", "ext-xmlwriter": "*", "phar-io/version": "^3.0.1", @@ -1180,22 +2040,28 @@ "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", "support": { "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/2.0.3" + "source": "https://github.com/phar-io/manifest/tree/master" }, - "time": "2021-07-20T11:28:43+00:00" + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2022-02-21T19:55:33+00:00" }, { "name": "phar-io/version", - "version": "3.1.0", + "version": "3.2.1", "source": { "type": "git", "url": "https://github.com/phar-io/version.git", - "reference": "bae7c545bef187884426f042434e561ab1ddb182" + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/bae7c545bef187884426f042434e561ab1ddb182", - "reference": "bae7c545bef187884426f042434e561ab1ddb182", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", "shasum": "" }, "require": { @@ -1231,291 +2097,190 @@ "description": "Library for handling version information and constraints", "support": { "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/3.1.0" + "source": "https://github.com/phar-io/version/tree/3.2.1" }, - "time": "2021-02-23T14:00:09+00:00" + "time": "2022-02-21T01:04:05+00:00" }, { - "name": "php-cs-fixer/diff", - "version": "v2.0.2", + "name": "phpoption/phpoption", + "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/PHP-CS-Fixer/diff.git", - "reference": "29dc0d507e838c4580d018bd8b5cb412474f7ec3" + "url": "https://github.com/schmittjoh/php-option.git", + "reference": "dd3a383e599f49777d8b628dadbb90cae435b87e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/diff/zipball/29dc0d507e838c4580d018bd8b5cb412474f7ec3", - "reference": "29dc0d507e838c4580d018bd8b5cb412474f7ec3", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/dd3a383e599f49777d8b628dadbb90cae435b87e", + "reference": "dd3a383e599f49777d8b628dadbb90cae435b87e", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0 || ^8.0" + "php": "^7.2.5 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^5.7.23 || ^6.4.3 || ^7.0", - "symfony/process": "^3.3" + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.32 || ^9.6.3 || ^10.0.12" + }, + "default-branch": true, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": true + }, + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpOption\\": "src/PhpOption/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com", + "homepage": "https://github.com/schmittjoh" + }, + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + } + ], + "description": "Option Type for PHP", + "keywords": [ + "language", + "option", + "php", + "type" + ], + "support": { + "issues": "https://github.com/schmittjoh/php-option/issues", + "source": "https://github.com/schmittjoh/php-option/tree/1.9.1" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpoption/phpoption", + "type": "tidelift" + } + ], + "time": "2023-02-25T19:38:58+00:00" + }, + { + "name": "phpstan/phpdoc-parser", + "version": "1.16.1", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "e27e92d939e2e3636f0a1f0afaba59692c0bf571" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/e27e92d939e2e3636f0a1f0afaba59692c0bf571", + "reference": "e27e92d939e2e3636f0a1f0afaba59692c0bf571", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.5", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.0", + "phpunit/phpunit": "^9.5", + "symfony/process": "^5.2" }, "type": "library", "autoload": { - "classmap": [ - "src/" + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPDoc parser with support for nullable, intersection and generic types", + "support": { + "issues": "https://github.com/phpstan/phpdoc-parser/issues", + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.16.1" + }, + "time": "2023-02-07T18:11:17+00:00" + }, + { + "name": "phpstan/phpstan", + "version": "1.10.x-dev", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "aed9319bda4e1bf862e2576baf28949877891853" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/aed9319bda4e1bf862e2576baf28949877891853", + "reference": "aed9319bda4e1bf862e2576baf28949877891853", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "default-branch": true, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" ] }, "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - } - ], - "description": "sebastian/diff v3 backport support for PHP 5.6+", - "homepage": "https://github.com/PHP-CS-Fixer", - "keywords": [ - "diff" - ], - "support": { - "issues": "https://github.com/PHP-CS-Fixer/diff/issues", - "source": "https://github.com/PHP-CS-Fixer/diff/tree/v2.0.2" - }, - "time": "2020-10-14T08:32:19+00:00" - }, - { - "name": "phpdocumentor/reflection-common", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "a0eeab580cbdf4414fef6978732510a36ed0a9d6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/a0eeab580cbdf4414fef6978732510a36ed0a9d6", - "reference": "a0eeab580cbdf4414fef6978732510a36ed0a9d6", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "authors": [ - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", + "description": "PHPStan - PHP Static Analysis Tool", "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", + "dev", "static analysis" ], "support": { - "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", - "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/master" + "issues": "https://github.com/phpstan/phpstan/issues", + "source": "https://github.com/phpstan/phpstan/tree/1.10.x" }, - "time": "2021-06-25T13:47:51+00:00" - }, - { - "name": "phpdocumentor/reflection-docblock", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", - "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", - "shasum": "" - }, - "require": { - "ext-filter": "*", - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.3", - "webmozart/assert": "^1.9.1" - }, - "require-dev": { - "mockery/mockery": "~1.3.2", - "psalm/phar": "^4.8" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ + "funding": [ { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" + "url": "https://github.com/ondrejmirtes", + "type": "github" }, { - "name": "Jaap van Otterdijk", - "email": "account@ijaap.nl" - } - ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0" - }, - "time": "2021-10-19T17:43:47+00:00" - }, - { - "name": "phpdocumentor/type-resolver", - "version": "1.x-dev", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "f8ec4ab631de5a97769e66b13418c3b8b24e81f4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/f8ec4ab631de5a97769e66b13418c3b8b24e81f4", - "reference": "f8ec4ab631de5a97769e66b13418c3b8b24e81f4", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0", - "phpdocumentor/reflection-common": "^2.0" - }, - "require-dev": { - "ext-tokenizer": "*", - "psalm/phar": "^4.8" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-1.x": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "support": { - "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.x" - }, - "time": "2021-11-24T08:29:39+00:00" - }, - { - "name": "phpspec/prophecy", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/bbcd7380b0ebf3961ee21409db7b38bc31d69a13", - "reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.2", - "php": "^7.2 || ~8.0, <8.2", - "phpdocumentor/reflection-docblock": "^5.2", - "sebastian/comparator": "^3.0 || ^4.0", - "sebastian/recursion-context": "^3.0 || ^4.0" - }, - "require-dev": { - "phpspec/phpspec": "^6.0 || ^7.0", - "phpunit/phpunit": "^8.0 || ^9.0" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Prophecy\\": "src/Prophecy" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" + "url": "https://github.com/phpstan", + "type": "github" }, { - "name": "Marcello Duarte", - "email": "marcello.duarte@gmail.com" + "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", + "type": "tidelift" } ], - "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", - "keywords": [ - "Double", - "Dummy", - "fake", - "mock", - "spy", - "stub" - ], - "support": { - "issues": "https://github.com/phpspec/prophecy/issues", - "source": "https://github.com/phpspec/prophecy/tree/v1.15.0" - }, - "time": "2021-12-08T12:19:24+00:00" + "time": "2023-03-02T09:48:34+00:00" }, { "name": "phpunit/php-code-coverage", @@ -1523,19 +2288,19 @@ "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "747f93928bcac855054f2781c209ec80d469fe14" + "reference": "700aa825126460ce5be79ae5e1cf2e2c5b71588b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/747f93928bcac855054f2781c209ec80d469fe14", - "reference": "747f93928bcac855054f2781c209ec80d469fe14", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/700aa825126460ce5be79ae5e1cf2e2c5b71588b", + "reference": "700aa825126460ce5be79ae5e1cf2e2c5b71588b", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.13.0", + "nikic/php-parser": "^4.15", "php": ">=7.3", "phpunit/php-file-iterator": "^3.0.3", "phpunit/php-text-template": "^2.0.2", @@ -1592,7 +2357,7 @@ "type": "github" } ], - "time": "2021-12-13T15:03:35+00:00" + "time": "2023-02-27T12:51:14+00:00" }, { "name": "phpunit/php-file-iterator", @@ -1600,12 +2365,12 @@ "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" + "reference": "38b24367e1b340aa78b96d7cab042942d917bb84" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/38b24367e1b340aa78b96d7cab042942d917bb84", + "reference": "38b24367e1b340aa78b96d7cab042942d917bb84", "shasum": "" }, "require": { @@ -1652,7 +2417,7 @@ "type": "github" } ], - "time": "2021-12-02T12:48:52+00:00" + "time": "2022-02-11T16:23:04+00:00" }, { "name": "phpunit/php-invoker", @@ -1837,20 +2602,20 @@ }, { "name": "phpunit/phpunit", - "version": "9.5.x-dev", + "version": "9.6.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "09f082e2c7564dc3a889e73015c65b836e2303a0" + "reference": "d6454d6dd71024848893a1e2d1f1dd78683351db" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/09f082e2c7564dc3a889e73015c65b836e2303a0", - "reference": "09f082e2c7564dc3a889e73015c65b836e2303a0", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d6454d6dd71024848893a1e2d1f1dd78683351db", + "reference": "d6454d6dd71024848893a1e2d1f1dd78683351db", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.3.1", + "doctrine/instantiator": "^1.3.1 || ^2", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", @@ -1861,28 +2626,23 @@ "phar-io/manifest": "^2.0.3", "phar-io/version": "^3.0.2", "php": ">=7.3", - "phpspec/prophecy": "^1.12.1", - "phpunit/php-code-coverage": "^9.2.7", + "phpunit/php-code-coverage": "^9.2.13", "phpunit/php-file-iterator": "^3.0.5", "phpunit/php-invoker": "^3.1.1", "phpunit/php-text-template": "^2.0.3", "phpunit/php-timer": "^5.0.2", "sebastian/cli-parser": "^1.0.1", "sebastian/code-unit": "^1.0.6", - "sebastian/comparator": "^4.0.5", + "sebastian/comparator": "^4.0.8", "sebastian/diff": "^4.0.3", "sebastian/environment": "^5.1.3", - "sebastian/exporter": "^4.0.3", + "sebastian/exporter": "^4.0.5", "sebastian/global-state": "^5.0.1", "sebastian/object-enumerator": "^4.0.3", "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^2.3.4", + "sebastian/type": "^3.2", "sebastian/version": "^3.0.2" }, - "require-dev": { - "ext-pdo": "*", - "phpspec/prophecy-phpunit": "^2.0.1" - }, "suggest": { "ext-soap": "*", "ext-xdebug": "*" @@ -1893,15 +2653,15 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.5-dev" + "dev-master": "9.6-dev" } }, "autoload": { - "classmap": [ - "src/" - ], "files": [ "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -1924,7 +2684,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6" }, "funding": [ { @@ -1934,31 +2694,39 @@ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" } ], - "time": "2021-12-13T14:59:17+00:00" + "time": "2023-02-28T06:43:37+00:00" }, { "name": "psr/cache", - "version": "1.0.1", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/php-fig/cache.git", - "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" + "reference": "0a7c67d0d1c8167b342eb74339d6f961663826ce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", - "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", + "url": "https://api.github.com/repos/php-fig/cache/zipball/0a7c67d0d1c8167b342eb74339d6f961663826ce", + "reference": "0a7c67d0d1c8167b342eb74339d6f961663826ce", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=8.0.0" }, + "suggest": { + "fig/cache-util": "Provides some useful PSR-6 utilities" + }, + "default-branch": true, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "3.0.x-dev" } }, "autoload": { @@ -1973,7 +2741,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interface for caching libraries", @@ -1985,26 +2753,32 @@ "support": { "source": "https://github.com/php-fig/cache/tree/master" }, - "time": "2016-08-06T20:24:11+00:00" + "time": "2021-02-24T03:25:37+00:00" }, { "name": "psr/container", - "version": "1.x-dev", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/php-fig/container.git", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" + "reference": "90db7b9ac2a2c5b849fcb69dde58f3ae182c68f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", + "url": "https://api.github.com/repos/php-fig/container/zipball/90db7b9ac2a2c5b849fcb69dde58f3ae182c68f5", + "reference": "90db7b9ac2a2c5b849fcb69dde58f3ae182c68f5", "shasum": "" }, "require": { "php": ">=7.4.0" }, + "default-branch": true, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, "autoload": { "psr-4": { "Psr\\Container\\": "src/" @@ -2031,9 +2805,9 @@ ], "support": { "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/1.1.2" + "source": "https://github.com/php-fig/container/tree/master" }, - "time": "2021-11-05T16:50:12+00:00" + "time": "2022-07-19T17:36:59+00:00" }, { "name": "psr/event-dispatcher", @@ -2041,12 +2815,12 @@ "source": { "type": "git", "url": "https://github.com/php-fig/event-dispatcher.git", - "reference": "aa4f89e91c423b516ff226c50dc83f824011c253" + "reference": "e275e2d67d53964a3f13e056886ecd769edee021" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/aa4f89e91c423b516ff226c50dc83f824011c253", - "reference": "aa4f89e91c423b516ff226c50dc83f824011c253", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/e275e2d67d53964a3f13e056886ecd769edee021", + "reference": "e275e2d67d53964a3f13e056886ecd769edee021", "shasum": "" }, "require": { @@ -2086,34 +2860,198 @@ "support": { "source": "https://github.com/php-fig/event-dispatcher/tree/master" }, - "time": "2021-02-08T21:15:39+00:00" + "time": "2022-06-29T17:22:39+00:00" }, { - "name": "psr/log", - "version": "1.1.4", + "name": "psr/http-client", + "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11" + "url": "https://github.com/php-fig/http-client.git", + "reference": "22b2ef5687f43679481615605d7a15c557ce85b1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/22b2ef5687f43679481615605d7a15c557ce85b1", + "reference": "22b2ef5687f43679481615605d7a15c557ce85b1", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0" + }, + "default-branch": true, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client/tree/master" + }, + "time": "2020-09-19T09:12:31+00:00" + }, + { + "name": "psr/http-factory", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "5a4f141ac2e5bc35e615134f127e1833158d2944" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/5a4f141ac2e5bc35e615134f127e1833158d2944", + "reference": "5a4f141ac2e5bc35e615134f127e1833158d2944", + "shasum": "" + }, + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0" + }, + "default-branch": true, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory/tree/master" + }, + "time": "2022-07-14T07:21:53+00:00" + }, + { + "name": "psr/http-message", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "efd67d1dc14a7ef4fc4e518e7dee91c271d524e4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/efd67d1dc14a7ef4fc4e518e7dee91c271d524e4", + "reference": "efd67d1dc14a7ef4fc4e518e7dee91c271d524e4", "shasum": "" }, "require": { "php": ">=5.3.0" }, + "default-branch": true, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { "psr-4": { - "Psr\\Log\\": "Psr/Log/" + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/master" + }, + "time": "2019-08-29T13:16:46+00:00" + }, + { + "name": "psr/log", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "default-branch": true, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -2134,9 +3072,99 @@ "psr-3" ], "support": { - "source": "https://github.com/php-fig/log/tree/1.1.4" + "source": "https://github.com/php-fig/log/tree/3.0.0" }, - "time": "2021-05-03T11:20:27+00:00" + "time": "2021-07-14T16:46:02+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "time": "2019-03-08T08:55:37+00:00" + }, + { + "name": "scrutinizer/ocular", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/scrutinizer-ci/ocular.git", + "reference": "dda3540f7458b2645cee2a02b24291914769c41c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/scrutinizer-ci/ocular/zipball/dda3540f7458b2645cee2a02b24291914769c41c", + "reference": "dda3540f7458b2645cee2a02b24291914769c41c", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "~6.3|^7.0", + "jms/serializer": "^1.0.0|^3.0", + "phpoption/phpoption": "~1.0", + "symfony/console": "^2.1.0|~3.0|~4.0|~5.0|^6.0", + "symfony/process": "~2.3|~3.0|~4.0|~5.0|^6.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.2", + "phpunit/phpunit": "^9.0.0", + "symfony/filesystem": "~2.0|~3.0|~4.0|~5.0|^6.0" + }, + "default-branch": true, + "bin": [ + "bin/ocular" + ], + "type": "library", + "autoload": { + "psr-4": { + "Scrutinizer\\Ocular\\": "src/Scrutinizer/Ocular" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "support": { + "issues": "https://github.com/scrutinizer-ci/ocular/issues", + "source": "https://github.com/scrutinizer-ci/ocular/tree/1.9" + }, + "time": "2022-02-22T09:49:51+00:00" }, { "name": "sebastian/cli-parser", @@ -2307,16 +3335,16 @@ }, { "name": "sebastian/comparator", - "version": "4.0.6", + "version": "4.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382" + "reference": "b247957a1c8dc81a671770f74b479c0a78a818f1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55f4261989e546dc112258c7a75935a81a7ce382", - "reference": "55f4261989e546dc112258c7a75935a81a7ce382", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/b247957a1c8dc81a671770f74b479c0a78a818f1", + "reference": "b247957a1c8dc81a671770f74b479c0a78a818f1", "shasum": "" }, "require": { @@ -2369,7 +3397,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.6" + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0" }, "funding": [ { @@ -2377,7 +3405,7 @@ "type": "github" } ], - "time": "2020-10-26T15:49:45+00:00" + "time": "2022-09-14T12:46:14+00:00" }, { "name": "sebastian/complexity", @@ -2504,16 +3532,16 @@ }, { "name": "sebastian/environment", - "version": "5.1.3", + "version": "5.1.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "388b6ced16caa751030f6a69e588299fa09200ac" + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/388b6ced16caa751030f6a69e588299fa09200ac", - "reference": "388b6ced16caa751030f6a69e588299fa09200ac", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", "shasum": "" }, "require": { @@ -2555,7 +3583,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.3" + "source": "https://github.com/sebastianbergmann/environment/tree/5.1" }, "funding": [ { @@ -2563,7 +3591,7 @@ "type": "github" } ], - "time": "2020-09-28T05:52:38+00:00" + "time": "2023-02-03T06:03:51+00:00" }, { "name": "sebastian/exporter", @@ -2571,12 +3599,12 @@ "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9" + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/65e8b7db476c5dd267e65eea9cab77584d3cfff9", - "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", "shasum": "" }, "require": { @@ -2640,20 +3668,20 @@ "type": "github" } ], - "time": "2021-11-11T14:18:36+00:00" + "time": "2022-09-14T06:03:37+00:00" }, { "name": "sebastian/global-state", - "version": "5.0.3", + "version": "5.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "23bd5951f7ff26f12d4e3242864df3e08dec4e49" + "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/23bd5951f7ff26f12d4e3242864df3e08dec4e49", - "reference": "23bd5951f7ff26f12d4e3242864df3e08dec4e49", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2", + "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2", "shasum": "" }, "require": { @@ -2696,7 +3724,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.3" + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5" }, "funding": [ { @@ -2704,7 +3732,7 @@ "type": "github" } ], - "time": "2021-06-11T13:31:12+00:00" + "time": "2022-02-14T08:28:10+00:00" }, { "name": "sebastian/lines-of-code", @@ -2877,16 +3905,16 @@ }, { "name": "sebastian/recursion-context", - "version": "4.0.4", + "version": "4.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172" + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", "shasum": "" }, "require": { @@ -2925,10 +3953,10 @@ } ], "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4" + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" }, "funding": [ { @@ -2936,20 +3964,20 @@ "type": "github" } ], - "time": "2020-10-26T13:17:30+00:00" + "time": "2023-02-03T06:07:39+00:00" }, { "name": "sebastian/resource-operations", - "version": "dev-master", + "version": "dev-main", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" + "reference": "e1157eac767e4dc4ae40dd9aab7fb4de6e56bd32" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/e1157eac767e4dc4ae40dd9aab7fb4de6e56bd32", + "reference": "e1157eac767e4dc4ae40dd9aab7fb4de6e56bd32", "shasum": "" }, "require": { @@ -2962,7 +3990,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -2983,8 +4011,7 @@ "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", "support": { - "issues": "https://github.com/sebastianbergmann/resource-operations/issues", - "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" + "source": "https://github.com/sebastianbergmann/resource-operations/tree/main" }, "funding": [ { @@ -2992,32 +4019,32 @@ "type": "github" } ], - "time": "2020-09-28T06:45:17+00:00" + "time": "2023-02-08T06:53:39+00:00" }, { "name": "sebastian/type", - "version": "2.3.x-dev", + "version": "3.2.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "f24cbc541026c3bb7d27c647f0f9ea337135b22a" + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/f24cbc541026c3bb7d27c647f0f9ea337135b22a", - "reference": "f24cbc541026c3bb7d27c647f0f9ea337135b22a", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", "shasum": "" }, "require": { "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^9.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -3040,7 +4067,7 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/2.3" + "source": "https://github.com/sebastianbergmann/type/tree/3.2" }, "funding": [ { @@ -3048,7 +4075,7 @@ "type": "github" } ], - "time": "2021-06-18T06:28:45+00:00" + "time": "2023-02-03T06:13:03+00:00" }, { "name": "sebastian/version", @@ -3105,46 +4132,43 @@ }, { "name": "symfony/console", - "version": "5.4.x-dev", + "version": "6.3.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "9130e1a0fc93cb0faadca4ee917171bd2ca9e5f4" + "reference": "1090bd292e4de35682f80e94d196c62aab4b3ad7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/9130e1a0fc93cb0faadca4ee917171bd2ca9e5f4", - "reference": "9130e1a0fc93cb0faadca4ee917171bd2ca9e5f4", + "url": "https://api.github.com/repos/symfony/console/zipball/1090bd292e4de35682f80e94d196c62aab4b3ad7", + "reference": "1090bd292e4de35682f80e94d196c62aab4b3ad7", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php73": "^1.9", - "symfony/polyfill-php80": "^1.16", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/string": "^5.1|^6.0" + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^5.4|^6.0" }, "conflict": { - "psr/log": ">=3", - "symfony/dependency-injection": "<4.4", - "symfony/dotenv": "<5.1", - "symfony/event-dispatcher": "<4.4", - "symfony/lock": "<4.4", - "symfony/process": "<4.4" + "symfony/dependency-injection": "<5.4", + "symfony/dotenv": "<5.4", + "symfony/event-dispatcher": "<5.4", + "symfony/lock": "<5.4", + "symfony/process": "<5.4" }, "provide": { - "psr/log-implementation": "1.0|2.0" + "psr/log-implementation": "1.0|2.0|3.0" }, "require-dev": { - "psr/log": "^1|^2", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/event-dispatcher": "^4.4|^5.0|^6.0", - "symfony/lock": "^4.4|^5.0|^6.0", - "symfony/process": "^4.4|^5.0|^6.0", - "symfony/var-dumper": "^4.4|^5.0|^6.0" + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/lock": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0", + "symfony/var-dumper": "^5.4|^6.0" }, "suggest": { "psr/log": "For using the console logger", @@ -3152,7 +4176,6 @@ "symfony/lock": "", "symfony/process": "" }, - "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -3185,7 +4208,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.4.1" + "source": "https://github.com/symfony/console/tree/6.3" }, "funding": [ { @@ -3201,29 +4224,30 @@ "type": "tidelift" } ], - "time": "2021-12-09T11:22:43+00:00" + "time": "2023-02-25T17:00:13+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "2.5.x-dev", + "version": "dev-main", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8" + "reference": "e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/6f981ee24cf69ee7ce9736146d1c57c2780598a8", - "reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e", + "reference": "e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=8.1" }, + "default-branch": true, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.5-dev" + "dev-main": "3.3-dev" }, "thanks": { "name": "symfony/contracts", @@ -3252,7 +4276,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/main" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.2.1" }, "funding": [ { @@ -3268,50 +4292,48 @@ "type": "tidelift" } ], - "time": "2021-07-12T14:48:14+00:00" + "time": "2023-03-01T10:25:55+00:00" }, { "name": "symfony/event-dispatcher", - "version": "5.4.x-dev", + "version": "6.3.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "27d39ae126352b9fa3be5e196ccf4617897be3eb" + "reference": "c58ec8623b8cbb3739fbaab5bf972df3f68ef312" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/27d39ae126352b9fa3be5e196ccf4617897be3eb", - "reference": "27d39ae126352b9fa3be5e196ccf4617897be3eb", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/c58ec8623b8cbb3739fbaab5bf972df3f68ef312", + "reference": "c58ec8623b8cbb3739fbaab5bf972df3f68ef312", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/event-dispatcher-contracts": "^2|^3", - "symfony/polyfill-php80": "^1.16" + "php": ">=8.1", + "symfony/event-dispatcher-contracts": "^2.5|^3" }, "conflict": { - "symfony/dependency-injection": "<4.4" + "symfony/dependency-injection": "<5.4", + "symfony/service-contracts": "<2.5" }, "provide": { "psr/event-dispatcher-implementation": "1.0", - "symfony/event-dispatcher-implementation": "2.0" + "symfony/event-dispatcher-implementation": "2.0|3.0" }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/http-foundation": "^4.4|^5.0|^6.0", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/stopwatch": "^4.4|^5.0|^6.0" + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/error-handler": "^5.4|^6.0", + "symfony/expression-language": "^5.4|^6.0", + "symfony/http-foundation": "^5.4|^6.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/stopwatch": "^5.4|^6.0" }, "suggest": { "symfony/dependency-injection": "", "symfony/http-kernel": "" }, - "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -3338,7 +4360,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v5.4.0" + "source": "https://github.com/symfony/event-dispatcher/tree/6.3" }, "funding": [ { @@ -3354,33 +4376,34 @@ "type": "tidelift" } ], - "time": "2021-11-23T10:19:22+00:00" + "time": "2023-02-16T09:01:12+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "2.5.x-dev", + "version": "dev-main", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "66bea3b09be61613cd3b4043a65a8ec48cfa6d2a" + "reference": "0ad3b6f1e4e2da5690fefe075cd53a238646d8dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/66bea3b09be61613cd3b4043a65a8ec48cfa6d2a", - "reference": "66bea3b09be61613cd3b4043a65a8ec48cfa6d2a", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/0ad3b6f1e4e2da5690fefe075cd53a238646d8dd", + "reference": "0ad3b6f1e4e2da5690fefe075cd53a238646d8dd", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.1", "psr/event-dispatcher": "^1" }, "suggest": { "symfony/event-dispatcher-implementation": "" }, + "default-branch": true, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.5-dev" + "dev-main": "3.3-dev" }, "thanks": { "name": "symfony/contracts", @@ -3417,7 +4440,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/2.5" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.2.1" }, "funding": [ { @@ -3433,29 +4456,27 @@ "type": "tidelift" } ], - "time": "2021-07-12T14:48:14+00:00" + "time": "2023-03-01T10:32:47+00:00" }, { "name": "symfony/filesystem", - "version": "5.4.x-dev", + "version": "6.3.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "731f917dc31edcffec2c6a777f3698c33bea8f01" + "reference": "bf3226d895bb4cd6635ef42649ec4a5818e3bf01" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/731f917dc31edcffec2c6a777f3698c33bea8f01", - "reference": "731f917dc31edcffec2c6a777f3698c33bea8f01", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/bf3226d895bb4cd6635ef42649ec4a5818e3bf01", + "reference": "bf3226d895bb4cd6635ef42649ec4a5818e3bf01", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.1", "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.8", - "symfony/polyfill-php80": "^1.16" + "symfony/polyfill-mbstring": "~1.8" }, - "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -3482,7 +4503,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v5.4.0" + "source": "https://github.com/symfony/filesystem/tree/6.3" }, "funding": [ { @@ -3498,28 +4519,28 @@ "type": "tidelift" } ], - "time": "2021-10-28T13:39:27+00:00" + "time": "2023-02-14T09:04:20+00:00" }, { "name": "symfony/finder", - "version": "5.4.x-dev", + "version": "6.3.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "d2f29dac98e96a98be467627bd49c2efb1bc2590" + "reference": "f5891f0383dc22a615ebd5848e87328d1efad0be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/d2f29dac98e96a98be467627bd49c2efb1bc2590", - "reference": "d2f29dac98e96a98be467627bd49c2efb1bc2590", + "url": "https://api.github.com/repos/symfony/finder/zipball/f5891f0383dc22a615ebd5848e87328d1efad0be", + "reference": "f5891f0383dc22a615ebd5848e87328d1efad0be", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php80": "^1.16" + "php": ">=8.1" + }, + "require-dev": { + "symfony/filesystem": "^6.0" }, - "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -3546,7 +4567,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v5.4.0" + "source": "https://github.com/symfony/finder/tree/6.3" }, "funding": [ { @@ -3562,29 +4583,26 @@ "type": "tidelift" } ], - "time": "2021-11-28T15:25:38+00:00" + "time": "2023-02-14T09:04:20+00:00" }, { "name": "symfony/options-resolver", - "version": "5.4.x-dev", + "version": "6.3.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "b0fb78576487af19c500aaddb269fd36701d4847" + "reference": "2fdfd4259397b1300da21c04ba52a673763b73c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/b0fb78576487af19c500aaddb269fd36701d4847", - "reference": "b0fb78576487af19c500aaddb269fd36701d4847", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/2fdfd4259397b1300da21c04ba52a673763b73c9", + "reference": "2fdfd4259397b1300da21c04ba52a673763b73c9", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-php73": "~1.0", - "symfony/polyfill-php80": "^1.16" + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3" }, - "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -3616,7 +4634,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v5.4.0" + "source": "https://github.com/symfony/options-resolver/tree/6.3" }, "funding": [ { @@ -3632,7 +4650,7 @@ "type": "tidelift" } ], - "time": "2021-11-23T10:19:22+00:00" + "time": "2023-02-14T09:04:20+00:00" }, { "name": "symfony/polyfill-ctype", @@ -3640,12 +4658,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "30885182c981ab175d4d034db0f6f469898070ab" + "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/30885182c981ab175d4d034db0f6f469898070ab", - "reference": "30885182c981ab175d4d034db0f6f469898070ab", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", + "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", "shasum": "" }, "require": { @@ -3661,7 +4679,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.23-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -3669,12 +4687,12 @@ } }, "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - }, "files": [ "bootstrap.php" - ] + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -3715,7 +4733,7 @@ "type": "tidelift" } ], - "time": "2021-10-20T20:35:02+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/polyfill-intl-grapheme", @@ -3723,12 +4741,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "81b86b50cf841a64252b439e738e97f4a34e2783" + "reference": "875e90aeea2777b6f135677f618529449334a612" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/81b86b50cf841a64252b439e738e97f4a34e2783", - "reference": "81b86b50cf841a64252b439e738e97f4a34e2783", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/875e90aeea2777b6f135677f618529449334a612", + "reference": "875e90aeea2777b6f135677f618529449334a612", "shasum": "" }, "require": { @@ -3741,7 +4759,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.23-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -3749,12 +4767,12 @@ } }, "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Intl\\Grapheme\\": "" - }, "files": [ "bootstrap.php" - ] + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -3797,7 +4815,7 @@ "type": "tidelift" } ], - "time": "2021-11-23T21:10:46+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/polyfill-intl-normalizer", @@ -3805,12 +4823,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8" + "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8", - "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", + "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", "shasum": "" }, "require": { @@ -3823,7 +4841,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.23-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -3831,12 +4849,12 @@ } }, "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Intl\\Normalizer\\": "" - }, "files": [ "bootstrap.php" ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, "classmap": [ "Resources/stubs" ] @@ -3866,7 +4884,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.23.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/main" }, "funding": [ { @@ -3882,7 +4900,7 @@ "type": "tidelift" } ], - "time": "2021-02-19T12:13:01+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/polyfill-mbstring", @@ -3890,12 +4908,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825" + "reference": "f9c7affe77a00ae32ca127ca6833d034e6d33f25" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/0abb51d2f102e00a4eefcf46ba7fec406d245825", - "reference": "0abb51d2f102e00a4eefcf46ba7fec406d245825", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/f9c7affe77a00ae32ca127ca6833d034e6d33f25", + "reference": "f9c7affe77a00ae32ca127ca6833d034e6d33f25", "shasum": "" }, "require": { @@ -3911,7 +4929,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.23-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -3919,12 +4937,12 @@ } }, "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - }, "files": [ "bootstrap.php" - ] + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -3966,87 +4984,7 @@ "type": "tidelift" } ], - "time": "2021-11-30T18:21:41+00:00" - }, - { - "name": "symfony/polyfill-php73", - "version": "dev-main", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "cc5db0e22b3cb4111010e48785a97f670b350ca5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/cc5db0e22b3cb4111010e48785a97f670b350ca5", - "reference": "cc5db0e22b3cb4111010e48785a97f670b350ca5", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.23-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Php73\\": "" - }, - "files": [ - "bootstrap.php" - ], - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/main" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2021-06-05T21:20:04+00:00" + "time": "2023-01-30T17:25:47+00:00" }, { "name": "symfony/polyfill-php80", @@ -4054,12 +4992,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "57b712b08eddb97c762a8caa32c84e037892d2e9" + "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/57b712b08eddb97c762a8caa32c84e037892d2e9", - "reference": "57b712b08eddb97c762a8caa32c84e037892d2e9", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5", + "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5", "shasum": "" }, "require": { @@ -4069,7 +5007,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.23-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -4077,12 +5015,12 @@ } }, "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" - }, "files": [ "bootstrap.php" ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, "classmap": [ "Resources/stubs" ] @@ -4130,7 +5068,7 @@ "type": "tidelift" } ], - "time": "2021-09-13T13:58:33+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/polyfill-php81", @@ -4138,12 +5076,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "5de4ba2d41b15f9bd0e19b2ab9674135813ec98f" + "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/5de4ba2d41b15f9bd0e19b2ab9674135813ec98f", - "reference": "5de4ba2d41b15f9bd0e19b2ab9674135813ec98f", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/7581cd600fa9fd681b797d00b02f068e2f13263b", + "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b", "shasum": "" }, "require": { @@ -4153,7 +5091,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.23-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -4161,12 +5099,12 @@ } }, "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Php81\\": "" - }, "files": [ "bootstrap.php" ], + "psr-4": { + "Symfony\\Polyfill\\Php81\\": "" + }, "classmap": [ "Resources/stubs" ] @@ -4210,27 +5148,25 @@ "type": "tidelift" } ], - "time": "2021-09-13T13:58:11+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/process", - "version": "5.4.x-dev", + "version": "6.3.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "bf0e245dd8f115502d11df04cdb91c49abbc83ec" + "reference": "e65ce5c9ccb249616aab1dbec53fc938c9017a4c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/bf0e245dd8f115502d11df04cdb91c49abbc83ec", - "reference": "bf0e245dd8f115502d11df04cdb91c49abbc83ec", + "url": "https://api.github.com/repos/symfony/process/zipball/e65ce5c9ccb249616aab1dbec53fc938c9017a4c", + "reference": "e65ce5c9ccb249616aab1dbec53fc938c9017a4c", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/polyfill-php80": "^1.16" + "php": ">=8.1" }, - "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -4257,7 +5193,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/5.4" + "source": "https://github.com/symfony/process/tree/6.3" }, "funding": [ { @@ -4273,26 +5209,25 @@ "type": "tidelift" } ], - "time": "2021-12-11T16:33:38+00:00" + "time": "2023-02-24T10:44:40+00:00" }, { "name": "symfony/service-contracts", - "version": "2.5.x-dev", + "version": "dev-main", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "034c73d5dd4c05c71a27f05b3c43c0f2fcc8985a" + "reference": "a8c9cedf55f314f3a186041d19537303766df09a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/034c73d5dd4c05c71a27f05b3c43c0f2fcc8985a", - "reference": "034c73d5dd4c05c71a27f05b3c43c0f2fcc8985a", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/a8c9cedf55f314f3a186041d19537303766df09a", + "reference": "a8c9cedf55f314f3a186041d19537303766df09a", "shasum": "" }, "require": { - "php": ">=7.2.5", - "psr/container": "^1.1", - "symfony/deprecation-contracts": "^2.1|^3" + "php": ">=8.1", + "psr/container": "^2.0" }, "conflict": { "ext-psr": "<1.1|>=2" @@ -4300,10 +5235,11 @@ "suggest": { "symfony/service-implementation": "" }, + "default-branch": true, "type": "library", "extra": { "branch-alias": { - "dev-main": "2.5-dev" + "dev-main": "3.3-dev" }, "thanks": { "name": "symfony/contracts", @@ -4313,7 +5249,10 @@ "autoload": { "psr-4": { "Symfony\\Contracts\\Service\\": "" - } + }, + "exclude-from-classmap": [ + "/Test/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -4340,7 +5279,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/2.5" + "source": "https://github.com/symfony/service-contracts/tree/v3.2.1" }, "funding": [ { @@ -4356,27 +5295,26 @@ "type": "tidelift" } ], - "time": "2021-11-23T10:19:22+00:00" + "time": "2023-03-01T10:32:47+00:00" }, { "name": "symfony/stopwatch", - "version": "5.4.x-dev", + "version": "6.3.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "208ef96122bfed82a8f3a61458a07113a08bdcfe" + "reference": "f7fa451783b748e7b5942b9afe889b8df062e935" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/208ef96122bfed82a8f3a61458a07113a08bdcfe", - "reference": "208ef96122bfed82a8f3a61458a07113a08bdcfe", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/f7fa451783b748e7b5942b9afe889b8df062e935", + "reference": "f7fa451783b748e7b5942b9afe889b8df062e935", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/service-contracts": "^1|^2|^3" + "php": ">=8.1", + "symfony/service-contracts": "^2.5|^3" }, - "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -4403,7 +5341,7 @@ "description": "Provides a way to profile code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/stopwatch/tree/v5.4.0" + "source": "https://github.com/symfony/stopwatch/tree/6.3" }, "funding": [ { @@ -4419,48 +5357,47 @@ "type": "tidelift" } ], - "time": "2021-11-23T10:19:22+00:00" + "time": "2023-02-14T09:04:20+00:00" }, { "name": "symfony/string", - "version": "5.4.x-dev", + "version": "6.3.x-dev", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "1a03b5bab07779e5f23f8b60ba76ccb7662ffcf6" + "reference": "599f0f073afa9866d1d3b16c1ffafa74a69fb3ce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/1a03b5bab07779e5f23f8b60ba76ccb7662ffcf6", - "reference": "1a03b5bab07779e5f23f8b60ba76ccb7662ffcf6", + "url": "https://api.github.com/repos/symfony/string/zipball/599f0f073afa9866d1d3b16c1ffafa74a69fb3ce", + "reference": "599f0f073afa9866d1d3b16c1ffafa74a69fb3ce", "shasum": "" }, "require": { - "php": ">=7.2.5", + "php": ">=8.1", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-grapheme": "~1.0", "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "~1.15" + "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/translation-contracts": ">=3.0" + "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/http-client": "^4.4|^5.0|^6.0", - "symfony/translation-contracts": "^1.1|^2", - "symfony/var-exporter": "^4.4|^5.0|^6.0" + "symfony/error-handler": "^5.4|^6.0", + "symfony/http-client": "^5.4|^6.0", + "symfony/intl": "^6.2", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^5.4|^6.0" }, - "default-branch": true, "type": "library", "autoload": { - "psr-4": { - "Symfony\\Component\\String\\": "" - }, "files": [ "Resources/functions.php" ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, "exclude-from-classmap": [ "/Tests/" ] @@ -4490,7 +5427,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/5.4" + "source": "https://github.com/symfony/string/tree/6.3" }, "funding": [ { @@ -4506,7 +5443,7 @@ "type": "tidelift" } ], - "time": "2021-12-11T13:33:37+00:00" + "time": "2023-02-24T10:44:40+00:00" }, { "name": "theseer/tokenizer", @@ -4557,81 +5494,27 @@ } ], "time": "2021-07-28T10:34:58+00:00" - }, - { - "name": "webmozart/assert", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/webmozarts/assert.git", - "reference": "b419d648592b0b8911cbbe10d450fe314f4fd262" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/b419d648592b0b8911cbbe10d450fe314f4fd262", - "reference": "b419d648592b0b8911cbbe10d450fe314f4fd262", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0", - "symfony/polyfill-ctype": "^1.8" - }, - "conflict": { - "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<4.6.1 || 4.6.2" - }, - "require-dev": { - "phpunit/phpunit": "^8.5.13" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.10-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "support": { - "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/master" - }, - "time": "2021-06-19T13:45:26+00:00" } ], "aliases": [], "minimum-stability": "dev", - "stability-flags": [], + "stability-flags": { + "shish/gqla": 20, + "naroga/redis-cache": 20, + "scrutinizer/ocular": 20, + "phpstan/phpstan": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": "^7.4 | ^8.0", + "php": "^8.1", "ext-pdo": "*", "ext-json": "*", "ext-fileinfo": "*" }, "platform-dev": [], "platform-overrides": { - "php": "7.4.0" + "php": "8.1.0" }, - "plugin-api-version": "2.2.0" + "plugin-api-version": "2.3.0" } diff --git a/core/basepage.php b/core/basepage.php index 11a99a88..410ae35b 100644 --- a/core/basepage.php +++ b/core/basepage.php @@ -1,15 +1,18 @@ mode = $mode; } @@ -227,7 +230,7 @@ class BasePage public function send_headers(): void { if (!headers_sent()) { - header("HTTP/1.0 {$this->code} Shimmie"); + header("HTTP/1.1 {$this->code} Shimmie"); header("Content-type: " . $this->mime); header("X-Powered-By: Shimmie-" . VERSION); @@ -255,7 +258,7 @@ class BasePage case PageMode::MANUAL: break; case PageMode::PAGE: - usort($this->blocks, "blockcmp"); + usort($this->blocks, "Shimmie2\blockcmp"); $this->add_auto_html_headers(); $this->render(); break; @@ -270,6 +273,7 @@ class BasePage if (!is_null($this->filename)) { header('Content-Disposition: ' . $this->disposition . '; filename=' . $this->filename); } + assert($this->file, "file should not be null with PageMode::FILE"); // https://gist.github.com/codler/3906826 $size = filesize($this->file); // File size @@ -468,8 +472,8 @@ class BasePage } $sub_links = $sub_links??[]; - usort($nav_links, "sort_nav_links"); - usort($sub_links, "sort_nav_links"); + usort($nav_links, "Shimmie2\sort_nav_links"); + usort($sub_links, "Shimmie2\sort_nav_links"); return [$nav_links, $sub_links]; } diff --git a/core/basethemelet.php b/core/basethemelet.php index 13e8f245..2338d34f 100644 --- a/core/basethemelet.php +++ b/core/basethemelet.php @@ -2,6 +2,8 @@ declare(strict_types=1); +namespace Shimmie2; + /** * Class BaseThemelet * @@ -64,7 +66,7 @@ class BaseThemelet } $custom_classes = ""; - if (class_exists("Relationships")) { + if (class_exists("Shimmie2\Relationships")) { if (property_exists($image, 'parent_id') && $image->parent_id !== null) { $custom_classes .= "shm-thumb-has_parent "; } @@ -136,8 +138,8 @@ class BaseThemelet $next_html = $at_end ? "Next" : $this->gen_page_link($base_url, $query, $next, "Next"); $last_html = $at_end ? "Last" : $this->gen_page_link($base_url, $query, $total_pages, "Last"); - $start = $current_page-5 > 1 ? $current_page-5 : 1; - $end = $start+10 < $total_pages ? $start+10 : $total_pages; + $start = max($current_page - 5, 1); + $end = min($start + 10, $total_pages); $pages = []; foreach (range($start, $end) as $i) { diff --git a/core/block.php b/core/block.php index 40e0c726..8cf31329 100644 --- a/core/block.php +++ b/core/block.php @@ -2,6 +2,8 @@ declare(strict_types=1); +namespace Shimmie2; + /** * Class Block * @@ -43,10 +45,10 @@ class Block */ public bool $is_content = true; - public function __construct(string $header=null, string $body=null, string $section="main", int $position=50, string $id=null) + public function __construct(string $header=null, string|\MicroHTML\HTMLElement $body=null, string $section="main", int $position=50, string $id=null) { $this->header = $header; - $this->body = $body; + $this->body = (string)$body; $this->section = $section; $this->position = $position; diff --git a/core/cacheengine.php b/core/cacheengine.php index 37dadbea..18c379cc 100644 --- a/core/cacheengine.php +++ b/core/cacheengine.php @@ -1,200 +1,129 @@ memcache = new Memcached(); - #$this->memcache->setOption(Memcached::OPT_COMPRESSION, False); - #$this->memcache->setOption(Memcached::OPT_SERIALIZER, Memcached::SERIALIZER_PHP); - #$this->memcache->setOption(Memcached::OPT_PREFIX_KEY, phpversion()); - $this->memcache->addServer($hp[0], (int)$hp[1]); + $this->engine = $engine; + $this->tracer = $tracer; } - public function get(string $key) + public function get($key, $default=null) { - $key = urlencode($key); - - $val = $this->memcache->get($key); - $res = $this->memcache->getResultCode(); - - if ($res == Memcached::RES_SUCCESS) { - return $val; - } elseif ($res == Memcached::RES_NOTFOUND) { - return false; - } else { - error_log("Memcached error during get($key): $res"); - return false; + if ($key === "__etc_cache_hits") { + return $this->hits; } - } - - public function set(string $key, $val, int $time=0): void - { - $key = urlencode($key); - - $this->memcache->set($key, $val, $time); - $res = $this->memcache->getResultCode(); - if ($res != Memcached::RES_SUCCESS) { - error_log("Memcached error during set($key): $res"); + if ($key === "__etc_cache_misses") { + return $this->misses; } - } - public function delete(string $key): void - { - $key = urlencode($key); - - $this->memcache->delete($key); - $res = $this->memcache->getResultCode(); - if ($res != Memcached::RES_SUCCESS && $res != Memcached::RES_NOTFOUND) { - error_log("Memcached error during delete($key): $res"); - } - } -} - -class APCCache implements CacheEngine -{ - public function __construct(string $args) - { - // $args is not used, but is passed in when APC cache is created. - } - - public function get(string $key) - { - return apc_fetch($key); - } - - public function set(string $key, $val, int $time=0): void - { - apc_store($key, $val, $time); - } - - public function delete(string $key): void - { - apc_delete($key); - } -} - -class RedisCache implements CacheEngine -{ - private Redis $redis; - - public function __construct(string $args) - { - $this->redis = new Redis(); - $hp = explode(":", $args); - $this->redis->pconnect($hp[0], (int)$hp[1]); - $this->redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_PHP); - $this->redis->setOption(Redis::OPT_PREFIX, 'shm:'); - } - - public function get(string $key) - { - return $this->redis->get($key); - } - - public function set(string $key, $val, int $time=0): void - { - if ($time > 0) { - $this->redis->setEx($key, $time, $val); - } else { - $this->redis->set($key, $val); - } - } - - public function delete(string $key): void - { - $this->redis->del($key); - } -} - -class Cache -{ - public $engine; - public int $hits=0; - public int $misses=0; - public int $time=0; - - public function __construct(?string $dsn) - { - $matches = []; - $c = null; - if ($dsn && preg_match("#(.*)://(.*)#", $dsn, $matches) && !isset($_GET['DISABLE_CACHE'])) { - if ($matches[1] == "memcached") { - $c = new MemcachedCache($matches[2]); - } elseif ($matches[1] == "apc") { - $c = new APCCache($matches[2]); - } elseif ($matches[1] == "redis") { - $c = new RedisCache($matches[2]); - } - } else { - $c = new NoCache(); - } - $this->engine = $c; - } - - public function get(string $key) - { - global $_tracer; - $_tracer->begin("Cache Query", ["key"=>$key]); - $val = $this->engine->get($key); - if ($val !== false) { + $sentinel = "__etc_sentinel"; + $this->tracer->begin("Cache Get", ["key"=>$key]); + $val = $this->engine->get($key, $sentinel); + if ($val != $sentinel) { $res = "hit"; $this->hits++; } else { $res = "miss"; + $val = $default; $this->misses++; } - $_tracer->end(null, ["result"=>$res]); + $this->tracer->end(null, ["result"=>$res]); return $val; } - public function set(string $key, $val, int $time=0) + public function set($key, $value, $ttl = null) { - global $_tracer; - $_tracer->begin("Cache Set", ["key"=>$key, "time"=>$time]); - $this->engine->set($key, $val, $time); - $_tracer->end(); + $this->tracer->begin("Cache Set", ["key"=>$key, "ttl"=>$ttl]); + $val = $this->engine->set($key, $value, $ttl); + $this->tracer->end(); + return $val; } - public function delete(string $key) + public function delete($key) { - global $_tracer; - $_tracer->begin("Cache Delete", ["key"=>$key]); - $this->engine->delete($key); - $_tracer->end(); + $this->tracer->begin("Cache Delete", ["key"=>$key]); + $val = $this->engine->delete($key); + $this->tracer->end(); + return $val; } - public function get_hits(): int + public function clear() { - return $this->hits; + $this->tracer->begin("Cache Clear"); + $val = $this->engine->clear(); + $this->tracer->end(); + return $val; } - public function get_misses(): int + + public function getMultiple($keys, $default = null) { - return $this->misses; + $this->tracer->begin("Cache Get Multiple", ["keys" => $keys]); + $val = $this->engine->getMultiple($keys, $default); + $this->tracer->end(); + return $val; + } + + public function setMultiple($values, $ttl = null) + { + $this->tracer->begin("Cache Set Multiple", ["keys" => array_keys($values)]); + $val = $this->engine->setMultiple($values, $ttl); + $this->tracer->end(); + return $val; + } + + public function deleteMultiple($keys) + { + $this->tracer->begin("Cache Delete Multiple", ["keys" => $keys]); + $val = $this->engine->deleteMultiple($keys); + $this->tracer->end(); + return $val; + } + + public function has($key) + { + $this->tracer->begin("Cache Has", ["key"=>$key]); + $val = $this->engine->has($key); + $this->tracer->end(null, ["exists"=>$val]); + return $val; } } + +function loadCache(?string $dsn): CacheInterface +{ + $matches = []; + $c = null; + if ($dsn && preg_match("#(.*)://(.*)#", $dsn, $matches) && !isset($_GET['DISABLE_CACHE'])) { + if ($matches[1] == "memcached" || $matches[1] == "memcache") { + $hp = explode(":", $matches[2]); + $memcache = new \Memcached(); + $memcache->addServer($hp[0], (int)$hp[1]); + $c = new \Sabre\Cache\Memcached($memcache); + } elseif ($matches[1] == "apc") { + $c = new \Sabre\Cache\Apcu(); + } elseif ($matches[1] == "redis") { + $hp = explode(":", $matches[2]); + $redis = new \Predis\Client([ + 'scheme' => 'tcp', + 'host' => $hp[0], + 'port' => (int)$hp[1] + ], ['prefix' => 'shm:']); + $c = new \Naroga\RedisCache\Redis($redis); + } + } else { + $c = new \Sabre\Cache\Memory(); + } + global $_tracer; + return new EventTracingCache($c, $_tracer); +} diff --git a/core/captcha.php b/core/captcha.php index ec79c2cb..22c36f97 100644 --- a/core/captcha.php +++ b/core/captcha.php @@ -1,6 +1,9 @@ "; - } else { + } /*else { session_start(); - $captcha = Securimage::getCaptchaHtml(['securimage_path' => './vendor/dapphp/securimage/']); - } + $captcha = \Securimage::getCaptchaHtml(['securimage_path' => './vendor/dapphp/securimage/']); + }*/ } return $captcha; } @@ -48,14 +51,14 @@ function captcha_check(): bool log_info("core", "Captcha failed (ReCaptcha): " . implode("", $resp->getErrorCodes())); return false; } - } else { + } /*else { session_start(); - $securimg = new Securimage(); + $securimg = new \Securimage(); if ($securimg->check($_POST['captcha_code']) === false) { log_info("core", "Captcha failed (Securimage)"); return false; } - } + }*/ } return true; diff --git a/core/command_builder.php b/core/command_builder.php index bd1f828b..34b4532e 100644 --- a/core/command_builder.php +++ b/core/command_builder.php @@ -2,6 +2,8 @@ declare(strict_types=1); +namespace Shimmie2; + // Provides mechanisms for cleanly executing command-line applications // Was created to try to centralize a solution for whatever caused this: // quotes are only needed if the path to convert contains a space; some other times, quotes break things, see github bug #27 @@ -14,7 +16,7 @@ class CommandBuilder public function __construct(String $executable) { if (empty($executable)) { - throw new InvalidArgumentException("executable cannot be empty"); + throw new \InvalidArgumentException("executable cannot be empty"); } $this->executable = $executable; diff --git a/core/config.php b/core/config.php index 708d94be..3372bf17 100644 --- a/core/config.php +++ b/core/config.php @@ -2,6 +2,8 @@ declare(strict_types=1); +namespace Shimmie2; + /** * Interface Config * @@ -262,6 +264,7 @@ class DatabaseConfig extends BaseConfig private string $table_name; private ?string $sub_column; private ?string $sub_value; + private string $cache_name; public function __construct( Database $database, @@ -275,14 +278,10 @@ class DatabaseConfig extends BaseConfig $this->table_name = $table_name; $this->sub_value = $sub_value; $this->sub_column = $sub_column; + $this->cache_name = empty($sub_value) ? "config" : "config_{$sub_value}"; - $cache_name = "config"; - if (!empty($sub_value)) { - $cache_name .= "_".$sub_value; - } - - $cached = $cache->get($cache_name); - if ($cached) { + $cached = $cache->get($this->cache_name); + if (!is_null($cached)) { $this->values = $cached; } else { $this->values = []; @@ -298,7 +297,7 @@ class DatabaseConfig extends BaseConfig foreach ($this->database->get_all($query, $args) as $row) { $this->values[$row["name"]] = $row["value"]; } - $cache->set($cache_name, $this->values); + $cache->set($this->cache_name, $this->values); } } @@ -333,7 +332,7 @@ class DatabaseConfig extends BaseConfig } // rather than deleting and having some other request(s) do a thundering // herd of race-conditioned updates, just save the updated version once here - $cache->set("config", $this->values); - $this->database->notify("config"); + $cache->set($this->cache_name, $this->values); + $this->database->notify($this->cache_name); } } diff --git a/core/database.php b/core/database.php index e83b08e7..78f8cf80 100644 --- a/core/database.php +++ b/core/database.php @@ -1,13 +1,17 @@ db = new PDO($this->dsn); $this->connect_engine(); - $this->engine->init($this->db); + $this->get_engine()->init($this->db); $this->begin_transaction(); } @@ -54,11 +59,11 @@ class Database throw new SCoreException("Can't figure out database engine"); } - if ($db_proto === DatabaseDriver::MYSQL) { + if ($db_proto === DatabaseDriverID::MYSQL->value) { $this->engine = new MySQL(); - } elseif ($db_proto === DatabaseDriver::PGSQL) { + } elseif ($db_proto === DatabaseDriverID::PGSQL->value) { $this->engine = new PostgreSQL(); - } elseif ($db_proto === DatabaseDriver::SQLITE) { + } elseif ($db_proto === DatabaseDriverID::SQLITE->value) { $this->engine = new SQLite(); } else { die_nicely( @@ -98,47 +103,53 @@ class Database } } - public function scoreql_to_sql(string $input): string + private function get_engine(): DBEngine { if (is_null($this->engine)) { $this->connect_engine(); } - return $this->engine->scoreql_to_sql($input); + return $this->engine; } - public function get_driver_name(): string + public function scoreql_to_sql(string $input): string { - if (is_null($this->engine)) { - $this->connect_engine(); - } - return $this->engine->name; + return $this->get_engine()->scoreql_to_sql($input); + } + + public function get_driver_id(): DatabaseDriverID + { + return $this->get_engine()->id; } public function get_version(): string { - return $this->engine->get_version($this->db); + return $this->get_engine()->get_version($this->db); } private function count_time(string $method, float $start, string $query, ?array $args): void { global $_tracer, $tracer_enabled; - $dur = microtime(true) - $start; + $dur = ftime() - $start; + // trim whitespace + $query = preg_replace('/[\n\t ]/m', ' ', $query); + $query = preg_replace('/ +/m', ' ', $query); + $query = trim($query); if ($tracer_enabled) { - $query = trim(preg_replace('/^[\t ]+/m', '', $query)); // trim leading whitespace $_tracer->complete($start * 1000000, $dur * 1000000, "DB Query", ["query"=>$query, "args"=>$args, "method"=>$method]); } + $this->queries[] = $query; $this->query_count++; $this->dbtime += $dur; } public function set_timeout(?int $time): void { - $this->engine->set_timeout($this->db, $time); + $this->get_engine()->set_timeout($this->db, $time); } public function notify(string $channel, ?string $data=null): void { - $this->engine->notify($this->db, $channel, $data); + $this->get_engine()->notify($this->db, $channel, $data); } public function execute(string $query, array $args = []): PDOStatement @@ -147,12 +158,17 @@ class Database if (is_null($this->db)) { $this->connect_db(); } - return $this->db->execute( + $ret = $this->db->execute( "-- " . str_replace("%2F", "/", urlencode($_GET['q'] ?? '')). "\n" . $query, $args ); - } catch (PDOException $pdoe) { + if ($ret === false) { + throw new SCoreException("Query failed", $query); + } + /** @noinspection PhpIncompatibleReturnTypeInspection */ + return $ret; + } catch (\PDOException $pdoe) { throw new SCoreException($pdoe->getMessage(), $query); } } @@ -162,7 +178,7 @@ class Database */ public function get_all(string $query, array $args = []): array { - $_start = microtime(true); + $_start = ftime(); $data = $this->execute($query, $args)->fetchAll(); $this->count_time("get_all", $_start, $query, $args); return $data; @@ -173,7 +189,7 @@ class Database */ public function get_all_iterable(string $query, array $args = []): PDOStatement { - $_start = microtime(true); + $_start = ftime(); $data = $this->execute($query, $args); $this->count_time("get_all_iterable", $_start, $query, $args); return $data; @@ -184,7 +200,7 @@ class Database */ public function get_row(string $query, array $args = []): ?array { - $_start = microtime(true); + $_start = ftime(); $row = $this->execute($query, $args)->fetch(); $this->count_time("get_row", $_start, $query, $args); return $row ? $row : null; @@ -195,7 +211,7 @@ class Database */ public function get_col(string $query, array $args = []): array { - $_start = microtime(true); + $_start = ftime(); $res = $this->execute($query, $args)->fetchAll(PDO::FETCH_COLUMN); $this->count_time("get_col", $_start, $query, $args); return $res; @@ -204,9 +220,9 @@ class Database /** * Execute an SQL query and return the first column of each row as a single iterable object. */ - public function get_col_iterable(string $query, array $args = []): Generator + public function get_col_iterable(string $query, array $args = []): \Generator { - $_start = microtime(true); + $_start = ftime(); $stmt = $this->execute($query, $args); $this->count_time("get_col_iterable", $_start, $query, $args); foreach ($stmt as $row) { @@ -219,7 +235,7 @@ class Database */ public function get_pairs(string $query, array $args = []): array { - $_start = microtime(true); + $_start = ftime(); $res = $this->execute($query, $args)->fetchAll(PDO::FETCH_KEY_PAIR); $this->count_time("get_pairs", $_start, $query, $args); return $res; @@ -229,9 +245,9 @@ class Database /** * Execute an SQL query and return the the first column => the second column as an iterable object. */ - public function get_pairs_iterable(string $query, array $args = []): Generator + public function get_pairs_iterable(string $query, array $args = []): \Generator { - $_start = microtime(true); + $_start = ftime(); $stmt = $this->execute($query, $args); $this->count_time("get_pairs_iterable", $_start, $query, $args); foreach ($stmt as $row) { @@ -244,7 +260,7 @@ class Database */ public function get_one(string $query, array $args = []) { - $_start = microtime(true); + $_start = ftime(); $row = $this->execute($query, $args)->fetch(); $this->count_time("get_one", $_start, $query, $args); return $row ? $row[0] : null; @@ -255,7 +271,7 @@ class Database */ public function exists(string $query, array $args = []): bool { - $_start = microtime(true); + $_start = ftime(); $row = $this->execute($query, $args)->fetch(); $this->count_time("exists", $_start, $query, $args); if ($row==null) { @@ -269,7 +285,7 @@ class Database */ public function get_last_insert_id(string $seq): int { - if ($this->engine->name == DatabaseDriver::PGSQL) { + if ($this->get_engine()->id == DatabaseDriverID::PGSQL) { $id = $this->db->lastInsertId($seq); } else { $id = $this->db->lastInsertId(); @@ -287,7 +303,7 @@ class Database $this->connect_engine(); } $data = trim($data, ", \t\n\r\0\x0B"); // mysql doesn't like trailing commas - $this->execute($this->engine->create_table_sql($name, $data)); + $this->execute($this->get_engine()->create_table_sql($name, $data)); } /** @@ -301,32 +317,35 @@ class Database $this->connect_db(); } - if ($this->engine->name === DatabaseDriver::MYSQL) { + if ($this->get_engine()->id === DatabaseDriverID::MYSQL) { return count( $this->get_all("SHOW TABLES") ); - } elseif ($this->engine->name === DatabaseDriver::PGSQL) { + } elseif ($this->get_engine()->id === DatabaseDriverID::PGSQL) { return count( $this->get_all("SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'") ); - } elseif ($this->engine->name === DatabaseDriver::SQLITE) { + } elseif ($this->get_engine()->id === DatabaseDriverID::SQLITE) { return count( $this->get_all("SELECT name FROM sqlite_master WHERE type = 'table'") ); } else { - throw new SCoreException("Can't count tables for database type {$this->engine->name}"); + throw new SCoreException("Can't count tables for database type {$this->get_engine()->id}"); } } public function raw_db(): PDO { + if (is_null($this->db)) { + $this->connect_db(); + } return $this->db; } public function standardise_boolean(string $table, string $column, bool $include_postgres=false): void { - $d = $this->get_driver_name(); - if ($d == DatabaseDriver::MYSQL) { + $d = $this->get_driver_id(); + if ($d == DatabaseDriverID::MYSQL) { # In mysql, ENUM('Y', 'N') is secretly INTEGER where Y=1 and N=2. # BOOLEAN is secretly TINYINT where true=1 and false=0. # So we can cast directly from ENUM to BOOLEAN which gives us a @@ -335,16 +354,16 @@ class Database $this->execute("ALTER TABLE $table MODIFY COLUMN $column BOOLEAN;"); $this->execute("UPDATE $table SET $column=0 WHERE $column=2;"); } - if ($d == DatabaseDriver::SQLITE) { + if ($d == DatabaseDriverID::SQLITE) { # SQLite doesn't care about column types at all, everything is # text, so we can in-place replace a char with a bool $this->execute("UPDATE $table SET $column = ($column IN ('Y', 1))"); } - if ($d == DatabaseDriver::PGSQL && $include_postgres) { - $this->execute("ALTER TABLE $table ADD COLUMN ${column}_b BOOLEAN DEFAULT FALSE NOT NULL"); - $this->execute("UPDATE $table SET ${column}_b = ($column = 'Y')"); + if ($d == DatabaseDriverID::PGSQL && $include_postgres) { + $this->execute("ALTER TABLE $table ADD COLUMN {$column}_b BOOLEAN DEFAULT FALSE NOT NULL"); + $this->execute("UPDATE $table SET {$column}_b = ($column = 'Y')"); $this->execute("ALTER TABLE $table DROP COLUMN $column"); - $this->execute("ALTER TABLE $table RENAME COLUMN ${column}_b TO $column"); + $this->execute("ALTER TABLE $table RENAME COLUMN {$column}_b TO $column"); } } } diff --git a/core/dbengine.php b/core/dbengine.php index 22ea3cc0..bf32cd47 100644 --- a/core/dbengine.php +++ b/core/dbengine.php @@ -1,6 +1,11 @@ exec("PRAGMA foreign_keys = ON;"); - $db->sqliteCreateFunction('UNIX_TIMESTAMP', '_unix_timestamp', 1); - $db->sqliteCreateFunction('now', '_now', 0); - $db->sqliteCreateFunction('floor', '_floor', 1); - $db->sqliteCreateFunction('log', '_log'); - $db->sqliteCreateFunction('isnull', '_isnull', 1); - $db->sqliteCreateFunction('md5', '_md5', 1); - $db->sqliteCreateFunction('concat', '_concat', 2); - $db->sqliteCreateFunction('lower', '_lower', 1); - $db->sqliteCreateFunction('rand', '_rand', 0); - $db->sqliteCreateFunction('ln', '_ln', 1); + $db->sqliteCreateFunction('UNIX_TIMESTAMP', 'Shimmie2\_unix_timestamp', 1); + $db->sqliteCreateFunction('now', 'Shimmie2\_now', 0); + $db->sqliteCreateFunction('floor', 'Shimmie2\_floor', 1); + $db->sqliteCreateFunction('log', 'Shimmie2\_log'); + $db->sqliteCreateFunction('isnull', 'Shimmie2\_isnull', 1); + $db->sqliteCreateFunction('md5', 'Shimmie2\_md5', 1); + $db->sqliteCreateFunction('concat', 'Shimmie2\_concat', 2); + $db->sqliteCreateFunction('lower', 'Shimmie2\_lower', 1); + $db->sqliteCreateFunction('rand', 'Shimmie2\_rand', 0); + $db->sqliteCreateFunction('ln', 'Shimmie2\_ln', 1); } public function scoreql_to_sql(string $data): string diff --git a/core/event.php b/core/event.php index 355ac504..db6798ab 100644 --- a/core/event.php +++ b/core/event.php @@ -1,6 +1,9 @@ theme = $this->get_theme_object($class); $this->info = ExtensionInfo::get_for_extension_class($class); - if ($this->info===null) { - throw new ScoreException("Info class not found for extension $class"); - } $this->key = $this->info->key; } @@ -37,8 +37,9 @@ abstract class Extension */ private function get_theme_object(string $base): ?Themelet { - $custom = 'Custom'.$base.'Theme'; - $normal = $base.'Theme'; + $base = str_replace("Shimmie2\\", "", $base); + $custom = "Shimmie2\Custom{$base}Theme"; + $normal = "Shimmie2\\{$base}Theme"; if (class_exists($custom)) { return new $custom(); @@ -61,9 +62,11 @@ abstract class Extension public static function determine_enabled_extensions(): void { self::$enabled_extensions = []; + $extras = defined("EXTRA_EXTS") ? explode(",", EXTRA_EXTS) : []; + foreach (array_merge( ExtensionInfo::get_core_extensions(), - explode(",", EXTRA_EXTS) + $extras ) as $key) { $ext = ExtensionInfo::get_by_key($key); if ($ext===null || !$ext->is_supported()) { @@ -107,6 +110,13 @@ abstract class Extension } } +enum ExtensionVisibility +{ + case DEFAULT; + case ADMIN; + case HIDDEN; +} + abstract class ExtensionInfo { // Every credit you get costs us RAM. It stops now. @@ -119,11 +129,6 @@ abstract class ExtensionInfo public const LICENSE_MIT = "MIT"; public const LICENSE_WTFPL = "WTFPL"; - public const VISIBLE_DEFAULT = "default"; - public const VISIBLE_ADMIN = "admin"; - public const VISIBLE_HIDDEN = "hidden"; - private const VALID_VISIBILITY = [self::VISIBLE_DEFAULT, self::VISIBLE_ADMIN, self::VISIBLE_HIDDEN]; - public string $key; public bool $core = false; @@ -135,12 +140,12 @@ abstract class ExtensionInfo public array $authors = []; public array $dependencies = []; public array $conflicts = []; - public string $visibility = self::VISIBLE_DEFAULT; + public ExtensionVisibility $visibility = ExtensionVisibility::DEFAULT; public ?string $link = null; public ?string $version = null; public ?string $documentation = null; - /** @var string[] which DBs this ext supports (blank for 'all') */ + /** @var DatabaseDriverID[] which DBs this ext supports (blank for 'all') */ public array $db_support = []; private ?bool $supported = null; private ?string $support_info = null; @@ -169,7 +174,6 @@ abstract class ExtensionInfo { assert(!empty($this->key), "key field is required"); assert(!empty($this->name), "name field is required for extension $this->key"); - assert(empty($this->visibility) || in_array($this->visibility, self::VALID_VISIBILITY), "Invalid visibility for extension $this->key"); assert(is_array($this->db_support), "db_support has to be an array for extension $this->key"); assert(is_array($this->authors), "authors has to be an array for extension $this->key"); assert(is_array($this->dependencies), "dependencies has to be an array for extension $this->key"); @@ -184,7 +188,7 @@ abstract class ExtensionInfo { global $database; $this->support_info = ""; - if (!empty($this->db_support) && !in_array($database->get_driver_name(), $this->db_support)) { + if (!empty($this->db_support) && !in_array($database->get_driver_id(), $this->db_support)) { $this->support_info .= "Database not supported. "; } if (!empty($this->conflicts)) { @@ -223,23 +227,24 @@ abstract class ExtensionInfo } } - public static function get_for_extension_class(string $base): ?ExtensionInfo + public static function get_for_extension_class(string $base): ExtensionInfo { - $normal = $base.'Info'; + $normal = "{$base}Info"; if (array_key_exists($normal, self::$all_info_by_class)) { return self::$all_info_by_class[$normal]; } else { - return null; + $infos = print_r(array_keys(self::$all_info_by_class), true); + throw new SCoreException("$normal not found in {$infos}"); } } public static function load_all_extension_info() { - foreach (get_subclasses_of("ExtensionInfo") as $class) { + foreach (get_subclasses_of("Shimmie2\ExtensionInfo") as $class) { $extension_info = new $class(); if (array_key_exists($extension_info->key, self::$all_info_by_key)) { - throw new ScoreException("Extension Info $class with key $extension_info->key has already been loaded"); + throw new SCoreException("Extension Info $class with key $extension_info->key has already been loaded"); } self::$all_info_by_key[$extension_info->key] = $extension_info; @@ -308,43 +313,20 @@ abstract class DataHandlerExtension extends Extension if (is_null($existing)) { throw new UploadException("Post to replace does not exist!"); } - if ($existing->hash === $event->metadata['hash']) { + if ($existing->hash === $event->hash) { throw new UploadException("The uploaded post is the same as the one to replace."); } // even more hax.. $event->metadata['tags'] = $existing->get_tag_list(); - $image = $this->create_image_from_data(warehouse_path(Image::IMAGE_DIR, $event->metadata['hash']), $event->metadata); - if (is_null($image)) { - throw new UploadException("Data handler failed to create post object from data"); - } - if (empty($image->get_mime())) { - throw new UploadException("Unable to determine MIME for ". $event->tmpname); - } - try { - send_event(new MediaCheckPropertiesEvent($image)); - } catch (MediaException $e) { - throw new UploadException("Unable to scan media properties: ".$e->getMessage()); - } + $image = $this->create_image_from_data(warehouse_path(Image::IMAGE_DIR, $event->hash), $event->metadata); send_event(new ImageReplaceEvent($event->replace_id, $image)); $_id = $event->replace_id; assert(!is_null($_id)); $event->image_id = $_id; } else { $image = $this->create_image_from_data(warehouse_path(Image::IMAGE_DIR, $event->hash), $event->metadata); - if (is_null($image)) { - throw new UploadException("Data handler failed to create post object from data"); - } - if (empty($image->get_mime())) { - throw new UploadException("Unable to determine MIME for ". $event->tmpname); - } - try { - send_event(new MediaCheckPropertiesEvent($image)); - } catch (MediaException $e) { - throw new UploadException("Unable to scan media properties: ".$e->getMessage()); - } - $iae = send_event(new ImageAdditionEvent($image)); $event->image_id = $iae->image->id; $event->merged = $iae->merged; @@ -358,7 +340,7 @@ abstract class DataHandlerExtension extends Extension // Locked Stuff. if (!empty($event->metadata['locked'])) { $locked = $event->metadata['locked']; - send_event(new LockSetEvent($image, !empty($locked))); + send_event(new LockSetEvent($image, $locked)); } } } elseif ($supported_mime && !$check_contents) { @@ -390,14 +372,14 @@ abstract class DataHandlerExtension extends Extension { global $page; if ($this->supported_mime($event->image->get_mime())) { - /** @noinspection PhpPossiblePolymorphicInvocationInspection */ + // @phpstan-ignore-next-line $this->theme->display_image($page, $event->image); } } public function onMediaCheckProperties(MediaCheckPropertiesEvent $event) { - if ($this->supported_mime($event->mime)) { + if ($this->supported_mime($event->image->get_mime())) { $this->media_check_properties($event); } } @@ -406,19 +388,23 @@ abstract class DataHandlerExtension extends Extension { $image = new Image(); - $image->filesize = $metadata['size']; - $image->hash = $metadata['hash']; + assert(is_readable($filename)); + $image->filesize = filesize($filename); + $image->hash = md5_file($filename); $image->filename = (($pos = strpos($metadata['filename'], '?')) !== false) ? substr($metadata['filename'], 0, $pos) : $metadata['filename']; - - if (array_key_exists("extension", $metadata)) { - $image->set_mime(MimeType::get_for_file($filename, $metadata["extension"])); - } else { - $image->set_mime(MimeType::get_for_file($filename)); - } - + $image->set_mime(MimeType::get_for_file($filename, get_file_ext($metadata["filename"]) ?? null)); $image->tag_array = is_array($metadata['tags']) ? $metadata['tags'] : Tag::explode($metadata['tags']); $image->source = $metadata['source']; + if (empty($image->get_mime())) { + throw new UploadException("Unable to determine MIME for $filename"); + } + try { + send_event(new MediaCheckPropertiesEvent($image)); + } catch (MediaException $e) { + throw new UploadException("Unable to scan media properties $filename / $image->filename / $image->hash: ".$e->getMessage()); + } + return $image; } @@ -434,13 +420,13 @@ abstract class DataHandlerExtension extends Extension public static function get_all_supported_mimes(): array { $arr = []; - foreach (get_subclasses_of("DataHandlerExtension") as $handler) { + foreach (get_subclasses_of("Shimmie2\DataHandlerExtension") as $handler) { $handler = (new $handler()); $arr = array_merge($arr, $handler->SUPPORTED_MIME); } // Not sure how to handle this otherwise, don't want to set up a whole other event for this one class - if (class_exists("TranscodeImage")) { + if (class_exists("Shimmie2\TranscodeImage")) { $arr = array_merge($arr, TranscodeImage::get_enabled_mimes()); } diff --git a/core/imageboard/event.php b/core/imageboard/event.php index 70dc0afe..1580f848 100644 --- a/core/imageboard/event.php +++ b/core/imageboard/event.php @@ -2,13 +2,14 @@ declare(strict_types=1); +namespace Shimmie2; + /** * An image is being added to the database. */ class ImageAdditionEvent extends Event { public User $user; - public Image $image; public bool $merged = false; /** @@ -16,10 +17,10 @@ class ImageAdditionEvent extends Event * information. Also calls TagSetEvent to set the tags for * this new image. */ - public function __construct(Image $image) - { + public function __construct( + public Image $image, + ) { parent::__construct(); - $this->image = $image; } } @@ -32,20 +33,17 @@ class ImageAdditionException extends SCoreException */ class ImageDeletionEvent extends Event { - public Image $image; - public bool $force = false; - /** * Deletes an image. * * Used by things like tags and comments handlers to * clean out related rows in their tables. */ - public function __construct(Image $image, bool $force = false) - { + public function __construct( + public Image $image, + public bool $force = false, + ) { parent::__construct(); - $this->image = $image; - $this->force = $force; } } @@ -54,9 +52,6 @@ class ImageDeletionEvent extends Event */ class ImageReplaceEvent extends Event { - public int $id; - public Image $image; - /** * Replaces an image. * @@ -64,11 +59,11 @@ class ImageReplaceEvent extends Event * file, leaving the tags and such unchanged. Also removes * the old image file and thumbnail from the disk. */ - public function __construct(int $id, Image $image) - { + public function __construct( + public int $id, + public Image $image + ) { parent::__construct(); - $this->id = $id; - $this->image = $image; } } @@ -81,20 +76,17 @@ class ImageReplaceException extends SCoreException */ class ThumbnailGenerationEvent extends Event { - public string $hash; - public string $mime; - public bool $force; public bool $generated; /** * Request a thumbnail be made for an image object */ - public function __construct(string $hash, string $mime, bool $force=false) - { + public function __construct( + public string $hash, + public string $mime, + public bool $force=false + ) { parent::__construct(); - $this->hash = $hash; - $this->mime = $mime; - $this->force = $force; $this->generated = false; } } diff --git a/core/imageboard/image.php b/core/imageboard/image.php index f2fb0961..f40590a6 100644 --- a/core/imageboard/image.php +++ b/core/imageboard/image.php @@ -1,6 +1,13 @@ id; + } + #[Field(name: "id")] + public function graphql_guid(): string + { + return "post:{$this->id}"; + } + + #[Query(name: "post")] + public static function by_id(int $post_id): ?Image { global $database; - $row = $database->get_row("SELECT * FROM images WHERE images.id=:id", ["id"=>$id]); + if ($post_id > 2**32) { + // for some reason bots query huge numbers and pollute the DB error logs... + return null; + } + $row = $database->get_row("SELECT * FROM images WHERE images.id=:id", ["id"=>$post_id]); return ($row ? new Image($row) : null); } @@ -132,12 +166,13 @@ class Image /** * Search for an array of images * - * #param string[] $tags - * #return Image[] + * @param String[] $tags + * @return Image[] */ - public static function find_images(int $start, ?int $limit = null, array $tags=[]): array + #[Query(name: "posts", type: "[Post!]!", args: ["tags" => "[string!]"])] + public static function find_images(?int $offset = 0, ?int $limit = null, array $tags=[]): array { - $result = self::find_images_internal($start, $limit, $tags); + $result = self::find_images_internal($offset, $limit, $tags); $images = []; foreach ($result as $row) { @@ -149,7 +184,7 @@ class Image /** * Search for an array of images, returning a iterable object of Image */ - public static function find_images_iterable(int $start = 0, ?int $limit = null, array $tags=[]): Generator + public static function find_images_iterable(int $start = 0, ?int $limit = null, array $tags=[]): \Generator { $result = self::find_images_internal($start, $limit, $tags); foreach ($result as $row) { @@ -165,7 +200,7 @@ class Image { global $cache, $database; $total = $cache->get("image-count"); - if (!$total) { + if (is_null($total)) { $total = (int)$database->get_one("SELECT COUNT(*) FROM images"); $cache->set("image-count", $total, 600); } @@ -184,7 +219,7 @@ class Image /** * Count the number of image results for a given search * - * #param string[] $tags + * @param String[] $tags */ public static function count_images(array $tags=[]): int { @@ -207,7 +242,7 @@ class Image // implode(tags) can be too long for memcache... $cache_key = "image-count:" . md5(Tag::implode($tags)); $total = $cache->get($cache_key); - if (!$total) { + if (is_null($total)) { if (Extension::is_enabled(RatingsInfo::KEY)) { $tags[] = "rating:*"; } @@ -229,7 +264,7 @@ class Image /** * Count the number of pages for a given search * - * #param string[] $tags + * @param String[] $tags */ public static function count_pages(array $tags=[]): int { @@ -248,7 +283,6 @@ class Image * Turn a bunch of strings into a bunch of TagCondition * and ImgCondition objects */ - /** @var $stpe SearchTermParseEvent */ $stpe = send_event(new SearchTermParseEvent($stpen++, null, $terms)); if ($stpe->order) { $order = $stpe->order; @@ -268,7 +302,6 @@ class Image continue; } - /** @var $stpe SearchTermParseEvent */ $stpe = send_event(new SearchTermParseEvent($stpen++, $term, $terms)); if ($stpe->order) { $order = $stpe->order; @@ -296,7 +329,7 @@ class Image * Rather than simply $this_id + 1, one must take into account * deleted images and search queries * - * #param string[] $tags + * @param String[] $tags */ public function get_next(array $tags=[], bool $next=true): ?Image { @@ -332,7 +365,7 @@ class Image /** * The reverse of get_next * - * #param string[] $tags + * @param String[] $tags */ public function get_prev(array $tags=[]): ?Image { @@ -342,6 +375,7 @@ class Image /** * Find the User who owns this Image */ + #[Field(name: "owner")] public function get_owner(): User { return User::by_id($this->owner_id); @@ -369,7 +403,7 @@ class Image $cut_name = substr($this->filename, 0, 255); if (is_null($this->posted) || $this->posted == "") { - $this->posted = date('c', time()); + $this->posted = date('Y-m-d H:i:s', time()); } if (is_null($this->id)) { @@ -440,8 +474,9 @@ class Image /** * Get this image's tags as an array. * - * #return string[] + * @return String[] */ + #[Field(name: "tags", type: "[string!]!")] public function get_tag_array(): array { global $database; @@ -469,6 +504,7 @@ class Image /** * Get the URL for the full size image */ + #[Field(name: "image_link")] public function get_image_link(): string { return $this->get_link(ImageConfig::ILINK, '_images/$hash/$id%20-%20$tags.$ext', 'image/$id.$ext'); @@ -477,16 +513,16 @@ class Image /** * Get the nicely formatted version of the file name */ + #[Field(name: "nice_name")] public function get_nice_image_name(): string { - $plte = new ParseLinkTemplateEvent('$id - $tags.$ext', $this); - send_event($plte); - return $plte->text; + return send_event(new ParseLinkTemplateEvent('$id - $tags.$ext', $this))->text; } /** * Get the URL for the thumbnail */ + #[Field(name: "thumb_link")] public function get_thumb_link(): string { global $config; @@ -521,24 +557,22 @@ class Image * Get the tooltip for this image, formatted according to the * configured template. */ + #[Field(name: "tooltip")] public function get_tooltip(): string { global $config; - $plte = new ParseLinkTemplateEvent($config->get_string(ImageConfig::TIP), $this); - send_event($plte); - return $plte->text; + return send_event(new ParseLinkTemplateEvent($config->get_string(ImageConfig::TIP), $this))->text; } /** * Get the info for this image, formatted according to the * configured template. */ + #[Field(name: "info")] public function get_info(): string { global $config; - $plte = new ParseLinkTemplateEvent($config->get_string(ImageConfig::INFO), $this); - send_event($plte); - return $plte->text; + return send_event(new ParseLinkTemplateEvent($config->get_string(ImageConfig::INFO), $this))->text; } @@ -561,6 +595,7 @@ class Image /** * Get the original filename. */ + #[Field(name: "filename")] public function get_filename(): string { return $this->filename; @@ -569,6 +604,7 @@ class Image /** * Get the image's extension. */ + #[Field(name: "ext")] public function get_ext(): string { return $this->ext; @@ -577,6 +613,7 @@ class Image /** * Get the image's mime type. */ + #[Field(name: "mime")] public function get_mime(): ?string { if ($this->mime===MimeType::WEBP&&$this->lossless) { @@ -650,7 +687,7 @@ class Image public function delete_tags_from_image(): void { global $database; - if ($database->get_driver_name() == DatabaseDriver::MYSQL) { + if ($database->get_driver_id() == DatabaseDriverID::MYSQL) { //mysql < 5.6 has terrible subquery optimization, using EXISTS / JOIN fixes this $database->execute( " @@ -743,7 +780,7 @@ class Image VALUES(:iid, :tid) ", ["iid"=>$this->id, "tid"=>$id]); - array_push($written_tags, $id); + $written_tags[] = $id; } $database->execute( " @@ -796,14 +833,14 @@ class Image { global $database; $sq = "SELECT id FROM tags WHERE LOWER(tag) LIKE LOWER(:tag)"; - if ($database->get_driver_name() === DatabaseDriver::SQLITE) { + if ($database->get_driver_id() === DatabaseDriverID::SQLITE) { $sq .= "ESCAPE '\\'"; } return $database->get_col($sq, ["tag" => Tag::sqlify($tag)]); } /** - * #param string[] $terms + * @param String[] $terms */ private static function build_search_querylet( array $terms, diff --git a/core/imageboard/misc.php b/core/imageboard/misc.php index 0b871a78..e9944606 100644 --- a/core/imageboard/misc.php +++ b/core/imageboard/misc.php @@ -1,6 +1,9 @@ pathinfo($filename, PATHINFO_BASENAME), + 'tags' => Tag::explode($tags), + 'source' => $source, + ])); +} - $pathinfo = pathinfo($filename); - $metadata = []; - $metadata['filename'] = $pathinfo['basename']; - if (array_key_exists('extension', $pathinfo)) { - $metadata['extension'] = $pathinfo['extension']; - } - - $metadata['tags'] = Tag::explode($tags); - $metadata['source'] = null; - - $due = new DataUploadEvent($tmpname, $metadata); - send_event($due); - - return $due->image_id; +function get_file_ext(string $filename): ?string +{ + return pathinfo($filename)['extension'] ?? null; } /** diff --git a/core/imageboard/search.php b/core/imageboard/search.php index 10df2ec0..11ac9b03 100644 --- a/core/imageboard/search.php +++ b/core/imageboard/search.php @@ -1,15 +1,15 @@ sql = $sql; - $this->variables = $variables; + public function __construct( + public string $sql, + public array $variables=[], + ) { } public function append(Querylet $querylet): void @@ -31,24 +31,18 @@ class Querylet class TagCondition { - public string $tag; - public bool $positive; - - public function __construct(string $tag, bool $positive) - { - $this->tag = $tag; - $this->positive = $positive; + public function __construct( + public string $tag, + public bool $positive, + ) { } } class ImgCondition { - public Querylet $qlet; - public bool $positive; - - public function __construct(Querylet $qlet, bool $positive) - { - $this->qlet = $qlet; - $this->positive = $positive; + public function __construct( + public Querylet $qlet, + public bool $positive, + ) { } } diff --git a/core/imageboard/tag.php b/core/imageboard/tag.php index 3e79e26c..c5997586 100644 --- a/core/imageboard/tag.php +++ b/core/imageboard/tag.php @@ -1,6 +1,85 @@ tag = $tag; + $this->uses = $uses; + } + + /** + * @return TagUsage[] + */ + #[Query(name: "tags", type: '[TagUsage!]!')] + public static function tags(string $search, int $limit=10): array + { + global $cache, $database; + + if (!$search) { + return []; + } + + $search = strtolower($search); + if ( + $search == '' || + $search[0] == '_' || + $search[0] == '%' || + strlen($search) > 32 + ) { + return []; + } + + $cache_key = "tagusage-$search"; + $limitSQL = ""; + $search = str_replace('_', '\_', $search); + $search = str_replace('%', '\%', $search); + $SQLarr = ["search"=>"$search%"]; #, "cat_search"=>"%:$search%"]; + if ($limit !== 0) { + $limitSQL = "LIMIT :limit"; + $SQLarr['limit'] = $limit; + $cache_key .= "-" . $limit; + } + + $res = $cache->get($cache_key); + if (is_null($res)) { + $res = $database->get_pairs( + " + SELECT tag, count + FROM tags + WHERE LOWER(tag) LIKE LOWER(:search) + -- OR LOWER(tag) LIKE LOWER(:cat_search) + AND count > 0 + ORDER BY count DESC + $limitSQL + ", + $SQLarr + ); + $cache->set($cache_key, $res, 600); + } + + $counts = []; + foreach ($res as $k => $v) { + $counts[] = new TagUsage($k, $v); + } + return $counts; + } +} + /** * Class Tag * @@ -90,7 +169,7 @@ class Tag public static function sanitize(string $tag): string { $tag = preg_replace("/\s/", "", $tag); # whitespace - $tag = preg_replace('/\x20[\x0e\x0f]/', '', $tag); # unicode RTL + $tag = preg_replace('/\x20[\x0e\x0f]/', '', $tag); # unicode RTL $tag = preg_replace("/\.+/", ".", $tag); # strings of dots? $tag = preg_replace("/^(\.+[\/\\\\])+/", "", $tag); # trailing slashes? $tag = trim($tag, ", \t\n\r\0\x0B"); @@ -100,7 +179,7 @@ class Tag } // hard-code one bad case... if (mb_strlen($tag, 'UTF-8') > 255) { - throw new ScoreException("The tag below is longer than 255 characters, please use a shorter tag.\n$tag\n"); + throw new SCoreException("The tag below is longer than 255 characters, please use a shorter tag.\n$tag\n"); } return $tag; } @@ -113,15 +192,10 @@ class Tag $tags1 = array_map("strtolower", $tags1); $tags2 = array_map("strtolower", $tags2); - natcasesort($tags1); - natcasesort($tags2); + sort($tags1); + sort($tags2); - for ($i = 0; $i < count($tags1); $i++) { - if ($tags1[$i]!==$tags2[$i]) { - return false; - } - } - return true; + return $tags1 == $tags2; } public static function get_diff_tags(array $source, array $remove): array @@ -144,7 +218,7 @@ class Tag foreach ($tags as $tag) { try { $tag = Tag::sanitize($tag); - } catch (Exception $e) { + } catch (\Exception $e) { $page->flash($e->getMessage()); continue; } @@ -159,7 +233,7 @@ class Tag public static function sqlify(string $term): string { global $database; - if ($database->get_driver_name() === DatabaseDriver::SQLITE) { + if ($database->get_driver_id() === DatabaseDriverID::SQLITE) { $term = str_replace('\\', '\\\\', $term); } $term = str_replace('_', '\_', $term); diff --git a/core/install.php b/core/install.php index 106aa537..b18c14f8 100644 --- a/core/install.php +++ b/core/install.php @@ -1,4 +1,9 @@ value) { /** @noinspection PhpUnhandledExceptionInspection */ $id = bin2hex(random_bytes(5)); $dsn = "sqlite:data/shimmie.{$id}.sqlite"; @@ -97,11 +102,11 @@ function ask_questions() "; } - $drivers = PDO::getAvailableDrivers(); + $drivers = \PDO::getAvailableDrivers(); if ( - !in_array(DatabaseDriver::MYSQL, $drivers) && - !in_array(DatabaseDriver::PGSQL, $drivers) && - !in_array(DatabaseDriver::SQLITE, $drivers) + !in_array(DatabaseDriverID::MYSQL->value, $drivers) && + !in_array(DatabaseDriverID::PGSQL->value, $drivers) && + !in_array(DatabaseDriverID::SQLITE->value, $drivers) ) { $errors[] = " No database connection library could be found; shimmie needs @@ -109,9 +114,9 @@ function ask_questions() "; } - $db_m = in_array(DatabaseDriver::MYSQL, $drivers) ? '' : ""; - $db_p = in_array(DatabaseDriver::PGSQL, $drivers) ? '' : ""; - $db_s = in_array(DatabaseDriver::SQLITE, $drivers) ? '' : ""; + $db_m = in_array(DatabaseDriverID::MYSQL->value, $drivers) ? '' : ""; + $db_p = in_array(DatabaseDriverID::PGSQL->value, $drivers) ? '' : ""; + $db_s = in_array(DatabaseDriverID::SQLITE->value, $drivers) ? '' : ""; $warn_msg = $warnings ? "
", $warnings) : ""; $err_msg = $errors ? "
", $errors) : ""; @@ -287,7 +292,7 @@ function create_tables(Database $db) if ($db->is_transaction_open()) { $db->commit(); } - } catch (PDOException $e) { + } catch (\PDOException $e) { throw new InstallerException( "PDO Error:", "
An error occurred while trying to create the database tables necessary for Shimmie.
diff --git a/core/logging.php b/core/logging.php index 50db58db..7b5c3694 100644 --- a/core/logging.php +++ b/core/logging.php @@ -1,6 +1,9 @@ isAbstract() && is_subclass_of($class, $parent)) { $result[] = $class; } @@ -333,38 +336,17 @@ function get_base_href(): string function unparse_url(array $parsed_url): string { $scheme = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : ''; - $host = isset($parsed_url['host']) ? $parsed_url['host'] : ''; + $host = $parsed_url['host'] ?? ''; $port = isset($parsed_url['port']) ? ':' . $parsed_url['port'] : ''; - $user = isset($parsed_url['user']) ? $parsed_url['user'] : ''; + $user = $parsed_url['user'] ?? ''; $pass = isset($parsed_url['pass']) ? ':' . $parsed_url['pass'] : ''; $pass = ($user || $pass) ? "$pass@" : ''; - $path = isset($parsed_url['path']) ? $parsed_url['path'] : ''; + $path = $parsed_url['path'] ?? ''; $query = !empty($parsed_url['query']) ? '?' . $parsed_url['query'] : ''; $fragment = !empty($parsed_url['fragment']) ? '#' . $parsed_url['fragment'] : ''; return "$scheme$user$pass$host$port$path$query$fragment"; } -# finally in the core library starting from php8 -if (!function_exists('str_starts_with')) { - function str_starts_with(string $haystack, string $needle): bool - { - return strncmp($haystack, $needle, strlen($needle)) === 0; - } -} - -if (!function_exists('str_ends_with')) { - function str_ends_with(string $haystack, string $needle): bool - { - return $needle === '' || $needle === substr($haystack, - strlen($needle)); - } -} - -if (!function_exists('str_contains')) { - function str_contains(string $haystack, string $needle): bool - { - return '' === $needle || false !== strpos($haystack, $needle); - } -} /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * Input / Output Sanitising * @@ -517,19 +499,24 @@ function truncate(string $string, int $limit, string $break=" ", string $pad=".. function parse_shorthand_int(string $limit): int { if (preg_match('/^([\d\.]+)([tgmk])?b?$/i', (string)$limit, $m)) { - $value = $m[1]; + $value = (float)$m[1]; if (isset($m[2])) { switch (strtolower($m[2])) { /** @noinspection PhpMissingBreakStatementInspection */ - case 't': $value *= 1024; // fall through - /** @noinspection PhpMissingBreakStatementInspection */ - // no break - case 'g': $value *= 1024; // fall through - /** @noinspection PhpMissingBreakStatementInspection */ - // no break - case 'm': $value *= 1024; // fall through - // no break - case 'k': $value *= 1024; break; + case 't': + $value *= 1024; // fall through + /** @noinspection PhpMissingBreakStatementInspection */ + // no break + case 'g': + $value *= 1024; // fall through + /** @noinspection PhpMissingBreakStatementInspection */ + // no break + case 'm': + $value *= 1024; // fall through + // no break + case 'k': + $value *= 1024; + break; default: $value = -1; } } @@ -787,7 +774,7 @@ function join_path(string ...$paths): string /** * Perform callback on each item returned by an iterator. */ -function iterator_map(callable $callback, iterator $iter): Generator +function iterator_map(callable $callback, \iterator $iter): \Generator { foreach ($iter as $i) { yield call_user_func($callback, $i); @@ -797,7 +784,7 @@ function iterator_map(callable $callback, iterator $iter): Generator /** * Perform callback on each item returned by an iterator and combine the result into an array. */ -function iterator_map_to_array(callable $callback, iterator $iter): array +function iterator_map_to_array(callable $callback, \iterator $iter): array { return iterator_to_array(iterator_map($callback, $iter)); } @@ -806,7 +793,7 @@ function stringer($s): string { if (is_array($s)) { if (isset($s[0])) { - return "[" . implode(", ", array_map("stringer", $s)) . "]"; + return "[" . implode(", ", array_map("Shimmie2\stringer", $s)) . "]"; } else { $pairs = []; foreach ($s as $k=>$v) { @@ -815,8 +802,20 @@ function stringer($s): string return "[" . implode(", ", $pairs) . "]"; } } + if (is_null($s)) { + return "null"; + } if (is_string($s)) { return "\"$s\""; // FIXME: handle escaping quotes } - return (string)$s; + if (is_numeric($s)) { + return "$s"; + } + if (is_bool($s)) { + return $s ? "true" : "false"; + } + if (method_exists($s, "__toString")) { + return $s->__toString(); + } + return "Hash: $hash" : "";
@@ -635,7 +645,7 @@ function _fatal_error(Exception $e): void
foreach ($t as $n => $f) {
$c = $f['class'] ?? '';
$t = $f['type'] ?? '';
- $a = implode(", ", array_map("stringer", $f['args']));
+ $a = implode(", ", array_map("Shimmie2\stringer", $f['args']));
print("$n: {$f['file']}({$f['line']}): {$c}{$t}{$f['function']}({$a})\n");
}
@@ -674,12 +684,18 @@ function _get_user(): User
{
global $config, $page;
$my_user = null;
- if ($page->get_cookie("user") && $page->get_cookie("session")) {
- $tmp_user = User::by_session($page->get_cookie("user"), $page->get_cookie("session"));
- if (!is_null($tmp_user)) {
- $my_user = $tmp_user;
+ if (isset($_SERVER['HTTP_AUTHORIZATION'])) {
+ $parts = explode(" ", $_SERVER['HTTP_AUTHORIZATION'], 2);
+ if (count($parts) == 2 && $parts[0] == "Bearer") {
+ $parts = explode(":", $parts[1], 2);
+ if (count($parts) == 2) {
+ $my_user = User::by_session($parts[0], $parts[1]);
+ }
}
}
+ if ($page->get_cookie("user") && $page->get_cookie("session")) {
+ $my_user = User::by_session($page->get_cookie("user"), $page->get_cookie("session"));
+ }
if (is_null($my_user)) {
$my_user = User::by_id($config->get_int("anon_id", 0));
}
diff --git a/ext/admin/info.php b/ext/admin/info.php
index 54751718..806d37d9 100644
--- a/ext/admin/info.php
+++ b/ext/admin/info.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class AdminPageInfo extends ExtensionInfo
{
public const KEY = "admin";
@@ -13,5 +15,5 @@ class AdminPageInfo extends ExtensionInfo
public string $license = self::LICENSE_GPLV2;
public string $description = "Provides a base for various small admin functions";
public bool $core = true;
- public string $visibility = self::VISIBLE_HIDDEN;
+ public ExtensionVisibility $visibility = ExtensionVisibility::HIDDEN;
}
diff --git a/ext/admin/main.php b/ext/admin/main.php
index ad3bc67c..b06d0f7c 100644
--- a/ext/admin/main.php
+++ b/ext/admin/main.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
/**
* Sent when the admin page is ready to be added to
*/
@@ -115,7 +117,7 @@ class AdminPage extends Extension
$key = $event->args[1];
switch ($cmd) {
case "get":
- var_dump($cache->get($key));
+ var_export($cache->get($key));
break;
case "set":
$cache->set($key, $event->args[2], 60);
diff --git a/ext/admin/test.php b/ext/admin/test.php
index ae0583a3..a4cbfcae 100644
--- a/ext/admin/test.php
+++ b/ext/admin/test.php
@@ -1,6 +1,9 @@
0) {
$tmp = $_FILES['alias_file']['tmp_name'];
$contents = file_get_contents($tmp);
- $this->add_alias_csv($database, $contents);
+ $this->add_alias_csv($contents);
log_info("alias_editor", "Imported aliases from file", "Imported aliases"); # FIXME: how many?
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("alias/list"));
@@ -177,7 +179,7 @@ class AliasEditor extends Extension
return $csv;
}
- private function add_alias_csv(Database $database, string $csv): int
+ private function add_alias_csv(string $csv): int
{
$csv = str_replace("\r", "\n", $csv);
$i = 0;
diff --git a/ext/alias_editor/test.php b/ext/alias_editor/test.php
index d194fc31..78437026 100644
--- a/ext/alias_editor/test.php
+++ b/ext/alias_editor/test.php
@@ -1,6 +1,9 @@
get_arg(0)) {
//*************ARTIST SECTION**************
case "list":
- {
- $this->get_listing($page, $event);
- $this->theme->sidebar_options("neutral");
- break;
- }
+ {
+ $this->get_listing($event);
+ $this->theme->sidebar_options("neutral");
+ break;
+ }
case "new":
- {
- if (!$user->is_anonymous()) {
- $this->theme->new_artist_composer();
- } else {
- $this->theme->display_error(401, "Error", "You must be registered and logged in to create a new artist.");
- }
- break;
- }
- case "new_artist":
- {
- $page->set_mode(PageMode::REDIRECT);
- $page->set_redirect(make_link("artist/new"));
- break;
- }
- case "create":
- {
- if (!$user->is_anonymous()) {
- $newArtistID = $this->add_artist();
- if ($newArtistID == -1) {
- $this->theme->display_error(400, "Error", "Error when entering artist data.");
+ {
+ if (!$user->is_anonymous()) {
+ $this->theme->new_artist_composer();
} else {
- $page->set_mode(PageMode::REDIRECT);
- $page->set_redirect(make_link("artist/view/".$newArtistID));
+ $this->theme->display_error(401, "Error", "You must be registered and logged in to create a new artist.");
}
- } else {
- $this->theme->display_error(401, "Error", "You must be registered and logged in to create a new artist.");
+ break;
+ }
+ case "new_artist":
+ {
+ $page->set_mode(PageMode::REDIRECT);
+ $page->set_redirect(make_link("artist/new"));
+ break;
+ }
+ case "create":
+ {
+ if (!$user->is_anonymous()) {
+ $newArtistID = $this->add_artist();
+ if ($newArtistID == -1) {
+ $this->theme->display_error(400, "Error", "Error when entering artist data.");
+ } else {
+ $page->set_mode(PageMode::REDIRECT);
+ $page->set_redirect(make_link("artist/view/".$newArtistID));
+ }
+ } else {
+ $this->theme->display_error(401, "Error", "You must be registered and logged in to create a new artist.");
+ }
+ break;
}
- break;
- }
case "view":
- {
- $artistID = int_escape($event->get_arg(1));
- $artist = $this->get_artist($artistID);
- $aliases = $this->get_alias($artist['id']);
- $members = $this->get_members($artist['id']);
- $urls = $this->get_urls($artist['id']);
+ {
+ $artistID = int_escape($event->get_arg(1));
+ $artist = $this->get_artist($artistID);
+ $aliases = $this->get_alias($artist['id']);
+ $members = $this->get_members($artist['id']);
+ $urls = $this->get_urls($artist['id']);
- $userIsLogged = !$user->is_anonymous();
- $userIsAdmin = $user->can(Permissions::ARTISTS_ADMIN);
+ $userIsLogged = !$user->is_anonymous();
+ $userIsAdmin = $user->can(Permissions::ARTISTS_ADMIN);
- $images = Image::find_images(0, 4, Tag::explode($artist['name']));
+ $images = Image::find_images(0, 4, Tag::explode($artist['name']));
- $this->theme->show_artist($artist, $aliases, $members, $urls, $images, $userIsLogged, $userIsAdmin);
- /*
- if ($userIsLogged) {
- $this->theme->show_new_alias_composer($artistID);
- $this->theme->show_new_member_composer($artistID);
- $this->theme->show_new_url_composer($artistID);
+ $this->theme->show_artist($artist, $aliases, $members, $urls, $images, $userIsLogged, $userIsAdmin);
+ /*
+ if ($userIsLogged) {
+ $this->theme->show_new_alias_composer($artistID);
+ $this->theme->show_new_member_composer($artistID);
+ $this->theme->show_new_url_composer($artistID);
+ }
+ */
+
+ $this->theme->sidebar_options("editor", $artistID, $userIsAdmin);
+
+ break;
}
- */
-
- $this->theme->sidebar_options("editor", $artistID, $userIsAdmin);
-
- break;
- }
case "edit":
- {
- $artistID = int_escape($event->get_arg(1));
- $artist = $this->get_artist($artistID);
- $aliases = $this->get_alias($artistID);
- $members = $this->get_members($artistID);
- $urls = $this->get_urls($artistID);
+ {
+ $artistID = int_escape($event->get_arg(1));
+ $artist = $this->get_artist($artistID);
+ $aliases = $this->get_alias($artistID);
+ $members = $this->get_members($artistID);
+ $urls = $this->get_urls($artistID);
- if (!$user->is_anonymous()) {
- $this->theme->show_artist_editor($artist, $aliases, $members, $urls);
+ if (!$user->is_anonymous()) {
+ $this->theme->show_artist_editor($artist, $aliases, $members, $urls);
- $userIsAdmin = $user->can(Permissions::ARTISTS_ADMIN);
- $this->theme->sidebar_options("editor", $artistID, $userIsAdmin);
- } else {
- $this->theme->display_error(401, "Error", "You must be registered and logged in to edit an artist.");
+ $userIsAdmin = $user->can(Permissions::ARTISTS_ADMIN);
+ $this->theme->sidebar_options("editor", $artistID, $userIsAdmin);
+ } else {
+ $this->theme->display_error(401, "Error", "You must be registered and logged in to edit an artist.");
+ }
+ break;
}
- break;
- }
case "edit_artist":
- {
- $artistID = $_POST['artist_id'];
- $page->set_mode(PageMode::REDIRECT);
- $page->set_redirect(make_link("artist/edit/".$artistID));
- break;
- }
+ {
+ $artistID = $_POST['artist_id'];
+ $page->set_mode(PageMode::REDIRECT);
+ $page->set_redirect(make_link("artist/edit/".$artistID));
+ break;
+ }
case "edited":
- {
- $artistID = int_escape($_POST['id']);
- $this->update_artist();
- $page->set_mode(PageMode::REDIRECT);
- $page->set_redirect(make_link("artist/view/".$artistID));
- break;
- }
+ {
+ $artistID = int_escape($_POST['id']);
+ $this->update_artist();
+ $page->set_mode(PageMode::REDIRECT);
+ $page->set_redirect(make_link("artist/view/".$artistID));
+ break;
+ }
case "nuke_artist":
- {
- $artistID = $_POST['artist_id'];
- $page->set_mode(PageMode::REDIRECT);
- $page->set_redirect(make_link("artist/nuke/".$artistID));
- break;
- }
+ {
+ $artistID = $_POST['artist_id'];
+ $page->set_mode(PageMode::REDIRECT);
+ $page->set_redirect(make_link("artist/nuke/".$artistID));
+ break;
+ }
case "nuke":
- {
- $artistID = int_escape($event->get_arg(1));
- $this->delete_artist($artistID); // this will delete the artist, its alias, its urls and its members
- $page->set_mode(PageMode::REDIRECT);
- $page->set_redirect(make_link("artist/list"));
- break;
- }
+ {
+ $artistID = int_escape($event->get_arg(1));
+ $this->delete_artist($artistID); // this will delete the artist, its alias, its urls and its members
+ $page->set_mode(PageMode::REDIRECT);
+ $page->set_redirect(make_link("artist/list"));
+ break;
+ }
case "add_alias":
- {
- $artistID = $_POST['artist_id'];
- $this->theme->show_new_alias_composer($artistID);
- break;
- }
+ {
+ $artistID = $_POST['artist_id'];
+ $this->theme->show_new_alias_composer($artistID);
+ break;
+ }
case "add_member":
- {
- $artistID = $_POST['artist_id'];
- $this->theme->show_new_member_composer($artistID);
- break;
- }
+ {
+ $artistID = $_POST['artist_id'];
+ $this->theme->show_new_member_composer($artistID);
+ break;
+ }
case "add_url":
- {
- $artistID = $_POST['artist_id'];
- $this->theme->show_new_url_composer($artistID);
- break;
- }
- //***********ALIAS SECTION ***********************
+ {
+ $artistID = $_POST['artist_id'];
+ $this->theme->show_new_url_composer($artistID);
+ break;
+ }
+ //***********ALIAS SECTION ***********************
case "alias":
- {
- switch ($event->get_arg(1)) {
- case "add":
- {
- $artistID = $_POST['artistID'];
- $this->add_alias();
- $page->set_mode(PageMode::REDIRECT);
- $page->set_redirect(make_link("artist/view/".$artistID));
- break;
- }
- case "delete":
- {
- $aliasID = int_escape($event->get_arg(2));
- $artistID = $this->get_artistID_by_aliasID($aliasID);
- $this->delete_alias($aliasID);
- $page->set_mode(PageMode::REDIRECT);
- $page->set_redirect(make_link("artist/view/".$artistID));
- break;
- }
- case "edit":
- {
- $aliasID = int_escape($event->get_arg(2));
- $alias = $this->get_alias_by_id($aliasID);
- $this->theme->show_alias_editor($alias);
- break;
- }
- case "edited":
- {
- $this->update_alias();
- $aliasID = int_escape($_POST['aliasID']);
- $artistID = $this->get_artistID_by_aliasID($aliasID);
- $page->set_mode(PageMode::REDIRECT);
- $page->set_redirect(make_link("artist/view/".$artistID));
- break;
+ {
+ switch ($event->get_arg(1)) {
+ case "add":
+ {
+ $artistID = $_POST['artistID'];
+ $this->add_alias();
+ $page->set_mode(PageMode::REDIRECT);
+ $page->set_redirect(make_link("artist/view/".$artistID));
+ break;
+ }
+ case "delete":
+ {
+ $aliasID = int_escape($event->get_arg(2));
+ $artistID = $this->get_artistID_by_aliasID($aliasID);
+ $this->delete_alias($aliasID);
+ $page->set_mode(PageMode::REDIRECT);
+ $page->set_redirect(make_link("artist/view/".$artistID));
+ break;
+ }
+ case "edit":
+ {
+ $aliasID = int_escape($event->get_arg(2));
+ $alias = $this->get_alias_by_id($aliasID);
+ $this->theme->show_alias_editor($alias);
+ break;
+ }
+ case "edited":
+ {
+ $this->update_alias();
+ $aliasID = int_escape($_POST['aliasID']);
+ $artistID = $this->get_artistID_by_aliasID($aliasID);
+ $page->set_mode(PageMode::REDIRECT);
+ $page->set_redirect(make_link("artist/view/".$artistID));
+ break;
+ }
}
+ break; // case: alias
}
- break; // case: alias
- }
- //**************** URLS SECTION **********************
+ //**************** URLS SECTION **********************
case "url":
- {
- switch ($event->get_arg(1)) {
- case "add":
- {
- $artistID = $_POST['artistID'];
- $this->add_urls();
- $page->set_mode(PageMode::REDIRECT);
- $page->set_redirect(make_link("artist/view/".$artistID));
- break;
- }
- case "delete":
- {
- $urlID = int_escape($event->get_arg(2));
- $artistID = $this->get_artistID_by_urlID($urlID);
- $this->delete_url($urlID);
- $page->set_mode(PageMode::REDIRECT);
- $page->set_redirect(make_link("artist/view/".$artistID));
- break;
- }
- case "edit":
- {
- $urlID = int_escape($event->get_arg(2));
- $url = $this->get_url_by_id($urlID);
- $this->theme->show_url_editor($url);
- break;
- }
- case "edited":
- {
- $this->update_url();
- $urlID = int_escape($_POST['urlID']);
- $artistID = $this->get_artistID_by_urlID($urlID);
- $page->set_mode(PageMode::REDIRECT);
- $page->set_redirect(make_link("artist/view/".$artistID));
- break;
+ {
+ switch ($event->get_arg(1)) {
+ case "add":
+ {
+ $artistID = $_POST['artistID'];
+ $this->add_urls();
+ $page->set_mode(PageMode::REDIRECT);
+ $page->set_redirect(make_link("artist/view/".$artistID));
+ break;
+ }
+ case "delete":
+ {
+ $urlID = int_escape($event->get_arg(2));
+ $artistID = $this->get_artistID_by_urlID($urlID);
+ $this->delete_url($urlID);
+ $page->set_mode(PageMode::REDIRECT);
+ $page->set_redirect(make_link("artist/view/".$artistID));
+ break;
+ }
+ case "edit":
+ {
+ $urlID = int_escape($event->get_arg(2));
+ $url = $this->get_url_by_id($urlID);
+ $this->theme->show_url_editor($url);
+ break;
+ }
+ case "edited":
+ {
+ $this->update_url();
+ $urlID = int_escape($_POST['urlID']);
+ $artistID = $this->get_artistID_by_urlID($urlID);
+ $page->set_mode(PageMode::REDIRECT);
+ $page->set_redirect(make_link("artist/view/".$artistID));
+ break;
+ }
}
+ break; // case: urls
}
- break; // case: urls
- }
- //******************* MEMBERS SECTION *********************
+ //******************* MEMBERS SECTION *********************
case "member":
- {
- switch ($event->get_arg(1)) {
- case "add":
- {
- $artistID = $_POST['artistID'];
- $this->add_members();
- $page->set_mode(PageMode::REDIRECT);
- $page->set_redirect(make_link("artist/view/".$artistID));
- break;
- }
- case "delete":
- {
- $memberID = int_escape($event->get_arg(2));
- $artistID = $this->get_artistID_by_memberID($memberID);
- $this->delete_member($memberID);
- $page->set_mode(PageMode::REDIRECT);
- $page->set_redirect(make_link("artist/view/".$artistID));
- break;
- }
- case "edit":
- {
- $memberID = int_escape($event->get_arg(2));
- $member = $this->get_member_by_id($memberID);
- $this->theme->show_member_editor($member);
- break;
- }
- case "edited":
- {
- $this->update_member();
- $memberID = int_escape($_POST['memberID']);
- $artistID = $this->get_artistID_by_memberID($memberID);
- $page->set_mode(PageMode::REDIRECT);
- $page->set_redirect(make_link("artist/view/".$artistID));
- break;
+ {
+ switch ($event->get_arg(1)) {
+ case "add":
+ {
+ $artistID = $_POST['artistID'];
+ $this->add_members();
+ $page->set_mode(PageMode::REDIRECT);
+ $page->set_redirect(make_link("artist/view/".$artistID));
+ break;
+ }
+ case "delete":
+ {
+ $memberID = int_escape($event->get_arg(2));
+ $artistID = $this->get_artistID_by_memberID($memberID);
+ $this->delete_member($memberID);
+ $page->set_mode(PageMode::REDIRECT);
+ $page->set_redirect(make_link("artist/view/".$artistID));
+ break;
+ }
+ case "edit":
+ {
+ $memberID = int_escape($event->get_arg(2));
+ $member = $this->get_member_by_id($memberID);
+ $this->theme->show_member_editor($member);
+ break;
+ }
+ case "edited":
+ {
+ $this->update_member();
+ $memberID = int_escape($_POST['memberID']);
+ $artistID = $this->get_artistID_by_memberID($memberID);
+ $page->set_mode(PageMode::REDIRECT);
+ $page->set_redirect(make_link("artist/view/".$artistID));
+ break;
+ }
}
+ break; //case: members
}
- break; //case: members
- }
}
}
}
@@ -845,7 +847,7 @@ class Artists extends Extension
/*
* HERE WE GET THE LIST OF ALL ARTIST WITH PAGINATION
*/
- private function get_listing(Page $page, PageRequestEvent $event)
+ private function get_listing(PageRequestEvent $event)
{
global $config, $database;
@@ -1048,7 +1050,8 @@ class Artists extends Extension
ORDER BY alias ASC
", ['artist_id'=>$artistID]);
- for ($i = 0 ; $i < count($result) ; $i++) {
+ $rc = count($result);
+ for ($i = 0 ; $i < $rc ; $i++) {
$result[$i]["alias_name"] = stripslashes($result[$i]["alias_name"]);
}
return $result;
diff --git a/ext/artists/test.php b/ext/artists/test.php
index fdebbce5..47f312bd 100644
--- a/ext/artists/test.php
+++ b/ext/artists/test.php
@@ -1,6 +1,9 @@
";
if (count($aliases) > 1) {
- for ($i = 1; $i < count($aliases); $i++) {
+ $ac = count($aliases);
+ for ($i = 1; $i < $ac; $i++) {
$aliasViewLink = str_replace("_", " ", $aliases[$i]['alias_name']); // no link anymore
$aliasEditLink = "Edit";
$aliasDeleteLink = "Delete";
@@ -479,7 +483,8 @@ class ArtistsTheme extends Themelet
$html .= "";
if (count($members) > 1) {
- for ($i = 1; $i < count($members); $i++) {
+ $mc = count($members);
+ for ($i = 1; $i < $mc; $i++) {
$memberViewLink = str_replace("_", " ", $members[$i]['name']); // no link anymore
$memberEditLink = "Edit";
$memberDeleteLink = "Delete";
@@ -524,7 +529,8 @@ class ArtistsTheme extends Themelet
$html .= "";
if (count($urls) > 1) {
- for ($i = 1; $i < count($urls); $i++) {
+ $uc = count($urls);
+ for ($i = 1; $i < $uc; $i++) {
$urlViewLink = "" . str_replace("_", " ", $urls[$i]['url']) . "";
$urlEditLink = "Edit";
$urlDeleteLink = "Delete";
diff --git a/ext/auto_tagger/config.php b/ext/auto_tagger/config.php
index 3dd8e478..6fd5ed8e 100644
--- a/ext/auto_tagger/config.php
+++ b/ext/auto_tagger/config.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
abstract class AutoTaggerConfig
{
public const VERSION = "ext_auto_tagger_ver";
diff --git a/ext/auto_tagger/info.php b/ext/auto_tagger/info.php
index a466d470..ad1a7969 100644
--- a/ext/auto_tagger/info.php
+++ b/ext/auto_tagger/info.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class AutoTaggerInfo extends ExtensionInfo
{
public const KEY = "auto_tagger";
diff --git a/ext/auto_tagger/main.php b/ext/auto_tagger/main.php
index 3ffd75ea..370cdac5 100644
--- a/ext/auto_tagger/main.php
+++ b/ext/auto_tagger/main.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
require_once 'config.php';
use MicroCRUD\ActionColumn;
@@ -110,7 +112,7 @@ class AutoTagger extends Extension
if (count($_FILES) > 0) {
$tmp = $_FILES['auto_tag_file']['tmp_name'];
$contents = file_get_contents($tmp);
- $count = $this->add_auto_tag_csv($database, $contents);
+ $count = $this->add_auto_tag_csv($contents);
log_info(AutoTaggerInfo::KEY, "Imported $count auto-tag definitions from file from file", "Imported $count auto-tag definitions");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("auto_tag/list"));
@@ -142,7 +144,7 @@ class AutoTagger extends Extension
additional_tags VARCHAR(2000) NOT NULL
");
- if ($database->get_driver_name() == DatabaseDriver::PGSQL) {
+ if ($database->get_driver_id() == DatabaseDriverID::PGSQL) {
$database->execute('CREATE INDEX auto_tag_lower_tag_idx ON auto_tag ((lower(tag)))');
}
$this->set_version(AutoTaggerConfig::VERSION, 1);
@@ -189,7 +191,7 @@ class AutoTagger extends Extension
return $csv;
}
- private function add_auto_tag_csv(Database $database, string $csv): int
+ private function add_auto_tag_csv(string $csv): int
{
$csv = str_replace("\r", "\n", $csv);
$i = 0;
@@ -210,23 +212,23 @@ class AutoTagger extends Extension
private function add_auto_tag(string $tag, string $additional_tags)
{
global $database;
- $existing_tags = $database->get_one("SELECT additional_tags FROM auto_tag WHERE LOWER(tag)=LOWER(:tag)", ["tag"=>$tag]);
- if (!is_null($existing_tags)) {
- // Auto Tags already exist, so we will append new tags to the existing one
- $tag = Tag::sanitize($tag);
+ $existing_tags = $database->get_one("SELECT additional_tags FROM auto_tag WHERE LOWER(tag)=LOWER(:tag)", ["tag"=>$tag]);
+ if (!is_null($existing_tags)) {
+ // Auto Tags already exist, so we will append new tags to the existing one
+ $tag = Tag::sanitize($tag);
$additional_tags = Tag::explode($additional_tags);
- $existing_tags = Tag::explode($existing_tags);
- foreach ($additional_tags as $t) {
- if (!in_array(strtolower($t), $existing_tags)) {
- array_push($existing_tags, strtolower($t));
- }
- }
-
- $database->execute(
+ $existing_tags = Tag::explode($existing_tags);
+ foreach ($additional_tags as $t) {
+ if (!in_array(strtolower($t), $existing_tags)) {
+ $existing_tags[] = strtolower($t);
+ }
+ }
+
+ $database->execute(
"UPDATE auto_tag set additional_tags=:existing_tags where tag=:tag",
["tag"=>$tag, "existing_tags"=>Tag::implode($existing_tags)]
);
- log_info(
+ log_info(
AutoTaggerInfo::KEY,
"Updated auto-tag for {$tag} -> {".implode(" ", $additional_tags)."}"
);
@@ -244,39 +246,8 @@ class AutoTagger extends Extension
"Added auto-tag for {$tag} -> {".implode(" ", $additional_tags)."}"
);
}
- // Now we apply it to existing items
- $this->apply_new_auto_tag($tag);
- }
-
- private function update_auto_tag(string $tag, string $additional_tags): bool
- {
- global $database;
- $result = $database->get_row("SELECT * FROM auto_tag WHERE LOWER(tag)=LOWER(:tag)", ["tag"=>$tag]);
-
- if ($result===null) {
- throw new AutoTaggerException("Auto-tag not set for $tag, can't update");
- } else {
- $additional_tags = Tag::explode($additional_tags);
- $current_additional_tags = Tag::explode($result["additional_tags"]);
-
- if (!Tag::compare($additional_tags, $current_additional_tags)) {
- $database->execute(
- "UPDATE auto_tag SET additional_tags = :additional_tags WHERE LOWER(tag)=LOWER(:tag)",
- ["tag"=>$tag, "additional_tags"=>Tag::implode($additional_tags)]
- );
-
- log_info(
- AutoTaggerInfo::KEY,
- "Updated auto-tag for {$tag} -> {".implode(" ", $additional_tags)."}",
- "Updated Auto-Tag"
- );
-
- // Now we apply it to existing items
- $this->apply_new_auto_tag($tag);
- return true;
- }
- }
- return false;
+ // Now we apply it to existing items
+ $this->apply_new_auto_tag($tag);
}
private function apply_new_auto_tag(string $tag)
@@ -288,14 +259,11 @@ class AutoTagger extends Extension
foreach ($image_ids as $image_id) {
$image_id = (int) $image_id;
$image = Image::by_id($image_id);
- $event = new TagSetEvent($image, $image->get_tag_array());
- send_event($event);
+ send_event(new TagSetEvent($image, $image->get_tag_array()));
}
}
}
-
-
private function remove_auto_tag(String $tag)
{
global $database;
diff --git a/ext/auto_tagger/test.php b/ext/auto_tagger/test.php
index 419d72c9..e8ed6293 100644
--- a/ext/auto_tagger/test.php
+++ b/ext/auto_tagger/test.php
@@ -1,6 +1,9 @@
get($cache_key);
- if (!$res) {
+ if (is_null($res)) {
$res = $database->get_pairs(
"
SELECT tag, count
diff --git a/ext/autocomplete/test.php b/ext/autocomplete/test.php
index ec9d1ba4..8378e584 100644
--- a/ext/autocomplete/test.php
+++ b/ext/autocomplete/test.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class AutoCompleteTest extends ShimmiePHPUnitTestCase
{
public function testAuth()
diff --git a/ext/autocomplete/theme.php b/ext/autocomplete/theme.php
index d5fcbe8b..d2d17047 100644
--- a/ext/autocomplete/theme.php
+++ b/ext/autocomplete/theme.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class AutoCompleteTheme extends Themelet
{
public function build_autocomplete(Page $page)
diff --git a/ext/ban_words/info.php b/ext/ban_words/info.php
index b1f84dcb..247ab304 100644
--- a/ext/ban_words/info.php
+++ b/ext/ban_words/info.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class BanWordsInfo extends ExtensionInfo
{
public const KEY = "ban_words";
diff --git a/ext/ban_words/main.php b/ext/ban_words/main.php
index 39febc87..4e57b7b4 100644
--- a/ext/ban_words/main.php
+++ b/ext/ban_words/main.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class BanWords extends Extension
{
public function onInitExt(InitExtEvent $event)
diff --git a/ext/ban_words/test.php b/ext/ban_words/test.php
index 69ec598b..a70f6a06 100644
--- a/ext/ban_words/test.php
+++ b/ext/ban_words/test.php
@@ -1,6 +1,9 @@
get_auth_html();
-
$html = SHM_SIMPLE_FORM(
- $post_url,
+ make_link("biography"),
TEXTAREA(["style"=>"width: 100%", "rows"=>"6", "name"=>"biography"], $bio),
SHM_SUBMIT("Save")
);
- $page->add_block(new Block("About Me", (string)$html, "main", 30));
+ $page->add_block(new Block("About Me", $html, "main", 30));
}
}
diff --git a/ext/blocks/info.php b/ext/blocks/info.php
index e42066b3..7dca5bd3 100644
--- a/ext/blocks/info.php
+++ b/ext/blocks/info.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class BlocksInfo extends ExtensionInfo
{
public const KEY = "blocks";
diff --git a/ext/blocks/main.php b/ext/blocks/main.php
index f278dec0..ccf71069 100644
--- a/ext/blocks/main.php
+++ b/ext/blocks/main.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class Blocks extends Extension
{
/** @var BlocksTheme */
@@ -47,7 +49,7 @@ class Blocks extends Extension
global $cache, $database, $page, $user;
$blocks = $cache->get("blocks");
- if ($blocks === false) {
+ if (is_null($blocks)) {
$blocks = $database->get_all("SELECT * FROM blocks");
$cache->set("blocks", $blocks, 600);
}
diff --git a/ext/blocks/test.php b/ext/blocks/test.php
index b30ae863..15677c4f 100644
--- a/ext/blocks/test.php
+++ b/ext/blocks/test.php
@@ -1,6 +1,9 @@
theme->display_permission_denied();
} else {
$id = int_escape($_POST['id']);
- if (!isset($id)) {
- die("No ID!");
- }
$database->execute("DELETE FROM blotter WHERE id=:id", ["id"=>$id]);
log_info("blotter", "Removed Entry #$id");
$page->set_mode(PageMode::REDIRECT);
diff --git a/ext/blotter/test.php b/ext/blotter/test.php
index 1824a295..4bd3cfdb 100644
--- a/ext/blotter/test.php
+++ b/ext/blotter/test.php
@@ -1,6 +1,9 @@
action = $action;
@@ -173,7 +175,7 @@ class BulkActions extends Extension
if (empty($data)) {
throw new BulkActionException("No ids specified in bulk_selected_ids");
}
- if (is_array($data) && !empty($data)) {
+ if (is_array($data)) {
$items = $this->yield_items($data);
}
} elseif (isset($_POST['bulk_query']) && $_POST['bulk_query'] != "") {
@@ -201,7 +203,7 @@ class BulkActions extends Extension
}
}
- private function yield_items(array $data): Generator
+ private function yield_items(array $data): \Generator
{
foreach ($data as $id) {
if (is_numeric($id)) {
@@ -213,7 +215,7 @@ class BulkActions extends Extension
}
}
- private function yield_search_results(string $query): Generator
+ private function yield_search_results(string $query): \Generator
{
$tags = Tag::explode($query);
return Image::find_images_iterable(0, null, $tags);
@@ -231,7 +233,7 @@ class BulkActions extends Extension
$size = 0;
foreach ($posts as $post) {
try {
- if (class_exists("ImageBan") && isset($_POST['bulk_ban_reason'])) {
+ if (class_exists("Shimmie2\ImageBan") && isset($_POST['bulk_ban_reason'])) {
$reason = $_POST['bulk_ban_reason'];
if ($reason) {
send_event(new AddImageHashBanEvent($post->hash, $reason));
@@ -240,7 +242,7 @@ class BulkActions extends Extension
send_event(new ImageDeletionEvent($post));
$total++;
$size += $post->filesize;
- } catch (Exception $e) {
+ } catch (\Exception $e) {
$page->flash("Error while removing {$post->id}: " . $e->getMessage());
}
}
@@ -295,7 +297,7 @@ class BulkActions extends Extension
try {
send_event(new SourceSetEvent($image, $source));
$total++;
- } catch (Exception $e) {
+ } catch (\Exception $e) {
$page->flash("Error while setting source for {$image->id}: " . $e->getMessage());
}
}
diff --git a/ext/bulk_actions/theme.php b/ext/bulk_actions/theme.php
index e41a9764..777a7606 100644
--- a/ext/bulk_actions/theme.php
+++ b/ext/bulk_actions/theme.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class BulkActionsTheme extends Themelet
{
public function display_selector(Page $page, array $actions, string $query)
@@ -49,7 +51,7 @@ class BulkActionsTheme extends Themelet
public function render_ban_reason_input(): string
{
- if (class_exists("ImageBan")) {
+ if (class_exists("Shimmie2\ImageBan")) {
return "";
} else {
return "";
@@ -64,6 +66,6 @@ class BulkActionsTheme extends Themelet
public function render_source_input(): string
{
- return "";
+ return "";
}
}
diff --git a/ext/bulk_add/info.php b/ext/bulk_add/info.php
index dc5cfada..149c1b8e 100644
--- a/ext/bulk_add/info.php
+++ b/ext/bulk_add/info.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class BulkAddInfo extends ExtensionInfo
{
public const KEY = "bulk_add";
diff --git a/ext/bulk_add/main.php b/ext/bulk_add/main.php
index 953b36d7..9aed87dd 100644
--- a/ext/bulk_add/main.php
+++ b/ext/bulk_add/main.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class BulkAddEvent extends Event
{
public string $dir;
diff --git a/ext/bulk_add/test.php b/ext/bulk_add/test.php
index d99eb9b0..78c6e74c 100644
--- a/ext/bulk_add/test.php
+++ b/ext/bulk_add/test.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class BulkAddTest extends ShimmiePHPUnitTestCase
{
public function testInvalidDir()
diff --git a/ext/bulk_add/theme.php b/ext/bulk_add/theme.php
index cc7135da..6a74b3ef 100644
--- a/ext/bulk_add/theme.php
+++ b/ext/bulk_add/theme.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class BulkAddTheme extends Themelet
{
private array $messages = [];
diff --git a/ext/bulk_add_csv/info.php b/ext/bulk_add_csv/info.php
index 4d13d45a..46d13192 100644
--- a/ext/bulk_add_csv/info.php
+++ b/ext/bulk_add_csv/info.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class BulkAddCSVInfo extends ExtensionInfo
{
public const KEY = "bulk_add_csv";
diff --git a/ext/bulk_add_csv/main.php b/ext/bulk_add_csv/main.php
index 9ae858e9..6dfcb488 100644
--- a/ext/bulk_add_csv/main.php
+++ b/ext/bulk_add_csv/main.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class BulkAddCSV extends Extension
{
/** @var BulkAddCSVTheme */
@@ -48,21 +50,11 @@ class BulkAddCSV extends Extension
*/
private function add_image(string $tmpname, string $filename, string $tags, string $source, string $rating, string $thumbfile)
{
- assert(file_exists($tmpname));
-
- $pathinfo = pathinfo($filename);
- $metadata = [];
- $metadata['filename'] = $pathinfo['basename'];
- if (array_key_exists('extension', $pathinfo)) {
- $metadata['extension'] = $pathinfo['extension'];
- }
- $metadata['tags'] = Tag::explode($tags);
- $metadata['source'] = $source;
- $event = send_event(new DataUploadEvent($tmpname, $metadata));
+ $event = add_image($tmpname, $filename, $tags, $source);
if ($event->image_id == -1) {
throw new UploadException("File type not recognised");
} else {
- if (class_exists("RatingSetEvent") && in_array($rating, ["s", "q", "e"])) {
+ if (class_exists("Shimmie2\RatingSetEvent") && in_array($rating, ["s", "q", "e"])) {
send_event(new RatingSetEvent(Image::by_id($event->image_id), $rating));
}
if (file_exists($thumbfile)) {
@@ -103,14 +95,13 @@ class BulkAddCSV extends Extension
$source = $csvdata[2];
$rating = $csvdata[3];
$thumbfile = $csvdata[4];
- $pathinfo = pathinfo($fullpath);
- $shortpath = $pathinfo["basename"];
+ $shortpath = pathinfo($fullpath, PATHINFO_BASENAME);
$list .= " Search items can be combined to search for posts which match both,
-or you can stick \"-\" in front of an item to search for things that don't
-match it.
- Metatags can be followed by \":\" rather than \"=\" if you prefer.
- Some search methods provided by extensions:
Search for posts by source Returns posts with a source of "http://google.com/". Returns posts with a source of "https://google.com/". Search for posts by date posted. Returns posts posted on or after 07-19-2019. Returns posts posted on or after 2019-07-19. Can use <, <=, >, >=, or =. Date format is mm-dd-yyyy. Date posted includes time component, so = will not work unless the time is exact. Can use <, <=, >, >=, or =. Date format is yyyy-mm-dd. Date posted includes time component, so = will not work unless the time is exact. For legal reasons, we need to point out that:"+
- " A) this site contains material not suitable for minors"+
- " Click here if you're an adult, and you're ok with that"+
+ " Cookies may be used. Please read our privacy policy for more information."+
+ " By accepting to enter you agree to our rules and terms of service."+
+ "
".html_escape("$shortpath (".str_replace(" ", ", ", $tags).")... ");
if (file_exists($csvdata[0]) && is_file($csvdata[0])) {
try {
- $this->add_image($fullpath, $pathinfo["basename"], $tags, $source, $rating, $thumbfile);
+ $this->add_image($fullpath, $shortpath, $tags, $source, $rating, $thumbfile);
$list .= "ok\n";
- } catch (Exception $ex) {
+ } catch (\Exception $ex) {
$list .= "failed:
". $ex->getMessage();
}
} else {
diff --git a/ext/bulk_add_csv/theme.php b/ext/bulk_add_csv/theme.php
index 0af200e2..2128e5ae 100644
--- a/ext/bulk_add_csv/theme.php
+++ b/ext/bulk_add_csv/theme.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class BulkAddCSVTheme extends Themelet
{
private array $messages = [];
diff --git a/ext/bulk_download/info.php b/ext/bulk_download/info.php
index 02745855..d5260459 100644
--- a/ext/bulk_download/info.php
+++ b/ext/bulk_download/info.php
@@ -2,6 +2,7 @@
declare(strict_types=1);
+namespace Shimmie2;
class BulkDownloadInfo extends ExtensionInfo
{
diff --git a/ext/bulk_download/main.php b/ext/bulk_download/main.php
index 34eddfa6..64e38025 100644
--- a/ext/bulk_download/main.php
+++ b/ext/bulk_download/main.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class BulkDownloadConfig
{
public const SIZE_LIMIT = "bulk_download_size_limit";
@@ -47,11 +49,11 @@ class BulkDownload extends Extension
($event->action == BulkDownload::DOWNLOAD_ACTION_NAME)) {
$download_filename = $user->name . '-' . date('YmdHis') . '.zip';
$zip_filename = tempnam(sys_get_temp_dir(), "shimmie_bulk_download");
- $zip = new ZipArchive();
+ $zip = new \ZipArchive();
$size_total = 0;
$max_size = $config->get_int(BulkDownloadConfig::SIZE_LIMIT);
- if ($zip->open($zip_filename, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE) === true) {
+ if ($zip->open($zip_filename, \ZIPARCHIVE::CREATE | \ZIPARCHIVE::OVERWRITE) === true) {
foreach ($event->items as $image) {
$img_loc = warehouse_path(Image::IMAGE_DIR, $image->hash, false);
$size_total += filesize($img_loc);
diff --git a/ext/bulk_import_export/events.php b/ext/bulk_import_export/events.php
index 7a4d2c7a..89b4b00c 100644
--- a/ext/bulk_import_export/events.php
+++ b/ext/bulk_import_export/events.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class BulkExportEvent extends Event
{
public Image $image;
diff --git a/ext/bulk_import_export/info.php b/ext/bulk_import_export/info.php
index 78ebaf1d..6ad951b0 100644
--- a/ext/bulk_import_export/info.php
+++ b/ext/bulk_import_export/info.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
include_once "events.php";
class BulkImportExportInfo extends ExtensionInfo
diff --git a/ext/bulk_import_export/main.php b/ext/bulk_import_export/main.php
index 65d433a9..5f635784 100644
--- a/ext/bulk_import_export/main.php
+++ b/ext/bulk_import_export/main.php
@@ -2,6 +2,7 @@
declare(strict_types=1);
+namespace Shimmie2;
class BulkImportExport extends DataHandlerExtension
{
@@ -16,7 +17,7 @@ class BulkImportExport extends DataHandlerExtension
if ($this->supported_mime($event->mime) &&
$user->can(Permissions::BULK_IMPORT)) {
- $zip = new ZipArchive();
+ $zip = new \ZipArchive();
if ($zip->open($event->tmpname) === true) {
$json_data = $this->get_export_data($zip);
@@ -51,7 +52,7 @@ class BulkImportExport extends DataHandlerExtension
file_put_contents($tmpfile, $stream);
- $id = add_image($tmpfile, $item->filename, Tag::implode($item->tags));
+ $id = add_image($tmpfile, $item->filename, Tag::implode($item->tags))->image_id;
if ($id==-1) {
throw new SCoreException("Unable to import file $item->hash");
@@ -70,11 +71,11 @@ class BulkImportExport extends DataHandlerExtension
$database->commit();
$total++;
- } catch (Exception $ex) {
+ } catch (\Exception $ex) {
$failed++;
try {
$database->rollBack();
- } catch (Exception $ex2) {
+ } catch (\Exception $ex2) {
log_error(BulkImportExportInfo::KEY, "Could not roll back transaction: " . $ex2->getMessage(), "Could not import " . $item->hash . ": " . $ex->getMessage());
}
log_error(BulkImportExportInfo::KEY, "Could not import " . $item->hash . ": " . $ex->getMessage(), "Could not import " . $item->hash . ": " . $ex->getMessage());
@@ -117,23 +118,22 @@ class BulkImportExport extends DataHandlerExtension
($event->action == self::EXPORT_ACTION_NAME)) {
$download_filename = $user->name . '-' . date('YmdHis') . '.zip';
$zip_filename = tempnam(sys_get_temp_dir(), "shimmie_bulk_export");
- $zip = new ZipArchive();
+ $zip = new \ZipArchive();
$json_data = [];
- if ($zip->open($zip_filename, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE) === true) {
+ if ($zip->open($zip_filename, \ZIPARCHIVE::CREATE | \ZIPARCHIVE::OVERWRITE) === true) {
foreach ($event->items as $image) {
$img_loc = warehouse_path(Image::IMAGE_DIR, $image->hash, false);
- $export_event = new BulkExportEvent($image);
- send_event($export_event);
+ $export_event = send_event(new BulkExportEvent($image));
$data = $export_event->fields;
$data["hash"] = $image->hash;
$data["tags"] = $image->get_tag_array();
$data["filename"] = $image->filename;
$data["source"] = $image->source;
- array_push($json_data, $data);
+ $json_data[] = $data;
$zip->addFile($img_loc, $image->hash);
}
@@ -166,17 +166,17 @@ class BulkImportExport extends DataHandlerExtension
return false;
}
- private function get_export_data(ZipArchive $zip): ?array
+ private function get_export_data(\ZipArchive $zip): ?array
{
$info = $zip->getStream(self::EXPORT_INFO_FILE_NAME);
if ($info !== false) {
try {
$json_string = stream_get_contents($info);
$json_data = json_decode($json_string);
+ return $json_data;
} finally {
fclose($info);
}
- return $json_data;
} else {
return null;
}
diff --git a/ext/comment/info.php b/ext/comment/info.php
index d3fd5951..840aae94 100644
--- a/ext/comment/info.php
+++ b/ext/comment/info.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class CommentListInfo extends ExtensionInfo
{
public const KEY = "comment";
diff --git a/ext/comment/main.php b/ext/comment/main.php
index e48c0bab..b6da4eed 100644
--- a/ext/comment/main.php
+++ b/ext/comment/main.php
@@ -2,6 +2,13 @@
declare(strict_types=1);
+namespace Shimmie2;
+
+use GQLA\Type;
+use GQLA\Field;
+use GQLA\Query;
+use GQLA\Mutation;
+
require_once "vendor/ifixit/php-akismet/akismet.class.php";
class CommentPostingEvent extends Event
@@ -39,6 +46,7 @@ class CommentPostingException extends SCoreException
{
}
+#[Type(name: "Comment")]
class Comment
{
public ?User $owner;
@@ -46,10 +54,13 @@ class Comment
public string $owner_name;
public ?string $owner_email;
public string $owner_class;
+ #[Field]
public string $comment;
+ #[Field]
public int $comment_id;
public int $image_id;
public string $poster_ip;
+ #[Field]
public string $posted;
public function __construct($row)
@@ -76,6 +87,7 @@ class Comment
", ["owner_id"=>$user->id]);
}
+ #[Field(name: "owner")]
public function get_owner(): User
{
if (empty($this->owner)) {
@@ -83,6 +95,20 @@ class Comment
}
return $this->owner;
}
+
+ #[Field(extends: "Post", name: "comments", type: "[Comment!]!")]
+ public static function get_comments(Image $post): array
+ {
+ return CommentList::get_comments($post->id);
+ }
+
+ #[Mutation(name: "create_comment")]
+ public static function create_comment(int $post_id, string $comment): bool
+ {
+ global $user;
+ send_event(new CommentPostingEvent($post_id, $user, $comment));
+ return true;
+ }
}
class CommentList extends Extension
@@ -171,11 +197,21 @@ class CommentList extends Extension
{
if ($event->page_matches("comment")) {
switch ($event->get_arg(0)) {
- case "add": $this->onPageRequest_add(); break;
- case "delete": $this->onPageRequest_delete($event); break;
- case "bulk_delete": $this->onPageRequest_bulk_delete(); break;
- case "list": $this->onPageRequest_list($event); break;
- case "beta-search": $this->onPageRequest_beta_search($event); break;
+ case "add":
+ $this->onPageRequest_add();
+ break;
+ case "delete":
+ $this->onPageRequest_delete($event);
+ break;
+ case "bulk_delete":
+ $this->onPageRequest_bulk_delete();
+ break;
+ case "list":
+ $this->onPageRequest_list($event);
+ break;
+ case "beta-search":
+ $this->onPageRequest_beta_search($event);
+ break;
}
}
}
@@ -186,8 +222,7 @@ class CommentList extends Extension
if (isset($_POST['image_id']) && isset($_POST['comment'])) {
try {
$i_iid = int_escape($_POST['image_id']);
- $cpe = new CommentPostingEvent(int_escape($_POST['image_id']), $user, $_POST['comment']);
- send_event($cpe);
+ send_event(new CommentPostingEvent(int_escape($_POST['image_id']), $user, $_POST['comment']));
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/$i_iid", null, "comment_on_$i_iid"));
} catch (CommentPostingException $ex) {
@@ -244,7 +279,7 @@ class CommentList extends Extension
$where = SPEED_HAX ? "WHERE posted > now() - interval '24 hours'" : "";
$total_pages = $cache->get("comment_pages");
- if (empty($total_pages)) {
+ if (is_null($total_pages)) {
$total_pages = (int)ceil($database->get_one("
SELECT COUNT(c1)
FROM (SELECT COUNT(image_id) AS c1 FROM comments $where GROUP BY image_id) AS s1
@@ -316,7 +351,7 @@ class CommentList extends Extension
$cc = $config->get_int("comment_count");
if ($cc > 0) {
$recent = $cache->get("recent_comments");
- if (empty($recent)) {
+ if (is_null($recent)) {
$recent = $this->get_recent_comments($cc);
$cache->set("recent_comments", $recent, 60);
}
@@ -415,7 +450,7 @@ class CommentList extends Extension
/**
* #return Comment[]
*/
- private function get_generic_comments(string $query, array $args): array
+ private static function get_generic_comments(string $query, array $args): array
{
global $database;
$rows = $database->get_all($query, $args);
@@ -429,9 +464,9 @@ class CommentList extends Extension
/**
* #return Comment[]
*/
- private function get_recent_comments(int $count): array
+ private static function get_recent_comments(int $count): array
{
- return $this->get_generic_comments("
+ return CommentList::get_generic_comments("
SELECT
users.id as user_id, users.name as user_name, users.email as user_email, users.class as user_class,
comments.comment as comment, comments.id as comment_id,
@@ -447,9 +482,9 @@ class CommentList extends Extension
/**
* #return Comment[]
*/
- private function get_user_comments(int $user_id, int $count, int $offset=0): array
+ private static function get_user_comments(int $user_id, int $count, int $offset=0): array
{
- return $this->get_generic_comments("
+ return CommentList::get_generic_comments("
SELECT
users.id as user_id, users.name as user_name, users.email as user_email, users.class as user_class,
comments.comment as comment, comments.id as comment_id,
@@ -464,11 +499,12 @@ class CommentList extends Extension
}
/**
+ * public just for Image::get_comments()
* #return Comment[]
*/
- private function get_comments(int $image_id): array
+ public static function get_comments(int $image_id): array
{
- return $this->get_generic_comments("
+ return CommentList::get_generic_comments("
SELECT
users.id as user_id, users.name as user_name, users.email as user_email, users.class as user_class,
comments.comment as comment, comments.id as comment_id,
@@ -486,14 +522,14 @@ class CommentList extends Extension
global $config, $database;
// sqlite fails at intervals
- if ($database->get_driver_name() === DatabaseDriver::SQLITE) {
+ if ($database->get_driver_id() === DatabaseDriverID::SQLITE) {
return false;
}
$window = $config->get_int('comment_window');
$max = $config->get_int('comment_limit');
- if ($database->get_driver_name() == DatabaseDriver::MYSQL) {
+ if ($database->get_driver_id() == DatabaseDriverID::MYSQL) {
$window_sql = "interval $window minute";
} else {
$window_sql = "interval '$window minute'";
@@ -540,15 +576,18 @@ class CommentList extends Extension
'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'none',
];
- $akismet = new Akismet(
+ // @phpstan-ignore-next-line
+ $akismet = new \Akismet(
$_SERVER['SERVER_NAME'],
$config->get_string('comment_wordpress_key'),
$comment
);
+ // @phpstan-ignore-next-line
if ($akismet->errorsExist()) {
return false;
} else {
+ // @phpstan-ignore-next-line
return $akismet->isSpam();
}
}
diff --git a/ext/comment/test.php b/ext/comment/test.php
index 0c60f0c0..4bafa098 100644
--- a/ext/comment/test.php
+++ b/ext/comment/test.php
@@ -1,6 +1,9 @@
comment);
- send_event($tfe);
+ $tfe = send_event(new TextFormattingEvent($comment->comment));
$i_uid = $comment->owner_id;
$h_name = html_escape($comment->owner_name);
diff --git a/ext/cron_uploader/config.php b/ext/cron_uploader/config.php
index f6b37e88..1c827049 100644
--- a/ext/cron_uploader/config.php
+++ b/ext/cron_uploader/config.php
@@ -2,6 +2,7 @@
declare(strict_types=1);
+namespace Shimmie2;
abstract class CronUploaderConfig
{
diff --git a/ext/cron_uploader/info.php b/ext/cron_uploader/info.php
index 63379559..45d1635f 100644
--- a/ext/cron_uploader/info.php
+++ b/ext/cron_uploader/info.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
/*
* Name: Cron Uploader
* Authors: YaoiFox ";
$n = 1;
foreach ($list as $item) {
- $pathinfo = pathinfo($item);
- $name = $pathinfo["filename"];
+ $name = pathinfo($item, PATHINFO_FILENAME);
$html .= " :$name: ";
if ($n++ % 3 == 0) {
$html .= "";
diff --git a/ext/eokm/info.php b/ext/eokm/info.php
index 254cdd94..673415b6 100644
--- a/ext/eokm/info.php
+++ b/ext/eokm/info.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class EokmInfo extends ExtensionInfo
{
public const KEY = "eokm";
diff --git a/ext/eokm/main.php b/ext/eokm/main.php
index 767679a1..83b98f32 100644
--- a/ext/eokm/main.php
+++ b/ext/eokm/main.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class Eokm extends Extension
{
public function get_priority(): int
diff --git a/ext/eokm/test.php b/ext/eokm/test.php
index 96fee799..b71e45e1 100644
--- a/ext/eokm/test.php
+++ b/ext/eokm/test.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class EokmTest extends ShimmiePHPUnitTestCase
{
public function testPass()
diff --git a/ext/et/info.php b/ext/et/info.php
index b2fcdef7..e641eee8 100644
--- a/ext/et/info.php
+++ b/ext/et/info.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class ETInfo extends ExtensionInfo
{
public const KEY = "et";
diff --git a/ext/et/main.php b/ext/et/main.php
index a20e4f60..00d74a4e 100644
--- a/ext/et/main.php
+++ b/ext/et/main.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class ET extends Extension
{
/** @var ETTheme */
@@ -71,7 +73,7 @@ class ET extends Extension
'shimmie' => VERSION,
'schema' => $config->get_int("db_version"),
'php' => phpversion(),
- 'db' => $database->get_driver_name() . " " . $database->get_version(),
+ 'db' => $database->get_driver_id()->value . " " . $database->get_version(),
'os' => php_uname(),
'server' => $_SERVER["SERVER_SOFTWARE"] ?? 'unknown',
],
@@ -111,7 +113,8 @@ class ET extends Extension
'branch' => $commitBranch,
'origin' => $commitOrigin,
];
- } catch (Exception $e) {
+ } catch (\Exception $e) {
+ // If we can't get git data, just skip it
}
}
diff --git a/ext/et/test.php b/ext/et/test.php
index e2cdeeb0..8e94f525 100644
--- a/ext/et/test.php
+++ b/ext/et/test.php
@@ -1,6 +1,9 @@
add_block(new Block("Information:", $this->build_data_form($yaml)));
}
- protected function build_data_form($yaml): string
+ protected function build_data_form($yaml): \MicroHTML\HTMLElement
{
- return (string)FORM(
+ return FORM(
["action"=>"https://shimmie.shishnet.org/register.php", "method"=>"POST"],
INPUT(["type"=>"hidden", "name"=>"registration_api", "value"=>"2"]),
P(
diff --git a/ext/et_server/info.php b/ext/et_server/info.php
index a19945b4..d5ad2aac 100644
--- a/ext/et_server/info.php
+++ b/ext/et_server/info.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class ETServerInfo extends ExtensionInfo
{
public const KEY = "et_server";
@@ -13,5 +15,5 @@ class ETServerInfo extends ExtensionInfo
public string $license = self::LICENSE_GPLV2;
public string $description = "Keep track of shimmie registrations";
public ?string $documentation = "For internal use";
- public string $visibility = self::VISIBLE_HIDDEN;
+ public ExtensionVisibility $visibility = ExtensionVisibility::HIDDEN;
}
diff --git a/ext/et_server/main.php b/ext/et_server/main.php
index 485e612c..2c3f2762 100644
--- a/ext/et_server/main.php
+++ b/ext/et_server/main.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
use function MicroHTML\{PRE};
class ETServer extends Extension
@@ -26,7 +28,7 @@ class ETServer extends Extension
foreach ($database->get_all("SELECT responded, data FROM registration ORDER BY responded DESC") as $row) {
$page->add_block(new Block(
$row["responded"],
- (string)PRE(["style"=>"text-align: left; overflow: scroll;"], $row["data"]),
+ PRE(["style"=>"text-align: left; overflow: scroll;"], $row["data"]),
"main",
$n++
));
diff --git a/ext/ext_manager/info.php b/ext/ext_manager/info.php
index 22242b86..78ffba3a 100644
--- a/ext/ext_manager/info.php
+++ b/ext/ext_manager/info.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class ExtManagerInfo extends ExtensionInfo
{
public const KEY = "ext_manager";
@@ -11,7 +13,7 @@ class ExtManagerInfo extends ExtensionInfo
public string $url = self::SHIMMIE_URL;
public array $authors = self::SHISH_AUTHOR;
public string $license = self::LICENSE_GPLV2;
- public string $visibility = self::VISIBLE_ADMIN;
+ public ExtensionVisibility $visibility = ExtensionVisibility::ADMIN;
public string $description = "A thing for point & click extension management";
public ?string $documentation = "Allows the admin to view a list of all extensions and enable or disable them; also allows users to view the list of activated extensions and read their documentation";
public bool $core = true;
diff --git a/ext/ext_manager/main.php b/ext/ext_manager/main.php
index 33958352..2fa7d5db 100644
--- a/ext/ext_manager/main.php
+++ b/ext/ext_manager/main.php
@@ -2,6 +2,7 @@
declare(strict_types=1);
+namespace Shimmie2;
function __extman_extcmp(ExtensionInfo $a, ExtensionInfo $b): int
{
@@ -115,9 +116,9 @@ class ExtManager extends Extension
{
$extensions = ExtensionInfo::get_all();
if (!$all) {
- $extensions = array_filter($extensions, "__extman_extactive");
+ $extensions = array_filter($extensions, "Shimmie2\__extman_extactive");
}
- usort($extensions, "__extman_extcmp");
+ usort($extensions, "Shimmie2\__extman_extcmp");
return $extensions;
}
diff --git a/ext/ext_manager/test.php b/ext/ext_manager/test.php
index 4ac9d0fb..acb56b77 100644
--- a/ext/ext_manager/test.php
+++ b/ext/ext_manager/test.php
@@ -1,6 +1,9 @@
visibility === ExtensionInfo::VISIBLE_ADMIN)
- || $extension->visibility === ExtensionInfo::VISIBLE_HIDDEN) {
+ if ((!$editable && $extension->visibility === ExtensionVisibility::ADMIN)
+ || $extension->visibility === ExtensionVisibility::HIDDEN) {
continue;
}
@@ -87,7 +89,7 @@ class ExtManagerTheme extends Themelet
$page->set_title("Extensions");
$page->set_heading("Extensions");
$page->add_block(new NavBlock());
- $page->add_block(new Block("Extension Manager", (string)$form));
+ $page->add_block(new Block("Extension Manager", $form));
}
public function display_doc(Page $page, ExtensionInfo $info)
@@ -119,6 +121,6 @@ class ExtManagerTheme extends Themelet
$page->set_title("Documentation for " . html_escape($info->name));
$page->set_heading(html_escape($info->name));
$page->add_block(new NavBlock());
- $page->add_block(new Block("Documentation", (string)$html));
+ $page->add_block(new Block("Documentation", $html));
}
}
diff --git a/ext/favorites/info.php b/ext/favorites/info.php
index b33c7fb0..d0db6ae5 100644
--- a/ext/favorites/info.php
+++ b/ext/favorites/info.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class FavoritesInfo extends ExtensionInfo
{
public const KEY = "favorites";
diff --git a/ext/favorites/main.php b/ext/favorites/main.php
index 778e7be3..8a6e72f9 100644
--- a/ext/favorites/main.php
+++ b/ext/favorites/main.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class FavoriteSetEvent extends Event
{
public int $image_id;
@@ -143,7 +145,7 @@ class Favorites extends Extension
public function onHelpPageBuilding(HelpPageBuildingEvent $event)
{
if ($event->key===HelpPages::SEARCH) {
- $event->add_block(new Block("Favorites", (string)$this->theme->get_help_html()));
+ $event->add_block(new Block("Favorites", $this->theme->get_help_html()));
}
}
diff --git a/ext/favorites/test.php b/ext/favorites/test.php
index 8b38926c..ed1247bc 100644
--- a/ext/favorites/test.php
+++ b/ext/favorites/test.php
@@ -1,6 +1,9 @@
get_int("featured_id");
if ($fid > 0) {
$image = $cache->get("featured_image_object:$fid");
- if ($image === false) {
+ if (is_null($image)) {
$image = Image::by_id($fid);
if ($image) { // make sure the object is fully populated before saving
$image->get_tag_array();
@@ -69,6 +71,15 @@ class Featured extends Extension
}
}
+ public function onImageDeletion(ImageDeletionEvent $event)
+ {
+ global $config;
+ if ($event->image->id == $config->get_int("featured_id")) {
+ $config->set_int("featured_id", 0);
+ $config->save();
+ }
+ }
+
public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event)
{
global $user;
diff --git a/ext/featured/test.php b/ext/featured/test.php
index ee27be17..ef0c4119 100644
--- a/ext/featured/test.php
+++ b/ext/featured/test.php
@@ -1,6 +1,9 @@
width, $image->height);
- return (string)DIV(
+ return DIV(
["style"=>"text-align: center;"],
A(
["href"=>make_link("post/view/{$image->id}", $query)],
diff --git a/ext/forum/info.php b/ext/forum/info.php
index 9e2d4e34..09021550 100644
--- a/ext/forum/info.php
+++ b/ext/forum/info.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class ForumInfo extends ExtensionInfo
{
public const KEY = "forum";
diff --git a/ext/forum/main.php b/ext/forum/main.php
index 79c1026b..443af4ac 100644
--- a/ext/forum/main.php
+++ b/ext/forum/main.php
@@ -1,6 +1,9 @@
execute("UPDATE forum_threads SET uptodate=now() WHERE id=:id", ['id'=>$threadID]);
}
- private function retrieve_posts(int $threadID, int $pageNumber): array
- {
- global $database, $config;
- $postsPerPage = $config->get_int('forumPostsPerPage', 15);
-
- return $database->get_all(
- "SELECT p.id, p.date, p.message, u.name as user_name, u.email AS user_email, u.class AS user_class ".
- "FROM forum_posts AS p ".
- "INNER JOIN users AS u ".
- "ON p.user_id = u.id ".
- "WHERE thread_id = :thread_id ".
- "ORDER BY p.date ASC ".
- "LIMIT :limit OFFSET :offset ",
- ["thread_id"=>$threadID, "offset"=>($pageNumber - 1) * $postsPerPage, "limit"=>$postsPerPage]
- );
- }
-
private function delete_thread(int $threadID): void
{
global $database;
diff --git a/ext/forum/theme.php b/ext/forum/theme.php
index f3c316b2..9e7bab4e 100644
--- a/ext/forum/theme.php
+++ b/ext/forum/theme.php
@@ -1,6 +1,9 @@
formatted;
-
+ $message = send_event(new TextFormattingEvent($message))->formatted;
$message = str_replace('\n\r', '
', $message);
$message = str_replace('\r\n', '
', $message);
$message = str_replace('\n', '
', $message);
diff --git a/ext/four_oh_four/info.php b/ext/four_oh_four/info.php
index 943fe5ef..e40a5ffe 100644
--- a/ext/four_oh_four/info.php
+++ b/ext/four_oh_four/info.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class FourOhFourInfo extends ExtensionInfo
{
public const KEY = "four_oh_four";
@@ -11,7 +13,7 @@ class FourOhFourInfo extends ExtensionInfo
public string $url = self::SHIMMIE_URL;
public array $authors = self::SHISH_AUTHOR;
public string $license = self::LICENSE_GPLV2;
- public string $visibility = self::VISIBLE_HIDDEN;
+ public ExtensionVisibility $visibility = ExtensionVisibility::HIDDEN;
public string $description = "If no other extension puts anything onto the page, show 404";
public bool $core = true;
}
diff --git a/ext/four_oh_four/main.php b/ext/four_oh_four/main.php
index 241a2967..836c8f24 100644
--- a/ext/four_oh_four/main.php
+++ b/ext/four_oh_four/main.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class FourOhFour extends Extension
{
public function onPageRequest(PageRequestEvent $event)
diff --git a/ext/four_oh_four/test.php b/ext/four_oh_four/test.php
index a6f2a1a1..5c71a839 100644
--- a/ext/four_oh_four/test.php
+++ b/ext/four_oh_four/test.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class FourOhFourTest extends ShimmiePHPUnitTestCase
{
public function test404Handler()
diff --git a/ext/google_analytics/info.php b/ext/google_analytics/info.php
index e0c4401a..af4f5c9d 100644
--- a/ext/google_analytics/info.php
+++ b/ext/google_analytics/info.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class GoogleAnalyticsInfo extends ExtensionInfo
{
public const KEY = "google_analytics";
diff --git a/ext/google_analytics/main.php b/ext/google_analytics/main.php
index 410ff0b4..a9759374 100644
--- a/ext/google_analytics/main.php
+++ b/ext/google_analytics/main.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class GoogleAnalytics extends Extension
{
# Add analytics to config
diff --git a/ext/graphql/info.php b/ext/graphql/info.php
new file mode 100644
index 00000000..c6bfce05
--- /dev/null
+++ b/ext/graphql/info.php
@@ -0,0 +1,17 @@
+tags;
+ $_POST['tag_edit__source'] = $metadata->source;
+ $image = Image::by_id($post_id);
+ if (!$image->is_locked() || $user->can(Permissions::EDIT_IMAGE_LOCK)) {
+ send_event(new ImageInfoSetEvent($image));
+ }
+ return Image::by_id($post_id);
+ }
+}
+
+class GraphQL extends Extension
+{
+ public static function get_schema(): Schema
+ {
+ global $_tracer;
+ $_tracer->begin("Create Schema");
+ $schema = new \GQLA\Schema();
+ $_tracer->end(null);
+ return $schema;
+ }
+
+ private function cors(): void
+ {
+ global $config;
+ $pat = $config->get_string("graphql_cors_pattern");
+
+ if ($pat && isset($_SERVER['HTTP_ORIGIN'])) {
+ if (preg_match("#$pat#", $_SERVER['HTTP_ORIGIN'])) {
+ header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
+ header('Access-Control-Allow-Credentials: true');
+ header('Access-Control-Max-Age: 86400');
+ }
+ }
+
+ if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
+ if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) {
+ header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
+ }
+ if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) {
+ header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");
+ }
+ exit(0);
+ }
+ }
+
+ public function onInitExt(InitExtEvent $event)
+ {
+ global $config;
+ $config->set_default_string('graphql_cors_pattern', "");
+ $config->set_default_bool('graphql_debug', false);
+ }
+
+ public function onPageRequest(PageRequestEvent $event)
+ {
+ global $config, $page;
+ if ($event->page_matches("graphql")) {
+ $this->cors();
+ $t1 = ftime();
+ $server = new StandardServer([
+ 'schema' => $this->get_schema(),
+ ]);
+ $t2 = ftime();
+ $resp = $server->executeRequest();
+ if ($config->get_bool("graphql_debug")) {
+ $debug = DebugFlag::INCLUDE_DEBUG_MESSAGE | DebugFlag::RETHROW_INTERNAL_EXCEPTIONS;
+ $body = $resp->toArray($debug);
+ } else {
+ $body = $resp->toArray();
+ }
+ $t3 = ftime();
+ $body['stats'] = get_debug_info_arr();
+ $body['stats']['graphql_schema_time'] = round($t2 - $t1, 2);
+ $body['stats']['graphql_execute_time'] = round($t3 - $t2, 2);
+ // sleep(1);
+ $page->set_mode(PageMode::DATA);
+ $page->set_mime("application/json");
+ $page->set_data(\json_encode($body, JSON_UNESCAPED_UNICODE));
+ }
+ if ($event->page_matches("graphql_upload")) {
+ $this->cors();
+ $page->set_mode(PageMode::DATA);
+ $page->set_mime("application/json");
+ $page->set_data(\json_encode(self::handle_uploads()));
+ }
+ }
+
+ private static function handle_uploads(): array
+ {
+ global $user;
+
+ if (!$user->can(Permissions::CREATE_IMAGE)) {
+ return ["error" => "User cannot create posts"];
+ }
+
+ $common_tags = $_POST['common_tags'];
+ $common_source = $_POST['common_source'];
+
+ $results = [];
+ for ($n=0; $n<100; $n++) {
+ if (empty($_POST["url$n"]) && empty($_FILES["data$n"])) {
+ break;
+ }
+ if (isset($_FILES["data$n"]) && ($_FILES["data$n"]["size"] == 0 || $_FILES["data$n"]["error"] == UPLOAD_ERR_NO_FILE)) {
+ break;
+ }
+ try {
+ $results[] = self::handle_upload($n, $common_tags, $common_source);
+ } catch(\Exception $e) {
+ $results[] = ["error" => $e->getMessage()];
+ }
+ }
+ return ["results" => $results];
+ }
+
+ private static function handle_upload(int $n, string $common_tags, string $common_source): array
+ {
+ if (!empty($_POST["url$n"])) {
+ return ["error" => "URLs not handled yet"];
+ $tmpname = "...";
+ $filename = "...";
+ } else {
+ $ec = $_FILES["data$n"]["error"];
+ switch($ec) {
+ case UPLOAD_ERR_OK:
+ $tmpname = $_FILES["data$n"]["tmp_name"];
+ $filename = $_FILES["data$n"]["name"];
+ break;
+ case UPLOAD_ERR_INI_SIZE:
+ return ["error" => "File larger than PHP can handle"];
+ default:
+ return ["error" => "Mystery error: $ec"];
+ }
+ }
+
+ $tags = trim($common_tags . " " . $_POST["tags$n"]);
+ $source = $common_source;
+ if (!empty($_POST["source$n"])) {
+ $source = $_POST["source$n"];
+ }
+ $event = send_event(new DataUploadEvent($tmpname, [
+ 'filename' => $filename,
+ 'tags' => Tag::explode($tags),
+ 'source' => $source,
+ ]));
+
+ return ["image_id" => $event->image_id];
+ }
+
+ public function onCommand(CommandEvent $event)
+ {
+ if ($event->cmd == "help") {
+ print "\tgraphql
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
I.E: \"posted:2014-01-01\", \"id:>=500\" etc.
+ public ?string $documentation = " etc.
'.$st.' ⓘ
'.$short_wiki_description;
$page->add_block(new Block(null, $short_wiki_description, "main", 0, "short-wiki-description"));
@@ -291,8 +292,8 @@ and of course start organising your images :-)
source=http://google.com/
- source=https:///google.com/
+ posted>=07-19-2019
- posted>=2019-07-19
+
diff --git a/ext/ipban/info.php b/ext/ipban/info.php
index 1c10f540..740e3915 100644
--- a/ext/ipban/info.php
+++ b/ext/ipban/info.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class IPBanInfo extends ExtensionInfo
{
public const KEY = "ipban";
diff --git a/ext/ipban/main.php b/ext/ipban/main.php
index 90a14e2f..e8c6c33b 100644
--- a/ext/ipban/main.php
+++ b/ext/ipban/main.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
use MicroCRUD\ActionColumn;
use MicroCRUD\InetColumn;
use MicroCRUD\StringColumn;
@@ -105,7 +107,7 @@ class IPBan extends Extension
// Get lists of banned IPs and banned networks
$ips = $cache->get("ip_bans");
$networks = $cache->get("network_bans");
- if ($ips === false || $networks === false) {
+ if (is_null($ips) || is_null($networks)) {
$rows = $database->get_pairs("
SELECT ip, id
FROM bans
@@ -168,7 +170,7 @@ class IPBan extends Extension
$event->user->class = $_shm_user_classes["ghost"];
}
} else {
- header("HTTP/1.0 403 Forbidden");
+ header("HTTP/1.1 403 Forbidden");
print "$msg";
exit;
}
diff --git a/ext/ipban/test.php b/ext/ipban/test.php
index bc2c2765..4dbb9f1e 100644
--- a/ext/ipban/test.php
+++ b/ext/ipban/test.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class IPBanTest extends ShimmiePHPUnitTestCase
{
# FIXME: test that the IP is actually banned
diff --git a/ext/ipban/theme.php b/ext/ipban/theme.php
index 392b0929..996b40a7 100644
--- a/ext/ipban/theme.php
+++ b/ext/ipban/theme.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class IPBanTheme extends Themelet
{
public function display_bans(Page $page, $table, $paginator)
diff --git a/ext/link_image/info.php b/ext/link_image/info.php
index d87e3598..c0cedfe5 100644
--- a/ext/link_image/info.php
+++ b/ext/link_image/info.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class LinkImageInfo extends ExtensionInfo
{
public const KEY = "link_image";
diff --git a/ext/link_image/main.php b/ext/link_image/main.php
index 17033c96..315ed858 100644
--- a/ext/link_image/main.php
+++ b/ext/link_image/main.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class LinkImage extends Extension
{
/** @var LinkImageTheme */
diff --git a/ext/link_image/test.php b/ext/link_image/test.php
index 7d2a1b04..5681bf12 100644
--- a/ext/link_image/test.php
+++ b/ext/link_image/test.php
@@ -1,6 +1,9 @@
page_to_text(), $matches);
- $this->assertTrue(count($matches) > 0);
+ $this->assertNotEmpty($matches);
$page = $this->get_page($matches[1]);
$this->assertEquals("Post $image_id: pie", $page->title);
}
diff --git a/ext/link_image/theme.php b/ext/link_image/theme.php
index 9ed66b2a..6491de24 100644
--- a/ext/link_image/theme.php
+++ b/ext/link_image/theme.php
@@ -1,6 +1,9 @@
set_default_bool("log_console_access", true);
+ $config->set_default_bool("log_console_colour", true);
+ $config->set_default_int("log_console_level", SCORE_LOG_INFO);
+ }
+
+ public function onPageRequest(PageRequestEvent $event)
+ {
+ global $config, $page;
+
+ if (
+ $config->get_bool("log_console_access") &&
+ isset($_SERVER['REQUEST_METHOD']) &&
+ isset($_SERVER['REQUEST_URI'])
+ ) {
+ $this->log(new LogEvent(
+ "access",
+ SCORE_LOG_INFO,
+ "{$_SERVER['REQUEST_METHOD']} {$_SERVER['REQUEST_URI']}"
+ ));
+ }
+
+ /*
+ if ($event->page_matches("log_test")) {
+ log_debug("log_console", "Hello debug!");
+ log_info("log_console", "Hello info!");
+ log_warning("log_console", "Hello warning!");
+ $page->set_mode(PageMode::DATA);
+ $page->set_data("You should see something in the log\n");
+ }
+ */
+ }
+
+ public function onLog(LogEvent $event)
+ {
+ global $config;
+ if ($event->priority >= $config->get_int("log_console_level")) {
+ $this->log($event);
+ }
+ }
+
+ private function log(LogEvent $event)
+ {
+ global $config, $user;
+ // TODO: colour based on event->priority
+ $username = ($user && $user->name) ? $user->name : "Anonymous";
+ $str = join(" ", [
+ date(DATE_ISO8601),
+ get_real_ip(),
+ $event->section,
+ $username,
+ $event->message
+ ]);
+ if ($config->get_bool("log_console_colour")) {
+ if ($event->priority >= SCORE_LOG_WARNING) {
+ // red
+ $COL = "\033[0;31m";
+ } elseif ($event->priority >= SCORE_LOG_INFO) {
+ // default
+ $COL = "";
+ } elseif ($event->priority >= SCORE_LOG_NOTSET) {
+ // blue
+ $COL = "\033[0;34m";
+ } else {
+ // priority < 0 ???
+ // magenta
+ $COL = "\033[0;35m";
+ }
+ $str = "$COL$str\033[0m\n";
+ } else {
+ $str = "$str\n";
+ }
+ if (!defined("UNITTEST") && PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg') {
+ $fp = fopen("/dev/tty", "w");
+ if ($fp) {
+ fwrite($fp, $str);
+ fclose($fp);
+ }
+ }
+ }
+}
diff --git a/ext/log_db/info.php b/ext/log_db/info.php
index f221a1ab..0b0eeeb2 100644
--- a/ext/log_db/info.php
+++ b/ext/log_db/info.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class LogDatabaseInfo extends ExtensionInfo
{
public const KEY = "log_db";
@@ -11,5 +13,5 @@ class LogDatabaseInfo extends ExtensionInfo
public string $url = self::SHIMMIE_URL;
public array $authors = self::SHISH_AUTHOR;
public string $description = "Keep a record of SCore events (in the database).";
- public string $visibility = self::VISIBLE_ADMIN;
+ public ExtensionVisibility $visibility = ExtensionVisibility::ADMIN;
}
diff --git a/ext/log_db/main.php b/ext/log_db/main.php
index 440f516f..e7848631 100644
--- a/ext/log_db/main.php
+++ b/ext/log_db/main.php
@@ -2,12 +2,15 @@
declare(strict_types=1);
+namespace Shimmie2;
+
use MicroHTML\HTMLElement;
use MicroCRUD\ActionColumn;
use MicroCRUD\Column;
use MicroCRUD\DateTimeColumn;
use MicroCRUD\TextColumn;
use MicroCRUD\Table;
+
use function MicroHTML\A;
use function MicroHTML\SPAN;
use function MicroHTML\emptyHTML;
@@ -47,7 +50,7 @@ class ActorColumn extends Column
public function get_sql_filter(): string
{
- $driver = $this->table->db->getAttribute(PDO::ATTR_DRIVER_NAME);
+ $driver = $this->table->db->getAttribute(\PDO::ATTR_DRIVER_NAME);
switch ($driver) {
case "pgsql":
return "((LOWER(username) = LOWER(:{$this->name}_0)) OR (address && cast(:{$this->name}_1 as inet)))";
@@ -161,11 +164,21 @@ class MessageColumn extends Column
{
$c = "#000";
switch ($row['priority']) {
- case SCORE_LOG_DEBUG: $c = "#999"; break;
- case SCORE_LOG_INFO: $c = "#000"; break;
- case SCORE_LOG_WARNING: $c = "#800"; break;
- case SCORE_LOG_ERROR: $c = "#C00"; break;
- case SCORE_LOG_CRITICAL: $c = "#F00"; break;
+ case SCORE_LOG_DEBUG:
+ $c = "#999";
+ break;
+ case SCORE_LOG_INFO:
+ $c = "#000";
+ break;
+ case SCORE_LOG_WARNING:
+ $c = "#800";
+ break;
+ case SCORE_LOG_ERROR:
+ $c = "#C00";
+ break;
+ case SCORE_LOG_CRITICAL:
+ $c = "#F00";
+ break;
}
return SPAN(["style"=>"color: $c"], rawHTML($this->scan_entities($row[$this->name])));
}
diff --git a/ext/log_db/test.php b/ext/log_db/test.php
index 04a50040..6185d4c6 100644
--- a/ext/log_db/test.php
+++ b/ext/log_db/test.php
@@ -1,6 +1,9 @@
set_default_string("log_logstash_host", "127.0.0.1:1234");
+ }
+
public function onLog(LogEvent $event)
{
global $user;
@@ -26,7 +34,7 @@ class LogLogstash extends Extension
];
$this->send_data($data);
- } catch (Exception $e) {
+ } catch (\Exception $e) {
// we can't log that logging is broken
}
}
@@ -50,7 +58,7 @@ class LogLogstash extends Extension
}
fwrite($fp, json_encode($data));
fclose($fp);
- } catch (Exception $e) {
+ } catch (\Exception $e) {
// we can't log that logging is broken
}
}
diff --git a/ext/log_net/info.php b/ext/log_net/info.php
index c9ed2e14..dca447e3 100644
--- a/ext/log_net/info.php
+++ b/ext/log_net/info.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class LogNetInfo extends ExtensionInfo
{
public const KEY = "log_net";
@@ -11,5 +13,5 @@ class LogNetInfo extends ExtensionInfo
public string $url = self::SHIMMIE_URL;
public array $authors = self::SHISH_AUTHOR;
public string $description = "Send log events to a network port.";
- public string $visibility = self::VISIBLE_ADMIN;
+ public ExtensionVisibility $visibility = ExtensionVisibility::ADMIN;
}
diff --git a/ext/log_net/main.php b/ext/log_net/main.php
index b5b4d90a..7faa07ec 100644
--- a/ext/log_net/main.php
+++ b/ext/log_net/main.php
@@ -2,10 +2,18 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class LogNet extends Extension
{
private int $count = 0;
+ public function onInitExt(InitExtEvent $event)
+ {
+ global $config;
+ $config->set_default_string("log_net_host", "127.0.0.1:35353");
+ }
+
public function onLog(LogEvent $event)
{
global $user;
@@ -26,7 +34,7 @@ class LogNet extends Extension
private function msg($data)
{
global $config;
- $host = $config->get_string("log_net_host", "127.0.0.1:35353");
+ $host = $config->get_string("log_net_host");
if (!$host) {
return;
@@ -42,7 +50,7 @@ class LogNet extends Extension
}
fwrite($fp, "$data\n");
fclose($fp);
- } catch (Exception $e) {
+ } catch (\Exception $e) {
/* logging errors shouldn't break everything */
}
}
diff --git a/ext/media/config.php b/ext/media/config.php
index 3b795fa2..7427aded 100644
--- a/ext/media/config.php
+++ b/ext/media/config.php
@@ -1,6 +1,9 @@
image = $image;
- $this->file_name = warehouse_path(Image::IMAGE_DIR, $image->hash);
- $this->mime = strtolower($image->get_mime());
}
}
diff --git a/ext/media/info.php b/ext/media/info.php
index 749b8d99..5490639e 100644
--- a/ext/media/info.php
+++ b/ext/media/info.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class MediaInfo extends ExtensionInfo
{
public const KEY = "media";
@@ -13,5 +15,5 @@ class MediaInfo extends ExtensionInfo
public string $license = self::LICENSE_WTFPL;
public string $description = "Provides common functions and settings used for media operations.";
public bool $core = true;
- public string $visibility = self::VISIBLE_HIDDEN;
+ public ExtensionVisibility $visibility = ExtensionVisibility::HIDDEN;
}
diff --git a/ext/media/main.php b/ext/media/main.php
index 3fd8b3af..f7451f41 100644
--- a/ext/media/main.php
+++ b/ext/media/main.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
require_once "config.php";
require_once "events.php";
require_once "media_engine.php";
@@ -270,12 +272,12 @@ class Media extends Extension
{
if ($event->image->width && $event->image->height && $event->image->length) {
$s = ((int)($event->image->length / 100))/10;
- $event->replace('$size', "{$event->image->width}x{$event->image->height}, ${s}s");
+ $event->replace('$size', "{$event->image->width}x{$event->image->height}, {$s}s");
} elseif ($event->image->width && $event->image->height) {
$event->replace('$size', "{$event->image->width}x{$event->image->height}");
} elseif ($event->image->length) {
$s = ((int)($event->image->length / 100))/10;
- $event->replace('$size', "${s}s");
+ $event->replace('$size', "{$s}s");
}
}
@@ -573,7 +575,7 @@ class Media extends Extension
$input_ext = self::determine_ext($input_mime);
- $file_arg = "${input_ext}:\"${input_path}[0]\"";
+ $file_arg = "{$input_ext}:\"{$input_path}[0]\"";
if ($resize_type===Media::RESIZE_TYPE_FIT_BLUR_PORTRAIT) {
if ($new_height>$new_width) {
@@ -586,16 +588,16 @@ class Media extends Extension
switch ($resize_type) {
case Media::RESIZE_TYPE_FIT:
case Media::RESIZE_TYPE_STRETCH:
- $args .= "${file_arg} ${resize_arg} ${new_width}x${new_height}${resize_suffix} -background ${bg} -flatten ";
+ $args .= "{$file_arg} {$resize_arg} {$new_width}x{$new_height}{$resize_suffix} -background {$bg} -flatten ";
break;
case Media::RESIZE_TYPE_FILL:
- $args .= "${file_arg} ${resize_arg} ${new_width}x${new_height}\^ -background ${bg} -flatten -gravity center -extent ${new_width}x${new_height} ";
+ $args .= "{$file_arg} {$resize_arg} {$new_width}x{$new_height}\^ -background {$bg} -flatten -gravity center -extent {$new_width}x{$new_height} ";
break;
case Media::RESIZE_TYPE_FIT_BLUR:
$blur_size = max(ceil(max($new_width, $new_height) / 25), 5);
- $args .= "${file_arg} ".
- "\( -clone 0 -auto-orient -resize ${new_width}x${new_height}\^ -background ${bg} -flatten -gravity center -fill black -colorize 50% -extent ${new_width}x${new_height} -blur 0x${blur_size} \) ".
- "\( -clone 0 -auto-orient -resize ${new_width}x${new_height} \) ".
+ $args .= "{$file_arg} ".
+ "\( -clone 0 -auto-orient -resize {$new_width}x{$new_height}\^ -background {$bg} -flatten -gravity center -fill black -colorize 50% -extent {$new_width}x{$new_height} -blur 0x{$blur_size} \) ".
+ "\( -clone 0 -auto-orient -resize {$new_width}x{$new_height} \) ".
"-delete 0 -gravity center -compose over -composite";
break;
}
@@ -611,7 +613,7 @@ class Media extends Extension
}
- $args .= " -quality ${output_quality} ";
+ $args .= " -quality {$output_quality} ";
$output_ext = self::determine_ext($output_mime);
@@ -790,8 +792,7 @@ class Media extends Extension
imagedestroy($image_resized);
$image_resized = $new_image;
- break;
-
+ break;
}
switch ($output_mime) {
@@ -903,9 +904,9 @@ class Media extends Extension
if ($this->get_version(MediaConfig::VERSION) < 2) {
$database->execute("ALTER TABLE images ADD COLUMN image BOOLEAN NULL");
- switch ($database->get_driver_name()) {
- case DatabaseDriver::PGSQL:
- case DatabaseDriver::SQLITE:
+ switch ($database->get_driver_id()) {
+ case DatabaseDriverID::PGSQL:
+ case DatabaseDriverID::SQLITE:
$database->execute('CREATE INDEX images_image_idx ON images(image) WHERE image IS NOT NULL');
break;
default:
diff --git a/ext/media/media_engine.php b/ext/media/media_engine.php
index 3dff0e17..191d3259 100644
--- a/ext/media/media_engine.php
+++ b/ext/media/media_engine.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
abstract class MediaEngine
{
public const GD = "gd";
diff --git a/ext/media/theme.php b/ext/media/theme.php
index efb9506a..00ec1922 100644
--- a/ext/media/theme.php
+++ b/ext/media/theme.php
@@ -1,6 +1,9 @@
assertTrue(false, "Should've had an exception");
+ $this->fail("Should've had an exception");
} catch (TagSetException $e) {
$this->assertTrue(true);
}
diff --git a/ext/not_a_tag/theme.php b/ext/not_a_tag/theme.php
index 259d7c74..7c23a7a3 100644
--- a/ext/not_a_tag/theme.php
+++ b/ext/not_a_tag/theme.php
@@ -1,6 +1,9 @@
image_id);
+ }
+
+ #[Field]
+ public function user(): User
+ {
+ return User::by_id($this->user_id);
+ }
+
+ #[Field(extends: "Post")]
+ public static function score(Image $post): int
+ {
+ global $database;
+ if ($post->score ?? null) {
+ return $post->score;
+ }
+ return $database->get_one(
+ "SELECT sum(score) FROM numeric_score_votes WHERE image_id=:image_id",
+ ['image_id'=>$post->id]
+ ) ?? 0;
+ }
+
+ #[Field(extends: "Post", type: "[NumericScoreVote!]!")]
+ public static function votes(Image $post): array
+ {
+ global $database;
+ $rows = $database->get_all(
+ "SELECT * FROM numeric_score_votes WHERE image_id=:image_id",
+ ['image_id'=>$post->id]
+ );
+ $votes = [];
+ foreach ($rows as $row) {
+ $nsv = new NumericScoreVote();
+ $nsv->image_id = $row["image_id"];
+ $nsv->user_id = $row["user_id"];
+ $nsv->score = $row["score"];
+ $votes[] = $nsv;
+ }
+ return $votes;
+ }
+
+ #[Field(extends: "Post", type: "Int!")]
+ public static function my_vote(Image $post): int
+ {
+ global $database, $user;
+ return $database->get_one(
+ "SELECT score FROM numeric_score_votes WHERE image_id=:image_id AND user_id=:user_id",
+ ['image_id'=>$post->id, "user_id"=>$user->id]
+ ) ?? 0;
+ }
+
+ #[Mutation]
+ public static function create_vote(int $post_id, int $score): bool
+ {
+ global $user;
+ if ($user->can(Permissions::CREATE_VOTE)) {
+ assert($score == 0 || $score == -1 || $score == 1);
+ send_event(new NumericScoreSetEvent($post_id, $user, $score));
+ return true;
+ }
+ return false;
+ }
+}
+
class NumericScoreSetEvent extends Event
{
public int $image_id;
@@ -25,7 +107,7 @@ class NumericScore extends Extension
public function onDisplayingImage(DisplayingImageEvent $event)
{
global $user;
- if (!$user->is_anonymous()) {
+ if ($user->can(Permissions::CREATE_VOTE)) {
$this->theme->get_voter($event->image);
}
}
@@ -68,18 +150,10 @@ class NumericScore extends Extension
}
die($html);
} elseif ($event->page_matches("numeric_score_vote") && $user->check_auth_token()) {
- if (!$user->is_anonymous()) {
+ if ($user->can(Permissions::CREATE_VOTE)) {
$image_id = int_escape($_POST['image_id']);
- $char = $_POST['vote'];
- $score = null;
- if ($char == "up") {
- $score = 1;
- } elseif ($char == "null") {
- $score = 0;
- } elseif ($char == "down") {
- $score = -1;
- }
- if (!is_null($score) && $image_id>0) {
+ $score = int_escape($_POST['vote']);
+ if (($score == -1 || $score == 0 || $score == 1) && $image_id>0) {
send_event(new NumericScoreSetEvent($image_id, $user, $score));
}
$page->set_mode(PageMode::REDIRECT);
@@ -145,7 +219,7 @@ class NumericScore extends Extension
$dte = [$totaldate, $year, "\\y\\e\\a\\r\=Y", "year"];
} else {
// this should never happen due to the fact that the page event is already matched against earlier.
- throw new UnexpectedValueException("Error: Invalid page event.");
+ throw new \UnexpectedValueException("Error: Invalid page event.");
}
$sql .= " AND NOT numeric_score=0 ORDER BY numeric_score DESC LIMIT :limit OFFSET 0";
@@ -292,7 +366,7 @@ class NumericScore extends Extension
if (preg_match("/^vote[=|:](up|down|remove)$/", $event->term, $matches)) {
global $user;
$score = ($matches[1] == "up" ? 1 : ($matches[1] == "down" ? -1 : 0));
- if (!$user->is_anonymous()) {
+ if ($user->can(Permissions::CREATE_VOTE)) {
send_event(new NumericScoreSetEvent($event->image_id, $user, $score));
}
}
diff --git a/ext/numeric_score/test.php b/ext/numeric_score/test.php
index fe75ed16..44662acc 100644
--- a/ext/numeric_score/test.php
+++ b/ext/numeric_score/test.php
@@ -1,6 +1,9 @@
";
diff --git a/ext/ouroboros_api/info.php b/ext/ouroboros_api/info.php
index 664125eb..4c19d24a 100644
--- a/ext/ouroboros_api/info.php
+++ b/ext/ouroboros_api/info.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class OuroborosAPIInfo extends ExtensionInfo
{
public const KEY = "ouroboros_api";
diff --git a/ext/ouroboros_api/main.php b/ext/ouroboros_api/main.php
index 5d1b8884..07ec46c2 100644
--- a/ext/ouroboros_api/main.php
+++ b/ext/ouroboros_api/main.php
@@ -2,6 +2,7 @@
declare(strict_types=1);
+namespace Shimmie2;
class _SafeOuroborosImage
{
@@ -111,7 +112,7 @@ class OuroborosPost extends _SafeOuroborosImage
* Mainly just acts as a wrapper and validation layer
* @noinspection PhpMissingParentConstructorInspection
*/
- public function __construct(array $post, string $md5 = '')
+ public function __construct(array $post)
{
if (array_key_exists('tags', $post)) {
// implode(explode()) to resolve aliases and sanitise
@@ -170,10 +171,7 @@ class OuroborosPost extends _SafeOuroborosImage
$this->is_note_locked = $post['is_note_locked'];
}
if (array_key_exists('parent_id', $post)) {
- $this->parent_id = filter_var(
- $post['parent_id'],
- FILTER_SANITIZE_NUMBER_INT
- );
+ $this->parent_id = int_escape($post['parent_id']);
}
}
}
@@ -385,8 +383,7 @@ class OuroborosAPI extends Extension
}
$meta['extension'] = pathinfo($meta['filename'], PATHINFO_EXTENSION);
try {
- $upload = new DataUploadEvent($meta['file'], $meta);
- send_event($upload);
+ send_event(new DataUploadEvent($meta['file'], $meta));
$image = Image::by_hash($meta['hash']);
if (!is_null($image)) {
$this->sendResponse(200, make_link('post/view/' . $image->id), true);
@@ -520,7 +517,7 @@ class OuroborosAPI extends Extension
$response = json_encode($response);
} elseif ($this->type == 'xml') {
// Seriously, XML sucks...
- $xml = new XMLWriter();
+ $xml = new \XMLWriter();
$xml->openMemory();
$xml->startDocument('1.0', 'utf-8');
$xml->startElement('response');
@@ -545,14 +542,14 @@ class OuroborosAPI extends Extension
if ($this->type == 'json') {
$response = json_encode($data);
} elseif ($this->type == 'xml') {
- $xml = new XMLWriter();
+ $xml = new \XMLWriter();
$xml->openMemory();
$xml->startDocument('1.0', 'utf-8');
if (array_key_exists(0, $data)) {
$xml->startElement($type . 's');
if ($type == 'post') {
- $xml->writeAttribute('count', count($data));
- $xml->writeAttribute('offset', $offset);
+ $xml->writeAttribute('count', (string)count($data));
+ $xml->writeAttribute('offset', (string)$offset);
}
if ($type == 'tag') {
$xml->writeAttribute('type', 'array');
@@ -571,7 +568,7 @@ class OuroborosAPI extends Extension
$page->set_data($response);
}
- private function createItemXML(XMLWriter $xml, string $type, $item)
+ private function createItemXML(\XMLWriter $xml, string $type, $item)
{
$xml->startElement($type);
foreach ($item as $key => $val) {
diff --git a/ext/pm/info.php b/ext/pm/info.php
index 99ad2c3b..567d7cfa 100644
--- a/ext/pm/info.php
+++ b/ext/pm/info.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class PrivMsgInfo extends ExtensionInfo
{
public const KEY = "pm";
diff --git a/ext/pm/main.php b/ext/pm/main.php
index 4198b610..6d022eb3 100644
--- a/ext/pm/main.php
+++ b/ext/pm/main.php
@@ -2,6 +2,13 @@
declare(strict_types=1);
+namespace Shimmie2;
+
+use GQLA\Type;
+use GQLA\Field;
+use GQLA\Query;
+use GQLA\Mutation;
+
class SendPMEvent extends Event
{
public PM $pm;
@@ -13,40 +20,119 @@ class SendPMEvent extends Event
}
}
+#[Type(name: "PrivateMessage")]
class PM
{
- public int $id;
+ public int $id = -1;
public int $from_id;
public string $from_ip;
public int $to_id;
- /** @var mixed */
- public $sent_date;
+ public mixed $sent_date;
+ #[Field]
public string $subject;
+ #[Field]
public string $message;
+ #[Field]
public bool $is_read;
- public function __construct($from_id=0, string $from_ip="0.0.0.0", int $to_id=0, string $subject="A Message", string $message="Some Text", bool $read=false)
+ #[Field]
+ public function from(): User
{
- # PHP: the P stands for "really", the H stands for "awful" and the other P stands for "language"
- if (is_array($from_id)) {
- $a = $from_id;
- $this->id = (int)$a["id"];
- $this->from_id = (int)$a["from_id"];
- $this->from_ip = $a["from_ip"];
- $this->to_id = (int)$a["to_id"];
- $this->sent_date = $a["sent_date"];
- $this->subject = $a["subject"];
- $this->message = $a["message"];
- $this->is_read = bool_escape($a["is_read"]);
- } else {
- $this->id = -1;
- $this->from_id = $from_id;
- $this->from_ip = $from_ip;
- $this->to_id = $to_id;
- $this->subject = $subject;
- $this->message = $message;
- $this->is_read = $read;
+ return User::by_id($this->from_id);
+ }
+
+ #[Field(name: "pm_id")]
+ public function graphql_oid(): int
+ {
+ return $this->id;
+ }
+ #[Field(name: "id")]
+ public function graphql_guid(): string
+ {
+ return "pm:{$this->id}";
+ }
+
+ public function __construct(
+ int $from_id,
+ string $from_ip,
+ int $to_id,
+ string $subject,
+ string $message,
+ bool $is_read = false
+ ) {
+ $this->from_id = $from_id;
+ $this->from_ip = $from_ip;
+ $this->to_id = $to_id;
+ $this->subject = $subject;
+ $this->message = $message;
+ $this->is_read = $is_read;
+ }
+
+ public static function from_row(array $row): PM
+ {
+ $pm = new PM(
+ (int)$row["from_id"],
+ $row["from_ip"],
+ (int)$row["to_id"],
+ $row["subject"],
+ $row["message"],
+ bool_escape($row["is_read"]),
+ );
+ $pm->id = (int)$row["id"];
+ $pm->sent_date = $row["sent_date"];
+ return $pm;
+ }
+
+ #[Field(extends: "User", name: "private_messages", type: "[PrivateMessage!]")]
+ public static function get_pms(User $duser): ?array
+ {
+ global $database, $user;
+
+ if (!$user->can(Permissions::READ_PM)) {
+ return null;
}
+ if (($duser->id != $user->id) && !$user->can(Permissions::VIEW_OTHER_PMS)) {
+ return null;
+ }
+
+ $pms = [];
+ $arr = $database->get_all(
+ "SELECT * FROM private_message WHERE to_id = :to_id ORDER BY sent_date DESC",
+ ["to_id" => $duser->id]
+ );
+ foreach ($arr as $pm) {
+ $pms[] = PM::from_row($pm);
+ }
+ return $pms;
+ }
+
+ #[Field(extends: "User", name: "private_message_unread_count")]
+ public static function count_unread_pms(User $duser): ?int
+ {
+ global $database, $user;
+
+ if (!$user->can(Permissions::READ_PM)) {
+ return null;
+ }
+ if (($duser->id != $user->id) && !$user->can(Permissions::VIEW_OTHER_PMS)) {
+ return null;
+ }
+
+ return (int)$database->get_one(
+ "SELECT COUNT(*) FROM private_message WHERE to_id = :to_id AND is_read = :is_read",
+ ["is_read" => false, "to_id" => $duser->id]
+ );
+ }
+
+ #[Mutation(name: "create_private_message")]
+ public static function send_pm(int $to_user_id, string $subject, string $message): bool
+ {
+ global $user;
+ if (!$user->can(Permissions::SEND_PM)) {
+ return false;
+ }
+ send_event(new SendPMEvent(new PM($user->id, get_real_ip(), $to_user_id, $subject, $message)));
+ return true;
}
}
@@ -120,8 +206,9 @@ class PrivMsg extends Extension
global $page, $user;
$duser = $event->display_user;
if (!$user->is_anonymous() && !$duser->is_anonymous()) {
- if (($user->id == $duser->id) || $user->can(Permissions::VIEW_OTHER_PMS)) {
- $this->theme->display_pms($page, $this->get_pms($duser));
+ $pms = PM::get_pms($duser);
+ if (!is_null($pms)) {
+ $this->theme->display_pms($page, $pms);
}
if ($user->id != $duser->id) {
$this->theme->display_composer($page, $user, $duser);
@@ -146,7 +233,7 @@ class PrivMsg extends Extension
$database->execute("UPDATE private_message SET is_read=true WHERE id = :id", ["id" => $pm_id]);
$cache->delete("pm-count-{$user->id}");
}
- $this->theme->display_message($page, $from_user, $user, new PM($pm));
+ $this->theme->display_message($page, $from_user, $user, PM::from_row($pm));
} else {
$this->theme->display_permission_denied();
}
@@ -206,33 +293,12 @@ class PrivMsg extends Extension
log_info("pm", "Sent PM to User #{$event->pm->to_id}");
}
-
- private function get_pms(User $user): array
- {
- global $database;
-
- $arr = $database->get_all(
- "
- SELECT private_message.*,user_from.name AS from_name
- FROM private_message
- JOIN users AS user_from ON user_from.id=from_id
- WHERE to_id = :toid
- ORDER BY sent_date DESC",
- ["toid" => $user->id]
- );
- $pms = [];
- foreach ($arr as $pm) {
- $pms[] = new PM($pm);
- }
- return $pms;
- }
-
private function count_pms(User $user)
{
global $cache, $database;
$count = $cache->get("pm-count:{$user->id}");
- if (is_null($count) || $count === false) {
+ if (is_null($count)) {
$count = $database->get_one("
SELECT count(*)
FROM private_message
diff --git a/ext/pm/test.php b/ext/pm/test.php
index dd525430..7ad5595d 100644
--- a/ext/pm/test.php
+++ b/ext/pm/test.php
@@ -1,9 +1,12 @@
log_in_as_admin();
@@ -11,13 +14,10 @@ class PrivMsgTest extends ShimmiePHPUnitTestCase
User::by_name(self::$admin_name)->id,
"0.0.0.0",
User::by_name(self::$user_name)->id,
- "message demo to test"
+ "message demo to test",
+ "test body"
)));
- // Check that admin can see user's messages
- $this->get_page("user/" . self::$user_name);
- $this->assert_text("message demo to test");
-
// Check that user can see own messages
$this->log_in_as_user();
$this->get_page("user");
@@ -36,4 +36,21 @@ class PrivMsgTest extends ShimmiePHPUnitTestCase
// $this->get_page("pm/read/0");
// $this->assert_text("No such PM");
}
+
+ public function testAdminReadOtherMessage()
+ {
+ // Send from admin to user
+ $this->log_in_as_admin();
+ send_event(new SendPMEvent(new PM(
+ User::by_name(self::$admin_name)->id,
+ "0.0.0.0",
+ User::by_name(self::$user_name)->id,
+ "message demo to test",
+ "test body"
+ )));
+
+ // Check that admin can see user's messages
+ $this->get_page("user/" . self::$user_name);
+ $this->assert_text("message demo to test");
+ }
}
diff --git a/ext/pm/theme.php b/ext/pm/theme.php
index 119ee14d..283acace 100644
--- a/ext/pm/theme.php
+++ b/ext/pm/theme.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class PrivMsgTheme extends Themelet
{
public function display_pms(Page $page, $pms)
diff --git a/ext/pm_triggers/info.php b/ext/pm_triggers/info.php
index e5b287b9..a11d3a5a 100644
--- a/ext/pm_triggers/info.php
+++ b/ext/pm_triggers/info.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class PMTriggerInfo extends ExtensionInfo
{
public const KEY = "pm_triggers";
diff --git a/ext/pm_triggers/main.php b/ext/pm_triggers/main.php
index 5b36eb1a..65e20512 100644
--- a/ext/pm_triggers/main.php
+++ b/ext/pm_triggers/main.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class PMTrigger extends Extension
{
public function onImageDeletion(ImageDeletionEvent $event)
diff --git a/ext/pools/info.php b/ext/pools/info.php
index cc215aa4..a99ad94d 100644
--- a/ext/pools/info.php
+++ b/ext/pools/info.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class PoolsInfo extends ExtensionInfo
{
public const KEY = "pools";
diff --git a/ext/pools/main.php b/ext/pools/main.php
index 90ee31ba..85fff391 100644
--- a/ext/pools/main.php
+++ b/ext/pools/main.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
abstract class PoolsConfig
{
public const MAX_IMPORT_RESULTS = "poolsMaxImportResults";
@@ -234,14 +236,12 @@ class Pools extends Extension
case "create": // ADD _POST
try {
$title = $_POST["title"];
- $event = new PoolCreationEvent(
+ $event = send_event(new PoolCreationEvent(
$title,
$user,
bool_escape($_POST["public"]),
$_POST["description"]
- );
-
- send_event($event);
+ ));
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("pool/view/" . $event->new_id));
} catch (PoolCreationException $e) {
@@ -325,37 +325,35 @@ class Pools extends Extension
}
}
break;
- case "reverse":
- if ($this->have_permission($user, $pool)) {
- $result = $database->execute(
- "SELECT image_id FROM pool_images WHERE pool_id=:pid ORDER BY image_order DESC",
- ["pid" => $pool_id]
- );
- $image_order = 1;
- try {
- $database->begin_transaction();
- while ($row = $result->fetch()) {
- $database->execute(
- "
- UPDATE pool_images
- SET image_order=:ord
+ case "reverse":
+ if ($this->have_permission($user, $pool)) {
+ $result = $database->execute(
+ "SELECT image_id FROM pool_images WHERE pool_id=:pid ORDER BY image_order DESC",
+ ["pid" => $pool_id]
+ );
+ $image_order = 1;
+ try {
+ $database->begin_transaction();
+ while ($row = $result->fetch()) {
+ $database->execute(
+ "
+ UPDATE pool_images
+ SET image_order=:ord
WHERE pool_id = :pid AND image_id = :iid",
- ["ord" => $image_order, "pid" => $pool_id, "iid" => (int)$row['image_id']]
- );
- $image_order = $image_order + 1;
- }
- $database->commit();
- }
- catch (Exception $e) {
- $database->rollback();
- }
- $page->set_mode(PageMode::REDIRECT);
- $page->set_redirect(make_link("pool/view/" . $pool_id));
- }
- else {
- $this->theme->display_error(403, "Permission Denied", "You do not have permission to access this page");
- }
- break;
+ ["ord" => $image_order, "pid" => $pool_id, "iid" => (int)$row['image_id']]
+ );
+ $image_order = $image_order + 1;
+ }
+ $database->commit();
+ } catch (\Exception $e) {
+ $database->rollback();
+ }
+ $page->set_mode(PageMode::REDIRECT);
+ $page->set_redirect(make_link("pool/view/" . $pool_id));
+ } else {
+ $this->theme->display_error(403, "Permission Denied", "You do not have permission to access this page");
+ }
+ break;
case "import":
if ($this->have_permission($user, $pool)) {
$images = Image::find_images(
@@ -441,8 +439,6 @@ class Pools extends Extension
* When displaying an image, optionally list all the pools that the
* image is currently a member of on a side panel, as well as a link
* to the Next image in the pool.
- *
- * @var DisplayingImageEvent $event
*/
public function onDisplayingImage(DisplayingImageEvent $event)
{
@@ -522,7 +518,6 @@ class Pools extends Extension
$poolID = str_replace("_", " ", $matches[1]);
$event->add_querylet(new Querylet("images.id IN (SELECT DISTINCT image_id FROM pool_images WHERE pool_id = $poolID)"));
}
-
}
public function onTagTermCheck(TagTermCheckEvent $event)
@@ -582,7 +577,7 @@ class Pools extends Extension
if ($this->have_permission($user, $pool)) {
send_event(
- new PoolAddPostsEvent($pool_id, iterator_map_to_array("_image_to_id", $event->items))
+ new PoolAddPostsEvent($pool_id, iterator_map_to_array("Shimmie2\_image_to_id", $event->items))
);
}
break;
@@ -591,9 +586,8 @@ class Pools extends Extension
return;
}
$new_pool_title = $_POST['bulk_pool_new'];
- $pce = new PoolCreationEvent($new_pool_title);
- send_event($pce);
- send_event(new PoolAddPostsEvent($pce->new_id, iterator_map_to_array("_image_to_id", $event->items)));
+ $pce = send_event(new PoolCreationEvent($new_pool_title));
+ send_event(new PoolAddPostsEvent($pce->new_id, iterator_map_to_array("Shimmie2\_image_to_id", $event->items)));
break;
}
}
@@ -919,9 +913,8 @@ class Pools extends Extension
if ($entry['action'] == 0) {
// READ ENTRIES
- foreach ($images as $image) {
- $imageID = $image;
- $this->add_post($poolID, $imageID);
+ foreach ($images as $imageID) {
+ $this->add_post($poolID, int_escape($imageID));
$imageArray .= " " . $imageID;
$newAction = 1;
diff --git a/ext/pools/test.php b/ext/pools/test.php
index 20500914..67da7b48 100644
--- a/ext/pools/test.php
+++ b/ext/pools/test.php
@@ -1,6 +1,9 @@
testCreate();
-
+ $this->testCreate();
$this->get_page("pool/list");
$this->assert_text("Pool");
}
@@ -121,7 +123,7 @@ class PoolsTest extends ShimmiePHPUnitTestCase
"pool_id" => $pool_id,
"check" => [(string)($image_ids[0]), (string)($image_ids[1])]
]);
- $this->assertEquals("redirect", $page->mode);
+ $this->assertEquals(PageMode::REDIRECT, $page->mode);
return [$pool_id, $image_ids];
}
@@ -135,7 +137,7 @@ class PoolsTest extends ShimmiePHPUnitTestCase
"pool_id" => $pool_id,
"check" => [(string)($image_ids[0]), (string)($image_ids[1])]
]);
- $this->assertEquals("redirect", $page->mode);
+ $this->assertEquals(PageMode::REDIRECT, $page->mode);
}
/** @depends testCreate */
@@ -147,7 +149,7 @@ class PoolsTest extends ShimmiePHPUnitTestCase
"pool_id" => $pool_id,
"description" => "Updated description"
]);
- $this->assertEquals("redirect", $page->mode);
+ $this->assertEquals(PageMode::REDIRECT, $page->mode);
return [$pool_id, $image_ids];
}
@@ -173,6 +175,6 @@ class PoolsTest extends ShimmiePHPUnitTestCase
$page = $this->post_page("pool/nuke", [
"pool_id" => "$pool_id",
]);
- $this->assertEquals("redirect", $page->mode);
+ $this->assertEquals(PageMode::REDIRECT, $page->mode);
}
}
diff --git a/ext/pools/theme.php b/ext/pools/theme.php
index 2a00f816..79f8c2ec 100644
--- a/ext/pools/theme.php
+++ b/ext/pools/theme.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class PoolsTheme extends Themelet
{
/**
@@ -142,8 +144,7 @@ class PoolsTheme extends Themelet
$this->sidebar_options($page, $pool, $check_all);
}
}
- $tfe = new TextFormattingEvent($pool->description);
- send_event($tfe);
+ $tfe = send_event(new TextFormattingEvent($pool->description));
$page->add_block(new Block(html_escape($pool->title), $tfe->formatted, "main", 10));
}
}
@@ -361,7 +362,7 @@ class PoolsTheme extends Themelet
} elseif ($history['action'] == 0) {
$prefix = "-";
} else {
- throw new RuntimeException("history['action'] not in {0, 1}");
+ throw new \RuntimeException("history['action'] not in {0, 1}");
}
$images = trim($history['images']);
diff --git a/ext/post_peek/info.php b/ext/post_peek/info.php
index fe7f9f29..fa08270f 100644
--- a/ext/post_peek/info.php
+++ b/ext/post_peek/info.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class PostPeekInfo extends ExtensionInfo
{
public const KEY = "post_peek";
diff --git a/ext/post_peek/main.php b/ext/post_peek/main.php
index d7941b6a..88cf5e9c 100644
--- a/ext/post_peek/main.php
+++ b/ext/post_peek/main.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class PostPeek extends Extension
{
}
diff --git a/ext/post_peek/theme.php b/ext/post_peek/theme.php
index b1924f21..077c111c 100644
--- a/ext/post_peek/theme.php
+++ b/ext/post_peek/theme.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class PostPeekTheme extends Themelet
{
}
diff --git a/ext/post_titles/config.php b/ext/post_titles/config.php
index e5ed3af3..a711e435 100644
--- a/ext/post_titles/config.php
+++ b/ext/post_titles/config.php
@@ -2,6 +2,7 @@
declare(strict_types=1);
+namespace Shimmie2;
abstract class PostTitlesConfig
{
diff --git a/ext/post_titles/events/post_title_set_event.php b/ext/post_titles/events/post_title_set_event.php
index 2ab3a0a2..b0fd8f8a 100644
--- a/ext/post_titles/events/post_title_set_event.php
+++ b/ext/post_titles/events/post_title_set_event.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class PostTitleSetEvent extends Event
{
public Image $image;
diff --git a/ext/post_titles/info.php b/ext/post_titles/info.php
index 2174d80e..1c1c87b0 100644
--- a/ext/post_titles/info.php
+++ b/ext/post_titles/info.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class PostTitlesInfo extends ExtensionInfo
{
public const KEY = "post_titles";
diff --git a/ext/post_titles/main.php b/ext/post_titles/main.php
index f4e5df19..0088964f 100644
--- a/ext/post_titles/main.php
+++ b/ext/post_titles/main.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
require_once "config.php";
require_once "events/post_title_set_event.php";
@@ -79,8 +81,8 @@ class PostTitles extends Extension
}
public function onBulkImport(BulkImportEvent $event)
{
- if (property_exists($event->fields, "title") && $event->fields->title!=null) {
- $this->set_title($event->image->id, $event->fields->title);
+ if (array_key_exists("title", $event->fields) && $event->fields['title']!=null) {
+ $this->set_title($event->image->id, $event->fields['title']);
}
}
diff --git a/ext/post_titles/theme.php b/ext/post_titles/theme.php
index 96303d14..aa3c9d35 100644
--- a/ext/post_titles/theme.php
+++ b/ext/post_titles/theme.php
@@ -1,6 +1,9 @@
owner_id!=$user->can(Permissions::SET_OTHERS_PRIVATE_IMAGES)) {
- throw new SCoreException("Cannot set another user's image to private.");
+ throw new SCoreException("Cannot set another user's image to public.");
}
self::publicize_image($image_id);
@@ -112,7 +114,7 @@ class PrivateImage extends Extension
{
global $user, $page;
- if ($event->image->private===true && $event->image->owner_id!=$user->id && !$user->can(Permissions::SET_OTHERS_PRIVATE_IMAGES)) {
+ if ($event->image->private==true && $event->image->owner_id!=$user->id && !$user->can(Permissions::SET_OTHERS_PRIVATE_IMAGES)) {
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/list"));
}
@@ -219,7 +221,7 @@ class PrivateImage extends Extension
public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event)
{
global $user;
- if ($user->can(Permissions::SET_PRIVATE_IMAGE) && $user->id==$event->image->owner_id) {
+ if (($user->can(Permissions::SET_PRIVATE_IMAGE) && $user->id==$event->image->owner_id) || $user->can(Permissions::SET_OTHERS_PRIVATE_IMAGES)) {
$event->add_part($this->theme->get_image_admin_html($event->image));
}
}
diff --git a/ext/private_image/theme.php b/ext/private_image/theme.php
index 8be0f28f..9f63c7d2 100644
--- a/ext/private_image/theme.php
+++ b/ext/private_image/theme.php
@@ -1,13 +1,16 @@
private===false) {
+ if ($image->private==false) {
$html = SHM_SIMPLE_FORM(
'privatize_image/'.$image->id,
INPUT(["type"=>'hidden', "name"=>'image_id', "value"=>$image->id]),
diff --git a/ext/qr_code/info.php b/ext/qr_code/info.php
index 7dc69e0c..8e9d5fd5 100644
--- a/ext/qr_code/info.php
+++ b/ext/qr_code/info.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class QRImageInfo extends ExtensionInfo
{
public const KEY = "qr_code";
@@ -11,7 +13,7 @@ class QRImageInfo extends ExtensionInfo
public string $url = "http://seemslegit.com";
public array $authors = ["Zach Hall"=>"zach@sosguy.net"];
public string $license = self::LICENSE_GPLV2;
- public string $description = "Turns BBCode into HTML";
+ public string $description = "Shows a QR Code for downloading a post to cell phones";
public ?string $documentation =
"Shows a QR Code for downloading a post to cell phones.
Based on Artanis's Link to Post Extension
", $iabbe->parts);
$h_reportedimages .= "
";
diff --git a/themes/rule34v2/themelet.class.php b/themes/rule34v2/themelet.class.php
index 54836e5e..ef194c73 100644
--- a/themes/rule34v2/themelet.class.php
+++ b/themes/rule34v2/themelet.class.php
@@ -1,5 +1,9 @@
get("thumb-block:{$image->id}");
- if ($cached) {
+ if (!is_null($cached)) {
return $cached;
}
diff --git a/themes/rule34v2/upload.theme.php b/themes/rule34v2/upload.theme.php
index 42b2e903..d80d76ea 100644
--- a/themes/rule34v2/upload.theme.php
+++ b/themes/rule34v2/upload.theme.php
@@ -1,6 +1,11 @@
get_string("login_tac", "");
if ($config->get_bool("login_tac_bbcode")) {
- $tfe = new TextFormattingEvent($tac);
- send_event($tfe);
- $tac = $tfe->formatted;
+ $tac = send_event(new TextFormattingEvent($tac))->formatted;
}
$form = SHM_SIMPLE_FORM(
diff --git a/themes/warm/page.class.php b/themes/warm/page.class.php
index 40c168d4..3ffcbab4 100644
--- a/themes/warm/page.class.php
+++ b/themes/warm/page.class.php
@@ -1,6 +1,9 @@
{$image_link}
- Report by $userlink: $h_reason
+ Report by $userlink: $h_reason
".make_form(make_link("image_report/remove"))."
diff --git a/ext/res_limit/info.php b/ext/res_limit/info.php
index 6b48d2d1..c407f628 100644
--- a/ext/res_limit/info.php
+++ b/ext/res_limit/info.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class ResolutionLimitInfo extends ExtensionInfo
{
public const KEY = "res_limit";
diff --git a/ext/res_limit/main.php b/ext/res_limit/main.php
index 4169a1ad..69c61f33 100644
--- a/ext/res_limit/main.php
+++ b/ext/res_limit/main.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class ResolutionLimit extends Extension
{
public function get_priority(): int
@@ -42,8 +44,8 @@ class ResolutionLimit extends Extension
continue;
}
$valids++;
- $width = $parts[0];
- $height = $parts[1];
+ $width = (int)$parts[0];
+ $height = (int)$parts[1];
if ($image->width / $width == $image->height / $height) {
$ok = true;
break;
diff --git a/ext/res_limit/test.php b/ext/res_limit/test.php
index ba1ef5c0..7bb9ee49 100644
--- a/ext/res_limit/test.php
+++ b/ext/res_limit/test.php
@@ -1,6 +1,9 @@
log_in_as_user();
try {
$this->post_image("tests/pbx_screenshot.jpg", "pbx computer screenshot");
- $this->assertTrue(false, "Invalid-size image was allowed");
+ $this->fail("Invalid-size image was allowed");
} catch (UploadException $e) {
$this->assertEquals("Post too small", $e->getMessage());
}
@@ -49,7 +52,7 @@ class ResolutionLimitTest extends ShimmiePHPUnitTestCase
try {
$this->post_image("tests/pbx_screenshot.jpg", "pbx computer screenshot");
- $this->assertTrue(false, "Invalid-size image was allowed");
+ $this->fail("Invalid-size image was allowed");
} catch (UploadException $e) {
$this->assertEquals("Post too large", $e->getMessage());
}
@@ -66,7 +69,7 @@ class ResolutionLimitTest extends ShimmiePHPUnitTestCase
try {
$this->post_image("tests/pbx_screenshot.jpg", "pbx computer screenshot");
- $this->assertTrue(false, "Invalid-size image was allowed");
+ $this->fail("Invalid-size image was allowed");
} catch (UploadException $e) {
$this->assertEquals("Post needs to be in one of these ratios: 16:9", $e->getMessage());
}
diff --git a/ext/resize/info.php b/ext/resize/info.php
index edc2c99d..b7703588 100644
--- a/ext/resize/info.php
+++ b/ext/resize/info.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
/*
* Notice:
* The image resize and resample code is based off of the "smart_resize_image"
diff --git a/ext/resize/main.php b/ext/resize/main.php
index 3d34237d..96ca6ec3 100644
--- a/ext/resize/main.php
+++ b/ext/resize/main.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
abstract class ResizeConfig
{
public const ENABLED = 'resize_enabled';
@@ -134,10 +136,8 @@ class ResizeImage extends Extension
if (is_null($image)) {
$this->theme->display_error(404, "Post not found", "No image in the database has the ID #$image_id");
} else {
-
/* Check if options were given to resize an image. */
if (isset($_POST['resize_width']) || isset($_POST['resize_height'])) {
-
/* get options */
$width = $height = 0;
@@ -192,15 +192,14 @@ class ResizeImage extends Extension
throw new ImageResizeException("Unable to save temporary image file.");
}
- $mre = new MediaResizeEvent(
+ send_event(new MediaResizeEvent(
$config->get_string(ResizeConfig::ENGINE),
$event->path,
$event->mime,
$tmp_filename,
$new_width,
$new_height
- );
- send_event($mre);
+ ));
if ($event->file_modified===true&&$event->path!=$event->image->get_image_filename()) {
// This means that we're dealing with a temp file that will need cleaned up
diff --git a/ext/resize/theme.php b/ext/resize/theme.php
index 63240826..44937b1f 100644
--- a/ext/resize/theme.php
+++ b/ext/resize/theme.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class ResizeImageTheme extends Themelet
{
/*
diff --git a/ext/rotate/info.php b/ext/rotate/info.php
index e18462ed..51c530d4 100644
--- a/ext/rotate/info.php
+++ b/ext/rotate/info.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
/*
* Notice:
* The image resize and resample code is based off of the "smart_resize_image"
diff --git a/ext/rotate/main.php b/ext/rotate/main.php
index a5820b15..030a2ac2 100644
--- a/ext/rotate/main.php
+++ b/ext/rotate/main.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
// TODO Add warning that rotate doesn't support lossless webp output
/**
@@ -65,10 +67,8 @@ class RotateImage extends Extension
if (is_null($image)) {
$this->theme->display_error(404, "Post not found", "No image in the database has the ID #$image_id");
} else {
-
/* Check if options were given to rotate an image. */
if (isset($_POST['rotate_deg'])) {
-
/* get options */
$deg = 0;
@@ -153,13 +153,23 @@ class RotateImage extends Extension
/* Output to the same format as the original image */
switch ($info[2]) {
- case IMAGETYPE_GIF: $result = imagegif($image_rotated, $tmp_filename); break;
- case IMAGETYPE_JPEG: $result = imagejpeg($image_rotated, $tmp_filename); break;
- case IMAGETYPE_PNG: $result = imagepng($image_rotated, $tmp_filename, 9); break;
- case IMAGETYPE_WEBP: $result = imagewebp($image_rotated, $tmp_filename); break;
- case IMAGETYPE_BMP: $result = imagebmp($image_rotated, $tmp_filename, true); break;
- default:
- throw new ImageRotateException("Unsupported image type.");
+ case IMAGETYPE_GIF:
+ $result = imagegif($image_rotated, $tmp_filename);
+ break;
+ case IMAGETYPE_JPEG:
+ $result = imagejpeg($image_rotated, $tmp_filename);
+ break;
+ case IMAGETYPE_PNG:
+ $result = imagepng($image_rotated, $tmp_filename, 9);
+ break;
+ case IMAGETYPE_WEBP:
+ $result = imagewebp($image_rotated, $tmp_filename);
+ break;
+ case IMAGETYPE_BMP:
+ $result = imagebmp($image_rotated, $tmp_filename, true);
+ break;
+ default:
+ throw new ImageRotateException("Unsupported image type.");
}
if ($result===false) {
diff --git a/ext/rotate/theme.php b/ext/rotate/theme.php
index 732f099f..a8a08a26 100644
--- a/ext/rotate/theme.php
+++ b/ext/rotate/theme.php
@@ -1,6 +1,9 @@
get("rss-item-image:{$image->id}");
- if ($cached) {
+ if (!is_null($cached)) {
return $cached;
}
diff --git a/ext/rss_images/test.php b/ext/rss_images/test.php
index 06f19e46..89dc8acc 100644
--- a/ext/rss_images/test.php
+++ b/ext/rss_images/test.php
@@ -1,6 +1,9 @@
set_timeout(DATABASE_TIMEOUT+15000); // deleting users can take a while
+ # Database might not be connected at this point...
+ #$database->set_timeout(DATABASE_TIMEOUT+15000); // deleting users can take a while
if (function_exists("sd_notify_watchdog")) {
- sd_notify_watchdog();
+ \sd_notify_watchdog();
}
if ($event->page_matches("rule34/comic_admin")) {
diff --git a/ext/rule34/script.js b/ext/rule34/script.js
index b7d780a6..9d22a5e6 100644
--- a/ext/rule34/script.js
+++ b/ext/rule34/script.js
@@ -1,13 +1,12 @@
document.addEventListener('DOMContentLoaded', () => {
- if(Cookies.get("ui-tnc-agreed") !== "true") {
+ if(Cookies.get("ui-tnc-agreed") !== "true" && window.location.href.indexOf("/wiki/") == -1) {
$("BODY").addClass("censored");
$("BODY").append("");
$("BODY").append(""+
"
B) cookies may be used"+
- "";
+ $list = new \MicroHTML\HTMLElement("list", [$props]);
foreach ($tags as $tag) {
- $result .= $this->tag_to_xml($tag);
+ $list->appendChild(new \MicroHTML\HTMLElement("tag", [["id"=>$tag["id"], "count"=>$tag["count"]], $tag["tag"]]));
}
- return $result."
";
- }
- private function tag_to_xml(PDORow $tag): string
- {
- return
- " ";
diff --git a/themes/danbooru/view.theme.php b/themes/danbooru/view.theme.php
index 67c9a7d2..5135e41b 100644
--- a/themes/danbooru/view.theme.php
+++ b/themes/danbooru/view.theme.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class CustomViewImageTheme extends ViewImageTheme
{
public function display_page(Image $image, $editor_parts)
diff --git a/themes/danbooru2/admin.theme.php b/themes/danbooru2/admin.theme.php
index bb85ee16..1d8082f6 100644
--- a/themes/danbooru2/admin.theme.php
+++ b/themes/danbooru2/admin.theme.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class CustomAdminPageTheme extends AdminPageTheme
{
public function display_page()
diff --git a/themes/danbooru2/comment.theme.php b/themes/danbooru2/comment.theme.php
index 4a4a7e0c..d61b0786 100644
--- a/themes/danbooru2/comment.theme.php
+++ b/themes/danbooru2/comment.theme.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class CustomCommentListTheme extends CommentListTheme
{
public function display_comment_list(array $images, int $page_number, int $total_pages, bool $can_post)
@@ -94,8 +96,7 @@ class CustomCommentListTheme extends CommentListTheme
{
global $user;
- $tfe = new TextFormattingEvent($comment->comment);
- send_event($tfe);
+ $tfe = send_event(new TextFormattingEvent($comment->comment));
//$i_uid = $comment->owner_id;
$h_name = html_escape($comment->owner_name);
diff --git a/themes/danbooru2/ext_manager.theme.php b/themes/danbooru2/ext_manager.theme.php
index 35860dde..bdc7b0c2 100644
--- a/themes/danbooru2/ext_manager.theme.php
+++ b/themes/danbooru2/ext_manager.theme.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class CustomExtManagerTheme extends ExtManagerTheme
{
public function display_table(Page $page, array $extensions, bool $editable)
diff --git a/themes/danbooru2/index.theme.php b/themes/danbooru2/index.theme.php
index 6ef017b3..51bf4473 100644
--- a/themes/danbooru2/index.theme.php
+++ b/themes/danbooru2/index.theme.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class CustomIndexTheme extends IndexTheme
{
/**
diff --git a/themes/danbooru2/page.class.php b/themes/danbooru2/page.class.php
index f59c2ab7..d96d84fd 100644
--- a/themes/danbooru2/page.class.php
+++ b/themes/danbooru2/page.class.php
@@ -1,6 +1,9 @@
, updated by Daniel Oaks ".captcha_get_html()." ";
diff --git a/themes/danbooru2/view.theme.php b/themes/danbooru2/view.theme.php
index 9c40349f..bb211947 100644
--- a/themes/danbooru2/view.theme.php
+++ b/themes/danbooru2/view.theme.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class CustomViewImageTheme extends ViewImageTheme
{
public function display_page(Image $image, $editor_parts)
diff --git a/themes/default/page.class.php b/themes/default/page.class.php
index 62ee009a..026403af 100644
--- a/themes/default/page.class.php
+++ b/themes/default/page.class.php
@@ -1,6 +1,9 @@
inner_id; // because custom themes can't add params, because PHP
global $user;
- $tfe = new TextFormattingEvent($comment->comment);
- send_event($tfe);
+ $tfe = send_event(new TextFormattingEvent($comment->comment));
//$i_uid = $comment->owner_id;
$h_name = html_escape($comment->owner_name);
diff --git a/themes/futaba/page.class.php b/themes/futaba/page.class.php
index 178a9a7e..83be4b91 100644
--- a/themes/futaba/page.class.php
+++ b/themes/futaba/page.class.php
@@ -2,6 +2,8 @@
declare(strict_types=1);
+namespace Shimmie2;
+
class Page extends BasePage
{
public bool $left_enabled = true;
diff --git a/themes/futaba/themelet.class.php b/themes/futaba/themelet.class.php
index 359f4ac5..cb2c937d 100644
--- a/themes/futaba/themelet.class.php
+++ b/themes/futaba/themelet.class.php
@@ -1,6 +1,9 @@
@@ -74,7 +77,7 @@ class Page extends BasePage
$custom_sublinks .= "";
}
- if ($this->left_enabled == false) {
+ if (!$this->left_enabled) {
$left_block_html = "";
$main_block_html = "".captcha_get_html()."
Contact -";
- $main_links_html = empty($main_links) ? "" : preg_replace('data-clink-sel="" ', '', preg_replace('/shm-clink/', 'mdl-navigation__link', $main_links));
+ $main_links_html = empty($main_links) ? "" : preg_replace('/data-clink-sel="" /', '', preg_replace('/shm-clink/', 'mdl-navigation__link', $main_links));
$search_html = "
$sitename
+ $sitename
$main_links_html
$search_html
$message_html
@@ -66,9 +71,23 @@ EOD
+
+
+
$contact_link Serving $num_comma posts –
- Running Shimmie2
+ Running Shimmie2
".$block->get_html(false)." ";
break;
case "main":
+ if ($main_headings == 1) {
+ $block->header = null;
+ }
$main_block_html .= $block->get_html(false);
break;
case "subheading":
@@ -122,8 +135,7 @@ EOD;
Tags
-
+