diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 000000000..968d7a846 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,50 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/docker-existing-dockerfile +{ + "name": "Shimmie Dockerfile", + "build": { + "context": "..", + "dockerfile": "../Dockerfile", + "target": "devcontainer" + }, + + "workspaceMount": "source=${localWorkspaceFolder},target=/app,type=bind", + "workspaceFolder": "/app", + + // Features to add to the dev container. More info: https://containers.dev/features. + // "features": {}, + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + "forwardPorts": [8000], + + // Uncomment the next line to run commands after the container is created. + "postCreateCommand": "./.docker/entrypoint.sh unitd --no-daemon --control unix:/var/run/control.unit.sock", + "containerEnv": { + "UID": "2000", + "GID": "2000", + "UPLOAD_MAX_FILESIZE": "50M", + }, + "customizations": { + "vscode": { + "extensions": [ + "recca0120.vscode-phpunit", + "ryanluker.vscode-coverage-gutters", + "xdebug.php-debug", + "DEVSENSE.phptools-vscode", + "ms-azuretools.vscode-docker" + ], + "settings": { + "phpunit.args": [ + "--configuration", "${workspaceFolder}/tests/phpunit.xml", + "--coverage-clover", "data/coverage.clover" + ], + "coverage-gutters.coverageFileNames": [ + "data/coverage.clover" + ] + } + } + } + + // Uncomment to connect as an existing user other than the container default. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "devcontainer" +} diff --git a/.docker/entrypoint.d/config.json.tmpl b/.docker/entrypoint.d/config.json.tmpl new file mode 100644 index 000000000..d1088d6ef --- /dev/null +++ b/.docker/entrypoint.d/config.json.tmpl @@ -0,0 +1,81 @@ +{ + "listeners": { + "*:8000": { + "pass": "routes", + "forwarded": { + "client_ip": "X-Forwarded-For", + "recursive": false, + "source": [ + "172.17.0.0/16" + ] + } + } + }, + "routes": [ + { + "match": { + "uri": "~/_(thumbs|images)/.*" + }, + "action": { + "share": [ + "`/app/data/${uri.replace(/_(thumbs|images)\\/(..)(..)(.*?)\\/.*/, '$1/$2/$3/$2$3$4')}`", + "`/app/data/${uri.replace(/_(thumbs|images)\\/(..)(.*?)\\/.*/, '$1/$2/$2$3')}`" + ], + "response_headers": { + "Cache-Control": "public, max-age=31556926" + } + } + }, + { + "action": { + "share": [ + "/app/$uri" + ], + "types": [ + "image/*", + "application/javascript", + "text/css", + "application/sourcemap", + "!" + ], + "response_headers": { + "Cache-Control": "public, max-age=31556926" + }, + "fallback": { + "pass": "applications/shimmie" + } + } + } + ], + "applications": { + "shimmie": { + "type": "php", + "user": "shimmie", + "root": "/app/", + "script": "index.php", + "working_directory": "/app/", + "options": { + "admin": { + "memory_limit": "256M", + "upload_max_filesize": "$UPLOAD_MAX_FILESIZE", + "post_max_size": "$UPLOAD_MAX_FILESIZE" + } + }, + "processes": { + "max": 8, + "spare": 2, + "idle_timeout": 60 + } + } + }, + "settings": { + "http": { + "max_body_size": 1048576000, + "static": { + "mime_types": { + "application/sourcemap": [".map"] + } + } + } + } +} diff --git a/.docker/entrypoint.sh b/.docker/entrypoint.sh new file mode 100755 index 000000000..16ada3863 --- /dev/null +++ b/.docker/entrypoint.sh @@ -0,0 +1,108 @@ +#!/bin/sh + +set -e + +# if user shimmie doesn't already exist, create it +if ! id -u shimmie >/dev/null 2>&1; then + groupadd -g $GID shimmie || true + useradd -ms /bin/bash -u $UID -g $GID shimmie || true +fi +mkdir -p /app/data +chown shimmie:shimmie /app/data + +rm -rf /var/lib/unit/* + +envsubst '$UPLOAD_MAX_FILESIZE' < /app/.docker/entrypoint.d/config.json.tmpl > /app/.docker/entrypoint.d/config.json + +WAITLOOPS=5 +SLEEPSEC=1 + +curl_put() +{ + RET=$(/usr/bin/curl -s -w '%{http_code}' -X PUT --data-binary @$1 --unix-socket /var/run/control.unit.sock http://localhost/$2) + RET_BODY=$(echo $RET | /bin/sed '$ s/...$//') + RET_STATUS=$(echo $RET | /usr/bin/tail -c 4) + if [ "$RET_STATUS" -ne "200" ]; then + echo "$0: Error: HTTP response status code is '$RET_STATUS'" + echo "$RET_BODY" + return 1 + else + echo "$0: OK: HTTP response status code is '$RET_STATUS'" + echo "$RET_BODY" + fi + return 0 +} + +if [ "$1" = "unitd" ] || [ "$1" = "unitd-debug" ]; then + if /usr/bin/find "/var/lib/unit/" -mindepth 1 -print -quit 2>/dev/null | /bin/grep -q .; then + echo "$0: /var/lib/unit/ is not empty, skipping initial configuration..." + else + echo "$0: Launching Unit daemon to perform initial configuration..." + /usr/sbin/$1 --control unix:/var/run/control.unit.sock + + for i in $(/usr/bin/seq $WAITLOOPS); do + if [ ! -S /var/run/control.unit.sock ]; then + echo "$0: Waiting for control socket to be created..." + /bin/sleep $SLEEPSEC + else + break + fi + done + # even when the control socket exists, it does not mean unit has finished initialisation + # this curl call will get a reply once unit is fully launched + /usr/bin/curl -s -X GET --unix-socket /var/run/control.unit.sock http://localhost/ + if /usr/bin/find "/app/.docker/entrypoint.d/" -mindepth 1 -print -quit 2>/dev/null | /bin/grep -q .; then + echo "$0: /app/.docker/entrypoint.d/ is not empty, applying initial configuration..." + + echo "$0: Looking for certificate bundles in /app/.docker/entrypoint.d/..." + for f in $(/usr/bin/find /app/.docker/entrypoint.d/ -type f -name "*.pem"); do + echo "$0: Uploading certificates bundle: $f" + curl_put $f "certificates/$(basename $f .pem)" + done + echo "$0: Looking for JavaScript modules in /app/.docker/entrypoint.d/..." + for f in $(/usr/bin/find /app/.docker/entrypoint.d/ -type f -name "*.js"); do + echo "$0: Uploading JavaScript module: $f" + curl_put $f "js_modules/$(basename $f .js)" + done + + echo "$0: Looking for configuration snippets in /app/.docker/entrypoint.d/..." + for f in $(/usr/bin/find /app/.docker/entrypoint.d/ -type f -name "*.json"); do + echo "$0: Applying configuration $f"; + curl_put $f "config" + done + echo "$0: Looking for shell scripts in /app/.docker/entrypoint.d/..." + for f in $(/usr/bin/find /app/.docker/entrypoint.d/ -type f -name "*.sh"); do + echo "$0: Launching $f"; + "$f" + done + + # warn on filetypes we don't know what to do with + for f in $(/usr/bin/find /app/.docker/entrypoint.d/ -type f -not -name "*.sh" -not -name "*.json" -not -name "*.pem" -not -name "*.js"); do + echo "$0: Ignoring $f"; + done + else + echo "$0: /app/.docker/entrypoint.d/ is empty, creating 'welcome' configuration..." + curl_put /usr/share/unit/welcome/welcome.json "config" + fi + echo "$0: Stopping Unit daemon after initial configuration..." + kill -TERM $(/bin/cat /var/run/unit.pid) + + for i in $(/usr/bin/seq $WAITLOOPS); do + if [ -S /var/run/control.unit.sock ]; then + echo "$0: Waiting for control socket to be removed..." + /bin/sleep $SLEEPSEC + else + break + fi + done + if [ -S /var/run/control.unit.sock ]; then + kill -KILL $(/bin/cat /var/run/unit.pid) + rm -f /var/run/control.unit.sock + fi + echo + echo "$0: Unit initial configuration complete; ready for start up..." + echo + fi +fi + +exec "$@" diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 2e8fd122c..07e14207e 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -3,7 +3,9 @@ name: Publish on: workflow_run: workflows: Tests - branches: main + branches: + - main + - master types: completed workflow_dispatch: push: @@ -16,7 +18,18 @@ jobs: runs-on: ubuntu-latest if: ${{ github.event.workflow_run.conclusion == 'success' || github.event_name == 'workflow_dispatch' || github.event_name == 'push' }} steps: - - uses: actions/checkout@master + - name: Checkout triggering commit + if: ${{ github.event_name == 'workflow_run' }} + uses: actions/checkout@master + with: + ref: ${{ github.event.workflow_run.head_sha }} + - name: Checkout main commit + if: ${{ github.event_name != 'workflow_run' }} + uses: actions/checkout@master + - name: Set build vars + run: | + echo "BUILD_TIME=$(date +'%Y-%m-%dT%H:%M:%S')" >> $GITHUB_ENV + echo "BUILD_HASH=$GITHUB_SHA" >> $GITHUB_ENV - name: Publish to Registry uses: elgohr/Publish-Docker-Github-Action@main with: @@ -25,4 +38,5 @@ jobs: password: ${{ secrets.DOCKER_PASSWORD }} cache: ${{ github.event_name != 'schedule' }} buildoptions: "--build-arg RUN_TESTS=false" + buildargs: BUILD_TIME,BUILD_HASH tag_semver: true diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 369765aa9..43a213284 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -2,6 +2,9 @@ name: Tests on: push: + branches: + - main + - master pull_request: schedule: - cron: '0 2 * * 0' # Weekly on Sundays at 02:00 @@ -26,7 +29,7 @@ jobs: - name: Set up PHP uses: shivammathur/setup-php@master with: - php-version: 8.1 + php-version: 8.3 - name: Format run: ./vendor/bin/php-cs-fixer fix && git diff --exit-code @@ -57,7 +60,7 @@ jobs: strategy: fail-fast: false matrix: - php: ['8.1', '8.2'] + php: ['8.1', '8.2', '8.3'] database: ['pgsql', 'mysql', 'sqlite'] runs-on: ubuntu-latest @@ -122,9 +125,13 @@ jobs: if [[ "${{ matrix.database }}" == "sqlite" ]]; then export TEST_DSN="sqlite:data/shimmie.sqlite" fi - vendor/bin/phpunit --configuration tests/phpunit.xml --coverage-clover=data/coverage.clover + if [[ "${{ matrix.php }}" == "8.3" ]]; then + vendor/bin/phpunit --configuration tests/phpunit.xml --coverage-clover=data/coverage.clover + else + vendor/bin/phpunit --configuration tests/phpunit.xml + fi - name: Upload coverage - if: matrix.php == '8.1' + if: matrix.php == '8.3' run: | vendor/bin/ocular code-coverage:upload --format=php-clover data/coverage.clover diff --git a/.gitignore b/.gitignore index 4f3b64dcd..8f3636c25 100644 --- a/.gitignore +++ b/.gitignore @@ -1,16 +1,9 @@ backup data -images -thumbs -*.phar -*.sqlite -*.cache -.devcontainer -trace.json +.docker/entrypoint.d/config.json #Composer composer.phar -composer.lock /vendor/ # Created by http://www.gitignore.io diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 8a4d93aad..9fd655e94 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -14,4 +14,5 @@ 'array_syntax' => ['syntax' => 'short'], ]) ->setFinder($_phpcs_finder) -; \ No newline at end of file + ->setCacheFile("data/php-cs-fixer.cache") +; diff --git a/Dockerfile b/Dockerfile index 75508f592..3b391da1b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,31 +1,49 @@ ARG PHP_VERSION=8.2 -# Install base packages which all stages (build, test, run) need +# Tree of layers: +# base +# ├── dev-tools +# │ ├── build +# │ │ └── tests +# │ └── devcontainer +# └── run (copies built artifacts out of build) + +# Install base packages +# Things which all stages (build, test, run) need FROM debian:bookworm AS base -RUN apt update && apt upgrade -y && apt install -y \ +COPY --from=mwader/static-ffmpeg:6.1 /ffmpeg /ffprobe /usr/local/bin/ +RUN apt update && \ + apt upgrade -y && \ + apt install -y curl && \ + curl --output /usr/share/keyrings/nginx-keyring.gpg https://unit.nginx.org/keys/nginx-keyring.gpg && \ + echo 'deb [signed-by=/usr/share/keyrings/nginx-keyring.gpg] https://packages.nginx.org/unit/debian/ bookworm unit' > /etc/apt/sources.list.d/unit.list && \ + apt update && apt install -y --no-install-recommends \ 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 \ - gosu curl imagemagick ffmpeg zip unzip && \ + php${PHP_VERSION}-pgsql php${PHP_VERSION}-mysql php${PHP_VERSION}-sqlite3 php${PHP_VERSION}-curl \ + curl imagemagick zip unzip unit unit-php gettext && \ rm -rf /var/lib/apt/lists/* -# Composer has 100MB of dependencies, and we only need that during build and test -FROM base AS composer -RUN apt update && apt upgrade -y && apt install -y composer php${PHP_VERSION}-xdebug && rm -rf /var/lib/apt/lists/* +# Install dev packages +# Things which are only needed during development - Composer has 100MB of +# dependencies, so let's avoid including that in the final image +FROM base AS dev-tools +RUN apt update && apt upgrade -y && \ + apt install -y composer php${PHP_VERSION}-xdebug git procps net-tools vim && \ + rm -rf /var/lib/apt/lists/* +ENV XDEBUG_MODE=coverage -# "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 composer AS app +# "Build" shimmie (composer install) +# Done in its own stage so that we don't meed to include all the +# composer fluff in the final image +FROM dev-tools AS build COPY composer.json composer.lock /app/ WORKDIR /app RUN composer install --no-dev 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 composer AS tests -COPY composer.json composer.lock /app/ -WORKDIR /app +# Tests in their own image. +# Re-run composer install to get dev dependencies +FROM build AS tests RUN composer install COPY . /app/ ARG RUN_TESTS=true @@ -33,17 +51,22 @@ RUN [ $RUN_TESTS = false ] || (\ echo '=== Installing ===' && mkdir -p data/config && INSTALL_DSN="sqlite:data/shimmie.sqlite" php index.php && \ echo '=== Smoke Test ===' && php index.php get-page /post/list && \ echo '=== Unit Tests ===' && ./vendor/bin/phpunit --configuration tests/phpunit.xml && \ - echo '=== Coverage ===' && XDEBUG_MODE=coverage ./vendor/bin/phpunit --configuration tests/phpunit.xml --coverage-text && \ + echo '=== Coverage ===' && ./vendor/bin/phpunit --configuration tests/phpunit.xml --coverage-text && \ echo '=== Cleaning ===' && rm -rf data) -# Actually run shimmie -FROM base +# Devcontainer target +# Contains all of the build and debug tools, but no code, since +# that's mounted from the host +FROM dev-tools AS devcontainer EXPOSE 8000 -HEALTHCHECK --interval=1m --timeout=3s CMD curl --fail http://127.0.0.1:8000/ || exit 1 -ENV UID=1000 \ - GID=1000 \ - UPLOAD_MAX_FILESIZE=50M -COPY --from=app /app /app +# Actually run shimmie +FROM base AS run +EXPOSE 8000 +# HEALTHCHECK --interval=1m --timeout=3s CMD curl --fail http://127.0.0.1:8000/ || exit 1 +ARG BUILD_TIME=unknown BUILD_HASH=unknown +ENV UID=1000 GID=1000 UPLOAD_MAX_FILESIZE=50M BUILD_TIME=${BUILD_TIME} BUILD_HASH=${BUILD_HASH} +COPY --from=build /app /app WORKDIR /app -CMD ["/bin/sh", "/app/tests/docker-init.sh"] +ENTRYPOINT ["/app/.docker/entrypoint.sh"] +CMD ["unitd", "--no-daemon", "--control", "unix:/var/run/control.unit.sock"] diff --git a/README.md b/README.md index 032fc6e51..b4ea3d8ac 100644 --- a/README.md +++ b/README.md @@ -19,9 +19,10 @@ To Dos: # Shimmie -[![Test & Publish](https://github.com/shish/shimmie2/workflows/Test%20&%20Publish/badge.svg)](https://github.com/shish/shimmie2/actions) +[![Tests](https://github.com/shish/shimmie2/workflows/Tests/badge.svg?branch=main)](https://github.com/shish/shimmie2/actions) [![Code Quality](https://scrutinizer-ci.com/g/shish/shimmie2/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/shish/shimmie2/?branch=master) [![Code Coverage](https://scrutinizer-ci.com/g/shish/shimmie2/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/shish/shimmie2/?branch=master) +[![Matrix](https://matrix.to/img/matrix-badge.svg)](https://matrix.to/#/#shimmie:matrix.org) # Documentation @@ -35,13 +36,6 @@ To Dos: * [High-performance notes](https://github.com/shish/shimmie2/wiki/Performance) -# Contact - -Email: webmaster at shishnet.org - -Issue/Bug tracker: https://github.com/shish/shimmie2/issues - - # Licence All code is released under the [GNU GPL Version 2](https://www.gnu.org/licenses/gpl-2.0.html) unless mentioned otherwise. diff --git a/composer.json b/composer.json index 2732020a7..deadf4496 100644 --- a/composer.json +++ b/composer.json @@ -27,10 +27,6 @@ "reference" : "fd4ff50eb577457c1b7b887401663e91e77625ae" } } - }, - { - "type" : "vcs", - "url" : "https://github.com/shish/php-css.git" } ], @@ -39,31 +35,30 @@ "ext-pdo": "*", "ext-json": "*", "ext-fileinfo": "*", - - "flexihash/flexihash" : "^2.0", - "ifixit/php-akismet" : "^1.0", - "google/recaptcha" : "^1.1", - "shish/eventtracer-php" : "^2.0", - "shish/ffsphp" : "^1.0", - "shish/microcrud" : "^2.0", - "shish/microhtml" : "^2.2", - "shish/gqla" : "dev-main", - "enshrined/svg-sanitize" : "^0.16", - - "bower-asset/jquery" : "^1.12", - "bower-asset/jquery-timeago" : "^1.5", - "bower-asset/js-cookie" : "^2.1", - "psr/simple-cache" : "^1.0", - "sabre/cache" : "^2.0.1", + "flexihash/flexihash": "^2.0", + "ifixit/php-akismet": "^1.0", + "google/recaptcha": "^1.1", + "shish/eventtracer-php": "^2.0", + "shish/ffsphp": "^1.3", + "shish/microbundler": "^1.0", + "shish/microcrud": "^2.0", + "shish/microhtml": "^2.2", + "shish/gqla": "dev-main", + "enshrined/svg-sanitize": "^0.16", + "bower-asset/jquery": "^1.12", + "bower-asset/jquery-timeago": "^1.5", + "bower-asset/js-cookie": "^2.1", + "psr/simple-cache": "^1.0", + "sabre/cache": "^2.0.1", "naroga/redis-cache": "dev-master", - "tbela99/css": "dev-master" + "aws/aws-sdk-php": "^3.294" }, "require-dev" : { - "phpunit/phpunit" : "^9.0", - "friendsofphp/php-cs-fixer" : "^3.12", - "scrutinizer/ocular": "dev-master", - "phpstan/phpstan": "1.10.x-dev" + "phpunit/phpunit" : "10.5.3", + "friendsofphp/php-cs-fixer" : "3.41.1", + "scrutinizer/ocular": "1.9", + "phpstan/phpstan": "1.10.50" }, "suggest": { "ext-memcache": "memcache caching", diff --git a/composer.lock b/composer.lock index b288870e4..3183e5b35 100644 --- a/composer.lock +++ b/composer.lock @@ -4,206 +4,163 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "88e93ac9426438e6dc11301eb9faeed1", + "content-hash": "f414c6453498abc6d6578416a464b7e9", "packages": [ { - "name": "axy/backtrace", - "version": "1.0.7", + "name": "aws/aws-crt-php", + "version": "v1.2.4", "source": { "type": "git", - "url": "https://github.com/axypro/backtrace.git", - "reference": "c6c7d0f3497a07ae934f9e8511cbc2286db311c5" + "url": "https://github.com/awslabs/aws-crt-php.git", + "reference": "eb0c6e4e142224a10b08f49ebf87f32611d162b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/axypro/backtrace/zipball/c6c7d0f3497a07ae934f9e8511cbc2286db311c5", - "reference": "c6c7d0f3497a07ae934f9e8511cbc2286db311c5", + "url": "https://api.github.com/repos/awslabs/aws-crt-php/zipball/eb0c6e4e142224a10b08f49ebf87f32611d162b2", + "reference": "eb0c6e4e142224a10b08f49ebf87f32611d162b2", "shasum": "" }, "require": { - "php": ">=5.4.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "axy\\backtrace\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Oleg Grigoriev", - "email": "go.vasac@gmail.com" - } - ], - "description": "Tracing in PHP", - "homepage": "https://github.com/axypro/backtrace", - "keywords": [ - "Backtrace", - "debug", - "exception", - "trace" - ], - "support": { - "issues": "https://github.com/axypro/backtrace/issues", - "source": "https://github.com/axypro/backtrace/tree/1.0.7" - }, - "time": "2019-02-02T15:52:44+00:00" - }, - { - "name": "axy/codecs-base64vlq", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/axypro/codecs-base64vlq.git", - "reference": "53a1957f2cb773c6533ac615b3f1ac59e40e13cc" + "php": ">=5.5" }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/axypro/codecs-base64vlq/zipball/53a1957f2cb773c6533ac615b3f1ac59e40e13cc", - "reference": "53a1957f2cb773c6533ac615b3f1ac59e40e13cc", - "shasum": "" + "require-dev": { + "phpunit/phpunit": "^4.8.35||^5.6.3||^9.5", + "yoast/phpunit-polyfills": "^1.0" }, - "require": { - "axy/errors": "~1.0.1", - "php": ">=5.4.0" + "suggest": { + "ext-awscrt": "Make sure you install awscrt native extension to use any of the functionality." }, "type": "library", "autoload": { - "psr-4": { - "axy\\codecs\\base64vlq\\": "" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "Apache-2.0" ], "authors": [ { - "name": "Oleg Grigoriev", - "email": "go.vasac@gmail.com" + "name": "AWS SDK Common Runtime Team", + "email": "aws-sdk-common-runtime@amazon.com" } ], - "description": "Codec for VLQ (variable-length quantity) Base64 algorithm", - "homepage": "https://github.com/axypro/codecs-base64vlq", + "description": "AWS Common Runtime for PHP", + "homepage": "https://github.com/awslabs/aws-crt-php", "keywords": [ - "Source map", - "VLQ", - "Variable length quantity", - "base64", - "codec" + "amazon", + "aws", + "crt", + "sdk" ], "support": { - "issues": "https://github.com/axypro/codecs-base64vlq/issues", - "source": "https://github.com/axypro/codecs-base64vlq/tree/master" + "issues": "https://github.com/awslabs/aws-crt-php/issues", + "source": "https://github.com/awslabs/aws-crt-php/tree/v1.2.4" }, - "time": "2015-11-23T07:08:52+00:00" + "time": "2023-11-08T00:42:13+00:00" }, { - "name": "axy/errors", - "version": "1.0.5", + "name": "aws/aws-sdk-php", + "version": "3.295.4", "source": { "type": "git", - "url": "https://github.com/axypro/errors.git", - "reference": "2c64374ae2b9ca51304c09b6b6acc275557fc34f" + "url": "https://github.com/aws/aws-sdk-php.git", + "reference": "2372661db989fe4229abd95f4434b37252076d58" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/axypro/errors/zipball/2c64374ae2b9ca51304c09b6b6acc275557fc34f", - "reference": "2c64374ae2b9ca51304c09b6b6acc275557fc34f", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/2372661db989fe4229abd95f4434b37252076d58", + "reference": "2372661db989fe4229abd95f4434b37252076d58", "shasum": "" }, "require": { - "axy/backtrace": "~1.0.2", - "php": ">=5.4.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "axy\\errors\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Oleg Grigoriev", - "email": "go.vasac@gmail.com" - } - ], - "description": "Exceptions in PHP", - "homepage": "https://github.com/axypro/errors", - "keywords": [ - "error", - "exception" - ], - "support": { - "issues": "https://github.com/axypro/errors/issues", - "source": "https://github.com/axypro/errors/tree/1.0.5" - }, - "time": "2019-02-02T18:26:18+00:00" - }, - { - "name": "axy/sourcemap", - "version": "0.1.5", - "source": { - "type": "git", - "url": "https://github.com/axypro/sourcemap.git", - "reference": "95a52df5a08c3a011031dae2e79390134e28467c" + "aws/aws-crt-php": "^1.2.3", + "ext-json": "*", + "ext-pcre": "*", + "ext-simplexml": "*", + "guzzlehttp/guzzle": "^6.5.8 || ^7.4.5", + "guzzlehttp/promises": "^1.4.0 || ^2.0", + "guzzlehttp/psr7": "^1.9.1 || ^2.4.5", + "mtdowling/jmespath.php": "^2.6", + "php": ">=7.2.5", + "psr/http-message": "^1.0 || ^2.0" }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/axypro/sourcemap/zipball/95a52df5a08c3a011031dae2e79390134e28467c", - "reference": "95a52df5a08c3a011031dae2e79390134e28467c", - "shasum": "" + "require-dev": { + "andrewsville/php-token-reflection": "^1.4", + "aws/aws-php-sns-message-validator": "~1.0", + "behat/behat": "~3.0", + "composer/composer": "^1.10.22", + "dms/phpunit-arraysubset-asserts": "^0.4.0", + "doctrine/cache": "~1.4", + "ext-dom": "*", + "ext-openssl": "*", + "ext-pcntl": "*", + "ext-sockets": "*", + "nette/neon": "^2.3", + "paragonie/random_compat": ">= 2", + "phpunit/phpunit": "^5.6.3 || ^8.5 || ^9.5", + "psr/cache": "^1.0", + "psr/simple-cache": "^1.0", + "sebastian/comparator": "^1.2.3 || ^4.0", + "yoast/phpunit-polyfills": "^1.0" }, - "require": { - "axy/codecs-base64vlq": "~1.0.0", - "axy/errors": "~1.0.1", - "ext-json": "*", - "php": ">=5.4.0" + "suggest": { + "aws/aws-php-sns-message-validator": "To validate incoming SNS notifications", + "doctrine/cache": "To use the DoctrineCacheAdapter", + "ext-curl": "To send requests using cURL", + "ext-openssl": "Allows working with CloudFront private distributions and verifying received SNS messages", + "ext-sockets": "To use client-side monitoring" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, "autoload": { + "files": [ + "src/functions.php" + ], "psr-4": { - "axy\\sourcemap\\": "" + "Aws\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "Apache-2.0" ], "authors": [ { - "name": "Oleg Grigoriev", - "email": "go.vasac@gmail.com" + "name": "Amazon Web Services", + "homepage": "http://aws.amazon.com" } ], - "description": "Work with JavaScript/CSS Source Map", - "homepage": "https://github.com/axypro/sourcemap", + "description": "AWS SDK for PHP - Use Amazon Web Services in your PHP project", + "homepage": "http://aws.amazon.com/sdkforphp", "keywords": [ - "Source map", - "css", - "javascript", - "sourcemap" + "amazon", + "aws", + "cloud", + "dynamodb", + "ec2", + "glacier", + "s3", + "sdk" ], "support": { - "issues": "https://github.com/axypro/sourcemap/issues", - "source": "https://github.com/axypro/sourcemap/tree/0.1.5" + "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", + "issues": "https://github.com/aws/aws-sdk-php/issues", + "source": "https://github.com/aws/aws-sdk-php/tree/3.295.4" }, - "time": "2020-08-20T09:49:44+00:00" + "time": "2023-12-29T19:07:49+00:00" }, { "name": "bower-asset/jquery", "version": "1.12.4", "source": { "type": "git", - "url": "git@github.com:jquery/jquery-dist.git", + "url": "https://github.com/jquery/jquery-dist.git", "reference": "5e89585e0121e72ff47de177c5ef604f3089a53d" }, "dist": { @@ -303,20 +260,20 @@ }, { "name": "ezyang/htmlpurifier", - "version": "v4.16.0", + "version": "v4.17.0", "source": { "type": "git", "url": "https://github.com/ezyang/htmlpurifier.git", - "reference": "523407fb06eb9e5f3d59889b3978d5bfe94299c8" + "reference": "bbc513d79acf6691fa9cf10f192c90dd2957f18c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/523407fb06eb9e5f3d59889b3978d5bfe94299c8", - "reference": "523407fb06eb9e5f3d59889b3978d5bfe94299c8", + "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/bbc513d79acf6691fa9cf10f192c90dd2957f18c", + "reference": "bbc513d79acf6691fa9cf10f192c90dd2957f18c", "shasum": "" }, "require": { - "php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0" + "php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0" }, "require-dev": { "cerdic/css-tidy": "^1.7 || ^2.0", @@ -358,9 +315,9 @@ ], "support": { "issues": "https://github.com/ezyang/htmlpurifier/issues", - "source": "https://github.com/ezyang/htmlpurifier/tree/v4.16.0" + "source": "https://github.com/ezyang/htmlpurifier/tree/v4.17.0" }, - "time": "2022-09-18T07:06:19+00:00" + "time": "2023-11-17T15:01:25+00:00" }, { "name": "flexihash/flexihash", @@ -473,44 +430,56 @@ "time": "2023-02-20T17:27:30+00:00" }, { - "name": "ifixit/php-akismet", - "version": "1.1", - "source": { - "type": "git", - "url": "https://github.com/iFixit/php-akismet.git", - "reference": "fd4ff50eb577457c1b7b887401663e91e77625ae" - }, - "type": "library" - }, - { - "name": "naroga/redis-cache", - "version": "dev-master", + "name": "guzzlehttp/guzzle", + "version": "7.9.x-dev", "source": { "type": "git", - "url": "https://github.com/naroga/redis-cache.git", - "reference": "c32ee4ce2efcf8292cac6b6192c17c0306320d04" + "url": "https://github.com/guzzle/guzzle.git", + "reference": "41042bc7ab002487b876a0683fc8dce04ddce104" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/naroga/redis-cache/zipball/c32ee4ce2efcf8292cac6b6192c17c0306320d04", - "reference": "c32ee4ce2efcf8292cac6b6192c17c0306320d04", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/41042bc7ab002487b876a0683fc8dce04ddce104", + "reference": "41042bc7ab002487b876a0683fc8dce04ddce104", "shasum": "" }, "require": { - "php": ">=5.3.3", - "predis/predis": "^1.1", - "psr/simple-cache": "~1.0" + "ext-json": "*", + "guzzlehttp/promises": "^1.5.3 || ^2.0.1", + "guzzlehttp/psr7": "^1.9.1 || ^2.5.1", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" }, "require-dev": { - "phpunit/php-code-coverage": ">=2.2.4", - "phpunit/phpunit": ">=3.7.38", - "satooshi/php-coveralls": ">=1.0.1" + "bamarni/composer-bin-plugin": "^1.8.2", + "ext-curl": "*", + "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", + "php-http/message-factory": "^1.1", + "phpunit/phpunit": "^8.5.36 || ^9.6.15", + "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 + } + }, "autoload": { + "files": [ + "src/functions_include.php" + ], "psr-4": { - "Naroga\\RedisCache\\": "." + "GuzzleHttp\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -519,51 +488,105 @@ ], "authors": [ { - "name": "Pedro Cordeiro", - "email": "pedro.cordeiro@sympla.com.br" + "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": "A Redis driver that implements PSR-16 (Simple Cache)", + "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/naroga/redis-cache/issues", - "source": "https://github.com/naroga/redis-cache/tree/1.2" + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.8.1" }, - "time": "2021-01-25T13:15:08+00:00" + "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": "2023-12-03T20:35:24+00:00" }, { - "name": "opis/closure", - "version": "dev-master", + "name": "guzzlehttp/promises", + "version": "2.0.x-dev", "source": { "type": "git", - "url": "https://github.com/opis/closure.git", - "reference": "3d81e4309d2a927abbe66df935f4bb60082805ad" + "url": "https://github.com/guzzle/promises.git", + "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opis/closure/zipball/3d81e4309d2a927abbe66df935f4bb60082805ad", - "reference": "3d81e4309d2a927abbe66df935f4bb60082805ad", + "url": "https://api.github.com/repos/guzzle/promises/zipball/bbff78d96034045e58e13dedd6ad91b5d1253223", + "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223", "shasum": "" }, "require": { - "php": "^5.4 || ^7.0 || ^8.0" + "php": "^7.2.5 || ^8.0" }, "require-dev": { - "jeremeamia/superclosure": "^2.0", - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0" + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.36 || ^9.6.15" }, "default-branch": true, "type": "library", "extra": { - "branch-alias": { - "dev-master": "3.6.x-dev" + "bamarni-bin": { + "bin-links": true, + "forward-command": false } }, "autoload": { - "files": [ - "functions.php" - ], "psr-4": { - "Opis\\Closure\\": "src/" + "GuzzleHttp\\Promise\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -572,58 +595,93 @@ ], "authors": [ { - "name": "Marius Sarca", - "email": "marius.sarca@gmail.com" + "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": "Sorin Sarca", - "email": "sarca_sorin@hotmail.com" + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" } ], - "description": "A library that can be used to serialize closures (anonymous functions) and arbitrary objects.", - "homepage": "https://opis.io/closure", + "description": "Guzzle promises library", "keywords": [ - "anonymous functions", - "closure", - "function", - "serializable", - "serialization", - "serialize" + "promise" ], "support": { - "issues": "https://github.com/opis/closure/issues", - "source": "https://github.com/opis/closure/tree/3.6.3" + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/2.0.2" }, - "time": "2022-01-27T09:35:39+00:00" + "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": "2023-12-03T20:19:20+00:00" }, { - "name": "predis/predis", - "version": "v1.x-dev", + "name": "guzzlehttp/psr7", + "version": "2.6.x-dev", "source": { "type": "git", - "url": "https://github.com/predis/predis.git", - "reference": "deee2b6d605eb6401446f6f6354414ab7571a5a0" + "url": "https://github.com/guzzle/psr7.git", + "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/predis/predis/zipball/deee2b6d605eb6401446f6f6354414ab7571a5a0", - "reference": "deee2b6d605eb6401446f6f6354414ab7571a5a0", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/45b30f99ac27b5ca93cb4831afe16285f57b8221", + "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221", "shasum": "" }, "require": { - "php": ">=5.3.9" + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0", + "ralouphie/getallheaders": "^3.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" }, "require-dev": { - "phpunit/phpunit": "~4.8" + "bamarni/composer-bin-plugin": "^1.8.2", + "http-interop/http-factory-tests": "^0.9", + "phpunit/phpunit": "^8.5.36 || ^9.6.15" }, "suggest": { - "ext-curl": "Allows access to Webdis when paired with phpiredis", - "ext-phpiredis": "Allows faster serialization and deserialization of the Redis protocol" + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" }, + "default-branch": true, "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, "autoload": { "psr-4": { - "Predis\\": "src/" + "GuzzleHttp\\Psr7\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -632,62 +690,120 @@ ], "authors": [ { - "name": "Daniele Alessandri", - "email": "suppakilla@gmail.com", - "homepage": "http://clorophilla.net", - "role": "Creator & Maintainer" + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" }, { - "name": "Till Krüss", - "homepage": "https://till.im", - "role": "Maintainer" + "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": "Flexible and feature-complete Redis client for PHP and HHVM", - "homepage": "http://github.com/predis/predis", + "description": "PSR-7 message implementation that also provides common utility methods", "keywords": [ - "nosql", - "predis", - "redis" + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" ], "support": { - "issues": "https://github.com/predis/predis/issues", - "source": "https://github.com/predis/predis/tree/v1.x" + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/2.6.2" }, "funding": [ { - "url": "https://github.com/sponsors/tillkruss", + "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-09-19T16:11:21+00:00" + "time": "2023-12-03T20:05:35+00:00" }, { - "name": "psr/simple-cache", - "version": "1.0.1", + "name": "ifixit/php-akismet", + "version": "1.1", "source": { "type": "git", - "url": "https://github.com/php-fig/simple-cache.git", - "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" + "url": "https://github.com/iFixit/php-akismet.git", + "reference": "fd4ff50eb577457c1b7b887401663e91e77625ae" + }, + "type": "library" + }, + { + "name": "mtdowling/jmespath.php", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/jmespath/jmespath.php.git", + "reference": "b243cacd2a9803b4cbc259246aa5081208238c10" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", - "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/b243cacd2a9803b4cbc259246aa5081208238c10", + "reference": "b243cacd2a9803b4cbc259246aa5081208238c10", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": "^7.2.5 || ^8.0", + "symfony/polyfill-mbstring": "^1.17" + }, + "require-dev": { + "composer/xdebug-handler": "^3.0.3", + "phpunit/phpunit": "^8.5.33" }, + "default-branch": true, + "bin": [ + "bin/jp.php" + ], "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.7-dev" } }, "autoload": { + "files": [ + "src/JmesPath.php" + ], "psr-4": { - "Psr\\SimpleCache\\": "src/" + "JmesPath\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -696,117 +812,104 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "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" } ], - "description": "Common interfaces for simple caching", + "description": "Declaratively specify how to extract elements from a JSON document", "keywords": [ - "cache", - "caching", - "psr", - "psr-16", - "simple-cache" + "json", + "jsonpath" ], "support": { - "source": "https://github.com/php-fig/simple-cache/tree/master" + "issues": "https://github.com/jmespath/jmespath.php/issues", + "source": "https://github.com/jmespath/jmespath.php/tree/master" }, - "time": "2017-10-23T01:57:42+00:00" + "time": "2023-11-30T16:26:47+00:00" }, { - "name": "sabre/cache", - "version": "2.0.1", + "name": "naroga/redis-cache", + "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/sabre-io/cache.git", - "reference": "a843741b85025d8674bf4713121cae60172e6f86" + "url": "https://github.com/naroga/redis-cache.git", + "reference": "c32ee4ce2efcf8292cac6b6192c17c0306320d04" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sabre-io/cache/zipball/a843741b85025d8674bf4713121cae60172e6f86", - "reference": "a843741b85025d8674bf4713121cae60172e6f86", + "url": "https://api.github.com/repos/naroga/redis-cache/zipball/c32ee4ce2efcf8292cac6b6192c17c0306320d04", + "reference": "c32ee4ce2efcf8292cac6b6192c17c0306320d04", "shasum": "" }, "require": { - "php": "^7.4 || ^8.0", - "psr/simple-cache": "^1.0" - }, - "provide": { - "psr/simple-cache-implementation": "~1.0" + "php": ">=5.3.3", + "predis/predis": "^1.1", + "psr/simple-cache": "~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" + "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": { - "Sabre\\Cache\\": "lib/" + "Naroga\\RedisCache\\": "." } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Evert Pot", - "email": "me@evertpot.com", - "homepage": "https://evertpot.com/", - "role": "Developer" + "name": "Pedro Cordeiro", + "email": "pedro.cordeiro@sympla.com.br" } ], - "description": "Simple cache abstraction layer implementing PSR-16", - "homepage": "http://sabre.io/dav/", - "keywords": [ - "apc", - "apcu", - "cache", - "memcache", - "memcached", - "psr-16", - "sabre", - "simple-cache" - ], + "description": "A Redis driver that implements PSR-16 (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" + "issues": "https://github.com/naroga/redis-cache/issues", + "source": "https://github.com/naroga/redis-cache/tree/1.2" }, - "time": "2023-02-09T23:47:10+00:00" + "time": "2021-01-25T13:15:08+00:00" }, { - "name": "shish/eventtracer-php", - "version": "v2.1.0", + "name": "predis/predis", + "version": "v1.x-dev", "source": { "type": "git", - "url": "https://github.com/shish/eventtracer-php.git", - "reference": "5dfe2c090c8b7df772e982520c36f44b33ead035" + "url": "https://github.com/predis/predis.git", + "reference": "deee2b6d605eb6401446f6f6354414ab7571a5a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/shish/eventtracer-php/zipball/5dfe2c090c8b7df772e982520c36f44b33ead035", - "reference": "5dfe2c090c8b7df772e982520c36f44b33ead035", + "url": "https://api.github.com/repos/predis/predis/zipball/deee2b6d605eb6401446f6f6354414ab7571a5a0", + "reference": "deee2b6d605eb6401446f6f6354414ab7571a5a0", "shasum": "" }, "require": { - "ext-json": "*", - "php": "^8.0" + "php": ">=5.3.9" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.12", - "phpstan/phpstan": "^1.9", - "phpunit/phpunit": "^9.0" + "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": { - "classmap": [ - "src/" - ] + "psr-4": { + "Predis\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -814,47 +917,64 @@ ], "authors": [ { - "name": "Shish", - "email": "webmaster@shishnet.org", - "homepage": "http://shishnet.org", - "role": "Developer" + "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": "An API to write JSON traces as used by the Chrome Trace Viewer", - "homepage": "https://github.com/shish/eventtracer-php", + "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/shish/eventtracer-php/issues", - "source": "https://github.com/shish/eventtracer-php/tree/v2.1.0" - }, - "time": "2023-02-04T12:26:41+00:00" + "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-09-19T16:11:21+00:00" }, { - "name": "shish/ffsphp", - "version": "v1.2.0", + "name": "psr/http-client", + "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/shish/ffsphp.git", - "reference": "a2a1f0fe59606b90460513b48bacb442630dd253" + "url": "https://github.com/php-fig/http-client.git", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/shish/ffsphp/zipball/a2a1f0fe59606b90460513b48bacb442630dd253", - "reference": "a2a1f0fe59606b90460513b48bacb442630dd253", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", "shasum": "" }, "require": { - "ext-pdo": "*", - "php": "^8.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^3.12", - "phpstan/phpstan": "^1.9", - "phpunit/phpunit": "^9.0" + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0 || ^2.0" }, + "default-branch": true, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, "autoload": { "psr-4": { - "FFSPHP\\": "src" + "Psr\\Http\\Client\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -863,48 +983,51 @@ ], "authors": [ { - "name": "Shish", - "email": "webmaster@shishnet.org", - "homepage": "http://shishnet.org", - "role": "Developer" + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" } ], - "description": "A collection of workarounds for stupid PHP things", - "homepage": "https://github.com/shish/ffsphp", + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], "support": { - "issues": "https://github.com/shish/ffsphp/issues", - "source": "https://github.com/shish/ffsphp/tree/v1.2.0" + "source": "https://github.com/php-fig/http-client" }, - "time": "2023-08-28T15:51:16+00:00" + "time": "2023-09-23T14:17:50+00:00" }, { - "name": "shish/gqla", - "version": "dev-main", + "name": "psr/http-factory", + "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/shish/gqla.git", - "reference": "26bf0405445f4e32e68cd7f1ea2256e81c6c42cb" + "url": "https://github.com/php-fig/http-factory.git", + "reference": "7037f4b0950474e9d1350e8df89b15f1842085f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/shish/gqla/zipball/26bf0405445f4e32e68cd7f1ea2256e81c6c42cb", - "reference": "26bf0405445f4e32e68cd7f1ea2256e81c6c42cb", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/7037f4b0950474e9d1350e8df89b15f1842085f6", + "reference": "7037f4b0950474e9d1350e8df89b15f1842085f6", "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" + "php": ">=7.0.0", + "psr/http-message": "^1.0 || ^2.0" }, "default-branch": true, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, "autoload": { "psr-4": { - "GQLA\\": "src" + "Psr\\Http\\Message\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -913,52 +1036,53 @@ ], "authors": [ { - "name": "Shish", - "email": "webmaster@shishnet.org", - "homepage": "https://shish.io", - "role": "Developer" + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" } ], - "description": "A set of annotations for generating graphql APIs", - "homepage": "https://github.com/shish/gqla", + "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", "keywords": [ - "graphql" + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" ], "support": { - "issues": "https://github.com/shish/gqla/issues", - "source": "https://github.com/shish/gqla/tree/main" + "source": "https://github.com/php-fig/http-factory" }, - "time": "2023-03-03T00:12:44+00:00" + "time": "2023-09-22T11:16:44+00:00" }, { - "name": "shish/microcrud", - "version": "v2.1.1", + "name": "psr/http-message", + "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/shish/microcrud.git", - "reference": "8f0c38af61e2543c2e11ad6face37ae34e4571cf" + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/shish/microcrud/zipball/8f0c38af61e2543c2e11ad6face37ae34e4571cf", - "reference": "8f0c38af61e2543c2e11ad6face37ae34e4571cf", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", "shasum": "" }, "require": { - "ext-pdo": "*", - "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" + "php": "^7.2 || ^8.0" }, + "default-branch": true, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, "autoload": { "psr-4": { - "MicroCRUD\\": "src" + "Psr\\Http\\Message\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -967,51 +1091,52 @@ ], "authors": [ { - "name": "Shish", - "email": "webmaster@shishnet.org", - "homepage": "http://shishnet.org", - "role": "Developer" + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" } ], - "description": "A minimal CRUD generating library", - "homepage": "https://github.com/shish/microcrud", + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", "keywords": [ - "crud", - "generator" + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" ], "support": { - "issues": "https://github.com/shish/microcrud/issues", - "source": "https://github.com/shish/microcrud/tree/v2.1.1" + "source": "https://github.com/php-fig/http-message/tree/2.0" }, - "time": "2023-11-11T21:25:53+00:00" + "time": "2023-04-04T09:54:51+00:00" }, { - "name": "shish/microhtml", - "version": "v2.2.1", + "name": "psr/simple-cache", + "version": "1.0.1", "source": { "type": "git", - "url": "https://github.com/shish/microhtml.git", - "reference": "824d8541c7f0662e26d03d65d865d8f13ea57a72" + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/shish/microhtml/zipball/824d8541c7f0662e26d03d65d865d8f13ea57a72", - "reference": "824d8541c7f0662e26d03d65d865d8f13ea57a72", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", "shasum": "" }, "require": { - "php": "^8.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^3.12", - "phpstan/phpstan": "^1.9", - "phpunit/phpunit": "^9.0" + "php": ">=5.3.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, "autoload": { - "files": [ - "src/microhtml.php" - ] + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1019,118 +1144,609 @@ ], "authors": [ { - "name": "Shish", - "email": "webmaster@shishnet.org", - "homepage": "http://shishnet.org", - "role": "Developer" + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" } ], - "description": "A minimal HTML generating library", - "homepage": "https://github.com/shish/microhtml", + "description": "Common interfaces for simple caching", "keywords": [ - "generator", - "html" + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" ], "support": { - "issues": "https://github.com/shish/microhtml/issues", - "source": "https://github.com/shish/microhtml/tree/v2.2.1" + "source": "https://github.com/php-fig/simple-cache/tree/master" }, - "time": "2023-08-17T16:39:06+00:00" + "time": "2017-10-23T01:57:42+00:00" }, { - "name": "tbela99/css", - "version": "dev-master", + "name": "ralouphie/getallheaders", + "version": "3.0.3", "source": { "type": "git", - "url": "https://github.com/shish/php-css.git", - "reference": "bc343fe231a4c0fea6ef7405228f010956a5cd07" + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/shish/php-css/zipball/bc343fe231a4c0fea6ef7405228f010956a5cd07", - "reference": "bc343fe231a4c0fea6ef7405228f010956a5cd07", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", "shasum": "" }, "require": { - "axy/sourcemap": "^0.1.5", - "ext-json": "*", - "ext-mbstring": "*", - "opis/closure": "^3.6", - "php": ">=8.0" + "php": ">=5.6" }, "require-dev": { - "phpunit/phpunit": "^9.5" - }, - "suggest": { - "ext-curl": "*", - "ext-pcntl": "*", - "ext-sockets": "*" + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" }, - "default-branch": true, - "bin": [ - "cli/css-parser" - ], "type": "library", "autoload": { - "psr-4": { - "TBela\\CSS\\": "src" - } - }, - "archive": { - "exclude": [ - "*.sh", - "*.phar", - "test/", - "tool/", - "docs/", - "bin/" - ] - }, - "scripts": { - "test": [ - "./bin/runtest.sh" + "files": [ + "src/getallheaders.php" ] }, + "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT", - "LGPL-3.0-or-later" + "MIT" ], "authors": [ { - "name": "Thierry Bela", - "homepage": "https://tbela.net", - "role": "Developer" + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" } ], - "description": "A CSS parser and minifier written in PHP", - "homepage": "https://github.com/tbela99/css", - "keywords": [ - "Ast", - "CSS", - "PHP", - "beautifier", - "css-parser", - "minifier", - "parser", - "stylesheet" - ], + "description": "A polyfill for getallheaders.", "support": { - "source": "https://github.com/shish/php-css/tree/master" + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" }, - "time": "2023-08-18T18:26:28+00:00" + "time": "2019-03-08T08:55:37+00:00" }, { - "name": "webonyx/graphql-php", - "version": "v15.7.0", + "name": "sabre/cache", + "version": "2.0.1", "source": { "type": "git", - "url": "https://github.com/webonyx/graphql-php.git", - "reference": "44ff70977ee020c0b24bfdfaf947be56943de505" + "url": "https://github.com/sabre-io/cache.git", + "reference": "a843741b85025d8674bf4713121cae60172e6f86" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webonyx/graphql-php/zipball/44ff70977ee020c0b24bfdfaf947be56943de505", - "reference": "44ff70977ee020c0b24bfdfaf947be56943de505", + "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": "^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.12", + "phpstan/phpstan": "^1.9", + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Shish", + "email": "webmaster@shishnet.org", + "homepage": "http://shishnet.org", + "role": "Developer" + } + ], + "description": "An API to write JSON traces as used by the Chrome Trace Viewer", + "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.1.0" + }, + "time": "2023-02-04T12:26:41+00:00" + }, + { + "name": "shish/ffsphp", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/shish/ffsphp.git", + "reference": "26eea8149fda5f20bed7399b8b4a84946448bec0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/shish/ffsphp/zipball/26eea8149fda5f20bed7399b8b4a84946448bec0", + "reference": "26eea8149fda5f20bed7399b8b4a84946448bec0", + "shasum": "" + }, + "require": { + "ext-pdo": "*", + "php": "^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "3.41.1", + "phpstan/phpstan": "1.10.50", + "phpunit/phpunit": "10.5.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "FFSPHP\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Shish", + "email": "webmaster@shishnet.org", + "homepage": "http://shishnet.org", + "role": "Developer" + } + ], + "description": "A collection of workarounds for stupid PHP things", + "homepage": "https://github.com/shish/ffsphp", + "support": { + "issues": "https://github.com/shish/ffsphp/issues", + "source": "https://github.com/shish/ffsphp/tree/v1.3.0" + }, + "time": "2024-01-01T14:48:00+00:00" + }, + { + "name": "shish/gqla", + "version": "dev-main", + "source": { + "type": "git", + "url": "https://github.com/shish/gqla.git", + "reference": "26bf0405445f4e32e68cd7f1ea2256e81c6c42cb" + }, + "dist": { + "type": "zip", + "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/microbundler", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/shish/microbundler.git", + "reference": "5f48327e92d3601f2c86caef2856b9671a63b6b0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/shish/microbundler/zipball/5f48327e92d3601f2c86caef2856b9671a63b6b0", + "reference": "5f48327e92d3601f2c86caef2856b9671a63b6b0", + "shasum": "" + }, + "require": { + "php": "^8.1", + "shish/ffsphp": "^1.3" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "3.41.1", + "phpstan/phpstan": "1.10.50", + "phpunit/phpunit": "10.5.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "MicroBundler\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Shish", + "email": "webmaster@shishnet.org", + "homepage": "http://shishnet.org", + "role": "Developer" + } + ], + "description": "A minimal CSS / JS bundler", + "homepage": "https://github.com/shish/microbundler", + "keywords": [ + "JS", + "bundler", + "css" + ], + "support": { + "issues": "https://github.com/shish/microbundler/issues", + "source": "https://github.com/shish/microbundler/tree/v1.0.1" + }, + "time": "2024-01-01T19:58:28+00:00" + }, + { + "name": "shish/microcrud", + "version": "v2.1.1", + "source": { + "type": "git", + "url": "https://github.com/shish/microcrud.git", + "reference": "8f0c38af61e2543c2e11ad6face37ae34e4571cf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/shish/microcrud/zipball/8f0c38af61e2543c2e11ad6face37ae34e4571cf", + "reference": "8f0c38af61e2543c2e11ad6face37ae34e4571cf", + "shasum": "" + }, + "require": { + "ext-pdo": "*", + "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", + "autoload": { + "psr-4": { + "MicroCRUD\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Shish", + "email": "webmaster@shishnet.org", + "homepage": "http://shishnet.org", + "role": "Developer" + } + ], + "description": "A minimal CRUD generating library", + "homepage": "https://github.com/shish/microcrud", + "keywords": [ + "crud", + "generator" + ], + "support": { + "issues": "https://github.com/shish/microcrud/issues", + "source": "https://github.com/shish/microcrud/tree/v2.1.1" + }, + "time": "2023-11-11T21:25:53+00:00" + }, + { + "name": "shish/microhtml", + "version": "v2.2.1", + "source": { + "type": "git", + "url": "https://github.com/shish/microhtml.git", + "reference": "824d8541c7f0662e26d03d65d865d8f13ea57a72" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/shish/microhtml/zipball/824d8541c7f0662e26d03d65d865d8f13ea57a72", + "reference": "824d8541c7f0662e26d03d65d865d8f13ea57a72", + "shasum": "" + }, + "require": { + "php": "^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.12", + "phpstan/phpstan": "^1.9", + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "autoload": { + "files": [ + "src/microhtml.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Shish", + "email": "webmaster@shishnet.org", + "homepage": "http://shishnet.org", + "role": "Developer" + } + ], + "description": "A minimal HTML generating library", + "homepage": "https://github.com/shish/microhtml", + "keywords": [ + "generator", + "html" + ], + "support": { + "issues": "https://github.com/shish/microhtml/issues", + "source": "https://github.com/shish/microhtml/tree/v2.2.1" + }, + "time": "2023-08-17T16:39:06+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "dev-main", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", + "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "default-branch": true, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.4-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "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": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.4.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-05-23T14:45:45+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "1.x-dev", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "42292d99c55abe617799667f454222c54c60e229" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", + "reference": "42292d99c55abe617799667f454222c54c60e229", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "default-branch": true, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.28-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-07-28T09:04:16+00:00" + }, + { + "name": "webonyx/graphql-php", + "version": "v15.8.1", + "source": { + "type": "git", + "url": "https://github.com/webonyx/graphql-php.git", + "reference": "575ac95f13adfb38219a748572355385c101fdf7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webonyx/graphql-php/zipball/575ac95f13adfb38219a748572355385c101fdf7", + "reference": "575ac95f13adfb38219a748572355385c101fdf7", "shasum": "" }, "require": { @@ -1148,16 +1764,16 @@ "nyholm/psr7": "^1.5", "phpbench/phpbench": "^1.2", "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "1.10.37", - "phpstan/phpstan-phpunit": "1.3.14", - "phpstan/phpstan-strict-rules": "1.5.1", + "phpstan/phpstan": "1.10.47", + "phpstan/phpstan-phpunit": "1.3.15", + "phpstan/phpstan-strict-rules": "1.5.2", "phpunit/phpunit": "^9.5 || ^10", "psr/http-message": "^1 || ^2", "react/http": "^1.6", "react/promise": "^2.9", "rector/rector": "^0.18", "symfony/polyfill-php81": "^1.23", - "symfony/var-exporter": "^5 || ^6", + "symfony/var-exporter": "^5 || ^6 || ^7", "thecodingmachine/safe": "^1.3 || ^2" }, "suggest": { @@ -1183,7 +1799,7 @@ ], "support": { "issues": "https://github.com/webonyx/graphql-php/issues", - "source": "https://github.com/webonyx/graphql-php/tree/v15.7.0" + "source": "https://github.com/webonyx/graphql-php/tree/v15.8.1" }, "funding": [ { @@ -1191,7 +1807,7 @@ "type": "open_collective" } ], - "time": "2023-10-04T09:10:34+00:00" + "time": "2023-12-05T17:23:35+00:00" } ], "packages-dev": [ @@ -1484,306 +2100,46 @@ "keywords": [ "annotations", "docblock", - "parser" - ], - "support": { - "issues": "https://github.com/doctrine/annotations/issues", - "source": "https://github.com/doctrine/annotations/tree/2.0.x" - }, - "time": "2023-08-23T17:36:07+00:00" - }, - { - "name": "doctrine/instantiator", - "version": "2.0.x-dev", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "f49f6a836a816609c853718ba2ea422dc18a8e4a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/f49f6a836a816609c853718ba2ea422dc18a8e4a", - "reference": "f49f6a836a816609c853718ba2ea422dc18a8e4a", - "shasum": "" - }, - "require": { - "php": "^8.1" - }, - "require-dev": { - "doctrine/coding-standard": "^11", - "ext-pdo": "*", - "ext-phar": "*", - "phpbench/phpbench": "^1.2", - "phpstan/phpstan": "^1.9.4", - "phpstan/phpstan-phpunit": "^1.3", - "phpunit/phpunit": "^10.1.0", - "vimeo/psalm": "^5.4" - }, - "default-branch": true, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "https://ocramius.github.io/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://www.doctrine-project.org/projects/instantiator.html", - "keywords": [ - "constructor", - "instantiate" - ], - "support": { - "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/2.0.x" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", - "type": "tidelift" - } - ], - "time": "2023-08-24T20:23:35+00:00" - }, - { - "name": "doctrine/lexer", - "version": "3.1.x-dev", - "source": { - "type": "git", - "url": "https://github.com/doctrine/lexer.git", - "reference": "0d54c073afb397d5896df60cc34170cf37dfad5e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/0d54c073afb397d5896df60cc34170cf37dfad5e", - "reference": "0d54c073afb397d5896df60cc34170cf37dfad5e", - "shasum": "" - }, - "require": { - "php": "^8.1" - }, - "require-dev": { - "doctrine/coding-standard": "^10", - "phpstan/phpstan": "^1.9", - "phpunit/phpunit": "^9.5", - "psalm/plugin-phpunit": "^0.18.3", - "vimeo/psalm": "^5.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Lexer\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", - "homepage": "https://www.doctrine-project.org/projects/lexer.html", - "keywords": [ - "annotations", - "docblock", - "lexer", - "parser", - "php" - ], - "support": { - "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/3.1.x" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", - "type": "tidelift" - } - ], - "time": "2023-07-05T07:23:35+00:00" - }, - { - "name": "friendsofphp/php-cs-fixer", - "version": "v3.38.0", - "source": { - "type": "git", - "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "7e6070026e76aa09d77a47519625c86593fb8e31" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/7e6070026e76aa09d77a47519625c86593fb8e31", - "reference": "7e6070026e76aa09d77a47519625c86593fb8e31", - "shasum": "" - }, - "require": { - "composer/semver": "^3.3", - "composer/xdebug-handler": "^3.0.3", - "ext-json": "*", - "ext-tokenizer": "*", - "php": "^7.4 || ^8.0", - "sebastian/diff": "^4.0 || ^5.0", - "symfony/console": "^5.4 || ^6.0", - "symfony/event-dispatcher": "^5.4 || ^6.0", - "symfony/filesystem": "^5.4 || ^6.0", - "symfony/finder": "^5.4 || ^6.0", - "symfony/options-resolver": "^5.4 || ^6.0", - "symfony/polyfill-mbstring": "^1.27", - "symfony/polyfill-php80": "^1.27", - "symfony/polyfill-php81": "^1.27", - "symfony/process": "^5.4 || ^6.0", - "symfony/stopwatch": "^5.4 || ^6.0" - }, - "require-dev": { - "facile-it/paraunit": "^1.3 || ^2.0", - "justinrainbow/json-schema": "^5.2", - "keradus/cli-executor": "^2.0", - "mikey179/vfsstream": "^1.6.11", - "php-coveralls/php-coveralls": "^2.5.3", - "php-cs-fixer/accessible-object": "^1.1", - "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.2", - "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.2.1", - "phpspec/prophecy": "^1.16", - "phpspec/prophecy-phpunit": "^2.0", - "phpunit/phpunit": "^9.5", - "symfony/phpunit-bridge": "^6.2.3", - "symfony/yaml": "^5.4 || ^6.0" - }, - "suggest": { - "ext-dom": "For handling output formats in XML", - "ext-mbstring": "For handling non-UTF8 characters." - }, - "bin": [ - "php-cs-fixer" - ], - "type": "application", - "autoload": { - "psr-4": { - "PhpCsFixer\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Dariusz Rumiński", - "email": "dariusz.ruminski@gmail.com" - } - ], - "description": "A tool to automatically fix PHP code style", - "keywords": [ - "Static code analysis", - "fixer", - "standards", - "static analysis" - ], - "support": { - "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.38.0" - }, - "funding": [ - { - "url": "https://github.com/keradus", - "type": "github" - } + "parser" ], - "time": "2023-11-07T08:44:54+00:00" + "support": { + "issues": "https://github.com/doctrine/annotations/issues", + "source": "https://github.com/doctrine/annotations/tree/2.0.x" + }, + "time": "2023-08-23T17:36:07+00:00" }, { - "name": "guzzlehttp/guzzle", - "version": "7.9.x-dev", + "name": "doctrine/instantiator", + "version": "2.0.x-dev", "source": { "type": "git", - "url": "https://github.com/guzzle/guzzle.git", - "reference": "d95d9ab74822c2ca06b31477cd6775a4a299b8e8" + "url": "https://github.com/doctrine/instantiator.git", + "reference": "6c0ee619435c5d4f3bc515ab1514cf4cf1006c6e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/d95d9ab74822c2ca06b31477cd6775a4a299b8e8", - "reference": "d95d9ab74822c2ca06b31477cd6775a4a299b8e8", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/6c0ee619435c5d4f3bc515ab1514cf4cf1006c6e", + "reference": "6c0ee619435c5d4f3bc515ab1514cf4cf1006c6e", "shasum": "" }, "require": { - "ext-json": "*", - "guzzlehttp/promises": "^1.5.3 || ^2.0.1", - "guzzlehttp/psr7": "^1.9.1 || ^2.5.1", - "php": "^7.2.5 || ^8.0", - "psr/http-client": "^1.0", - "symfony/deprecation-contracts": "^2.2 || ^3.0" - }, - "provide": { - "psr/http-client-implementation": "1.0" + "php": "^8.1" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.1", - "ext-curl": "*", - "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", - "php-http/message-factory": "^1.1", - "phpunit/phpunit": "^8.5.29 || ^9.5.23", - "psr/log": "^1.1 || ^2.0 || ^3.0" - }, - "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" + "doctrine/coding-standard": "^12", + "ext-pdo": "*", + "ext-phar": "*", + "phpbench/phpbench": "^1.2", + "phpstan/phpstan": "^1.9.4", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^10.5", + "vimeo/psalm": "^5.4" }, + "default-branch": true, "type": "library", - "extra": { - "bamarni-bin": { - "bin-links": true, - "forward-command": false - } - }, "autoload": { - "files": [ - "src/functions_include.php" - ], "psr-4": { - "GuzzleHttp\\": "src/" + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1792,105 +2148,65 @@ ], "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" + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "https://ocramius.github.io/" } ], - "description": "Guzzle is a PHP HTTP client library", + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", "keywords": [ - "client", - "curl", - "framework", - "http", - "http client", - "psr-18", - "psr-7", - "rest", - "web service" + "constructor", + "instantiate" ], "support": { - "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.8" + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/2.0.x" }, "funding": [ { - "url": "https://github.com/GrahamCampbell", - "type": "github" + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" }, { - "url": "https://github.com/Nyholm", - "type": "github" + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" }, { - "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", "type": "tidelift" } ], - "time": "2023-09-11T09:12:01+00:00" + "time": "2023-12-09T14:19:21+00:00" }, { - "name": "guzzlehttp/promises", - "version": "2.0.x-dev", + "name": "doctrine/lexer", + "version": "3.1.x-dev", "source": { "type": "git", - "url": "https://github.com/guzzle/promises.git", - "reference": "71b12f952d8be69a239989db2fe08314a5189e3b" + "url": "https://github.com/doctrine/lexer.git", + "reference": "0d54c073afb397d5896df60cc34170cf37dfad5e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/71b12f952d8be69a239989db2fe08314a5189e3b", - "reference": "71b12f952d8be69a239989db2fe08314a5189e3b", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/0d54c073afb397d5896df60cc34170cf37dfad5e", + "reference": "0d54c073afb397d5896df60cc34170cf37dfad5e", "shasum": "" }, "require": { - "php": "^7.2.5 || ^8.0" + "php": "^8.1" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.1", - "phpunit/phpunit": "^8.5.29 || ^9.5.23" + "doctrine/coding-standard": "^10", + "phpstan/phpstan": "^1.9", + "phpunit/phpunit": "^9.5", + "psalm/plugin-phpunit": "^0.18.3", + "vimeo/psalm": "^5.0" }, - "default-branch": true, "type": "library", - "extra": { - "bamarni-bin": { - "bin-links": true, - "forward-command": false - } - }, "autoload": { "psr-4": { - "GuzzleHttp\\Promise\\": "src/" + "Doctrine\\Common\\Lexer\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -1899,93 +2215,103 @@ ], "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": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" }, { - "name": "Tobias Nyholm", - "email": "tobias.nyholm@gmail.com", - "homepage": "https://github.com/Nyholm" + "name": "Roman Borschel", + "email": "roman@code-factory.org" }, { - "name": "Tobias Schultze", - "email": "webmaster@tubo-world.de", - "homepage": "https://github.com/Tobion" + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" } ], - "description": "Guzzle promises library", + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", "keywords": [ - "promise" + "annotations", + "docblock", + "lexer", + "parser", + "php" ], "support": { - "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/2.0" + "issues": "https://github.com/doctrine/lexer/issues", + "source": "https://github.com/doctrine/lexer/tree/3.1.x" }, "funding": [ { - "url": "https://github.com/GrahamCampbell", - "type": "github" + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" }, { - "url": "https://github.com/Nyholm", - "type": "github" + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" }, { - "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", "type": "tidelift" } ], - "time": "2023-08-27T10:15:36+00:00" + "time": "2023-07-05T07:23:35+00:00" }, { - "name": "guzzlehttp/psr7", - "version": "2.6.x-dev", + "name": "friendsofphp/php-cs-fixer", + "version": "v3.41.1", "source": { "type": "git", - "url": "https://github.com/guzzle/psr7.git", - "reference": "38ef514a6c21335f29d9be64b097d2582ecbf8e4" + "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", + "reference": "8b6ae8dcbaf23f09680643ab832a4a3a260265f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/38ef514a6c21335f29d9be64b097d2582ecbf8e4", - "reference": "38ef514a6c21335f29d9be64b097d2582ecbf8e4", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/8b6ae8dcbaf23f09680643ab832a4a3a260265f6", + "reference": "8b6ae8dcbaf23f09680643ab832a4a3a260265f6", "shasum": "" }, "require": { - "php": "^7.2.5 || ^8.0", - "psr/http-factory": "^1.0", - "psr/http-message": "^1.1 || ^2.0", - "ralouphie/getallheaders": "^3.0" - }, - "provide": { - "psr/http-factory-implementation": "1.0", - "psr/http-message-implementation": "1.0" + "composer/semver": "^3.4", + "composer/xdebug-handler": "^3.0.3", + "ext-json": "*", + "ext-tokenizer": "*", + "php": "^7.4 || ^8.0", + "sebastian/diff": "^4.0 || ^5.0", + "symfony/console": "^5.4 || ^6.0 || ^7.0", + "symfony/event-dispatcher": "^5.4 || ^6.0 || ^7.0", + "symfony/filesystem": "^5.4 || ^6.0 || ^7.0", + "symfony/finder": "^5.4 || ^6.0 || ^7.0", + "symfony/options-resolver": "^5.4 || ^6.0 || ^7.0", + "symfony/polyfill-mbstring": "^1.28", + "symfony/polyfill-php80": "^1.28", + "symfony/polyfill-php81": "^1.28", + "symfony/process": "^5.4 || ^6.0 || ^7.0", + "symfony/stopwatch": "^5.4 || ^6.0 || ^7.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" + "facile-it/paraunit": "^1.3 || ^2.0", + "justinrainbow/json-schema": "^5.2", + "keradus/cli-executor": "^2.1", + "mikey179/vfsstream": "^1.6.11", + "php-coveralls/php-coveralls": "^2.7", + "php-cs-fixer/accessible-object": "^1.1", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.4", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.4", + "phpunit/phpunit": "^9.6", + "symfony/phpunit-bridge": "^6.3.8 || ^7.0", + "symfony/yaml": "^5.4 || ^6.0 || ^7.0" }, "suggest": { - "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" - }, - "default-branch": true, - "type": "library", - "extra": { - "bamarni-bin": { - "bin-links": true, - "forward-command": false - } + "ext-dom": "For handling output formats in XML", + "ext-mbstring": "For handling non-UTF8 characters." }, + "bin": [ + "php-cs-fixer" + ], + "type": "application", "autoload": { "psr-4": { - "GuzzleHttp\\Psr7\\": "src/" + "PhpCsFixer\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1994,71 +2320,32 @@ ], "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": "Fabien Potencier", + "email": "fabien@symfony.com" }, { - "name": "Márk Sági-Kazár", - "email": "mark.sagikazar@gmail.com", - "homepage": "https://sagikazarmark.hu" + "name": "Dariusz Rumiński", + "email": "dariusz.ruminski@gmail.com" } ], - "description": "PSR-7 message implementation that also provides common utility methods", + "description": "A tool to automatically fix PHP code style", "keywords": [ - "http", - "message", - "psr-7", - "request", - "response", - "stream", - "uri", - "url" + "Static code analysis", + "fixer", + "standards", + "static analysis" ], "support": { - "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.6" + "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.41.1" }, "funding": [ { - "url": "https://github.com/GrahamCampbell", - "type": "github" - }, - { - "url": "https://github.com/Nyholm", + "url": "https://github.com/keradus", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", - "type": "tidelift" } ], - "time": "2023-09-10T16:11:14+00:00" + "time": "2023-12-10T19:59:27+00:00" }, { "name": "jms/metadata", @@ -2131,12 +2418,12 @@ "source": { "type": "git", "url": "https://github.com/schmittjoh/serializer.git", - "reference": "f24027583f8ad3c1789bff412b039013132316ac" + "reference": "4ff99e4cbba44cdbe57028ec2ccc874c8f61bbe9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/serializer/zipball/f24027583f8ad3c1789bff412b039013132316ac", - "reference": "f24027583f8ad3c1789bff412b039013132316ac", + "url": "https://api.github.com/repos/schmittjoh/serializer/zipball/4ff99e4cbba44cdbe57028ec2ccc874c8f61bbe9", + "reference": "4ff99e4cbba44cdbe57028ec2ccc874c8f61bbe9", "shasum": "" }, "require": { @@ -2144,12 +2431,12 @@ "doctrine/instantiator": "^1.3.1 || ^2.0", "doctrine/lexer": "^2.0 || ^3.0", "jms/metadata": "^2.6", - "php": "^7.2 || ^8.0", + "php": "^7.4 || ^8.0", "phpstan/phpdoc-parser": "^1.20" }, "require-dev": { "doctrine/coding-standard": "^12.0", - "doctrine/orm": "^2.14", + "doctrine/orm": "^2.14 || ^3.0", "doctrine/persistence": "^2.5.2 || ^3.0", "doctrine/phpcr-odm": "^1.5.2 || ^2.0", "ext-pdo_sqlite": "*", @@ -2157,16 +2444,16 @@ "ocramius/proxy-manager": "^1.0 || ^2.0", "phpbench/phpbench": "^1.0", "phpstan/phpstan": "^1.0.2", - "phpunit/phpunit": "^8.5.21 || ^9.0 || ^10.0", + "phpunit/phpunit": "^9.0 || ^10.0", "psr/container": "^1.0 || ^2.0", - "symfony/dependency-injection": "^3.4 || ^4.0 || ^5.0 || ^6.0 || ^7.0", - "symfony/expression-language": "^3.2 || ^4.0 || ^5.0 || ^6.0 || ^7.0", - "symfony/filesystem": "^4.2 || ^5.0 || ^6.0 || ^7.0", - "symfony/form": "^3.4 || ^4.0 || ^5.0 || ^6.0 || ^7.0", - "symfony/translation": "^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0", - "symfony/uid": "^5.1 || ^6.0 || ^7.0", - "symfony/validator": "^3.1.9 || ^4.0 || ^5.0 || ^6.0 || ^7.0", - "symfony/yaml": "^3.4 || ^4.0 || ^5.0 || ^6.0 || ^7.0", + "symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0", + "symfony/expression-language": "^5.4 || ^6.0 || ^7.0", + "symfony/filesystem": "^5.4 || ^6.0 || ^7.0", + "symfony/form": "^5.4 || ^6.0 || ^7.0", + "symfony/translation": "^5.4 || ^6.0 || ^7.0", + "symfony/uid": "^5.4 || ^6.0 || ^7.0", + "symfony/validator": "^5.4 || ^6.0 || ^7.0", + "symfony/yaml": "^5.4 || ^6.0 || ^7.0", "twig/twig": "^1.34 || ^2.4 || ^3.0" }, "suggest": { @@ -2220,7 +2507,7 @@ "type": "github" } ], - "time": "2023-10-29T15:36:01+00:00" + "time": "2023-12-22T14:51:09+00:00" }, { "name": "myclabs/deep-copy", @@ -2285,33 +2572,36 @@ }, { "name": "nikic/php-parser", - "version": "4.x-dev", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "402b6cf3452c21c58aa11d9549cee6205d14e347" + "reference": "1eeeb2d5252d6d8706c5a8d9d88b8d1e7ecf2109" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/402b6cf3452c21c58aa11d9549cee6205d14e347", - "reference": "402b6cf3452c21c58aa11d9549cee6205d14e347", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/1eeeb2d5252d6d8706c5a8d9d88b8d1e7ecf2109", + "reference": "1eeeb2d5252d6d8706c5a8d9d88b8d1e7ecf2109", "shasum": "" }, "require": { + "ext-ctype": "*", + "ext-json": "*", "ext-tokenizer": "*", - "php": ">=7.0" + "php": ">=7.4" }, "require-dev": { "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" }, + "default-branch": true, "bin": [ "bin/php-parse" ], "type": "library", "extra": { "branch-alias": { - "dev-master": "4.9-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -2335,9 +2625,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/4.x" + "source": "https://github.com/nikic/PHP-Parser/tree/master" }, - "time": "2023-11-01T20:31:02+00:00" + "time": "2023-12-22T18:57:32+00:00" }, { "name": "phar-io/manifest", @@ -2464,12 +2754,12 @@ "source": { "type": "git", "url": "https://github.com/schmittjoh/php-option.git", - "reference": "dd3a383e599f49777d8b628dadbb90cae435b87e" + "reference": "416ca2ac2a84555b785a98002d613fe13d1d1c2f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/dd3a383e599f49777d8b628dadbb90cae435b87e", - "reference": "dd3a383e599f49777d8b628dadbb90cae435b87e", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/416ca2ac2a84555b785a98002d613fe13d1d1c2f", + "reference": "416ca2ac2a84555b785a98002d613fe13d1d1c2f", "shasum": "" }, "require": { @@ -2477,14 +2767,14 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.32 || ^9.6.3 || ^10.0.12" + "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" }, "default-branch": true, "type": "library", "extra": { "bamarni-bin": { "bin-links": true, - "forward-command": true + "forward-command": false }, "branch-alias": { "dev-master": "1.9-dev" @@ -2520,7 +2810,7 @@ ], "support": { "issues": "https://github.com/schmittjoh/php-option/issues", - "source": "https://github.com/schmittjoh/php-option/tree/1.9.1" + "source": "https://github.com/schmittjoh/php-option/tree/master" }, "funding": [ { @@ -2532,20 +2822,20 @@ "type": "tidelift" } ], - "time": "2023-02-25T19:38:58+00:00" + "time": "2023-11-12T22:52:20+00:00" }, { "name": "phpstan/phpdoc-parser", - "version": "1.24.2", + "version": "1.24.5", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "bcad8d995980440892759db0c32acae7c8e79442" + "reference": "fedf211ff14ec8381c9bf5714e33a7a552dd1acc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/bcad8d995980440892759db0c32acae7c8e79442", - "reference": "bcad8d995980440892759db0c32acae7c8e79442", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/fedf211ff14ec8381c9bf5714e33a7a552dd1acc", + "reference": "fedf211ff14ec8381c9bf5714e33a7a552dd1acc", "shasum": "" }, "require": { @@ -2577,22 +2867,22 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.24.2" + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.24.5" }, - "time": "2023-09-26T12:28:12+00:00" + "time": "2023-12-16T09:33:33+00:00" }, { "name": "phpstan/phpstan", - "version": "1.10.x-dev", + "version": "1.10.50", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "2fa2aa0de39a1ac2d44d3a0a03f7586720882635" + "reference": "06a98513ac72c03e8366b5a0cb00750b487032e4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/2fa2aa0de39a1ac2d44d3a0a03f7586720882635", - "reference": "2fa2aa0de39a1ac2d44d3a0a03f7586720882635", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/06a98513ac72c03e8366b5a0cb00750b487032e4", + "reference": "06a98513ac72c03e8366b5a0cb00750b487032e4", "shasum": "" }, "require": { @@ -2641,39 +2931,39 @@ "type": "tidelift" } ], - "time": "2023-11-11T20:39:57+00:00" + "time": "2023-12-13T10:59:42+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "9.2.x-dev", + "version": "10.1.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "00bc23209e885ae1aab33c9a2303b0eb8ebd5c28" + "reference": "e8a1b365339597e7268340f4df827c2688be7f83" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/00bc23209e885ae1aab33c9a2303b0eb8ebd5c28", - "reference": "00bc23209e885ae1aab33c9a2303b0eb8ebd5c28", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/e8a1b365339597e7268340f4df827c2688be7f83", + "reference": "e8a1b365339597e7268340f4df827c2688be7f83", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.15", - "php": ">=7.3", - "phpunit/php-file-iterator": "^3.0.3", - "phpunit/php-text-template": "^2.0.2", - "sebastian/code-unit-reverse-lookup": "^2.0.2", - "sebastian/complexity": "^2.0", - "sebastian/environment": "^5.1.2", - "sebastian/lines-of-code": "^1.0.3", - "sebastian/version": "^3.0.1", + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=8.1", + "phpunit/php-file-iterator": "^4.0", + "phpunit/php-text-template": "^3.0", + "sebastian/code-unit-reverse-lookup": "^3.0", + "sebastian/complexity": "^3.0", + "sebastian/environment": "^6.0", + "sebastian/lines-of-code": "^2.0", + "sebastian/version": "^4.0", "theseer/tokenizer": "^1.2.0" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.1" }, "suggest": { "ext-pcov": "PHP extension that provides line coverage", @@ -2682,7 +2972,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.2-dev" + "dev-main": "10.1-dev" } }, "autoload": { @@ -2711,7 +3001,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1" }, "funding": [ { @@ -2719,32 +3009,32 @@ "type": "github" } ], - "time": "2023-11-09T06:48:38+00:00" + "time": "2023-12-31T07:35:59+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "3.0.x-dev", + "version": "4.1.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "38b24367e1b340aa78b96d7cab042942d917bb84" + "reference": "b36c308bfdd69e7bbafc4348f31c83a822458ec5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/38b24367e1b340aa78b96d7cab042942d917bb84", - "reference": "38b24367e1b340aa78b96d7cab042942d917bb84", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/b36c308bfdd69e7bbafc4348f31c83a822458ec5", + "reference": "b36c308bfdd69e7bbafc4348f31c83a822458ec5", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "4.1-dev" } }, "autoload": { @@ -2771,7 +3061,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0" + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1" }, "funding": [ { @@ -2779,28 +3070,28 @@ "type": "github" } ], - "time": "2022-02-11T16:23:04+00:00" + "time": "2023-12-31T07:36:54+00:00" }, { "name": "phpunit/php-invoker", - "version": "3.1.1", + "version": "4.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" + "reference": "4dc48195da24dd8200c891fc80f4c42675837d40" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/4dc48195da24dd8200c891fc80f4c42675837d40", + "reference": "4dc48195da24dd8200c891fc80f4c42675837d40", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { "ext-pcntl": "*", - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "suggest": { "ext-pcntl": "*" @@ -2808,7 +3099,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -2834,7 +3125,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" + "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0" }, "funding": [ { @@ -2842,32 +3134,32 @@ "type": "github" } ], - "time": "2020-09-28T05:58:55+00:00" + "time": "2023-12-31T07:37:20+00:00" }, { "name": "phpunit/php-text-template", - "version": "2.0.4", + "version": "3.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" + "reference": "647402cf7377b645e13d5dc7b842549296149ae9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/647402cf7377b645e13d5dc7b842549296149ae9", + "reference": "647402cf7377b645e13d5dc7b842549296149ae9", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -2893,7 +3185,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0" }, "funding": [ { @@ -2901,32 +3194,32 @@ "type": "github" } ], - "time": "2020-10-26T05:33:50+00:00" + "time": "2023-12-31T07:38:21+00:00" }, { "name": "phpunit/php-timer", - "version": "5.0.3", + "version": "6.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" + "reference": "ec2a787f80646fbaca26bdcf16bb52c5d358a716" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/ec2a787f80646fbaca26bdcf16bb52c5d358a716", + "reference": "ec2a787f80646fbaca26bdcf16bb52c5d358a716", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -2952,7 +3245,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" + "security": "https://github.com/sebastianbergmann/php-timer/security/policy", + "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0" }, "funding": [ { @@ -2960,24 +3254,23 @@ "type": "github" } ], - "time": "2020-10-26T13:16:10+00:00" + "time": "2023-12-31T07:38:42+00:00" }, { "name": "phpunit/phpunit", - "version": "9.6.x-dev", + "version": "10.5.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "3e2444b311b9bcca7c8b5294dc0c27a3fec0832a" + "reference": "6fce887c71076a73f32fd3e0774a6833fc5c7f19" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3e2444b311b9bcca7c8b5294dc0c27a3fec0832a", - "reference": "3e2444b311b9bcca7c8b5294dc0c27a3fec0832a", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/6fce887c71076a73f32fd3e0774a6833fc5c7f19", + "reference": "6fce887c71076a73f32fd3e0774a6833fc5c7f19", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.3.1 || ^2", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", @@ -2987,27 +3280,26 @@ "myclabs/deep-copy": "^1.10.1", "phar-io/manifest": "^2.0.3", "phar-io/version": "^3.0.2", - "php": ">=7.3", - "phpunit/php-code-coverage": "^9.2.28", - "phpunit/php-file-iterator": "^3.0.5", - "phpunit/php-invoker": "^3.1.1", - "phpunit/php-text-template": "^2.0.3", - "phpunit/php-timer": "^5.0.2", - "sebastian/cli-parser": "^1.0.1", - "sebastian/code-unit": "^1.0.6", - "sebastian/comparator": "^4.0.8", - "sebastian/diff": "^4.0.3", - "sebastian/environment": "^5.1.3", - "sebastian/exporter": "^4.0.5", - "sebastian/global-state": "^5.0.1", - "sebastian/object-enumerator": "^4.0.3", - "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^3.2", - "sebastian/version": "^3.0.2" + "php": ">=8.1", + "phpunit/php-code-coverage": "^10.1.5", + "phpunit/php-file-iterator": "^4.0", + "phpunit/php-invoker": "^4.0", + "phpunit/php-text-template": "^3.0", + "phpunit/php-timer": "^6.0", + "sebastian/cli-parser": "^2.0", + "sebastian/code-unit": "^2.0", + "sebastian/comparator": "^5.0", + "sebastian/diff": "^5.0", + "sebastian/environment": "^6.0", + "sebastian/exporter": "^5.1", + "sebastian/global-state": "^6.0.1", + "sebastian/object-enumerator": "^5.0", + "sebastian/recursion-context": "^5.0", + "sebastian/type": "^4.0", + "sebastian/version": "^4.0" }, "suggest": { - "ext-soap": "To be able to generate mocks based on WSDL files", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + "ext-soap": "To be able to generate mocks based on WSDL files" }, "bin": [ "phpunit" @@ -3015,7 +3307,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.6-dev" + "dev-main": "10.5-dev" } }, "autoload": { @@ -3047,7 +3339,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6" + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.3" }, "funding": [ { @@ -3063,7 +3355,7 @@ "type": "tidelift" } ], - "time": "2023-11-09T06:47:38+00:00" + "time": "2023-12-13T07:25:23+00:00" }, { "name": "psr/cache", @@ -3225,169 +3517,6 @@ }, "time": "2023-09-22T11:10:57+00:00" }, - { - "name": "psr/http-client", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-client.git", - "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", - "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", - "shasum": "" - }, - "require": { - "php": "^7.0 || ^8.0", - "psr/http-message": "^1.0 || ^2.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" - }, - "time": "2023-09-23T14:17:50+00:00" - }, - { - "name": "psr/http-factory", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-factory.git", - "reference": "7037f4b0950474e9d1350e8df89b15f1842085f6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-factory/zipball/7037f4b0950474e9d1350e8df89b15f1842085f6", - "reference": "7037f4b0950474e9d1350e8df89b15f1842085f6", - "shasum": "" - }, - "require": { - "php": ">=7.0.0", - "psr/http-message": "^1.0 || ^2.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": "PSR-17: 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" - }, - "time": "2023-09-22T11:16:44+00:00" - }, - { - "name": "psr/http-message", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", - "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.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 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/2.0" - }, - "time": "2023-04-04T09:54:51+00:00" - }, { "name": "psr/log", "version": "dev-master", @@ -3428,64 +3557,20 @@ } ], "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "support": { - "source": "https://github.com/php-fig/log/tree/3.0.0" - }, - "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" - } + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" ], - "description": "A polyfill for getallheaders.", "support": { - "issues": "https://github.com/ralouphie/getallheaders/issues", - "source": "https://github.com/ralouphie/getallheaders/tree/develop" + "source": "https://github.com/php-fig/log/tree/3.0.0" }, - "time": "2019-03-08T08:55:37+00:00" + "time": "2021-07-14T16:46:02+00:00" }, { "name": "scrutinizer/ocular", - "version": "dev-master", + "version": "1.9", "source": { "type": "git", "url": "https://github.com/scrutinizer-ci/ocular.git", @@ -3509,7 +3594,6 @@ "phpunit/phpunit": "^9.0.0", "symfony/filesystem": "~2.0|~3.0|~4.0|~5.0|^6.0" }, - "default-branch": true, "bin": [ "bin/ocular" ], @@ -3531,28 +3615,28 @@ }, { "name": "sebastian/cli-parser", - "version": "1.0.1", + "version": "2.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" + "reference": "c7c703fd197a868d43a4cd838de640ee66714c7f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/c7c703fd197a868d43a4cd838de640ee66714c7f", + "reference": "c7c703fd197a868d43a4cd838de640ee66714c7f", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-main": "2.0-dev" } }, "autoload": { @@ -3575,7 +3659,8 @@ "homepage": "https://github.com/sebastianbergmann/cli-parser", "support": { "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0" }, "funding": [ { @@ -3583,32 +3668,32 @@ "type": "github" } ], - "time": "2020-09-28T06:08:49+00:00" + "time": "2023-12-31T07:30:32+00:00" }, { "name": "sebastian/code-unit", - "version": "1.0.8", + "version": "2.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" + "reference": "1901c2cd4d50e5b1c86e067e078032708122b960" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1901c2cd4d50e5b1c86e067e078032708122b960", + "reference": "1901c2cd4d50e5b1c86e067e078032708122b960", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-main": "2.0-dev" } }, "autoload": { @@ -3631,7 +3716,8 @@ "homepage": "https://github.com/sebastianbergmann/code-unit", "support": { "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" + "security": "https://github.com/sebastianbergmann/code-unit/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0" }, "funding": [ { @@ -3639,32 +3725,32 @@ "type": "github" } ], - "time": "2020-10-26T13:08:54+00:00" + "time": "2023-12-31T07:31:01+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", - "version": "2.0.3", + "version": "3.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" + "reference": "35abdc17ebae0ddd0e174f9743cfe88936851758" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/35abdc17ebae0ddd0e174f9743cfe88936851758", + "reference": "35abdc17ebae0ddd0e174f9743cfe88936851758", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -3686,7 +3772,8 @@ "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", "support": { "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" + "security": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0" }, "funding": [ { @@ -3694,34 +3781,36 @@ "type": "github" } ], - "time": "2020-09-28T05:30:19+00:00" + "time": "2023-12-31T07:31:25+00:00" }, { "name": "sebastian/comparator", - "version": "4.0.x-dev", + "version": "5.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "b247957a1c8dc81a671770f74b479c0a78a818f1" + "reference": "06c9db507d5d6fb5efaa1a0b1a229a12e0ce8574" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/b247957a1c8dc81a671770f74b479c0a78a818f1", - "reference": "b247957a1c8dc81a671770f74b479c0a78a818f1", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/06c9db507d5d6fb5efaa1a0b1a229a12e0ce8574", + "reference": "06c9db507d5d6fb5efaa1a0b1a229a12e0ce8574", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/diff": "^4.0", - "sebastian/exporter": "^4.0" + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/diff": "^5.0", + "sebastian/exporter": "^5.0" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -3760,7 +3849,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0" + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/5.0" }, "funding": [ { @@ -3768,33 +3858,33 @@ "type": "github" } ], - "time": "2022-09-14T12:46:14+00:00" + "time": "2023-12-31T07:31:46+00:00" }, { "name": "sebastian/complexity", - "version": "2.0.2", + "version": "3.2.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" + "reference": "7337abb9e9beaf34af915ec1497599d75b5e2f4d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/7337abb9e9beaf34af915ec1497599d75b5e2f4d", + "reference": "7337abb9e9beaf34af915ec1497599d75b5e2f4d", "shasum": "" }, "require": { - "nikic/php-parser": "^4.7", - "php": ">=7.3" + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "3.2-dev" } }, "autoload": { @@ -3817,7 +3907,8 @@ "homepage": "https://github.com/sebastianbergmann/complexity", "support": { "issues": "https://github.com/sebastianbergmann/complexity/issues", - "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/3.2" }, "funding": [ { @@ -3825,33 +3916,33 @@ "type": "github" } ], - "time": "2020-10-26T15:52:27+00:00" + "time": "2023-12-31T07:32:09+00:00" }, { "name": "sebastian/diff", - "version": "4.0.x-dev", + "version": "5.1.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131" + "reference": "6fc9529a8e8eff86ad1f9125bad481b7c898f08f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131", - "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/6fc9529a8e8eff86ad1f9125bad481b7c898f08f", + "reference": "6fc9529a8e8eff86ad1f9125bad481b7c898f08f", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3", - "symfony/process": "^4.2 || ^5" + "phpunit/phpunit": "^10.0", + "symfony/process": "^6.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.1-dev" } }, "autoload": { @@ -3883,7 +3974,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0" + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/5.1" }, "funding": [ { @@ -3891,27 +3983,27 @@ "type": "github" } ], - "time": "2023-05-07T05:35:17+00:00" + "time": "2023-12-31T07:32:59+00:00" }, { "name": "sebastian/environment", - "version": "5.1.x-dev", + "version": "6.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" + "reference": "a7b60a4fd8d7ee68f06d2986ae38ebfbd7224399" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", - "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/a7b60a4fd8d7ee68f06d2986ae38ebfbd7224399", + "reference": "a7b60a4fd8d7ee68f06d2986ae38ebfbd7224399", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "suggest": { "ext-posix": "*" @@ -3919,7 +4011,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.1-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -3938,7 +4030,7 @@ } ], "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", + "homepage": "https://github.com/sebastianbergmann/environment", "keywords": [ "Xdebug", "environment", @@ -3946,7 +4038,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1" + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/6.0" }, "funding": [ { @@ -3954,34 +4047,34 @@ "type": "github" } ], - "time": "2023-02-03T06:03:51+00:00" + "time": "2023-12-31T07:33:18+00:00" }, { "name": "sebastian/exporter", - "version": "4.0.x-dev", + "version": "5.1.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" + "reference": "0af67d5d3b795b3a034a5ecb9c494658de9ef55d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", - "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/0af67d5d3b795b3a034a5ecb9c494658de9ef55d", + "reference": "0af67d5d3b795b3a034a5ecb9c494658de9ef55d", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/recursion-context": "^4.0" + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/recursion-context": "^5.0" }, "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.1-dev" } }, "autoload": { @@ -4023,7 +4116,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0" + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/5.1" }, "funding": [ { @@ -4031,38 +4125,35 @@ "type": "github" } ], - "time": "2022-09-14T06:03:37+00:00" + "time": "2023-12-31T07:33:37+00:00" }, { "name": "sebastian/global-state", - "version": "5.0.x-dev", + "version": "6.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bde739e7565280bda77be70044ac1047bc007e34" + "reference": "f15849a2a7207eff11f73919dfd279e2cc85dd1b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bde739e7565280bda77be70044ac1047bc007e34", - "reference": "bde739e7565280bda77be70044ac1047bc007e34", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/f15849a2a7207eff11f73919dfd279e2cc85dd1b", + "reference": "f15849a2a7207eff11f73919dfd279e2cc85dd1b", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" }, "require-dev": { "ext-dom": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-uopz": "*" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -4081,13 +4172,14 @@ } ], "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", + "homepage": "https://www.github.com/sebastianbergmann/global-state", "keywords": [ "global state" ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0" + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/6.0" }, "funding": [ { @@ -4095,33 +4187,33 @@ "type": "github" } ], - "time": "2023-08-02T09:26:13+00:00" + "time": "2023-12-31T07:33:55+00:00" }, { "name": "sebastian/lines-of-code", - "version": "1.0.3", + "version": "2.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" + "reference": "29f7720f283062763daf59d02499b569fd0b53e4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/29f7720f283062763daf59d02499b569fd0b53e4", + "reference": "29f7720f283062763daf59d02499b569fd0b53e4", "shasum": "" }, "require": { - "nikic/php-parser": "^4.6", - "php": ">=7.3" + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-main": "2.0-dev" } }, "autoload": { @@ -4144,7 +4236,8 @@ "homepage": "https://github.com/sebastianbergmann/lines-of-code", "support": { "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0" }, "funding": [ { @@ -4152,34 +4245,34 @@ "type": "github" } ], - "time": "2020-11-28T06:42:11+00:00" + "time": "2023-12-31T07:34:13+00:00" }, { "name": "sebastian/object-enumerator", - "version": "4.0.4", + "version": "5.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" + "reference": "8df0d10e04532a48d17078a4cb504bfcfc3a1101" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/8df0d10e04532a48d17078a4cb504bfcfc3a1101", + "reference": "8df0d10e04532a48d17078a4cb504bfcfc3a1101", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -4201,7 +4294,8 @@ "homepage": "https://github.com/sebastianbergmann/object-enumerator/", "support": { "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" + "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0" }, "funding": [ { @@ -4209,32 +4303,32 @@ "type": "github" } ], - "time": "2020-10-26T13:12:34+00:00" + "time": "2023-12-31T07:34:38+00:00" }, { "name": "sebastian/object-reflector", - "version": "2.0.4", + "version": "3.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" + "reference": "f6eb82d03f39cb1d13ae9ad9b7cb745144ecacda" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/f6eb82d03f39cb1d13ae9ad9b7cb745144ecacda", + "reference": "f6eb82d03f39cb1d13ae9ad9b7cb745144ecacda", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -4256,7 +4350,8 @@ "homepage": "https://github.com/sebastianbergmann/object-reflector/", "support": { "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" + "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0" }, "funding": [ { @@ -4264,32 +4359,32 @@ "type": "github" } ], - "time": "2020-10-26T13:14:26+00:00" + "time": "2023-12-31T07:35:14+00:00" }, { "name": "sebastian/recursion-context", - "version": "4.0.x-dev", + "version": "5.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" + "reference": "f7894029dc8a280837f77d643e881b53b6a04677" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/f7894029dc8a280837f77d643e881b53b6a04677", + "reference": "f7894029dc8a280837f77d643e881b53b6a04677", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -4319,62 +4414,8 @@ "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2023-02-03T06:07:39+00:00" - }, - { - "name": "sebastian/resource-operations", - "version": "dev-main", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "20bdda85c7c585ab265c0c37ec052a019bae29c4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/20bdda85c7c585ab265c0c37ec052a019bae29c4", - "reference": "20bdda85c7c585ab265c0c37ec052a019bae29c4", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.0" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "support": { - "source": "https://github.com/sebastianbergmann/resource-operations/tree/main" + "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0" }, "funding": [ { @@ -4382,32 +4423,32 @@ "type": "github" } ], - "time": "2023-03-25T08:11:39+00:00" + "time": "2023-12-31T07:40:00+00:00" }, { "name": "sebastian/type", - "version": "3.2.x-dev", + "version": "4.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" + "reference": "4337b83f7f8e9260afb858162b7c801a728c0353" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", - "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/4337b83f7f8e9260afb858162b7c801a728c0353", + "reference": "4337b83f7f8e9260afb858162b7c801a728c0353", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.5" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.2-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -4430,7 +4471,8 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.2" + "security": "https://github.com/sebastianbergmann/type/security/policy", + "source": "https://github.com/sebastianbergmann/type/tree/4.0" }, "funding": [ { @@ -4438,29 +4480,29 @@ "type": "github" } ], - "time": "2023-02-03T06:13:03+00:00" + "time": "2023-12-31T07:40:32+00:00" }, { "name": "sebastian/version", - "version": "3.0.x-dev", + "version": "4.0.x-dev", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c6c1022351a901512170118436c764e473f6de8c" + "reference": "116978f15ca072d5df4dab9419a32a66e386830d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", - "reference": "c6c1022351a901512170118436c764e473f6de8c", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/116978f15ca072d5df4dab9419a32a66e386830d", + "reference": "116978f15ca072d5df4dab9419a32a66e386830d", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -4483,7 +4525,8 @@ "homepage": "https://github.com/sebastianbergmann/version", "support": { "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" + "security": "https://github.com/sebastianbergmann/version/security/policy", + "source": "https://github.com/sebastianbergmann/version/tree/4.0" }, "funding": [ { @@ -4491,7 +4534,7 @@ "type": "github" } ], - "time": "2020-09-28T06:39:44+00:00" + "time": "2023-12-31T07:41:08+00:00" }, { "name": "symfony/console", @@ -4499,12 +4542,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "380ae25f02e34809fba16fa387191f1da9852778" + "reference": "0254811a143e6bc6c8deea08b589a7e68a37f625" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/380ae25f02e34809fba16fa387191f1da9852778", - "reference": "380ae25f02e34809fba16fa387191f1da9852778", + "url": "https://api.github.com/repos/symfony/console/zipball/0254811a143e6bc6c8deea08b589a7e68a37f625", + "reference": "0254811a143e6bc6c8deea08b589a7e68a37f625", "shasum": "" }, "require": { @@ -4585,75 +4628,7 @@ "type": "tidelift" } ], - "time": "2023-11-02T13:23:55+00:00" - }, - { - "name": "symfony/deprecation-contracts", - "version": "dev-main", - "source": { - "type": "git", - "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", - "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.4-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "files": [ - "function.php" - ] - }, - "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": "A generic function and convention to trigger deprecation notices", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.3.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-05-23T14:45:45+00:00" + "time": "2023-12-10T16:15:48+00:00" }, { "name": "symfony/event-dispatcher", @@ -4661,12 +4636,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "d76d2632cfc2206eecb5ad2b26cd5934082941b6" + "reference": "e95216850555cd55e71b857eb9d6c2674124603a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d76d2632cfc2206eecb5ad2b26cd5934082941b6", - "reference": "d76d2632cfc2206eecb5ad2b26cd5934082941b6", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/e95216850555cd55e71b857eb9d6c2674124603a", + "reference": "e95216850555cd55e71b857eb9d6c2674124603a", "shasum": "" }, "require": { @@ -4733,7 +4708,7 @@ "type": "tidelift" } ], - "time": "2023-07-27T06:52:43+00:00" + "time": "2023-12-27T22:16:42+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -4794,7 +4769,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.3.0" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.4.0" }, "funding": [ { @@ -5256,90 +5231,6 @@ ], "time": "2023-01-26T09:26:14+00:00" }, - { - "name": "symfony/polyfill-mbstring", - "version": "1.x-dev", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "42292d99c55abe617799667f454222c54c60e229" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", - "reference": "42292d99c55abe617799667f454222c54c60e229", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "provide": { - "ext-mbstring": "*" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-07-28T09:04:16+00:00" - }, { "name": "symfony/polyfill-php80", "version": "1.x-dev", @@ -5510,12 +5401,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "a91571ff5df8825fcc74569d99cddc7242f479b7" + "reference": "c4b1ef0bc80533d87a2e969806172f1c2a980241" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/a91571ff5df8825fcc74569d99cddc7242f479b7", - "reference": "a91571ff5df8825fcc74569d99cddc7242f479b7", + "url": "https://api.github.com/repos/symfony/process/zipball/c4b1ef0bc80533d87a2e969806172f1c2a980241", + "reference": "c4b1ef0bc80533d87a2e969806172f1c2a980241", "shasum": "" }, "require": { @@ -5563,7 +5454,7 @@ "type": "tidelift" } ], - "time": "2023-11-04T20:16:32+00:00" + "time": "2023-12-22T16:42:54+00:00" }, { "name": "symfony/service-contracts", @@ -5571,17 +5462,17 @@ "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "a4025a1c812c231d88ed0780e866b0cc644f4a84" + "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/a4025a1c812c231d88ed0780e866b0cc644f4a84", - "reference": "a4025a1c812c231d88ed0780e866b0cc644f4a84", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0", + "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0", "shasum": "" }, "require": { "php": ">=8.1", - "psr/container": "^2.0" + "psr/container": "^1.1|^2.0" }, "conflict": { "ext-psr": "<1.1|>=2" @@ -5630,7 +5521,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/main" + "source": "https://github.com/symfony/service-contracts/tree/v3.4.1" }, "funding": [ { @@ -5646,7 +5537,7 @@ "type": "tidelift" } ], - "time": "2023-07-29T13:12:44+00:00" + "time": "2023-12-26T14:02:43+00:00" }, { "name": "symfony/stopwatch", @@ -5716,12 +5607,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "afab7ffd61240b6fee63ea207b2b98c84f12791e" + "reference": "7cb80bc10bfcdf6b5492741c0b9357dac66940bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/afab7ffd61240b6fee63ea207b2b98c84f12791e", - "reference": "afab7ffd61240b6fee63ea207b2b98c84f12791e", + "url": "https://api.github.com/repos/symfony/string/zipball/7cb80bc10bfcdf6b5492741c0b9357dac66940bc", + "reference": "7cb80bc10bfcdf6b5492741c0b9357dac66940bc", "shasum": "" }, "require": { @@ -5794,20 +5685,20 @@ "type": "tidelift" } ], - "time": "2023-11-09T08:51:37+00:00" + "time": "2023-12-10T16:15:48+00:00" }, { "name": "theseer/tokenizer", - "version": "1.2.1", + "version": "1.2.2", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" + "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b2ad5003ca10d4ee50a12da31de12a5774ba6b96", + "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96", "shasum": "" }, "require": { @@ -5836,7 +5727,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.1" + "source": "https://github.com/theseer/tokenizer/tree/1.2.2" }, "funding": [ { @@ -5844,17 +5735,14 @@ "type": "github" } ], - "time": "2021-07-28T10:34:58+00:00" + "time": "2023-11-20T00:12:19+00:00" } ], "aliases": [], "minimum-stability": "dev", "stability-flags": { "shish/gqla": 20, - "naroga/redis-cache": 20, - "tbela99/css": 20, - "scrutinizer/ocular": 20, - "phpstan/phpstan": 20 + "naroga/redis-cache": 20 }, "prefer-stable": false, "prefer-lowest": false, @@ -5868,5 +5756,5 @@ "platform-overrides": { "php": "8.1.0" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } diff --git a/core/basepage.php b/core/basepage.php index a691336a8..f151e2f95 100644 --- a/core/basepage.php +++ b/core/basepage.php @@ -5,8 +5,6 @@ namespace Shimmie2; use MicroHTML\HTMLElement; -use TBela\CSS\Parser; -use TBela\CSS\Renderer; require_once "core/event.php"; @@ -113,6 +111,7 @@ public function set_redirect(string $redirect): void public string $title = ""; public string $heading = ""; public string $subheading = ""; + public bool $left_enabled = true; /** @var string[] */ public array $html_headers = []; @@ -157,6 +156,11 @@ public function flash(string $message): void $this->flash[] = $message; } + public function disable_left() + { + $this->left_enabled = false; + } + /** * Add a line to the HTML head section. */ @@ -376,6 +380,9 @@ public function add_auto_html_headers(): void $css_cache_file = $this->get_css_cache_file($theme_name, $config_latest); $this->add_html_header("", 43); + $initjs_cache_file = $this->get_initjs_cache_file($theme_name, $config_latest); + $this->add_html_header("", 44); + $js_cache_file = $this->get_js_cache_file($theme_name, $config_latest); $this->add_html_header("", 44); } @@ -393,31 +400,39 @@ private function get_css_cache_file(string $theme_name, int $config_latest): str $css_md5 = md5(serialize($css_files)); $css_cache_file = data_path("cache/style/{$theme_name}.{$css_latest}.{$css_md5}.css"); if (!file_exists($css_cache_file)) { - // the CSS minifier causes a bunch of deprecation warnings, - // so we turn off error reporting while it runs - $old_error_level = error_reporting(error_reporting(null) & ~E_DEPRECATED); - $parser = new Parser(); - foreach($css_files as $file) { - $parser->append($file); + $mcss = new \MicroBundler\MicroBundler(); + foreach($css_files as $css) { + $mcss->addSource($css, file_get_contents($css)); } - $element = $parser->parse(); - - // minified output - $renderer = new Renderer([ - 'compress' => true, - 'convert_color' => 'hex', - 'css_level' => 3, - 'sourcemap' => true, - 'allow_duplicate_declarations' => false, - 'legacy_rendering' => true, // turn nested CSS into regular - ]); - $renderer->save($element, $css_cache_file); - error_reporting($old_error_level); + $mcss->save($css_cache_file); } return $css_cache_file; } + private function get_initjs_cache_file(string $theme_name, int $config_latest): string + { + $js_latest = $config_latest; + $js_files = array_merge( + zglob("ext/{" . Extension::get_enabled_extensions_as_string() . "}/init.js"), + zglob("themes/$theme_name/init.js") + ); + foreach ($js_files as $js) { + $js_latest = max($js_latest, filemtime($js)); + } + $js_md5 = md5(serialize($js_files)); + $js_cache_file = data_path("cache/initscript/{$theme_name}.{$js_latest}.{$js_md5}.js"); + if (!file_exists($js_cache_file)) { + $mcss = new \MicroBundler\MicroBundler(); + foreach($js_files as $js) { + $mcss->addSource($js, file_get_contents($js)); + } + $mcss->save($js_cache_file); + } + + return $js_cache_file; + } + private function get_js_cache_file(string $theme_name, int $config_latest): string { $js_latest = $config_latest; @@ -426,7 +441,6 @@ private function get_js_cache_file(string $theme_name, int $config_latest): stri "vendor/bower-asset/jquery/dist/jquery.min.js", "vendor/bower-asset/jquery-timeago/jquery.timeago.js", "vendor/bower-asset/js-cookie/src/js.cookie.js", - "ext/static_files/modernizr-3.3.1.custom.js", ], zglob("ext/{" . Extension::get_enabled_extensions_as_string() . "}/script.js"), zglob("themes/$theme_name/{" . implode(",", $this->get_theme_scripts()) . "}") @@ -437,17 +451,16 @@ private function get_js_cache_file(string $theme_name, int $config_latest): stri $js_md5 = md5(serialize($js_files)); $js_cache_file = data_path("cache/script/{$theme_name}.{$js_latest}.{$js_md5}.js"); if (!file_exists($js_cache_file)) { - $js_data = ""; - foreach ($js_files as $file) { - $js_data .= file_get_contents($file) . "\n"; + $mcss = new \MicroBundler\MicroBundler(); + foreach($js_files as $js) { + $mcss->addSource($js, file_get_contents($js)); } - file_put_contents($js_cache_file, $js_data); + $mcss->save($js_cache_file); } return $js_cache_file; } - /** * @return array A list of stylesheets relative to the theme root. */ @@ -505,8 +518,9 @@ protected function get_nav_links(): array } $sub_links = $sub_links ?? []; - usort($nav_links, "Shimmie2\sort_nav_links"); - usort($sub_links, "Shimmie2\sort_nav_links"); + + usort($nav_links, fn (NavLink $a, NavLink $b) => $a->order - $b->order); + usort($sub_links, fn (NavLink $a, NavLink $b) => $a->order - $b->order); return [$nav_links, $sub_links]; } @@ -521,7 +535,7 @@ public function render() print << - + $head_html $body_html @@ -699,8 +713,3 @@ public static function is_active(array $pages_matched, string $url = null): bool return false; } } - -function sort_nav_links(NavLink $a, NavLink $b): int -{ - return $a->order - $b->order; -} diff --git a/core/config.php b/core/config.php index 85c3a2a1e..35f068695 100644 --- a/core/config.php +++ b/core/config.php @@ -278,27 +278,27 @@ public function __construct( $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}"; + $this->cache_name = empty($sub_value) ? "config" : "config_{$sub_column}_{$sub_value}"; + $this->values = cache_get_or_set($this->cache_name, fn () => $this->get_values()); + } - $cached = $cache->get($this->cache_name); - if (!is_null($cached)) { - $this->values = $cached; - } else { - $this->values = []; + private function get_values(): mixed + { + $values = []; - $query = "SELECT name, value FROM {$this->table_name}"; - $args = []; + $query = "SELECT name, value FROM {$this->table_name}"; + $args = []; - if (!empty($sub_column) && !empty($sub_value)) { - $query .= " WHERE $sub_column = :sub_value"; - $args["sub_value"] = $sub_value; - } + if (!empty($this->sub_column) && !empty($this->sub_value)) { + $query .= " WHERE {$this->sub_column} = :sub_value"; + $args["sub_value"] = $this->sub_value; + } - foreach ($this->database->get_all($query, $args) as $row) { - $this->values[$row["name"]] = $row["value"]; - } - $cache->set($this->cache_name, $this->values); + foreach ($this->database->get_all($query, $args) as $row) { + $values[$row["name"]] = $row["value"]; } + + return $values; } public function save(string $name = null): void diff --git a/core/event.php b/core/event.php index c1eec6d6f..5e8e9936d 100644 --- a/core/event.php +++ b/core/event.php @@ -46,6 +46,7 @@ class InitExtEvent extends Event */ class PageRequestEvent extends Event { + public string $method; /** * @var string[] */ @@ -53,11 +54,13 @@ class PageRequestEvent extends Event public int $arg_count; public int $part_count; - public function __construct(string $path) + public function __construct(string $method, string $path) { parent::__construct(); global $config; + $this->method = $method; + // trim starting slashes $path = ltrim($path, "/"); @@ -103,7 +106,7 @@ public function get_arg(int $n): string { $offset = $this->part_count + $n; if ($offset >= 0 && $offset < $this->arg_count) { - return $this->args[$offset]; + return rawurldecode($this->args[$offset]); } else { $nm1 = $this->arg_count - 1; throw new UserErrorException("Requested an invalid page argument {$offset} / {$nm1}"); @@ -144,7 +147,33 @@ public function get_search_terms(): array { $search_terms = []; if ($this->count_args() === 2) { - $search_terms = Tag::explode(Tag::decaret($this->get_arg(0))); + $str = $this->get_arg(0); + + // decode legacy caret-encoding just in case + // somebody has bookmarked such a URL + $from_caret = [ + "^" => "^", + "s" => "/", + "b" => "\\", + "q" => "?", + "a" => "&", + "d" => ".", + ]; + $out = ""; + $length = strlen($str); + for ($i = 0; $i < $length; $i++) { + if ($str[$i] == "^") { + $i++; + $out .= $from_caret[$str[$i]] ?? ''; + } else { + $out .= $str[$i]; + } + } + $str = $out; + // end legacy + + + $search_terms = Tag::explode($str); } return $search_terms; } @@ -184,7 +213,7 @@ class CommandEvent extends Event public array $args = []; /** - * #param string[] $args + * @param string[] $args */ public function __construct(array $args) { diff --git a/core/extension.php b/core/extension.php index cf246e8cb..65d906942 100644 --- a/core/extension.php +++ b/core/extension.php @@ -110,6 +110,10 @@ protected function set_version(string $name, int $ver) } } +class ExtensionNotFound extends SCoreException +{ +} + enum ExtensionVisibility { case DEFAULT; @@ -235,7 +239,7 @@ public static function get_for_extension_class(string $base): ExtensionInfo return self::$all_info_by_class[$normal]; } else { $infos = print_r(array_keys(self::$all_info_by_class), true); - throw new SCoreException("$normal not found in {$infos}"); + throw new ExtensionNotFound("$normal not found in {$infos}"); } } @@ -370,10 +374,13 @@ public function onThumbnailGeneration(ThumbnailGenerationEvent $event) public function onDisplayingImage(DisplayingImageEvent $event) { - global $page; + global $config, $page; if ($this->supported_mime($event->image->get_mime())) { // @phpstan-ignore-next-line - $this->theme->display_image($page, $event->image); + $this->theme->display_image($event->image); + if ($config->get_bool(ImageConfig::SHOW_META) && method_exists($this->theme, "display_metadata")) { + $this->theme->display_metadata($event->image); + } } } diff --git a/core/imageboard/autocomplete_column.php b/core/imageboard/autocomplete_column.php new file mode 100644 index 000000000..50ce8fcad --- /dev/null +++ b/core/imageboard/autocomplete_column.php @@ -0,0 +1,34 @@ + "text", + "name" => "r_{$this->name}", + "class" => "autocomplete_tags", + "placeholder" => $this->title, + "value" => @$inputs["r_{$this->name}"] + ]); + } + + public function create_input(array $inputs) + { + return INPUT([ + "type" => "text", + "name" => "c_{$this->name}", + "class" => "autocomplete_tags", + "placeholder" => $this->title, + "value" => @$inputs["c_{$this->name}"] + ]); + } +} diff --git a/core/imageboard/image.php b/core/imageboard/image.php index ec30eb64b..846a0b600 100644 --- a/core/imageboard/image.php +++ b/core/imageboard/image.php @@ -126,7 +126,7 @@ public static function by_id_or_hash(string $id): ?Image public static function by_random(array $tags = [], int $limit_range = 0): ?Image { - $max = Image::count_images($tags); + $max = Search::count_images($tags); if ($max < 1) { return null; } // From Issue #22 - opened by HungryFeline on May 30, 2011. @@ -134,7 +134,7 @@ public static function by_random(array $tags = [], int $limit_range = 0): ?Image $max = $limit_range; } $rand = mt_rand(0, $max - 1); - $set = Image::find_images($rand, 1, $tags); + $set = Search::find_images($rand, 1, $tags); if (count($set) > 0) { return $set[0]; } else { @@ -142,136 +142,6 @@ public static function by_random(array $tags = [], int $limit_range = 0): ?Image } } - private static function find_images_internal(int $start = 0, ?int $limit = null, array $tags = []): iterable - { - global $database, $user; - - if ($start < 0) { - $start = 0; - } - if ($limit !== null && $limit < 1) { - $limit = 1; - } - - if (SPEED_HAX) { - if (!$user->can(Permissions::BIG_SEARCH) and count($tags) > 3) { - throw new PermissionDeniedException("Anonymous users may only search for up to 3 tags at a time"); - } - } - - $querylet = Image::build_search_querylet($tags, $limit, $start); - return $database->get_all_iterable($querylet->sql, $querylet->variables); - } - - /** - * Search for an array of images - * - * @param string[] $tags - * @return Image[] - */ - #[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($offset, $limit, $tags); - - $images = []; - foreach ($result as $row) { - $images[] = new Image($row); - } - return $images; - } - - /** - * 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 - { - $result = self::find_images_internal($start, $limit, $tags); - foreach ($result as $row) { - yield new Image($row); - } - } - - /* - * Image-related utility functions - */ - - public static function count_total_images(): int - { - global $cache, $database; - $total = $cache->get("image-count"); - if (is_null($total)) { - $total = (int)$database->get_one("SELECT COUNT(*) FROM images"); - $cache->set("image-count", $total, 600); - } - return $total; - } - - public static function count_tag(string $tag): int - { - global $database; - return (int)$database->get_one( - "SELECT count FROM tags WHERE LOWER(tag) = LOWER(:tag)", - ["tag" => $tag] - ); - } - - /** - * Count the number of image results for a given search - * - * @param string[] $tags - */ - public static function count_images(array $tags = []): int - { - global $cache, $database; - $tag_count = count($tags); - - if (SPEED_HAX && $tag_count === 0) { - // total number of images in the DB - $total = self::count_total_images(); - } elseif (SPEED_HAX && $tag_count === 1 && !preg_match("/[:=><\*\?]/", $tags[0])) { - if (!str_starts_with($tags[0], "-")) { - // one tag - we can look that up directly - $total = self::count_tag($tags[0]); - } else { - // one negative tag - subtract from the total - $total = self::count_total_images() - self::count_tag(substr($tags[0], 1)); - } - } else { - // complex query - // implode(tags) can be too long for memcache... - $cache_key = "image-count:" . md5(Tag::implode($tags)); - $total = $cache->get($cache_key); - if (is_null($total)) { - if (Extension::is_enabled(RatingsInfo::KEY)) { - $tags[] = "rating:*"; - } - $querylet = Image::build_search_querylet($tags); - $total = (int)$database->get_one("SELECT COUNT(*) AS cnt FROM ($querylet->sql) AS tbl", $querylet->variables); - if (SPEED_HAX && $total > 5000) { - // when we have a ton of images, the count - // won't change dramatically very often - $cache->set($cache_key, $total, 3600); - } - } - } - if (is_null($total)) { - return 0; - } - return $total; - } - - /** - * Count the number of pages for a given search - * - * @param string[] $tags - */ - public static function count_pages(array $tags = []): int - { - global $config; - return (int)ceil(Image::count_images($tags) / $config->get_int(IndexConfig::IMAGES)); - } - /* * Accessors & mutators */ @@ -296,23 +166,10 @@ public function get_next(array $tags = [], bool $next = true): ?Image $dir = "ASC"; } - if (count($tags) === 0) { - $row = $database->get_row(' - SELECT images.* - FROM images - WHERE images.id '.$gtlt.' '.$this->id.' - ORDER BY images.id '.$dir.' - LIMIT 1 - '); - } else { - $tags[] = 'id'. $gtlt . $this->id; - $tags[] = 'order:id_'. strtolower($dir); - $querylet = Image::build_search_querylet($tags); - $querylet->append_sql(' LIMIT 1'); - $row = $database->get_row($querylet->sql, $querylet->variables); - } - - return ($row ? new Image($row) : null); + $tags[] = 'id'. $gtlt . $this->id; + $tags[] = 'order:id_'. strtolower($dir); + $images = Search::find_images(0, 1, $tags); + return (count($images) > 0) ? $images[0] : null; } /** @@ -737,223 +594,4 @@ public function parse_link_template(string $tmpl, int $n = 0): string $tmpl = $plte->link; return load_balance_url($tmpl, $this->hash, $n); } - - private static function tag_or_wildcard_to_ids(string $tag): array - { - global $database; - $sq = "SELECT id FROM tags WHERE LOWER(tag) LIKE LOWER(:tag)"; - if ($database->get_driver_id() === DatabaseDriverID::SQLITE) { - $sq .= "ESCAPE '\\'"; - } - return $database->get_col($sq, ["tag" => Tag::sqlify($tag)]); - } - - /** - * @param string[] $terms - */ - private static function build_search_querylet( - array $terms, - ?int $limit = null, - ?int $offset = null - ): Querylet { - global $config; - - $tag_conditions = []; - $img_conditions = []; - $order = null; - - /* - * Turn a bunch of strings into a bunch of TagCondition - * and ImgCondition objects - */ - $stpen = 0; // search term parse event number - foreach (array_merge([null], $terms) as $term) { - $stpe = send_event(new SearchTermParseEvent($stpen++, $term, $terms)); - $order ??= $stpe->order; - $img_conditions = array_merge($img_conditions, $stpe->img_conditions); - $tag_conditions = array_merge($tag_conditions, $stpe->tag_conditions); - } - - $order = ($order ?: "images.".$config->get_string(IndexConfig::ORDER)); - - /* - * Turn a bunch of Querylet objects into a base query - * - * Must follow the format - * - * SELECT images.* - * FROM (...) AS images - * WHERE (...) - * - * ie, return a set of images.* columns, and end with a WHERE - */ - - // no tags, do a simple search - if (count($tag_conditions) === 0) { - $query = new Querylet("SELECT images.* FROM images WHERE 1=1"); - } - - // one tag sorted by ID - we can fetch this from the image_tags table, - // and do the offset / limit there, which is 10x faster than fetching - // all the image_tags and doing the offset / limit on the result. - elseif ( - count($tag_conditions) === 1 - && empty($img_conditions) - && ($order == "id DESC" || $order == "images.id DESC") - && !is_null($offset) - && !is_null($limit) - ) { - $tc = $tag_conditions[0]; - $in = $tc->positive ? "IN" : "NOT IN"; - // IN (SELECT id FROM tags) is 100x slower than doing a separate - // query and then a second query for IN(first_query_results)?? - $tag_array = self::tag_or_wildcard_to_ids($tc->tag); - if (count($tag_array) == 0) { - // if wildcard expanded to nothing, take a shortcut - if ($tc->positive) { - $query = new Querylet("SELECT images.* FROM images WHERE 1=0"); - } else { - $query = new Querylet("SELECT images.* FROM images WHERE 1=1"); - } - } else { - $set = implode(', ', $tag_array); - $query = new Querylet(" - SELECT images.* - FROM images INNER JOIN ( - SELECT it.image_id - FROM image_tags it - WHERE it.tag_id $in ($set) - ORDER BY it.image_id DESC - LIMIT :limit OFFSET :offset - ) a on a.image_id = images.id - ORDER BY images.id DESC - ", ["limit" => $limit, "offset" => $offset]); - // don't offset at the image level because - // we already offset at the image_tags level - $order = null; - $limit = null; - $offset = null; - } - } - - // more than one tag, or more than zero other conditions, or a non-default sort order - else { - $positive_tag_id_array = []; - $positive_wildcard_id_array = []; - $negative_tag_id_array = []; - $all_nonexistent_negatives = true; - - foreach ($tag_conditions as $tq) { - $tag_ids = self::tag_or_wildcard_to_ids($tq->tag); - $tag_count = count($tag_ids); - - if ($tq->positive) { - $all_nonexistent_negatives = false; - if ($tag_count == 0) { - # one of the positive tags had zero results, therefor there - # can be no results; "where 1=0" should shortcut things - return new Querylet("SELECT images.* FROM images WHERE 1=0"); - } elseif ($tag_count == 1) { - // All wildcard terms that qualify for a single tag can be treated the same as non-wildcards - $positive_tag_id_array[] = $tag_ids[0]; - } else { - // Terms that resolve to multiple tags act as an OR within themselves - // and as an AND in relation to all other terms, - $positive_wildcard_id_array[] = $tag_ids; - } - } else { - if ($tag_count > 0) { - $all_nonexistent_negatives = false; - // Unlike positive criteria, negative criteria are all handled in an OR fashion, - // so we can just compile them all into a single sub-query. - $negative_tag_id_array = array_merge($negative_tag_id_array, $tag_ids); - } - } - } - - assert($positive_tag_id_array || $positive_wildcard_id_array || $negative_tag_id_array || $all_nonexistent_negatives, @$_GET['q']); - - if ($all_nonexistent_negatives) { - $query = new Querylet("SELECT images.* FROM images WHERE 1=1"); - } elseif (!empty($positive_tag_id_array) || !empty($positive_wildcard_id_array)) { - $inner_joins = []; - if (!empty($positive_tag_id_array)) { - foreach ($positive_tag_id_array as $tag) { - $inner_joins[] = "= $tag"; - } - } - if (!empty($positive_wildcard_id_array)) { - foreach ($positive_wildcard_id_array as $tags) { - $positive_tag_id_list = join(', ', $tags); - $inner_joins[] = "IN ($positive_tag_id_list)"; - } - } - - $first = array_shift($inner_joins); - $sub_query = "SELECT it.image_id FROM image_tags it "; - $i = 0; - foreach ($inner_joins as $inner_join) { - $i++; - $sub_query .= " INNER JOIN image_tags it$i ON it$i.image_id = it.image_id AND it$i.tag_id $inner_join "; - } - if (!empty($negative_tag_id_array)) { - $negative_tag_id_list = join(', ', $negative_tag_id_array); - $sub_query .= " LEFT JOIN image_tags negative ON negative.image_id = it.image_id AND negative.tag_id IN ($negative_tag_id_list) "; - } - $sub_query .= "WHERE it.tag_id $first "; - if (!empty($negative_tag_id_array)) { - $sub_query .= " AND negative.image_id IS NULL"; - } - $sub_query .= " GROUP BY it.image_id "; - - $query = new Querylet(" - SELECT images.* - FROM images - INNER JOIN ($sub_query) a on a.image_id = images.id - "); - } elseif (!empty($negative_tag_id_array)) { - $negative_tag_id_list = join(', ', $negative_tag_id_array); - $query = new Querylet(" - SELECT images.* - FROM images - LEFT JOIN image_tags negative ON negative.image_id = images.id AND negative.tag_id in ($negative_tag_id_list) - WHERE negative.image_id IS NULL - "); - } else { - throw new SCoreException("No criteria specified"); - } - } - - /* - * Merge all the image metadata searches into one generic querylet - * and append to the base querylet with "AND blah" - */ - if (!empty($img_conditions)) { - $n = 0; - $img_sql = ""; - $img_vars = []; - foreach ($img_conditions as $iq) { - if ($n++ > 0) { - $img_sql .= " AND"; - } - if (!$iq->positive) { - $img_sql .= " NOT"; - } - $img_sql .= " (" . $iq->qlet->sql . ")"; - $img_vars = array_merge($img_vars, $iq->qlet->variables); - } - $query->append_sql(" AND "); - $query->append(new Querylet($img_sql, $img_vars)); - } - - if (!is_null($order)) { - $query->append(new Querylet(" ORDER BY ".$order)); - } - if (!is_null($limit)) { - $query->append(new Querylet(" LIMIT :limit ", ["limit" => $limit])); - $query->append(new Querylet(" OFFSET :offset ", ["offset" => $offset])); - } - - return $query; - } } diff --git a/core/imageboard/misc.php b/core/imageboard/misc.php index 2fdc82a82..6a96baeec 100644 --- a/core/imageboard/misc.php +++ b/core/imageboard/misc.php @@ -187,7 +187,7 @@ function redirect_to_next_image(Image $image): void global $page; if (isset($_GET['search'])) { - $search_terms = Tag::explode(Tag::decaret($_GET['search'])); + $search_terms = Tag::explode($_GET['search']); $query = "search=" . url_escape($_GET['search']); } else { $search_terms = []; diff --git a/core/imageboard/search.php b/core/imageboard/search.php index 624f52237..2b9dfff57 100644 --- a/core/imageboard/search.php +++ b/core/imageboard/search.php @@ -4,6 +4,8 @@ namespace Shimmie2; +use GQLA\Query; + class Querylet { public function __construct( @@ -33,7 +35,7 @@ class TagCondition { public function __construct( public string $tag, - public bool $positive, + public bool $positive = true, ) { } } @@ -42,7 +44,365 @@ class ImgCondition { public function __construct( public Querylet $qlet, - public bool $positive, + public bool $positive = true, ) { } } + +class Search +{ + public static array $_search_path = []; + + private static function find_images_internal(int $start = 0, ?int $limit = null, array $tags = []): iterable + { + global $database, $user; + + if ($start < 0) { + $start = 0; + } + if ($limit !== null && $limit < 1) { + $limit = 1; + } + + if (SPEED_HAX) { + if (!$user->can(Permissions::BIG_SEARCH) and count($tags) > 3) { + throw new PermissionDeniedException("Anonymous users may only search for up to 3 tags at a time"); + } + } + + [$tag_conditions, $img_conditions, $order] = self::terms_to_conditions($tags); + $querylet = self::build_search_querylet($tag_conditions, $img_conditions, $order, $limit, $start); + return $database->get_all_iterable($querylet->sql, $querylet->variables); + } + + /** + * Search for an array of images + * + * @param string[] $tags + * @return Image[] + */ + #[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($offset, $limit, $tags); + + $images = []; + foreach ($result as $row) { + $images[] = new Image($row); + } + return $images; + } + + /** + * 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 + { + $result = self::find_images_internal($start, $limit, $tags); + foreach ($result as $row) { + yield new Image($row); + } + } + + /* + * Image-related utility functions + */ + + public static function count_tag(string $tag): int + { + global $database; + return (int)$database->get_one( + "SELECT count FROM tags WHERE LOWER(tag) = LOWER(:tag)", + ["tag" => $tag] + ); + } + + private static function count_total_images(): int + { + global $database; + return cache_get_or_set("image-count", fn () => (int)$database->get_one("SELECT COUNT(*) FROM images"), 600); + } + + /** + * Count the number of image results for a given search + * + * @param string[] $tags + */ + public static function count_images(array $tags = []): int + { + global $cache, $database; + $tag_count = count($tags); + + // SPEED_HAX ignores the fact that extensions can add img_conditions + // even when there are no tags being searched for + if (SPEED_HAX && $tag_count === 0) { + // total number of images in the DB + $total = self::count_total_images(); + } elseif (SPEED_HAX && $tag_count === 1 && !preg_match("/[:=><\*\?]/", $tags[0])) { + if (!str_starts_with($tags[0], "-")) { + // one positive tag - we can look that up directly + $total = self::count_tag($tags[0]); + } else { + // one negative tag - subtract from the total + $total = self::count_total_images() - self::count_tag(substr($tags[0], 1)); + } + } else { + // complex query + // implode(tags) can be too long for memcache, so use the hash of tags as the key + $cache_key = "image-count:" . md5(Tag::implode($tags)); + $total = $cache->get($cache_key); + if (is_null($total)) { + if (Extension::is_enabled(RatingsInfo::KEY)) { + $tags[] = "rating:*"; + } + [$tag_conditions, $img_conditions, $order] = self::terms_to_conditions($tags); + $querylet = self::build_search_querylet($tag_conditions, $img_conditions, $order); + $total = (int)$database->get_one("SELECT COUNT(*) AS cnt FROM ($querylet->sql) AS tbl", $querylet->variables); + if (SPEED_HAX && $total > 5000) { + // when we have a ton of images, the count + // won't change dramatically very often + $cache->set($cache_key, $total, 3600); + } + } + } + if (is_null($total)) { + return 0; + } + return $total; + } + + + private static function tag_or_wildcard_to_ids(string $tag): array + { + global $database; + $sq = "SELECT id FROM tags WHERE LOWER(tag) LIKE LOWER(:tag)"; + if ($database->get_driver_id() === DatabaseDriverID::SQLITE) { + $sq .= "ESCAPE '\\'"; + } + return $database->get_col($sq, ["tag" => Tag::sqlify($tag)]); + } + + /** + * Turn a human input string into a an abstract search query + * + * @param string[] $terms + * @return array{0: TagCondition[], 1: ImgCondition[], 2: string} + */ + private static function terms_to_conditions(array $terms): array + { + global $config; + + $tag_conditions = []; + $img_conditions = []; + $order = null; + + /* + * Turn a bunch of strings into a bunch of TagCondition + * and ImgCondition objects + */ + $stpen = 0; // search term parse event number + foreach (array_merge([null], $terms) as $term) { + $stpe = send_event(new SearchTermParseEvent($stpen++, $term, $terms)); + $order ??= $stpe->order; + $img_conditions = array_merge($img_conditions, $stpe->img_conditions); + $tag_conditions = array_merge($tag_conditions, $stpe->tag_conditions); + } + + $order = ($order ?: "images.".$config->get_string(IndexConfig::ORDER)); + + return [$tag_conditions, $img_conditions, $order]; + } + + /** + * Turn an abstract search query into an SQL Querylet + * + * @param TagCondition[] $tag_conditions + * @param ImgCondition[] $img_conditions + */ + private static function build_search_querylet( + array $tag_conditions, + array $img_conditions, + string $order, + ?int $limit = null, + ?int $offset = null + ): Querylet { + // no tags, do a simple search + if (count($tag_conditions) === 0) { + static::$_search_path[] = "no_tags"; + $query = new Querylet("SELECT images.* FROM images WHERE 1=1"); + } + + // one tag sorted by ID - we can fetch this from the image_tags table, + // and do the offset / limit there, which is 10x faster than fetching + // all the image_tags and doing the offset / limit on the result. + elseif ( + count($tag_conditions) === 1 + && $tag_conditions[0]->positive + // We can only do this if img_conditions is empty, because + // we're going to apply the offset / limit to the image_tags + // subquery, and applying extra conditions to the top-level + // query might reduce the total results below the target limit + && empty($img_conditions) + // We can only do this if we're sorting by ID, because + // we're going to be using the image_tags table, which + // only has image_id and tag_id, not any other columns + && ($order == "id DESC" || $order == "images.id DESC") + // This is only an optimisation if we are applying limit + // and offset + && !is_null($limit) + && !is_null($offset) + ) { + static::$_search_path[] = "fast"; + $tc = $tag_conditions[0]; + // IN (SELECT id FROM tags) is 100x slower than doing a separate + // query and then a second query for IN(first_query_results)?? + $tag_array = self::tag_or_wildcard_to_ids($tc->tag); + if (count($tag_array) == 0) { + // if wildcard expanded to nothing, take a shortcut + static::$_search_path[] = "invalid_tag"; + $query = new Querylet("SELECT images.* FROM images WHERE 1=0"); + } else { + $set = implode(', ', $tag_array); + $query = new Querylet(" + SELECT images.* + FROM images INNER JOIN ( + SELECT DISTINCT it.image_id + FROM image_tags it + WHERE it.tag_id IN ($set) + ORDER BY it.image_id DESC + LIMIT :limit OFFSET :offset + ) a on a.image_id = images.id + WHERE 1=1 + ", ["limit" => $limit, "offset" => $offset]); + // don't offset at the image level because + // we already offset at the image_tags level + $limit = null; + $offset = null; + } + } + + // more than one tag, or more than zero other conditions, or a non-default sort order + else { + static::$_search_path[] = "general"; + $positive_tag_id_array = []; + $positive_wildcard_id_array = []; + $negative_tag_id_array = []; + $all_nonexistent_negatives = true; + + foreach ($tag_conditions as $tq) { + $tag_ids = self::tag_or_wildcard_to_ids($tq->tag); + $tag_count = count($tag_ids); + + if ($tq->positive) { + $all_nonexistent_negatives = false; + if ($tag_count == 0) { + # one of the positive tags had zero results, therefor there + # can be no results; "where 1=0" should shortcut things + static::$_search_path[] = "invalid_tag"; + return new Querylet("SELECT images.* FROM images WHERE 1=0"); + } elseif ($tag_count == 1) { + // All wildcard terms that qualify for a single tag can be treated the same as non-wildcards + $positive_tag_id_array[] = $tag_ids[0]; + } else { + // Terms that resolve to multiple tags act as an OR within themselves + // and as an AND in relation to all other terms, + $positive_wildcard_id_array[] = $tag_ids; + } + } else { + if ($tag_count > 0) { + $all_nonexistent_negatives = false; + // Unlike positive criteria, negative criteria are all handled in an OR fashion, + // so we can just compile them all into a single sub-query. + $negative_tag_id_array = array_merge($negative_tag_id_array, $tag_ids); + } + } + } + + assert($positive_tag_id_array || $positive_wildcard_id_array || $negative_tag_id_array || $all_nonexistent_negatives, @$_GET['q']); + + if ($all_nonexistent_negatives) { + static::$_search_path[] = "all_nonexistent_negatives"; + $query = new Querylet("SELECT images.* FROM images WHERE 1=1"); + } elseif (!empty($positive_tag_id_array) || !empty($positive_wildcard_id_array)) { + static::$_search_path[] = "some_positives"; + $inner_joins = []; + if (!empty($positive_tag_id_array)) { + foreach ($positive_tag_id_array as $tag) { + $inner_joins[] = "= $tag"; + } + } + if (!empty($positive_wildcard_id_array)) { + foreach ($positive_wildcard_id_array as $tags) { + $positive_tag_id_list = join(', ', $tags); + $inner_joins[] = "IN ($positive_tag_id_list)"; + } + } + + $first = array_shift($inner_joins); + $sub_query = "SELECT DISTINCT it.image_id FROM image_tags it "; + $i = 0; + foreach ($inner_joins as $inner_join) { + $i++; + $sub_query .= " INNER JOIN image_tags it$i ON it$i.image_id = it.image_id AND it$i.tag_id $inner_join "; + } + if (!empty($negative_tag_id_array)) { + $negative_tag_id_list = join(', ', $negative_tag_id_array); + $sub_query .= " LEFT JOIN image_tags negative ON negative.image_id = it.image_id AND negative.tag_id IN ($negative_tag_id_list) "; + } + $sub_query .= "WHERE it.tag_id $first "; + if (!empty($negative_tag_id_array)) { + $sub_query .= " AND negative.image_id IS NULL"; + } + $sub_query .= " GROUP BY it.image_id "; + + $query = new Querylet(" + SELECT images.* + FROM images + INNER JOIN ($sub_query) a on a.image_id = images.id + "); + } elseif (!empty($negative_tag_id_array)) { + static::$_search_path[] = "only_negative_tags"; + $negative_tag_id_list = join(', ', $negative_tag_id_array); + $query = new Querylet(" + SELECT images.* + FROM images + LEFT JOIN image_tags negative ON negative.image_id = images.id AND negative.tag_id in ($negative_tag_id_list) + WHERE negative.image_id IS NULL + "); + } else { + throw new SCoreException("No criteria specified"); + } + } + + /* + * Merge all the image metadata searches into one generic querylet + * and append to the base querylet with "AND blah" + */ + if (!empty($img_conditions)) { + $n = 0; + $img_sql = ""; + $img_vars = []; + foreach ($img_conditions as $iq) { + if ($n++ > 0) { + $img_sql .= " AND"; + } + if (!$iq->positive) { + $img_sql .= " NOT"; + } + $img_sql .= " (" . $iq->qlet->sql . ")"; + $img_vars = array_merge($img_vars, $iq->qlet->variables); + } + $query->append_sql(" AND "); + $query->append(new Querylet($img_sql, $img_vars)); + } + + $query->append(new Querylet(" ORDER BY ".$order)); + + if (!is_null($limit)) { + $query->append(new Querylet(" LIMIT :limit ", ["limit" => $limit])); + $query->append(new Querylet(" OFFSET :offset ", ["offset" => $offset])); + } + + return $query; + } +} diff --git a/core/imageboard/tag.php b/core/imageboard/tag.php index 547ed0f04..6d4b5d600 100644 --- a/core/imageboard/tag.php +++ b/core/imageboard/tag.php @@ -55,9 +55,9 @@ public static function tags(string $search, int $limit = 10): array $cache_key .= "-" . $limit; } - $res = $cache->get($cache_key); - if (is_null($res)) { - $res = $database->get_pairs( + $res = cache_get_or_set( + $cache_key, + fn () => $database->get_pairs( " SELECT tag, count FROM tags @@ -68,9 +68,9 @@ public static function tags(string $search, int $limit = 10): array $limitSQL ", $SQLarr - ); - $cache->set($cache_key, $res, 600); - } + ), + 600 + ); $counts = []; foreach ($res as $k => $v) { @@ -273,53 +273,4 @@ public static function sqlify(string $term): string // $term = str_replace("?", "_", $term); return $term; } - - /** - * Kind of like urlencode, but using a custom scheme so that - * tags always fit neatly between slashes in a URL. Use this - * when you want to put an arbitrary tag into a URL. - */ - public static function caret(string $input): string - { - $to_caret = [ - "^" => "^", - "/" => "s", - "\\" => "b", - "?" => "q", - "&" => "a", - "." => "d", - ]; - - foreach ($to_caret as $from => $to) { - $input = str_replace($from, '^' . $to, $input); - } - return $input; - } - - /** - * Use this when you want to get a tag out of a URL - */ - public static function decaret(string $str): string - { - $from_caret = [ - "^" => "^", - "s" => "/", - "b" => "\\", - "q" => "?", - "a" => "&", - "d" => ".", - ]; - - $out = ""; - $length = strlen($str); - for ($i = 0; $i < $length; $i++) { - if ($str[$i] == "^") { - $i++; - $out .= $from_caret[$str[$i]] ?? ''; - } else { - $out .= $str[$i]; - } - } - return $out; - } } diff --git a/core/microhtml.php b/core/microhtml.php index aadd633df..c7848900b 100644 --- a/core/microhtml.php +++ b/core/microhtml.php @@ -15,6 +15,7 @@ use function MicroHTML\PRE; use function MicroHTML\P; use function MicroHTML\SELECT; +use function MicroHTML\SPAN; use function MicroHTML\TABLE; use function MicroHTML\THEAD; use function MicroHTML\TFOOT; @@ -153,18 +154,26 @@ function SHM_OPTION(string $value, string $text, bool $selected = false): HTMLEl } function SHM_POST_INFO( - HTMLElement|string $title, - bool $can_edit, - HTMLElement|string $view, - HTMLElement|string $edit = "", + string $title, + HTMLElement|string|null $view = null, + HTMLElement|string|null $edit = null, + string|null $link = null, ): HTMLElement { + if(!is_null($view) && !is_null($edit)) { + $show = emptyHTML( + SPAN(["class" => "view"], $view), + SPAN(["class" => "edit"], $edit), + ); + } elseif(!is_null($edit)) { + $show = $edit; + } elseif(!is_null($view)) { + $show = $view; + } else { + $show = "???"; + } return TR( - TH(["width" => "50px"], $title), - $can_edit ? - emptyHTML( - TD(["class" => "view"], $view), - TD(["class" => "edit"], $edit), - ) : - TD($view) + ["data-row" => $title], + TH(["width" => "50px"], $link ? A(["href" => $link], $title) : $title), + TD($show) ); } diff --git a/core/polyfills.php b/core/polyfills.php index bcecda02b..6609945d8 100644 --- a/core/polyfills.php +++ b/core/polyfills.php @@ -814,3 +814,18 @@ function stringer($s): string } return ""; } + +/** + * If a value is in the cache, return it; otherwise, call the callback + * to generate it and store it in the cache. + */ +function cache_get_or_set(string $key, callable $callback, int $ttl = 0) +{ + global $cache; + $value = $cache->get($key); + if ($value === null) { + $value = $callback(); + $cache->set($key, $value, $ttl); + } + return $value; +} diff --git a/core/send_event.php b/core/send_event.php index e8ee335cd..73af571d9 100644 --- a/core/send_event.php +++ b/core/send_event.php @@ -21,7 +21,10 @@ function _load_event_listeners(): void { global $_shm_event_listeners; - $cache_path = data_path("cache/shm_event_listeners.php"); + $ver = preg_replace("/[^a-zA-Z0-9\.]/", "_", VERSION); + $key = md5(Extension::get_enabled_extensions_as_string()); + + $cache_path = data_path("cache/event_listeners/el.$ver.$key.php"); if (SPEED_HAX && file_exists($cache_path)) { require_once($cache_path); } else { diff --git a/core/testcase.php b/core/testcase.php new file mode 100644 index 000000000..f536e92b4 --- /dev/null +++ b/core/testcase.php @@ -0,0 +1,237 @@ +begin(get_called_class()); + + self::create_user(self::$admin_name); + self::create_user(self::$user_name); + } + + public function setUp(): void + { + global $database, $_tracer; + $_tracer->begin($this->name()); + $_tracer->begin("setUp"); + $class = str_replace("Test", "", get_class($this)); + try { + if (!ExtensionInfo::get_for_extension_class($class)->is_supported()) { + $this->markTestSkipped("$class not supported with this database"); + } + } catch (ExtensionNotFound $e) { + // ignore - this is a core test rather than an extension test + } + + // Set up a clean environment for each test + self::log_out(); + foreach ($database->get_col("SELECT id FROM images") as $image_id) { + send_event(new ImageDeletionEvent(Image::by_id((int)$image_id), true)); + } + + $_tracer->end(); # setUp + $_tracer->begin("test"); + } + + public function tearDown(): void + { + global $_tracer; + $_tracer->end(); # test + $_tracer->end(); # $this->getName() + $_tracer->clear(); + $_tracer->flush("data/test-trace.json"); + } + + public static function tearDownAfterClass(): void + { + parent::tearDownAfterClass(); + global $_tracer; + $_tracer->end(); # get_called_class() + } + + protected static function create_user(string $name): void + { + if (is_null(User::by_name($name))) { + $userPage = new UserPage(); + $userPage->onUserCreation(new UserCreationEvent($name, $name, $name, "$name@$name.com", false)); + assert(!is_null(User::by_name($name)), "Creation of user $name failed"); + } + } + + private static function check_args(?array $args): array + { + if (!$args) { + return []; + } + foreach ($args as $k => $v) { + if (is_array($v)) { + $args[$k] = $v; + } else { + $args[$k] = (string)$v; + } + } + return $args; + } + + protected static function request($method, $page_name, $get_args = null, $post_args = null): Page + { + // use a fresh page + global $page; + $get_args = self::check_args($get_args); + $post_args = self::check_args($post_args); + + if (str_contains($page_name, "?")) { + throw new \RuntimeException("Query string included in page name"); + } + $_SERVER['REQUEST_URI'] = make_link($page_name, http_build_query($get_args)); + $_GET = $get_args; + $_POST = $post_args; + $page = new Page(); + send_event(new PageRequestEvent($method, $page_name)); + if ($page->mode == PageMode::REDIRECT) { + $page->code = 302; + } + return $page; + } + + protected static function get_page($page_name, $args = null): Page + { + return self::request("GET", $page_name, $args, null); + } + + protected static function post_page($page_name, $args = null): Page + { + return self::request("POST", $page_name, null, $args); + } + + // page things + protected function assert_title(string $title): void + { + global $page; + $this->assertStringContainsString($title, $page->title); + } + + protected function assert_title_matches($title): void + { + global $page; + $this->assertStringMatchesFormat($title, $page->title); + } + + protected function assert_no_title(string $title): void + { + global $page; + $this->assertStringNotContainsString($title, $page->title); + } + + protected function assert_response(int $code): void + { + global $page; + $this->assertEquals($code, $page->code); + } + + protected function page_to_text(string $section = null): string + { + global $page; + if ($page->mode == PageMode::PAGE) { + $text = $page->title . "\n"; + foreach ($page->blocks as $block) { + if (is_null($section) || $section == $block->section) { + $text .= $block->header . "\n"; + $text .= $block->body . "\n\n"; + } + } + return $text; + } elseif ($page->mode == PageMode::DATA) { + return $page->data; + } else { + $this->fail("Page mode is {$page->mode->name} (only PAGE and DATA are supported)"); + } + } + + protected function assert_text(string $text, string $section = null): void + { + $this->assertStringContainsString($text, $this->page_to_text($section)); + } + + protected function assert_no_text(string $text, string $section = null): void + { + $this->assertStringNotContainsString($text, $this->page_to_text($section)); + } + + protected function assert_content(string $content): void + { + global $page; + $this->assertStringContainsString($content, $page->data); + } + + protected function assert_no_content(string $content): void + { + global $page; + $this->assertStringNotContainsString($content, $page->data); + } + + protected function assert_search_results($tags, $results): void + { + $images = Search::find_images(0, null, $tags); + $ids = []; + foreach ($images as $image) { + $ids[] = $image->id; + } + $this->assertEquals($results, $ids); + } + + // user things + protected static function log_in_as_admin(): void + { + send_event(new UserLoginEvent(User::by_name(self::$admin_name))); + } + + protected static function log_in_as_user(): void + { + send_event(new UserLoginEvent(User::by_name(self::$user_name))); + } + + protected static function log_out(): void + { + global $config; + send_event(new UserLoginEvent(User::by_id($config->get_int("anon_id", 0)))); + } + + // post things + protected function post_image(string $filename, string $tags): int + { + $dae = send_event(new DataUploadEvent($filename, [ + "filename" => $filename, + "tags" => Tag::explode($tags), + "source" => null, + ])); + // if($dae->image_id == -1) throw new \Exception("Upload failed :("); + return $dae->image_id; + } + + protected function delete_image(int $image_id): void + { + $img = Image::by_id($image_id); + if ($img) { + send_event(new ImageDeletionEvent($img, true)); + } + } + } +} else { + abstract class ShimmiePHPUnitTestCase + { + } +} diff --git a/core/tests/basepage.test.php b/core/tests/BasePageTest.php similarity index 100% rename from core/tests/basepage.test.php rename to core/tests/BasePageTest.php diff --git a/core/tests/block.test.php b/core/tests/BlockTest.php similarity index 100% rename from core/tests/block.test.php rename to core/tests/BlockTest.php diff --git a/core/tests/init.test.php b/core/tests/InitTest.php similarity index 91% rename from core/tests/init.test.php rename to core/tests/InitTest.php index 02d3a0fff..3fc48857b 100644 --- a/core/tests/init.test.php +++ b/core/tests/InitTest.php @@ -6,7 +6,7 @@ use PHPUnit\Framework\TestCase; -class TestInit extends TestCase +class InitTest extends TestCase { public function testInitExt() { diff --git a/core/tests/polyfills.test.php b/core/tests/PolyfillsTest.php similarity index 100% rename from core/tests/polyfills.test.php rename to core/tests/PolyfillsTest.php diff --git a/core/tests/SearchTest.php b/core/tests/SearchTest.php new file mode 100644 index 000000000..303072f7b --- /dev/null +++ b/core/tests/SearchTest.php @@ -0,0 +1,490 @@ +log_in_as_user(); + $image_id_1 = $this->post_image("tests/pbx_screenshot.jpg", "question? colon:thing exclamation!"); + $image_id_2 = $this->post_image("tests/bedroom_workshop.jpg", "question. colon_thing exclamation%"); + + $this->assert_search_results(["question?"], [$image_id_1]); + $this->assert_search_results(["question."], [$image_id_2]); + $this->assert_search_results(["colon:thing"], [$image_id_1]); + $this->assert_search_results(["colon_thing"], [$image_id_2]); + $this->assert_search_results(["exclamation!"], [$image_id_1]); + $this->assert_search_results(["exclamation%"], [$image_id_2]); + } + + // base case + public function testUpload(): array + { + $this->log_in_as_user(); + $image_id_1 = $this->post_image("tests/pbx_screenshot.jpg", "thing computer screenshot pbx phone"); + $image_id_2 = $this->post_image("tests/bedroom_workshop.jpg", "thing computer computing bedroom workshop"); + $this->log_out(); + + # make sure both uploads were ok + $this->assertTrue($image_id_1 > 0); + $this->assertTrue($image_id_2 > 0); + + return [$image_id_1, $image_id_2]; + } + + + /******************************************************** + * Test turning a string into an abstract query + */ + private function assert_TTC(string $tags, array $expected_tag_conditions, array $expected_img_conditions, string $expected_order) + { + $class = new \ReflectionClass('\Shimmie2\Search'); + $terms_to_conditions = $class->getMethod("terms_to_conditions"); + $terms_to_conditions->setAccessible(true); // Use this if you are running PHP older than 8.1.0 + + $obj = new Search(); + [$tag_conditions, $img_conditions, $order] = $terms_to_conditions->invokeArgs($obj, [Tag::explode($tags, false)]); + + static::assertThat( + [ + "tags" => $expected_tag_conditions, + "imgs" => $expected_img_conditions, + "order" => $expected_order, + ], + new IsEqual([ + "tags" => $tag_conditions, + "imgs" => $img_conditions, + "order" => $order, + ]) + ); + } + + public function testTTC_Empty() + { + $this->assert_TTC( + "", + [ + ], + [ + new ImgCondition(new Querylet("trash != :true", ["true" => true])), + new ImgCondition(new Querylet("private != :true OR owner_id = :private_owner_id", [ + "private_owner_id" => 1, + "true" => true])), + new ImgCondition(new Querylet("rating IN ('?', 's', 'q', 'e')", [])), + ], + "images.id DESC" + ); + } + + public function testTTC_Hash() + { + $this->assert_TTC( + "hash=1234567890", + [ + ], + [ + new ImgCondition(new Querylet("trash != :true", ["true" => true])), + new ImgCondition(new Querylet("private != :true OR owner_id = :private_owner_id", [ + "private_owner_id" => 1, + "true" => true])), + new ImgCondition(new Querylet("rating IN ('?', 's', 'q', 'e')", [])), + new ImgCondition(new Querylet("images.hash = :hash", ["hash" => "1234567890"])), + ], + "images.id DESC" + ); + } + + public function testTTC_Ratio() + { + $this->assert_TTC( + "ratio=42:12345", + [ + ], + [ + new ImgCondition(new Querylet("trash != :true", ["true" => true])), + new ImgCondition(new Querylet("private != :true OR owner_id = :private_owner_id", [ + "private_owner_id" => 1, + "true" => true])), + new ImgCondition(new Querylet("rating IN ('?', 's', 'q', 'e')", [])), + new ImgCondition(new Querylet("width / :width1 = height / :height1", ['width1' => 42, + 'height1' => 12345])), + ], + "images.id DESC" + ); + } + + public function testTTC_Order() + { + $this->assert_TTC( + "order=score", + [ + ], + [ + new ImgCondition(new Querylet("trash != :true", ["true" => true])), + new ImgCondition(new Querylet("private != :true OR owner_id = :private_owner_id", [ + "private_owner_id" => 1, + "true" => true])), + new ImgCondition(new Querylet("rating IN ('?', 's', 'q', 'e')", [])), + ], + "images.numeric_score DESC" + ); + } + + /******************************************************** + * Test turning an abstract query into SQL + fetching the results + */ + private function assert_BSQ( + array $tcs = [], + array $ics = [], + string $order = "id DESC", + int $limit = 9999, + int $start = 0, + array $res = [], + array $path = null, + ) { + global $database; + + $tcs = array_map( + fn ($tag) => ($tag[0] == "-") ? + new TagCondition(substr($tag, 1), false) : + new TagCondition($tag), + $tcs + ); + + $ics = array_map( + fn ($ic) => send_event(new SearchTermParseEvent(0, $ic, []))->img_conditions, + $ics + ); + $ics = array_merge(...$ics); + + Search::$_search_path = []; + + $class = new \ReflectionClass('\Shimmie2\Search'); + $build_search_querylet = $class->getMethod("build_search_querylet"); + $build_search_querylet->setAccessible(true); // Use this if you are running PHP older than 8.1.0 + + $obj = new Search(); + $querylet = $build_search_querylet->invokeArgs($obj, [$tcs, $ics, $order, $limit, $start]); + + $results = $database->get_all($querylet->sql, $querylet->variables); + + static::assertThat( + [ + "res" => array_map(fn ($row) => $row['id'], $results), + "path" => Search::$_search_path, + ], + new IsEqual([ + "res" => $res, + "path" => $path ?? Search::$_search_path, + ]) + ); + } + + /* * * * * * * * * * * + * No-tag search * + * * * * * * * * * * */ + #[Depends('testUpload')] + public function testBSQ_NoTags($image_ids) + { + $image_ids = $this->testUpload(); + $this->assert_BSQ( + tcs: [], + res: [$image_ids[1], $image_ids[0]], + path: ["no_tags"], + ); + } + + /* * * * * * * * * * * + * Fast-path search * + * * * * * * * * * * */ + #[Depends('testUpload')] + public function testBSQ_FastPath_NoResults($image_ids) + { + $this->testUpload(); + $this->assert_BSQ( + tcs: ["maumaumau"], + res: [], + path: ["fast", "invalid_tag"], + ); + } + + #[Depends('testUpload')] + public function testBSQ_FastPath_OneResult($image_ids) + { + $image_ids = $this->testUpload(); + $this->assert_BSQ( + tcs: ["pbx"], + res: [$image_ids[0]], + path: ["fast"], + ); + } + + #[Depends('testUpload')] + public function testBSQ_FastPath_ManyResults($image_ids) + { + $image_ids = $this->testUpload(); + $this->assert_BSQ( + tcs: ["computer"], + res: [$image_ids[1], $image_ids[0]], + path: ["fast"], + ); + } + + #[Depends('testUpload')] + public function testBSQ_FastPath_WildNoResults($image_ids) + { + $this->testUpload(); + $this->assert_BSQ( + tcs: ["asdfasdf*"], + res: [], + path: ["fast", "invalid_tag"], + ); + } + + /** + * Only the first image matches both the wildcard and the tag. + * This checks for a bug where searching for "a* b" would return + * an image tagged "a1 a2" because the number of matched tags + * was equal to the number of searched tags. + * + * https://github.com/shish/shimmie2/issues/547 + */ + #[Depends('testUpload')] + public function testBSQ_FastPath_WildOneResult($image_ids) + { + $image_ids = $this->testUpload(); + $this->assert_BSQ( + tcs: ["screen*"], + res: [$image_ids[0]], + path: ["fast"], + ); + } + + /** + * Test that the fast path doesn't return duplicate results + * when a wildcard matches one image multiple times. + */ + #[Depends('testUpload')] + public function testBSQ_FastPath_WildManyResults($image_ids) + { + $image_ids = $this->testUpload(); + // two images match comp* - one matches it once, one matches it twice + $this->assert_BSQ( + tcs: ["comp*"], + res: [$image_ids[1], $image_ids[0]], + path: ["fast"], + ); + } + + /* * * * * * * * * * * + * General search * + * * * * * * * * * * */ + #[Depends('testUpload')] + public function testBSQ_GeneralPath_NoResults($image_ids) + { + $this->testUpload(); + # multiple tags, one of which doesn't exist + # (test the "one tag doesn't exist = no hits" path) + $this->assert_BSQ( + tcs: ["computer", "not_a_tag"], + res: [], + path: ["general", "invalid_tag"], + ); + } + + #[Depends('testUpload')] + public function testBSQ_GeneralPath_OneResult($image_ids) + { + $image_ids = $this->testUpload(); + $this->assert_BSQ( + tcs: ["computer", "screenshot"], + res: [$image_ids[0]], + path: ["general", "some_positives"], + ); + } + + /** + * Only the first image matches both the wildcard and the tag. + * This checks for a bug where searching for "a* b" would return + * an image tagged "a1 a2" because the number of matched tags + * was equal to the number of searched tags. + * + * https://github.com/shish/shimmie2/issues/547 + */ + #[Depends('testUpload')] + public function testBSQ_GeneralPath_WildOneResult($image_ids) + { + $image_ids = $this->testUpload(); + $this->assert_BSQ( + tcs: ["comp*", "screenshot"], + res: [$image_ids[0]], + path: ["general", "some_positives"], + ); + } + + #[Depends('testUpload')] + public function testBSQ_GeneralPath_ManyResults($image_ids) + { + $image_ids = $this->testUpload(); + $this->assert_BSQ( + tcs: ["computer", "thing"], + res: [$image_ids[1], $image_ids[0]], + path: ["general", "some_positives"], + ); + } + + #[Depends('testUpload')] + public function testBSQ_GeneralPath_WildManyResults($image_ids) + { + $image_ids = $this->testUpload(); + $this->assert_BSQ( + tcs: ["comp*", "-asdf"], + res: [$image_ids[1], $image_ids[0]], + path: ["general", "some_positives"], + ); + } + + #[Depends('testUpload')] + public function testBSQ_GeneralPath_SubtractValidFromResults($image_ids) + { + $image_ids = $this->testUpload(); + $this->assert_BSQ( + tcs: ["computer", "-pbx"], + res: [$image_ids[1]], + path: ["general", "some_positives"], + ); + } + + #[Depends('testUpload')] + public function testBSQ_GeneralPath_SubtractNotValidFromResults($image_ids) + { + $image_ids = $this->testUpload(); + $this->assert_BSQ( + tcs: ["computer", "-not_a_tag"], + res: [$image_ids[1], $image_ids[0]], + path: ["general", "some_positives"], + ); + } + + #[Depends('testUpload')] + public function testBSQ_GeneralPath_SubtractValidFromDefault($image_ids) + { + $image_ids = $this->testUpload(); + // negative tag alone, should remove the image with that tag + $this->assert_BSQ( + tcs: ["-pbx"], + res: [$image_ids[1]], + path: ["general", "only_negative_tags"], + ); + } + + #[Depends('testUpload')] + public function testBSQ_GeneralPath_SubtractNotValidFromDefault($image_ids) + { + $image_ids = $this->testUpload(); + // negative that doesn't exist, should return all results + $this->assert_BSQ( + tcs: ["-not_a_tag"], + res: [$image_ids[1], $image_ids[0]], + path: ["general", "all_nonexistent_negatives"], + ); + } + + #[Depends('testUpload')] + public function testBSQ_GeneralPath_SubtractMultipleNotValidFromDefault($image_ids) + { + $image_ids = $this->testUpload(); + // multiple negative tags that don't exist, should return all results + $this->assert_BSQ( + tcs: ["-not_a_tag", "-also_not_a_tag"], + res: [$image_ids[1], $image_ids[0]], + path: ["general", "all_nonexistent_negatives"], + ); + } + + /* * * * * * * * * * * + * Meta Search * + * * * * * * * * * * */ + #[Depends('testUpload')] + public function testBSQ_ImgCond_NoResults($image_ids) + { + $this->testUpload(); + $this->assert_BSQ( + ics: ["hash=1234567890"], + res: [], + path: ["no_tags"], + ); + $this->assert_BSQ( + ics: ["ratio=42:12345"], + res: [], + path: ["no_tags"], + ); + } + + #[Depends('testUpload')] + public function testBSQ_ImgCond_OneResult($image_ids) + { + $image_ids = $this->testUpload(); + $this->assert_BSQ( + ics: ["hash=feb01bab5698a11dd87416724c7a89e3"], + res: [$image_ids[0]], + path: ["no_tags"], + ); + $this->assert_BSQ( + ics: ["id={$image_ids[1]}"], + res: [$image_ids[1]], + path: ["no_tags"], + ); + $this->assert_BSQ( + ics: ["filename=screenshot"], + res: [$image_ids[0]], + path: ["no_tags"], + ); + } + + #[Depends('testUpload')] + public function testBSQ_ImgCond_ManyResults($image_ids) + { + $image_ids = $this->testUpload(); + + $this->assert_BSQ( + ics: ["size=640x480"], + res: [$image_ids[1], $image_ids[0]], + path: ["no_tags"], + ); + $this->assert_BSQ( + ics: ["tags=5"], + res: [$image_ids[1], $image_ids[0]], + path: ["no_tags"], + ); + $this->assert_BSQ( + ics: ["ext=jpg"], + res: [$image_ids[1], $image_ids[0]], + path: ["no_tags"], + ); + } + + /* * * * * * * * * * * + * Mixed * + * * * * * * * * * * */ + #[Depends('testUpload')] + public function testBSQ_TagCondWithImgCond($image_ids) + { + $image_ids = $this->testUpload(); + // multiple tags, many results + $this->assert_BSQ( + tcs: ["computer"], + ics: ["size=640x480"], + res: [$image_ids[1], $image_ids[0]], + path: ["general", "some_positives"], + ); + } +} diff --git a/core/tests/tag.test.php b/core/tests/TagTest.php similarity index 51% rename from core/tests/tag.test.php rename to core/tests/TagTest.php index 1fdbcdf40..de9288985 100644 --- a/core/tests/tag.test.php +++ b/core/tests/TagTest.php @@ -10,20 +10,6 @@ class TagTest extends TestCase { - public function test_caret() - { - $this->assertEquals("foo", Tag::decaret("foo")); - $this->assertEquals("foo?", Tag::decaret("foo^q")); - $this->assertEquals("a^b/c\\d?e&f", Tag::decaret("a^^b^sc^bd^qe^af")); - } - - public function test_decaret() - { - $this->assertEquals("foo", Tag::caret("foo")); - $this->assertEquals("foo^q", Tag::caret("foo?")); - $this->assertEquals("a^^b^sc^bd^qe^af", Tag::caret("a^b/c\\d?e&f")); - } - public function test_compare() { $this->assertFalse(Tag::compare(["foo"], ["bar"])); diff --git a/core/tests/urls.test.php b/core/tests/UrlsTest.php similarity index 96% rename from core/tests/urls.test.php rename to core/tests/UrlsTest.php index 5d939c84a..2d8c8e101 100644 --- a/core/tests/urls.test.php +++ b/core/tests/UrlsTest.php @@ -13,11 +13,11 @@ class UrlsTest extends TestCase public function test_search_link() { $this->assertEquals( - "/test/post/list/bar+foo/1", + "/test/post/list/bar%20foo/1", search_link(["foo", "bar"]) ); $this->assertEquals( - "/test/post/list/cat%2A+rating%3D%5Eq/1", + "/test/post/list/cat%2A%20rating%3D%3F/1", search_link(["rating=?", "cat*"]) ); } diff --git a/core/tests/util.test.php b/core/tests/UtilTest.php similarity index 100% rename from core/tests/util.test.php rename to core/tests/UtilTest.php diff --git a/core/urls.php b/core/urls.php index e2fbf864d..845873e90 100644 --- a/core/urls.php +++ b/core/urls.php @@ -4,8 +4,6 @@ namespace Shimmie2; -use PhpParser\Node\Expr\Cast\Double; - class Link { public ?string $page; @@ -30,7 +28,7 @@ public function make_link(): string function search_link(array $terms = [], int $page = 1): string { if($terms) { - $q = urlencode(Tag::caret(Tag::implode($terms))); + $q = url_escape(Tag::implode($terms)); return make_link("post/list/$q/$page"); } else { return make_link("post/list/$page"); diff --git a/core/user.php b/core/user.php index 521e35f26..8dc8c1309 100644 --- a/core/user.php +++ b/core/user.php @@ -11,12 +11,6 @@ use function MicroHTML\INPUT; -function _new_user(array $row): User -{ - return new User($row); -} - - /** * Class User * diff --git a/core/userclass.php b/core/userclass.php index 2473e9549..bbc608639 100644 --- a/core/userclass.php +++ b/core/userclass.php @@ -88,6 +88,7 @@ public function can(string $ability): bool // Ghost users can't do anything new UserClass("ghost", "base", [ + Permissions::READ_PM => true, ]); // Anonymous users can't do anything by default, but diff --git a/core/util.php b/core/util.php index 2e0e197e1..9c695e7d3 100644 --- a/core/util.php +++ b/core/util.php @@ -565,11 +565,20 @@ function _load_core_files() )); } +function _load_extension_files() +{ + ExtensionInfo::load_all_extension_info(); + Extension::determine_enabled_extensions(); + require_all(zglob("ext/{".Extension::get_enabled_extensions_as_string()."}/main.php")); +} + function _load_theme_files() { $theme = get_theme(); - $files = _get_themelet_files($theme); - require_all($files); + require_once('themes/'.$theme.'/page.class.php'); + require_once('themes/'.$theme.'/themelet.class.php'); + require_all(zglob("ext/{".Extension::get_enabled_extensions_as_string()."}/theme.php")); + require_all(zglob('themes/'.$theme.'/{'.Extension::get_enabled_extensions_as_string().'}.theme.php')); } function _set_up_shimmie_environment(): void @@ -595,19 +604,6 @@ function _set_up_shimmie_environment(): void } -function _get_themelet_files(string $_theme): array -{ - $base_themelets = []; - $base_themelets[] = 'themes/'.$_theme.'/page.class.php'; - $base_themelets[] = 'themes/'.$_theme.'/themelet.class.php'; - - $ext_themelets = zglob("ext/{".Extension::get_enabled_extensions_as_string()."}/theme.php"); - $custom_themelets = zglob('themes/'.$_theme.'/{'.Extension::get_enabled_extensions_as_string().'}.theme.php'); - - return array_merge($base_themelets, $ext_themelets, $custom_themelets); -} - - /** * Used to display fatal errors to the web user. */ @@ -677,7 +673,7 @@ function _get_user(): User } } } - if ($page->get_cookie("user") && $page->get_cookie("session")) { + if (is_null($my_user) && $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)) { @@ -690,7 +686,19 @@ function _get_user(): User function _get_query(): string { - return (@$_POST["q"] ?: @$_GET["q"]) ?: "/"; + // if query is explicitly set, use it + $q = @$_POST["q"] ?: @$_GET["q"]; + if(!empty($q)) { + return $q; + } + // if we're just looking at index.php, use the default query + elseif (str_contains($_SERVER['REQUEST_URI'], "index.php")) { + return "/"; + } + // otherwise, use the request URI + else { + return explode("?", $_SERVER['REQUEST_URI'])[0]; + } } diff --git a/ext/admin/main.php b/ext/admin/main.php index f564d971e..44b6d503f 100644 --- a/ext/admin/main.php +++ b/ext/admin/main.php @@ -86,16 +86,15 @@ public function onCommand(CommandEvent $event) parse_str($event->args[1], $_GET); $_SERVER['REQUEST_URI'] .= "?" . $event->args[1]; } - send_event(new PageRequestEvent($event->args[0])); + send_event(new PageRequestEvent("GET", $event->args[0])); $page->display(); } if ($event->cmd == "post-page") { global $page; - $_SERVER['REQUEST_METHOD'] = "POST"; if (isset($event->args[1])) { parse_str($event->args[1], $_POST); } - send_event(new PageRequestEvent($event->args[0])); + send_event(new PageRequestEvent("POST", $event->args[0])); $page->display(); } if ($event->cmd == "get-token") { diff --git a/ext/alias_editor/main.php b/ext/alias_editor/main.php index 25632f229..c4c978425 100644 --- a/ext/alias_editor/main.php +++ b/ext/alias_editor/main.php @@ -19,8 +19,8 @@ public function __construct(\FFSPHP\PDO $db) $this->size = 100; $this->limit = 1000000; $this->set_columns([ - new TextColumn("oldtag", "Old Tag"), - new TextColumn("newtag", "New Tag"), + new AutoCompleteColumn("oldtag", "Old Tag"), + new AutoCompleteColumn("newtag", "New Tag"), new ActionColumn("oldtag"), ]); $this->order_by = ["oldtag"]; diff --git a/ext/artists/main.php b/ext/artists/main.php index 51be763be..05eba47ca 100644 --- a/ext/artists/main.php +++ b/ext/artists/main.php @@ -209,7 +209,7 @@ public function onPageRequest(PageRequestEvent $event) $userIsLogged = !$user->is_anonymous(); $userIsAdmin = $user->can(Permissions::ARTISTS_ADMIN); - $images = Image::find_images(limit: 4, tags: Tag::explode($artist['name'])); + $images = Search::find_images(limit: 4, tags: Tag::explode($artist['name'])); $this->theme->show_artist($artist, $aliases, $members, $urls, $images, $userIsLogged, $userIsAdmin); /* diff --git a/ext/artists/theme.php b/ext/artists/theme.php index 5db8f1e61..12e9e9219 100644 --- a/ext/artists/theme.php +++ b/ext/artists/theme.php @@ -15,7 +15,6 @@ public function get_author_editor_html(string $author): HTMLElement { return SHM_POST_INFO( "Author", - true, $author, INPUT(["type" => "text", "name" => "tag_edit__author", "value" => $author]) ); diff --git a/ext/auto_tagger/main.php b/ext/auto_tagger/main.php index a20084575..fc2d860ac 100644 --- a/ext/auto_tagger/main.php +++ b/ext/auto_tagger/main.php @@ -21,8 +21,8 @@ public function __construct(\FFSPHP\PDO $db) $this->size = 100; $this->limit = 1000000; $this->set_columns([ - new TextColumn("tag", "Tag"), - new TextColumn("additional_tags", "Additional Tags"), + new AutoCompleteColumn("tag", "Tag"), + new AutoCompleteColumn("additional_tags", "Additional Tags"), new ActionColumn("tag"), ]); $this->order_by = ["tag"]; @@ -272,7 +272,7 @@ private function remove_auto_tag(string $tag) } /** - * #param string[] $tags_mixed + * @param string[] $tags_mixed */ private function apply_auto_tags(array $tags_mixed): ?array { diff --git a/ext/autocomplete/lib/jquery-ui.min.css b/ext/autocomplete/lib/jquery-ui.min.css deleted file mode 100644 index 91f16a3b8..000000000 --- a/ext/autocomplete/lib/jquery-ui.min.css +++ /dev/null @@ -1,7 +0,0 @@ -/*! jQuery UI - v1.11.2 - 2014-10-16 -* http://jqueryui.com -* Includes: core.css, accordion.css, autocomplete.css, button.css, datepicker.css, dialog.css, draggable.css, menu.css, progressbar.css, resizable.css, selectable.css, selectmenu.css, slider.css, sortable.css, spinner.css, tabs.css, tooltip.css, theme.css -* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Trebuchet%20MS%2CTahoma%2CVerdana%2CArial%2Csans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=f6a828&bgTextureHeader=gloss_wave&bgImgOpacityHeader=35&borderColorHeader=e78f08&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=eeeeee&bgTextureContent=highlight_soft&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=333333&iconColorContent=222222&bgColorDefault=f6f6f6&bgTextureDefault=glass&bgImgOpacityDefault=100&borderColorDefault=cccccc&fcDefault=1c94c4&iconColorDefault=ef8c08&bgColorHover=fdf5ce&bgTextureHover=glass&bgImgOpacityHover=100&borderColorHover=fbcb09&fcHover=c77405&iconColorHover=ef8c08&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=fbd850&fcActive=eb8f00&iconColorActive=ef8c08&bgColorHighlight=ffe45c&bgTextureHighlight=highlight_soft&bgImgOpacityHighlight=75&borderColorHighlight=fed22f&fcHighlight=363636&iconColorHighlight=228ef1&bgColorError=b81900&bgTextureError=diagonals_thick&bgImgOpacityError=18&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffd27a&bgColorOverlay=666666&bgTextureOverlay=diagonals_thick&bgImgOpacityOverlay=20&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=flat&bgImgOpacityShadow=10&opacityShadow=20&thicknessShadow=5px&offsetTopShadow=-5px&offsetLeftShadow=-5px&cornerRadiusShadow=5px -* Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */ - -.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin:2px 0 0 0;padding:.5em .5em .5em .7em;min-height:0;font-size:100%}.ui-accordion .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-icons .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-header .ui-accordion-header-icon{position:absolute;left:.5em;top:50%;margin-top:-8px}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-button{display:inline-block;position:relative;padding:0;line-height:normal;margin-right:.1em;cursor:pointer;vertical-align:middle;text-align:center;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2.2em}button.ui-button-icon-only{width:2.4em}.ui-button-icons-only{width:3.4em}button.ui-button-icons-only{width:3.7em}.ui-button .ui-button-text{display:block;line-height:normal}.ui-button-text-only .ui-button-text{padding:.4em 1em}.ui-button-icon-only .ui-button-text,.ui-button-icons-only .ui-button-text{padding:.4em;text-indent:-9999999px}.ui-button-text-icon-primary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 1em .4em 2.1em}.ui-button-text-icon-secondary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 2.1em .4em 1em}.ui-button-text-icons .ui-button-text{padding-left:2.1em;padding-right:2.1em}input.ui-button{padding:.4em 1em}.ui-button-icon-only .ui-icon,.ui-button-text-icon-primary .ui-icon,.ui-button-text-icon-secondary .ui-icon,.ui-button-text-icons .ui-icon,.ui-button-icons-only .ui-icon{position:absolute;top:50%;margin-top:-8px}.ui-button-icon-only .ui-icon{left:50%;margin-left:-8px}.ui-button-text-icon-primary .ui-button-icon-primary,.ui-button-text-icons .ui-button-icon-primary,.ui-button-icons-only .ui-button-icon-primary{left:.5em}.ui-button-text-icon-secondary .ui-button-icon-secondary,.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-buttonset{margin-right:7px}.ui-buttonset .ui-button{margin-left:0;margin-right:-.3em}input.ui-button::-moz-focus-inner,button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:45%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-dialog{overflow:hidden;position:absolute;top:0;left:0;padding:.2em;outline:0}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 0;white-space:nowrap;width:90%;overflow:hidden;text-overflow:ellipsis}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:20px;margin:-10px 0 0 0;padding:1px;height:20px}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin-top:.5em;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-se{width:12px;height:12px;right:-5px;bottom:-5px;background-position:16px 16px}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-draggable-handle{-ms-touch-action:none;touch-action:none}.ui-menu{list-style:none;padding:0;margin:0;display:block;outline:none}.ui-menu .ui-menu{position:absolute}.ui-menu .ui-menu-item{position:relative;margin:0;padding:3px 1em 3px .4em;cursor:pointer;min-height:0;list-style-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7")}.ui-menu .ui-menu-divider{margin:5px 0;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-state-focus,.ui-menu .ui-state-active{margin:-1px}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item{padding-left:2em}.ui-menu .ui-icon{position:absolute;top:0;bottom:0;left:.2em;margin:auto 0}.ui-menu .ui-menu-icon{left:auto;right:0}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-progressbar .ui-progressbar-overlay{background:url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==");height:100%;filter:alpha(opacity=25);opacity:0.25}.ui-progressbar-indeterminate .ui-progressbar-value{background-image:none}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block;-ms-touch-action:none;touch-action:none}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-selectable{-ms-touch-action:none;touch-action:none}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}.ui-selectmenu-menu{padding:0;margin:0;position:absolute;top:0;left:0;display:none}.ui-selectmenu-menu .ui-menu{overflow:auto;overflow-x:hidden;padding-bottom:1px}.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup{font-size:1em;font-weight:bold;line-height:1.5;padding:2px 0.4em;margin:0.5em 0 0 0;height:auto;border:0}.ui-selectmenu-open{display:block}.ui-selectmenu-button{display:inline-block;overflow:hidden;position:relative;text-decoration:none;cursor:pointer}.ui-selectmenu-button span.ui-icon{right:0.5em;left:auto;margin-top:-8px;position:absolute;top:50%}.ui-selectmenu-button span.ui-selectmenu-text{text-align:left;padding:0.4em 2.1em 0.4em 1em;display:block;line-height:1.4;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default;-ms-touch-action:none;touch-action:none}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-sortable-handle{-ms-touch-action:none;touch-action:none}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:none;background:none;color:inherit;padding:0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:22px}.ui-spinner-button{width:16px;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner a.ui-spinner-button{border-top:none;border-bottom:none;border-right:none}.ui-spinner .ui-icon{position:absolute;margin-top:-8px;top:50%;left:0}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-spinner .ui-icon-triangle-1-s{background-position:-65px -16px}.ui-tabs{position:relative;padding:.2em}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom-width:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav .ui-tabs-anchor{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor{cursor:text}.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px;-webkit-box-shadow:0 0 5px #aaa;box-shadow:0 0 5px #aaa}body .ui-tooltip{border-width:2px}.ui-widget{font-family:Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #ddd;background:#eee url("images/ui-bg_highlight-soft_100_eeeeee_1x100.png") 50% top repeat-x;color:#333}.ui-widget-content a{color:#333}.ui-widget-header{border:1px solid #e78f08;background:#f6a828 url("images/ui-bg_gloss-wave_35_f6a828_500x100.png") 50% 50% repeat-x;color:#fff;font-weight:bold}.ui-widget-header a{color:#fff}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #ccc;background:#f6f6f6 url("images/ui-bg_glass_100_f6f6f6_1x400.png") 50% 50% repeat-x;font-weight:bold;color:#1c94c4}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#1c94c4;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #fbcb09;background:#fdf5ce url("images/ui-bg_glass_100_fdf5ce_1x400.png") 50% 50% repeat-x;font-weight:bold;color:#c77405}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited{color:#c77405;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #fbd850;background:#fff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x;font-weight:bold;color:#eb8f00}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#eb8f00;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fed22f;background:#ffe45c url("images/ui-bg_highlight-soft_75_ffe45c_1x100.png") 50% top repeat-x;color:#363636}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#b81900 url("images/ui-bg_diagonals-thick_18_b81900_40x40.png") 50% 50% repeat;color:#fff}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#fff}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#fff}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("images/ui-icons_222222_256x240.png")}.ui-widget-header .ui-icon{background-image:url("images/ui-icons_ffffff_256x240.png")}.ui-state-default .ui-icon{background-image:url("images/ui-icons_ef8c08_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url("images/ui-icons_ef8c08_256x240.png")}.ui-state-active .ui-icon{background-image:url("images/ui-icons_ef8c08_256x240.png")}.ui-state-highlight .ui-icon{background-image:url("images/ui-icons_228ef1_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("images/ui-icons_ffd27a_256x240.png")}.ui-icon-blank{background-position:16px 16px}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:4px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:4px}.ui-widget-overlay{background:#666 url("images/ui-bg_diagonals-thick_20_666666_40x40.png") 50% 50% repeat;opacity:.5;filter:Alpha(Opacity=50)}.ui-widget-shadow{margin:-5px 0 0 -5px;padding:5px;background:#000 url("images/ui-bg_flat_10_000000_40x100.png") 50% 50% repeat-x;opacity:.2;filter:Alpha(Opacity=20);border-radius:5px} \ No newline at end of file diff --git a/ext/autocomplete/lib/jquery-ui.min.js b/ext/autocomplete/lib/jquery-ui.min.js deleted file mode 100644 index 17eab7903..000000000 --- a/ext/autocomplete/lib/jquery-ui.min.js +++ /dev/null @@ -1,13 +0,0 @@ -/*! jQuery UI - v1.11.2 - 2014-10-16 -* http://jqueryui.com -* Includes: core.js, widget.js, mouse.js, position.js, accordion.js, autocomplete.js, button.js, datepicker.js, dialog.js, draggable.js, droppable.js, effect.js, effect-blind.js, effect-bounce.js, effect-clip.js, effect-drop.js, effect-explode.js, effect-fade.js, effect-fold.js, effect-highlight.js, effect-puff.js, effect-pulsate.js, effect-scale.js, effect-shake.js, effect-size.js, effect-slide.js, effect-transfer.js, menu.js, progressbar.js, resizable.js, selectable.js, selectmenu.js, slider.js, sortable.js, spinner.js, tabs.js, tooltip.js -* Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */ - -(function(e){"function"==typeof define&&define.amd?define(["jquery"],e):e(jQuery)})(function(e){function t(t,s){var n,a,o,r=t.nodeName.toLowerCase();return"area"===r?(n=t.parentNode,a=n.name,t.href&&a&&"map"===n.nodeName.toLowerCase()?(o=e("img[usemap='#"+a+"']")[0],!!o&&i(o)):!1):(/input|select|textarea|button|object/.test(r)?!t.disabled:"a"===r?t.href||s:s)&&i(t)}function i(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return"hidden"===e.css(this,"visibility")}).length}function s(e){for(var t,i;e.length&&e[0]!==document;){if(t=e.css("position"),("absolute"===t||"relative"===t||"fixed"===t)&&(i=parseInt(e.css("zIndex"),10),!isNaN(i)&&0!==i))return i;e=e.parent()}return 0}function n(){this._curInst=null,this._keyEvent=!1,this._disabledInputs=[],this._datepickerShowing=!1,this._inDialog=!1,this._mainDivId="ui-datepicker-div",this._inlineClass="ui-datepicker-inline",this._appendClass="ui-datepicker-append",this._triggerClass="ui-datepicker-trigger",this._dialogClass="ui-datepicker-dialog",this._disableClass="ui-datepicker-disabled",this._unselectableClass="ui-datepicker-unselectable",this._currentClass="ui-datepicker-current-day",this._dayOverClass="ui-datepicker-days-cell-over",this.regional=[],this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""},this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:!1,hideIfNoPrevNext:!1,navigationAsDateFormat:!1,gotoCurrent:!1,changeMonth:!1,changeYear:!1,yearRange:"c-10:c+10",showOtherMonths:!1,selectOtherMonths:!1,showWeek:!1,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:!0,showButtonPanel:!1,autoSize:!1,disabled:!1},e.extend(this._defaults,this.regional[""]),this.regional.en=e.extend(!0,{},this.regional[""]),this.regional["en-US"]=e.extend(!0,{},this.regional.en),this.dpDiv=a(e("
"))}function a(t){var i="button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";return t.delegate(i,"mouseout",function(){e(this).removeClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&e(this).removeClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&e(this).removeClass("ui-datepicker-next-hover")}).delegate(i,"mouseover",o)}function o(){e.datepicker._isDisabledDatepicker(v.inline?v.dpDiv.parent()[0]:v.input[0])||(e(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"),e(this).addClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&e(this).addClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&e(this).addClass("ui-datepicker-next-hover"))}function r(t,i){e.extend(t,i);for(var s in i)null==i[s]&&(t[s]=i[s]);return t}function h(e){return function(){var t=this.element.val();e.apply(this,arguments),this._refresh(),t!==this.element.val()&&this._trigger("change")}}e.ui=e.ui||{},e.extend(e.ui,{version:"1.11.2",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({scrollParent:function(t){var i=this.css("position"),s="absolute"===i,n=t?/(auto|scroll|hidden)/:/(auto|scroll)/,a=this.parents().filter(function(){var t=e(this);return s&&"static"===t.css("position")?!1:n.test(t.css("overflow")+t.css("overflow-y")+t.css("overflow-x"))}).eq(0);return"fixed"!==i&&a.length?a:e(this[0].ownerDocument||document)},uniqueId:function(){var e=0;return function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++e)})}}(),removeUniqueId:function(){return this.each(function(){/^ui-id-\d+$/.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(i){return!!e.data(i,t)}}):function(t,i,s){return!!e.data(t,s[3])},focusable:function(i){return t(i,!isNaN(e.attr(i,"tabindex")))},tabbable:function(i){var s=e.attr(i,"tabindex"),n=isNaN(s);return(n||s>=0)&&t(i,!n)}}),e("").outerWidth(1).jquery||e.each(["Width","Height"],function(t,i){function s(t,i,s,a){return e.each(n,function(){i-=parseFloat(e.css(t,"padding"+this))||0,s&&(i-=parseFloat(e.css(t,"border"+this+"Width"))||0),a&&(i-=parseFloat(e.css(t,"margin"+this))||0)}),i}var n="Width"===i?["Left","Right"]:["Top","Bottom"],a=i.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+i]=function(t){return void 0===t?o["inner"+i].call(this):this.each(function(){e(this).css(a,s(this,t)+"px")})},e.fn["outer"+i]=function(t,n){return"number"!=typeof t?o["outer"+i].call(this,t):this.each(function(){e(this).css(a,s(this,t,!0,n)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e("").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(i){return arguments.length?t.call(this,e.camelCase(i)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.fn.extend({focus:function(t){return function(i,s){return"number"==typeof i?this.each(function(){var t=this;setTimeout(function(){e(t).focus(),s&&s.call(t)},i)}):t.apply(this,arguments)}}(e.fn.focus),disableSelection:function(){var e="onselectstart"in document.createElement("div")?"selectstart":"mousedown";return function(){return this.bind(e+".ui-disableSelection",function(e){e.preventDefault()})}}(),enableSelection:function(){return this.unbind(".ui-disableSelection")},zIndex:function(t){if(void 0!==t)return this.css("zIndex",t);if(this.length)for(var i,s,n=e(this[0]);n.length&&n[0]!==document;){if(i=n.css("position"),("absolute"===i||"relative"===i||"fixed"===i)&&(s=parseInt(n.css("zIndex"),10),!isNaN(s)&&0!==s))return s;n=n.parent()}return 0}}),e.ui.plugin={add:function(t,i,s){var n,a=e.ui[t].prototype;for(n in s)a.plugins[n]=a.plugins[n]||[],a.plugins[n].push([i,s[n]])},call:function(e,t,i,s){var n,a=e.plugins[t];if(a&&(s||e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType))for(n=0;a.length>n;n++)e.options[a[n][0]]&&a[n][1].apply(e.element,i)}};var l=0,u=Array.prototype.slice;e.cleanData=function(t){return function(i){var s,n,a;for(a=0;null!=(n=i[a]);a++)try{s=e._data(n,"events"),s&&s.remove&&e(n).triggerHandler("remove")}catch(o){}t(i)}}(e.cleanData),e.widget=function(t,i,s){var n,a,o,r,h={},l=t.split(".")[0];return t=t.split(".")[1],n=l+"-"+t,s||(s=i,i=e.Widget),e.expr[":"][n.toLowerCase()]=function(t){return!!e.data(t,n)},e[l]=e[l]||{},a=e[l][t],o=e[l][t]=function(e,t){return this._createWidget?(arguments.length&&this._createWidget(e,t),void 0):new o(e,t)},e.extend(o,a,{version:s.version,_proto:e.extend({},s),_childConstructors:[]}),r=new i,r.options=e.widget.extend({},r.options),e.each(s,function(t,s){return e.isFunction(s)?(h[t]=function(){var e=function(){return i.prototype[t].apply(this,arguments)},n=function(e){return i.prototype[t].apply(this,e)};return function(){var t,i=this._super,a=this._superApply;return this._super=e,this._superApply=n,t=s.apply(this,arguments),this._super=i,this._superApply=a,t}}(),void 0):(h[t]=s,void 0)}),o.prototype=e.widget.extend(r,{widgetEventPrefix:a?r.widgetEventPrefix||t:t},h,{constructor:o,namespace:l,widgetName:t,widgetFullName:n}),a?(e.each(a._childConstructors,function(t,i){var s=i.prototype;e.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete a._childConstructors):i._childConstructors.push(o),e.widget.bridge(t,o),o},e.widget.extend=function(t){for(var i,s,n=u.call(arguments,1),a=0,o=n.length;o>a;a++)for(i in n[a])s=n[a][i],n[a].hasOwnProperty(i)&&void 0!==s&&(t[i]=e.isPlainObject(s)?e.isPlainObject(t[i])?e.widget.extend({},t[i],s):e.widget.extend({},s):s);return t},e.widget.bridge=function(t,i){var s=i.prototype.widgetFullName||t;e.fn[t]=function(n){var a="string"==typeof n,o=u.call(arguments,1),r=this;return n=!a&&o.length?e.widget.extend.apply(null,[n].concat(o)):n,a?this.each(function(){var i,a=e.data(this,s);return"instance"===n?(r=a,!1):a?e.isFunction(a[n])&&"_"!==n.charAt(0)?(i=a[n].apply(a,o),i!==a&&void 0!==i?(r=i&&i.jquery?r.pushStack(i.get()):i,!1):void 0):e.error("no such method '"+n+"' for "+t+" widget instance"):e.error("cannot call methods on "+t+" prior to initialization; "+"attempted to call method '"+n+"'")}):this.each(function(){var t=e.data(this,s);t?(t.option(n||{}),t._init&&t._init()):e.data(this,s,new i(n,this))}),r}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"
",options:{disabled:!1,create:null},_createWidget:function(t,i){i=e(i||this.defaultElement||this)[0],this.element=e(i),this.uuid=l++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=e(),this.hoverable=e(),this.focusable=e(),i!==this&&(e.data(i,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===i&&this.destroy()}}),this.document=e(i.style?i.ownerDocument:i.document||i),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(t,i){var s,n,a,o=t;if(0===arguments.length)return e.widget.extend({},this.options);if("string"==typeof t)if(o={},s=t.split("."),t=s.shift(),s.length){for(n=o[t]=e.widget.extend({},this.options[t]),a=0;s.length-1>a;a++)n[s[a]]=n[s[a]]||{},n=n[s[a]];if(t=s.pop(),1===arguments.length)return void 0===n[t]?null:n[t];n[t]=i}else{if(1===arguments.length)return void 0===this.options[t]?null:this.options[t];o[t]=i}return this._setOptions(o),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,"disabled"===e&&(this.widget().toggleClass(this.widgetFullName+"-disabled",!!t),t&&(this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus"))),this},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_on:function(t,i,s){var n,a=this;"boolean"!=typeof t&&(s=i,i=t,t=!1),s?(i=n=e(i),this.bindings=this.bindings.add(i)):(s=i,i=this.element,n=this.widget()),e.each(s,function(s,o){function r(){return t||a.options.disabled!==!0&&!e(this).hasClass("ui-state-disabled")?("string"==typeof o?a[o]:o).apply(a,arguments):void 0}"string"!=typeof o&&(r.guid=o.guid=o.guid||r.guid||e.guid++);var h=s.match(/^([\w:-]*)\s*(.*)$/),l=h[1]+a.eventNamespace,u=h[2];u?n.delegate(u,l,r):i.bind(l,r)})},_off:function(t,i){i=(i||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,t.unbind(i).undelegate(i),this.bindings=e(this.bindings.not(t).get()),this.focusable=e(this.focusable.not(t).get()),this.hoverable=e(this.hoverable.not(t).get())},_delay:function(e,t){function i(){return("string"==typeof e?s[e]:e).apply(s,arguments)}var s=this;return setTimeout(i,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,i,s){var n,a,o=this.options[t];if(s=s||{},i=e.Event(i),i.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),i.target=this.element[0],a=i.originalEvent)for(n in a)n in i||(i[n]=a[n]);return this.element.trigger(i,s),!(e.isFunction(o)&&o.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,i){e.Widget.prototype["_"+t]=function(s,n,a){"string"==typeof n&&(n={effect:n});var o,r=n?n===!0||"number"==typeof n?i:n.effect||i:t;n=n||{},"number"==typeof n&&(n={duration:n}),o=!e.isEmptyObject(n),n.complete=a,n.delay&&s.delay(n.delay),o&&e.effects&&e.effects.effect[r]?s[t](n):r!==t&&s[r]?s[r](n.duration,n.easing,a):s.queue(function(i){e(this)[t](),a&&a.call(s[0]),i()})}}),e.widget;var d=!1;e(document).mouseup(function(){d=!1}),e.widget("ui.mouse",{version:"1.11.2",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.bind("mousedown."+this.widgetName,function(e){return t._mouseDown(e)}).bind("click."+this.widgetName,function(i){return!0===e.data(i.target,t.widgetName+".preventClickEvent")?(e.removeData(i.target,t.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):void 0}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&this.document.unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(t){if(!d){this._mouseMoved=!1,this._mouseStarted&&this._mouseUp(t),this._mouseDownEvent=t;var i=this,s=1===t.which,n="string"==typeof this.options.cancel&&t.target.nodeName?e(t.target).closest(this.options.cancel).length:!1;return s&&!n&&this._mouseCapture(t)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){i.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(t)!==!1,!this._mouseStarted)?(t.preventDefault(),!0):(!0===e.data(t.target,this.widgetName+".preventClickEvent")&&e.removeData(t.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(e){return i._mouseMove(e)},this._mouseUpDelegate=function(e){return i._mouseUp(e)},this.document.bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),t.preventDefault(),d=!0,!0)):!0}},_mouseMove:function(t){if(this._mouseMoved){if(e.ui.ie&&(!document.documentMode||9>document.documentMode)&&!t.button)return this._mouseUp(t);if(!t.which)return this._mouseUp(t)}return(t.which||t.button)&&(this._mouseMoved=!0),this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted)},_mouseUp:function(t){return this.document.unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),d=!1,!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}}),function(){function t(e,t,i){return[parseFloat(e[0])*(p.test(e[0])?t/100:1),parseFloat(e[1])*(p.test(e[1])?i/100:1)]}function i(t,i){return parseInt(e.css(t,i),10)||0}function s(t){var i=t[0];return 9===i.nodeType?{width:t.width(),height:t.height(),offset:{top:0,left:0}}:e.isWindow(i)?{width:t.width(),height:t.height(),offset:{top:t.scrollTop(),left:t.scrollLeft()}}:i.preventDefault?{width:0,height:0,offset:{top:i.pageY,left:i.pageX}}:{width:t.outerWidth(),height:t.outerHeight(),offset:t.offset()}}e.ui=e.ui||{};var n,a,o=Math.max,r=Math.abs,h=Math.round,l=/left|center|right/,u=/top|center|bottom/,d=/[\+\-]\d+(\.[\d]+)?%?/,c=/^\w+/,p=/%$/,f=e.fn.position;e.position={scrollbarWidth:function(){if(void 0!==n)return n;var t,i,s=e("
"),a=s.children()[0];return e("body").append(s),t=a.offsetWidth,s.css("overflow","scroll"),i=a.offsetWidth,t===i&&(i=s[0].clientWidth),s.remove(),n=t-i},getScrollInfo:function(t){var i=t.isWindow||t.isDocument?"":t.element.css("overflow-x"),s=t.isWindow||t.isDocument?"":t.element.css("overflow-y"),n="scroll"===i||"auto"===i&&t.widthi?"left":t>0?"right":"center",vertical:0>a?"top":s>0?"bottom":"middle"};d>m&&m>r(t+i)&&(h.horizontal="center"),c>g&&g>r(s+a)&&(h.vertical="middle"),h.important=o(r(t),r(i))>o(r(s),r(a))?"horizontal":"vertical",n.using.call(this,e,h)}),u.offset(e.extend(M,{using:l}))})},e.ui.position={fit:{left:function(e,t){var i,s=t.within,n=s.isWindow?s.scrollLeft:s.offset.left,a=s.width,r=e.left-t.collisionPosition.marginLeft,h=n-r,l=r+t.collisionWidth-a-n;t.collisionWidth>a?h>0&&0>=l?(i=e.left+h+t.collisionWidth-a-n,e.left+=h-i):e.left=l>0&&0>=h?n:h>l?n+a-t.collisionWidth:n:h>0?e.left+=h:l>0?e.left-=l:e.left=o(e.left-r,e.left)},top:function(e,t){var i,s=t.within,n=s.isWindow?s.scrollTop:s.offset.top,a=t.within.height,r=e.top-t.collisionPosition.marginTop,h=n-r,l=r+t.collisionHeight-a-n;t.collisionHeight>a?h>0&&0>=l?(i=e.top+h+t.collisionHeight-a-n,e.top+=h-i):e.top=l>0&&0>=h?n:h>l?n+a-t.collisionHeight:n:h>0?e.top+=h:l>0?e.top-=l:e.top=o(e.top-r,e.top)}},flip:{left:function(e,t){var i,s,n=t.within,a=n.offset.left+n.scrollLeft,o=n.width,h=n.isWindow?n.scrollLeft:n.offset.left,l=e.left-t.collisionPosition.marginLeft,u=l-h,d=l+t.collisionWidth-o-h,c="left"===t.my[0]?-t.elemWidth:"right"===t.my[0]?t.elemWidth:0,p="left"===t.at[0]?t.targetWidth:"right"===t.at[0]?-t.targetWidth:0,f=-2*t.offset[0];0>u?(i=e.left+c+p+f+t.collisionWidth-o-a,(0>i||r(u)>i)&&(e.left+=c+p+f)):d>0&&(s=e.left-t.collisionPosition.marginLeft+c+p+f-h,(s>0||d>r(s))&&(e.left+=c+p+f))},top:function(e,t){var i,s,n=t.within,a=n.offset.top+n.scrollTop,o=n.height,h=n.isWindow?n.scrollTop:n.offset.top,l=e.top-t.collisionPosition.marginTop,u=l-h,d=l+t.collisionHeight-o-h,c="top"===t.my[1],p=c?-t.elemHeight:"bottom"===t.my[1]?t.elemHeight:0,f="top"===t.at[1]?t.targetHeight:"bottom"===t.at[1]?-t.targetHeight:0,m=-2*t.offset[1];0>u?(s=e.top+p+f+m+t.collisionHeight-o-a,e.top+p+f+m>u&&(0>s||r(u)>s)&&(e.top+=p+f+m)):d>0&&(i=e.top-t.collisionPosition.marginTop+p+f+m-h,e.top+p+f+m>d&&(i>0||d>r(i))&&(e.top+=p+f+m))}},flipfit:{left:function(){e.ui.position.flip.left.apply(this,arguments),e.ui.position.fit.left.apply(this,arguments)},top:function(){e.ui.position.flip.top.apply(this,arguments),e.ui.position.fit.top.apply(this,arguments)}}},function(){var t,i,s,n,o,r=document.getElementsByTagName("body")[0],h=document.createElement("div");t=document.createElement(r?"div":"body"),s={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},r&&e.extend(s,{position:"absolute",left:"-1000px",top:"-1000px"});for(o in s)t.style[o]=s[o];t.appendChild(h),i=r||document.documentElement,i.insertBefore(t,i.firstChild),h.style.cssText="position: absolute; left: 10.7432222px;",n=e(h).offset().left,a=n>10&&11>n,t.innerHTML="",i.removeChild(t)}()}(),e.ui.position,e.widget("ui.accordion",{version:"1.11.2",options:{active:0,animate:{},collapsible:!1,event:"click",header:"> li > :first-child,> :not(li):even",heightStyle:"auto",icons:{activeHeader:"ui-icon-triangle-1-s",header:"ui-icon-triangle-1-e"},activate:null,beforeActivate:null},hideProps:{borderTopWidth:"hide",borderBottomWidth:"hide",paddingTop:"hide",paddingBottom:"hide",height:"hide"},showProps:{borderTopWidth:"show",borderBottomWidth:"show",paddingTop:"show",paddingBottom:"show",height:"show"},_create:function(){var t=this.options;this.prevShow=this.prevHide=e(),this.element.addClass("ui-accordion ui-widget ui-helper-reset").attr("role","tablist"),t.collapsible||t.active!==!1&&null!=t.active||(t.active=0),this._processPanels(),0>t.active&&(t.active+=this.headers.length),this._refresh()},_getCreateEventData:function(){return{header:this.active,panel:this.active.length?this.active.next():e()}},_createIcons:function(){var t=this.options.icons;t&&(e("").addClass("ui-accordion-header-icon ui-icon "+t.header).prependTo(this.headers),this.active.children(".ui-accordion-header-icon").removeClass(t.header).addClass(t.activeHeader),this.headers.addClass("ui-accordion-icons"))},_destroyIcons:function(){this.headers.removeClass("ui-accordion-icons").children(".ui-accordion-header-icon").remove()},_destroy:function(){var e;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role"),this.headers.removeClass("ui-accordion-header ui-accordion-header-active ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-selected").removeAttr("aria-controls").removeAttr("tabIndex").removeUniqueId(),this._destroyIcons(),e=this.headers.next().removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled").css("display","").removeAttr("role").removeAttr("aria-hidden").removeAttr("aria-labelledby").removeUniqueId(),"content"!==this.options.heightStyle&&e.css("height","")},_setOption:function(e,t){return"active"===e?(this._activate(t),void 0):("event"===e&&(this.options.event&&this._off(this.headers,this.options.event),this._setupEvents(t)),this._super(e,t),"collapsible"!==e||t||this.options.active!==!1||this._activate(0),"icons"===e&&(this._destroyIcons(),t&&this._createIcons()),"disabled"===e&&(this.element.toggleClass("ui-state-disabled",!!t).attr("aria-disabled",t),this.headers.add(this.headers.next()).toggleClass("ui-state-disabled",!!t)),void 0)},_keydown:function(t){if(!t.altKey&&!t.ctrlKey){var i=e.ui.keyCode,s=this.headers.length,n=this.headers.index(t.target),a=!1;switch(t.keyCode){case i.RIGHT:case i.DOWN:a=this.headers[(n+1)%s];break;case i.LEFT:case i.UP:a=this.headers[(n-1+s)%s];break;case i.SPACE:case i.ENTER:this._eventHandler(t);break;case i.HOME:a=this.headers[0];break;case i.END:a=this.headers[s-1]}a&&(e(t.target).attr("tabIndex",-1),e(a).attr("tabIndex",0),a.focus(),t.preventDefault())}},_panelKeyDown:function(t){t.keyCode===e.ui.keyCode.UP&&t.ctrlKey&&e(t.currentTarget).prev().focus()},refresh:function(){var t=this.options;this._processPanels(),t.active===!1&&t.collapsible===!0||!this.headers.length?(t.active=!1,this.active=e()):t.active===!1?this._activate(0):this.active.length&&!e.contains(this.element[0],this.active[0])?this.headers.length===this.headers.find(".ui-state-disabled").length?(t.active=!1,this.active=e()):this._activate(Math.max(0,t.active-1)):t.active=this.headers.index(this.active),this._destroyIcons(),this._refresh()},_processPanels:function(){var e=this.headers,t=this.panels;this.headers=this.element.find(this.options.header).addClass("ui-accordion-header ui-state-default ui-corner-all"),this.panels=this.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom").filter(":not(.ui-accordion-content-active)").hide(),t&&(this._off(e.not(this.headers)),this._off(t.not(this.panels)))},_refresh:function(){var t,i=this.options,s=i.heightStyle,n=this.element.parent();this.active=this._findActive(i.active).addClass("ui-accordion-header-active ui-state-active ui-corner-top").removeClass("ui-corner-all"),this.active.next().addClass("ui-accordion-content-active").show(),this.headers.attr("role","tab").each(function(){var t=e(this),i=t.uniqueId().attr("id"),s=t.next(),n=s.uniqueId().attr("id");t.attr("aria-controls",n),s.attr("aria-labelledby",i)}).next().attr("role","tabpanel"),this.headers.not(this.active).attr({"aria-selected":"false","aria-expanded":"false",tabIndex:-1}).next().attr({"aria-hidden":"true"}).hide(),this.active.length?this.active.attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0}).next().attr({"aria-hidden":"false"}):this.headers.eq(0).attr("tabIndex",0),this._createIcons(),this._setupEvents(i.event),"fill"===s?(t=n.height(),this.element.siblings(":visible").each(function(){var i=e(this),s=i.css("position");"absolute"!==s&&"fixed"!==s&&(t-=i.outerHeight(!0))}),this.headers.each(function(){t-=e(this).outerHeight(!0)}),this.headers.next().each(function(){e(this).height(Math.max(0,t-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):"auto"===s&&(t=0,this.headers.next().each(function(){t=Math.max(t,e(this).css("height","").height())}).height(t))},_activate:function(t){var i=this._findActive(t)[0];i!==this.active[0]&&(i=i||this.active[0],this._eventHandler({target:i,currentTarget:i,preventDefault:e.noop}))},_findActive:function(t){return"number"==typeof t?this.headers.eq(t):e()},_setupEvents:function(t){var i={keydown:"_keydown"};t&&e.each(t.split(" "),function(e,t){i[t]="_eventHandler"}),this._off(this.headers.add(this.headers.next())),this._on(this.headers,i),this._on(this.headers.next(),{keydown:"_panelKeyDown"}),this._hoverable(this.headers),this._focusable(this.headers)},_eventHandler:function(t){var i=this.options,s=this.active,n=e(t.currentTarget),a=n[0]===s[0],o=a&&i.collapsible,r=o?e():n.next(),h=s.next(),l={oldHeader:s,oldPanel:h,newHeader:o?e():n,newPanel:r};t.preventDefault(),a&&!i.collapsible||this._trigger("beforeActivate",t,l)===!1||(i.active=o?!1:this.headers.index(n),this.active=a?e():n,this._toggle(l),s.removeClass("ui-accordion-header-active ui-state-active"),i.icons&&s.children(".ui-accordion-header-icon").removeClass(i.icons.activeHeader).addClass(i.icons.header),a||(n.removeClass("ui-corner-all").addClass("ui-accordion-header-active ui-state-active ui-corner-top"),i.icons&&n.children(".ui-accordion-header-icon").removeClass(i.icons.header).addClass(i.icons.activeHeader),n.next().addClass("ui-accordion-content-active")))},_toggle:function(t){var i=t.newPanel,s=this.prevShow.length?this.prevShow:t.oldPanel;this.prevShow.add(this.prevHide).stop(!0,!0),this.prevShow=i,this.prevHide=s,this.options.animate?this._animate(i,s,t):(s.hide(),i.show(),this._toggleComplete(t)),s.attr({"aria-hidden":"true"}),s.prev().attr("aria-selected","false"),i.length&&s.length?s.prev().attr({tabIndex:-1,"aria-expanded":"false"}):i.length&&this.headers.filter(function(){return 0===e(this).attr("tabIndex")}).attr("tabIndex",-1),i.attr("aria-hidden","false").prev().attr({"aria-selected":"true",tabIndex:0,"aria-expanded":"true"})},_animate:function(e,t,i){var s,n,a,o=this,r=0,h=e.length&&(!t.length||e.index()",delay:300,options:{icons:{submenu:"ui-icon-carat-1-e"},items:"> *",menus:"ul",position:{my:"left-1 top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.mouseHandled=!1,this.element.uniqueId().addClass("ui-menu ui-widget ui-widget-content").toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length).attr({role:this.options.role,tabIndex:0}),this.options.disabled&&this.element.addClass("ui-state-disabled").attr("aria-disabled","true"),this._on({"mousedown .ui-menu-item":function(e){e.preventDefault()},"click .ui-menu-item":function(t){var i=e(t.target);!this.mouseHandled&&i.not(".ui-state-disabled").length&&(this.select(t),t.isPropagationStopped()||(this.mouseHandled=!0),i.has(".ui-menu").length?this.expand(t):!this.element.is(":focus")&&e(this.document[0].activeElement).closest(".ui-menu").length&&(this.element.trigger("focus",[!0]),this.active&&1===this.active.parents(".ui-menu").length&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":function(t){if(!this.previousFilter){var i=e(t.currentTarget);i.siblings(".ui-state-active").removeClass("ui-state-active"),this.focus(t,i) -}},mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(e,t){var i=this.active||this.element.find(this.options.items).eq(0);t||this.focus(e,i)},blur:function(t){this._delay(function(){e.contains(this.element[0],this.document[0].activeElement)||this.collapseAll(t)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(e){this._closeOnDocumentClick(e)&&this.collapseAll(e),this.mouseHandled=!1}})},_destroy:function(){this.element.removeAttr("aria-activedescendant").find(".ui-menu").addBack().removeClass("ui-menu ui-widget ui-widget-content ui-menu-icons ui-front").removeAttr("role").removeAttr("tabIndex").removeAttr("aria-labelledby").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-disabled").removeUniqueId().show(),this.element.find(".ui-menu-item").removeClass("ui-menu-item").removeAttr("role").removeAttr("aria-disabled").removeUniqueId().removeClass("ui-state-hover").removeAttr("tabIndex").removeAttr("role").removeAttr("aria-haspopup").children().each(function(){var t=e(this);t.data("ui-menu-submenu-carat")&&t.remove()}),this.element.find(".ui-menu-divider").removeClass("ui-menu-divider ui-widget-content")},_keydown:function(t){var i,s,n,a,o=!0;switch(t.keyCode){case e.ui.keyCode.PAGE_UP:this.previousPage(t);break;case e.ui.keyCode.PAGE_DOWN:this.nextPage(t);break;case e.ui.keyCode.HOME:this._move("first","first",t);break;case e.ui.keyCode.END:this._move("last","last",t);break;case e.ui.keyCode.UP:this.previous(t);break;case e.ui.keyCode.DOWN:this.next(t);break;case e.ui.keyCode.LEFT:this.collapse(t);break;case e.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(t);break;case e.ui.keyCode.ENTER:case e.ui.keyCode.SPACE:this._activate(t);break;case e.ui.keyCode.ESCAPE:this.collapse(t);break;default:o=!1,s=this.previousFilter||"",n=String.fromCharCode(t.keyCode),a=!1,clearTimeout(this.filterTimer),n===s?a=!0:n=s+n,i=this._filterMenuItems(n),i=a&&-1!==i.index(this.active.next())?this.active.nextAll(".ui-menu-item"):i,i.length||(n=String.fromCharCode(t.keyCode),i=this._filterMenuItems(n)),i.length?(this.focus(t,i),this.previousFilter=n,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter}o&&t.preventDefault()},_activate:function(e){this.active.is(".ui-state-disabled")||(this.active.is("[aria-haspopup='true']")?this.expand(e):this.select(e))},refresh:function(){var t,i,s=this,n=this.options.icons.submenu,a=this.element.find(this.options.menus);this.element.toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length),a.filter(":not(.ui-menu)").addClass("ui-menu ui-widget ui-widget-content ui-front").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var t=e(this),i=t.parent(),s=e("").addClass("ui-menu-icon ui-icon "+n).data("ui-menu-submenu-carat",!0);i.attr("aria-haspopup","true").prepend(s),t.attr("aria-labelledby",i.attr("id"))}),t=a.add(this.element),i=t.find(this.options.items),i.not(".ui-menu-item").each(function(){var t=e(this);s._isDivider(t)&&t.addClass("ui-widget-content ui-menu-divider")}),i.not(".ui-menu-item, .ui-menu-divider").addClass("ui-menu-item").uniqueId().attr({tabIndex:-1,role:this._itemRole()}),i.filter(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!e.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},_setOption:function(e,t){"icons"===e&&this.element.find(".ui-menu-icon").removeClass(this.options.icons.submenu).addClass(t.submenu),"disabled"===e&&this.element.toggleClass("ui-state-disabled",!!t).attr("aria-disabled",t),this._super(e,t)},focus:function(e,t){var i,s;this.blur(e,e&&"focus"===e.type),this._scrollIntoView(t),this.active=t.first(),s=this.active.addClass("ui-state-focus").removeClass("ui-state-active"),this.options.role&&this.element.attr("aria-activedescendant",s.attr("id")),this.active.parent().closest(".ui-menu-item").addClass("ui-state-active"),e&&"keydown"===e.type?this._close():this.timer=this._delay(function(){this._close()},this.delay),i=t.children(".ui-menu"),i.length&&e&&/^mouse/.test(e.type)&&this._startOpening(i),this.activeMenu=t.parent(),this._trigger("focus",e,{item:t})},_scrollIntoView:function(t){var i,s,n,a,o,r;this._hasScroll()&&(i=parseFloat(e.css(this.activeMenu[0],"borderTopWidth"))||0,s=parseFloat(e.css(this.activeMenu[0],"paddingTop"))||0,n=t.offset().top-this.activeMenu.offset().top-i-s,a=this.activeMenu.scrollTop(),o=this.activeMenu.height(),r=t.outerHeight(),0>n?this.activeMenu.scrollTop(a+n):n+r>o&&this.activeMenu.scrollTop(a+n-o+r))},blur:function(e,t){t||clearTimeout(this.timer),this.active&&(this.active.removeClass("ui-state-focus"),this.active=null,this._trigger("blur",e,{item:this.active}))},_startOpening:function(e){clearTimeout(this.timer),"true"===e.attr("aria-hidden")&&(this.timer=this._delay(function(){this._close(),this._open(e)},this.delay))},_open:function(t){var i=e.extend({of:this.active},this.options.position);clearTimeout(this.timer),this.element.find(".ui-menu").not(t.parents(".ui-menu")).hide().attr("aria-hidden","true"),t.show().removeAttr("aria-hidden").attr("aria-expanded","true").position(i)},collapseAll:function(t,i){clearTimeout(this.timer),this.timer=this._delay(function(){var s=i?this.element:e(t&&t.target).closest(this.element.find(".ui-menu"));s.length||(s=this.element),this._close(s),this.blur(t),this.activeMenu=s},this.delay)},_close:function(e){e||(e=this.active?this.active.parent():this.element),e.find(".ui-menu").hide().attr("aria-hidden","true").attr("aria-expanded","false").end().find(".ui-state-active").not(".ui-state-focus").removeClass("ui-state-active")},_closeOnDocumentClick:function(t){return!e(t.target).closest(".ui-menu").length},_isDivider:function(e){return!/[^\-\u2014\u2013\s]/.test(e.text())},collapse:function(e){var t=this.active&&this.active.parent().closest(".ui-menu-item",this.element);t&&t.length&&(this._close(),this.focus(e,t))},expand:function(e){var t=this.active&&this.active.children(".ui-menu ").find(this.options.items).first();t&&t.length&&(this._open(t.parent()),this._delay(function(){this.focus(e,t)}))},next:function(e){this._move("next","first",e)},previous:function(e){this._move("prev","last",e)},isFirstItem:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},isLastItem:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},_move:function(e,t,i){var s;this.active&&(s="first"===e||"last"===e?this.active["first"===e?"prevAll":"nextAll"](".ui-menu-item").eq(-1):this.active[e+"All"](".ui-menu-item").eq(0)),s&&s.length&&this.active||(s=this.activeMenu.find(this.options.items)[t]()),this.focus(i,s)},nextPage:function(t){var i,s,n;return this.active?(this.isLastItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.nextAll(".ui-menu-item").each(function(){return i=e(this),0>i.offset().top-s-n}),this.focus(t,i)):this.focus(t,this.activeMenu.find(this.options.items)[this.active?"last":"first"]())),void 0):(this.next(t),void 0)},previousPage:function(t){var i,s,n;return this.active?(this.isFirstItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.prevAll(".ui-menu-item").each(function(){return i=e(this),i.offset().top-s+n>0}),this.focus(t,i)):this.focus(t,this.activeMenu.find(this.options.items).first())),void 0):(this.next(t),void 0)},_hasScroll:function(){return this.element.outerHeight()",options:{appendTo:null,autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},requestIndex:0,pending:0,_create:function(){var t,i,s,n=this.element[0].nodeName.toLowerCase(),a="textarea"===n,o="input"===n;this.isMultiLine=a?!0:o?!1:this.element.prop("isContentEditable"),this.valueMethod=this.element[a||o?"val":"text"],this.isNewMenu=!0,this.element.addClass("ui-autocomplete-input").attr("autocomplete","off"),this._on(this.element,{keydown:function(n){if(this.element.prop("readOnly"))return t=!0,s=!0,i=!0,void 0;t=!1,s=!1,i=!1;var a=e.ui.keyCode;switch(n.keyCode){case a.PAGE_UP:t=!0,this._move("previousPage",n);break;case a.PAGE_DOWN:t=!0,this._move("nextPage",n);break;case a.UP:t=!0,this._keyEvent("previous",n);break;case a.DOWN:t=!0,this._keyEvent("next",n);break;case a.ENTER:this.menu.active&&(t=!0,n.preventDefault(),this.menu.select(n));break;case a.TAB:this.menu.active&&this.menu.select(n);break;case a.ESCAPE:this.menu.element.is(":visible")&&(this.isMultiLine||this._value(this.term),this.close(n),n.preventDefault());break;default:i=!0,this._searchTimeout(n)}},keypress:function(s){if(t)return t=!1,(!this.isMultiLine||this.menu.element.is(":visible"))&&s.preventDefault(),void 0;if(!i){var n=e.ui.keyCode;switch(s.keyCode){case n.PAGE_UP:this._move("previousPage",s);break;case n.PAGE_DOWN:this._move("nextPage",s);break;case n.UP:this._keyEvent("previous",s);break;case n.DOWN:this._keyEvent("next",s)}}},input:function(e){return s?(s=!1,e.preventDefault(),void 0):(this._searchTimeout(e),void 0)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(e){return this.cancelBlur?(delete this.cancelBlur,void 0):(clearTimeout(this.searching),this.close(e),this._change(e),void 0)}}),this._initSource(),this.menu=e("
    ").addClass("ui-autocomplete ui-front").appendTo(this._appendTo()).menu({role:null}).hide().menu("instance"),this._on(this.menu.element,{mousedown:function(t){t.preventDefault(),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur});var i=this.menu.element[0];e(t.target).closest(".ui-menu-item").length||this._delay(function(){var t=this;this.document.one("mousedown",function(s){s.target===t.element[0]||s.target===i||e.contains(i,s.target)||t.close()})})},menufocus:function(t,i){var s,n;return this.isNewMenu&&(this.isNewMenu=!1,t.originalEvent&&/^mouse/.test(t.originalEvent.type))?(this.menu.blur(),this.document.one("mousemove",function(){e(t.target).trigger(t.originalEvent)}),void 0):(n=i.item.data("ui-autocomplete-item"),!1!==this._trigger("focus",t,{item:n})&&t.originalEvent&&/^key/.test(t.originalEvent.type)&&this._value(n.value),s=i.item.attr("aria-label")||n.value,s&&e.trim(s).length&&(this.liveRegion.children().hide(),e("
    ").text(s).appendTo(this.liveRegion)),void 0)},menuselect:function(e,t){var i=t.item.data("ui-autocomplete-item"),s=this.previous;this.element[0]!==this.document[0].activeElement&&(this.element.focus(),this.previous=s,this._delay(function(){this.previous=s,this.selectedItem=i})),!1!==this._trigger("select",e,{item:i})&&this._value(i.value),this.term=this._value(),this.close(e),this.selectedItem=i}}),this.liveRegion=e("",{role:"status","aria-live":"assertive","aria-relevant":"additions"}).addClass("ui-helper-hidden-accessible").appendTo(this.document[0].body),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_destroy:function(){clearTimeout(this.searching),this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete"),this.menu.element.remove(),this.liveRegion.remove()},_setOption:function(e,t){this._super(e,t),"source"===e&&this._initSource(),"appendTo"===e&&this.menu.element.appendTo(this._appendTo()),"disabled"===e&&t&&this.xhr&&this.xhr.abort()},_appendTo:function(){var t=this.options.appendTo;return t&&(t=t.jquery||t.nodeType?e(t):this.document.find(t).eq(0)),t&&t[0]||(t=this.element.closest(".ui-front")),t.length||(t=this.document[0].body),t},_initSource:function(){var t,i,s=this;e.isArray(this.options.source)?(t=this.options.source,this.source=function(i,s){s(e.ui.autocomplete.filter(t,i.term))}):"string"==typeof this.options.source?(i=this.options.source,this.source=function(t,n){s.xhr&&s.xhr.abort(),s.xhr=e.ajax({url:i,data:t,dataType:"json",success:function(e){n(e)},error:function(){n([])}})}):this.source=this.options.source},_searchTimeout:function(e){clearTimeout(this.searching),this.searching=this._delay(function(){var t=this.term===this._value(),i=this.menu.element.is(":visible"),s=e.altKey||e.ctrlKey||e.metaKey||e.shiftKey;(!t||t&&!i&&!s)&&(this.selectedItem=null,this.search(null,e))},this.options.delay)},search:function(e,t){return e=null!=e?e:this._value(),this.term=this._value(),e.length").text(i.label).appendTo(t)},_move:function(e,t){return this.menu.element.is(":visible")?this.menu.isFirstItem()&&/^previous/.test(e)||this.menu.isLastItem()&&/^next/.test(e)?(this.isMultiLine||this._value(this.term),this.menu.blur(),void 0):(this.menu[e](t),void 0):(this.search(null,t),void 0)},widget:function(){return this.menu.element},_value:function(){return this.valueMethod.apply(this.element,arguments)},_keyEvent:function(e,t){(!this.isMultiLine||this.menu.element.is(":visible"))&&(this._move(e,t),t.preventDefault())}}),e.extend(e.ui.autocomplete,{escapeRegex:function(e){return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")},filter:function(t,i){var s=RegExp(e.ui.autocomplete.escapeRegex(i),"i");return e.grep(t,function(e){return s.test(e.label||e.value||e)})}}),e.widget("ui.autocomplete",e.ui.autocomplete,{options:{messages:{noResults:"No search results.",results:function(e){return e+(e>1?" results are":" result is")+" available, use up and down arrow keys to navigate."}}},__response:function(t){var i;this._superApply(arguments),this.options.disabled||this.cancelSearch||(i=t&&t.length?this.options.messages.results(t.length):this.options.messages.noResults,this.liveRegion.children().hide(),e("
    ").text(i).appendTo(this.liveRegion))}}),e.ui.autocomplete;var c,p="ui-button ui-widget ui-state-default ui-corner-all",f="ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",m=function(){var t=e(this);setTimeout(function(){t.find(":ui-button").button("refresh")},1)},g=function(t){var i=t.name,s=t.form,n=e([]);return i&&(i=i.replace(/'/g,"\\'"),n=s?e(s).find("[name='"+i+"'][type=radio]"):e("[name='"+i+"'][type=radio]",t.ownerDocument).filter(function(){return!this.form})),n};e.widget("ui.button",{version:"1.11.2",defaultElement:"").addClass(this._triggerClass).html(a?e("").attr({src:a,alt:n,title:n}):n)),t[r?"before":"after"](i.trigger),i.trigger.click(function(){return e.datepicker._datepickerShowing&&e.datepicker._lastInput===t[0]?e.datepicker._hideDatepicker():e.datepicker._datepickerShowing&&e.datepicker._lastInput!==t[0]?(e.datepicker._hideDatepicker(),e.datepicker._showDatepicker(t[0])):e.datepicker._showDatepicker(t[0]),!1}))},_autoSize:function(e){if(this._get(e,"autoSize")&&!e.inline){var t,i,s,n,a=new Date(2009,11,20),o=this._get(e,"dateFormat");o.match(/[DM]/)&&(t=function(e){for(i=0,s=0,n=0;e.length>n;n++)e[n].length>i&&(i=e[n].length,s=n);return s},a.setMonth(t(this._get(e,o.match(/MM/)?"monthNames":"monthNamesShort"))),a.setDate(t(this._get(e,o.match(/DD/)?"dayNames":"dayNamesShort"))+20-a.getDay())),e.input.attr("size",this._formatDate(e,a).length)}},_inlineDatepicker:function(t,i){var s=e(t);s.hasClass(this.markerClassName)||(s.addClass(this.markerClassName).append(i.dpDiv),e.data(t,"datepicker",i),this._setDate(i,this._getDefaultDate(i),!0),this._updateDatepicker(i),this._updateAlternate(i),i.settings.disabled&&this._disableDatepicker(t),i.dpDiv.css("display","block"))},_dialogDatepicker:function(t,i,s,n,a){var o,h,l,u,d,c=this._dialogInst;return c||(this.uuid+=1,o="dp"+this.uuid,this._dialogInput=e(""),this._dialogInput.keydown(this._doKeyDown),e("body").append(this._dialogInput),c=this._dialogInst=this._newInst(this._dialogInput,!1),c.settings={},e.data(this._dialogInput[0],"datepicker",c)),r(c.settings,n||{}),i=i&&i.constructor===Date?this._formatDate(c,i):i,this._dialogInput.val(i),this._pos=a?a.length?a:[a.pageX,a.pageY]:null,this._pos||(h=document.documentElement.clientWidth,l=document.documentElement.clientHeight,u=document.documentElement.scrollLeft||document.body.scrollLeft,d=document.documentElement.scrollTop||document.body.scrollTop,this._pos=[h/2-100+u,l/2-150+d]),this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px"),c.settings.onSelect=s,this._inDialog=!0,this.dpDiv.addClass(this._dialogClass),this._showDatepicker(this._dialogInput[0]),e.blockUI&&e.blockUI(this.dpDiv),e.data(this._dialogInput[0],"datepicker",c),this},_destroyDatepicker:function(t){var i,s=e(t),n=e.data(t,"datepicker");s.hasClass(this.markerClassName)&&(i=t.nodeName.toLowerCase(),e.removeData(t,"datepicker"),"input"===i?(n.append.remove(),n.trigger.remove(),s.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)):("div"===i||"span"===i)&&s.removeClass(this.markerClassName).empty())},_enableDatepicker:function(t){var i,s,n=e(t),a=e.data(t,"datepicker");n.hasClass(this.markerClassName)&&(i=t.nodeName.toLowerCase(),"input"===i?(t.disabled=!1,a.trigger.filter("button").each(function(){this.disabled=!1}).end().filter("img").css({opacity:"1.0",cursor:""})):("div"===i||"span"===i)&&(s=n.children("."+this._inlineClass),s.children().removeClass("ui-state-disabled"),s.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!1)),this._disabledInputs=e.map(this._disabledInputs,function(e){return e===t?null:e}))},_disableDatepicker:function(t){var i,s,n=e(t),a=e.data(t,"datepicker");n.hasClass(this.markerClassName)&&(i=t.nodeName.toLowerCase(),"input"===i?(t.disabled=!0,a.trigger.filter("button").each(function(){this.disabled=!0}).end().filter("img").css({opacity:"0.5",cursor:"default"})):("div"===i||"span"===i)&&(s=n.children("."+this._inlineClass),s.children().addClass("ui-state-disabled"),s.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!0)),this._disabledInputs=e.map(this._disabledInputs,function(e){return e===t?null:e}),this._disabledInputs[this._disabledInputs.length]=t)},_isDisabledDatepicker:function(e){if(!e)return!1;for(var t=0;this._disabledInputs.length>t;t++)if(this._disabledInputs[t]===e)return!0;return!1},_getInst:function(t){try{return e.data(t,"datepicker")}catch(i){throw"Missing instance data for this datepicker"}},_optionDatepicker:function(t,i,s){var n,a,o,h,l=this._getInst(t);return 2===arguments.length&&"string"==typeof i?"defaults"===i?e.extend({},e.datepicker._defaults):l?"all"===i?e.extend({},l.settings):this._get(l,i):null:(n=i||{},"string"==typeof i&&(n={},n[i]=s),l&&(this._curInst===l&&this._hideDatepicker(),a=this._getDateDatepicker(t,!0),o=this._getMinMaxDate(l,"min"),h=this._getMinMaxDate(l,"max"),r(l.settings,n),null!==o&&void 0!==n.dateFormat&&void 0===n.minDate&&(l.settings.minDate=this._formatDate(l,o)),null!==h&&void 0!==n.dateFormat&&void 0===n.maxDate&&(l.settings.maxDate=this._formatDate(l,h)),"disabled"in n&&(n.disabled?this._disableDatepicker(t):this._enableDatepicker(t)),this._attachments(e(t),l),this._autoSize(l),this._setDate(l,a),this._updateAlternate(l),this._updateDatepicker(l)),void 0)},_changeDatepicker:function(e,t,i){this._optionDatepicker(e,t,i)},_refreshDatepicker:function(e){var t=this._getInst(e);t&&this._updateDatepicker(t)},_setDateDatepicker:function(e,t){var i=this._getInst(e);i&&(this._setDate(i,t),this._updateDatepicker(i),this._updateAlternate(i))},_getDateDatepicker:function(e,t){var i=this._getInst(e);return i&&!i.inline&&this._setDateFromField(i,t),i?this._getDate(i):null},_doKeyDown:function(t){var i,s,n,a=e.datepicker._getInst(t.target),o=!0,r=a.dpDiv.is(".ui-datepicker-rtl");if(a._keyEvent=!0,e.datepicker._datepickerShowing)switch(t.keyCode){case 9:e.datepicker._hideDatepicker(),o=!1;break;case 13:return n=e("td."+e.datepicker._dayOverClass+":not(."+e.datepicker._currentClass+")",a.dpDiv),n[0]&&e.datepicker._selectDay(t.target,a.selectedMonth,a.selectedYear,n[0]),i=e.datepicker._get(a,"onSelect"),i?(s=e.datepicker._formatDate(a),i.apply(a.input?a.input[0]:null,[s,a])):e.datepicker._hideDatepicker(),!1;case 27:e.datepicker._hideDatepicker();break;case 33:e.datepicker._adjustDate(t.target,t.ctrlKey?-e.datepicker._get(a,"stepBigMonths"):-e.datepicker._get(a,"stepMonths"),"M");break;case 34:e.datepicker._adjustDate(t.target,t.ctrlKey?+e.datepicker._get(a,"stepBigMonths"):+e.datepicker._get(a,"stepMonths"),"M");break;case 35:(t.ctrlKey||t.metaKey)&&e.datepicker._clearDate(t.target),o=t.ctrlKey||t.metaKey;break;case 36:(t.ctrlKey||t.metaKey)&&e.datepicker._gotoToday(t.target),o=t.ctrlKey||t.metaKey;break;case 37:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,r?1:-1,"D"),o=t.ctrlKey||t.metaKey,t.originalEvent.altKey&&e.datepicker._adjustDate(t.target,t.ctrlKey?-e.datepicker._get(a,"stepBigMonths"):-e.datepicker._get(a,"stepMonths"),"M");break;case 38:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,-7,"D"),o=t.ctrlKey||t.metaKey;break;case 39:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,r?-1:1,"D"),o=t.ctrlKey||t.metaKey,t.originalEvent.altKey&&e.datepicker._adjustDate(t.target,t.ctrlKey?+e.datepicker._get(a,"stepBigMonths"):+e.datepicker._get(a,"stepMonths"),"M");break;case 40:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,7,"D"),o=t.ctrlKey||t.metaKey;break;default:o=!1}else 36===t.keyCode&&t.ctrlKey?e.datepicker._showDatepicker(this):o=!1;o&&(t.preventDefault(),t.stopPropagation())},_doKeyPress:function(t){var i,s,n=e.datepicker._getInst(t.target);return e.datepicker._get(n,"constrainInput")?(i=e.datepicker._possibleChars(e.datepicker._get(n,"dateFormat")),s=String.fromCharCode(null==t.charCode?t.keyCode:t.charCode),t.ctrlKey||t.metaKey||" ">s||!i||i.indexOf(s)>-1):void 0 -},_doKeyUp:function(t){var i,s=e.datepicker._getInst(t.target);if(s.input.val()!==s.lastVal)try{i=e.datepicker.parseDate(e.datepicker._get(s,"dateFormat"),s.input?s.input.val():null,e.datepicker._getFormatConfig(s)),i&&(e.datepicker._setDateFromField(s),e.datepicker._updateAlternate(s),e.datepicker._updateDatepicker(s))}catch(n){}return!0},_showDatepicker:function(t){if(t=t.target||t,"input"!==t.nodeName.toLowerCase()&&(t=e("input",t.parentNode)[0]),!e.datepicker._isDisabledDatepicker(t)&&e.datepicker._lastInput!==t){var i,n,a,o,h,l,u;i=e.datepicker._getInst(t),e.datepicker._curInst&&e.datepicker._curInst!==i&&(e.datepicker._curInst.dpDiv.stop(!0,!0),i&&e.datepicker._datepickerShowing&&e.datepicker._hideDatepicker(e.datepicker._curInst.input[0])),n=e.datepicker._get(i,"beforeShow"),a=n?n.apply(t,[t,i]):{},a!==!1&&(r(i.settings,a),i.lastVal=null,e.datepicker._lastInput=t,e.datepicker._setDateFromField(i),e.datepicker._inDialog&&(t.value=""),e.datepicker._pos||(e.datepicker._pos=e.datepicker._findPos(t),e.datepicker._pos[1]+=t.offsetHeight),o=!1,e(t).parents().each(function(){return o|="fixed"===e(this).css("position"),!o}),h={left:e.datepicker._pos[0],top:e.datepicker._pos[1]},e.datepicker._pos=null,i.dpDiv.empty(),i.dpDiv.css({position:"absolute",display:"block",top:"-1000px"}),e.datepicker._updateDatepicker(i),h=e.datepicker._checkOffset(i,h,o),i.dpDiv.css({position:e.datepicker._inDialog&&e.blockUI?"static":o?"fixed":"absolute",display:"none",left:h.left+"px",top:h.top+"px"}),i.inline||(l=e.datepicker._get(i,"showAnim"),u=e.datepicker._get(i,"duration"),i.dpDiv.css("z-index",s(e(t))+1),e.datepicker._datepickerShowing=!0,e.effects&&e.effects.effect[l]?i.dpDiv.show(l,e.datepicker._get(i,"showOptions"),u):i.dpDiv[l||"show"](l?u:null),e.datepicker._shouldFocusInput(i)&&i.input.focus(),e.datepicker._curInst=i))}},_updateDatepicker:function(t){this.maxRows=4,v=t,t.dpDiv.empty().append(this._generateHTML(t)),this._attachHandlers(t);var i,s=this._getNumberOfMonths(t),n=s[1],a=17,r=t.dpDiv.find("."+this._dayOverClass+" a");r.length>0&&o.apply(r.get(0)),t.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""),n>1&&t.dpDiv.addClass("ui-datepicker-multi-"+n).css("width",a*n+"em"),t.dpDiv[(1!==s[0]||1!==s[1]?"add":"remove")+"Class"]("ui-datepicker-multi"),t.dpDiv[(this._get(t,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl"),t===e.datepicker._curInst&&e.datepicker._datepickerShowing&&e.datepicker._shouldFocusInput(t)&&t.input.focus(),t.yearshtml&&(i=t.yearshtml,setTimeout(function(){i===t.yearshtml&&t.yearshtml&&t.dpDiv.find("select.ui-datepicker-year:first").replaceWith(t.yearshtml),i=t.yearshtml=null},0))},_shouldFocusInput:function(e){return e.input&&e.input.is(":visible")&&!e.input.is(":disabled")&&!e.input.is(":focus")},_checkOffset:function(t,i,s){var n=t.dpDiv.outerWidth(),a=t.dpDiv.outerHeight(),o=t.input?t.input.outerWidth():0,r=t.input?t.input.outerHeight():0,h=document.documentElement.clientWidth+(s?0:e(document).scrollLeft()),l=document.documentElement.clientHeight+(s?0:e(document).scrollTop());return i.left-=this._get(t,"isRTL")?n-o:0,i.left-=s&&i.left===t.input.offset().left?e(document).scrollLeft():0,i.top-=s&&i.top===t.input.offset().top+r?e(document).scrollTop():0,i.left-=Math.min(i.left,i.left+n>h&&h>n?Math.abs(i.left+n-h):0),i.top-=Math.min(i.top,i.top+a>l&&l>a?Math.abs(a+r):0),i},_findPos:function(t){for(var i,s=this._getInst(t),n=this._get(s,"isRTL");t&&("hidden"===t.type||1!==t.nodeType||e.expr.filters.hidden(t));)t=t[n?"previousSibling":"nextSibling"];return i=e(t).offset(),[i.left,i.top]},_hideDatepicker:function(t){var i,s,n,a,o=this._curInst;!o||t&&o!==e.data(t,"datepicker")||this._datepickerShowing&&(i=this._get(o,"showAnim"),s=this._get(o,"duration"),n=function(){e.datepicker._tidyDialog(o)},e.effects&&(e.effects.effect[i]||e.effects[i])?o.dpDiv.hide(i,e.datepicker._get(o,"showOptions"),s,n):o.dpDiv["slideDown"===i?"slideUp":"fadeIn"===i?"fadeOut":"hide"](i?s:null,n),i||n(),this._datepickerShowing=!1,a=this._get(o,"onClose"),a&&a.apply(o.input?o.input[0]:null,[o.input?o.input.val():"",o]),this._lastInput=null,this._inDialog&&(this._dialogInput.css({position:"absolute",left:"0",top:"-100px"}),e.blockUI&&(e.unblockUI(),e("body").append(this.dpDiv))),this._inDialog=!1)},_tidyDialog:function(e){e.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(t){if(e.datepicker._curInst){var i=e(t.target),s=e.datepicker._getInst(i[0]);(i[0].id!==e.datepicker._mainDivId&&0===i.parents("#"+e.datepicker._mainDivId).length&&!i.hasClass(e.datepicker.markerClassName)&&!i.closest("."+e.datepicker._triggerClass).length&&e.datepicker._datepickerShowing&&(!e.datepicker._inDialog||!e.blockUI)||i.hasClass(e.datepicker.markerClassName)&&e.datepicker._curInst!==s)&&e.datepicker._hideDatepicker()}},_adjustDate:function(t,i,s){var n=e(t),a=this._getInst(n[0]);this._isDisabledDatepicker(n[0])||(this._adjustInstDate(a,i+("M"===s?this._get(a,"showCurrentAtPos"):0),s),this._updateDatepicker(a))},_gotoToday:function(t){var i,s=e(t),n=this._getInst(s[0]);this._get(n,"gotoCurrent")&&n.currentDay?(n.selectedDay=n.currentDay,n.drawMonth=n.selectedMonth=n.currentMonth,n.drawYear=n.selectedYear=n.currentYear):(i=new Date,n.selectedDay=i.getDate(),n.drawMonth=n.selectedMonth=i.getMonth(),n.drawYear=n.selectedYear=i.getFullYear()),this._notifyChange(n),this._adjustDate(s)},_selectMonthYear:function(t,i,s){var n=e(t),a=this._getInst(n[0]);a["selected"+("M"===s?"Month":"Year")]=a["draw"+("M"===s?"Month":"Year")]=parseInt(i.options[i.selectedIndex].value,10),this._notifyChange(a),this._adjustDate(n)},_selectDay:function(t,i,s,n){var a,o=e(t);e(n).hasClass(this._unselectableClass)||this._isDisabledDatepicker(o[0])||(a=this._getInst(o[0]),a.selectedDay=a.currentDay=e("a",n).html(),a.selectedMonth=a.currentMonth=i,a.selectedYear=a.currentYear=s,this._selectDate(t,this._formatDate(a,a.currentDay,a.currentMonth,a.currentYear)))},_clearDate:function(t){var i=e(t);this._selectDate(i,"")},_selectDate:function(t,i){var s,n=e(t),a=this._getInst(n[0]);i=null!=i?i:this._formatDate(a),a.input&&a.input.val(i),this._updateAlternate(a),s=this._get(a,"onSelect"),s?s.apply(a.input?a.input[0]:null,[i,a]):a.input&&a.input.trigger("change"),a.inline?this._updateDatepicker(a):(this._hideDatepicker(),this._lastInput=a.input[0],"object"!=typeof a.input[0]&&a.input.focus(),this._lastInput=null)},_updateAlternate:function(t){var i,s,n,a=this._get(t,"altField");a&&(i=this._get(t,"altFormat")||this._get(t,"dateFormat"),s=this._getDate(t),n=this.formatDate(i,s,this._getFormatConfig(t)),e(a).each(function(){e(this).val(n)}))},noWeekends:function(e){var t=e.getDay();return[t>0&&6>t,""]},iso8601Week:function(e){var t,i=new Date(e.getTime());return i.setDate(i.getDate()+4-(i.getDay()||7)),t=i.getTime(),i.setMonth(0),i.setDate(1),Math.floor(Math.round((t-i)/864e5)/7)+1},parseDate:function(t,i,s){if(null==t||null==i)throw"Invalid arguments";if(i="object"==typeof i?""+i:i+"",""===i)return null;var n,a,o,r,h=0,l=(s?s.shortYearCutoff:null)||this._defaults.shortYearCutoff,u="string"!=typeof l?l:(new Date).getFullYear()%100+parseInt(l,10),d=(s?s.dayNamesShort:null)||this._defaults.dayNamesShort,c=(s?s.dayNames:null)||this._defaults.dayNames,p=(s?s.monthNamesShort:null)||this._defaults.monthNamesShort,f=(s?s.monthNames:null)||this._defaults.monthNames,m=-1,g=-1,v=-1,y=-1,b=!1,_=function(e){var i=t.length>n+1&&t.charAt(n+1)===e;return i&&n++,i},x=function(e){var t=_(e),s="@"===e?14:"!"===e?20:"y"===e&&t?4:"o"===e?3:2,n="y"===e?s:1,a=RegExp("^\\d{"+n+","+s+"}"),o=i.substring(h).match(a);if(!o)throw"Missing number at position "+h;return h+=o[0].length,parseInt(o[0],10)},w=function(t,s,n){var a=-1,o=e.map(_(t)?n:s,function(e,t){return[[t,e]]}).sort(function(e,t){return-(e[1].length-t[1].length)});if(e.each(o,function(e,t){var s=t[1];return i.substr(h,s.length).toLowerCase()===s.toLowerCase()?(a=t[0],h+=s.length,!1):void 0}),-1!==a)return a+1;throw"Unknown name at position "+h},k=function(){if(i.charAt(h)!==t.charAt(n))throw"Unexpected literal at position "+h;h++};for(n=0;t.length>n;n++)if(b)"'"!==t.charAt(n)||_("'")?k():b=!1;else switch(t.charAt(n)){case"d":v=x("d");break;case"D":w("D",d,c);break;case"o":y=x("o");break;case"m":g=x("m");break;case"M":g=w("M",p,f);break;case"y":m=x("y");break;case"@":r=new Date(x("@")),m=r.getFullYear(),g=r.getMonth()+1,v=r.getDate();break;case"!":r=new Date((x("!")-this._ticksTo1970)/1e4),m=r.getFullYear(),g=r.getMonth()+1,v=r.getDate();break;case"'":_("'")?k():b=!0;break;default:k()}if(i.length>h&&(o=i.substr(h),!/^\s+/.test(o)))throw"Extra/unparsed characters found in date: "+o;if(-1===m?m=(new Date).getFullYear():100>m&&(m+=(new Date).getFullYear()-(new Date).getFullYear()%100+(u>=m?0:-100)),y>-1)for(g=1,v=y;;){if(a=this._getDaysInMonth(m,g-1),a>=v)break;g++,v-=a}if(r=this._daylightSavingAdjust(new Date(m,g-1,v)),r.getFullYear()!==m||r.getMonth()+1!==g||r.getDate()!==v)throw"Invalid date";return r},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:1e7*60*60*24*(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925)),formatDate:function(e,t,i){if(!t)return"";var s,n=(i?i.dayNamesShort:null)||this._defaults.dayNamesShort,a=(i?i.dayNames:null)||this._defaults.dayNames,o=(i?i.monthNamesShort:null)||this._defaults.monthNamesShort,r=(i?i.monthNames:null)||this._defaults.monthNames,h=function(t){var i=e.length>s+1&&e.charAt(s+1)===t;return i&&s++,i},l=function(e,t,i){var s=""+t;if(h(e))for(;i>s.length;)s="0"+s;return s},u=function(e,t,i,s){return h(e)?s[t]:i[t]},d="",c=!1;if(t)for(s=0;e.length>s;s++)if(c)"'"!==e.charAt(s)||h("'")?d+=e.charAt(s):c=!1;else switch(e.charAt(s)){case"d":d+=l("d",t.getDate(),2);break;case"D":d+=u("D",t.getDay(),n,a);break;case"o":d+=l("o",Math.round((new Date(t.getFullYear(),t.getMonth(),t.getDate()).getTime()-new Date(t.getFullYear(),0,0).getTime())/864e5),3);break;case"m":d+=l("m",t.getMonth()+1,2);break;case"M":d+=u("M",t.getMonth(),o,r);break;case"y":d+=h("y")?t.getFullYear():(10>t.getYear()%100?"0":"")+t.getYear()%100;break;case"@":d+=t.getTime();break;case"!":d+=1e4*t.getTime()+this._ticksTo1970;break;case"'":h("'")?d+="'":c=!0;break;default:d+=e.charAt(s)}return d},_possibleChars:function(e){var t,i="",s=!1,n=function(i){var s=e.length>t+1&&e.charAt(t+1)===i;return s&&t++,s};for(t=0;e.length>t;t++)if(s)"'"!==e.charAt(t)||n("'")?i+=e.charAt(t):s=!1;else switch(e.charAt(t)){case"d":case"m":case"y":case"@":i+="0123456789";break;case"D":case"M":return null;case"'":n("'")?i+="'":s=!0;break;default:i+=e.charAt(t)}return i},_get:function(e,t){return void 0!==e.settings[t]?e.settings[t]:this._defaults[t]},_setDateFromField:function(e,t){if(e.input.val()!==e.lastVal){var i=this._get(e,"dateFormat"),s=e.lastVal=e.input?e.input.val():null,n=this._getDefaultDate(e),a=n,o=this._getFormatConfig(e);try{a=this.parseDate(i,s,o)||n}catch(r){s=t?"":s}e.selectedDay=a.getDate(),e.drawMonth=e.selectedMonth=a.getMonth(),e.drawYear=e.selectedYear=a.getFullYear(),e.currentDay=s?a.getDate():0,e.currentMonth=s?a.getMonth():0,e.currentYear=s?a.getFullYear():0,this._adjustInstDate(e)}},_getDefaultDate:function(e){return this._restrictMinMax(e,this._determineDate(e,this._get(e,"defaultDate"),new Date))},_determineDate:function(t,i,s){var n=function(e){var t=new Date;return t.setDate(t.getDate()+e),t},a=function(i){try{return e.datepicker.parseDate(e.datepicker._get(t,"dateFormat"),i,e.datepicker._getFormatConfig(t))}catch(s){}for(var n=(i.toLowerCase().match(/^c/)?e.datepicker._getDate(t):null)||new Date,a=n.getFullYear(),o=n.getMonth(),r=n.getDate(),h=/([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,l=h.exec(i);l;){switch(l[2]||"d"){case"d":case"D":r+=parseInt(l[1],10);break;case"w":case"W":r+=7*parseInt(l[1],10);break;case"m":case"M":o+=parseInt(l[1],10),r=Math.min(r,e.datepicker._getDaysInMonth(a,o));break;case"y":case"Y":a+=parseInt(l[1],10),r=Math.min(r,e.datepicker._getDaysInMonth(a,o))}l=h.exec(i)}return new Date(a,o,r)},o=null==i||""===i?s:"string"==typeof i?a(i):"number"==typeof i?isNaN(i)?s:n(i):new Date(i.getTime());return o=o&&"Invalid Date"==""+o?s:o,o&&(o.setHours(0),o.setMinutes(0),o.setSeconds(0),o.setMilliseconds(0)),this._daylightSavingAdjust(o)},_daylightSavingAdjust:function(e){return e?(e.setHours(e.getHours()>12?e.getHours()+2:0),e):null},_setDate:function(e,t,i){var s=!t,n=e.selectedMonth,a=e.selectedYear,o=this._restrictMinMax(e,this._determineDate(e,t,new Date));e.selectedDay=e.currentDay=o.getDate(),e.drawMonth=e.selectedMonth=e.currentMonth=o.getMonth(),e.drawYear=e.selectedYear=e.currentYear=o.getFullYear(),n===e.selectedMonth&&a===e.selectedYear||i||this._notifyChange(e),this._adjustInstDate(e),e.input&&e.input.val(s?"":this._formatDate(e))},_getDate:function(e){var t=!e.currentYear||e.input&&""===e.input.val()?null:this._daylightSavingAdjust(new Date(e.currentYear,e.currentMonth,e.currentDay));return t},_attachHandlers:function(t){var i=this._get(t,"stepMonths"),s="#"+t.id.replace(/\\\\/g,"\\");t.dpDiv.find("[data-handler]").map(function(){var t={prev:function(){e.datepicker._adjustDate(s,-i,"M")},next:function(){e.datepicker._adjustDate(s,+i,"M")},hide:function(){e.datepicker._hideDatepicker()},today:function(){e.datepicker._gotoToday(s)},selectDay:function(){return e.datepicker._selectDay(s,+this.getAttribute("data-month"),+this.getAttribute("data-year"),this),!1},selectMonth:function(){return e.datepicker._selectMonthYear(s,this,"M"),!1},selectYear:function(){return e.datepicker._selectMonthYear(s,this,"Y"),!1}};e(this).bind(this.getAttribute("data-event"),t[this.getAttribute("data-handler")])})},_generateHTML:function(e){var t,i,s,n,a,o,r,h,l,u,d,c,p,f,m,g,v,y,b,_,x,w,k,T,D,S,M,C,N,A,P,I,z,H,F,E,O,j,W,L=new Date,R=this._daylightSavingAdjust(new Date(L.getFullYear(),L.getMonth(),L.getDate())),Y=this._get(e,"isRTL"),B=this._get(e,"showButtonPanel"),J=this._get(e,"hideIfNoPrevNext"),q=this._get(e,"navigationAsDateFormat"),K=this._getNumberOfMonths(e),V=this._get(e,"showCurrentAtPos"),U=this._get(e,"stepMonths"),Q=1!==K[0]||1!==K[1],G=this._daylightSavingAdjust(e.currentDay?new Date(e.currentYear,e.currentMonth,e.currentDay):new Date(9999,9,9)),X=this._getMinMaxDate(e,"min"),$=this._getMinMaxDate(e,"max"),Z=e.drawMonth-V,et=e.drawYear;if(0>Z&&(Z+=12,et--),$)for(t=this._daylightSavingAdjust(new Date($.getFullYear(),$.getMonth()-K[0]*K[1]+1,$.getDate())),t=X&&X>t?X:t;this._daylightSavingAdjust(new Date(et,Z,1))>t;)Z--,0>Z&&(Z=11,et--);for(e.drawMonth=Z,e.drawYear=et,i=this._get(e,"prevText"),i=q?this.formatDate(i,this._daylightSavingAdjust(new Date(et,Z-U,1)),this._getFormatConfig(e)):i,s=this._canAdjustMonth(e,-1,et,Z)?""+i+"":J?"":""+i+"",n=this._get(e,"nextText"),n=q?this.formatDate(n,this._daylightSavingAdjust(new Date(et,Z+U,1)),this._getFormatConfig(e)):n,a=this._canAdjustMonth(e,1,et,Z)?""+n+"":J?"":""+n+"",o=this._get(e,"currentText"),r=this._get(e,"gotoCurrent")&&e.currentDay?G:R,o=q?this.formatDate(o,r,this._getFormatConfig(e)):o,h=e.inline?"":"",l=B?"
    "+(Y?h:"")+(this._isInRange(e,r)?"":"")+(Y?"":h)+"
    ":"",u=parseInt(this._get(e,"firstDay"),10),u=isNaN(u)?0:u,d=this._get(e,"showWeek"),c=this._get(e,"dayNames"),p=this._get(e,"dayNamesMin"),f=this._get(e,"monthNames"),m=this._get(e,"monthNamesShort"),g=this._get(e,"beforeShowDay"),v=this._get(e,"showOtherMonths"),y=this._get(e,"selectOtherMonths"),b=this._getDefaultDate(e),_="",w=0;K[0]>w;w++){for(k="",this.maxRows=4,T=0;K[1]>T;T++){if(D=this._daylightSavingAdjust(new Date(et,Z,e.selectedDay)),S=" ui-corner-all",M="",Q){if(M+="
    "}for(M+="
    "+(/all|left/.test(S)&&0===w?Y?a:s:"")+(/all|right/.test(S)&&0===w?Y?s:a:"")+this._generateMonthYearHeader(e,Z,et,X,$,w>0||T>0,f,m)+"
    "+"",C=d?"":"",x=0;7>x;x++)N=(x+u)%7,C+="";for(M+=C+"",A=this._getDaysInMonth(et,Z),et===e.selectedYear&&Z===e.selectedMonth&&(e.selectedDay=Math.min(e.selectedDay,A)),P=(this._getFirstDayOfMonth(et,Z)-u+7)%7,I=Math.ceil((P+A)/7),z=Q?this.maxRows>I?this.maxRows:I:I,this.maxRows=z,H=this._daylightSavingAdjust(new Date(et,Z,1-P)),F=0;z>F;F++){for(M+="",E=d?"":"",x=0;7>x;x++)O=g?g.apply(e.input?e.input[0]:null,[H]):[!0,""],j=H.getMonth()!==Z,W=j&&!y||!O[0]||X&&X>H||$&&H>$,E+="",H.setDate(H.getDate()+1),H=this._daylightSavingAdjust(H);M+=E+""}Z++,Z>11&&(Z=0,et++),M+="
    "+this._get(e,"weekHeader")+"=5?" class='ui-datepicker-week-end'":"")+">"+""+p[N]+"
    "+this._get(e,"calculateWeek")(H)+""+(j&&!v?" ":W?""+H.getDate()+"":""+H.getDate()+"")+"
    "+(Q?"
    "+(K[0]>0&&T===K[1]-1?"
    ":""):""),k+=M}_+=k}return _+=l,e._keyEvent=!1,_},_generateMonthYearHeader:function(e,t,i,s,n,a,o,r){var h,l,u,d,c,p,f,m,g=this._get(e,"changeMonth"),v=this._get(e,"changeYear"),y=this._get(e,"showMonthAfterYear"),b="
    ",_="";if(a||!g)_+=""+o[t]+"";else{for(h=s&&s.getFullYear()===i,l=n&&n.getFullYear()===i,_+=""}if(y||(b+=_+(!a&&g&&v?"":" ")),!e.yearshtml)if(e.yearshtml="",a||!v)b+=""+i+"";else{for(d=this._get(e,"yearRange").split(":"),c=(new Date).getFullYear(),p=function(e){var t=e.match(/c[+\-].*/)?i+parseInt(e.substring(1),10):e.match(/[+\-].*/)?c+parseInt(e,10):parseInt(e,10);return isNaN(t)?c:t},f=p(d[0]),m=Math.max(f,p(d[1]||"")),f=s?Math.max(f,s.getFullYear()):f,m=n?Math.min(m,n.getFullYear()):m,e.yearshtml+="",b+=e.yearshtml,e.yearshtml=null}return b+=this._get(e,"yearSuffix"),y&&(b+=(!a&&g&&v?"":" ")+_),b+="
    "},_adjustInstDate:function(e,t,i){var s=e.drawYear+("Y"===i?t:0),n=e.drawMonth+("M"===i?t:0),a=Math.min(e.selectedDay,this._getDaysInMonth(s,n))+("D"===i?t:0),o=this._restrictMinMax(e,this._daylightSavingAdjust(new Date(s,n,a)));e.selectedDay=o.getDate(),e.drawMonth=e.selectedMonth=o.getMonth(),e.drawYear=e.selectedYear=o.getFullYear(),("M"===i||"Y"===i)&&this._notifyChange(e)},_restrictMinMax:function(e,t){var i=this._getMinMaxDate(e,"min"),s=this._getMinMaxDate(e,"max"),n=i&&i>t?i:t;return s&&n>s?s:n},_notifyChange:function(e){var t=this._get(e,"onChangeMonthYear");t&&t.apply(e.input?e.input[0]:null,[e.selectedYear,e.selectedMonth+1,e])},_getNumberOfMonths:function(e){var t=this._get(e,"numberOfMonths");return null==t?[1,1]:"number"==typeof t?[1,t]:t},_getMinMaxDate:function(e,t){return this._determineDate(e,this._get(e,t+"Date"),null)},_getDaysInMonth:function(e,t){return 32-this._daylightSavingAdjust(new Date(e,t,32)).getDate()},_getFirstDayOfMonth:function(e,t){return new Date(e,t,1).getDay()},_canAdjustMonth:function(e,t,i,s){var n=this._getNumberOfMonths(e),a=this._daylightSavingAdjust(new Date(i,s+(0>t?t:n[0]*n[1]),1));return 0>t&&a.setDate(this._getDaysInMonth(a.getFullYear(),a.getMonth())),this._isInRange(e,a)},_isInRange:function(e,t){var i,s,n=this._getMinMaxDate(e,"min"),a=this._getMinMaxDate(e,"max"),o=null,r=null,h=this._get(e,"yearRange");return h&&(i=h.split(":"),s=(new Date).getFullYear(),o=parseInt(i[0],10),r=parseInt(i[1],10),i[0].match(/[+\-].*/)&&(o+=s),i[1].match(/[+\-].*/)&&(r+=s)),(!n||t.getTime()>=n.getTime())&&(!a||t.getTime()<=a.getTime())&&(!o||t.getFullYear()>=o)&&(!r||r>=t.getFullYear())},_getFormatConfig:function(e){var t=this._get(e,"shortYearCutoff");return t="string"!=typeof t?t:(new Date).getFullYear()%100+parseInt(t,10),{shortYearCutoff:t,dayNamesShort:this._get(e,"dayNamesShort"),dayNames:this._get(e,"dayNames"),monthNamesShort:this._get(e,"monthNamesShort"),monthNames:this._get(e,"monthNames")}},_formatDate:function(e,t,i,s){t||(e.currentDay=e.selectedDay,e.currentMonth=e.selectedMonth,e.currentYear=e.selectedYear);var n=t?"object"==typeof t?t:this._daylightSavingAdjust(new Date(s,i,t)):this._daylightSavingAdjust(new Date(e.currentYear,e.currentMonth,e.currentDay));return this.formatDate(this._get(e,"dateFormat"),n,this._getFormatConfig(e))}}),e.fn.datepicker=function(t){if(!this.length)return this;e.datepicker.initialized||(e(document).mousedown(e.datepicker._checkExternalClick),e.datepicker.initialized=!0),0===e("#"+e.datepicker._mainDivId).length&&e("body").append(e.datepicker.dpDiv);var i=Array.prototype.slice.call(arguments,1);return"string"!=typeof t||"isDisabled"!==t&&"getDate"!==t&&"widget"!==t?"option"===t&&2===arguments.length&&"string"==typeof arguments[1]?e.datepicker["_"+t+"Datepicker"].apply(e.datepicker,[this[0]].concat(i)):this.each(function(){"string"==typeof t?e.datepicker["_"+t+"Datepicker"].apply(e.datepicker,[this].concat(i)):e.datepicker._attachDatepicker(this,t)}):e.datepicker["_"+t+"Datepicker"].apply(e.datepicker,[this[0]].concat(i))},e.datepicker=new n,e.datepicker.initialized=!1,e.datepicker.uuid=(new Date).getTime(),e.datepicker.version="1.11.2",e.datepicker,e.widget("ui.draggable",e.ui.mouse,{version:"1.11.2",widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1,drag:null,start:null,stop:null},_create:function(){"original"===this.options.helper&&this._setPositionRelative(),this.options.addClasses&&this.element.addClass("ui-draggable"),this.options.disabled&&this.element.addClass("ui-draggable-disabled"),this._setHandleClassName(),this._mouseInit()},_setOption:function(e,t){this._super(e,t),"handle"===e&&(this._removeHandleClassName(),this._setHandleClassName())},_destroy:function(){return(this.helper||this.element).is(".ui-draggable-dragging")?(this.destroyOnClear=!0,void 0):(this.element.removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled"),this._removeHandleClassName(),this._mouseDestroy(),void 0)},_mouseCapture:function(t){var i=this.options;return this._blurActiveElement(t),this.helper||i.disabled||e(t.target).closest(".ui-resizable-handle").length>0?!1:(this.handle=this._getHandle(t),this.handle?(this._blockFrames(i.iframeFix===!0?"iframe":i.iframeFix),!0):!1)},_blockFrames:function(t){this.iframeBlocks=this.document.find(t).map(function(){var t=e(this);return e("
    ").css("position","absolute").appendTo(t.parent()).outerWidth(t.outerWidth()).outerHeight(t.outerHeight()).offset(t.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_blurActiveElement:function(t){var i=this.document[0];if(this.handleElement.is(t.target))try{i.activeElement&&"body"!==i.activeElement.nodeName.toLowerCase()&&e(i.activeElement).blur()}catch(s){}},_mouseStart:function(t){var i=this.options;return this.helper=this._createHelper(t),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),e.ui.ddmanager&&(e.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(!0),this.offsetParent=this.helper.offsetParent(),this.hasFixedAncestor=this.helper.parents().filter(function(){return"fixed"===e(this).css("position")}).length>0,this.positionAbs=this.element.offset(),this._refreshOffsets(t),this.originalPosition=this.position=this._generatePosition(t,!1),this.originalPageX=t.pageX,this.originalPageY=t.pageY,i.cursorAt&&this._adjustOffsetFromHelper(i.cursorAt),this._setContainment(),this._trigger("start",t)===!1?(this._clear(),!1):(this._cacheHelperProportions(),e.ui.ddmanager&&!i.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this._normalizeRightBottom(),this._mouseDrag(t,!0),e.ui.ddmanager&&e.ui.ddmanager.dragStart(this,t),!0)},_refreshOffsets:function(e){this.offset={top:this.positionAbs.top-this.margins.top,left:this.positionAbs.left-this.margins.left,scroll:!1,parent:this._getParentOffset(),relative:this._getRelativeOffset()},this.offset.click={left:e.pageX-this.offset.left,top:e.pageY-this.offset.top}},_mouseDrag:function(t,i){if(this.hasFixedAncestor&&(this.offset.parent=this._getParentOffset()),this.position=this._generatePosition(t,!0),this.positionAbs=this._convertPositionTo("absolute"),!i){var s=this._uiHash();if(this._trigger("drag",t,s)===!1)return this._mouseUp({}),!1;this.position=s.position}return this.helper[0].style.left=this.position.left+"px",this.helper[0].style.top=this.position.top+"px",e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),!1},_mouseStop:function(t){var i=this,s=!1;return e.ui.ddmanager&&!this.options.dropBehaviour&&(s=e.ui.ddmanager.drop(this,t)),this.dropped&&(s=this.dropped,this.dropped=!1),"invalid"===this.options.revert&&!s||"valid"===this.options.revert&&s||this.options.revert===!0||e.isFunction(this.options.revert)&&this.options.revert.call(this.element,s)?e(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){i._trigger("stop",t)!==!1&&i._clear()}):this._trigger("stop",t)!==!1&&this._clear(),!1},_mouseUp:function(t){return this._unblockFrames(),e.ui.ddmanager&&e.ui.ddmanager.dragStop(this,t),this.handleElement.is(t.target)&&this.element.focus(),e.ui.mouse.prototype._mouseUp.call(this,t)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear(),this},_getHandle:function(t){return this.options.handle?!!e(t.target).closest(this.element.find(this.options.handle)).length:!0},_setHandleClassName:function(){this.handleElement=this.options.handle?this.element.find(this.options.handle):this.element,this.handleElement.addClass("ui-draggable-handle")},_removeHandleClassName:function(){this.handleElement.removeClass("ui-draggable-handle")},_createHelper:function(t){var i=this.options,s=e.isFunction(i.helper),n=s?e(i.helper.apply(this.element[0],[t])):"clone"===i.helper?this.element.clone().removeAttr("id"):this.element;return n.parents("body").length||n.appendTo("parent"===i.appendTo?this.element[0].parentNode:i.appendTo),s&&n[0]===this.element[0]&&this._setPositionRelative(),n[0]===this.element[0]||/(fixed|absolute)/.test(n.css("position"))||n.css("position","absolute"),n},_setPositionRelative:function(){/^(?:r|a|f)/.test(this.element.css("position"))||(this.element[0].style.position="relative")},_adjustOffsetFromHelper:function(t){"string"==typeof t&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_isRootNode:function(e){return/(html|body)/i.test(e.tagName)||e===this.document[0]},_getParentOffset:function(){var t=this.offsetParent.offset(),i=this.document[0];return"absolute"===this.cssPosition&&this.scrollParent[0]!==i&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop()),this._isRootNode(this.offsetParent[0])&&(t={top:0,left:0}),{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"!==this.cssPosition)return{top:0,left:0};var e=this.element.position(),t=this._isRootNode(this.scrollParent[0]);return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+(t?0:this.scrollParent.scrollTop()),left:e.left-(parseInt(this.helper.css("left"),10)||0)+(t?0:this.scrollParent.scrollLeft())}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t,i,s,n=this.options,a=this.document[0];return this.relativeContainer=null,n.containment?"window"===n.containment?(this.containment=[e(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,e(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,e(window).scrollLeft()+e(window).width()-this.helperProportions.width-this.margins.left,e(window).scrollTop()+(e(window).height()||a.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],void 0):"document"===n.containment?(this.containment=[0,0,e(a).width()-this.helperProportions.width-this.margins.left,(e(a).height()||a.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],void 0):n.containment.constructor===Array?(this.containment=n.containment,void 0):("parent"===n.containment&&(n.containment=this.helper[0].parentNode),i=e(n.containment),s=i[0],s&&(t=/(scroll|auto)/.test(i.css("overflow")),this.containment=[(parseInt(i.css("borderLeftWidth"),10)||0)+(parseInt(i.css("paddingLeft"),10)||0),(parseInt(i.css("borderTopWidth"),10)||0)+(parseInt(i.css("paddingTop"),10)||0),(t?Math.max(s.scrollWidth,s.offsetWidth):s.offsetWidth)-(parseInt(i.css("borderRightWidth"),10)||0)-(parseInt(i.css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(t?Math.max(s.scrollHeight,s.offsetHeight):s.offsetHeight)-(parseInt(i.css("borderBottomWidth"),10)||0)-(parseInt(i.css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relativeContainer=i),void 0):(this.containment=null,void 0) -},_convertPositionTo:function(e,t){t||(t=this.position);var i="absolute"===e?1:-1,s=this._isRootNode(this.scrollParent[0]);return{top:t.top+this.offset.relative.top*i+this.offset.parent.top*i-("fixed"===this.cssPosition?-this.offset.scroll.top:s?0:this.offset.scroll.top)*i,left:t.left+this.offset.relative.left*i+this.offset.parent.left*i-("fixed"===this.cssPosition?-this.offset.scroll.left:s?0:this.offset.scroll.left)*i}},_generatePosition:function(e,t){var i,s,n,a,o=this.options,r=this._isRootNode(this.scrollParent[0]),h=e.pageX,l=e.pageY;return r&&this.offset.scroll||(this.offset.scroll={top:this.scrollParent.scrollTop(),left:this.scrollParent.scrollLeft()}),t&&(this.containment&&(this.relativeContainer?(s=this.relativeContainer.offset(),i=[this.containment[0]+s.left,this.containment[1]+s.top,this.containment[2]+s.left,this.containment[3]+s.top]):i=this.containment,e.pageX-this.offset.click.lefti[2]&&(h=i[2]+this.offset.click.left),e.pageY-this.offset.click.top>i[3]&&(l=i[3]+this.offset.click.top)),o.grid&&(n=o.grid[1]?this.originalPageY+Math.round((l-this.originalPageY)/o.grid[1])*o.grid[1]:this.originalPageY,l=i?n-this.offset.click.top>=i[1]||n-this.offset.click.top>i[3]?n:n-this.offset.click.top>=i[1]?n-o.grid[1]:n+o.grid[1]:n,a=o.grid[0]?this.originalPageX+Math.round((h-this.originalPageX)/o.grid[0])*o.grid[0]:this.originalPageX,h=i?a-this.offset.click.left>=i[0]||a-this.offset.click.left>i[2]?a:a-this.offset.click.left>=i[0]?a-o.grid[0]:a+o.grid[0]:a),"y"===o.axis&&(h=this.originalPageX),"x"===o.axis&&(l=this.originalPageY)),{top:l-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.offset.scroll.top:r?0:this.offset.scroll.top),left:h-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.offset.scroll.left:r?0:this.offset.scroll.left)}},_clear:function(){this.helper.removeClass("ui-draggable-dragging"),this.helper[0]===this.element[0]||this.cancelHelperRemoval||this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1,this.destroyOnClear&&this.destroy()},_normalizeRightBottom:function(){"y"!==this.options.axis&&"auto"!==this.helper.css("right")&&(this.helper.width(this.helper.width()),this.helper.css("right","auto")),"x"!==this.options.axis&&"auto"!==this.helper.css("bottom")&&(this.helper.height(this.helper.height()),this.helper.css("bottom","auto"))},_trigger:function(t,i,s){return s=s||this._uiHash(),e.ui.plugin.call(this,t,[i,s,this],!0),/^(drag|start|stop)/.test(t)&&(this.positionAbs=this._convertPositionTo("absolute"),s.offset=this.positionAbs),e.Widget.prototype._trigger.call(this,t,i,s)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),e.ui.plugin.add("draggable","connectToSortable",{start:function(t,i,s){var n=e.extend({},i,{item:s.element});s.sortables=[],e(s.options.connectToSortable).each(function(){var i=e(this).sortable("instance");i&&!i.options.disabled&&(s.sortables.push(i),i.refreshPositions(),i._trigger("activate",t,n))})},stop:function(t,i,s){var n=e.extend({},i,{item:s.element});s.cancelHelperRemoval=!1,e.each(s.sortables,function(){var e=this;e.isOver?(e.isOver=0,s.cancelHelperRemoval=!0,e.cancelHelperRemoval=!1,e._storedCSS={position:e.placeholder.css("position"),top:e.placeholder.css("top"),left:e.placeholder.css("left")},e._mouseStop(t),e.options.helper=e.options._helper):(e.cancelHelperRemoval=!0,e._trigger("deactivate",t,n))})},drag:function(t,i,s){e.each(s.sortables,function(){var n=!1,a=this;a.positionAbs=s.positionAbs,a.helperProportions=s.helperProportions,a.offset.click=s.offset.click,a._intersectsWith(a.containerCache)&&(n=!0,e.each(s.sortables,function(){return this.positionAbs=s.positionAbs,this.helperProportions=s.helperProportions,this.offset.click=s.offset.click,this!==a&&this._intersectsWith(this.containerCache)&&e.contains(a.element[0],this.element[0])&&(n=!1),n})),n?(a.isOver||(a.isOver=1,a.currentItem=i.helper.appendTo(a.element).data("ui-sortable-item",!0),a.options._helper=a.options.helper,a.options.helper=function(){return i.helper[0]},t.target=a.currentItem[0],a._mouseCapture(t,!0),a._mouseStart(t,!0,!0),a.offset.click.top=s.offset.click.top,a.offset.click.left=s.offset.click.left,a.offset.parent.left-=s.offset.parent.left-a.offset.parent.left,a.offset.parent.top-=s.offset.parent.top-a.offset.parent.top,s._trigger("toSortable",t),s.dropped=a.element,e.each(s.sortables,function(){this.refreshPositions()}),s.currentItem=s.element,a.fromOutside=s),a.currentItem&&(a._mouseDrag(t),i.position=a.position)):a.isOver&&(a.isOver=0,a.cancelHelperRemoval=!0,a.options._revert=a.options.revert,a.options.revert=!1,a._trigger("out",t,a._uiHash(a)),a._mouseStop(t,!0),a.options.revert=a.options._revert,a.options.helper=a.options._helper,a.placeholder&&a.placeholder.remove(),s._refreshOffsets(t),i.position=s._generatePosition(t,!0),s._trigger("fromSortable",t),s.dropped=!1,e.each(s.sortables,function(){this.refreshPositions()}))})}}),e.ui.plugin.add("draggable","cursor",{start:function(t,i,s){var n=e("body"),a=s.options;n.css("cursor")&&(a._cursor=n.css("cursor")),n.css("cursor",a.cursor)},stop:function(t,i,s){var n=s.options;n._cursor&&e("body").css("cursor",n._cursor)}}),e.ui.plugin.add("draggable","opacity",{start:function(t,i,s){var n=e(i.helper),a=s.options;n.css("opacity")&&(a._opacity=n.css("opacity")),n.css("opacity",a.opacity)},stop:function(t,i,s){var n=s.options;n._opacity&&e(i.helper).css("opacity",n._opacity)}}),e.ui.plugin.add("draggable","scroll",{start:function(e,t,i){i.scrollParentNotHidden||(i.scrollParentNotHidden=i.helper.scrollParent(!1)),i.scrollParentNotHidden[0]!==i.document[0]&&"HTML"!==i.scrollParentNotHidden[0].tagName&&(i.overflowOffset=i.scrollParentNotHidden.offset())},drag:function(t,i,s){var n=s.options,a=!1,o=s.scrollParentNotHidden[0],r=s.document[0];o!==r&&"HTML"!==o.tagName?(n.axis&&"x"===n.axis||(s.overflowOffset.top+o.offsetHeight-t.pageY=0;c--)h=s.snapElements[c].left-s.margins.left,l=h+s.snapElements[c].width,u=s.snapElements[c].top-s.margins.top,d=u+s.snapElements[c].height,h-m>v||g>l+m||u-m>b||y>d+m||!e.contains(s.snapElements[c].item.ownerDocument,s.snapElements[c].item)?(s.snapElements[c].snapping&&s.options.snap.release&&s.options.snap.release.call(s.element,t,e.extend(s._uiHash(),{snapItem:s.snapElements[c].item})),s.snapElements[c].snapping=!1):("inner"!==f.snapMode&&(n=m>=Math.abs(u-b),a=m>=Math.abs(d-y),o=m>=Math.abs(h-v),r=m>=Math.abs(l-g),n&&(i.position.top=s._convertPositionTo("relative",{top:u-s.helperProportions.height,left:0}).top),a&&(i.position.top=s._convertPositionTo("relative",{top:d,left:0}).top),o&&(i.position.left=s._convertPositionTo("relative",{top:0,left:h-s.helperProportions.width}).left),r&&(i.position.left=s._convertPositionTo("relative",{top:0,left:l}).left)),p=n||a||o||r,"outer"!==f.snapMode&&(n=m>=Math.abs(u-y),a=m>=Math.abs(d-b),o=m>=Math.abs(h-g),r=m>=Math.abs(l-v),n&&(i.position.top=s._convertPositionTo("relative",{top:u,left:0}).top),a&&(i.position.top=s._convertPositionTo("relative",{top:d-s.helperProportions.height,left:0}).top),o&&(i.position.left=s._convertPositionTo("relative",{top:0,left:h}).left),r&&(i.position.left=s._convertPositionTo("relative",{top:0,left:l-s.helperProportions.width}).left)),!s.snapElements[c].snapping&&(n||a||o||r||p)&&s.options.snap.snap&&s.options.snap.snap.call(s.element,t,e.extend(s._uiHash(),{snapItem:s.snapElements[c].item})),s.snapElements[c].snapping=n||a||o||r||p)}}),e.ui.plugin.add("draggable","stack",{start:function(t,i,s){var n,a=s.options,o=e.makeArray(e(a.stack)).sort(function(t,i){return(parseInt(e(t).css("zIndex"),10)||0)-(parseInt(e(i).css("zIndex"),10)||0)});o.length&&(n=parseInt(e(o[0]).css("zIndex"),10)||0,e(o).each(function(t){e(this).css("zIndex",n+t)}),this.css("zIndex",n+o.length))}}),e.ui.plugin.add("draggable","zIndex",{start:function(t,i,s){var n=e(i.helper),a=s.options;n.css("zIndex")&&(a._zIndex=n.css("zIndex")),n.css("zIndex",a.zIndex)},stop:function(t,i,s){var n=s.options;n._zIndex&&e(i.helper).css("zIndex",n._zIndex)}}),e.ui.draggable,e.widget("ui.resizable",e.ui.mouse,{version:"1.11.2",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_num:function(e){return parseInt(e,10)||0},_isNumber:function(e){return!isNaN(parseInt(e,10))},_hasScroll:function(t,i){if("hidden"===e(t).css("overflow"))return!1;var s=i&&"left"===i?"scrollLeft":"scrollTop",n=!1;return t[s]>0?!0:(t[s]=1,n=t[s]>0,t[s]=0,n)},_create:function(){var t,i,s,n,a,o=this,r=this.options;if(this.element.addClass("ui-resizable"),e.extend(this,{_aspectRatio:!!r.aspectRatio,aspectRatio:r.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:r.helper||r.ghost||r.animate?r.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(e("
    ").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.resizable("instance")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=r.handles||(e(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),t=this.handles.split(","),this.handles={},i=0;t.length>i;i++)s=e.trim(t[i]),a="ui-resizable-"+s,n=e("
    "),n.css({zIndex:r.zIndex}),"se"===s&&n.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[s]=".ui-resizable-"+s,this.element.append(n);this._renderAxis=function(t){var i,s,n,a;t=t||this.element;for(i in this.handles)this.handles[i].constructor===String&&(this.handles[i]=this.element.children(this.handles[i]).first().show()),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)&&(s=e(this.handles[i],this.element),a=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),t.css(n,a),this._proportionallyResize()),e(this.handles[i]).length},this._renderAxis(this.element),this._handles=e(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){o.resizing||(this.className&&(n=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),o.axis=n&&n[1]?n[1]:"se")}),r.autoHide&&(this._handles.hide(),e(this.element).addClass("ui-resizable-autohide").mouseenter(function(){r.disabled||(e(this).removeClass("ui-resizable-autohide"),o._handles.show())}).mouseleave(function(){r.disabled||o.resizing||(e(this).addClass("ui-resizable-autohide"),o._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var t,i=function(t){e(t).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),t=this.element,this.originalElement.css({position:t.css("position"),width:t.outerWidth(),height:t.outerHeight(),top:t.css("top"),left:t.css("left")}).insertAfter(t),t.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_mouseCapture:function(t){var i,s,n=!1;for(i in this.handles)s=e(this.handles[i])[0],(s===t.target||e.contains(s,t.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(t){var i,s,n,a=this.options,o=this.element;return this.resizing=!0,this._renderProxy(),i=this._num(this.helper.css("left")),s=this._num(this.helper.css("top")),a.containment&&(i+=e(a.containment).scrollLeft()||0,s+=e(a.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:i,top:s},this.size=this._helper?{width:this.helper.width(),height:this.helper.height()}:{width:o.width(),height:o.height()},this.originalSize=this._helper?{width:o.outerWidth(),height:o.outerHeight()}:{width:o.width(),height:o.height()},this.sizeDiff={width:o.outerWidth()-o.width(),height:o.outerHeight()-o.height()},this.originalPosition={left:i,top:s},this.originalMousePosition={left:t.pageX,top:t.pageY},this.aspectRatio="number"==typeof a.aspectRatio?a.aspectRatio:this.originalSize.width/this.originalSize.height||1,n=e(".ui-resizable-"+this.axis).css("cursor"),e("body").css("cursor","auto"===n?this.axis+"-resize":n),o.addClass("ui-resizable-resizing"),this._propagate("start",t),!0},_mouseDrag:function(t){var i,s,n=this.originalMousePosition,a=this.axis,o=t.pageX-n.left||0,r=t.pageY-n.top||0,h=this._change[a];return this._updatePrevProperties(),h?(i=h.apply(this,[t,o,r]),this._updateVirtualBoundaries(t.shiftKey),(this._aspectRatio||t.shiftKey)&&(i=this._updateRatio(i,t)),i=this._respectSize(i,t),this._updateCache(i),this._propagate("resize",t),s=this._applyChanges(),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),e.isEmptyObject(s)||(this._updatePrevProperties(),this._trigger("resize",t,this.ui()),this._applyChanges()),!1):!1},_mouseStop:function(t){this.resizing=!1;var i,s,n,a,o,r,h,l=this.options,u=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&this._hasScroll(i[0],"left")?0:u.sizeDiff.height,a=s?0:u.sizeDiff.width,o={width:u.helper.width()-a,height:u.helper.height()-n},r=parseInt(u.element.css("left"),10)+(u.position.left-u.originalPosition.left)||null,h=parseInt(u.element.css("top"),10)+(u.position.top-u.originalPosition.top)||null,l.animate||this.element.css(e.extend(o,{top:h,left:r})),u.helper.height(u.size.height),u.helper.width(u.size.width),this._helper&&!l.animate&&this._proportionallyResize()),e("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updatePrevProperties:function(){this.prevPosition={top:this.position.top,left:this.position.left},this.prevSize={width:this.size.width,height:this.size.height}},_applyChanges:function(){var e={};return this.position.top!==this.prevPosition.top&&(e.top=this.position.top+"px"),this.position.left!==this.prevPosition.left&&(e.left=this.position.left+"px"),this.size.width!==this.prevSize.width&&(e.width=this.size.width+"px"),this.size.height!==this.prevSize.height&&(e.height=this.size.height+"px"),this.helper.css(e),e},_updateVirtualBoundaries:function(e){var t,i,s,n,a,o=this.options;a={minWidth:this._isNumber(o.minWidth)?o.minWidth:0,maxWidth:this._isNumber(o.maxWidth)?o.maxWidth:1/0,minHeight:this._isNumber(o.minHeight)?o.minHeight:0,maxHeight:this._isNumber(o.maxHeight)?o.maxHeight:1/0},(this._aspectRatio||e)&&(t=a.minHeight*this.aspectRatio,s=a.minWidth/this.aspectRatio,i=a.maxHeight*this.aspectRatio,n=a.maxWidth/this.aspectRatio,t>a.minWidth&&(a.minWidth=t),s>a.minHeight&&(a.minHeight=s),a.maxWidth>i&&(a.maxWidth=i),a.maxHeight>n&&(a.maxHeight=n)),this._vBoundaries=a},_updateCache:function(e){this.offset=this.helper.offset(),this._isNumber(e.left)&&(this.position.left=e.left),this._isNumber(e.top)&&(this.position.top=e.top),this._isNumber(e.height)&&(this.size.height=e.height),this._isNumber(e.width)&&(this.size.width=e.width)},_updateRatio:function(e){var t=this.position,i=this.size,s=this.axis;return this._isNumber(e.height)?e.width=e.height*this.aspectRatio:this._isNumber(e.width)&&(e.height=e.width/this.aspectRatio),"sw"===s&&(e.left=t.left+(i.width-e.width),e.top=null),"nw"===s&&(e.top=t.top+(i.height-e.height),e.left=t.left+(i.width-e.width)),e},_respectSize:function(e){var t=this._vBoundaries,i=this.axis,s=this._isNumber(e.width)&&t.maxWidth&&t.maxWidthe.width,o=this._isNumber(e.height)&&t.minHeight&&t.minHeight>e.height,r=this.originalPosition.left+this.originalSize.width,h=this.position.top+this.size.height,l=/sw|nw|w/.test(i),u=/nw|ne|n/.test(i);return a&&(e.width=t.minWidth),o&&(e.height=t.minHeight),s&&(e.width=t.maxWidth),n&&(e.height=t.maxHeight),a&&l&&(e.left=r-t.minWidth),s&&l&&(e.left=r-t.maxWidth),o&&u&&(e.top=h-t.minHeight),n&&u&&(e.top=h-t.maxHeight),e.width||e.height||e.left||!e.top?e.width||e.height||e.top||!e.left||(e.left=null):e.top=null,e},_getPaddingPlusBorderDimensions:function(e){for(var t=0,i=[],s=[e.css("borderTopWidth"),e.css("borderRightWidth"),e.css("borderBottomWidth"),e.css("borderLeftWidth")],n=[e.css("paddingTop"),e.css("paddingRight"),e.css("paddingBottom"),e.css("paddingLeft")];4>t;t++)i[t]=parseInt(s[t],10)||0,i[t]+=parseInt(n[t],10)||0;return{height:i[0]+i[2],width:i[1]+i[3]}},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var e,t=0,i=this.helper||this.element;this._proportionallyResizeElements.length>t;t++)e=this._proportionallyResizeElements[t],this.outerDimensions||(this.outerDimensions=this._getPaddingPlusBorderDimensions(e)),e.css({height:i.height()-this.outerDimensions.height||0,width:i.width()-this.outerDimensions.width||0})},_renderProxy:function(){var t=this.element,i=this.options;this.elementOffset=t.offset(),this._helper?(this.helper=this.helper||e("
    "),this.helper.addClass(this._helper).css({width:this.element.outerWidth()-1,height:this.element.outerHeight()-1,position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(e,t){return{width:this.originalSize.width+t}},w:function(e,t){var i=this.originalSize,s=this.originalPosition;return{left:s.left+t,width:i.width-t}},n:function(e,t,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(e,t,i){return{height:this.originalSize.height+i}},se:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},sw:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,i,s]))},ne:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},nw:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,i,s]))}},_propagate:function(t,i){e.ui.plugin.call(this,t,[i,this.ui()]),"resize"!==t&&this._trigger(t,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),e.ui.plugin.add("resizable","animate",{stop:function(t){var i=e(this).resizable("instance"),s=i.options,n=i._proportionallyResizeElements,a=n.length&&/textarea/i.test(n[0].nodeName),o=a&&i._hasScroll(n[0],"left")?0:i.sizeDiff.height,r=a?0:i.sizeDiff.width,h={width:i.size.width-r,height:i.size.height-o},l=parseInt(i.element.css("left"),10)+(i.position.left-i.originalPosition.left)||null,u=parseInt(i.element.css("top"),10)+(i.position.top-i.originalPosition.top)||null;i.element.animate(e.extend(h,u&&l?{top:u,left:l}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseInt(i.element.css("width"),10),height:parseInt(i.element.css("height"),10),top:parseInt(i.element.css("top"),10),left:parseInt(i.element.css("left"),10)};n&&n.length&&e(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",t)}})}}),e.ui.plugin.add("resizable","containment",{start:function(){var t,i,s,n,a,o,r,h=e(this).resizable("instance"),l=h.options,u=h.element,d=l.containment,c=d instanceof e?d.get(0):/parent/.test(d)?u.parent().get(0):d;c&&(h.containerElement=e(c),/document/.test(d)||d===document?(h.containerOffset={left:0,top:0},h.containerPosition={left:0,top:0},h.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight}):(t=e(c),i=[],e(["Top","Right","Left","Bottom"]).each(function(e,s){i[e]=h._num(t.css("padding"+s))}),h.containerOffset=t.offset(),h.containerPosition=t.position(),h.containerSize={height:t.innerHeight()-i[3],width:t.innerWidth()-i[1]},s=h.containerOffset,n=h.containerSize.height,a=h.containerSize.width,o=h._hasScroll(c,"left")?c.scrollWidth:a,r=h._hasScroll(c)?c.scrollHeight:n,h.parentData={element:c,left:s.left,top:s.top,width:o,height:r}))},resize:function(t){var i,s,n,a,o=e(this).resizable("instance"),r=o.options,h=o.containerOffset,l=o.position,u=o._aspectRatio||t.shiftKey,d={top:0,left:0},c=o.containerElement,p=!0;c[0]!==document&&/static/.test(c.css("position"))&&(d=h),l.left<(o._helper?h.left:0)&&(o.size.width=o.size.width+(o._helper?o.position.left-h.left:o.position.left-d.left),u&&(o.size.height=o.size.width/o.aspectRatio,p=!1),o.position.left=r.helper?h.left:0),l.top<(o._helper?h.top:0)&&(o.size.height=o.size.height+(o._helper?o.position.top-h.top:o.position.top),u&&(o.size.width=o.size.height*o.aspectRatio,p=!1),o.position.top=o._helper?h.top:0),n=o.containerElement.get(0)===o.element.parent().get(0),a=/relative|absolute/.test(o.containerElement.css("position")),n&&a?(o.offset.left=o.parentData.left+o.position.left,o.offset.top=o.parentData.top+o.position.top):(o.offset.left=o.element.offset().left,o.offset.top=o.element.offset().top),i=Math.abs(o.sizeDiff.width+(o._helper?o.offset.left-d.left:o.offset.left-h.left)),s=Math.abs(o.sizeDiff.height+(o._helper?o.offset.top-d.top:o.offset.top-h.top)),i+o.size.width>=o.parentData.width&&(o.size.width=o.parentData.width-i,u&&(o.size.height=o.size.width/o.aspectRatio,p=!1)),s+o.size.height>=o.parentData.height&&(o.size.height=o.parentData.height-s,u&&(o.size.width=o.size.height*o.aspectRatio,p=!1)),p||(o.position.left=o.prevPosition.left,o.position.top=o.prevPosition.top,o.size.width=o.prevSize.width,o.size.height=o.prevSize.height)},stop:function(){var t=e(this).resizable("instance"),i=t.options,s=t.containerOffset,n=t.containerPosition,a=t.containerElement,o=e(t.helper),r=o.offset(),h=o.outerWidth()-t.sizeDiff.width,l=o.outerHeight()-t.sizeDiff.height;t._helper&&!i.animate&&/relative/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l}),t._helper&&!i.animate&&/static/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l})}}),e.ui.plugin.add("resizable","alsoResize",{start:function(){var t=e(this).resizable("instance"),i=t.options,s=function(t){e(t).each(function(){var t=e(this);t.data("ui-resizable-alsoresize",{width:parseInt(t.width(),10),height:parseInt(t.height(),10),left:parseInt(t.css("left"),10),top:parseInt(t.css("top"),10)})})};"object"!=typeof i.alsoResize||i.alsoResize.parentNode?s(i.alsoResize):i.alsoResize.length?(i.alsoResize=i.alsoResize[0],s(i.alsoResize)):e.each(i.alsoResize,function(e){s(e)})},resize:function(t,i){var s=e(this).resizable("instance"),n=s.options,a=s.originalSize,o=s.originalPosition,r={height:s.size.height-a.height||0,width:s.size.width-a.width||0,top:s.position.top-o.top||0,left:s.position.left-o.left||0},h=function(t,s){e(t).each(function(){var t=e(this),n=e(this).data("ui-resizable-alsoresize"),a={},o=s&&s.length?s:t.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(o,function(e,t){var i=(n[t]||0)+(r[t]||0);i&&i>=0&&(a[t]=i||null)}),t.css(a)})};"object"!=typeof n.alsoResize||n.alsoResize.nodeType?h(n.alsoResize):e.each(n.alsoResize,function(e,t){h(e,t)})},stop:function(){e(this).removeData("resizable-alsoresize")}}),e.ui.plugin.add("resizable","ghost",{start:function(){var t=e(this).resizable("instance"),i=t.options,s=t.size;t.ghost=t.originalElement.clone(),t.ghost.css({opacity:.25,display:"block",position:"relative",height:s.height,width:s.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass("string"==typeof i.ghost?i.ghost:""),t.ghost.appendTo(t.helper)},resize:function(){var t=e(this).resizable("instance");t.ghost&&t.ghost.css({position:"relative",height:t.size.height,width:t.size.width})},stop:function(){var t=e(this).resizable("instance");t.ghost&&t.helper&&t.helper.get(0).removeChild(t.ghost.get(0))}}),e.ui.plugin.add("resizable","grid",{resize:function(){var t,i=e(this).resizable("instance"),s=i.options,n=i.size,a=i.originalSize,o=i.originalPosition,r=i.axis,h="number"==typeof s.grid?[s.grid,s.grid]:s.grid,l=h[0]||1,u=h[1]||1,d=Math.round((n.width-a.width)/l)*l,c=Math.round((n.height-a.height)/u)*u,p=a.width+d,f=a.height+c,m=s.maxWidth&&p>s.maxWidth,g=s.maxHeight&&f>s.maxHeight,v=s.minWidth&&s.minWidth>p,y=s.minHeight&&s.minHeight>f;s.grid=h,v&&(p+=l),y&&(f+=u),m&&(p-=l),g&&(f-=u),/^(se|s|e)$/.test(r)?(i.size.width=p,i.size.height=f):/^(ne)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.top=o.top-c):/^(sw)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.left=o.left-d):((0>=f-u||0>=p-l)&&(t=i._getPaddingPlusBorderDimensions(this)),f-u>0?(i.size.height=f,i.position.top=o.top-c):(f=u-t.height,i.size.height=f,i.position.top=o.top+a.height-f),p-l>0?(i.size.width=p,i.position.left=o.left-d):(p=u-t.height,i.size.width=p,i.position.left=o.left+a.width-p))}}),e.ui.resizable,e.widget("ui.dialog",{version:"1.11.2",options:{appendTo:"body",autoOpen:!0,buttons:[],closeOnEscape:!0,closeText:"Close",dialogClass:"",draggable:!0,hide:null,height:"auto",maxHeight:null,maxWidth:null,minHeight:150,minWidth:150,modal:!1,position:{my:"center",at:"center",of:window,collision:"fit",using:function(t){var i=e(this).css(t).offset().top;0>i&&e(this).css("top",t.top-i)}},resizable:!0,show:null,title:null,width:300,beforeClose:null,close:null,drag:null,dragStart:null,dragStop:null,focus:null,open:null,resize:null,resizeStart:null,resizeStop:null},sizeRelatedOptions:{buttons:!0,height:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,width:!0},resizableRelatedOptions:{maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0},_create:function(){this.originalCss={display:this.element[0].style.display,width:this.element[0].style.width,minHeight:this.element[0].style.minHeight,maxHeight:this.element[0].style.maxHeight,height:this.element[0].style.height},this.originalPosition={parent:this.element.parent(),index:this.element.parent().children().index(this.element)},this.originalTitle=this.element.attr("title"),this.options.title=this.options.title||this.originalTitle,this._createWrapper(),this.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(this.uiDialog),this._createTitlebar(),this._createButtonPane(),this.options.draggable&&e.fn.draggable&&this._makeDraggable(),this.options.resizable&&e.fn.resizable&&this._makeResizable(),this._isOpen=!1,this._trackFocus()},_init:function(){this.options.autoOpen&&this.open()},_appendTo:function(){var t=this.options.appendTo;return t&&(t.jquery||t.nodeType)?e(t):this.document.find(t||"body").eq(0)},_destroy:function(){var e,t=this.originalPosition;this._destroyOverlay(),this.element.removeUniqueId().removeClass("ui-dialog-content ui-widget-content").css(this.originalCss).detach(),this.uiDialog.stop(!0,!0).remove(),this.originalTitle&&this.element.attr("title",this.originalTitle),e=t.parent.children().eq(t.index),e.length&&e[0]!==this.element[0]?e.before(this.element):t.parent.append(this.element)},widget:function(){return this.uiDialog},disable:e.noop,enable:e.noop,close:function(t){var i,s=this;if(this._isOpen&&this._trigger("beforeClose",t)!==!1){if(this._isOpen=!1,this._focusedElement=null,this._destroyOverlay(),this._untrackInstance(),!this.opener.filter(":focusable").focus().length)try{i=this.document[0].activeElement,i&&"body"!==i.nodeName.toLowerCase()&&e(i).blur()}catch(n){}this._hide(this.uiDialog,this.options.hide,function(){s._trigger("close",t)})}},isOpen:function(){return this._isOpen},moveToTop:function(){this._moveToTop()},_moveToTop:function(t,i){var s=!1,n=this.uiDialog.siblings(".ui-front:visible").map(function(){return+e(this).css("z-index")}).get(),a=Math.max.apply(null,n);return a>=+this.uiDialog.css("z-index")&&(this.uiDialog.css("z-index",a+1),s=!0),s&&!i&&this._trigger("focus",t),s},open:function(){var t=this;return this._isOpen?(this._moveToTop()&&this._focusTabbable(),void 0):(this._isOpen=!0,this.opener=e(this.document[0].activeElement),this._size(),this._position(),this._createOverlay(),this._moveToTop(null,!0),this.overlay&&this.overlay.css("z-index",this.uiDialog.css("z-index")-1),this._show(this.uiDialog,this.options.show,function(){t._focusTabbable(),t._trigger("focus")}),this._makeFocusTarget(),this._trigger("open"),void 0)},_focusTabbable:function(){var e=this._focusedElement;e||(e=this.element.find("[autofocus]")),e.length||(e=this.element.find(":tabbable")),e.length||(e=this.uiDialogButtonPane.find(":tabbable")),e.length||(e=this.uiDialogTitlebarClose.filter(":tabbable")),e.length||(e=this.uiDialog),e.eq(0).focus()},_keepFocus:function(t){function i(){var t=this.document[0].activeElement,i=this.uiDialog[0]===t||e.contains(this.uiDialog[0],t);i||this._focusTabbable()}t.preventDefault(),i.call(this),this._delay(i)},_createWrapper:function(){this.uiDialog=e("
    ").addClass("ui-dialog ui-widget ui-widget-content ui-corner-all ui-front "+this.options.dialogClass).hide().attr({tabIndex:-1,role:"dialog"}).appendTo(this._appendTo()),this._on(this.uiDialog,{keydown:function(t){if(this.options.closeOnEscape&&!t.isDefaultPrevented()&&t.keyCode&&t.keyCode===e.ui.keyCode.ESCAPE)return t.preventDefault(),this.close(t),void 0; -if(t.keyCode===e.ui.keyCode.TAB&&!t.isDefaultPrevented()){var i=this.uiDialog.find(":tabbable"),s=i.filter(":first"),n=i.filter(":last");t.target!==n[0]&&t.target!==this.uiDialog[0]||t.shiftKey?t.target!==s[0]&&t.target!==this.uiDialog[0]||!t.shiftKey||(this._delay(function(){n.focus()}),t.preventDefault()):(this._delay(function(){s.focus()}),t.preventDefault())}},mousedown:function(e){this._moveToTop(e)&&this._focusTabbable()}}),this.element.find("[aria-describedby]").length||this.uiDialog.attr({"aria-describedby":this.element.uniqueId().attr("id")})},_createTitlebar:function(){var t;this.uiDialogTitlebar=e("
    ").addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(this.uiDialog),this._on(this.uiDialogTitlebar,{mousedown:function(t){e(t.target).closest(".ui-dialog-titlebar-close")||this.uiDialog.focus()}}),this.uiDialogTitlebarClose=e("").button({label:this.options.closeText,icons:{primary:"ui-icon-closethick"},text:!1}).addClass("ui-dialog-titlebar-close").appendTo(this.uiDialogTitlebar),this._on(this.uiDialogTitlebarClose,{click:function(e){e.preventDefault(),this.close(e)}}),t=e("").uniqueId().addClass("ui-dialog-title").prependTo(this.uiDialogTitlebar),this._title(t),this.uiDialog.attr({"aria-labelledby":t.attr("id")})},_title:function(e){this.options.title||e.html(" "),e.text(this.options.title)},_createButtonPane:function(){this.uiDialogButtonPane=e("
    ").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),this.uiButtonSet=e("
    ").addClass("ui-dialog-buttonset").appendTo(this.uiDialogButtonPane),this._createButtons()},_createButtons:function(){var t=this,i=this.options.buttons;return this.uiDialogButtonPane.remove(),this.uiButtonSet.empty(),e.isEmptyObject(i)||e.isArray(i)&&!i.length?(this.uiDialog.removeClass("ui-dialog-buttons"),void 0):(e.each(i,function(i,s){var n,a;s=e.isFunction(s)?{click:s,text:i}:s,s=e.extend({type:"button"},s),n=s.click,s.click=function(){n.apply(t.element[0],arguments)},a={icons:s.icons,text:s.showText},delete s.icons,delete s.showText,e("",s).button(a).appendTo(t.uiButtonSet)}),this.uiDialog.addClass("ui-dialog-buttons"),this.uiDialogButtonPane.appendTo(this.uiDialog),void 0)},_makeDraggable:function(){function t(e){return{position:e.position,offset:e.offset}}var i=this,s=this.options;this.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(s,n){e(this).addClass("ui-dialog-dragging"),i._blockFrames(),i._trigger("dragStart",s,t(n))},drag:function(e,s){i._trigger("drag",e,t(s))},stop:function(n,a){var o=a.offset.left-i.document.scrollLeft(),r=a.offset.top-i.document.scrollTop();s.position={my:"left top",at:"left"+(o>=0?"+":"")+o+" "+"top"+(r>=0?"+":"")+r,of:i.window},e(this).removeClass("ui-dialog-dragging"),i._unblockFrames(),i._trigger("dragStop",n,t(a))}})},_makeResizable:function(){function t(e){return{originalPosition:e.originalPosition,originalSize:e.originalSize,position:e.position,size:e.size}}var i=this,s=this.options,n=s.resizable,a=this.uiDialog.css("position"),o="string"==typeof n?n:"n,e,s,w,se,sw,ne,nw";this.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:this.element,maxWidth:s.maxWidth,maxHeight:s.maxHeight,minWidth:s.minWidth,minHeight:this._minHeight(),handles:o,start:function(s,n){e(this).addClass("ui-dialog-resizing"),i._blockFrames(),i._trigger("resizeStart",s,t(n))},resize:function(e,s){i._trigger("resize",e,t(s))},stop:function(n,a){var o=i.uiDialog.offset(),r=o.left-i.document.scrollLeft(),h=o.top-i.document.scrollTop();s.height=i.uiDialog.height(),s.width=i.uiDialog.width(),s.position={my:"left top",at:"left"+(r>=0?"+":"")+r+" "+"top"+(h>=0?"+":"")+h,of:i.window},e(this).removeClass("ui-dialog-resizing"),i._unblockFrames(),i._trigger("resizeStop",n,t(a))}}).css("position",a)},_trackFocus:function(){this._on(this.widget(),{focusin:function(t){this._makeFocusTarget(),this._focusedElement=e(t.target)}})},_makeFocusTarget:function(){this._untrackInstance(),this._trackingInstances().unshift(this)},_untrackInstance:function(){var t=this._trackingInstances(),i=e.inArray(this,t);-1!==i&&t.splice(i,1)},_trackingInstances:function(){var e=this.document.data("ui-dialog-instances");return e||(e=[],this.document.data("ui-dialog-instances",e)),e},_minHeight:function(){var e=this.options;return"auto"===e.height?e.minHeight:Math.min(e.minHeight,e.height)},_position:function(){var e=this.uiDialog.is(":visible");e||this.uiDialog.show(),this.uiDialog.position(this.options.position),e||this.uiDialog.hide()},_setOptions:function(t){var i=this,s=!1,n={};e.each(t,function(e,t){i._setOption(e,t),e in i.sizeRelatedOptions&&(s=!0),e in i.resizableRelatedOptions&&(n[e]=t)}),s&&(this._size(),this._position()),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option",n)},_setOption:function(e,t){var i,s,n=this.uiDialog;"dialogClass"===e&&n.removeClass(this.options.dialogClass).addClass(t),"disabled"!==e&&(this._super(e,t),"appendTo"===e&&this.uiDialog.appendTo(this._appendTo()),"buttons"===e&&this._createButtons(),"closeText"===e&&this.uiDialogTitlebarClose.button({label:""+t}),"draggable"===e&&(i=n.is(":data(ui-draggable)"),i&&!t&&n.draggable("destroy"),!i&&t&&this._makeDraggable()),"position"===e&&this._position(),"resizable"===e&&(s=n.is(":data(ui-resizable)"),s&&!t&&n.resizable("destroy"),s&&"string"==typeof t&&n.resizable("option","handles",t),s||t===!1||this._makeResizable()),"title"===e&&this._title(this.uiDialogTitlebar.find(".ui-dialog-title")))},_size:function(){var e,t,i,s=this.options;this.element.show().css({width:"auto",minHeight:0,maxHeight:"none",height:0}),s.minWidth>s.width&&(s.width=s.minWidth),e=this.uiDialog.css({height:"auto",width:s.width}).outerHeight(),t=Math.max(0,s.minHeight-e),i="number"==typeof s.maxHeight?Math.max(0,s.maxHeight-e):"none","auto"===s.height?this.element.css({minHeight:t,maxHeight:i,height:"auto"}):this.element.height(Math.max(0,s.height-e)),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())},_blockFrames:function(){this.iframeBlocks=this.document.find("iframe").map(function(){var t=e(this);return e("
    ").css({position:"absolute",width:t.outerWidth(),height:t.outerHeight()}).appendTo(t.parent()).offset(t.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_allowInteraction:function(t){return e(t.target).closest(".ui-dialog").length?!0:!!e(t.target).closest(".ui-datepicker").length},_createOverlay:function(){if(this.options.modal){var t=!0;this._delay(function(){t=!1}),this.document.data("ui-dialog-overlays")||this._on(this.document,{focusin:function(e){t||this._allowInteraction(e)||(e.preventDefault(),this._trackingInstances()[0]._focusTabbable())}}),this.overlay=e("
    ").addClass("ui-widget-overlay ui-front").appendTo(this._appendTo()),this._on(this.overlay,{mousedown:"_keepFocus"}),this.document.data("ui-dialog-overlays",(this.document.data("ui-dialog-overlays")||0)+1)}},_destroyOverlay:function(){if(this.options.modal&&this.overlay){var e=this.document.data("ui-dialog-overlays")-1;e?this.document.data("ui-dialog-overlays",e):this.document.unbind("focusin").removeData("ui-dialog-overlays"),this.overlay.remove(),this.overlay=null}}}),e.widget("ui.droppable",{version:"1.11.2",widgetEventPrefix:"drop",options:{accept:"*",activeClass:!1,addClasses:!0,greedy:!1,hoverClass:!1,scope:"default",tolerance:"intersect",activate:null,deactivate:null,drop:null,out:null,over:null},_create:function(){var t,i=this.options,s=i.accept;this.isover=!1,this.isout=!0,this.accept=e.isFunction(s)?s:function(e){return e.is(s)},this.proportions=function(){return arguments.length?(t=arguments[0],void 0):t?t:t={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight}},this._addToManager(i.scope),i.addClasses&&this.element.addClass("ui-droppable")},_addToManager:function(t){e.ui.ddmanager.droppables[t]=e.ui.ddmanager.droppables[t]||[],e.ui.ddmanager.droppables[t].push(this)},_splice:function(e){for(var t=0;e.length>t;t++)e[t]===this&&e.splice(t,1)},_destroy:function(){var t=e.ui.ddmanager.droppables[this.options.scope];this._splice(t),this.element.removeClass("ui-droppable ui-droppable-disabled")},_setOption:function(t,i){if("accept"===t)this.accept=e.isFunction(i)?i:function(e){return e.is(i)};else if("scope"===t){var s=e.ui.ddmanager.droppables[this.options.scope];this._splice(s),this._addToManager(i)}this._super(t,i)},_activate:function(t){var i=e.ui.ddmanager.current;this.options.activeClass&&this.element.addClass(this.options.activeClass),i&&this._trigger("activate",t,this.ui(i))},_deactivate:function(t){var i=e.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass),i&&this._trigger("deactivate",t,this.ui(i))},_over:function(t){var i=e.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this.options.hoverClass&&this.element.addClass(this.options.hoverClass),this._trigger("over",t,this.ui(i)))},_out:function(t){var i=e.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("out",t,this.ui(i)))},_drop:function(t,i){var s=i||e.ui.ddmanager.current,n=!1;return s&&(s.currentItem||s.element)[0]!==this.element[0]?(this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function(){var i=e(this).droppable("instance");return i.options.greedy&&!i.options.disabled&&i.options.scope===s.options.scope&&i.accept.call(i.element[0],s.currentItem||s.element)&&e.ui.intersect(s,e.extend(i,{offset:i.element.offset()}),i.options.tolerance,t)?(n=!0,!1):void 0}),n?!1:this.accept.call(this.element[0],s.currentItem||s.element)?(this.options.activeClass&&this.element.removeClass(this.options.activeClass),this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("drop",t,this.ui(s)),this.element):!1):!1},ui:function(e){return{draggable:e.currentItem||e.element,helper:e.helper,position:e.position,offset:e.positionAbs}}}),e.ui.intersect=function(){function e(e,t,i){return e>=t&&t+i>e}return function(t,i,s,n){if(!i.offset)return!1;var a=(t.positionAbs||t.position.absolute).left+t.margins.left,o=(t.positionAbs||t.position.absolute).top+t.margins.top,r=a+t.helperProportions.width,h=o+t.helperProportions.height,l=i.offset.left,u=i.offset.top,d=l+i.proportions().width,c=u+i.proportions().height;switch(s){case"fit":return a>=l&&d>=r&&o>=u&&c>=h;case"intersect":return a+t.helperProportions.width/2>l&&d>r-t.helperProportions.width/2&&o+t.helperProportions.height/2>u&&c>h-t.helperProportions.height/2;case"pointer":return e(n.pageY,u,i.proportions().height)&&e(n.pageX,l,i.proportions().width);case"touch":return(o>=u&&c>=o||h>=u&&c>=h||u>o&&h>c)&&(a>=l&&d>=a||r>=l&&d>=r||l>a&&r>d);default:return!1}}}(),e.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(t,i){var s,n,a=e.ui.ddmanager.droppables[t.options.scope]||[],o=i?i.type:null,r=(t.currentItem||t.element).find(":data(ui-droppable)").addBack();e:for(s=0;a.length>s;s++)if(!(a[s].options.disabled||t&&!a[s].accept.call(a[s].element[0],t.currentItem||t.element))){for(n=0;r.length>n;n++)if(r[n]===a[s].element[0]){a[s].proportions().height=0;continue e}a[s].visible="none"!==a[s].element.css("display"),a[s].visible&&("mousedown"===o&&a[s]._activate.call(a[s],i),a[s].offset=a[s].element.offset(),a[s].proportions({width:a[s].element[0].offsetWidth,height:a[s].element[0].offsetHeight}))}},drop:function(t,i){var s=!1;return e.each((e.ui.ddmanager.droppables[t.options.scope]||[]).slice(),function(){this.options&&(!this.options.disabled&&this.visible&&e.ui.intersect(t,this,this.options.tolerance,i)&&(s=this._drop.call(this,i)||s),!this.options.disabled&&this.visible&&this.accept.call(this.element[0],t.currentItem||t.element)&&(this.isout=!0,this.isover=!1,this._deactivate.call(this,i)))}),s},dragStart:function(t,i){t.element.parentsUntil("body").bind("scroll.droppable",function(){t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,i)})},drag:function(t,i){t.options.refreshPositions&&e.ui.ddmanager.prepareOffsets(t,i),e.each(e.ui.ddmanager.droppables[t.options.scope]||[],function(){if(!this.options.disabled&&!this.greedyChild&&this.visible){var s,n,a,o=e.ui.intersect(t,this,this.options.tolerance,i),r=!o&&this.isover?"isout":o&&!this.isover?"isover":null;r&&(this.options.greedy&&(n=this.options.scope,a=this.element.parents(":data(ui-droppable)").filter(function(){return e(this).droppable("instance").options.scope===n}),a.length&&(s=e(a[0]).droppable("instance"),s.greedyChild="isover"===r)),s&&"isover"===r&&(s.isover=!1,s.isout=!0,s._out.call(s,i)),this[r]=!0,this["isout"===r?"isover":"isout"]=!1,this["isover"===r?"_over":"_out"].call(this,i),s&&"isout"===r&&(s.isout=!1,s.isover=!0,s._over.call(s,i)))}})},dragStop:function(t,i){t.element.parentsUntil("body").unbind("scroll.droppable"),t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,i)}},e.ui.droppable;var y="ui-effects-",b=e;e.effects={effect:{}},function(e,t){function i(e,t,i){var s=d[t.type]||{};return null==e?i||!t.def?null:t.def:(e=s.floor?~~e:parseFloat(e),isNaN(e)?t.def:s.mod?(e+s.mod)%s.mod:0>e?0:e>s.max?s.max:e)}function s(i){var s=l(),n=s._rgba=[];return i=i.toLowerCase(),f(h,function(e,a){var o,r=a.re.exec(i),h=r&&a.parse(r),l=a.space||"rgba";return h?(o=s[l](h),s[u[l].cache]=o[u[l].cache],n=s._rgba=o._rgba,!1):t}),n.length?("0,0,0,0"===n.join()&&e.extend(n,a.transparent),s):a[i]}function n(e,t,i){return i=(i+1)%1,1>6*i?e+6*(t-e)*i:1>2*i?t:2>3*i?e+6*(t-e)*(2/3-i):e}var a,o="backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",r=/^([\-+])=\s*(\d+\.?\d*)/,h=[{re:/rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(e){return[e[1],e[2],e[3],e[4]]}},{re:/rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(e){return[2.55*e[1],2.55*e[2],2.55*e[3],e[4]]}},{re:/#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,parse:function(e){return[parseInt(e[1],16),parseInt(e[2],16),parseInt(e[3],16)]}},{re:/#([a-f0-9])([a-f0-9])([a-f0-9])/,parse:function(e){return[parseInt(e[1]+e[1],16),parseInt(e[2]+e[2],16),parseInt(e[3]+e[3],16)]}},{re:/hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,space:"hsla",parse:function(e){return[e[1],e[2]/100,e[3]/100,e[4]]}}],l=e.Color=function(t,i,s,n){return new e.Color.fn.parse(t,i,s,n)},u={rgba:{props:{red:{idx:0,type:"byte"},green:{idx:1,type:"byte"},blue:{idx:2,type:"byte"}}},hsla:{props:{hue:{idx:0,type:"degrees"},saturation:{idx:1,type:"percent"},lightness:{idx:2,type:"percent"}}}},d={"byte":{floor:!0,max:255},percent:{max:1},degrees:{mod:360,floor:!0}},c=l.support={},p=e("

    ")[0],f=e.each;p.style.cssText="background-color:rgba(1,1,1,.5)",c.rgba=p.style.backgroundColor.indexOf("rgba")>-1,f(u,function(e,t){t.cache="_"+e,t.props.alpha={idx:3,type:"percent",def:1}}),l.fn=e.extend(l.prototype,{parse:function(n,o,r,h){if(n===t)return this._rgba=[null,null,null,null],this;(n.jquery||n.nodeType)&&(n=e(n).css(o),o=t);var d=this,c=e.type(n),p=this._rgba=[];return o!==t&&(n=[n,o,r,h],c="array"),"string"===c?this.parse(s(n)||a._default):"array"===c?(f(u.rgba.props,function(e,t){p[t.idx]=i(n[t.idx],t)}),this):"object"===c?(n instanceof l?f(u,function(e,t){n[t.cache]&&(d[t.cache]=n[t.cache].slice())}):f(u,function(t,s){var a=s.cache;f(s.props,function(e,t){if(!d[a]&&s.to){if("alpha"===e||null==n[e])return;d[a]=s.to(d._rgba)}d[a][t.idx]=i(n[e],t,!0)}),d[a]&&0>e.inArray(null,d[a].slice(0,3))&&(d[a][3]=1,s.from&&(d._rgba=s.from(d[a])))}),this):t},is:function(e){var i=l(e),s=!0,n=this;return f(u,function(e,a){var o,r=i[a.cache];return r&&(o=n[a.cache]||a.to&&a.to(n._rgba)||[],f(a.props,function(e,i){return null!=r[i.idx]?s=r[i.idx]===o[i.idx]:t})),s}),s},_space:function(){var e=[],t=this;return f(u,function(i,s){t[s.cache]&&e.push(i)}),e.pop()},transition:function(e,t){var s=l(e),n=s._space(),a=u[n],o=0===this.alpha()?l("transparent"):this,r=o[a.cache]||a.to(o._rgba),h=r.slice();return s=s[a.cache],f(a.props,function(e,n){var a=n.idx,o=r[a],l=s[a],u=d[n.type]||{};null!==l&&(null===o?h[a]=l:(u.mod&&(l-o>u.mod/2?o+=u.mod:o-l>u.mod/2&&(o-=u.mod)),h[a]=i((l-o)*t+o,n)))}),this[n](h)},blend:function(t){if(1===this._rgba[3])return this;var i=this._rgba.slice(),s=i.pop(),n=l(t)._rgba;return l(e.map(i,function(e,t){return(1-s)*n[t]+s*e}))},toRgbaString:function(){var t="rgba(",i=e.map(this._rgba,function(e,t){return null==e?t>2?1:0:e});return 1===i[3]&&(i.pop(),t="rgb("),t+i.join()+")"},toHslaString:function(){var t="hsla(",i=e.map(this.hsla(),function(e,t){return null==e&&(e=t>2?1:0),t&&3>t&&(e=Math.round(100*e)+"%"),e});return 1===i[3]&&(i.pop(),t="hsl("),t+i.join()+")"},toHexString:function(t){var i=this._rgba.slice(),s=i.pop();return t&&i.push(~~(255*s)),"#"+e.map(i,function(e){return e=(e||0).toString(16),1===e.length?"0"+e:e}).join("")},toString:function(){return 0===this._rgba[3]?"transparent":this.toRgbaString()}}),l.fn.parse.prototype=l.fn,u.hsla.to=function(e){if(null==e[0]||null==e[1]||null==e[2])return[null,null,null,e[3]];var t,i,s=e[0]/255,n=e[1]/255,a=e[2]/255,o=e[3],r=Math.max(s,n,a),h=Math.min(s,n,a),l=r-h,u=r+h,d=.5*u;return t=h===r?0:s===r?60*(n-a)/l+360:n===r?60*(a-s)/l+120:60*(s-n)/l+240,i=0===l?0:.5>=d?l/u:l/(2-u),[Math.round(t)%360,i,d,null==o?1:o]},u.hsla.from=function(e){if(null==e[0]||null==e[1]||null==e[2])return[null,null,null,e[3]];var t=e[0]/360,i=e[1],s=e[2],a=e[3],o=.5>=s?s*(1+i):s+i-s*i,r=2*s-o;return[Math.round(255*n(r,o,t+1/3)),Math.round(255*n(r,o,t)),Math.round(255*n(r,o,t-1/3)),a]},f(u,function(s,n){var a=n.props,o=n.cache,h=n.to,u=n.from;l.fn[s]=function(s){if(h&&!this[o]&&(this[o]=h(this._rgba)),s===t)return this[o].slice();var n,r=e.type(s),d="array"===r||"object"===r?s:arguments,c=this[o].slice();return f(a,function(e,t){var s=d["object"===r?e:t.idx];null==s&&(s=c[t.idx]),c[t.idx]=i(s,t)}),u?(n=l(u(c)),n[o]=c,n):l(c)},f(a,function(t,i){l.fn[t]||(l.fn[t]=function(n){var a,o=e.type(n),h="alpha"===t?this._hsla?"hsla":"rgba":s,l=this[h](),u=l[i.idx];return"undefined"===o?u:("function"===o&&(n=n.call(this,u),o=e.type(n)),null==n&&i.empty?this:("string"===o&&(a=r.exec(n),a&&(n=u+parseFloat(a[2])*("+"===a[1]?1:-1))),l[i.idx]=n,this[h](l)))})})}),l.hook=function(t){var i=t.split(" ");f(i,function(t,i){e.cssHooks[i]={set:function(t,n){var a,o,r="";if("transparent"!==n&&("string"!==e.type(n)||(a=s(n)))){if(n=l(a||n),!c.rgba&&1!==n._rgba[3]){for(o="backgroundColor"===i?t.parentNode:t;(""===r||"transparent"===r)&&o&&o.style;)try{r=e.css(o,"backgroundColor"),o=o.parentNode}catch(h){}n=n.blend(r&&"transparent"!==r?r:"_default")}n=n.toRgbaString()}try{t.style[i]=n}catch(h){}}},e.fx.step[i]=function(t){t.colorInit||(t.start=l(t.elem,i),t.end=l(t.end),t.colorInit=!0),e.cssHooks[i].set(t.elem,t.start.transition(t.end,t.pos))}})},l.hook(o),e.cssHooks.borderColor={expand:function(e){var t={};return f(["Top","Right","Bottom","Left"],function(i,s){t["border"+s+"Color"]=e}),t}},a=e.Color.names={aqua:"#00ffff",black:"#000000",blue:"#0000ff",fuchsia:"#ff00ff",gray:"#808080",green:"#008000",lime:"#00ff00",maroon:"#800000",navy:"#000080",olive:"#808000",purple:"#800080",red:"#ff0000",silver:"#c0c0c0",teal:"#008080",white:"#ffffff",yellow:"#ffff00",transparent:[null,null,null,0],_default:"#ffffff"}}(b),function(){function t(t){var i,s,n=t.ownerDocument.defaultView?t.ownerDocument.defaultView.getComputedStyle(t,null):t.currentStyle,a={};if(n&&n.length&&n[0]&&n[n[0]])for(s=n.length;s--;)i=n[s],"string"==typeof n[i]&&(a[e.camelCase(i)]=n[i]);else for(i in n)"string"==typeof n[i]&&(a[i]=n[i]);return a}function i(t,i){var s,a,o={};for(s in i)a=i[s],t[s]!==a&&(n[s]||(e.fx.step[s]||!isNaN(parseFloat(a)))&&(o[s]=a));return o}var s=["add","remove","toggle"],n={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};e.each(["borderLeftStyle","borderRightStyle","borderBottomStyle","borderTopStyle"],function(t,i){e.fx.step[i]=function(e){("none"!==e.end&&!e.setAttr||1===e.pos&&!e.setAttr)&&(b.style(e.elem,i,e.end),e.setAttr=!0)}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e.effects.animateClass=function(n,a,o,r){var h=e.speed(a,o,r);return this.queue(function(){var a,o=e(this),r=o.attr("class")||"",l=h.children?o.find("*").addBack():o;l=l.map(function(){var i=e(this);return{el:i,start:t(this)}}),a=function(){e.each(s,function(e,t){n[t]&&o[t+"Class"](n[t])})},a(),l=l.map(function(){return this.end=t(this.el[0]),this.diff=i(this.start,this.end),this}),o.attr("class",r),l=l.map(function(){var t=this,i=e.Deferred(),s=e.extend({},h,{queue:!1,complete:function(){i.resolve(t)}});return this.el.animate(this.diff,s),i.promise()}),e.when.apply(e,l.get()).done(function(){a(),e.each(arguments,function(){var t=this.el;e.each(this.diff,function(e){t.css(e,"")})}),h.complete.call(o[0])})})},e.fn.extend({addClass:function(t){return function(i,s,n,a){return s?e.effects.animateClass.call(this,{add:i},s,n,a):t.apply(this,arguments)}}(e.fn.addClass),removeClass:function(t){return function(i,s,n,a){return arguments.length>1?e.effects.animateClass.call(this,{remove:i},s,n,a):t.apply(this,arguments)}}(e.fn.removeClass),toggleClass:function(t){return function(i,s,n,a,o){return"boolean"==typeof s||void 0===s?n?e.effects.animateClass.call(this,s?{add:i}:{remove:i},n,a,o):t.apply(this,arguments):e.effects.animateClass.call(this,{toggle:i},s,n,a)}}(e.fn.toggleClass),switchClass:function(t,i,s,n,a){return e.effects.animateClass.call(this,{add:i,remove:t},s,n,a)}})}(),function(){function t(t,i,s,n){return e.isPlainObject(t)&&(i=t,t=t.effect),t={effect:t},null==i&&(i={}),e.isFunction(i)&&(n=i,s=null,i={}),("number"==typeof i||e.fx.speeds[i])&&(n=s,s=i,i={}),e.isFunction(s)&&(n=s,s=null),i&&e.extend(t,i),s=s||i.duration,t.duration=e.fx.off?0:"number"==typeof s?s:s in e.fx.speeds?e.fx.speeds[s]:e.fx.speeds._default,t.complete=n||i.complete,t}function i(t){return!t||"number"==typeof t||e.fx.speeds[t]?!0:"string"!=typeof t||e.effects.effect[t]?e.isFunction(t)?!0:"object"!=typeof t||t.effect?!1:!0:!0}e.extend(e.effects,{version:"1.11.2",save:function(e,t){for(var i=0;t.length>i;i++)null!==t[i]&&e.data(y+t[i],e[0].style[t[i]])},restore:function(e,t){var i,s;for(s=0;t.length>s;s++)null!==t[s]&&(i=e.data(y+t[s]),void 0===i&&(i=""),e.css(t[s],i))},setMode:function(e,t){return"toggle"===t&&(t=e.is(":hidden")?"show":"hide"),t},getBaseline:function(e,t){var i,s;switch(e[0]){case"top":i=0;break;case"middle":i=.5;break;case"bottom":i=1;break;default:i=e[0]/t.height}switch(e[1]){case"left":s=0;break;case"center":s=.5;break;case"right":s=1;break;default:s=e[1]/t.width}return{x:s,y:i}},createWrapper:function(t){if(t.parent().is(".ui-effects-wrapper"))return t.parent();var i={width:t.outerWidth(!0),height:t.outerHeight(!0),"float":t.css("float")},s=e("

    ").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),n={width:t.width(),height:t.height()},a=document.activeElement;try{a.id}catch(o){a=document.body}return t.wrap(s),(t[0]===a||e.contains(t[0],a))&&e(a).focus(),s=t.parent(),"static"===t.css("position")?(s.css({position:"relative"}),t.css({position:"relative"})):(e.extend(i,{position:t.css("position"),zIndex:t.css("z-index")}),e.each(["top","left","bottom","right"],function(e,s){i[s]=t.css(s),isNaN(parseInt(i[s],10))&&(i[s]="auto")}),t.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),t.css(n),s.css(i).show()},removeWrapper:function(t){var i=document.activeElement;return t.parent().is(".ui-effects-wrapper")&&(t.parent().replaceWith(t),(t[0]===i||e.contains(t[0],i))&&e(i).focus()),t},setTransition:function(t,i,s,n){return n=n||{},e.each(i,function(e,i){var a=t.cssUnit(i);a[0]>0&&(n[i]=a[0]*s+a[1])}),n}}),e.fn.extend({effect:function(){function i(t){function i(){e.isFunction(a)&&a.call(n[0]),e.isFunction(t)&&t()}var n=e(this),a=s.complete,r=s.mode;(n.is(":hidden")?"hide"===r:"show"===r)?(n[r](),i()):o.call(n[0],s,i)}var s=t.apply(this,arguments),n=s.mode,a=s.queue,o=e.effects.effect[s.effect];return e.fx.off||!o?n?this[n](s.duration,s.complete):this.each(function(){s.complete&&s.complete.call(this)}):a===!1?this.each(i):this.queue(a||"fx",i)},show:function(e){return function(s){if(i(s))return e.apply(this,arguments);var n=t.apply(this,arguments);return n.mode="show",this.effect.call(this,n)}}(e.fn.show),hide:function(e){return function(s){if(i(s))return e.apply(this,arguments);var n=t.apply(this,arguments);return n.mode="hide",this.effect.call(this,n)}}(e.fn.hide),toggle:function(e){return function(s){if(i(s)||"boolean"==typeof s)return e.apply(this,arguments);var n=t.apply(this,arguments);return n.mode="toggle",this.effect.call(this,n)}}(e.fn.toggle),cssUnit:function(t){var i=this.css(t),s=[];return e.each(["em","px","%","pt"],function(e,t){i.indexOf(t)>0&&(s=[parseFloat(i),t])}),s}})}(),function(){var t={};e.each(["Quad","Cubic","Quart","Quint","Expo"],function(e,i){t[i]=function(t){return Math.pow(t,e+2)}}),e.extend(t,{Sine:function(e){return 1-Math.cos(e*Math.PI/2)},Circ:function(e){return 1-Math.sqrt(1-e*e)},Elastic:function(e){return 0===e||1===e?e:-Math.pow(2,8*(e-1))*Math.sin((80*(e-1)-7.5)*Math.PI/15)},Back:function(e){return e*e*(3*e-2)},Bounce:function(e){for(var t,i=4;((t=Math.pow(2,--i))-1)/11>e;);return 1/Math.pow(4,3-i)-7.5625*Math.pow((3*t-2)/22-e,2)}}),e.each(t,function(t,i){e.easing["easeIn"+t]=i,e.easing["easeOut"+t]=function(e){return 1-i(1-e)},e.easing["easeInOut"+t]=function(e){return.5>e?i(2*e)/2:1-i(-2*e+2)/2}})}(),e.effects,e.effects.effect.blind=function(t,i){var s,n,a,o=e(this),r=/up|down|vertical/,h=/up|left|vertical|horizontal/,l=["position","top","bottom","left","right","height","width"],u=e.effects.setMode(o,t.mode||"hide"),d=t.direction||"up",c=r.test(d),p=c?"height":"width",f=c?"top":"left",m=h.test(d),g={},v="show"===u;o.parent().is(".ui-effects-wrapper")?e.effects.save(o.parent(),l):e.effects.save(o,l),o.show(),s=e.effects.createWrapper(o).css({overflow:"hidden"}),n=s[p](),a=parseFloat(s.css(f))||0,g[p]=v?n:0,m||(o.css(c?"bottom":"right",0).css(c?"top":"left","auto").css({position:"absolute"}),g[f]=v?a:n+a),v&&(s.css(p,0),m||s.css(f,a+n)),s.animate(g,{duration:t.duration,easing:t.easing,queue:!1,complete:function(){"hide"===u&&o.hide(),e.effects.restore(o,l),e.effects.removeWrapper(o),i()}})},e.effects.effect.bounce=function(t,i){var s,n,a,o=e(this),r=["position","top","bottom","left","right","height","width"],h=e.effects.setMode(o,t.mode||"effect"),l="hide"===h,u="show"===h,d=t.direction||"up",c=t.distance,p=t.times||5,f=2*p+(u||l?1:0),m=t.duration/f,g=t.easing,v="up"===d||"down"===d?"top":"left",y="up"===d||"left"===d,b=o.queue(),_=b.length;for((u||l)&&r.push("opacity"),e.effects.save(o,r),o.show(),e.effects.createWrapper(o),c||(c=o["top"===v?"outerHeight":"outerWidth"]()/3),u&&(a={opacity:1},a[v]=0,o.css("opacity",0).css(v,y?2*-c:2*c).animate(a,m,g)),l&&(c/=Math.pow(2,p-1)),a={},a[v]=0,s=0;p>s;s++)n={},n[v]=(y?"-=":"+=")+c,o.animate(n,m,g).animate(a,m,g),c=l?2*c:c/2;l&&(n={opacity:0},n[v]=(y?"-=":"+=")+c,o.animate(n,m,g)),o.queue(function(){l&&o.hide(),e.effects.restore(o,r),e.effects.removeWrapper(o),i()}),_>1&&b.splice.apply(b,[1,0].concat(b.splice(_,f+1))),o.dequeue()},e.effects.effect.clip=function(t,i){var s,n,a,o=e(this),r=["position","top","bottom","left","right","height","width"],h=e.effects.setMode(o,t.mode||"hide"),l="show"===h,u=t.direction||"vertical",d="vertical"===u,c=d?"height":"width",p=d?"top":"left",f={};e.effects.save(o,r),o.show(),s=e.effects.createWrapper(o).css({overflow:"hidden"}),n="IMG"===o[0].tagName?s:o,a=n[c](),l&&(n.css(c,0),n.css(p,a/2)),f[c]=l?a:0,f[p]=l?0:a/2,n.animate(f,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){l||o.hide(),e.effects.restore(o,r),e.effects.removeWrapper(o),i()}})},e.effects.effect.drop=function(t,i){var s,n=e(this),a=["position","top","bottom","left","right","opacity","height","width"],o=e.effects.setMode(n,t.mode||"hide"),r="show"===o,h=t.direction||"left",l="up"===h||"down"===h?"top":"left",u="up"===h||"left"===h?"pos":"neg",d={opacity:r?1:0};e.effects.save(n,a),n.show(),e.effects.createWrapper(n),s=t.distance||n["top"===l?"outerHeight":"outerWidth"](!0)/2,r&&n.css("opacity",0).css(l,"pos"===u?-s:s),d[l]=(r?"pos"===u?"+=":"-=":"pos"===u?"-=":"+=")+s,n.animate(d,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){"hide"===o&&n.hide(),e.effects.restore(n,a),e.effects.removeWrapper(n),i()}})},e.effects.effect.explode=function(t,i){function s(){b.push(this),b.length===d*c&&n()}function n(){p.css({visibility:"visible"}),e(b).remove(),m||p.hide(),i()}var a,o,r,h,l,u,d=t.pieces?Math.round(Math.sqrt(t.pieces)):3,c=d,p=e(this),f=e.effects.setMode(p,t.mode||"hide"),m="show"===f,g=p.show().css("visibility","hidden").offset(),v=Math.ceil(p.outerWidth()/c),y=Math.ceil(p.outerHeight()/d),b=[];for(a=0;d>a;a++)for(h=g.top+a*y,u=a-(d-1)/2,o=0;c>o;o++)r=g.left+o*v,l=o-(c-1)/2,p.clone().appendTo("body").wrap("
    ").css({position:"absolute",visibility:"visible",left:-o*v,top:-a*y}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:v,height:y,left:r+(m?l*v:0),top:h+(m?u*y:0),opacity:m?0:1}).animate({left:r+(m?0:l*v),top:h+(m?0:u*y),opacity:m?1:0},t.duration||500,t.easing,s)},e.effects.effect.fade=function(t,i){var s=e(this),n=e.effects.setMode(s,t.mode||"toggle");s.animate({opacity:n},{queue:!1,duration:t.duration,easing:t.easing,complete:i})},e.effects.effect.fold=function(t,i){var s,n,a=e(this),o=["position","top","bottom","left","right","height","width"],r=e.effects.setMode(a,t.mode||"hide"),h="show"===r,l="hide"===r,u=t.size||15,d=/([0-9]+)%/.exec(u),c=!!t.horizFirst,p=h!==c,f=p?["width","height"]:["height","width"],m=t.duration/2,g={},v={};e.effects.save(a,o),a.show(),s=e.effects.createWrapper(a).css({overflow:"hidden"}),n=p?[s.width(),s.height()]:[s.height(),s.width()],d&&(u=parseInt(d[1],10)/100*n[l?0:1]),h&&s.css(c?{height:0,width:u}:{height:u,width:0}),g[f[0]]=h?n[0]:u,v[f[1]]=h?n[1]:0,s.animate(g,m,t.easing).animate(v,m,t.easing,function(){l&&a.hide(),e.effects.restore(a,o),e.effects.removeWrapper(a),i()})},e.effects.effect.highlight=function(t,i){var s=e(this),n=["backgroundImage","backgroundColor","opacity"],a=e.effects.setMode(s,t.mode||"show"),o={backgroundColor:s.css("backgroundColor")};"hide"===a&&(o.opacity=0),e.effects.save(s,n),s.show().css({backgroundImage:"none",backgroundColor:t.color||"#ffff99"}).animate(o,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){"hide"===a&&s.hide(),e.effects.restore(s,n),i()}})},e.effects.effect.size=function(t,i){var s,n,a,o=e(this),r=["position","top","bottom","left","right","width","height","overflow","opacity"],h=["position","top","bottom","left","right","overflow","opacity"],l=["width","height","overflow"],u=["fontSize"],d=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],c=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],p=e.effects.setMode(o,t.mode||"effect"),f=t.restore||"effect"!==p,m=t.scale||"both",g=t.origin||["middle","center"],v=o.css("position"),y=f?r:h,b={height:0,width:0,outerHeight:0,outerWidth:0};"show"===p&&o.show(),s={height:o.height(),width:o.width(),outerHeight:o.outerHeight(),outerWidth:o.outerWidth()},"toggle"===t.mode&&"show"===p?(o.from=t.to||b,o.to=t.from||s):(o.from=t.from||("show"===p?b:s),o.to=t.to||("hide"===p?b:s)),a={from:{y:o.from.height/s.height,x:o.from.width/s.width},to:{y:o.to.height/s.height,x:o.to.width/s.width}},("box"===m||"both"===m)&&(a.from.y!==a.to.y&&(y=y.concat(d),o.from=e.effects.setTransition(o,d,a.from.y,o.from),o.to=e.effects.setTransition(o,d,a.to.y,o.to)),a.from.x!==a.to.x&&(y=y.concat(c),o.from=e.effects.setTransition(o,c,a.from.x,o.from),o.to=e.effects.setTransition(o,c,a.to.x,o.to))),("content"===m||"both"===m)&&a.from.y!==a.to.y&&(y=y.concat(u).concat(l),o.from=e.effects.setTransition(o,u,a.from.y,o.from),o.to=e.effects.setTransition(o,u,a.to.y,o.to)),e.effects.save(o,y),o.show(),e.effects.createWrapper(o),o.css("overflow","hidden").css(o.from),g&&(n=e.effects.getBaseline(g,s),o.from.top=(s.outerHeight-o.outerHeight())*n.y,o.from.left=(s.outerWidth-o.outerWidth())*n.x,o.to.top=(s.outerHeight-o.to.outerHeight)*n.y,o.to.left=(s.outerWidth-o.to.outerWidth)*n.x),o.css(o.from),("content"===m||"both"===m)&&(d=d.concat(["marginTop","marginBottom"]).concat(u),c=c.concat(["marginLeft","marginRight"]),l=r.concat(d).concat(c),o.find("*[width]").each(function(){var i=e(this),s={height:i.height(),width:i.width(),outerHeight:i.outerHeight(),outerWidth:i.outerWidth()}; -f&&e.effects.save(i,l),i.from={height:s.height*a.from.y,width:s.width*a.from.x,outerHeight:s.outerHeight*a.from.y,outerWidth:s.outerWidth*a.from.x},i.to={height:s.height*a.to.y,width:s.width*a.to.x,outerHeight:s.height*a.to.y,outerWidth:s.width*a.to.x},a.from.y!==a.to.y&&(i.from=e.effects.setTransition(i,d,a.from.y,i.from),i.to=e.effects.setTransition(i,d,a.to.y,i.to)),a.from.x!==a.to.x&&(i.from=e.effects.setTransition(i,c,a.from.x,i.from),i.to=e.effects.setTransition(i,c,a.to.x,i.to)),i.css(i.from),i.animate(i.to,t.duration,t.easing,function(){f&&e.effects.restore(i,l)})})),o.animate(o.to,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){0===o.to.opacity&&o.css("opacity",o.from.opacity),"hide"===p&&o.hide(),e.effects.restore(o,y),f||("static"===v?o.css({position:"relative",top:o.to.top,left:o.to.left}):e.each(["top","left"],function(e,t){o.css(t,function(t,i){var s=parseInt(i,10),n=e?o.to.left:o.to.top;return"auto"===i?n+"px":s+n+"px"})})),e.effects.removeWrapper(o),i()}})},e.effects.effect.scale=function(t,i){var s=e(this),n=e.extend(!0,{},t),a=e.effects.setMode(s,t.mode||"effect"),o=parseInt(t.percent,10)||(0===parseInt(t.percent,10)?0:"hide"===a?0:100),r=t.direction||"both",h=t.origin,l={height:s.height(),width:s.width(),outerHeight:s.outerHeight(),outerWidth:s.outerWidth()},u={y:"horizontal"!==r?o/100:1,x:"vertical"!==r?o/100:1};n.effect="size",n.queue=!1,n.complete=i,"effect"!==a&&(n.origin=h||["middle","center"],n.restore=!0),n.from=t.from||("show"===a?{height:0,width:0,outerHeight:0,outerWidth:0}:l),n.to={height:l.height*u.y,width:l.width*u.x,outerHeight:l.outerHeight*u.y,outerWidth:l.outerWidth*u.x},n.fade&&("show"===a&&(n.from.opacity=0,n.to.opacity=1),"hide"===a&&(n.from.opacity=1,n.to.opacity=0)),s.effect(n)},e.effects.effect.puff=function(t,i){var s=e(this),n=e.effects.setMode(s,t.mode||"hide"),a="hide"===n,o=parseInt(t.percent,10)||150,r=o/100,h={height:s.height(),width:s.width(),outerHeight:s.outerHeight(),outerWidth:s.outerWidth()};e.extend(t,{effect:"scale",queue:!1,fade:!0,mode:n,complete:i,percent:a?o:100,from:a?h:{height:h.height*r,width:h.width*r,outerHeight:h.outerHeight*r,outerWidth:h.outerWidth*r}}),s.effect(t)},e.effects.effect.pulsate=function(t,i){var s,n=e(this),a=e.effects.setMode(n,t.mode||"show"),o="show"===a,r="hide"===a,h=o||"hide"===a,l=2*(t.times||5)+(h?1:0),u=t.duration/l,d=0,c=n.queue(),p=c.length;for((o||!n.is(":visible"))&&(n.css("opacity",0).show(),d=1),s=1;l>s;s++)n.animate({opacity:d},u,t.easing),d=1-d;n.animate({opacity:d},u,t.easing),n.queue(function(){r&&n.hide(),i()}),p>1&&c.splice.apply(c,[1,0].concat(c.splice(p,l+1))),n.dequeue()},e.effects.effect.shake=function(t,i){var s,n=e(this),a=["position","top","bottom","left","right","height","width"],o=e.effects.setMode(n,t.mode||"effect"),r=t.direction||"left",h=t.distance||20,l=t.times||3,u=2*l+1,d=Math.round(t.duration/u),c="up"===r||"down"===r?"top":"left",p="up"===r||"left"===r,f={},m={},g={},v=n.queue(),y=v.length;for(e.effects.save(n,a),n.show(),e.effects.createWrapper(n),f[c]=(p?"-=":"+=")+h,m[c]=(p?"+=":"-=")+2*h,g[c]=(p?"-=":"+=")+2*h,n.animate(f,d,t.easing),s=1;l>s;s++)n.animate(m,d,t.easing).animate(g,d,t.easing);n.animate(m,d,t.easing).animate(f,d/2,t.easing).queue(function(){"hide"===o&&n.hide(),e.effects.restore(n,a),e.effects.removeWrapper(n),i()}),y>1&&v.splice.apply(v,[1,0].concat(v.splice(y,u+1))),n.dequeue()},e.effects.effect.slide=function(t,i){var s,n=e(this),a=["position","top","bottom","left","right","width","height"],o=e.effects.setMode(n,t.mode||"show"),r="show"===o,h=t.direction||"left",l="up"===h||"down"===h?"top":"left",u="up"===h||"left"===h,d={};e.effects.save(n,a),n.show(),s=t.distance||n["top"===l?"outerHeight":"outerWidth"](!0),e.effects.createWrapper(n).css({overflow:"hidden"}),r&&n.css(l,u?isNaN(s)?"-"+s:-s:s),d[l]=(r?u?"+=":"-=":u?"-=":"+=")+s,n.animate(d,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){"hide"===o&&n.hide(),e.effects.restore(n,a),e.effects.removeWrapper(n),i()}})},e.effects.effect.transfer=function(t,i){var s=e(this),n=e(t.to),a="fixed"===n.css("position"),o=e("body"),r=a?o.scrollTop():0,h=a?o.scrollLeft():0,l=n.offset(),u={top:l.top-r,left:l.left-h,height:n.innerHeight(),width:n.innerWidth()},d=s.offset(),c=e("
    ").appendTo(document.body).addClass(t.className).css({top:d.top-r,left:d.left-h,height:s.innerHeight(),width:s.innerWidth(),position:a?"fixed":"absolute"}).animate(u,t.duration,t.easing,function(){c.remove(),i()})},e.widget("ui.progressbar",{version:"1.11.2",options:{max:100,value:0,change:null,complete:null},min:0,_create:function(){this.oldValue=this.options.value=this._constrainedValue(),this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min}),this.valueDiv=e("
    ").appendTo(this.element),this._refreshValue()},_destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.valueDiv.remove()},value:function(e){return void 0===e?this.options.value:(this.options.value=this._constrainedValue(e),this._refreshValue(),void 0)},_constrainedValue:function(e){return void 0===e&&(e=this.options.value),this.indeterminate=e===!1,"number"!=typeof e&&(e=0),this.indeterminate?!1:Math.min(this.options.max,Math.max(this.min,e))},_setOptions:function(e){var t=e.value;delete e.value,this._super(e),this.options.value=this._constrainedValue(t),this._refreshValue()},_setOption:function(e,t){"max"===e&&(t=Math.max(this.min,t)),"disabled"===e&&this.element.toggleClass("ui-state-disabled",!!t).attr("aria-disabled",t),this._super(e,t)},_percentage:function(){return this.indeterminate?100:100*(this.options.value-this.min)/(this.options.max-this.min)},_refreshValue:function(){var t=this.options.value,i=this._percentage();this.valueDiv.toggle(this.indeterminate||t>this.min).toggleClass("ui-corner-right",t===this.options.max).width(i.toFixed(0)+"%"),this.element.toggleClass("ui-progressbar-indeterminate",this.indeterminate),this.indeterminate?(this.element.removeAttr("aria-valuenow"),this.overlayDiv||(this.overlayDiv=e("
    ").appendTo(this.valueDiv))):(this.element.attr({"aria-valuemax":this.options.max,"aria-valuenow":t}),this.overlayDiv&&(this.overlayDiv.remove(),this.overlayDiv=null)),this.oldValue!==t&&(this.oldValue=t,this._trigger("change")),t===this.options.max&&this._trigger("complete")}}),e.widget("ui.selectable",e.ui.mouse,{version:"1.11.2",options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch",selected:null,selecting:null,start:null,stop:null,unselected:null,unselecting:null},_create:function(){var t,i=this;this.element.addClass("ui-selectable"),this.dragged=!1,this.refresh=function(){t=e(i.options.filter,i.element[0]),t.addClass("ui-selectee"),t.each(function(){var t=e(this),i=t.offset();e.data(this,"selectable-item",{element:this,$element:t,left:i.left,top:i.top,right:i.left+t.outerWidth(),bottom:i.top+t.outerHeight(),startselected:!1,selected:t.hasClass("ui-selected"),selecting:t.hasClass("ui-selecting"),unselecting:t.hasClass("ui-unselecting")})})},this.refresh(),this.selectees=t.addClass("ui-selectee"),this._mouseInit(),this.helper=e("
    ")},_destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item"),this.element.removeClass("ui-selectable ui-selectable-disabled"),this._mouseDestroy()},_mouseStart:function(t){var i=this,s=this.options;this.opos=[t.pageX,t.pageY],this.options.disabled||(this.selectees=e(s.filter,this.element[0]),this._trigger("start",t),e(s.appendTo).append(this.helper),this.helper.css({left:t.pageX,top:t.pageY,width:0,height:0}),s.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var s=e.data(this,"selectable-item");s.startselected=!0,t.metaKey||t.ctrlKey||(s.$element.removeClass("ui-selected"),s.selected=!1,s.$element.addClass("ui-unselecting"),s.unselecting=!0,i._trigger("unselecting",t,{unselecting:s.element}))}),e(t.target).parents().addBack().each(function(){var s,n=e.data(this,"selectable-item");return n?(s=!t.metaKey&&!t.ctrlKey||!n.$element.hasClass("ui-selected"),n.$element.removeClass(s?"ui-unselecting":"ui-selected").addClass(s?"ui-selecting":"ui-unselecting"),n.unselecting=!s,n.selecting=s,n.selected=s,s?i._trigger("selecting",t,{selecting:n.element}):i._trigger("unselecting",t,{unselecting:n.element}),!1):void 0}))},_mouseDrag:function(t){if(this.dragged=!0,!this.options.disabled){var i,s=this,n=this.options,a=this.opos[0],o=this.opos[1],r=t.pageX,h=t.pageY;return a>r&&(i=r,r=a,a=i),o>h&&(i=h,h=o,o=i),this.helper.css({left:a,top:o,width:r-a,height:h-o}),this.selectees.each(function(){var i=e.data(this,"selectable-item"),l=!1;i&&i.element!==s.element[0]&&("touch"===n.tolerance?l=!(i.left>r||a>i.right||i.top>h||o>i.bottom):"fit"===n.tolerance&&(l=i.left>a&&r>i.right&&i.top>o&&h>i.bottom),l?(i.selected&&(i.$element.removeClass("ui-selected"),i.selected=!1),i.unselecting&&(i.$element.removeClass("ui-unselecting"),i.unselecting=!1),i.selecting||(i.$element.addClass("ui-selecting"),i.selecting=!0,s._trigger("selecting",t,{selecting:i.element}))):(i.selecting&&((t.metaKey||t.ctrlKey)&&i.startselected?(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.$element.addClass("ui-selected"),i.selected=!0):(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.startselected&&(i.$element.addClass("ui-unselecting"),i.unselecting=!0),s._trigger("unselecting",t,{unselecting:i.element}))),i.selected&&(t.metaKey||t.ctrlKey||i.startselected||(i.$element.removeClass("ui-selected"),i.selected=!1,i.$element.addClass("ui-unselecting"),i.unselecting=!0,s._trigger("unselecting",t,{unselecting:i.element})))))}),!1}},_mouseStop:function(t){var i=this;return this.dragged=!1,e(".ui-unselecting",this.element[0]).each(function(){var s=e.data(this,"selectable-item");s.$element.removeClass("ui-unselecting"),s.unselecting=!1,s.startselected=!1,i._trigger("unselected",t,{unselected:s.element})}),e(".ui-selecting",this.element[0]).each(function(){var s=e.data(this,"selectable-item");s.$element.removeClass("ui-selecting").addClass("ui-selected"),s.selecting=!1,s.selected=!0,s.startselected=!0,i._trigger("selected",t,{selected:s.element})}),this._trigger("stop",t),this.helper.remove(),!1}}),e.widget("ui.selectmenu",{version:"1.11.2",defaultElement:"",widgetEventPrefix:"spin",options:{culture:null,icons:{down:"ui-icon-triangle-1-s",up:"ui-icon-triangle-1-n"},incremental:!0,max:null,min:null,numberFormat:null,page:10,step:1,change:null,spin:null,start:null,stop:null},_create:function(){this._setOption("max",this.options.max),this._setOption("min",this.options.min),this._setOption("step",this.options.step),""!==this.value()&&this._value(this.element.val(),!0),this._draw(),this._on(this._events),this._refresh(),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_getCreateOptions:function(){var t={},i=this.element;return e.each(["min","max","step"],function(e,s){var n=i.attr(s);void 0!==n&&n.length&&(t[s]=n)}),t},_events:{keydown:function(e){this._start(e)&&this._keydown(e)&&e.preventDefault()},keyup:"_stop",focus:function(){this.previous=this.element.val()},blur:function(e){return this.cancelBlur?(delete this.cancelBlur,void 0):(this._stop(),this._refresh(),this.previous!==this.element.val()&&this._trigger("change",e),void 0)},mousewheel:function(e,t){if(t){if(!this.spinning&&!this._start(e))return!1;this._spin((t>0?1:-1)*this.options.step,e),clearTimeout(this.mousewheelTimer),this.mousewheelTimer=this._delay(function(){this.spinning&&this._stop(e)},100),e.preventDefault()}},"mousedown .ui-spinner-button":function(t){function i(){var e=this.element[0]===this.document[0].activeElement;e||(this.element.focus(),this.previous=s,this._delay(function(){this.previous=s}))}var s;s=this.element[0]===this.document[0].activeElement?this.previous:this.element.val(),t.preventDefault(),i.call(this),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur,i.call(this)}),this._start(t)!==!1&&this._repeat(null,e(t.currentTarget).hasClass("ui-spinner-up")?1:-1,t)},"mouseup .ui-spinner-button":"_stop","mouseenter .ui-spinner-button":function(t){return e(t.currentTarget).hasClass("ui-state-active")?this._start(t)===!1?!1:(this._repeat(null,e(t.currentTarget).hasClass("ui-spinner-up")?1:-1,t),void 0):void 0},"mouseleave .ui-spinner-button":"_stop"},_draw:function(){var e=this.uiSpinner=this.element.addClass("ui-spinner-input").attr("autocomplete","off").wrap(this._uiSpinnerHtml()).parent().append(this._buttonHtml());this.element.attr("role","spinbutton"),this.buttons=e.find(".ui-spinner-button").attr("tabIndex",-1).button().removeClass("ui-corner-all"),this.buttons.height()>Math.ceil(.5*e.height())&&e.height()>0&&e.height(e.height()),this.options.disabled&&this.disable()},_keydown:function(t){var i=this.options,s=e.ui.keyCode;switch(t.keyCode){case s.UP:return this._repeat(null,1,t),!0;case s.DOWN:return this._repeat(null,-1,t),!0;case s.PAGE_UP:return this._repeat(null,i.page,t),!0;case s.PAGE_DOWN:return this._repeat(null,-i.page,t),!0}return!1},_uiSpinnerHtml:function(){return""},_buttonHtml:function(){return""+""+""+""+""},_start:function(e){return this.spinning||this._trigger("start",e)!==!1?(this.counter||(this.counter=1),this.spinning=!0,!0):!1},_repeat:function(e,t,i){e=e||500,clearTimeout(this.timer),this.timer=this._delay(function(){this._repeat(40,t,i)},e),this._spin(t*this.options.step,i)},_spin:function(e,t){var i=this.value()||0;this.counter||(this.counter=1),i=this._adjustValue(i+e*this._increment(this.counter)),this.spinning&&this._trigger("spin",t,{value:i})===!1||(this._value(i),this.counter++)},_increment:function(t){var i=this.options.incremental;return i?e.isFunction(i)?i(t):Math.floor(t*t*t/5e4-t*t/500+17*t/200+1):1},_precision:function(){var e=this._precisionOf(this.options.step);return null!==this.options.min&&(e=Math.max(e,this._precisionOf(this.options.min))),e},_precisionOf:function(e){var t=""+e,i=t.indexOf(".");return-1===i?0:t.length-i-1},_adjustValue:function(e){var t,i,s=this.options;return t=null!==s.min?s.min:0,i=e-t,i=Math.round(i/s.step)*s.step,e=t+i,e=parseFloat(e.toFixed(this._precision())),null!==s.max&&e>s.max?s.max:null!==s.min&&s.min>e?s.min:e},_stop:function(e){this.spinning&&(clearTimeout(this.timer),clearTimeout(this.mousewheelTimer),this.counter=0,this.spinning=!1,this._trigger("stop",e))},_setOption:function(e,t){if("culture"===e||"numberFormat"===e){var i=this._parse(this.element.val());return this.options[e]=t,this.element.val(this._format(i)),void 0}("max"===e||"min"===e||"step"===e)&&"string"==typeof t&&(t=this._parse(t)),"icons"===e&&(this.buttons.first().find(".ui-icon").removeClass(this.options.icons.up).addClass(t.up),this.buttons.last().find(".ui-icon").removeClass(this.options.icons.down).addClass(t.down)),this._super(e,t),"disabled"===e&&(this.widget().toggleClass("ui-state-disabled",!!t),this.element.prop("disabled",!!t),this.buttons.button(t?"disable":"enable"))},_setOptions:h(function(e){this._super(e)}),_parse:function(e){return"string"==typeof e&&""!==e&&(e=window.Globalize&&this.options.numberFormat?Globalize.parseFloat(e,10,this.options.culture):+e),""===e||isNaN(e)?null:e},_format:function(e){return""===e?"":window.Globalize&&this.options.numberFormat?Globalize.format(e,this.options.numberFormat,this.options.culture):e},_refresh:function(){this.element.attr({"aria-valuemin":this.options.min,"aria-valuemax":this.options.max,"aria-valuenow":this._parse(this.element.val())})},isValid:function(){var e=this.value();return null===e?!1:e===this._adjustValue(e)},_value:function(e,t){var i;""!==e&&(i=this._parse(e),null!==i&&(t||(i=this._adjustValue(i)),e=this._format(i))),this.element.val(e),this._refresh()},_destroy:function(){this.element.removeClass("ui-spinner-input").prop("disabled",!1).removeAttr("autocomplete").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.uiSpinner.replaceWith(this.element)},stepUp:h(function(e){this._stepUp(e)}),_stepUp:function(e){this._start()&&(this._spin((e||1)*this.options.step),this._stop())},stepDown:h(function(e){this._stepDown(e)}),_stepDown:function(e){this._start()&&(this._spin((e||1)*-this.options.step),this._stop())},pageUp:h(function(e){this._stepUp((e||1)*this.options.page)}),pageDown:h(function(e){this._stepDown((e||1)*this.options.page)}),value:function(e){return arguments.length?(h(this._value).call(this,e),void 0):this._parse(this.element.val())},widget:function(){return this.uiSpinner}}),e.widget("ui.tabs",{version:"1.11.2",delay:300,options:{active:null,collapsible:!1,event:"click",heightStyle:"content",hide:null,show:null,activate:null,beforeActivate:null,beforeLoad:null,load:null},_isLocal:function(){var e=/#.*$/;return function(t){var i,s;t=t.cloneNode(!1),i=t.href.replace(e,""),s=location.href.replace(e,"");try{i=decodeURIComponent(i)}catch(n){}try{s=decodeURIComponent(s)}catch(n){}return t.hash.length>1&&i===s}}(),_create:function(){var t=this,i=this.options;this.running=!1,this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all").toggleClass("ui-tabs-collapsible",i.collapsible),this._processTabs(),i.active=this._initialActive(),e.isArray(i.disabled)&&(i.disabled=e.unique(i.disabled.concat(e.map(this.tabs.filter(".ui-state-disabled"),function(e){return t.tabs.index(e)}))).sort()),this.active=this.options.active!==!1&&this.anchors.length?this._findActive(i.active):e(),this._refresh(),this.active.length&&this.load(i.active)},_initialActive:function(){var t=this.options.active,i=this.options.collapsible,s=location.hash.substring(1);return null===t&&(s&&this.tabs.each(function(i,n){return e(n).attr("aria-controls")===s?(t=i,!1):void 0}),null===t&&(t=this.tabs.index(this.tabs.filter(".ui-tabs-active"))),(null===t||-1===t)&&(t=this.tabs.length?0:!1)),t!==!1&&(t=this.tabs.index(this.tabs.eq(t)),-1===t&&(t=i?!1:0)),!i&&t===!1&&this.anchors.length&&(t=0),t},_getCreateEventData:function(){return{tab:this.active,panel:this.active.length?this._getPanelForTab(this.active):e()}},_tabKeydown:function(t){var i=e(this.document[0].activeElement).closest("li"),s=this.tabs.index(i),n=!0;if(!this._handlePageNav(t)){switch(t.keyCode){case e.ui.keyCode.RIGHT:case e.ui.keyCode.DOWN:s++;break;case e.ui.keyCode.UP:case e.ui.keyCode.LEFT:n=!1,s--;break;case e.ui.keyCode.END:s=this.anchors.length-1;break;case e.ui.keyCode.HOME:s=0;break;case e.ui.keyCode.SPACE:return t.preventDefault(),clearTimeout(this.activating),this._activate(s),void 0;case e.ui.keyCode.ENTER:return t.preventDefault(),clearTimeout(this.activating),this._activate(s===this.options.active?!1:s),void 0;default:return}t.preventDefault(),clearTimeout(this.activating),s=this._focusNextTab(s,n),t.ctrlKey||(i.attr("aria-selected","false"),this.tabs.eq(s).attr("aria-selected","true"),this.activating=this._delay(function(){this.option("active",s)},this.delay))}},_panelKeydown:function(t){this._handlePageNav(t)||t.ctrlKey&&t.keyCode===e.ui.keyCode.UP&&(t.preventDefault(),this.active.focus())},_handlePageNav:function(t){return t.altKey&&t.keyCode===e.ui.keyCode.PAGE_UP?(this._activate(this._focusNextTab(this.options.active-1,!1)),!0):t.altKey&&t.keyCode===e.ui.keyCode.PAGE_DOWN?(this._activate(this._focusNextTab(this.options.active+1,!0)),!0):void 0},_findNextTab:function(t,i){function s(){return t>n&&(t=0),0>t&&(t=n),t}for(var n=this.tabs.length-1;-1!==e.inArray(s(),this.options.disabled);)t=i?t+1:t-1;return t},_focusNextTab:function(e,t){return e=this._findNextTab(e,t),this.tabs.eq(e).focus(),e},_setOption:function(e,t){return"active"===e?(this._activate(t),void 0):"disabled"===e?(this._setupDisabled(t),void 0):(this._super(e,t),"collapsible"===e&&(this.element.toggleClass("ui-tabs-collapsible",t),t||this.options.active!==!1||this._activate(0)),"event"===e&&this._setupEvents(t),"heightStyle"===e&&this._setupHeightStyle(t),void 0)},_sanitizeSelector:function(e){return e?e.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g,"\\$&"):""},refresh:function(){var t=this.options,i=this.tablist.children(":has(a[href])");t.disabled=e.map(i.filter(".ui-state-disabled"),function(e){return i.index(e)}),this._processTabs(),t.active!==!1&&this.anchors.length?this.active.length&&!e.contains(this.tablist[0],this.active[0])?this.tabs.length===t.disabled.length?(t.active=!1,this.active=e()):this._activate(this._findNextTab(Math.max(0,t.active-1),!1)):t.active=this.tabs.index(this.active):(t.active=!1,this.active=e()),this._refresh()},_refresh:function(){this._setupDisabled(this.options.disabled),this._setupEvents(this.options.event),this._setupHeightStyle(this.options.heightStyle),this.tabs.not(this.active).attr({"aria-selected":"false","aria-expanded":"false",tabIndex:-1}),this.panels.not(this._getPanelForTab(this.active)).hide().attr({"aria-hidden":"true"}),this.active.length?(this.active.addClass("ui-tabs-active ui-state-active").attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0}),this._getPanelForTab(this.active).show().attr({"aria-hidden":"false"})):this.tabs.eq(0).attr("tabIndex",0)},_processTabs:function(){var t=this,i=this.tabs,s=this.anchors,n=this.panels;this.tablist=this._getList().addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").attr("role","tablist").delegate("> li","mousedown"+this.eventNamespace,function(t){e(this).is(".ui-state-disabled")&&t.preventDefault()}).delegate(".ui-tabs-anchor","focus"+this.eventNamespace,function(){e(this).closest("li").is(".ui-state-disabled")&&this.blur()}),this.tabs=this.tablist.find("> li:has(a[href])").addClass("ui-state-default ui-corner-top").attr({role:"tab",tabIndex:-1}),this.anchors=this.tabs.map(function(){return e("a",this)[0] -}).addClass("ui-tabs-anchor").attr({role:"presentation",tabIndex:-1}),this.panels=e(),this.anchors.each(function(i,s){var n,a,o,r=e(s).uniqueId().attr("id"),h=e(s).closest("li"),l=h.attr("aria-controls");t._isLocal(s)?(n=s.hash,o=n.substring(1),a=t.element.find(t._sanitizeSelector(n))):(o=h.attr("aria-controls")||e({}).uniqueId()[0].id,n="#"+o,a=t.element.find(n),a.length||(a=t._createPanel(o),a.insertAfter(t.panels[i-1]||t.tablist)),a.attr("aria-live","polite")),a.length&&(t.panels=t.panels.add(a)),l&&h.data("ui-tabs-aria-controls",l),h.attr({"aria-controls":o,"aria-labelledby":r}),a.attr("aria-labelledby",r)}),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").attr("role","tabpanel"),i&&(this._off(i.not(this.tabs)),this._off(s.not(this.anchors)),this._off(n.not(this.panels)))},_getList:function(){return this.tablist||this.element.find("ol,ul").eq(0)},_createPanel:function(t){return e("
    ").attr("id",t).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)},_setupDisabled:function(t){e.isArray(t)&&(t.length?t.length===this.anchors.length&&(t=!0):t=!1);for(var i,s=0;i=this.tabs[s];s++)t===!0||-1!==e.inArray(s,t)?e(i).addClass("ui-state-disabled").attr("aria-disabled","true"):e(i).removeClass("ui-state-disabled").removeAttr("aria-disabled");this.options.disabled=t},_setupEvents:function(t){var i={};t&&e.each(t.split(" "),function(e,t){i[t]="_eventHandler"}),this._off(this.anchors.add(this.tabs).add(this.panels)),this._on(!0,this.anchors,{click:function(e){e.preventDefault()}}),this._on(this.anchors,i),this._on(this.tabs,{keydown:"_tabKeydown"}),this._on(this.panels,{keydown:"_panelKeydown"}),this._focusable(this.tabs),this._hoverable(this.tabs)},_setupHeightStyle:function(t){var i,s=this.element.parent();"fill"===t?(i=s.height(),i-=this.element.outerHeight()-this.element.height(),this.element.siblings(":visible").each(function(){var t=e(this),s=t.css("position");"absolute"!==s&&"fixed"!==s&&(i-=t.outerHeight(!0))}),this.element.children().not(this.panels).each(function(){i-=e(this).outerHeight(!0)}),this.panels.each(function(){e(this).height(Math.max(0,i-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):"auto"===t&&(i=0,this.panels.each(function(){i=Math.max(i,e(this).height("").height())}).height(i))},_eventHandler:function(t){var i=this.options,s=this.active,n=e(t.currentTarget),a=n.closest("li"),o=a[0]===s[0],r=o&&i.collapsible,h=r?e():this._getPanelForTab(a),l=s.length?this._getPanelForTab(s):e(),u={oldTab:s,oldPanel:l,newTab:r?e():a,newPanel:h};t.preventDefault(),a.hasClass("ui-state-disabled")||a.hasClass("ui-tabs-loading")||this.running||o&&!i.collapsible||this._trigger("beforeActivate",t,u)===!1||(i.active=r?!1:this.tabs.index(a),this.active=o?e():a,this.xhr&&this.xhr.abort(),l.length||h.length||e.error("jQuery UI Tabs: Mismatching fragment identifier."),h.length&&this.load(this.tabs.index(a),t),this._toggle(t,u))},_toggle:function(t,i){function s(){a.running=!1,a._trigger("activate",t,i)}function n(){i.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),o.length&&a.options.show?a._show(o,a.options.show,s):(o.show(),s())}var a=this,o=i.newPanel,r=i.oldPanel;this.running=!0,r.length&&this.options.hide?this._hide(r,this.options.hide,function(){i.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),n()}):(i.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),r.hide(),n()),r.attr("aria-hidden","true"),i.oldTab.attr({"aria-selected":"false","aria-expanded":"false"}),o.length&&r.length?i.oldTab.attr("tabIndex",-1):o.length&&this.tabs.filter(function(){return 0===e(this).attr("tabIndex")}).attr("tabIndex",-1),o.attr("aria-hidden","false"),i.newTab.attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0})},_activate:function(t){var i,s=this._findActive(t);s[0]!==this.active[0]&&(s.length||(s=this.active),i=s.find(".ui-tabs-anchor")[0],this._eventHandler({target:i,currentTarget:i,preventDefault:e.noop}))},_findActive:function(t){return t===!1?e():this.tabs.eq(t)},_getIndex:function(e){return"string"==typeof e&&(e=this.anchors.index(this.anchors.filter("[href$='"+e+"']"))),e},_destroy:function(){this.xhr&&this.xhr.abort(),this.element.removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible"),this.tablist.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").removeAttr("role"),this.anchors.removeClass("ui-tabs-anchor").removeAttr("role").removeAttr("tabIndex").removeUniqueId(),this.tablist.unbind(this.eventNamespace),this.tabs.add(this.panels).each(function(){e.data(this,"ui-tabs-destroy")?e(this).remove():e(this).removeClass("ui-state-default ui-state-active ui-state-disabled ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel").removeAttr("tabIndex").removeAttr("aria-live").removeAttr("aria-busy").removeAttr("aria-selected").removeAttr("aria-labelledby").removeAttr("aria-hidden").removeAttr("aria-expanded").removeAttr("role")}),this.tabs.each(function(){var t=e(this),i=t.data("ui-tabs-aria-controls");i?t.attr("aria-controls",i).removeData("ui-tabs-aria-controls"):t.removeAttr("aria-controls")}),this.panels.show(),"content"!==this.options.heightStyle&&this.panels.css("height","")},enable:function(t){var i=this.options.disabled;i!==!1&&(void 0===t?i=!1:(t=this._getIndex(t),i=e.isArray(i)?e.map(i,function(e){return e!==t?e:null}):e.map(this.tabs,function(e,i){return i!==t?i:null})),this._setupDisabled(i))},disable:function(t){var i=this.options.disabled;if(i!==!0){if(void 0===t)i=!0;else{if(t=this._getIndex(t),-1!==e.inArray(t,i))return;i=e.isArray(i)?e.merge([t],i).sort():[t]}this._setupDisabled(i)}},load:function(t,i){t=this._getIndex(t);var s=this,n=this.tabs.eq(t),a=n.find(".ui-tabs-anchor"),o=this._getPanelForTab(n),r={tab:n,panel:o};this._isLocal(a[0])||(this.xhr=e.ajax(this._ajaxSettings(a,i,r)),this.xhr&&"canceled"!==this.xhr.statusText&&(n.addClass("ui-tabs-loading"),o.attr("aria-busy","true"),this.xhr.success(function(e){setTimeout(function(){o.html(e),s._trigger("load",i,r)},1)}).complete(function(e,t){setTimeout(function(){"abort"===t&&s.panels.stop(!1,!0),n.removeClass("ui-tabs-loading"),o.removeAttr("aria-busy"),e===s.xhr&&delete s.xhr},1)})))},_ajaxSettings:function(t,i,s){var n=this;return{url:t.attr("href"),beforeSend:function(t,a){return n._trigger("beforeLoad",i,e.extend({jqXHR:t,ajaxSettings:a},s))}}},_getPanelForTab:function(t){var i=e(t).attr("aria-controls");return this.element.find(this._sanitizeSelector("#"+i))}}),e.widget("ui.tooltip",{version:"1.11.2",options:{content:function(){var t=e(this).attr("title")||"";return e("").text(t).html()},hide:!0,items:"[title]:not([disabled])",position:{my:"left top+15",at:"left bottom",collision:"flipfit flip"},show:!0,tooltipClass:null,track:!1,close:null,open:null},_addDescribedBy:function(t,i){var s=(t.attr("aria-describedby")||"").split(/\s+/);s.push(i),t.data("ui-tooltip-id",i).attr("aria-describedby",e.trim(s.join(" ")))},_removeDescribedBy:function(t){var i=t.data("ui-tooltip-id"),s=(t.attr("aria-describedby")||"").split(/\s+/),n=e.inArray(i,s);-1!==n&&s.splice(n,1),t.removeData("ui-tooltip-id"),s=e.trim(s.join(" ")),s?t.attr("aria-describedby",s):t.removeAttr("aria-describedby")},_create:function(){this._on({mouseover:"open",focusin:"open"}),this.tooltips={},this.parents={},this.options.disabled&&this._disable(),this.liveRegion=e("
    ").attr({role:"log","aria-live":"assertive","aria-relevant":"additions"}).addClass("ui-helper-hidden-accessible").appendTo(this.document[0].body)},_setOption:function(t,i){var s=this;return"disabled"===t?(this[i?"_disable":"_enable"](),this.options[t]=i,void 0):(this._super(t,i),"content"===t&&e.each(this.tooltips,function(e,t){s._updateContent(t.element)}),void 0)},_disable:function(){var t=this;e.each(this.tooltips,function(i,s){var n=e.Event("blur");n.target=n.currentTarget=s.element[0],t.close(n,!0)}),this.element.find(this.options.items).addBack().each(function(){var t=e(this);t.is("[title]")&&t.data("ui-tooltip-title",t.attr("title")).removeAttr("title")})},_enable:function(){this.element.find(this.options.items).addBack().each(function(){var t=e(this);t.data("ui-tooltip-title")&&t.attr("title",t.data("ui-tooltip-title"))})},open:function(t){var i=this,s=e(t?t.target:this.element).closest(this.options.items);s.length&&!s.data("ui-tooltip-id")&&(s.attr("title")&&s.data("ui-tooltip-title",s.attr("title")),s.data("ui-tooltip-open",!0),t&&"mouseover"===t.type&&s.parents().each(function(){var t,s=e(this);s.data("ui-tooltip-open")&&(t=e.Event("blur"),t.target=t.currentTarget=this,i.close(t,!0)),s.attr("title")&&(s.uniqueId(),i.parents[this.id]={element:this,title:s.attr("title")},s.attr("title",""))}),this._updateContent(s,t))},_updateContent:function(e,t){var i,s=this.options.content,n=this,a=t?t.type:null;return"string"==typeof s?this._open(t,e,s):(i=s.call(e[0],function(i){e.data("ui-tooltip-open")&&n._delay(function(){t&&(t.type=a),this._open(t,e,i)})}),i&&this._open(t,e,i),void 0)},_open:function(t,i,s){function n(e){u.of=e,o.is(":hidden")||o.position(u)}var a,o,r,h,l,u=e.extend({},this.options.position);if(s){if(a=this._find(i))return a.tooltip.find(".ui-tooltip-content").html(s),void 0;i.is("[title]")&&(t&&"mouseover"===t.type?i.attr("title",""):i.removeAttr("title")),a=this._tooltip(i),o=a.tooltip,this._addDescribedBy(i,o.attr("id")),o.find(".ui-tooltip-content").html(s),this.liveRegion.children().hide(),s.clone?(l=s.clone(),l.removeAttr("id").find("[id]").removeAttr("id")):l=s,e("
    ").html(l).appendTo(this.liveRegion),this.options.track&&t&&/^mouse/.test(t.type)?(this._on(this.document,{mousemove:n}),n(t)):o.position(e.extend({of:i},this.options.position)),o.hide(),this._show(o,this.options.show),this.options.show&&this.options.show.delay&&(h=this.delayedShow=setInterval(function(){o.is(":visible")&&(n(u.of),clearInterval(h))},e.fx.interval)),this._trigger("open",t,{tooltip:o}),r={keyup:function(t){if(t.keyCode===e.ui.keyCode.ESCAPE){var s=e.Event(t);s.currentTarget=i[0],this.close(s,!0)}}},i[0]!==this.element[0]&&(r.remove=function(){this._removeTooltip(o)}),t&&"mouseover"!==t.type||(r.mouseleave="close"),t&&"focusin"!==t.type||(r.focusout="close"),this._on(!0,i,r)}},close:function(t){var i,s=this,n=e(t?t.currentTarget:this.element),a=this._find(n);a&&(i=a.tooltip,a.closing||(clearInterval(this.delayedShow),n.data("ui-tooltip-title")&&!n.attr("title")&&n.attr("title",n.data("ui-tooltip-title")),this._removeDescribedBy(n),a.hiding=!0,i.stop(!0),this._hide(i,this.options.hide,function(){s._removeTooltip(e(this))}),n.removeData("ui-tooltip-open"),this._off(n,"mouseleave focusout keyup"),n[0]!==this.element[0]&&this._off(n,"remove"),this._off(this.document,"mousemove"),t&&"mouseleave"===t.type&&e.each(this.parents,function(t,i){e(i.element).attr("title",i.title),delete s.parents[t]}),a.closing=!0,this._trigger("close",t,{tooltip:i}),a.hiding||(a.closing=!1)))},_tooltip:function(t){var i=e("
    ").attr("role","tooltip").addClass("ui-tooltip ui-widget ui-corner-all ui-widget-content "+(this.options.tooltipClass||"")),s=i.uniqueId().attr("id");return e("
    ").addClass("ui-tooltip-content").appendTo(i),i.appendTo(this.document[0].body),this.tooltips[s]={element:t,tooltip:i}},_find:function(e){var t=e.data("ui-tooltip-id");return t?this.tooltips[t]:null},_removeTooltip:function(e){e.remove(),delete this.tooltips[e.attr("id")]},_destroy:function(){var t=this;e.each(this.tooltips,function(i,s){var n=e.Event("blur"),a=s.element;n.target=n.currentTarget=a[0],t.close(n,!0),e("#"+i).remove(),a.data("ui-tooltip-title")&&(a.attr("title")||a.attr("title",a.data("ui-tooltip-title")),a.removeData("ui-tooltip-title"))}),this.liveRegion.remove()}})}); \ No newline at end of file diff --git a/ext/autocomplete/lib/jquery-ui.theme.min.css b/ext/autocomplete/lib/jquery-ui.theme.min.css deleted file mode 100644 index 1b9f9bfa5..000000000 --- a/ext/autocomplete/lib/jquery-ui.theme.min.css +++ /dev/null @@ -1,5 +0,0 @@ -/*! jQuery UI - v1.11.2 - 2015-01-31 -* http://jqueryui.com -* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */ - -.ui-widget{font-family:Helvetica,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Helvetica,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #ddd;background:#fff url("images/ui-bg_flat_75_ffffff_40x100.png") 50% 50% repeat-x;color:#444}.ui-widget-content a{color:#444}.ui-widget-header{border:1px solid #ddd;background:#ddd url("images/ui-bg_highlight-soft_50_dddddd_1x100.png") 50% 50% repeat-x;color:#444;font-weight:bold}.ui-widget-header a{color:#444}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #ddd;background:#f6f6f6 url("images/ui-bg_highlight-soft_100_f6f6f6_1x100.png") 50% 50% repeat-x;font-weight:bold;color:#0073ea}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#0073ea;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #0073ea;background:#0073ea url("images/ui-bg_highlight-soft_25_0073ea_1x100.png") 50% 50% repeat-x;font-weight:bold;color:#fff}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited{color:#fff;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #ddd;background:#fff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x;font-weight:bold;color:#ff0084}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#ff0084;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #ccc;background:#fff url("images/ui-bg_flat_55_ffffff_40x100.png") 50% 50% repeat-x;color:#444}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#444}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #ff0084;background:#fff url("images/ui-bg_flat_55_ffffff_40x100.png") 50% 50% repeat-x;color:#222}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#222}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#222}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("images/ui-icons_ff0084_256x240.png")}.ui-widget-header .ui-icon{background-image:url("images/ui-icons_0073ea_256x240.png")}.ui-state-default .ui-icon{background-image:url("images/ui-icons_666666_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url("images/ui-icons_ffffff_256x240.png")}.ui-state-active .ui-icon{background-image:url("images/ui-icons_454545_256x240.png")}.ui-state-highlight .ui-icon{background-image:url("images/ui-icons_0073ea_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("images/ui-icons_ff0084_256x240.png")}.ui-icon-blank{background-position:16px 16px}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:2px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:2px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:2px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:2px}.ui-widget-overlay{background:#eee url("images/ui-bg_flat_0_eeeeee_40x100.png") 50% 50% repeat-x;opacity:.8;filter:Alpha(Opacity=80)}.ui-widget-shadow{margin:-4px 0 0 -4px;padding:4px;background:#aaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x;opacity:.6;filter:Alpha(Opacity=60);border-radius:0} \ No newline at end of file diff --git a/ext/autocomplete/lib/jquery.tagit.css b/ext/autocomplete/lib/jquery.tagit.css deleted file mode 100644 index f18650d91..000000000 --- a/ext/autocomplete/lib/jquery.tagit.css +++ /dev/null @@ -1,69 +0,0 @@ -ul.tagit { - padding: 1px 5px; - overflow: auto; - margin-left: inherit; /* usually we don't want the regular ul margins. */ - margin-right: inherit; -} -ul.tagit li { - display: block; - float: left; - margin: 2px 5px 2px 0; -} -ul.tagit li.tagit-choice { - position: relative; - line-height: inherit; -} -input.tagit-hidden-field { - display: none; -} -ul.tagit li.tagit-choice-read-only { - padding: .2em .5em .2em .5em; -} - -ul.tagit li.tagit-choice-editable { - padding: .2em 18px .2em .5em; -} - -ul.tagit li.tagit-new { - padding: .25em 4px .25em 0; -} - -ul.tagit li.tagit-choice a.tagit-label { - cursor: pointer; - text-decoration: none; -} -ul.tagit li.tagit-choice .tagit-close { - cursor: pointer; - position: absolute; - right: .1em; - top: 50%; - margin-top: -8px; - line-height: 17px; -} - -/* used for some custom themes that don't need image icons */ -ul.tagit li.tagit-choice .tagit-close .text-icon { - display: none; -} - -ul.tagit li.tagit-choice input { - display: block; - float: left; - margin: 2px 5px 2px 0; -} -ul.tagit input[type="text"] { - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; - - -moz-box-shadow: none; - -webkit-box-shadow: none; - box-shadow: none; - - border: none; - margin: 0; - padding: 0; - width: inherit; - background-color: inherit; - outline: none; -} diff --git a/ext/autocomplete/lib/tag-it.min.js b/ext/autocomplete/lib/tag-it.min.js deleted file mode 100644 index af48aee1a..000000000 --- a/ext/autocomplete/lib/tag-it.min.js +++ /dev/null @@ -1,18 +0,0 @@ -//Removed TAB keybind -;(function(b){b.widget("ui.tagit",{options:{allowDuplicates:!1,caseSensitive:!0,fieldName:"tags",placeholderText:null,readOnly:!1,removeConfirmation:!1,tagLimit:null,availableTags:[],autocomplete:{},showAutocompleteOnFocus:!1,allowSpaces:!1,singleField:!1,singleFieldDelimiter:",",singleFieldNode:null,animate:!0,tabIndex:null,beforeTagAdded:null,afterTagAdded:null,beforeTagRemoved:null,afterTagRemoved:null,onTagClicked:null,onTagLimitExceeded:null,onTagAdded:null,onTagRemoved:null,tagSource:null},_create:function(){var a= -this;this.element.is("input")?(this.tagList=b("
      ").insertAfter(this.element),this.options.singleField=!0,this.options.singleFieldNode=this.element,this.element.addClass("tagit-hidden-field")):this.tagList=this.element.find("ul, ol").andSelf().last();this.tagInput=b('').addClass("ui-widget-content");this.options.readOnly&&this.tagInput.attr("disabled","disabled");this.options.tabIndex&&this.tagInput.attr("tabindex",this.options.tabIndex);this.options.placeholderText&&this.tagInput.attr("placeholder", -this.options.placeholderText);this.options.autocomplete.source||(this.options.autocomplete.source=function(a,e){var d=a.term.toLowerCase(),c=b.grep(this.options.availableTags,function(a){return 0===a.toLowerCase().indexOf(d)});this.options.allowDuplicates||(c=this._subtractArray(c,this.assignedTags()));e(c)});this.options.showAutocompleteOnFocus&&(this.tagInput.focus(function(b,d){a._showAutocomplete()}),"undefined"===typeof this.options.autocomplete.minLength&&(this.options.autocomplete.minLength= -0));b.isFunction(this.options.autocomplete.source)&&(this.options.autocomplete.source=b.proxy(this.options.autocomplete.source,this));b.isFunction(this.options.tagSource)&&(this.options.tagSource=b.proxy(this.options.tagSource,this));this.tagList.addClass("tagit").addClass("ui-widget ui-widget-content ui-corner-all").append(b('
    • ').append(this.tagInput)).click(function(d){var c=b(d.target);c.hasClass("tagit-label")?(c=c.closest(".tagit-choice"),c.hasClass("removed")||a._trigger("onTagClicked", -d,{tag:c,tagLabel:a.tagLabel(c)})):a.tagInput.focus()});var c=!1;if(this.options.singleField)if(this.options.singleFieldNode){var d=b(this.options.singleFieldNode),f=d.val().split(this.options.singleFieldDelimiter);d.val("");b.each(f,function(b,d){a.createTag(d,null,!0);c=!0})}else this.options.singleFieldNode=b(''),this.tagList.after(this.options.singleFieldNode);c||this.tagList.children("li").each(function(){b(this).hasClass("tagit-new")|| -(a.createTag(b(this).text(),b(this).attr("class"),!0),b(this).remove())});this.tagInput.keydown(function(c){if(c.which==b.ui.keyCode.BACKSPACE&&""===a.tagInput.val()){var d=a._lastTag();!a.options.removeConfirmation||d.hasClass("remove")?a.removeTag(d):a.options.removeConfirmation&&d.addClass("remove ui-state-highlight")}else a.options.removeConfirmation&&a._lastTag().removeClass("remove ui-state-highlight");if(c.which===b.ui.keyCode.COMMA&&!1===c.shiftKey||c.which===b.ui.keyCode.ENTER||c.which== -c.which==b.ui.keyCode.SPACE&&!0!==a.options.allowSpaces&&('"'!=b.trim(a.tagInput.val()).replace(/^s*/,"").charAt(0)||'"'==b.trim(a.tagInput.val()).charAt(0)&&'"'==b.trim(a.tagInput.val()).charAt(b.trim(a.tagInput.val()).length-1)&&0!==b.trim(a.tagInput.val()).length-1))c.which===b.ui.keyCode.ENTER&&""===a.tagInput.val()||c.preventDefault(),a.options.autocomplete.autoFocus&&a.tagInput.data("autocomplete-open")||(a.tagInput.autocomplete("close"),a.createTag(a._cleanedInput()))}).blur(function(b){a.tagInput.data("autocomplete-open")|| -a.createTag(a._cleanedInput())});if(this.options.availableTags||this.options.tagSource||this.options.autocomplete.source)d={select:function(b,c){a.createTag(c.item.value);return!1}},b.extend(d,this.options.autocomplete),d.source=this.options.tagSource||d.source,this.tagInput.autocomplete(d).bind("autocompleteopen.tagit",function(b,c){a.tagInput.data("autocomplete-open",!0)}).bind("autocompleteclose.tagit",function(b,c){a.tagInput.data("autocomplete-open",!1)}),this.tagInput.autocomplete("widget").addClass("tagit-autocomplete")}, -destroy:function(){b.Widget.prototype.destroy.call(this);this.element.unbind(".tagit");this.tagList.unbind(".tagit");this.tagInput.removeData("autocomplete-open");this.tagList.removeClass("tagit ui-widget ui-widget-content ui-corner-all tagit-hidden-field");this.element.is("input")?(this.element.removeClass("tagit-hidden-field"),this.tagList.remove()):(this.element.children("li").each(function(){b(this).hasClass("tagit-new")?b(this).remove():(b(this).removeClass("tagit-choice ui-widget-content ui-state-default ui-state-highlight ui-corner-all remove tagit-choice-editable tagit-choice-read-only"), -b(this).text(b(this).children(".tagit-label").text()))}),this.singleFieldNode&&this.singleFieldNode.remove());return this},_cleanedInput:function(){return b.trim(this.tagInput.val().replace(/^"(.*)"$/,"$1"))},_lastTag:function(){return this.tagList.find(".tagit-choice:last:not(.removed)")},_tags:function(){return this.tagList.find(".tagit-choice:not(.removed)")},assignedTags:function(){var a=this,c=[];this.options.singleField?(c=b(this.options.singleFieldNode).val().split(this.options.singleFieldDelimiter), -""===c[0]&&(c=[])):this._tags().each(function(){c.push(a.tagLabel(this))});return c},_updateSingleTagsField:function(a){b(this.options.singleFieldNode).val(a.join(this.options.singleFieldDelimiter)).trigger("change")},_subtractArray:function(a,c){for(var d=[],f=0;f=this.options.tagLimit)return this._trigger("onTagLimitExceeded",null,{duringInitialization:d}),!1;var g=b(this.options.onTagClicked?'
      ':'').text(a),e=b("
    • ").addClass("tagit-choice ui-widget-content ui-state-default ui-corner-all").addClass(c).append(g); -this.options.readOnly?e.addClass("tagit-choice-read-only"):(e.addClass("tagit-choice-editable"),c=b("").addClass("ui-icon ui-icon-close"),c=b('\u00d7').addClass("tagit-close").append(c).click(function(a){f.removeTag(e)}),e.append(c));this.options.singleField||(g=g.html(),e.append(''));!1!==this._trigger("beforeTagAdded",null,{tag:e,tagLabel:this.tagLabel(e), -duringInitialization:d})&&(this.options.singleField&&(g=this.assignedTags(),g.push(a),this._updateSingleTagsField(g)),this._trigger("onTagAdded",null,e),this.tagInput.val(""),this.tagInput.parent().before(e),this._trigger("afterTagAdded",null,{tag:e,tagLabel:this.tagLabel(e),duringInitialization:d}),this.options.showAutocompleteOnFocus&&!d&&setTimeout(function(){f._showAutocomplete()},0))},removeTag:function(a,c){c="undefined"===typeof c?this.options.animate:c;a=b(a);this._trigger("onTagRemoved", -null,a);if(!1!==this._trigger("beforeTagRemoved",null,{tag:a,tagLabel:this.tagLabel(a)})){if(this.options.singleField){var d=this.assignedTags(),f=this.tagLabel(a),d=b.grep(d,function(a){return a!=f});this._updateSingleTagsField(d)}if(c){a.addClass("removed");var d=this._effectExists("blind")?["blind",{direction:"horizontal"},"fast"]:["fast"],g=this;d.push(function(){a.remove();g._trigger("afterTagRemoved",null,{tag:a,tagLabel:g.tagLabel(a)})});a.fadeOut("fast").hide.apply(a,d).dequeue()}else a.remove(), -this._trigger("afterTagRemoved",null,{tag:a,tagLabel:this.tagLabel(a)})}},removeTagByLabel:function(a,b){var d=this._findTagByLabel(a);if(!d)throw"No such tag exists with the name '"+a+"'";this.removeTag(d,b)},removeAll:function(){var a=this;this._tags().each(function(b,d){a.removeTag(d,!1)})}})})(jQuery); diff --git a/ext/autocomplete/lib/tagit.ui-zendesk.css b/ext/autocomplete/lib/tagit.ui-zendesk.css deleted file mode 100644 index 18982864b..000000000 --- a/ext/autocomplete/lib/tagit.ui-zendesk.css +++ /dev/null @@ -1,97 +0,0 @@ - -/* Optional scoped theme for tag-it which mimics the zendesk widget. */ - - -ul.tagit { - border-style: solid; - border-width: 1px; - border-color: #C6C6C6; - background: inherit; -} -ul.tagit li.tagit-choice { - -moz-border-radius: 6px; - border-radius: 6px; - -webkit-border-radius: 6px; - border: 1px solid #CAD8F3; - - background: #DEE7F8 none; - - font-weight: normal; -} -ul.tagit li.tagit-choice .tagit-label:not(a) { - color: #555; -} -ul.tagit li.tagit-choice a.tagit-close { - text-decoration: none; -} -ul.tagit li.tagit-choice .tagit-close { - right: .4em; -} -ul.tagit li.tagit-choice .ui-icon { - display: none; -} -ul.tagit li.tagit-choice .tagit-close .text-icon { - display: inline; - font-family: arial, sans-serif; - font-size: 16px; - line-height: 16px; - color: #777; -} -ul.tagit li.tagit-choice:hover, ul.tagit li.tagit-choice.remove { - background-color: #bbcef1; - border-color: #6d95e0; -} -ul.tagit li.tagit-choice a.tagLabel:hover, -ul.tagit li.tagit-choice a.tagit-close .text-icon:hover { - color: #222; -} -ul.tagit input[type="text"] { - color: #333333; - background: none; -} -.ui-widget { - font-size: 1.1em; -} - -/* Forked from a jQuery UI theme, so that we don't require the jQuery UI CSS as a dependency. */ -.tagit-autocomplete.ui-autocomplete { position: absolute; cursor: default; } -* html .tagit-autocomplete.ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */ -.tagit-autocomplete.ui-menu { - list-style:none; - padding: 2px; - margin: 0; - display:block; - float: left; -} -.tagit-autocomplete.ui-menu .ui-menu { - margin-top: -3px; -} -.tagit-autocomplete.ui-menu .ui-menu-item { - margin:0; - padding: 0; - zoom: 1; - float: left; - clear: left; - width: 100%; -} -.tagit-autocomplete.ui-menu .ui-menu-item a { - text-decoration:none; - display:block; - padding:.2em .4em; - line-height:1.5; - zoom:1; -} -.tagit-autocomplete .ui-menu .ui-menu-item a.ui-state-hover, -.tagit-autocomplete .ui-menu .ui-menu-item a.ui-state-active { - font-weight: normal; - margin: -1px; -} -.tagit-autocomplete.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff 50% 50% repeat-x; color: #222222; } -.tagit-autocomplete.ui-corner-all, .tagit-autocomplete .ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; -khtml-border-radius: 4px; border-radius: 4px; } -.tagit-autocomplete .ui-state-hover, .tagit-autocomplete .ui-state-focus { border: 1px solid #999999; background: #dadada; font-weight: normal; color: #212121; } -.tagit-autocomplete .ui-state-active { border: 1px solid #aaaaaa; } - -.tagit-autocomplete .ui-widget-content { border: 1px solid #aaaaaa; } -.tagit .ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px,1px,1px,1px); } - - diff --git a/ext/autocomplete/main.php b/ext/autocomplete/main.php index a350c00d9..25d779b1b 100644 --- a/ext/autocomplete/main.php +++ b/ext/autocomplete/main.php @@ -6,9 +6,6 @@ class AutoComplete extends Extension { - /** @var AutoCompleteTheme */ - protected Themelet $theme; - public function get_priority(): int { return 30; @@ -19,7 +16,7 @@ public function onPageRequest(PageRequestEvent $event) global $page; if ($event->page_matches("api/internal/autocomplete")) { - $limit = (int)($_GET["limit"] ?? 0); + $limit = (int)($_GET["limit"] ?? 1000); $s = $_GET["s"] ?? ""; $res = $this->complete($s, $limit); @@ -28,8 +25,6 @@ public function onPageRequest(PageRequestEvent $event) $page->set_mime(MimeType::JSON); $page->set_data(json_encode($res)); } - - $this->theme->build_autocomplete($page); } private function complete(string $search, int $limit): array @@ -51,7 +46,7 @@ private function complete(string $search, int $limit): array } # memcache keys can't contain spaces - $cache_key = "autocomplete:" . md5($search); + $cache_key = "autocomplete:$limit:" . md5($search); $limitSQL = ""; $search = str_replace('_', '\_', $search); $search = str_replace('%', '\%', $search); @@ -62,23 +57,17 @@ private function complete(string $search, int $limit): array $cache_key .= "-" . $limit; } - $res = $cache->get($cache_key); - if (is_null($res)) { - $res = $database->get_pairs( - " + return cache_get_or_set($cache_key, fn () => $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 + ORDER BY count DESC, tag ASC $limitSQL ", - $SQLarr - ); - $cache->set($cache_key, $res, 600); - } - - return $res; + $SQLarr + ), 600); } } diff --git a/ext/autocomplete/script.js b/ext/autocomplete/script.js index d437bbf9d..bdd9c1b47 100644 --- a/ext/autocomplete/script.js +++ b/ext/autocomplete/script.js @@ -1,115 +1,244 @@ -document.addEventListener('DOMContentLoaded', () => { - var metatags = ['order:id', 'order:width', 'order:height', 'order:filesize', 'order:filename', 'order:favorites']; - - $('.autocomplete_tags').tagit({ - singleFieldDelimiter: ' ', - beforeTagAdded: function(event, ui) { - if(metatags.indexOf(ui.tagLabel) !== -1) { - ui.tag.addClass('tag-metatag'); - } else { - console.log(ui.tagLabel); - // give special class to negative tags - if(ui.tagLabel[0] === '-') { - ui.tag.addClass('tag-negative'); - }else{ - ui.tag.addClass('tag-positive'); +/** + * Find the word currently being typed in the given element + * + * @param {HTMLInputElement} element + * @returns {string} + */ +function getCurrentWord(element) { + let text = element.value; + let pos = element.selectionStart; + var start = text.lastIndexOf(' ', pos-1); + if(start === -1) { + start = 0; + } + else { + start++; // skip the space + } + return text.substring(start, pos); +} + +/** + * Whenever input changes, look at what word is currently + * being typed, and fetch completions for it. + * + * @param {HTMLInputElement} element + */ +function updateCompletions(element) { + // Reset selction, but no need to validate and re-render + // highlightCompletion(element, -1); + element.selected_completion = -1; + + // get the word before the cursor + var word = getCurrentWord(element); + + // search for completions + if(element.completer_timeout !== null) { + clearTimeout(element.completer_timeout); + element.completer_timeout = null; + } + if(word === '') { + element.completions = {}; + renderCompletions(element); + } + else { + element.completer_timeout = setTimeout(() => { + fetch(base_href + '/api/internal/autocomplete?s=' + word).then( + (response) => response.json() + ).then((json) => { + if(element.selected_completion !== -1) { + return; // user has started to navigate the completions, so don't update them } + element.completions = json; + renderCompletions(element); + }); + }, 250); + renderCompletions(element); + } +} + +/** + * Highlight the nth completion + * + * @param {HTMLInputElement} element + * @param {number} n + */ +function highlightCompletion(element, n) { + if(!element.completions) return; + element.selected_completion = Math.min( + Math.max(n, -1), + Object.keys(element.completions).length-1 + ); + renderCompletions(element); +} + +/** + * Render the completion block + * + * @param {HTMLInputElement} element + */ +function renderCompletions(element) { + let completions = element.completions; + let selected_completion = element.selected_completion; + + // remove any existing completion block + hideCompletions(); + + // if there are no completions, don't render anything + if(Object.keys(completions).length === 0) { + return; + } + + let completions_el = document.createElement('ul'); + completions_el.className = 'autocomplete_completions'; + completions_el.id = 'completions'; + + // add children for top completions, with the selected one highlighted + let word = getCurrentWord(element); + Object.keys(completions).filter( + (key) => key.toLowerCase().startsWith(word.toLowerCase()) + ).slice(0, 100).forEach((key, i) => { + let value = completions[key]; + let li = document.createElement('li'); + li.innerText = key + ' (' + value + ')'; + if(i === selected_completion) { + li.className = 'selected'; + } + // on hover, select the completion + // (use mousemove rather than mouseover, because + // if the mouse is stationary, then we want the + // keyboard to be able to override it) + li.addEventListener('mousemove', () => { + // avoid re-rendering if the completion is already selected + if(element.selected_completion !== i) { + highlightCompletion(element, i); } - }, - autocomplete : ({ - source: function (request, response) { - var ac_metatags = $.map( - $.grep(metatags, function(s) { - // Only show metatags for strings longer than one character - return (request.term.length > 1 && s.indexOf(request.term) === 0); - }), - function(item) { - return { - label : item + ' [metatag]', - value : item - }; - } - ); - - var isNegative = (request.term[0] === '-'); - $.ajax({ - url: base_href + '/api/internal/autocomplete', - data: {'s': (isNegative ? request.term.substring(1) : request.term)}, - dataType : 'json', - type : 'GET', - success : function (data) { - response( - $.merge(ac_metatags, - $.map(data, function (count, item) { - item = (isNegative ? '-'+item : item); - return { - label : item + ' ('+count+')', - value : item - }; - }) - ) - ); - }, - error : function (request, status, error) { - console.log(error); - } - }); - }, - minLength: 1 - }) + }); + // on click, set the completion + // (mousedown is used instead of click because click is + // fired after blur, which causes the completion block to + // be removed before the click event is handled) + li.addEventListener('mousedown', (event) => { + setCompletion(element, key); + event.preventDefault(); + }); + li.addEventListener('touchstart', (event) => { + setCompletion(element, key); + event.preventDefault(); + }); + completions_el.appendChild(li); }); - $('#tag_editor,[name="bulk_tags"]').tagit({ - singleFieldDelimiter: ' ', - autocomplete : ({ - source: function (request, response) { - $.ajax({ - url: base_href + '/api/internal/autocomplete', - data: {'s': request.term}, - dataType : 'json', - type : 'GET', - success : function (data) { - response( - $.map(data, function (count, item) { - return { - label : item + ' ('+count+')', - value : item - }; - }) - ); - }, - error : function (request, status, error) { - console.log(error); - } - }); - }, - minLength: 1 - }) + // insert the completion block after the element + if(element.parentNode) { + element.parentNode.insertBefore(completions_el, element.nextSibling); + let br = element.getBoundingClientRect(); + completions_el.style.minWidth = br.width + 'px'; + completions_el.style.left = window.scrollX + br.left + 'px'; + completions_el.style.top = window.scrollY + (br.top + br.height) + 'px'; + } +} + +/** + * hide the completions block + */ +function hideCompletions() { + document.querySelectorAll('.autocomplete_completions').forEach((element) => { + element.remove(); }); +} - $('.ui-autocomplete-input').keydown(function(e) { - var keyCode = e.keyCode || e.which; +/** + * Set the current word to the given completion + * + * @param {HTMLInputElement} element + * @param {string} new_word + */ +function setCompletion(element, new_word) { + let text = element.value; + let pos = element.selectionStart; - //Stop tags containing space. - if(keyCode === 32) { - e.preventDefault(); - var el = $('.ui-widget-content:focus'); + // get the word before the cursor + var start = text.lastIndexOf(' ', pos-1); + if(start === -1) { + start = 0; + } + else { + start++; // skip the space + } + var end = text.indexOf(' ', pos); + if(end === -1) { + end = text.length; + } - //Find the correct element in a page with multiple tagit input boxes. - $('.autocomplete_tags').each(function(_,n){ - if (n.parentNode.contains(el[0])){ - $(n.parentNode).find('.autocomplete_tags').tagit('createTag', el.val()); - } - }); - $(this).autocomplete('close'); - } else if (keyCode === 9) { - e.preventDefault(); - - var tag = $('.tagit-autocomplete[style*=\"display: block\"] > li:focus, .tagit-autocomplete[style*=\"display: block\"] > li:first').first(); - if(tag.length){ - $(tag).click(); - $('.ui-autocomplete-input').val(''); //If tag already exists, make sure to remove duplicate. + // replace the word with the completion + new_word += ' '; + element.value = text.substring(0, start) + new_word + text.substring(end); + element.selectionStart = start + new_word.length; + element.selectionEnd = start + new_word.length; + + // reset metadata + element.completions = {}; + element.selected_completion = -1; + if(element.completer_timeout) { + clearTimeout(element.completer_timeout); + element.completer_timeout = null; + } +} + +document.addEventListener('DOMContentLoaded', () => { + // Find all elements with class 'autocomplete_tags' + document.querySelectorAll('.autocomplete_tags').forEach((element) => { + // set metadata + element.completions = {}; + element.selected_completion = -1; + element.completer_timeout = null; + + // disable built-in autocomplete + element.setAttribute('autocomplete', 'off'); + + // when element is focused, add completion block + element.addEventListener('focus', () => { + updateCompletions(element); + }); + + // when element is blurred, remove completion block + element.addEventListener('blur', () => { + hideCompletions(); + }); + + // when cursor is moved, change current completion + document.addEventListener('selectionchange', () => { + // if element is focused + if(document.activeElement === element) { + updateCompletions(element); } - } + }); + + element.addEventListener('keydown', (event) => { + // up / down should select previous / next completion + if(event.code === "ArrowUp") { + event.preventDefault(); + highlightCompletion(element, element.selected_completion-1); + } + if(event.code === "ArrowDown") { + event.preventDefault(); + highlightCompletion(element, element.selected_completion+1); + } + // if enter or right are pressed, add the selected completion + if((event.code === "Enter" || event.code == "ArrowRight") && element.selected_completion !== -1) { + event.preventDefault(); + setCompletion(element, Object.keys(element.completions)[element.selected_completion]); + } + // if escape is pressed, hide the completion block + if(event.code === "Escape") { + event.preventDefault(); + hideCompletions(); + } + }); + + // on change, update completions + element.addEventListener('input', () => { + updateCompletions(element); + }); }); }); diff --git a/ext/autocomplete/style.css b/ext/autocomplete/style.css index 7ff0f69bc..e258e62e6 100644 --- a/ext/autocomplete/style.css +++ b/ext/autocomplete/style.css @@ -1,9 +1,19 @@ -#Navigationleft .blockbody { overflow: visible; } - -.tagit { background: white !important; border: 1px solid grey !important; cursor: text; } -.tagit-choice { cursor: initial; } -input[name=search] ~ input[type=submit] { display: inline-block !important; } - -.tag-negative { background: #ff8080 !important; } -.tag-positive { background: #40bf40 !important; } -.tag-metatag { background: #eaa338 !important; } +.autocomplete_completions { + position: absolute; + z-index: 1000; + border: 1px solid #ccc; + color: #000; + background-color: #fff; + padding: 5px; + list-style: none; + margin: 0; + padding: 0; + font-size: 1rem; +} +.autocomplete_completions LI { + padding: 0.15em; +} +.autocomplete_completions .selected { + background-color: #ccc; + outline: none; +} diff --git a/ext/autocomplete/theme.php b/ext/autocomplete/theme.php deleted file mode 100644 index e52151889..000000000 --- a/ext/autocomplete/theme.php +++ /dev/null @@ -1,28 +0,0 @@ -add_html_header(""); - $page->add_html_header(""); - $page->add_html_header(''); - $page->add_html_header(""); - - // determine which theme is being used, then load that theme's css last for stuff like input button styles can overwrite jQuery if needed - $theme = get_theme(); - if(!file_exists("themes/$theme")) { - // something went wrong, better not load anything - ; - } else { - $page->add_html_header(""); - } - } -} diff --git a/ext/bbcode/main.php b/ext/bbcode/main.php index 5d39b6f45..8746a0504 100644 --- a/ext/bbcode/main.php +++ b/ext/bbcode/main.php @@ -7,6 +7,12 @@ class BBCode extends FormatterExtension { public function format(string $text): string + { + $text = $this->_format($text); + return "$text"; + } + + public function _format(string $text): string { $text = $this->extract_code($text); foreach ([ @@ -158,7 +164,7 @@ private function insert_code(string $text): string $middle = base64_decode(substr($text, $start + $l1, ($end - $start - $l1))); $ending = substr($text, $end + $l2, (strlen($text) - $end + $l2)); - $text = $beginning . "
      " . $middle . "
      " . $ending; + $text = $beginning . "
      " . $middle . "
      " . $ending; } return $text; } diff --git a/ext/bbcode/script.js b/ext/bbcode/script.js index 96c6ea7d8..acedba749 100644 --- a/ext/bbcode/script.js +++ b/ext/bbcode/script.js @@ -1,18 +1,20 @@ document.addEventListener('DOMContentLoaded', () => { - $(".shm-clink").each(function(idx, elm) { - var target_id = $(elm).data("clink-sel"); - if(target_id && $(target_id).length > 0) { + document.querySelectorAll(".shm-clink").forEach(function(el) { + var target_id = el.getAttribute("data-clink-sel"); + if(target_id && document.querySelectorAll(target_id).length > 0) { // if the target comment is already on this page, don't bother // switching pages - $(elm).attr("href", target_id); + el.setAttribute("href", target_id); + // highlight it when clicked - $(elm).click(function(e) { + el.addEventListener("click", function(e) { // This needs jQuery UI $(target_id).highlight(); }); + // vanilla target name should already be in the URL tag, but this // will include the anon ID as displayed on screen - $(elm).html("@"+$(target_id+" .username").html()); + el.innerHTML = "@"+document.querySelector(target_id+" .username").innerHTML; } }); }); diff --git a/ext/bbcode/style.css b/ext/bbcode/style.css index 200221cc2..525ff5c54 100644 --- a/ext/bbcode/style.css +++ b/ext/bbcode/style.css @@ -1,16 +1,15 @@ - -CODE { - background: #DEDEDE; - font-size: 0.8em; +.bbcode PRE.code { + background: #DEDEDE; + font-size: 0.9rem; } -BLOCKQUOTE { +.bbcode BLOCKQUOTE { border: 1px solid black; padding: 8px; background: #DDD; } -.anchor A.alink { +.bbcode .anchor A.alink { visibility: hidden; } -.anchor:hover A.alink { +.bbcode .anchor:hover A.alink { visibility: visible; } diff --git a/ext/bbcode/test.php b/ext/bbcode/test.php index 359ee3e04..20b42b6aa 100644 --- a/ext/bbcode/test.php +++ b/ext/bbcode/test.php @@ -37,7 +37,7 @@ public function testFailure() public function testCode() { $this->assertEquals( - "
      [b]bold[/b]
      ", + "
      [b]bold[/b]
      ", $this->filter("[code][b]bold[/b][/code]") ); } @@ -104,7 +104,7 @@ public function testAnchor() private function filter($in): string { $bb = new BBCode(); - return $bb->format($in); + return $bb->_format($in); } private function strip($in): string diff --git a/ext/blocks/main.php b/ext/blocks/main.php index c7bcb2b96..2711fd9ab 100644 --- a/ext/blocks/main.php +++ b/ext/blocks/main.php @@ -53,11 +53,7 @@ public function onPageRequest(PageRequestEvent $event) { global $cache, $database, $page, $user; - $blocks = $cache->get("blocks"); - if (is_null($blocks)) { - $blocks = $database->get_all("SELECT * FROM blocks"); - $cache->set("blocks", $blocks, 600); - } + $blocks = cache_get_or_set("blocks", fn () => $database->get_all("SELECT * FROM blocks"), 600); foreach ($blocks as $block) { $path = implode("/", $event->args); if (strlen($path) < 4000 && fnmatch($block['pages'], $path)) { diff --git a/ext/blotter/script.js b/ext/blotter/script.js index 2623f3e45..664d8588e 100644 --- a/ext/blotter/script.js +++ b/ext/blotter/script.js @@ -4,14 +4,14 @@ document.addEventListener('DOMContentLoaded', () => { $(".shm-blotter2-toggle").click(function() { $(".shm-blotter2").slideToggle("slow", function() { if($(".shm-blotter2").is(":hidden")) { - Cookies.set("ui-blotter2-hidden", 'true'); + shm_cookie_set("ui-blotter2-hidden", 'true'); } else { - Cookies.set("ui-blotter2-hidden", 'false'); + shm_cookie_set("ui-blotter2-hidden", 'false'); } }); }); - if(Cookies.get("ui-blotter2-hidden") === 'true') { + if(shm_cookie_get("ui-blotter2-hidden") === 'true') { $(".shm-blotter2").hide(); } }); diff --git a/ext/bulk_actions/main.php b/ext/bulk_actions/main.php index ee235eed8..e296893dc 100644 --- a/ext/bulk_actions/main.php +++ b/ext/bulk_actions/main.php @@ -214,7 +214,7 @@ private function yield_items(array $data): \Generator private function yield_search_results(string $query): \Generator { $tags = Tag::explode($query); - return Image::find_images_iterable(0, null, $tags); + return Search::find_images_iterable(0, null, $tags); } private function sort_blocks($a, $b) diff --git a/ext/bulk_actions/script.js b/ext/bulk_actions/script.js index 831c00870..184a4b8cb 100644 --- a/ext/bulk_actions/script.js +++ b/ext/bulk_actions/script.js @@ -68,11 +68,11 @@ function get_selected_items() { } function set_selected_items(items) { - $(".shm-thumb").removeClass('selected'); + $(".shm-thumb").removeClass('bulk_selected'); $(items).each( function(index,item) { - $('.shm-thumb[data-post-id="' + item + '"]').addClass('selected'); + $('.shm-thumb[data-post-id="' + item + '"]').addClass('bulk_selected'); } ); diff --git a/ext/bulk_actions/style.css b/ext/bulk_actions/style.css index 4e7449fc6..117a5ce87 100644 --- a/ext/bulk_actions/style.css +++ b/ext/bulk_actions/style.css @@ -1,4 +1,4 @@ -.selected { +.bulk_selected { outline: 3px solid blue; } diff --git a/ext/bulk_add_csv/main.php b/ext/bulk_add_csv/main.php index 868ae5ac5..f04e93edc 100644 --- a/ext/bulk_add_csv/main.php +++ b/ext/bulk_add_csv/main.php @@ -24,8 +24,8 @@ public function onPageRequest(PageRequestEvent $event) public function onCommand(CommandEvent $event) { if ($event->cmd == "help") { - print " bulk-add-csv [/path/to.csv]\n"; - print " Import this .csv file (refer to documentation)\n\n"; + print "\tbulk-add-csv [/path/to.csv]\n"; + print "\t\tImport this .csv file (refer to documentation)\n\n"; } if ($event->cmd == "bulk-add-csv") { global $user; diff --git a/ext/comment/main.php b/ext/comment/main.php index a16d8d643..6bf5f686b 100644 --- a/ext/comment/main.php +++ b/ext/comment/main.php @@ -283,20 +283,17 @@ private function onPageRequest_list(PageRequestEvent $event) { global $cache, $config, $database, $user; + $threads_per_page = 10; + $where = SPEED_HAX ? "WHERE posted > now() - interval '24 hours'" : ""; - $total_pages = $cache->get("comment_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 - ") / 10); - $cache->set("comment_pages", $total_pages, 600); - } + $total_pages = cache_get_or_set("comment_pages", fn () => (int)ceil($database->get_one(" + SELECT COUNT(c1) + FROM (SELECT COUNT(image_id) AS c1 FROM comments $where GROUP BY image_id) AS s1 + ") / $threads_per_page), 600); $total_pages = max($total_pages, 1); $current_page = $event->try_page_num(1, $total_pages); - $threads_per_page = 10; $start = $threads_per_page * $current_page; $result = $database->execute(" @@ -357,11 +354,7 @@ public function onPostListBuilding(PostListBuildingEvent $event) global $cache, $config; $cc = $config->get_int("comment_count"); if ($cc > 0) { - $recent = $cache->get("recent_comments"); - if (is_null($recent)) { - $recent = $this->get_recent_comments($cc); - $cache->set("recent_comments", $recent, 60); - } + $recent = cache_get_or_set("recent_comments", fn () => $this->get_recent_comments($cc), 60); if (count($recent) > 0) { $this->theme->display_recent_comments($recent); } @@ -572,7 +565,8 @@ public static function get_hash(): string private function is_spam_akismet(string $text): bool { global $config, $user; - if (strlen($config->get_string('comment_wordpress_key')) > 0) { + $key = $config->get_string('comment_wordpress_key'); + if (!is_null($key) && strlen($key) > 0) { $comment = [ 'author' => $user->name, 'email' => $user->email, @@ -584,11 +578,7 @@ private function is_spam_akismet(string $text): bool ]; // @phpstan-ignore-next-line - $akismet = new \Akismet( - $_SERVER['SERVER_NAME'], - $config->get_string('comment_wordpress_key'), - $comment - ); + $akismet = new \Akismet($_SERVER['SERVER_NAME'], $key, $comment); // @phpstan-ignore-next-line if ($akismet->errorsExist()) { diff --git a/ext/comment/script.js b/ext/comment/script.js index 47023be79..a6f15345f 100644 --- a/ext/comment/script.js +++ b/ext/comment/script.js @@ -1,8 +1,8 @@ function replyTo(imageId, commentId, userId) { - var box = $("#comment_on_"+imageId); + var box = document.getElementById("comment_on_"+imageId); var text = "[url=site://post/view/"+imageId+"#c"+commentId+"]@"+userId+"[/url]: "; box.focus(); - box.val(box.val() + text); + box.value += text; $("#c"+commentId).highlight(); } diff --git a/ext/comment/theme.php b/ext/comment/theme.php index 8bef60e0d..911b4eb0b 100644 --- a/ext/comment/theme.php +++ b/ext/comment/theme.php @@ -111,7 +111,7 @@ public function display_admin_block() /** * Add some comments to the page, probably in a sidebar. * - * #param Comment[] $comments An array of Comment objects to be shown + * @param Comment[] $comments An array of Comment objects to be shown */ public function display_recent_comments(array $comments) { @@ -128,7 +128,7 @@ public function display_recent_comments(array $comments) /** * Show comments for an image. * - * #param Comment[] $comments + * @param Comment[] $comments */ public function display_image_comments(Image $image, array $comments, bool $postbox) { @@ -147,7 +147,7 @@ public function display_image_comments(Image $image, array $comments, bool $post /** * Show comments made by a user. * - * #param Comment[] $comments + * @param Comment[] $comments */ public function display_recent_user_comments(array $comments, User $user) { diff --git a/ext/cron_uploader/style.css b/ext/cron_uploader/style.css index 2643a6a16..770152bde 100644 --- a/ext/cron_uploader/style.css +++ b/ext/cron_uploader/style.css @@ -1,3 +1,3 @@ -table.log th { +table.cron_uploader_log th { width: 200px; } \ No newline at end of file diff --git a/ext/cron_uploader/theme.php b/ext/cron_uploader/theme.php index e367ba195..977f40f34 100644 --- a/ext/cron_uploader/theme.php +++ b/ext/cron_uploader/theme.php @@ -115,7 +115,7 @@ public function display_documentation( $page->add_block($block_usage); if (!empty($log_entries)) { - $log_html = ""; + $log_html = "
      "; foreach ($log_entries as $entry) { $log_html .= ""; } diff --git a/ext/danbooru_api/main.php b/ext/danbooru_api/main.php index 569de860c..1104f04f3 100644 --- a/ext/danbooru_api/main.php +++ b/ext/danbooru_api/main.php @@ -199,8 +199,8 @@ private function api_find_posts(): HTMLElement $tags = array_filter($tags, static function ($element) { return $element !== "*"; }); - $count = Image::count_images($tags); - $results = Image::find_images(max($start, 0), min($limit, 100), $tags); + $count = Search::count_images($tags); + $results = Search::find_images(max($start, 0), min($limit, 100), $tags); } // Now we have the array $results filled with Image objects diff --git a/ext/downtime/theme.php b/ext/downtime/theme.php index 6876eaf6b..1a21d9aee 100644 --- a/ext/downtime/theme.php +++ b/ext/downtime/theme.php @@ -13,7 +13,7 @@ public function display_notification(Page $page) { $page->add_block(new Block( "Downtime", - "DOWNTIME MODE IS ON!", + "DOWNTIME MODE IS ON!", "left", 0 )); diff --git a/ext/ext_manager/main.php b/ext/ext_manager/main.php index 164b0e822..c66a3edd8 100644 --- a/ext/ext_manager/main.php +++ b/ext/ext_manager/main.php @@ -137,7 +137,7 @@ private function set_things($settings) } /** - * #param string[] $extras + * @param string[] $extras */ private function write_config(array $extras) { diff --git a/ext/ext_manager/theme.php b/ext/ext_manager/theme.php index 2b5bb35c2..8e0ee1faf 100644 --- a/ext/ext_manager/theme.php +++ b/ext/ext_manager/theme.php @@ -25,7 +25,7 @@ class ExtManagerTheme extends Themelet { /** - * #param ExtensionInfo[] $extensions + * @param ExtensionInfo[] $extensions */ public function display_table(Page $page, array $extensions, bool $editable) { diff --git a/ext/favorites/main.php b/ext/favorites/main.php index af2db5bc2..75e3584a5 100644 --- a/ext/favorites/main.php +++ b/ext/favorites/main.php @@ -72,7 +72,7 @@ public function onPageRequest(PageRequestEvent $event) public function onUserPageBuilding(UserPageBuildingEvent $event) { - $i_favorites_count = Image::count_images(["favorited_by={$event->display_user->name}"]); + $i_favorites_count = Search::count_images(["favorited_by={$event->display_user->name}"]); $i_days_old = ((time() - strtotime($event->display_user->join_date)) / 86400) + 1; $h_favorites_rate = sprintf("%.1f", ($i_favorites_count / $i_days_old)); $favorites_link = search_link(["favorited_by={$event->display_user->name}"]); diff --git a/ext/featured/main.php b/ext/featured/main.php index 11cba6ecb..de82bde3f 100644 --- a/ext/featured/main.php +++ b/ext/featured/main.php @@ -52,14 +52,17 @@ public function onPostListBuilding(PostListBuildingEvent $event) global $cache, $config, $page, $user; $fid = $config->get_int("featured_id"); if ($fid > 0) { - $image = $cache->get("featured_image_object:$fid"); - if (is_null($image)) { - $image = Image::by_id($fid); - if ($image) { // make sure the object is fully populated before saving - $image->get_tag_array(); - } - $cache->set("featured_image_object:$fid", $image, 600); - } + $image = cache_get_or_set( + "featured_image_object:$fid", + function () use ($fid) { + $image = Image::by_id($fid); + if ($image) { // make sure the object is fully populated before saving + $image->get_tag_array(); + } + return $image; + }, + 600 + ); if (!is_null($image)) { if (Extension::is_enabled(RatingsInfo::KEY)) { if (!in_array($image->rating, Ratings::get_user_class_privs($user))) { diff --git a/ext/handle_cbz/comic.js b/ext/handle_cbz/comic.js index 8d0f12ee3..613e9cf7a 100644 --- a/ext/handle_cbz/comic.js +++ b/ext/handle_cbz/comic.js @@ -11,8 +11,8 @@ function Comic(root, comicURL) { self.comicZip = zip; // Shimmie-specific; nullify existing back / forward - $("[rel='previous']").remove(); - $("[rel='next']").remove(); + document.querySelector("LINK[rel='previous']").remove(); + document.querySelector("LINK[rel='next']").remove(); zip.forEach(function (relativePath, file){ self.comicPages.push(relativePath); @@ -53,7 +53,8 @@ function Comic(root, comicURL) { }; this.onKeyUp = function(e) { - if ($(e.target).is('input,textarea')) { return; } + let t = e.target; + if (t.tagName === "INPUT" || t.tagName === "TEXTAREA") { return; } if (e.metaKey || e.ctrlKey || e.altKey || e.shiftKey) { return; } if (e.keyCode === 37) {self.prev();} else if (e.keyCode === 39) {self.next();} diff --git a/ext/handle_cbz/style.css b/ext/handle_cbz/style.css index 4813925cc..bb9dbd34e 100644 --- a/ext/handle_cbz/style.css +++ b/ext/handle_cbz/style.css @@ -1,7 +1,7 @@ #comicMain { background: black; color: white; - font-size: 3em; + font-size: 3rem; } #comicPageList { width: 90%; diff --git a/ext/handle_cbz/theme.php b/ext/handle_cbz/theme.php index ce574a8f5..5d6dff37d 100644 --- a/ext/handle_cbz/theme.php +++ b/ext/handle_cbz/theme.php @@ -6,8 +6,9 @@ class CBZFileHandlerTheme extends Themelet { - public function display_image(Page $page, Image $image) + public function display_image(Image $image) { + global $page; $data_href = get_base_href(); $ilink = $image->get_image_link(); $html = " diff --git a/ext/handle_flash/info.php b/ext/handle_flash/info.php deleted file mode 100644 index 24f36c398..000000000 --- a/ext/handle_flash/info.php +++ /dev/null @@ -1,16 +0,0 @@ -image->lossless = true; - $event->image->video = true; - $event->image->image = false; - - $info = getimagesize($event->image->get_image_filename()); - if ($info) { - $event->image->width = $info[0]; - $event->image->height = $info[1]; - } - } - - protected function create_thumb(string $hash, string $mime): bool - { - if (!Media::create_thumbnail_ffmpeg($hash)) { - copy("ext/handle_flash/thumb.jpg", warehouse_path(Image::THUMBNAIL_DIR, $hash)); - } - return true; - } - - protected function check_contents(string $tmpname): bool - { - $fp = fopen($tmpname, "r"); - $head = fread($fp, 3); - fclose($fp); - return in_array($head, ["CWS", "FWS"]); - } -} diff --git a/ext/handle_flash/theme.php b/ext/handle_flash/theme.php deleted file mode 100644 index 9e2c799f9..000000000 --- a/ext/handle_flash/theme.php +++ /dev/null @@ -1,31 +0,0 @@ -get_image_link(); - // FIXME: object and embed have "height" and "width" - $html = " - - - - - "; - $page->add_block(new Block("Flash Animation", $html, "main", 10)); - } -} diff --git a/ext/handle_flash/thumb.jpg b/ext/handle_flash/thumb.jpg deleted file mode 100644 index 3debb306b..000000000 Binary files a/ext/handle_flash/thumb.jpg and /dev/null differ diff --git a/ext/handle_ico/theme.php b/ext/handle_ico/theme.php index 81f6c74fa..2f2587c09 100644 --- a/ext/handle_ico/theme.php +++ b/ext/handle_ico/theme.php @@ -6,8 +6,9 @@ class IcoFileHandlerTheme extends Themelet { - public function display_image(Page $page, Image $image) + public function display_image(Image $image) { + global $page; $ilink = $image->get_image_link(); $html = " main imageget_image_link(); $html = " diff --git a/ext/handle_pixel/script.js b/ext/handle_pixel/script.js index 6cd83fbf3..ce09d1850 100644 --- a/ext/handle_pixel/script.js +++ b/ext/handle_pixel/script.js @@ -24,7 +24,7 @@ document.addEventListener('DOMContentLoaded', () => { $(".shm-zoomer").val(zoom_type); if (save_cookie) { - Cookies.set("ui-image-zoom", zoom_type, {expires: 365}); + shm_cookie_set("ui-image-zoom", zoom_type); } } @@ -38,13 +38,13 @@ document.addEventListener('DOMContentLoaded', () => { }); $("img.shm-main-image").click(function(e) { - switch(Cookies.get("ui-image-zoom")) { + switch(shm_cookie_get("ui-image-zoom")) { case "full": zoom("width"); break; default: zoom("full"); break; } }); - if(Cookies.get("ui-image-zoom")) { - zoom(Cookies.get("ui-image-zoom")); + if(shm_cookie_get("ui-image-zoom")) { + zoom(shm_cookie_get("ui-image-zoom")); } }); diff --git a/ext/handle_pixel/theme.php b/ext/handle_pixel/theme.php index 3bf5b3022..0ffebd775 100644 --- a/ext/handle_pixel/theme.php +++ b/ext/handle_pixel/theme.php @@ -4,14 +4,32 @@ namespace Shimmie2; +use function MicroHTML\IMG; + class PixelFileHandlerTheme extends Themelet { - public function display_image(Page $page, Image $image) + public function display_image(Image $image) + { + global $config, $page; + + $html = IMG([ + 'alt' => 'main image', + 'class' => 'shm-main-image', + 'id' => 'main_image', + 'src' => $image->get_image_link(), + 'data-width' => $image->width, + 'data-height' => $image->height, + 'data-mime' => $image->get_mime(), + 'onerror' => "shm_log('Error loading >>{$image->id}')", + ]); + $page->add_block(new Block("Image", $html, "main", 10)); + } + + public function display_metadata(Image $image) { - global $config; + global $page; - $u_ilink = $image->get_image_link(); - if ($config->get_bool(ImageConfig::SHOW_META) && function_exists(ImageIO::EXIF_READ_FUNCTION)) { + if (function_exists(ImageIO::EXIF_READ_FUNCTION)) { # FIXME: only read from jpegs? $exif = @exif_read_data($image->get_image_filename(), "IFD0", true); if ($exif) { @@ -32,9 +50,5 @@ public function display_image(Page $page, Image $image) } } } - - $html = "main image"; - $page->add_block(new Block("Image", $html, "main", 10)); } } diff --git a/ext/handle_svg/theme.php b/ext/handle_svg/theme.php index 375575816..a9fd63df5 100644 --- a/ext/handle_svg/theme.php +++ b/ext/handle_svg/theme.php @@ -6,8 +6,9 @@ class SVGFileHandlerTheme extends Themelet { - public function display_image(Page $page, Image $image) + public function display_image(Image $image) { + global $page; $ilink = make_link("get_svg/{$image->id}/{$image->id}.svg"); // $ilink = $image->get_image_link(); $html = " diff --git a/ext/handle_video/main.php b/ext/handle_video/main.php index 1f8d21fc3..0c64436d4 100644 --- a/ext/handle_video/main.php +++ b/ext/handle_video/main.php @@ -88,14 +88,8 @@ protected function media_check_properties(MediaCheckPropertiesEvent $event): voi break; } } - if (array_key_exists("width", $stream) && !empty($stream["width"]) - && is_numeric($stream["width"]) && intval($stream["width"]) > ($event->image->width) ?? 0) { - $event->image->width = intval($stream["width"]); - } - if (array_key_exists("height", $stream) && !empty($stream["height"]) - && is_numeric($stream["height"]) && intval($stream["height"]) > ($event->image->height) ?? 0) { - $event->image->height = intval($stream["height"]); - } + $event->image->width = max($event->image->width, @$stream["width"]); + $event->image->height = max($event->image->height, @$stream["height"]); } } $event->image->video = $video; diff --git a/ext/handle_video/theme.php b/ext/handle_video/theme.php index cd0e54f6c..dcb702089 100644 --- a/ext/handle_video/theme.php +++ b/ext/handle_video/theme.php @@ -4,17 +4,13 @@ namespace Shimmie2; +use function MicroHTML\{A, BR, VIDEO, SOURCE, emptyHTML}; + class VideoFileHandlerTheme extends Themelet { - public function display_image(Page $page, Image $image) + public function display_image(Image $image) { - global $config; - $ilink = $image->get_image_link(); - $thumb_url = make_http($image->get_thumb_link()); //used as fallback image - $mime = strtolower($image->get_mime()); - $autoplay = $config->get_bool(VideoFileHandlerConfig::PLAYBACK_AUTOPLAY); - $loop = $config->get_bool(VideoFileHandlerConfig::PLAYBACK_LOOP); - $mute = $config->get_bool(VideoFileHandlerConfig::PLAYBACK_MUTE); + global $config, $page; $width = "auto"; if ($image->width > 1) { @@ -25,31 +21,31 @@ public function display_image(Page $page, Image $image) $height = $image->height."px"; } - $html = "Video not playing? Click here to download the file.
      "; - - //Browser media format support: https://developer.mozilla.org/en-US/docs/Web/HTML/Supported_media_formats - - if (MimeType::matches_array($mime, VideoFileHandler::SUPPORTED_MIME)) { - if ($mime == MimeType::WEBM) { - //Several browsers still lack WebM support sadly: https://caniuse.com/#feat=webm - $html .= ""; - } + $html = emptyHTML( + "Video not playing? ", + A(['href' => $image->get_image_link()], "Click here"), + " to download the file.", + BR(), + VIDEO( + [ + 'controls' => true, + 'class' => 'shm-main-image', + 'id' => 'main_image', + 'alt' => 'main image', + 'poster' => make_http($image->get_thumb_link()), + 'autoplay' => $config->get_bool(VideoFileHandlerConfig::PLAYBACK_AUTOPLAY), + 'loop' => $config->get_bool(VideoFileHandlerConfig::PLAYBACK_LOOP), + 'muted' => $config->get_bool(VideoFileHandlerConfig::PLAYBACK_MUTE), + 'style' => "height: $height; width: $width; max-width: 100%; object-fit: contain; background-color: black;", + 'onloadstart' => 'this.volume = 0.25', + ], + SOURCE([ + 'src' => $image->get_image_link(), + 'type' => strtolower($image->get_mime()) + ]) + ) + ); - $autoplay = ($autoplay ? ' autoplay' : ''); - $loop = ($loop ? ' loop' : ''); - $mute = ($mute ? ' muted' : ''); - - $html .= " - - - "; - } else { - //This should never happen, but just in case let's have a fallback.. - $html = "Video type '$mime' not recognised"; - } $page->add_block(new Block("Video", $html, "main", 10)); } } diff --git a/ext/home/main.php b/ext/home/main.php index aa214ddff..8a02bce6d 100644 --- a/ext/home/main.php +++ b/ext/home/main.php @@ -52,12 +52,10 @@ private function get_body(): string } $counter_dir = $config->get_string('home_counter', 'default'); - $num_comma = ""; + $total = Search::count_images(); + $num_comma = number_format($total); $counter_text = ""; if ($counter_dir != 'none') { - $total = Image::count_images(); - $num_comma = number_format($total); - if ($counter_dir != 'text-only') { $strtotal = "$total"; $length = strlen($strtotal); diff --git a/ext/home/style.css b/ext/home/style.css index 7eb09c886..d7ff71995 100644 --- a/ext/home/style.css +++ b/ext/home/style.css @@ -1,11 +1,11 @@ -div#front-page h1 {font-size: 4em; margin-top: 2em; margin-bottom: 0; text-align: center; border: none; background: none; box-shadow: none; -webkit-box-shadow: none; -moz-box-shadow: none;} +div#front-page h1 {font-size: 4rem; margin-top: 2em; margin-bottom: 0; text-align: center; border: none; background: none; box-shadow: none; -webkit-box-shadow: none; -moz-box-shadow: none;} div#front-page {text-align:center;position:relative;top:4rem;} -.space {margin-bottom: 1em;} +div#front-page .space {margin-bottom: 1em;} div#front-page div#links a {margin: 0 0.5em;} div#front-page li {list-style-type: none; margin: 0;} @media (max-width: 800px) { - div#front-page h1 {font-size: 3em; margin-top: 0.5em; margin-bottom: 0.5em;} - #counter {display: none;} + div#front-page h1 {font-size: 3rem; margin-top: 0.5em; margin-bottom: 0.5em;} + div#front-page #counter {display: none;} } div#front-page > #search > form { margin: 0 auto; } diff --git a/ext/home/theme.php b/ext/home/theme.php index 4360e124f..e2b59e23f 100644 --- a/ext/home/theme.php +++ b/ext/home/theme.php @@ -38,7 +38,7 @@ public function build_body(string $sitename, string $main_links, string $main_te $search_html = "
      {$entry["date_sent"]}{$entry["message"]}
      - - + +
      Search
      Replace
      Search
      Replace
      @@ -56,16 +56,16 @@ public function get_tag_editor_html(Image $image): HTMLElement return SHM_POST_INFO( "Tags", - $user->can(Permissions::EDIT_IMAGE_TAG), joinHTML(", ", $tag_links), - INPUT([ + $user->can(Permissions::EDIT_IMAGE_TAG) ? TEXTAREA([ "class" => "autocomplete_tags", "type" => "text", "name" => "tag_edit__tags", - "value" => $image->get_tag_list(), "id" => "tag_editor", - "autocomplete" => "off" - ]) + ], $image->get_tag_list()) : null, + link: Extension::is_enabled(TagHistoryInfo::KEY) ? + make_link("tag_history/{$image->id}") : + null, ); } @@ -77,9 +77,8 @@ public function get_user_editor_html(Image $image): HTMLElement $ip = $user->can(Permissions::VIEW_IP) ? rawHTML(" (" . show_ip($image->owner_ip, "Post posted {$image->posted}") . ")") : ""; $info = SHM_POST_INFO( "Uploader", - $user->can(Permissions::EDIT_IMAGE_OWNER), emptyHTML(A(["class" => "username", "href" => make_link("user/$owner")], $owner), $ip, ", ", $date), - INPUT(["type" => "text", "name" => "tag_edit__owner", "value" => $owner]) + $user->can(Permissions::EDIT_IMAGE_OWNER) ? INPUT(["type" => "text", "name" => "tag_edit__owner", "value" => $owner]) : null ); // SHM_POST_INFO returns a TR, let's sneakily append // a TD with the avatar in it @@ -96,13 +95,13 @@ public function get_source_editor_html(Image $image): HTMLElement { global $user; return SHM_POST_INFO( - "Source", - $user->can(Permissions::EDIT_IMAGE_SOURCE), + "Source Link", DIV( ["style" => "overflow: hidden; white-space: nowrap; max-width: 350px; text-overflow: ellipsis;"], $this->format_source($image->get_source()) ), - INPUT(["type" => "text", "name" => "tag_edit__source", "value" => $image->get_source()]) + $user->can(Permissions::EDIT_IMAGE_SOURCE) ? INPUT(["type" => "text", "name" => "tag_edit__source", "value" => $image->get_source()]) : null, + link: Extension::is_enabled(SourceHistoryInfo::KEY) ? make_link("source_history/{$image->id}") : null, ); } @@ -127,9 +126,8 @@ public function get_lock_editor_html(Image $image): HTMLElement global $user; return SHM_POST_INFO( "Locked", - $user->can(Permissions::EDIT_IMAGE_LOCK), $image->is_locked() ? "Yes (Only admins may edit these details)" : "No", - INPUT(["type" => "checkbox", "name" => "tag_edit__locked", "checked" => $image->is_locked()]) + $user->can(Permissions::EDIT_IMAGE_LOCK) ? INPUT(["type" => "checkbox", "name" => "tag_edit__locked", "checked" => $image->is_locked()]) : null ); } } diff --git a/ext/tag_editcloud/style.css b/ext/tag_editcloud/style.css index 0c5b9566d..995d2d56a 100644 --- a/ext/tag_editcloud/style.css +++ b/ext/tag_editcloud/style.css @@ -1,4 +1,4 @@ -span.tag-selected { +.tageditcloud span.tag-selected { background:#88EE88; } diff --git a/ext/tag_history/main.php b/ext/tag_history/main.php index a748a5520..94da23e5f 100644 --- a/ext/tag_history/main.php +++ b/ext/tag_history/main.php @@ -346,7 +346,7 @@ public function process_revert_all_changes(?string $name, ?string $ip, ?string $ /** * This function is called just before an images tag are changed. * - * #param string[] $tags + * @param string[] $tags */ private function add_tag_history(Image $image, array $tags) { diff --git a/ext/tag_list/main.php b/ext/tag_list/main.php index ddea7eb07..9b77a1974 100644 --- a/ext/tag_list/main.php +++ b/ext/tag_list/main.php @@ -532,7 +532,7 @@ private function add_popular_block(Page $page) } /** - * #param string[] $search + * @param string[] $search */ private function add_refine_block(Page $page, array $search) { @@ -555,7 +555,6 @@ public static function get_related_tags(array $search, int $limit): array { global $cache, $database; - $wild_tags = $search; $cache_key = "related_tags:" . md5(Tag::implode($search)); $related_tags = $cache->get($cache_key); diff --git a/ext/upload/bookmarklet.js b/ext/upload/bookmarklet.js index 29c2945bf..bf22884f8 100644 --- a/ext/upload/bookmarklet.js +++ b/ext/upload/bookmarklet.js @@ -26,11 +26,10 @@ else if(CA === 2) { // New Tags /* * Danbooru2 - * jQuery should always active here, meaning we can use jQuery in this part of the bookmarklet. */ if(document.getElementById("image-container") !== null) { - var imageContainer = $('#image-container')[0]; + var imageContainer = document.querySelector('#image-container'); if (typeof tag !== "ftp://ftp." && chk !==1) { var tag = imageContainer.getAttribute('data-tags'); } @@ -40,9 +39,9 @@ if(document.getElementById("image-container") !== null) { var rating = imageContainer.getAttribute('data-rating'); - var fileinfo = $('#sidebar > section:eq(3) > ul > :contains("Size") > a'); - var furl = "http://" + document.location.hostname + fileinfo.attr('href'); - var fs = fileinfo.text().split(" "); + var fileinfo = document.querySelector('#sidebar > section:eq(3) > ul > :contains("Size") > a'); + var furl = "http://" + document.location.hostname + fileinfo.getAttribute('href'); + var fs = fileinfo.innerText.split(" "); var filesize = (fs[1] === "MB" ? fs[0] * 1024 : fs[0]); if(supext.search(furl.match("[a-zA-Z0-9]+$")[0]) !== -1){ diff --git a/ext/upload/main.php b/ext/upload/main.php index f22d55c41..bc53e1d05 100644 --- a/ext/upload/main.php +++ b/ext/upload/main.php @@ -58,6 +58,34 @@ class UploadException extends SCoreException { } +abstract class UploadResult +{ + public function __construct( + public string $name + ) { + } +} + +class UploadError extends UploadResult +{ + public function __construct( + string $name, + public string $error + ) { + parent::__construct($name); + } +} + +class UploadSuccess extends UploadResult +{ + public function __construct( + string $name, + public int $image_id + ) { + parent::__construct($name); + } +} + /** * Main upload class. * All files that are uploaded to the site are handled through this class. @@ -183,7 +211,7 @@ public function onPageRequest(PageRequestEvent $event) } } - if ($event->page_matches("upload/replace")) { + if ($event->page_matches("replace")) { if (!$user->can(Permissions::REPLACE_IMAGE)) { $this->theme->display_error(403, "Error", "{$user->name} doesn't have permission to replace images"); return; @@ -193,35 +221,23 @@ public function onPageRequest(PageRequestEvent $event) return; } - // Try to get the image ID - if ($event->count_args() >= 1) { - $image_id = int_escape($event->get_arg(0)); - } elseif (isset($_POST['image_id'])) { - $image_id = int_escape($_POST['image_id']); - } else { - throw new UploadException("Can not replace Post: No valid Post ID given."); - } + $image_id = int_escape($event->get_arg(0)); $image_old = Image::by_id($image_id); if (is_null($image_old)) { throw new UploadException("Can not replace Post: No post with ID $image_id"); } - $source = $_POST['source'] ?? null; - - if (!empty($_POST["url"])) { - $image_ids = $this->try_transload($_POST["url"], [], $source, $image_id); - $cache->delete("thumb-block:{$image_id}"); - $this->theme->display_upload_status($page, $image_ids); - } elseif (count($_FILES) > 0) { - $image_ids = $this->try_upload($_FILES["data"], [], $source, $image_id); - $cache->delete("thumb-block:{$image_id}"); - $this->theme->display_upload_status($page, $image_ids); - } elseif (!empty($_GET['url'])) { - $image_ids = $this->try_transload($_GET['url'], [], $source, $image_id); - $cache->delete("thumb-block:{$image_id}"); - $this->theme->display_upload_status($page, $image_ids); - } else { + if($event->method == "GET") { $this->theme->display_replace_page($page, $image_id); + } elseif($event->method == "POST") { + $results = []; + if (!empty($_POST["url"])) { + $results = $this->try_transload($_POST["url"], [], $_POST['source'] ?? null, $image_id); + } elseif (count($_FILES) > 0) { + $results = $this->try_upload($_FILES["data"], [], $_POST['source'] ?? null, $image_id); + } + $cache->delete("thumb-block:{$image_id}"); + $this->theme->display_upload_status($page, $results); } } elseif ($event->page_matches("upload")) { if (!$user->can(Permissions::CREATE_IMAGE)) { @@ -233,36 +249,32 @@ public function onPageRequest(PageRequestEvent $event) return; } - /* Regular Upload Image */ - if (count($_FILES) > 0 || count($_POST) > 0) { - $image_ids = []; - - foreach ($_FILES as $name => $file) { - $tags = $this->tags_for_upload_slot(int_escape(substr($name, 4))); - $source = $_POST['source'] ?? null; - $image_ids += $this->try_upload($file, $tags, $source); - } - foreach ($_POST as $name => $value) { - if (str_starts_with($name, "url") && strlen($value) > 0) { - $tags = $this->tags_for_upload_slot(int_escape(substr($name, 3))); - $source = $_POST['source'] ?? $value; - $image_ids += $this->try_transload($value, $tags, $source); - } + if($event->method == "GET") { + $this->theme->display_page($page); + } elseif($event->method == "POST") { + $results = []; + + $files = array_filter($_FILES, function ($file) { + return !empty($file['name']); + }); + foreach ($files as $name => $file) { + $slot = int_escape(substr($name, 4)); + $tags = $this->tags_for_upload_slot($slot); + $source = $this->source_for_upload_slot($slot); + $results = array_merge($results, $this->try_upload($file, $tags, $source)); } - $this->theme->display_upload_status($page, $image_ids); - } elseif (!empty($_GET['url'])) { - $url = $_GET['url']; - $source = $_GET['source'] ?? $url; - $tags = ['tagme']; - if (!empty($_GET['tags']) && $_GET['tags'] != "null") { - $tags = Tag::explode($_GET['tags']); + $urls = array_filter($_POST, function ($value, $key) { + return str_starts_with($key, "url") && strlen($value) > 0; + }, ARRAY_FILTER_USE_BOTH); + foreach ($urls as $name => $value) { + $slot = int_escape(substr($name, 3)); + $tags = $this->tags_for_upload_slot($slot); + $source = $this->source_for_upload_slot($slot); + $results = array_merge($results, $this->try_transload($value, $tags, $source)); } - $image_ids = $this->try_transload($url, $tags, $source); - $this->theme->display_upload_status($page, $image_ids); - } else { - $this->theme->display_page($page); + $this->theme->display_upload_status($page, $results); } } } @@ -278,6 +290,11 @@ private function tags_for_upload_slot(int $id): array ); } + private function source_for_upload_slot(int $id): ?string + { + return $_POST["source$id"] ?? $_POST['source'] ?? null; + } + /** * Returns a descriptive error message for the specified PHP error code. * @@ -310,8 +327,9 @@ private function upload_error_message(int $error_code): string /** * Handle an upload. - * #param string[] $file - * #param string[] $tags + * @param mixed[] $file + * @param string[] $tags + * @return UploadResult[] */ private function try_upload(array $file, array $tags, ?string $source = null, ?int $replace_id = null): array { @@ -326,61 +344,50 @@ private function try_upload(array $file, array $tags, ?string $source = null, ?i $source = null; } - $image_ids = []; + $results = []; - $num_files = count($file['name']); - $limit = $config->get_int(UploadConfig::COUNT); - try { - if ($num_files > $limit) { - throw new UploadException("Upload limited to $limit"); - } + for ($i = 0; $i < count($file['name']); $i++) { + $name = $file['name'][$i]; + $error = $file['error'][$i]; + $tmp_name = $file['tmp_name'][$i]; - for ($i = 0; $i < $num_files; $i++) { - if (empty($file['name'][$i])) { - continue; + if (empty($name)) { + continue; + } + try { + // check if the upload was successful + if ($error !== UPLOAD_ERR_OK) { + throw new UploadException($this->upload_error_message($error)); } - try { - // check if the upload was successful - if ($file['error'][$i] !== UPLOAD_ERR_OK) { - throw new UploadException($this->upload_error_message($file['error'][$i])); - } - - $metadata = []; - $metadata['filename'] = pathinfo($file['name'][$i], PATHINFO_BASENAME); - $metadata['tags'] = $tags; - $metadata['source'] = $source; - - $event = new DataUploadEvent($file['tmp_name'][$i], $metadata, $replace_id); - send_event($event); - if ($event->image_id == -1) { - throw new UploadException("MIME type not supported: " . $event->mime); - } - $image_ids[] = $event->image_id; - $page->add_http_header("X-Shimmie-Post-ID: " . $event->image_id); - } catch (UploadException $ex) { - $this->theme->display_upload_error( - $page, - "Error with " . html_escape($file['name'][$i]), - $ex->getMessage() - ); + + $metadata = []; + $metadata['filename'] = pathinfo($name, PATHINFO_BASENAME); + $metadata['tags'] = $tags; + $metadata['source'] = $source; + + $event = new DataUploadEvent($tmp_name, $metadata, $replace_id); + send_event($event); + if ($event->image_id == -1) { + throw new UploadException("MIME type not supported: " . $event->mime); } + $results[] = new UploadSuccess($name, $event->image_id); + $page->add_http_header("X-Shimmie-Post-ID: " . $event->image_id); + } catch (UploadException $ex) { + $results[] = new UploadError($name, $ex->getMessage()); } - } catch (UploadException $ex) { - $this->theme->display_upload_error( - $page, - "Error with upload", - $ex->getMessage() - ); } - return $image_ids; + return $results; } + /** + * @return UploadResult[] + */ private function try_transload(string $url, array $tags, string $source = null, ?int $replace_id = null): array { global $page, $config, $user; - $image_ids = []; + $results = []; $tmp_filename = tempnam(ini_get('upload_tmp_dir'), "shimmie_transload"); try { @@ -417,19 +424,15 @@ private function try_transload(string $url, array $tags, string $source = null, if ($event->image_id == -1) { throw new UploadException("File type not supported: " . $event->mime); } - $image_ids[] = $event->image_id; + $results[] = new UploadSuccess($url, $event->image_id); } catch (UploadException $ex) { - $this->theme->display_upload_error( - $page, - "Error with " . html_escape($url), - $ex->getMessage() - ); + $results[] = new UploadError($url, $ex->getMessage()); } finally { if (file_exists($tmp_filename)) { unlink($tmp_filename); } } - return $image_ids; + return $results; } } diff --git a/ext/upload/minus.png b/ext/upload/minus.png deleted file mode 100644 index 57c86dec5..000000000 Binary files a/ext/upload/minus.png and /dev/null differ diff --git a/ext/upload/plus.png b/ext/upload/plus.png deleted file mode 100644 index d7ec0ae30..000000000 Binary files a/ext/upload/plus.png and /dev/null differ diff --git a/ext/upload/script.js b/ext/upload/script.js new file mode 100644 index 000000000..cae836789 --- /dev/null +++ b/ext/upload/script.js @@ -0,0 +1,56 @@ +function fileSize(size) { + var i = Math.floor(Math.log(size) / Math.log(1024)); + return (size / Math.pow(1024, i)).toFixed(2) * 1 + ['B', 'kB', 'MB', 'GB', 'TB'][i]; +} +function updateTracker() { + var size = 0; + var upbtn = document.getElementById("uploadbutton"); + var tracker = document.getElementById("upload_size_tracker"); + var lockbtn = false; + + // check that each individual file is less than the max file size + document.querySelectorAll("#large_upload_form input[type='file']").forEach((input) => { + var cancelbtn = document.getElementById("cancel"+input.id); + var toobig = false; + if (input.files.length) { + if(cancelbtn) cancelbtn.style.visibility = 'visible'; + for (var i = 0; i < input.files.length; i++) { + size += input.files[i].size + 1024; // extra buffer for metadata + if (window.shm_max_size > 0 && input.files[i].size > window.shm_max_size) { + toobig = true; + } + } + if (toobig) { + lockbtn = true; + input.style = 'color:red'; + } else { + input.style = 'color:initial'; + } + } else { + if(cancelbtn) cancelbtn.style.visibility = 'hidden'; + input.style = 'color:initial'; + } + }); + + // check that the total is less than the max total size + if (size) { + tracker.innerText = fileSize(size); + if (window.shm_max_total_size > 0 && size > window.shm_max_total_size) { + lockbtn = true; + tracker.style = 'color:red'; + } else { + tracker.style = 'color:initial'; + } + } else { + tracker.innerText = '0MB'; + } + upbtn.disabled = lockbtn; +} +document.addEventListener('DOMContentLoaded', () => { + if(document.getElementById("upload_size_tracker")) { + document.querySelectorAll("#large_upload_form input[type='file']").forEach((el) => { + el.addEventListener('change', updateTracker); + }); + updateTracker(); + } +}); diff --git a/ext/upload/style.css b/ext/upload/style.css index d6d803849..6dd19550d 100644 --- a/ext/upload/style.css +++ b/ext/upload/style.css @@ -1,17 +1,8 @@ -/* Only need to change the file/url inputs */ -#large_upload_form INPUT.wid { - width: 100%; -} -#radio_button { - width: auto; -} -#wrapper { - opacity: 0.4; - filter: alpha(opacity=40); /* msie */ +#large_upload_form TD, +#large_upload_form TH { + vertical-align: middle; } -/* This is needed since the theme style.css forcibly sets vertical align to "top". */ -TABLE.vert TD, TABLE.vert TH {vertical-align: middle;} .mini_upload INPUT { width: 100%; } diff --git a/ext/upload/test.php b/ext/upload/test.php index 9e12f99e0..be099ba6f 100644 --- a/ext/upload/test.php +++ b/ext/upload/test.php @@ -67,7 +67,7 @@ public function testRawReplace() ] ]; - $page = $this->post_page("upload/replace", ["image_id" => $image_id]); + $page = $this->post_page("replace/$image_id"); $this->assert_response(302); $this->assertEquals("/test/post/view/$image_id", $page->redirect); diff --git a/ext/upload/theme.php b/ext/upload/theme.php index 77ba47c0b..78ee4005a 100644 --- a/ext/upload/theme.php +++ b/ext/upload/theme.php @@ -17,13 +17,12 @@ use function MicroHTML\DIV; use function MicroHTML\BR; use function MicroHTML\A; +use function MicroHTML\SPAN; use function MicroHTML\P; class UploadTheme extends Themelet { - protected bool $has_errors = false; - public function display_block(Page $page): void { $b = new Block("Upload", (string)$this->build_upload_block(), "left", 20); @@ -43,89 +42,41 @@ public function display_page(Page $page): void $tl_enabled = ($config->get_string(UploadConfig::TRANSLOAD_ENGINE, "none") != "none"); $max_size = $config->get_int(UploadConfig::SIZE); $max_kb = to_shorthand_int($max_size); - $max_total_size = parse_shorthand_int(ini_get('post_max_size')) - 102400; //leave room for http request data + $max_total_size = parse_shorthand_int(ini_get('post_max_size')); $max_total_kb = to_shorthand_int($max_total_size); - $upload_list = $this->h_upload_list_1(); + $upload_list = $this->build_upload_list(); $form = SHM_FORM("upload", "POST", true, "file_upload"); $form->appendChild( TABLE( - ["id" => "large_upload_form", "class" => "vert"], + ["id" => "large_upload_form"], TR( TD(["width" => "20"], rawHTML("Common Tags")), - TD(["colspan" => "5"], INPUT(["name" => "tags", "type" => "text", "placeholder" => "tagme", "class" => "autocomplete_tags", "autocomplete" => "off"])) + TD(["colspan" => "6"], INPUT(["name" => "tags", "type" => "text", "placeholder" => "tagme", "class" => "autocomplete_tags"])) ), TR( TD(["width" => "20"], rawHTML("Common Source")), - TD(["colspan" => "5"], INPUT(["name" => "source", "type" => "text"])) + TD(["colspan" => "6"], INPUT(["name" => "source", "type" => "text", "placeholder" => "https://..."])) ), $upload_list, TR( - TD(["colspan" => $tl_enabled ? 2 : 4,"id" => "upload_size_tracker"], ""), - TD(["colspan" => 2], ""), - ), - TR( - TD(["colspan" => "6"], INPUT(["id" => "uploadbutton", "type" => "submit", "value" => "Post"])) + TD(["colspan" => "7"], INPUT(["id" => "uploadbutton", "type" => "submit", "value" => "Post"])) ), ) ); $html = emptyHTML( $form, - SMALL("(Max file size is $max_kb)"), - SMALL(BR(), "(Max total size is $max_total_kb)"), + SMALL( + "(", + $max_size > 0 ? "Per-file limit: $max_kb" : null, + $max_total_size > 0 ? " / Total limit: $max_total_kb" : null, + " / Current total: ", + SPAN(["id" => "upload_size_tracker"], "0KB"), + ")" + ), rawHTML("") ); @@ -134,11 +85,11 @@ function updateTracker(){ $page->add_block(new NavBlock()); $page->add_block(new Block("Upload", $html, "main", 20)); if ($tl_enabled) { - $page->add_block(new Block("Bookmarklets", (string)$this->h_bookmarklets(), "left", 20)); + $page->add_block(new Block("Bookmarklets", $this->build_bookmarklets(), "left", 20)); } } - protected function h_upload_list_1(): HTMLElement + protected function build_upload_list(): HTMLElement { global $config; $upload_list = emptyHTML(); @@ -148,18 +99,53 @@ protected function h_upload_list_1(): HTMLElement $upload_list->appendChild( TR( - TD(["colspan" => $tl_enabled ? 2 : 4], "Files"), - $tl_enabled ? TD(["colspan" => "2"], "URLs") : emptyHTML(), - TD(["colspan" => "2"], "Post-Specific Tags"), + TD(["colspan" => 2], "Select File"), + TD($tl_enabled ? "or URL" : null), + TD("Post-Specific Tags"), + TD("Post-Specific Source"), ) ); for ($i = 0; $i < $upload_count; $i++) { $upload_list->appendChild( TR( - TD(["colspan" => $tl_enabled ? 2 : 4], DIV(["name" => "canceldata{$i}[]","style" => "display:inline;margin-right:5px;font-size:15px;visibility:hidden;","onclick" => "$(\"input[name='data{$i}[]']\")[0].value='';updateTracker();"], "✖"), INPUT(["type" => "file", "name" => "data{$i}[]", "accept" => $accept, "multiple" => true])), - $tl_enabled ? TD(["colspan" => "2"], INPUT(["type" => "text", "name" => "url{$i}"])) : emptyHTML(), - TD(["colspan" => "2"], INPUT(["type" => "text", "name" => "tags{$i}", "class" => "autocomplete_tags", "autocomplete" => "off"])), + TD( + ["colspan" => 2, "style" => "white-space: nowrap;"], + DIV([ + "id" => "canceldata{$i}", + "style" => "display:inline;margin-right:5px;font-size:15px;visibility:hidden;", + "onclick" => "document.getElementById('data{$i}').value='';updateTracker();", + ], "✖"), + INPUT([ + "type" => "file", + "id" => "data{$i}", + "name" => "data{$i}[]", + "accept" => $accept, + "multiple" => true, + ]), + ), + TD( + $tl_enabled ? INPUT([ + "type" => "text", + "name" => "url{$i}", + "value" => ($i == 0) ? @$_GET['url'] : null, + ]) : null + ), + TD( + INPUT([ + "type" => "text", + "name" => "tags{$i}", + "class" => "autocomplete_tags", + "value" => ($i == 0) ? @$_GET['tags'] : null, + ]) + ), + TD( + INPUT([ + "type" => "text", + "name" => "source{$i}", + "value" => ($i == 0) ? @$_GET['source'] : null, + ]) + ), ) ); } @@ -167,7 +153,7 @@ protected function h_upload_list_1(): HTMLElement return $upload_list; } - protected function h_bookmarklets(): HTMLElement + protected function build_bookmarklets(): HTMLElement { global $config; $link = make_http(make_link("upload")); @@ -217,7 +203,7 @@ function() { '; $html2 = P( A(["href" => $js], $title), - rawHTML("(Click when looking at a post page. Works on sites running Shimmie / Danbooru / Gelbooru. (This also grabs the tags / rating / source!))"), + rawHTML(" (Click when looking at a post page. Works on sites running Shimmie / Danbooru / Gelbooru. (This also grabs the tags / rating / source!))"), ); return emptyHTML($html1, $html2); @@ -242,7 +228,7 @@ public function display_replace_page(Page $page, int $image_id) $upload_list->appendChild( TR( TD("or URL"), - TD(INPUT(["name" => "url", "type" => "text"])) + TD(INPUT(["name" => "url", "type" => "text", "value" => @$_GET['url']])) ) ); } @@ -253,11 +239,10 @@ public function display_replace_page(Page $page, int $image_id) $image = Image::by_id($image_id); $thumbnail = $this->build_thumb_html($image); - $form = SHM_FORM("upload/replace/".$image_id, "POST", true); + $form = SHM_FORM("replace/".$image_id, "POST", true); $form->appendChild(emptyHTML( - INPUT(["type" => "hidden", "name" => "image_id", "value" => $image_id]), TABLE( - ["id" => "large_upload_form", "class" => "vert"], + ["id" => "large_upload_form"], $upload_list, TR(TD("Source"), TD(["colspan" => 3], INPUT(["name" => "source", "type" => "text"]))), TR(TD(["colspan" => 4], INPUT(["id" => "uploadbutton", "type" => "submit", "value" => "Post"]))), @@ -273,7 +258,7 @@ public function display_replace_page(Page $page, int $image_id) $thumbnail, BR(), $form, - SMALL("(Max file size is $max_kb)"), + $max_size > 0 ? SMALL("(Max file size is $max_kb)") : null, ); $page->set_title("Replace Post"); @@ -282,37 +267,40 @@ public function display_replace_page(Page $page, int $image_id) $page->add_block(new Block("Upload Replacement Post", $html, "main", 20)); } - public function display_upload_status(Page $page, array $image_ids): void + /** + * @param UploadResult[] $results + */ + public function display_upload_status(Page $page, array $results): void { global $user; - if ($this->has_errors) { + /** @var UploadSuccess[] */ + $successes = array_filter($results, fn ($r) => is_a($r, UploadSuccess::class)); + + /** @var UploadError[] */ + $errors = array_filter($results, fn ($r) => is_a($r, UploadError::class)); + + if (count($errors) > 0) { $page->set_title("Upload Status"); $page->set_heading("Upload Status"); $page->add_block(new NavBlock()); - } else { - if (count($image_ids) < 1) { - $page->set_title("No images uploaded"); - $page->set_heading("No images uploaded"); - $page->add_block(new NavBlock()); - } elseif (count($image_ids) == 1) { - $page->set_mode(PageMode::REDIRECT); - $page->set_redirect(make_link("post/view/{$image_ids[0]}")); - } else { - $page->set_mode(PageMode::REDIRECT); - $page->set_redirect(search_link(["poster={$user->name}"])); + foreach($errors as $error) { + $page->add_block(new Block($error->name, format_text($error->error))); } + } elseif (count($successes) == 0) { + $page->set_title("No images uploaded"); + $page->set_heading("No images uploaded"); + $page->add_block(new NavBlock()); + $page->add_block(new Block("No images uploaded", "Upload attempted, but nothing succeeded and nothing failed?")); + } elseif (count($successes) == 1) { + $page->set_mode(PageMode::REDIRECT); + $page->set_redirect(make_link("post/view/{$successes[0]->image_id}")); + } else { + $page->set_mode(PageMode::REDIRECT); + $page->set_redirect(search_link(["poster={$user->name}"])); } } - public function display_upload_error(Page $page, string $title, string $message): void - { - // this message has intentional HTML in it... - $message = str_contains($message, "already has hash") ? $message : html_escape($message); - $page->add_block(new Block($title, $message)); - $this->has_errors = true; - } - protected function build_upload_block(): HTMLElement { global $config; @@ -329,7 +317,7 @@ protected function build_upload_block(): HTMLElement $form->appendChild( emptyHTML( INPUT(["id" => "data[]", "name" => "data[]", "size" => "16", "type" => "file", "accept" => $accept, "multiple" => true]), - INPUT(["name" => "tags", "type" => "text", "placeholder" => "tagme", "class" => "autocomplete_tags", "required" => true, "autocomplete" => "off"]), + INPUT(["name" => "tags", "type" => "text", "placeholder" => "tagme", "class" => "autocomplete_tags", "required" => true]), INPUT(["type" => "submit", "value" => "Post"]), ) ); @@ -337,8 +325,8 @@ protected function build_upload_block(): HTMLElement return DIV( ["class" => 'mini_upload'], $form, - SMALL("(Max file size is $max_kb)"), - SMALL(BR(), "(Max total size is $max_total_kb)"), + $max_size > 0 ? SMALL("(Max file size is $max_kb)") : null, + $max_total_size > 0 ? SMALL(BR(), "(Max total size is $max_total_kb)") : null, NOSCRIPT(BR(), A(["href" => make_link("upload")], "Larger Form")) ); } diff --git a/ext/user/main.php b/ext/user/main.php index ce2c97334..9a3884f26 100644 --- a/ext/user/main.php +++ b/ext/user/main.php @@ -149,6 +149,7 @@ public function onInitExt(InitExtEvent $event) $config->set_default_string("avatar_gravatar_default", ""); $config->set_default_string("avatar_gravatar_rating", "g"); $config->set_default_bool("login_tac_bbcode", true); + $config->set_default_bool("user_email_required", true); } public function onUserLogin(UserLoginEvent $event) @@ -347,6 +348,7 @@ public function onSetupBuilding(SetupBuildingEvent $event) $sb->start_table(); $sb->add_bool_option(UserConfig::ENABLE_API_KEYS, "Enable user API keys", true); $sb->add_bool_option("login_signup_enabled", "Allow new signups", true); + $sb->add_bool_option("user_email_required", "Require email address", true); $sb->add_longtext_option("login_tac", "Terms & Conditions", true); $sb->add_choice_option( "user_loginshowprofile", @@ -423,11 +425,12 @@ public function onAdminBuilding(AdminBuildingEvent $event) public function onUserCreation(UserCreationEvent $event) { + global $config, $page, $user; + $name = $event->username; //$pass = $event->password; //$email = $event->email; - global $config, $page, $user; if (!$user->can(Permissions::CREATE_USER)) { throw new UserCreationException("Account creation is currently disabled"); } @@ -452,6 +455,12 @@ public function onUserCreation(UserCreationEvent $event) if ($event->password != $event->password2) { throw new UserCreationException("Passwords don't match"); } + if( + $user->can(Permissions::CREATE_OTHER_USER) || + ($config->get_bool("user_email_required") && empty($event->email)) + ) { + throw new UserCreationException("Email address is required"); + } $new_user = $this->create_user($event); if ($event->login) { diff --git a/ext/user/theme.php b/ext/user/theme.php index dbba5ed74..d0997c258 100644 --- a/ext/user/theme.php +++ b/ext/user/theme.php @@ -63,14 +63,18 @@ public function display_user_block(Page $page, User $user, $parts) public function display_signup_page(Page $page) { - global $config; + global $config, $user; $tac = $config->get_string("login_tac", ""); if ($config->get_bool("login_tac_bbcode")) { - $tfe = send_event(new TextFormattingEvent($tac)); - $tac = $tfe->formatted; + $tac = send_event(new TextFormattingEvent($tac))->formatted; } + $email_required = ( + $config->get_bool("user_email_required") && + !$user->can(Permissions::CREATE_OTHER_USER) + ); + $form = SHM_SIMPLE_FORM( "user_admin/create", TABLE( @@ -89,8 +93,8 @@ public function display_signup_page(Page $page) TD(INPUT(["type" => 'password', "name" => 'pass2', "required" => true])) ), TR( - TH(rawHTML("Email (Optional)")), - TD(INPUT(["type" => 'email', "name" => 'email'])) + TH($email_required ? "Email" : rawHTML("Email (Optional)")), + TD(INPUT(["type" => 'email', "name" => 'email', "required" => $email_required])) ), TR( TD(["colspan" => "2"], rawHTML(captcha_get_html())) @@ -135,9 +139,12 @@ public function display_user_creator() TD(INPUT(["type" => 'password', "name" => 'pass2', "required" => true])) ), TR( - TH(rawHTML("Email (Optional)")), + TH(rawHTML("Email")), TD(INPUT(["type" => 'email', "name" => 'email'])) ), + TR( + TD(["colspan" => 2], rawHTML("(Email is optional for admin-created accounts)")), + ), ), TFOOT( TR(TD(["colspan" => "2"], INPUT(["type" => "submit", "value" => "Create Account"]))) @@ -159,6 +166,11 @@ public function display_signups_disabled(Page $page) } public function display_login_block(Page $page) + { + $page->add_block(new Block("Login", $this->create_login_block(), "left", 90)); + } + + public function create_login_block(): HTMLElement { global $config, $user; $form = SHM_SIMPLE_FORM( @@ -187,7 +199,7 @@ public function display_login_block(Page $page) $html->appendChild(SMALL(A(["href" => make_link("user_admin/create")], "Create Account"))); } - $page->add_block(new Block("Login", $html, "left", 90)); + return $html; } private function _ip_list(string $name, array $ips): HTMLElement diff --git a/ext/user_config/style.css b/ext/user_config/style.css deleted file mode 100644 index bc460fa4e..000000000 --- a/ext/user_config/style.css +++ /dev/null @@ -1,43 +0,0 @@ -.setupblocks { - column-width: 400px; - -moz-column-width: 400px; - -webkit-column-width: 400px; - max-width: 1200px; - margin: auto; -} -.setupblocks > .setupblock:first-of-type { margin-top: 0; } - -.setupblock { - break-inside: avoid; - -moz-break-inside: avoid; - -webkit-break-inside: avoid; - column-break-inside: avoid; - -moz-column-break-inside: avoid; - -webkit-column-break-inside: avoid; - text-align: center; - width: 90%; -} -.setupblock TEXTAREA { - width: 100%; - font-size: 0.75em; - resize: vertical; -} - -.helpable { - border-bottom: 1px dashed gray; -} - -.ok { - background: #AFA; -} -.bad { - background: #FAA; -} - -#Setupmain .blockbody { - background: none; - border: none; - box-shadow: none; - margin: 0; - padding: 0; -} diff --git a/ext/view/info.php b/ext/view/info.php index 27602aa08..e6cbd218f 100644 --- a/ext/view/info.php +++ b/ext/view/info.php @@ -4,7 +4,7 @@ namespace Shimmie2; -class ViewImageInfo extends ExtensionInfo +class ViewPostInfo extends ExtensionInfo { public const KEY = "view"; diff --git a/ext/view/main.php b/ext/view/main.php index 52e674fb2..fbed253cd 100644 --- a/ext/view/main.php +++ b/ext/view/main.php @@ -13,20 +13,20 @@ use function MicroHTML\TH; use function MicroHTML\TD; -class ViewImage extends Extension +class ViewPost extends Extension { - /** @var ViewImageTheme */ + /** @var ViewPostTheme */ protected Themelet $theme; public function onPageRequest(PageRequestEvent $event) { global $page, $user; - if ($event->page_matches("post/prev") || $event->page_matches("post/next")) { + if ($event->page_matches("post/prev") || $event->page_matches("post/next")) { $image_id = int_escape($event->get_arg(0)); if (isset($_GET['search'])) { - $search_terms = Tag::explode(Tag::decaret($_GET['search'])); + $search_terms = Tag::explode($_GET['search']); $query = "#search=".url_escape($_GET['search']); } else { $search_terms = []; @@ -123,7 +123,7 @@ public function onImageInfoBoxBuilding(ImageInfoBoxBuildingEvent $event) global $config; $image_info = $config->get_string(ImageConfig::INFO); if ($image_info) { - $event->add_part(SHM_POST_INFO("Info", false, $event->image->get_info()), 85); + $event->add_part(SHM_POST_INFO("Info", $event->image->get_info()), 85); } } } diff --git a/ext/view/script.js b/ext/view/script.js index 3c8799f3e..ed459c012 100644 --- a/ext/view/script.js +++ b/ext/view/script.js @@ -6,24 +6,35 @@ function joinUrlSegments(base, query) { return base + separatorChar + query; } +function clearViewMode() { + document.querySelectorAll('.image_info').forEach((element) => { + element.classList.remove('infomode-view'); + }); +} + +function updateAttr(selector, attr, value) { + document.querySelectorAll(selector).forEach(function(e) { + let current = e.getAttribute(attr); + let newval = joinUrlSegments(current, value); + e.setAttribute(attr, newval); + }); +} + document.addEventListener('DOMContentLoaded', () => { + // find elements with class image_info and set them to view mode + // (by default, with no js, they are in edit mode - so that no-js + // users can still edit them) + document.querySelectorAll('.image_info').forEach((element) => { + element.classList.add('infomode-view'); + }); + if(document.location.hash.length > 3) { var query = document.location.hash.substring(1); - $('LINK#prevlink').attr('href', function(i, attr) { - return joinUrlSegments(attr,query); - }); - $('LINK#nextlink').attr('href', function(i, attr) { - return joinUrlSegments(attr,query); - }); - $('A#prevlink').attr('href', function(i, attr) { - return joinUrlSegments(attr,query); - }); - $('A#nextlink').attr('href', function(i, attr) { - return joinUrlSegments(attr,query); - }); - $('span#image_delete_form form').attr('action', function(i, attr) { - return joinUrlSegments(attr,query); - }); + updateAttr("LINK#prevlink", "href", query); + updateAttr("LINK#nextlink", "href", query); + updateAttr("A#prevlink", "href", query); + updateAttr("A#nextlink", "href", query); + updateAttr("span#image_delete_form form", "action", query); } }); diff --git a/ext/view/style.css b/ext/view/style.css index d7d7c2c00..b321d98e0 100644 --- a/ext/view/style.css +++ b/ext/view/style.css @@ -1,15 +1,19 @@ - -.js .image_info .edit { - display: none; -} -.js .image_info .view { - display: block; +TABLE.form.image_info { + width: 550px; + max-width: 100%; } -.no-js .image_info .edit { +.image_info .edit { display: block; } -.no-js .image_info .view { +.image_info .view { display: none; } +.image_info.infomode-view .edit { + display: none; +} +.image_info.infomode-view .view { + display: block; +} + diff --git a/ext/view/test.php b/ext/view/test.php index 320270522..fc6898a07 100644 --- a/ext/view/test.php +++ b/ext/view/test.php @@ -4,7 +4,7 @@ namespace Shimmie2; -class ViewImageTest extends ShimmiePHPUnitTestCase +class ViewPostTest extends ShimmiePHPUnitTestCase { public function setUp(): void { diff --git a/ext/view/theme.php b/ext/view/theme.php index f41b17d61..657a5404f 100644 --- a/ext/view/theme.php +++ b/ext/view/theme.php @@ -4,7 +4,11 @@ namespace Shimmie2; -class ViewImageTheme extends Themelet +use MicroHTML\HTMLElement; + +use function MicroHTML\{A, joinHTML, TABLE, TR, TD, INPUT, emptyHTML}; + +class ViewPostTheme extends Themelet { public function display_meta_headers(Image $image) { @@ -45,21 +49,21 @@ public function display_admin_block(Page $page, $parts) protected function get_query(): ?string { if (isset($_GET['search'])) { - $query = "search=".url_escape(Tag::caret($_GET['search'])); + $query = "search=".url_escape($_GET['search']); } else { $query = null; } return $query; } - protected function build_pin(Image $image): string + protected function build_pin(Image $image): HTMLElement { $query = $this->get_query(); - $h_prev = "Prev"; - $h_index = "Index"; - $h_next = "Next"; - - return "$h_prev | $h_index | $h_next"; + return joinHTML(" | ", [ + A(["href" => make_link("post/prev/{$image->id}", $query), "id" => "prevlink"], "Prev"), + A(["href" => make_link()], "Index"), + A(["href" => make_link("post/next/{$image->id}", $query), "id" => "nextlink"], "Next"), + ]); } protected function build_navigation(Image $image): string @@ -68,7 +72,7 @@ protected function build_navigation(Image $image): string $h_search = "

      - +
      "; @@ -76,36 +80,34 @@ protected function build_navigation(Image $image): string return "$h_pin
      $h_search"; } - protected function build_info(Image $image, $editor_parts): string + protected function build_info(Image $image, $editor_parts): HTMLElement { global $user; if (count($editor_parts) == 0) { - return ($image->is_locked() ? "
      [Post Locked]" : ""); + return emptyHTML($image->is_locked() ? "[Post Locked]" : ""); } - $html = make_form(make_link("post/set"))." - - - "; - foreach ($editor_parts as $part) { - $html .= $part; - } - if ( + if( (!$image->is_locked() || $user->can(Permissions::EDIT_IMAGE_LOCK)) && $user->can(Permissions::EDIT_IMAGE_TAG) ) { - $html .= " - - "; + $editor_parts[] = TR(TD( + ["colspan" => 4], + INPUT(["class" => "view", "type" => "button", "value" => "Edit", "onclick" => "clearViewMode()"]), + INPUT(["class" => "edit", "type" => "submit", "value" => "Set"]) + )); } - $html .= " -
      - - -
      - - "; - return $html; + + return SHM_SIMPLE_FORM( + "post/set", + INPUT(["type" => "hidden", "name" => "image_id", "value" => $image->id]), + TABLE( + [ + "class" => "image_info form", + ], + ...$editor_parts, + ), + ); } } diff --git a/index.php b/index.php index 7aebad1c4..1cc8e2c02 100644 --- a/index.php +++ b/index.php @@ -50,9 +50,7 @@ $cache = loadCache(CACHE_DSN); $database = new Database(DATABASE_DSN); $config = new DatabaseConfig($database); -ExtensionInfo::load_all_extension_info(); -Extension::determine_enabled_extensions(); -require_all(zglob("ext/{".Extension::get_enabled_extensions_as_string()."}/main.php")); +_load_extension_files(); _load_theme_files(); $page = new Page(); _load_event_listeners(); @@ -84,7 +82,7 @@ if (PHP_SAPI === 'cli' || PHP_SAPI == 'phpdbg') { send_event(new CommandEvent($argv)); } else { - send_event(new PageRequestEvent(_get_query())); + send_event(new PageRequestEvent($_SERVER['REQUEST_METHOD'], _get_query())); $page->display(); } diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 2cd651ef3..05dcb4979 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -4,8 +4,6 @@ namespace Shimmie2; -use PHPUnit\Framework\TestCase; - chdir(dirname(dirname(__FILE__))); require_once "core/sanitize_php.php"; require_once "vendor/autoload.php"; @@ -15,8 +13,8 @@ require_once "core/util.php"; $_SERVER['QUERY_STRING'] = '/'; -if (file_exists("tests/trace.json")) { - unlink("tests/trace.json"); +if (file_exists("data/test-trace.json")) { + unlink("data/test-trace.json"); } global $cache, $config, $database, $user, $page, $_tracer; @@ -26,242 +24,17 @@ $_tracer->begin("bootstrap"); _load_core_files(); $cache = loadCache(CACHE_DSN); -$dsn = getenv("TEST_DSN"); -$database = new Database($dsn ? $dsn : "sqlite::memory:"); +$database = new Database(getenv("TEST_DSN") ?: "sqlite::memory:"); create_dirs(); create_tables($database); $config = new DatabaseConfig($database); -ExtensionInfo::load_all_extension_info(); -Extension::determine_enabled_extensions(); -require_all(zglob("ext/{".Extension::get_enabled_extensions_as_string()."}/main.php")); +_load_extension_files(); _load_theme_files(); $page = new Page(); _load_event_listeners(); -$config->set_string("thumb_engine", "static"); # GD has less overhead per-call +$config->set_string("thumb_engine", "static"); $config->set_bool("nice_urls", true); send_event(new DatabaseUpgradeEvent()); send_event(new InitExtEvent()); $user = User::by_id($config->get_int("anon_id", 0)); $_tracer->end(); - -abstract class ShimmiePHPUnitTestCase extends TestCase -{ - protected static string $anon_name = "anonymous"; - protected static string $admin_name = "demo"; - protected static string $user_name = "test"; - protected string $wipe_time = "test"; - - public static function setUpBeforeClass(): void - { - parent::setUpBeforeClass(); - global $_tracer; - $_tracer->begin(get_called_class()); - - self::create_user(self::$admin_name); - self::create_user(self::$user_name); - } - - public function setUp(): void - { - global $database, $_tracer; - $_tracer->begin($this->getName()); - $_tracer->begin("setUp"); - $class = str_replace("Test", "", get_class($this)); - if (!ExtensionInfo::get_for_extension_class($class)->is_supported()) { - $this->markTestSkipped("$class not supported with this database"); - } - - // Set up a clean environment for each test - self::log_out(); - foreach ($database->get_col("SELECT id FROM images") as $image_id) { - send_event(new ImageDeletionEvent(Image::by_id((int)$image_id), true)); - } - - $_tracer->end(); # setUp - $_tracer->begin("test"); - } - - public function tearDown(): void - { - global $_tracer; - $_tracer->end(); # test - $_tracer->end(); # $this->getName() - $_tracer->clear(); - $_tracer->flush("tests/trace.json"); - } - - public static function tearDownAfterClass(): void - { - parent::tearDownAfterClass(); - global $_tracer; - $_tracer->end(); # get_called_class() - } - - protected static function create_user(string $name): void - { - if (is_null(User::by_name($name))) { - $userPage = new UserPage(); - $userPage->onUserCreation(new UserCreationEvent($name, $name, $name, "", false)); - assert(!is_null(User::by_name($name)), "Creation of user $name failed"); - } - } - - private static function check_args(?array $args): array - { - if (!$args) { - return []; - } - foreach ($args as $k => $v) { - if (is_array($v)) { - $args[$k] = $v; - } else { - $args[$k] = (string)$v; - } - } - return $args; - } - - protected static function request($page_name, $get_args = null, $post_args = null): Page - { - // use a fresh page - global $page; - $get_args = self::check_args($get_args); - $post_args = self::check_args($post_args); - - if (str_contains($page_name, "?")) { - throw new \RuntimeException("Query string included in page name"); - } - $_SERVER['REQUEST_URI'] = make_link($page_name, http_build_query($get_args)); - $_GET = $get_args; - $_POST = $post_args; - $page = new Page(); - send_event(new PageRequestEvent($page_name)); - if ($page->mode == PageMode::REDIRECT) { - $page->code = 302; - } - return $page; - } - - protected static function get_page($page_name, $args = null): Page - { - return self::request($page_name, $args, null); - } - - protected static function post_page($page_name, $args = null): Page - { - return self::request($page_name, null, $args); - } - - // page things - protected function assert_title(string $title): void - { - global $page; - $this->assertStringContainsString($title, $page->title); - } - - protected function assert_title_matches($title): void - { - global $page; - $this->assertStringMatchesFormat($title, $page->title); - } - - protected function assert_no_title(string $title): void - { - global $page; - $this->assertStringNotContainsString($title, $page->title); - } - - protected function assert_response(int $code): void - { - global $page; - $this->assertEquals($code, $page->code); - } - - protected function page_to_text(string $section = null): string - { - global $page; - if ($page->mode == PageMode::PAGE) { - $text = $page->title . "\n"; - foreach ($page->blocks as $block) { - if (is_null($section) || $section == $block->section) { - $text .= $block->header . "\n"; - $text .= $block->body . "\n\n"; - } - } - return $text; - } elseif ($page->mode == PageMode::DATA) { - return $page->data; - } else { - $this->fail("Page mode is not PAGE or DATA"); - } - } - - protected function assert_text(string $text, string $section = null): void - { - $this->assertStringContainsString($text, $this->page_to_text($section)); - } - - protected function assert_no_text(string $text, string $section = null): void - { - $this->assertStringNotContainsString($text, $this->page_to_text($section)); - } - - protected function assert_content(string $content): void - { - global $page; - $this->assertStringContainsString($content, $page->data); - } - - protected function assert_no_content(string $content): void - { - global $page; - $this->assertStringNotContainsString($content, $page->data); - } - - protected function assert_search_results($tags, $results): void - { - $images = Image::find_images(0, null, $tags); - $ids = []; - foreach ($images as $image) { - $ids[] = $image->id; - } - $this->assertEquals($results, $ids); - } - - // user things - protected static function log_in_as_admin(): void - { - send_event(new UserLoginEvent(User::by_name(self::$admin_name))); - } - - protected static function log_in_as_user(): void - { - send_event(new UserLoginEvent(User::by_name(self::$user_name))); - } - - protected static function log_out(): void - { - global $config; - send_event(new UserLoginEvent(User::by_id($config->get_int("anon_id", 0)))); - } - - // post things - protected function post_image(string $filename, string $tags): int - { - $dae = send_event(new DataUploadEvent($filename, [ - "filename" => $filename, - "tags" => Tag::explode($tags), - "source" => null, - ])); - // if($dae->image_id == -1) throw new \Exception("Upload failed :("); - return $dae->image_id; - } - - protected function delete_image(int $image_id): void - { - $img = Image::by_id($image_id); - if ($img) { - send_event(new ImageDeletionEvent($img, true)); - } - } -} diff --git a/tests/docker-init.sh b/tests/docker-init.sh deleted file mode 100644 index e83854435..000000000 --- a/tests/docker-init.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh -groupadd -g $GID shimmie || true -useradd -ms /bin/bash -u $UID -g $GID shimmie -mkdir -p /app/data -chown $UID:$GID /app/data -export PHP_CLI_SERVER_WORKERS=8 -exec gosu shimmie:shimmie \ - /usr/bin/php \ - -d upload_max_filesize=$UPLOAD_MAX_FILESIZE \ - -d post_max_size=$UPLOAD_MAX_FILESIZE \ - -S 0.0.0.0:8000 \ - tests/router.php 2>&1 | grep --line-buffered -vE " (Accepted|Closing)" diff --git a/tests/phpstan.neon b/tests/phpstan.neon index 2a379a7f0..9faf61e30 100644 --- a/tests/phpstan.neon +++ b/tests/phpstan.neon @@ -4,6 +4,6 @@ parameters: - ../core - ../ext - ../tests - - ../themes/default + - ../themes ignoreErrors: - '#Access to an undefined property Shimmie2\\Image::\$#' diff --git a/tests/phpunit.xml b/tests/phpunit.xml index 2ded9aa85..de47f9ef5 100644 --- a/tests/phpunit.xml +++ b/tests/phpunit.xml @@ -1,18 +1,25 @@ - - - - ../core - ../ext - ../themes/default - - + + - ../core/ + ../core/ ../ext/ + + + ../core + ../ext + ../themes/default + + diff --git a/tests/router.php b/tests/router.php deleted file mode 100644 index 63a522b43..000000000 --- a/tests/router.php +++ /dev/null @@ -1,36 +0,0 @@ -get_string(SetupConfig::TITLE); } else { $search_string = Tag::implode($this->search_terms); - $query = url_escape(Tag::caret($search_string)); + $query = url_escape($search_string); $page_title = html_escape($search_string); } @@ -42,7 +42,7 @@ public function display_page(Page $page, array $images) } /** - * #param string[] $search_terms + * @param string[] $search_terms */ protected function build_navigation(int $page_number, int $total_pages, array $search_terms): string { diff --git a/themes/danbooru/page.class.php b/themes/danbooru/page.class.php index 3eee4ac05..6ff8dba7f 100644 --- a/themes/danbooru/page.class.php +++ b/themes/danbooru/page.class.php @@ -50,13 +50,6 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ class Page extends BasePage { - public bool $left_enabled = true; - - public function disable_left() - { - $this->left_enabled = false; - } - public function render() { global $config; @@ -135,7 +128,7 @@ public function render() print << - + $head_html
      diff --git a/themes/danbooru/style.css b/themes/danbooru/style.css index 598c05f91..b912670b4 100644 --- a/themes/danbooru/style.css +++ b/themes/danbooru/style.css @@ -219,21 +219,6 @@ margin:16px; padding:8px; width:350px; } -.helpable { -border-bottom:1px dashed gray; -} -.ok { --moz-background-clip:border; --moz-background-inline-policy:continuous; --moz-background-origin:padding; -background:#AAFFAA none repeat scroll 0 0; -} -.bad { --moz-background-clip:border; --moz-background-inline-policy:continuous; --moz-background-origin:padding; -background:#FFAAAA none repeat scroll 0 0; -} .comment .username { font-size:1.5em; font-weight:bold; diff --git a/themes/danbooru/view.theme.php b/themes/danbooru/view.theme.php index 28facb934..121a93dc0 100644 --- a/themes/danbooru/view.theme.php +++ b/themes/danbooru/view.theme.php @@ -4,7 +4,7 @@ namespace Shimmie2; -class CustomViewImageTheme extends ViewImageTheme +class CustomViewPostTheme extends ViewPostTheme { public function display_page(Image $image, $editor_parts) { diff --git a/themes/danbooru2/index.theme.php b/themes/danbooru2/index.theme.php index 51bf44730..e1fa8aa47 100644 --- a/themes/danbooru2/index.theme.php +++ b/themes/danbooru2/index.theme.php @@ -7,7 +7,7 @@ class CustomIndexTheme extends IndexTheme { /** - * #param Image[] $images + * @param Image[] $images */ public function display_page(Page $page, array $images) { @@ -26,7 +26,7 @@ public function display_page(Page $page, array $images) } /** - * #param string[] $search_terms + * @param string[] $search_terms */ protected function build_navigation(int $page_number, int $total_pages, array $search_terms): string { @@ -42,7 +42,7 @@ protected function build_navigation(int $page_number, int $total_pages, array $s } /** - * #param Image[] $images + * @param Image[] $images */ protected function build_table(array $images, ?string $query): string { diff --git a/themes/danbooru2/page.class.php b/themes/danbooru2/page.class.php index d4575d37f..d34354a32 100644 --- a/themes/danbooru2/page.class.php +++ b/themes/danbooru2/page.class.php @@ -51,12 +51,6 @@ class Page extends BasePage { - public bool $left_enabled = true; - public function disable_left() - { - $this->left_enabled = false; - } - public function render() { global $config; @@ -135,7 +129,7 @@ public function render() print << - + $head_html
      diff --git a/themes/danbooru2/style.css b/themes/danbooru2/style.css index ba42886f1..70d23acd2 100644 --- a/themes/danbooru2/style.css +++ b/themes/danbooru2/style.css @@ -269,21 +269,6 @@ width:100%; margin-top:0.4rem; padding:0.2rem 0.6rem; } -.helpable { -border-bottom:1px dashed gray; -} -.ok { -background:#AAFFAA none repeat scroll 0 0; --moz-background-clip:border; --moz-background-inline-policy:continuous; --moz-background-origin:padding; -} -.bad { -background:#FFAAAA none repeat scroll 0 0; --moz-background-clip:border; --moz-background-inline-policy:continuous; --moz-background-origin:padding; -} .comment .username { font-weight:bold; font-size:1.5em; diff --git a/themes/danbooru2/view.theme.php b/themes/danbooru2/view.theme.php index 99e3c8607..febb71f42 100644 --- a/themes/danbooru2/view.theme.php +++ b/themes/danbooru2/view.theme.php @@ -4,7 +4,7 @@ namespace Shimmie2; -class CustomViewImageTheme extends ViewImageTheme +class CustomViewPostTheme extends ViewPostTheme { public function display_page(Image $image, $editor_parts) { diff --git a/themes/default/style.css b/themes/default/style.css index 3ff7a787c..4fad4fff5 100644 --- a/themes/default/style.css +++ b/themes/default/style.css @@ -45,12 +45,14 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * things common to all pages * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +:root { + font-size: 14px; + font-family: sans-serif; +} BODY { background: var(--page); color: var(--text); - font-family: sans-serif; - font-size: 14px; margin: 0; } H1 { @@ -97,7 +99,7 @@ TABLE.zebra TR:nth-child(even) {background: var(--zebra-even);} FOOTER { clear: both; - font-size: 0.7em; + font-size: 0.7rem; text-align: center; background: var(--title); border: 1px solid var(--title-border); @@ -129,7 +131,7 @@ NAV { margin-left: 16px; } NAV .blockbody { - font-size: 0.85em; + font-size: 0.85rem; text-align: center; overflow: hidden; } diff --git a/themes/futaba/page.class.php b/themes/futaba/page.class.php index 83be4b913..60652ba29 100644 --- a/themes/futaba/page.class.php +++ b/themes/futaba/page.class.php @@ -6,12 +6,6 @@ class Page extends BasePage { - public bool $left_enabled = true; - public function disable_left() - { - $this->left_enabled = false; - } - public function render() { $left_block_html = ""; @@ -55,7 +49,7 @@ public function render() print << - + $head_html
      diff --git a/themes/futaba/style.css b/themes/futaba/style.css index e0cf705d6..3d07afa8c 100644 --- a/themes/futaba/style.css +++ b/themes/futaba/style.css @@ -2,10 +2,12 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * things common to all pages * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -BODY { +:root { font-family: arial,helvetica,sans-serif; font-size: 10pt; +} + +BODY { background: #FFFFEE url(fade.png) top center repeat-x; color: #800000; padding-left: 5px; @@ -24,7 +26,7 @@ H1 { FOOTER { clear: both; padding-top: 8px; - font-size: 0.7em; + font-size: 0.7rem; text-align: center; } @@ -43,7 +45,7 @@ NAV { margin-left: 16px; } NAV .blockbody { - font-size: 0.85em; + font-size: 0.85rem; text-align: center; overflow: hidden; } @@ -113,7 +115,7 @@ TABLE.tag_list>TBODY>TR>TD:after { #short-wiki-description > .blockbody { padding-bottom: 15px; - font-size: 1.1em; + font-size: 1.1rem; } #short-wiki-description h2 { margin: 0 0 0.4em; diff --git a/themes/futaba/view.theme.php b/themes/futaba/view.theme.php index eb40ad1ec..7f4a9f19e 100644 --- a/themes/futaba/view.theme.php +++ b/themes/futaba/view.theme.php @@ -4,7 +4,7 @@ namespace Shimmie2; -class CustomViewImageTheme extends ViewImageTheme +class CustomViewPostTheme extends ViewPostTheme { public function display_page(Image $image, $editor_parts) { diff --git a/themes/lite/comment.theme.php b/themes/lite/comment.theme.php index 20717a981..3be430a8d 100644 --- a/themes/lite/comment.theme.php +++ b/themes/lite/comment.theme.php @@ -8,11 +8,13 @@ class CustomCommentListTheme extends CommentListTheme { protected function comment_to_html(Comment $comment, bool $trim = false): string { - return $this->rr(parent::comment_to_html($comment, $trim)); + $html = parent::comment_to_html($comment, $trim); + return "
      $html
      "; } protected function build_postbox(int $image_id): string { - return $this->rr(parent::build_postbox($image_id)); + $html = parent::build_postbox($image_id); + return "
      $html
      "; } } diff --git a/themes/lite/page.class.php b/themes/lite/page.class.php index d6d606344..242ed9830 100644 --- a/themes/lite/page.class.php +++ b/themes/lite/page.class.php @@ -17,13 +17,6 @@ class Page extends BasePage { - public bool $left_enabled = true; - - public function disable_left() - { - $this->left_enabled = false; - } - public function render() { global $config; @@ -94,7 +87,7 @@ public function render() print << - + $head_html
      diff --git a/themes/lite/setup.theme.php b/themes/lite/setup.theme.php index 34f185447..b1e90085b 100644 --- a/themes/lite/setup.theme.php +++ b/themes/lite/setup.theme.php @@ -4,43 +4,11 @@ namespace Shimmie2; -/** - * Class CustomSetupTheme - * - * A customised version of the Setup theme. - * - */ class CustomSetupTheme extends SetupTheme { protected function sb_to_html(SetupBlock $block): string { - $h = $block->header; - $b = $block->body; - $i = preg_replace('/[^a-zA-Z0-9]/', '_', $h) . "-setup"; - $html = " - -
      - $h -
      $b
      -
      - "; - - return $this->rr($html); + $html = parent::sb_to_html($block); + return "
      $html
      "; } } diff --git a/themes/lite/style.css b/themes/lite/style.css index 0d8fced9f..6ebe6fd4d 100644 --- a/themes/lite/style.css +++ b/themes/lite/style.css @@ -3,10 +3,12 @@ * http://qwebirc.org/ */ -BODY { - background: #F0F7FF; +:root { font-family: sans-serif; font-size: 14px; +} +BODY { + background: #F0F7FF; margin: 0; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * @@ -126,16 +128,7 @@ TD { } CODE { background: #DEDEDE; - font-size: 0.8em; -} -#subtitle { - width: 256px; - font-size: 0.75em; - margin: -16px auto auto; - text-align: center; - border: 1px solid black; - border-top: none; - background: #DDD; + font-size: 0.8rem; } TABLE.zebra {border-spacing: 0; border: 2px solid #C3D2E0;} @@ -164,7 +157,7 @@ INPUT:hover, button:hover, TEXTAREA:hover { FOOTER { clear: both; padding: 8px; - font-size: 0.7em; + font-size: 0.7rem; text-align: center; border-top: 1px solid #C3D2E0; background: #E3EFFA; @@ -194,7 +187,7 @@ NAV { margin-left: 16px; } NAV .blockbody { - font-size: 0.85em; + font-size: 0.85rem; text-align: center; } NAV TABLE { @@ -320,19 +313,9 @@ ARTICLE TABLE { } .setupblock TEXTAREA { width: 300px; - font-size: 0.75em; -} - -.helpable { - border-bottom: 1px dashed gray; + font-size: 0.75rem; } -.ok { - background: #AFA; -} -.bad { - background: #FAA; -} NAV .thumbblock { float: none; diff --git a/themes/lite/themelet.class.php b/themes/lite/themelet.class.php index 39c61b720..fd293a38e 100644 --- a/themes/lite/themelet.class.php +++ b/themes/lite/themelet.class.php @@ -8,23 +8,8 @@ use function MicroHTML\{A,DIV,SPAN,joinHTML}; -/** - * Class Themelet - */ class Themelet extends BaseThemelet { - /** - * Put something in a rounded rectangle box; specific to the default theme. - */ - public function rr(string $html): string - { - return " -
      - $html -
      - "; - } - public function display_paginator(Page $page, string $base, ?string $query, int $page_number, int $total_pages, bool $show_random = false) { if ($total_pages == 0) { diff --git a/themes/lite/user_config.theme.php b/themes/lite/user_config.theme.php index b0c9f1fe8..46d748184 100644 --- a/themes/lite/user_config.theme.php +++ b/themes/lite/user_config.theme.php @@ -4,43 +4,11 @@ namespace Shimmie2; -/** - * Class CustomSetupTheme - * - * A customised version of the Setup theme. - * - */ class CustomUserConfigTheme extends UserConfigTheme { protected function sb_to_html(SetupBlock $block): string { - $h = $block->header; - $b = $block->body; - $i = preg_replace('/[^a-zA-Z0-9]/', '_', $h) . "-setup"; - $html = " - -
      - $h -
      $b
      -
      - "; - - return $this->rr($html); + $html = parent::sb_to_html($block); + return "
      $html
      "; } } diff --git a/themes/lite/view.theme.php b/themes/lite/view.theme.php index 02d55c963..7b0f018b1 100644 --- a/themes/lite/view.theme.php +++ b/themes/lite/view.theme.php @@ -4,7 +4,7 @@ namespace Shimmie2; -class CustomViewImageTheme extends ViewImageTheme +class CustomViewPostTheme extends ViewPostTheme { public function display_page(Image $image, $editor_parts) { diff --git a/themes/rule34v2/bg.png b/themes/rule34v2/bg.png deleted file mode 100644 index 45e1b42c0..000000000 Binary files a/themes/rule34v2/bg.png and /dev/null differ diff --git a/themes/rule34v2/header.inc b/themes/rule34v2/header.inc index b2fde29c4..5c48a6852 100644 --- a/themes/rule34v2/header.inc +++ b/themes/rule34v2/header.inc @@ -8,7 +8,7 @@
      -  Sidebar  +  Sidebar  logo @@ -17,7 +17,7 @@ - +
      @@ -68,26 +68,28 @@ -
      diff --git a/themes/rule34v2/home.theme.php b/themes/rule34v2/home.theme.php deleted file mode 100644 index 065c56f94..000000000 --- a/themes/rule34v2/home.theme.php +++ /dev/null @@ -1,95 +0,0 @@ -set_mode(PageMode::DATA); - $page->add_auto_html_headers(); - $hh = $page->get_all_html_headers(); - $page->set_data( - << - - $sitename - - - - $hh - - - - - $body - - -EOD - ); - } - - public function build_body(string $sitename, string $main_links, string $main_text, string $contact_link, $num_comma, string $counter_text): string - { - $main_links_html = empty($main_links) ? "" : ""; - $message_html = empty($main_text) ? "" : "
      $main_text
      "; - $counter_html = empty($counter_text) ? "" : "
      $counter_text
      "; - $contact_link = empty($contact_link) ? "" : "
      Contact –"; - $search_html = " - - "; - return " -
      -

      $sitename

      - $main_links_html - $search_html - $message_html - $counter_html - -
      "; - } -} diff --git a/themes/rule34v2/index.theme.php b/themes/rule34v2/index.theme.php index 94793bad0..1ac3b8ac5 100644 --- a/themes/rule34v2/index.theme.php +++ b/themes/rule34v2/index.theme.php @@ -6,6 +6,10 @@ class CustomIndexTheme extends IndexTheme { + public static array $_search_query = []; + + // override to add the can-del class, so that thumbnail HTML can be cached + // with admin-controls included, and CSS is used to show or hide the controls protected function build_table(array $images, ?string $query): string { global $user; @@ -21,13 +25,14 @@ protected function build_table(array $images, ?string $query): string return $table; } + // Override to add a custom error message public function display_page(Page $page, $images) { $this->display_page_header($page, $images); $nav = $this->build_navigation($this->page_number, $this->total_pages, $this->search_terms); if (!empty($this->search_terms)) { - $page->_search_query = $this->search_terms; + static::$_search_query = $this->search_terms; } $page->add_block(new Block("Navigation", $nav, "left", 0)); diff --git a/themes/rule34v2/menuh.css b/themes/rule34v2/menuh.css index d55e58719..1fb96d80f 100644 --- a/themes/rule34v2/menuh.css +++ b/themes/rule34v2/menuh.css @@ -10,7 +10,7 @@ a:active.menu { color: #FF0000; text-decoration: none; } #menuh-container { - font-size: 1em; + font-size: 1rem; float: left; top:0; left: 5%; diff --git a/themes/rule34v2/page.class.php b/themes/rule34v2/page.class.php index 94c84eca2..6a1e9d8b3 100644 --- a/themes/rule34v2/page.class.php +++ b/themes/rule34v2/page.class.php @@ -53,7 +53,7 @@ public function render() } } - $query = !empty($this->_search_query) ? html_escape(Tag::implode($this->_search_query)) : ""; + $query = !empty(CustomIndexTheme::$_search_query) ? html_escape(Tag::implode(CustomIndexTheme::$_search_query)) : ""; assert(!is_null($query)); # used in header.inc, do not remove :P $flash_html = $this->flash ? "".nl2br(html_escape(implode("\n", $this->flash)))."" : ""; $generated = autodate(date('c')); diff --git a/themes/rule34v2/script.js b/themes/rule34v2/script.js index 8c559ad7c..7897627b2 100644 --- a/themes/rule34v2/script.js +++ b/themes/rule34v2/script.js @@ -7,18 +7,18 @@ document.addEventListener('DOMContentLoaded', () => { var navHidden = false; function toggleNav() { if(navHidden) { - $('BODY').removeClass('navHidden'); - Cookies.set("ui-shownav", "true"); + document.body.classList.remove('navHidden'); + shm_cookie_set("ui-shownav", "true"); } else { - $('BODY').addClass('navHidden'); - Cookies.set("ui-shownav", "false"); + document.body.classList.add('navHidden'); + shm_cookie_set("ui-shownav", "false"); } navHidden = !navHidden; } document.addEventListener('DOMContentLoaded', () => { - if(Cookies.get("ui-shownav") === "false") { + if(shm_cookie_get("ui-shownav") === "false") { toggleNav(); } }); @@ -29,12 +29,12 @@ function toggleDesktop() { if(forceDesktop) { let viewport = document.querySelector("meta[name=viewport]"); viewport.setAttribute('content', 'width=512'); - Cookies.set("ui-desktop", "false"); + shm_cookie_set("ui-desktop", "false"); } else { let viewport = document.querySelector("meta[name=viewport]"); viewport.setAttribute('content', 'width=1024, initial-scale=0.4'); - Cookies.set("ui-desktop", "true"); + shm_cookie_set("ui-desktop", "true"); navHidden = true; toggleNav(); } @@ -42,7 +42,7 @@ function toggleDesktop() { } document.addEventListener('DOMContentLoaded', () => { - if(Cookies.get("ui-desktop") === "true") { + if(shm_cookie_get("ui-desktop") === "true") { toggleDesktop(); } }); diff --git a/themes/rule34v2/style.css b/themes/rule34v2/style.css index 4b60f8b98..84a8ebe34 100644 --- a/themes/rule34v2/style.css +++ b/themes/rule34v2/style.css @@ -3,10 +3,12 @@ * things common to all pages * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -BODY { - background: url(bg.png) #ACE4A3; +:root { font-family: "Arial", sans-serif; font-size: 14px; +} +BODY { + background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPBAMAAADJ+Ih5AAAAFVBMVEV8und+uXeo5aKo5qOq5aOr46Ks5KN5+6UZAAAAN0lEQVQImWNIc2FLcUhzYWBIczRLEU5zNGBwEQlxdHURCWBwdEkRcXN0SWBgVkswSgMSDDRTDADa2B2AhUf94AAAAABJRU5ErkJggg=='); margin: 0; } #header { @@ -18,7 +20,7 @@ BODY { text-align: center; } H1 { - font-size: 5em; + font-size: 5rem; margin: 0; padding: 0; } @@ -37,15 +39,6 @@ TD { text-align: center; } -#subtitle { - width: 256px; - font-size: 0.75em; - margin: -16px auto auto; - text-align: center; - border: 1px solid black; - border-top: none; - background: #DDD; -} #flash { background: #FF7; display: block; @@ -55,14 +48,14 @@ TD { } TABLE.zebra {background: #ACE4A3; border-collapse: collapse; border: 1px solid #7EB977;} -TABLE.zebra TD {font-size: 0.8em;margin: 0; border-top: 1px solid #7EB977; padding: 2px;} +TABLE.zebra TD {font-size: 0.8rem;margin: 0; border-top: 1px solid #7EB977; padding: 2px;} TABLE.zebra TR:nth-child(odd) {background: #9CD493;} TABLE.zebra TR:nth-child(even) {background: #ACE4A3;} FOOTER { clear: both; padding: 8px; - font-size: 0.7em; + font-size: 0.7rem; text-align: center; border-top: 1px solid #7EB977; background: #ACE4A3; @@ -94,7 +87,7 @@ NAV { margin-left: 16px; } NAV .blockbody { - font-size: 0.85em; + font-size: 0.85rem; text-align: center; } NAV TABLE { @@ -216,16 +209,6 @@ SECTION>H3 { padding: 4px; } -div#twitter_update_list li { - list-style:none; - padding-bottom:0; - text-align:left; - margin-top:5px; - margin-bottom:5px; - border: solid 1px #000; - background: url(bg.png); -} - .username { font-weight: bold; } @@ -234,7 +217,7 @@ div#twitter_update_list li { vertical-align: middle; } #bans INPUT { - font-size: 0.85em; + font-size: 0.85rem; } .need-del { @@ -249,14 +232,7 @@ div#twitter_update_list li { color: red; } -UL.tagit { - margin: 0; -} -ul.tagit li.tagit-new { - width: 50px; -} - - +[data-tags~="ai-generated"]>A>IMG { background: #BC8F8F; } [data-tags~="animated"]>A>IMG { background: #CC00CC; } [data-ext="mp4"]>A>IMG, [data-ext="webm"]>A>IMG { background: #0000FF; } @@ -267,13 +243,29 @@ ul.tagit li.tagit-new { margin: auto; } +/* + * Image info - show both edit and view modes at the same time, + * except for Tags, Locked, and the Edit button. + */ +.image_info.infomode-view .edit, +.image_info.infomode-view .view { + display: block; +} +.image_info.infomode-view TR[data-row="Tags"] .view, +.image_info.infomode-view TR[data-row="Locked"] .view, +.image_info INPUT[type="button"][value="Edit"] { + display: none; +} + + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * responsive overrides * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ @media (max-width: 750px) { .atoz, #paginator { - font-size: 2em; + font-size: 2rem; } .header-sites { display: none; @@ -339,7 +331,7 @@ ul.tagit li.tagit-new { #UserBlockhead {display: block;} #Loginleft {display: none;} #Loginhead {display: block;} -.headcol {width: 250px; font-size: 0.85em;} +.headcol {width: 250px; font-size: 0.85rem;} .headbox {width: 80%; margin: auto;} #big-logo {display: table-cell;} #mini-logo {display: none;} @@ -357,7 +349,7 @@ ul.tagit li.tagit-new { /* hide nav-search when header-search is sticky */ ARTICLE {margin-top: 0;} - #Navigationleft .blockbody {font-size: 1.5em;} + #Navigationleft .blockbody {font-size: 1.5rem;} #Navigationleft .blockbody P, #Navigationleft .blockbody FORM {display: none;} @@ -374,3 +366,14 @@ ul.tagit li.tagit-new { #ed91727bc9c7a73fdcec6db562e63151main { overflow: scroll; } + +/* front page */ +div#front-page h1 {font-size: 4rem; margin-top: 2em; margin-bottom: 0; text-align: center; border: none; background: none; box-shadow: none; -webkit-box-shadow: none; -moz-box-shadow: none;} +div#front-page {text-align:center;} +.space {margin-bottom: 1em;} +div#front-page div#links a {margin: 0 0.5em;} +div#front-page li {list-style-type: none; margin: 0;} +@media (max-width: 800px) { + div#front-page h1 {font-size: 3rem; margin-top: 0.5em; margin-bottom: 0.5em;} + #counter {display: none;} +} diff --git a/themes/rule34v2/tag_edit.theme.php b/themes/rule34v2/tag_edit.theme.php deleted file mode 100644 index 1c1533af8..000000000 --- a/themes/rule34v2/tag_edit.theme.php +++ /dev/null @@ -1,57 +0,0 @@ - - Search - Replace - - - - "; - $page->add_block(new Block("Mass Tag Edit", $html)); - } - - public function get_tag_editor_html(Image $image): string - { - $h_tags = html_escape($image->get_tag_list()); - return " - - Tags - - - - - "; - } - - public function get_source_editor_html(Image $image): string - { - global $user; - $h_source = html_escape($image->get_source()); - $f_source = $this->format_source($image->get_source()); - $style = "overflow: hidden; white-space: nowrap; max-width: 350px; text-overflow: ellipsis;"; - return " - - Source Link - - ".($user->can("edit_image_source") ? " -
      $f_source
      - - " : " -
      $f_source
      - ")." - - - "; - } -} diff --git a/themes/rule34v2/upload.theme.php b/themes/rule34v2/upload.theme.php index bf4ccb708..20f3e05a6 100644 --- a/themes/rule34v2/upload.theme.php +++ b/themes/rule34v2/upload.theme.php @@ -21,93 +21,24 @@ class CustomUploadTheme extends UploadTheme { + // override to put upload block in head and left + // (with css media queries deciding which one is visible) public function display_block(Page $page): void { $page->add_block(new Block("Upload", $this->build_upload_block(), "head", 20)); $page->add_block(new Block("Upload", $this->build_upload_block(), "left", 20)); } + // override to put the warning in the header public function display_full(Page $page): void { $page->add_block(new Block("Upload", "Disk nearly full, uploads disabled", "head", 20)); } - public function display_page(Page $page): void - { - global $config, $page; - - $tl_enabled = ($config->get_string(UploadConfig::TRANSLOAD_ENGINE, "none") != "none"); - $max_size = $config->get_int(UploadConfig::SIZE); - $max_kb = to_shorthand_int($max_size); - $upload_list = $this->h_upload_list_1(); - - $form = SHM_FORM("upload", "POST", true, "file_upload"); - $form->appendChild( - TABLE( - ["id" => "large_upload_form", "class" => "vert"], - TR( - TD(["width" => "20"], rawHTML("Common Tags")), - TD(["colspan" => "5"], INPUT(["name" => "tags", "type" => "text", "placeholder" => "tagme", "autocomplete" => "off"])) - ), - TR( - TD(["width" => "20"], rawHTML("Common Source")), - TD(["colspan" => "5"], INPUT(["name" => "source", "type" => "text"])) - ), - $upload_list, - TR( - TD(["colspan" => "6"], INPUT(["id" => "uploadbutton", "type" => "submit", "value" => "Post"])) - ), - ) - ); - $html = emptyHTML( - $form, - SMALL("(Max file size is $max_kb)") - ); - - $page->set_title("Upload"); - $page->set_heading("Upload"); - $page->add_block(new NavBlock()); - $page->add_block(new Block("Upload", $html, "main", 20)); - if ($tl_enabled) { - $page->add_block(new Block("Bookmarklets", (string)$this->h_bookmarklets(), "left", 20)); - } - $html = " - Tagging Guide - "; - $page->add_block(new Block(null, $html, "main", 19)); - } - + // override to remove small uploader and just show a link to + // the big page protected function build_upload_block(): HTMLElement { - return A(["href" => make_link("upload"), "style" => 'font-size: 2em; display: block;'], "Upload"); - } - - protected function h_upload_list_1(): HTMLElement - { - global $config; - $upload_list = emptyHTML(); - $upload_count = $config->get_int(UploadConfig::COUNT); - $tl_enabled = ($config->get_string(UploadConfig::TRANSLOAD_ENGINE, "none") != "none"); - $accept = $this->get_accept(); - - $upload_list->appendChild( - TR( - TD(["colspan" => $tl_enabled ? 2 : 4], "Files"), - $tl_enabled ? TD(["colspan" => "2"], "URLs") : emptyHTML(), - TD(["colspan" => "2"], "Post-Specific Tags"), - ) - ); - - for ($i = 0; $i < $upload_count; $i++) { - $upload_list->appendChild( - TR( - TD(["colspan" => $tl_enabled ? 2 : 4], INPUT(["type" => "file", "name" => "data{$i}[]", "accept" => $accept, "multiple" => true])), - $tl_enabled ? TD(["colspan" => "2"], INPUT(["type" => "text", "name" => "url{$i}"])) : emptyHTML(), - TD(["colspan" => "2"], INPUT(["type" => "text", "name" => "tags{$i}", "autocomplete" => "off"])), - ) - ); - } - - return $upload_list; + return A(["href" => make_link("upload"), "style" => 'font-size: 1.7rem; display: block;'], "Upload"); } } diff --git a/themes/rule34v2/user.theme.php b/themes/rule34v2/user.theme.php index f621e1579..600d90d64 100644 --- a/themes/rule34v2/user.theme.php +++ b/themes/rule34v2/user.theme.php @@ -23,6 +23,10 @@ class CustomUserPageTheme extends UserPageTheme { + // Override to display user block in the head and in the left column + // (with css media queries deciding which one is visible), and also + // to switch between new-line and inline display depending on the + // number of links. public function display_user_block(Page $page, User $user, $parts) { $h_name = html_escape($user->name); @@ -42,110 +46,11 @@ public function display_user_block(Page $page, User $user, $parts) $page->add_block(new Block("Logged in as $h_name", $html, "left", 15, "UserBlockleft")); } + // Override to display login block in the head and in the left column + // (with css media queries deciding which one is visible) public function display_login_block(Page $page) { - global $config; - $html = " -
      - - - - -
      Name
      Password
      -
      - "; - if ($config->get_bool("login_signup_enabled")) { - $html .= "Create Account"; - } - $page->add_block(new Block("Login", $html, "head", 90)); - $page->add_block(new Block("Login", $html, "left", 15)); - } - - public function display_signup_page(Page $page) - { - global $config; - $tac = $config->get_string("login_tac", ""); - - if ($config->get_bool("login_tac_bbcode")) { - $tac = send_event(new TextFormattingEvent($tac))->formatted; - } - - $form = SHM_SIMPLE_FORM( - "user_admin/create", - TABLE( - ["class" => "form"], - TBODY( - TR( - TH("Name"), - TD(INPUT(["type" => 'text', "name" => 'name', "required" => true])) - ), - TR( - TH("Password"), - TD(INPUT(["type" => 'password', "name" => 'pass1', "required" => true])) - ), - TR( - TH(rawHTML("Repeat Password")), - TD(INPUT(["type" => 'password', "name" => 'pass2', "required" => true])) - ), - TR( - TH(rawHTML("Email")), - TD(INPUT(["type" => 'email', "name" => 'email', "required" => true])) - ), - TR( - TD(["colspan" => "2"], rawHTML(captcha_get_html())) - ), - ), - TFOOT( - TR(TD(["colspan" => "2"], INPUT(["type" => "submit", "value" => "Create Account"]))) - ) - ) - ); - - $html = emptyHTML( - $tac ? P(rawHTML($tac)) : null, - $form - ); - - $page->set_title("Create Account"); - $page->set_heading("Create Account"); - $page->add_block(new NavBlock()); - $page->add_block(new Block("Signup", $html)); - } - - public function display_user_creator() - { - global $page; - - $form = SHM_SIMPLE_FORM( - "user_admin/create_other", - TABLE( - ["class" => "form"], - TBODY( - TR( - TH("Name"), - TD(INPUT(["type" => 'text', "name" => 'name', "required" => true])) - ), - TR( - TH("Password"), - TD(INPUT(["type" => 'password', "name" => 'pass1', "required" => true])) - ), - TR( - TH(rawHTML("Repeat Password")), - TD(INPUT(["type" => 'password', "name" => 'pass2', "required" => true])) - ), - TR( - TH(rawHTML("Email")), - TD(INPUT(["type" => 'email', "name" => 'email'])) - ), - TR( - TD(["colspan" => 2], rawHTML("(Email is optional for admin-created accounts)")), - ), - ), - TFOOT( - TR(TD(["colspan" => "2"], INPUT(["type" => "submit", "value" => "Create Account"]))) - ) - ) - ); - $page->add_block(new Block("Create User", (string)$form, "main", 75)); + $page->add_block(new Block("Login", $this->create_login_block(), "head", 90)); + $page->add_block(new Block("Login", $this->create_login_block(), "left", 15)); } } diff --git a/themes/warm/page.class.php b/themes/warm/page.class.php index 3ffcbab4a..3147da570 100644 --- a/themes/warm/page.class.php +++ b/themes/warm/page.class.php @@ -45,7 +45,7 @@ public function render() print << - + $head_html
      diff --git a/themes/warm/style.css b/themes/warm/style.css index 616010eea..894ea9d36 100644 --- a/themes/warm/style.css +++ b/themes/warm/style.css @@ -3,10 +3,12 @@ * things common to all pages * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -BODY { - background: url(bg.png); +:root { font-family: "Arial", sans-serif; font-size: 14px; +} +BODY { + background: url(bg.png); margin: 0; } HEADER { @@ -18,7 +20,7 @@ HEADER { text-align: center; } H1 { - font-size: 5em; + font-size: 5rem; margin: 0; padding: 0; } @@ -38,16 +40,7 @@ TD { } CODE { background: #DEDEDE; - font-size: 0.8em; -} -#subtitle { - width: 256px; - font-size: 0.75em; - margin: -16px auto auto; - text-align: center; - border: 1px solid black; - border-top: none; - background: #DDD; + font-size: 0.8rem; } TABLE.zebra {border-spacing: 0; border: 1px solid #B89F7C; } @@ -61,7 +54,7 @@ TABLE.zebra TR:nth-child(even) {background: #DABC92;} FOOTER { clear: both; padding: 8px; - font-size: 0.7em; + font-size: 0.7rem; text-align: center; border-top: 1px solid #B89F7C; background: #FCD9A9; @@ -98,7 +91,7 @@ NAV { margin-left: 16px; } NAV .blockbody { - font-size: 0.85em; + font-size: 0.85rem; text-align: center; } NAV TABLE {