diff --git a/.dockerignore b/.dockerignore index 3e435513..ca6c1299 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,9 +1,14 @@ +# ignore everything * + +# unignored directories !bin -!docs !res !src !views + +# unignored files !composer.json !composer.lock !LICENSE +!php-cli.ini diff --git a/.gitattributes b/.gitattributes index 60834d0d..3d1f24fc 100644 --- a/.gitattributes +++ b/.gitattributes @@ -5,3 +5,16 @@ # See core.whitespace @ http://git-scm.com/docs/git-config for whitespace flags. *.php text eol=lf whitespace=blank-at-eol,blank-at-eof,space-before-tab,tab-in-indent,tabwidth=4 diff=php *.json text eol=lf whitespace=blank-at-eol,blank-at-eof,space-before-tab,tab-in-indent,tabwidth=4 + +# Exclude these files from git export. +# This will effect when package is installed via --prefer-dist +/*.dist export-ignore +/.*.dist export-ignore +/.*.yml export-ignore +/.dockerignore export-ignore +/.git* export-ignore +/Dockerfile export-ignore +/box.json export-ignore +/docs/ export-ignore +/tests/ export-ignore +/webpack.config.js export-ignore diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..c6a7ce9a --- /dev/null +++ b/.github/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at rob.bast@gmail.com. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +https://www.contributor-covenant.org/faq diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 00000000..a7f9957a --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,11 @@ +# Contributing to Satis + +:+1::tada: First off, thanks for taking the time to contribute! :tada::+1: + +This project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms. + +## How to contribute? + +1. Fork the project, +2. create a feature branch, +3. and send us a pull request. diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..d071feff --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,3 @@ +# These are supported funding model platforms + +custom: https://packagist.com diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..c934f8d2 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,23 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: bug +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Provide configuration file(s) and the exact command that you invoked. + +**Outcome** +If applicable, please provide detailed verbose output (`-vvv`) of the command. + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000..4fe86d5e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: feature +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/other.md b/.github/ISSUE_TEMPLATE/other.md new file mode 100644 index 00000000..c26c397c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/other.md @@ -0,0 +1,8 @@ +--- +name: Question or general feedback +about: Not a bug or feature request? Let us hear your thoughts. +title: '' +labels: '' +assignees: '' + +--- diff --git a/.github/SECURITY.md b/.github/SECURITY.md new file mode 100644 index 00000000..1a40871b --- /dev/null +++ b/.github/SECURITY.md @@ -0,0 +1,5 @@ +# Security Policy + +## Reporting a Vulnerability + +Please e-mail any vulnerability related discoveries, feedback or otherwise to rob.bast@gmail.com. In case of sensitive content, my PGP key can be found on https://robbast.nl diff --git a/.gitignore b/.gitignore index ed802967..a54f7941 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ /build/ +/node_modules/ /vendor/ /.php_cs.cache +/.phpunit.result.cache /composer.phar /phpunit.xml /satis.phar diff --git a/.php_cs.dist b/.php_cs.dist index 388acb5b..3fb594c5 100644 --- a/.php_cs.dist +++ b/.php_cs.dist @@ -28,6 +28,7 @@ return (new PhpCsFixer\Config('satis')) // additionally 'array_syntax' => ['syntax' => 'short'], 'concat_space' => false, + 'declare_strict_types' => true, 'header_comment' => ['header' => $header], 'no_unused_imports' => false, 'no_useless_else' => true, diff --git a/.travis.yml b/.travis.yml index 5ac3d561..e8f862e9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,31 +1,39 @@ -sudo: false -dist: trusty - language: php +dist: bionic + cache: directories: - - $HOME/.composer/cache/files + - $HOME/.composer + - vendor git: depth: 5 php: - - 7.0 - - 7.1 - - 7.2 - - nightly +- 7.2 +- 7.3 +- 7.4 +- nightly + +env: + matrix: + - COMPOSER_FLAGS="--prefer-lowest" + - COMPOSER_FLAGS="" matrix: fast_finish: true allow_failures: - - php: nightly + - php: nightly before_install: - - flags="--no-interaction --no-progress --prefer-dist" +- travis_retry composer self-update --no-interaction install: - - composer install $flags +- travis_retry composer update --no-interaction --no-progress --no-suggest --prefer-dist $COMPOSER_FLAGS script: - - vendor/bin/phpunit +- vendor/bin/phpunit --coverage-text --coverage-clover coverage.xml + +after_success: +- bash <(curl -s https://codecov.io/bash) diff --git a/Dockerfile b/Dockerfile index c17de119..4087a5de 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,47 +1,44 @@ -FROM php:7-alpine +FROM composer:1 AS build -MAINTAINER https://github.com/composer/satis +WORKDIR /satis -RUN apk --no-cache add curl git subversion mercurial openssh openssl tini zlib-dev +COPY . /satis/ -RUN docker-php-ext-install zip \ - && echo "memory_limit=-1" > "$PHP_INI_DIR/conf.d/memory-limit.ini" \ - && echo "date.timezone=${PHP_TIMEZONE:-UTC}" > "$PHP_INI_DIR/conf.d/date_timezone.ini" +RUN set -eux; \ + composer install \ + --no-interaction \ + --no-ansi \ + --no-scripts \ + --no-plugins \ + --no-dev \ + --prefer-dist \ + --no-progress \ + --no-suggest \ + --classmap-authoritative -ENV COMPOSER_HOME /composer -ENV PATH "/composer/vendor/bin:$PATH" -ENV COMPOSER_ALLOW_SUPERUSER 1 - -RUN mkdir /build \ - && mkdir /composer \ - && chmod -R 777 /composer \ - && curl -sfLo /tmp/composer-setup.php https://getcomposer.org/installer \ - && curl -sfLo /tmp/composer-setup.sig https://composer.github.io/installer.sig \ - && php -r " \ - \$hash = hash('SHA384', file_get_contents('/tmp/composer-setup.php')); \ - \$signature = trim(file_get_contents('/tmp/composer-setup.sig')); \ - if (!hash_equals(\$signature, \$hash)) { \ - unlink('/tmp/composer-setup.php'); \ - echo 'Integrity check failed, installer is either corrupt or worse.' . PHP_EOL; \ - exit(1); \ - }" \ - && php /tmp/composer-setup.php --no-ansi --install-dir=/usr/bin --filename=composer \ - && composer --no-interaction --no-ansi --version \ - && rm /tmp/composer-setup.php +FROM php:7-cli-alpine -WORKDIR /satis +MAINTAINER https://github.com/composer/satis -COPY ["composer.json", "composer.lock", "/satis/"] +RUN set -eux; \ + apk add --no-cache --upgrade \ + bash \ + curl \ + git \ + subversion \ + mercurial \ + openssh \ + openssl \ + zip \ + unzip -RUN composer install --no-interaction --no-ansi --no-autoloader --no-scripts --no-plugins --no-dev +ENV COMPOSER_HOME /composer -COPY bin /satis/bin/ -COPY res /satis/res/ -COPY views /satis/views/ -COPY src /satis/src/ +COPY php-cli.ini /usr/local/etc/php/ +COPY --from=build /satis /satis/ -RUN composer dump-autoload --no-interaction --no-ansi --optimize --no-dev +WORKDIR /build -ENTRYPOINT ["/sbin/tini", "-g", "--", "/satis/bin/docker-entrypoint.sh"] +ENTRYPOINT ["/satis/bin/docker-entrypoint.sh"] CMD ["--ansi", "-vvv", "build", "/build/satis.json", "/build/output"] diff --git a/README.md b/README.md index 26c83e70..20542b1c 100644 --- a/README.md +++ b/README.md @@ -3,12 +3,15 @@ Simple static Composer repository generator. [](https://travis-ci.org/composer/satis) +[](https://codecov.io/gh/composer/satis) ## Run from source -- Install satis: `composer create-project composer/satis:dev-master --keep-vcs` -- Build a repository: `php bin/satis build ` +Satis requires a recent PHP version, it does not run with unsupported PHP versions. Check the `composer.json` file for details. + +- Install satis: `composer create-project composer/satis:dev-master` +- Build a repository: `php bin/satis build ` Read the more detailed instructions in the [documentation][]. @@ -21,27 +24,21 @@ Pull the image: docker pull composer/satis ``` -Run the image: - -``` sh -docker run --rm -it -v /build:/build composer/satis -``` - - > Note: by default it will look for a configuration file named `satis.json` - inside the `/build` directory and dump the generated output files in - `/build/output`. - Run the image (with Composer cache from host): ``` sh -docker run --rm -it -v /build:/build -v $COMPOSER_HOME:/composer composer/satis +docker run --rm --init -it \ + --user $(id -u):$(id -g) \ + --volume $(pwd):/build \ + --volume "${COMPOSER_HOME:-$HOME/.composer}:/composer" \ + composer/satis build ``` If you want to run the image without implicitly running Satis, you have to override the entrypoint specified in the `Dockerfile`: ``` sh -docker run --rm -it --entrypoint /bin/sh composer/satis +--entrypoint /bin/sh ``` @@ -60,7 +57,7 @@ php bin/satis purge ## Updating -Updating Satis is as simple as running `git pull && composer update` in the +Updating Satis is as simple as running `git pull && composer install` in the Satis directory. If you are running Satis as a Docker container, simply pull the latest image. @@ -73,6 +70,8 @@ By participating in this project you agree to abide by its terms. Fork the project, create a feature branch, and send us a pull request. +If you introduce a new feature, or fix a bug, please try to include a testcase. + ## Authors @@ -90,6 +89,11 @@ See the list of [contributors][] who participate(d) in this project. (satis.json) "require" key on the basis of the project composer.json. +## Examples + +- [eventum/composer] - A simple static set of packages hosted in GitHub Pages + + ## License Satis is licensed under the MIT License - see the [LICENSE][] file for details @@ -103,3 +107,4 @@ Satis is licensed under the MIT License - see the [LICENSE][] file for details [satis-control-panel]: https://github.com/realshadow/satis-control-panel [composer-satis-builder]: https://github.com/AOEpeople/composer-satis-builder [LICENSE]: https://github.com/composer/satis/blob/master/LICENSE +[eventum/composer]: https://github.com/eventum/composer diff --git a/bin/docker-entrypoint.sh b/bin/docker-entrypoint.sh index a5baf650..eb9fffc5 100755 --- a/bin/docker-entrypoint.sh +++ b/bin/docker-entrypoint.sh @@ -1,5 +1,4 @@ #!/bin/sh -set -e isCommand() { for cmd in \ diff --git a/composer.json b/composer.json index 996e3f16..fae4370e 100644 --- a/composer.json +++ b/composer.json @@ -8,11 +8,15 @@ "authors": [{ "name": "Jordi Boggiano", "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" + "homepage": "https://seld.be" }, { "name": "Nils Adermann", "email": "naderman@naderman.de", "homepage": "http://www.naderman.de" + }, { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "https://robbast.nl" }], "support": { "issues": "https://github.com/composer/satis", @@ -22,28 +26,23 @@ }, "bin": ["bin/satis"], "require": { - "php": "^7.0", - "composer/composer": "^1.4", - "twig/twig": "^1.7 || ^2.0", - "symfony/console": "^2.1 || ^3.0.4 || ^4.0" + "php": "^7.2||^8.0", + "composer/composer": "^1.9", + "symfony/console": "^4.4||^5.0", + "twig/twig": "^2.12||^3.0" }, "autoload": { "psr-4": { "Composer\\Satis\\": "src" } }, "require-dev": { - "phpunit/phpunit": "^6.4", - "phpunit/phpunit-mock-objects": "^4.0", - "mikey179/vfsStream": "^1.6", - "friendsofphp/php-cs-fixer": "^2.11" + "ext-json": "*", + "friendsofphp/php-cs-fixer": "^2.15", + "mikey179/vfsstream": "^1.6.7", + "phpunit/phpunit": "^8.2||^9.0" }, "autoload-dev": { "psr-4": { "Composer\\Satis\\": "tests" } }, - "config": { - "platform": { - "php": "7.0" - } - }, "extra": { "branch-alias": { "dev-master": "2.0-dev" diff --git a/composer.lock b/composer.lock index d797123e..7ee516dd 100644 --- a/composer.lock +++ b/composer.lock @@ -4,31 +4,31 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "80da4dc8d56a32677aa1f10d3153fb69", + "content-hash": "39a2812a962ea5afd71fa5ab0ff36ddd", "packages": [ { "name": "composer/ca-bundle", - "version": "1.1.1", + "version": "1.2.6", "source": { "type": "git", "url": "https://github.com/composer/ca-bundle.git", - "reference": "d2c0a83b7533d6912e8d516756ebd34f893e9169" + "reference": "47fe531de31fca4a1b997f87308e7d7804348f7e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/ca-bundle/zipball/d2c0a83b7533d6912e8d516756ebd34f893e9169", - "reference": "d2c0a83b7533d6912e8d516756ebd34f893e9169", + "url": "https://api.github.com/repos/composer/ca-bundle/zipball/47fe531de31fca4a1b997f87308e7d7804348f7e", + "reference": "47fe531de31fca4a1b997f87308e7d7804348f7e", "shasum": "" }, "require": { "ext-openssl": "*", "ext-pcre": "*", - "php": "^5.3.2 || ^7.0" + "php": "^5.3.2 || ^7.0 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5", + "phpunit/phpunit": "^4.8.35 || ^5.7 || 6.5 - 8", "psr/log": "^1.0", - "symfony/process": "^2.5 || ^3.0 || ^4.0" + "symfony/process": "^2.5 || ^3.0 || ^4.0 || ^5.0" }, "type": "library", "extra": { @@ -60,30 +60,30 @@ "ssl", "tls" ], - "time": "2018-03-29T19:57:20+00:00" + "time": "2020-01-13T10:02:55+00:00" }, { "name": "composer/composer", - "version": "1.6.4", + "version": "1.9.3", "source": { "type": "git", "url": "https://github.com/composer/composer.git", - "reference": "86ad51e8a3c64c9782446aae740a61fc6faa2522" + "reference": "1291a16ce3f48bfdeca39d64fca4875098af4d7b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/composer/zipball/86ad51e8a3c64c9782446aae740a61fc6faa2522", - "reference": "86ad51e8a3c64c9782446aae740a61fc6faa2522", + "url": "https://api.github.com/repos/composer/composer/zipball/1291a16ce3f48bfdeca39d64fca4875098af4d7b", + "reference": "1291a16ce3f48bfdeca39d64fca4875098af4d7b", "shasum": "" }, "require": { "composer/ca-bundle": "^1.0", "composer/semver": "^1.0", "composer/spdx-licenses": "^1.2", + "composer/xdebug-handler": "^1.1", "justinrainbow/json-schema": "^3.0 || ^4.0 || ^5.0", "php": "^5.3.2 || ^7.0", "psr/log": "^1.0", - "seld/cli-prompt": "^1.0", "seld/jsonlint": "^1.4", "seld/phar-utils": "^1.0", "symfony/console": "^2.7 || ^3.0 || ^4.0", @@ -91,6 +91,9 @@ "symfony/finder": "^2.7 || ^3.0 || ^4.0", "symfony/process": "^2.7 || ^3.0 || ^4.0" }, + "conflict": { + "symfony/console": "2.8.38" + }, "require-dev": { "phpunit/phpunit": "^4.8.35 || ^5.7", "phpunit/phpunit-mock-objects": "^2.3 || ^3.0" @@ -106,7 +109,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.6-dev" + "dev-master": "1.9-dev" } }, "autoload": { @@ -130,35 +133,34 @@ "homepage": "http://seld.be" } ], - "description": "Composer helps you declare, manage and install dependencies of PHP projects, ensuring you have the right stack everywhere.", + "description": "Composer helps you declare, manage and install dependencies of PHP projects. It ensures you have the right stack everywhere.", "homepage": "https://getcomposer.org/", "keywords": [ "autoload", "dependency", "package" ], - "time": "2018-04-13T10:04:24+00:00" + "time": "2020-02-04T11:58:49+00:00" }, { "name": "composer/semver", - "version": "1.4.2", + "version": "1.5.1", "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573" + "reference": "c6bea70230ef4dd483e6bbcab6005f682ed3a8de" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/c7cb9a2095a074d131b65a8a0cd294479d785573", - "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573", + "url": "https://api.github.com/repos/composer/semver/zipball/c6bea70230ef4dd483e6bbcab6005f682ed3a8de", + "reference": "c6bea70230ef4dd483e6bbcab6005f682ed3a8de", "shasum": "" }, "require": { "php": "^5.3.2 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "^4.5 || ^5.0.5", - "phpunit/phpunit-mock-objects": "2.3.0 || ^3.0" + "phpunit/phpunit": "^4.5 || ^5.0.5" }, "type": "library", "extra": { @@ -199,28 +201,27 @@ "validation", "versioning" ], - "time": "2016-08-30T16:08:34+00:00" + "time": "2020-01-13T12:06:48+00:00" }, { "name": "composer/spdx-licenses", - "version": "1.3.0", + "version": "1.5.3", "source": { "type": "git", "url": "https://github.com/composer/spdx-licenses.git", - "reference": "7e111c50db92fa2ced140f5ba23b4e261bc77a30" + "reference": "0c3e51e1880ca149682332770e25977c70cf9dae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/7e111c50db92fa2ced140f5ba23b4e261bc77a30", - "reference": "7e111c50db92fa2ced140f5ba23b4e261bc77a30", + "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/0c3e51e1880ca149682332770e25977c70cf9dae", + "reference": "0c3e51e1880ca149682332770e25977c70cf9dae", "shasum": "" }, "require": { - "php": "^5.3.2 || ^7.0" + "php": "^5.3.2 || ^7.0 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5", - "phpunit/phpunit-mock-objects": "2.3.0 || ^3.0" + "phpunit/phpunit": "^4.8.35 || ^5.7 || 6.5 - 7" }, "type": "library", "extra": { @@ -260,27 +261,71 @@ "spdx", "validator" ], - "time": "2018-01-31T13:17:27+00:00" + "time": "2020-02-14T07:44:31+00:00" + }, + { + "name": "composer/xdebug-handler", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "cbe23383749496fe0f373345208b79568e4bc248" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/cbe23383749496fe0f373345208b79568e4bc248", + "reference": "cbe23383749496fe0f373345208b79568e4bc248", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0", + "psr/log": "^1.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || 6.5 - 8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without Xdebug.", + "keywords": [ + "Xdebug", + "performance" + ], + "time": "2019-11-06T16:40:04+00:00" }, { "name": "justinrainbow/json-schema", - "version": "5.2.7", + "version": "5.2.9", "source": { "type": "git", "url": "https://github.com/justinrainbow/json-schema.git", - "reference": "8560d4314577199ba51bf2032f02cd1315587c23" + "reference": "44c6787311242a979fa15c704327c20e7221a0e4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/8560d4314577199ba51bf2032f02cd1315587c23", - "reference": "8560d4314577199ba51bf2032f02cd1315587c23", + "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/44c6787311242a979fa15c704327c20e7221a0e4", + "reference": "44c6787311242a979fa15c704327c20e7221a0e4", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^2.1", + "friendsofphp/php-cs-fixer": "~2.2.20||~2.15.1", "json-schema/json-schema-test-suite": "1.2.0", "phpunit/phpunit": "^4.8.35" }, @@ -326,20 +371,20 @@ "json", "schema" ], - "time": "2018-02-14T22:26:30+00:00" + "time": "2019-09-25T14:49:45+00:00" }, { - "name": "psr/log", - "version": "1.0.2", + "name": "psr/container", + "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" + "url": "https://github.com/php-fig/container.git", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", "shasum": "" }, "require": { @@ -353,7 +398,7 @@ }, "autoload": { "psr-4": { - "Psr\\Log\\": "Psr/Log/" + "Psr\\Container\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -366,41 +411,43 @@ "homepage": "http://www.php-fig.org/" } ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", "keywords": [ - "log", - "psr", - "psr-3" + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" ], - "time": "2016-10-10T12:19:37+00:00" + "time": "2017-02-14T16:28:37+00:00" }, { - "name": "seld/cli-prompt", - "version": "1.0.3", + "name": "psr/log", + "version": "1.1.2", "source": { "type": "git", - "url": "https://github.com/Seldaek/cli-prompt.git", - "reference": "a19a7376a4689d4d94cab66ab4f3c816019ba8dd" + "url": "https://github.com/php-fig/log.git", + "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/cli-prompt/zipball/a19a7376a4689d4d94cab66ab4f3c816019ba8dd", - "reference": "a19a7376a4689d4d94cab66ab4f3c816019ba8dd", + "url": "https://api.github.com/repos/php-fig/log/zipball/446d54b4cb6bf489fc9d75f55843658e6f25d801", + "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801", "shasum": "" }, "require": { - "php": ">=5.3" + "php": ">=5.3.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.x-dev" + "dev-master": "1.1.x-dev" } }, "autoload": { "psr-4": { - "Seld\\CliPrompt\\": "src/" + "Psr\\Log\\": "Psr/Log/" } }, "notification-url": "https://packagist.org/downloads/", @@ -409,32 +456,31 @@ ], "authors": [ { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be" + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" } ], - "description": "Allows you to prompt for user input on the command line, and optionally hide the characters they type", + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", "keywords": [ - "cli", - "console", - "hidden", - "input", - "prompt" + "log", + "psr", + "psr-3" ], - "time": "2017-03-18T11:32:45+00:00" + "time": "2019-11-01T11:05:21+00:00" }, { "name": "seld/jsonlint", - "version": "1.7.1", + "version": "1.7.2", "source": { "type": "git", "url": "https://github.com/Seldaek/jsonlint.git", - "reference": "d15f59a67ff805a44c50ea0516d2341740f81a38" + "reference": "e2e5d290e4d2a4f0eb449f510071392e00e10d19" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/d15f59a67ff805a44c50ea0516d2341740f81a38", - "reference": "d15f59a67ff805a44c50ea0516d2341740f81a38", + "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/e2e5d290e4d2a4f0eb449f510071392e00e10d19", + "reference": "e2e5d290e4d2a4f0eb449f510071392e00e10d19", "shasum": "" }, "require": { @@ -470,20 +516,20 @@ "parser", "validator" ], - "time": "2018-01-24T12:46:19+00:00" + "time": "2019-10-24T14:27:39+00:00" }, { "name": "seld/phar-utils", - "version": "1.0.1", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/Seldaek/phar-utils.git", - "reference": "7009b5139491975ef6486545a39f3e6dad5ac30a" + "reference": "8800503d56b9867d43d9c303b9cbcc26016e82f0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/phar-utils/zipball/7009b5139491975ef6486545a39f3e6dad5ac30a", - "reference": "7009b5139491975ef6486545a39f3e6dad5ac30a", + "url": "https://api.github.com/repos/Seldaek/phar-utils/zipball/8800503d56b9867d43d9c303b9cbcc26016e82f0", + "reference": "8800503d56b9867d43d9c303b9cbcc26016e82f0", "shasum": "" }, "require": { @@ -512,51 +558,58 @@ ], "description": "PHAR file format utilities, for when PHP phars you up", "keywords": [ - "phra" + "phar" ], - "time": "2015-10-13T18:44:15+00:00" + "time": "2020-02-14T15:25:33+00:00" }, { "name": "symfony/console", - "version": "v3.3.6", + "version": "v4.4.4", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "b0878233cb5c4391347e5495089c7af11b8e6201" + "reference": "f512001679f37e6a042b51897ed24a2f05eba656" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/b0878233cb5c4391347e5495089c7af11b8e6201", - "reference": "b0878233cb5c4391347e5495089c7af11b8e6201", + "url": "https://api.github.com/repos/symfony/console/zipball/f512001679f37e6a042b51897ed24a2f05eba656", + "reference": "f512001679f37e6a042b51897ed24a2f05eba656", "shasum": "" }, "require": { - "php": ">=5.5.9", - "symfony/debug": "~2.8|~3.0", - "symfony/polyfill-mbstring": "~1.0" + "php": "^7.1.3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php73": "^1.8", + "symfony/service-contracts": "^1.1|^2" }, "conflict": { - "symfony/dependency-injection": "<3.3" + "symfony/dependency-injection": "<3.4", + "symfony/event-dispatcher": "<4.3|>=5", + "symfony/lock": "<4.4", + "symfony/process": "<3.3" + }, + "provide": { + "psr/log-implementation": "1.0" }, "require-dev": { "psr/log": "~1.0", - "symfony/config": "~3.3", - "symfony/dependency-injection": "~3.3", - "symfony/event-dispatcher": "~2.8|~3.0", - "symfony/filesystem": "~2.8|~3.0", - "symfony/http-kernel": "~2.8|~3.0", - "symfony/process": "~2.8|~3.0" + "symfony/config": "^3.4|^4.0|^5.0", + "symfony/dependency-injection": "^3.4|^4.0|^5.0", + "symfony/event-dispatcher": "^4.3", + "symfony/lock": "^4.4|^5.0", + "symfony/process": "^3.4|^4.0|^5.0", + "symfony/var-dumper": "^4.3|^5.0" }, "suggest": { "psr/log": "For using the console logger", "symfony/event-dispatcher": "", - "symfony/filesystem": "", + "symfony/lock": "", "symfony/process": "" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "4.4-dev" } }, "autoload": { @@ -583,41 +636,35 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2017-07-29T21:27:59+00:00" + "time": "2020-01-25T12:44:29+00:00" }, { - "name": "symfony/debug", - "version": "v3.3.6", + "name": "symfony/filesystem", + "version": "v4.4.4", "source": { "type": "git", - "url": "https://github.com/symfony/debug.git", - "reference": "7c13ae8ce1e2adbbd574fc39de7be498e1284e13" + "url": "https://github.com/symfony/filesystem.git", + "reference": "266c9540b475f26122b61ef8b23dd9198f5d1cfd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/7c13ae8ce1e2adbbd574fc39de7be498e1284e13", - "reference": "7c13ae8ce1e2adbbd574fc39de7be498e1284e13", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/266c9540b475f26122b61ef8b23dd9198f5d1cfd", + "reference": "266c9540b475f26122b61ef8b23dd9198f5d1cfd", "shasum": "" }, "require": { - "php": ">=5.5.9", - "psr/log": "~1.0" - }, - "conflict": { - "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" - }, - "require-dev": { - "symfony/http-kernel": "~2.8|~3.0" + "php": "^7.1.3", + "symfony/polyfill-ctype": "~1.8" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "4.4-dev" } }, "autoload": { "psr-4": { - "Symfony\\Component\\Debug\\": "" + "Symfony\\Component\\Filesystem\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -637,36 +684,36 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Debug Component", + "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2017-07-28T15:27:31+00:00" + "time": "2020-01-21T08:20:44+00:00" }, { - "name": "symfony/filesystem", - "version": "v3.3.6", + "name": "symfony/finder", + "version": "v4.4.4", "source": { "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "427987eb4eed764c3b6e38d52a0f87989e010676" + "url": "https://github.com/symfony/finder.git", + "reference": "3a50be43515590faf812fbd7708200aabc327ec3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/427987eb4eed764c3b6e38d52a0f87989e010676", - "reference": "427987eb4eed764c3b6e38d52a0f87989e010676", + "url": "https://api.github.com/repos/symfony/finder/zipball/3a50be43515590faf812fbd7708200aabc327ec3", + "reference": "3a50be43515590faf812fbd7708200aabc327ec3", "shasum": "" }, "require": { - "php": ">=5.5.9" + "php": "^7.1.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "4.4-dev" } }, "autoload": { "psr-4": { - "Symfony\\Component\\Filesystem\\": "" + "Symfony\\Component\\Finder\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -686,39 +733,42 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Filesystem Component", + "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2017-07-11T07:17:58+00:00" + "time": "2020-01-04T13:00:46+00:00" }, { - "name": "symfony/finder", - "version": "v3.3.6", + "name": "symfony/polyfill-ctype", + "version": "v1.14.0", "source": { "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "baea7f66d30854ad32988c11a09d7ffd485810c4" + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "fbdeaec0df06cf3d51c93de80c7eb76e271f5a38" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/baea7f66d30854ad32988c11a09d7ffd485810c4", - "reference": "baea7f66d30854ad32988c11a09d7ffd485810c4", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/fbdeaec0df06cf3d51c93de80c7eb76e271f5a38", + "reference": "fbdeaec0df06cf3d51c93de80c7eb76e271f5a38", "shasum": "" }, "require": { - "php": ">=5.5.9" + "php": ">=5.3.3" + }, + "suggest": { + "ext-ctype": "For best performance" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "1.14-dev" } }, "autoload": { "psr-4": { - "Symfony\\Component\\Finder\\": "" + "Symfony\\Polyfill\\Ctype\\": "" }, - "exclude-from-classmap": [ - "/Tests/" + "files": [ + "bootstrap.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -727,30 +777,36 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Finder Component", + "description": "Symfony polyfill for ctype functions", "homepage": "https://symfony.com", - "time": "2017-06-01T21:01:25+00:00" + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "time": "2020-01-13T11:15:53+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.7.0", + "version": "v1.14.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b" + "reference": "34094cfa9abe1f0f14f48f490772db7a775559f2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/78be803ce01e55d3491c1397cf1c64beb9c1b63b", - "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/34094cfa9abe1f0f14f48f490772db7a775559f2", + "reference": "34094cfa9abe1f0f14f48f490772db7a775559f2", "shasum": "" }, "require": { @@ -762,7 +818,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.7-dev" + "dev-master": "1.14-dev" } }, "autoload": { @@ -796,29 +852,87 @@ "portable", "shim" ], - "time": "2018-01-30T19:27:44+00:00" + "time": "2020-01-13T11:15:53+00:00" + }, + { + "name": "symfony/polyfill-php73", + "version": "v1.14.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "5e66a0fa1070bf46bec4bea7962d285108edd675" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/5e66a0fa1070bf46bec4bea7962d285108edd675", + "reference": "5e66a0fa1070bf46bec4bea7962d285108edd675", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.14-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php73\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2020-01-13T11:15:53+00:00" }, { "name": "symfony/process", - "version": "v3.3.6", + "version": "v4.4.4", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "07432804942b9f6dd7b7377faf9920af5f95d70a" + "reference": "f5697ab4cb14a5deed7473819e63141bf5352c36" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/07432804942b9f6dd7b7377faf9920af5f95d70a", - "reference": "07432804942b9f6dd7b7377faf9920af5f95d70a", + "url": "https://api.github.com/repos/symfony/process/zipball/f5697ab4cb14a5deed7473819e63141bf5352c36", + "reference": "f5697ab4cb14a5deed7473819e63141bf5352c36", "shasum": "" }, "require": { - "php": ">=5.5.9" + "php": "^7.1.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "4.4-dev" } }, "autoload": { @@ -845,41 +959,96 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2017-07-13T13:05:09+00:00" + "time": "2020-01-09T09:50:08+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v2.0.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "144c5e51266b281231e947b51223ba14acf1a749" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/144c5e51266b281231e947b51223ba14acf1a749", + "reference": "144c5e51266b281231e947b51223ba14acf1a749", + "shasum": "" + }, + "require": { + "php": "^7.2.5", + "psr/container": "^1.0" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + } + }, + "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": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2019-11-18T17:27:11+00:00" }, { "name": "twig/twig", - "version": "v2.4.8", + "version": "v3.0.3", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "7b604c89da162034bdf4bb66310f358d313dd16d" + "reference": "3b88ccd180a6b61ebb517aea3b1a8906762a1dc2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/7b604c89da162034bdf4bb66310f358d313dd16d", - "reference": "7b604c89da162034bdf4bb66310f358d313dd16d", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/3b88ccd180a6b61ebb517aea3b1a8906762a1dc2", + "reference": "3b88ccd180a6b61ebb517aea3b1a8906762a1dc2", "shasum": "" }, "require": { - "php": "^7.0", - "symfony/polyfill-mbstring": "~1.0" + "php": "^7.2.5", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-mbstring": "^1.3" }, "require-dev": { "psr/container": "^1.0", - "symfony/debug": "^2.7", - "symfony/phpunit-bridge": "^3.3" + "symfony/phpunit-bridge": "^4.4|^5.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.4-dev" + "dev-master": "3.0-dev" } }, "autoload": { - "psr-0": { - "Twig_": "lib/" - }, "psr-4": { "Twig\\": "src/" } @@ -895,52 +1064,51 @@ "homepage": "http://fabien.potencier.org", "role": "Lead Developer" }, + { + "name": "Twig Team", + "role": "Contributors" + }, { "name": "Armin Ronacher", "email": "armin.ronacher@active-4.com", "role": "Project Founder" - }, - { - "name": "Twig Team", - "homepage": "http://twig.sensiolabs.org/contributors", - "role": "Contributors" } ], "description": "Twig, the flexible, fast, and secure template language for PHP", - "homepage": "http://twig.sensiolabs.org", + "homepage": "https://twig.symfony.com", "keywords": [ "templating" ], - "time": "2018-04-02T09:24:19+00:00" + "time": "2020-02-11T15:33:47+00:00" } ], "packages-dev": [ { "name": "doctrine/annotations", - "version": "v1.4.0", + "version": "v1.8.0", "source": { "type": "git", "url": "https://github.com/doctrine/annotations.git", - "reference": "54cacc9b81758b14e3ce750f205a393d52339e97" + "reference": "904dca4eb10715b92569fbcd79e201d5c349b6bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/54cacc9b81758b14e3ce750f205a393d52339e97", - "reference": "54cacc9b81758b14e3ce750f205a393d52339e97", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/904dca4eb10715b92569fbcd79e201d5c349b6bc", + "reference": "904dca4eb10715b92569fbcd79e201d5c349b6bc", "shasum": "" }, "require": { "doctrine/lexer": "1.*", - "php": "^5.6 || ^7.0" + "php": "^7.1" }, "require-dev": { "doctrine/cache": "1.*", - "phpunit/phpunit": "^5.7" + "phpunit/phpunit": "^7.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4.x-dev" + "dev-master": "1.7.x-dev" } }, "autoload": { @@ -953,6 +1121,10 @@ "MIT" ], "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, { "name": "Roman Borschel", "email": "roman@code-factory.org" @@ -961,10 +1133,6 @@ "name": "Benjamin Eberlei", "email": "kontakt@beberlei.de" }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, { "name": "Jonathan Wage", "email": "jonwage@gmail.com" @@ -981,36 +1149,38 @@ "docblock", "parser" ], - "time": "2017-02-24T16:22:25+00:00" + "time": "2019-10-01T18:55:10+00:00" }, { "name": "doctrine/instantiator", - "version": "1.0.5", + "version": "1.3.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" + "reference": "ae466f726242e637cebdd526a7d991b9433bacf1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/ae466f726242e637cebdd526a7d991b9433bacf1", + "reference": "ae466f726242e637cebdd526a7d991b9433bacf1", "shasum": "" }, "require": { - "php": ">=5.3,<8.0-DEV" + "php": "^7.1" }, "require-dev": { - "athletic/athletic": "~0.1.8", + "doctrine/coding-standard": "^6.0", "ext-pdo": "*", "ext-phar": "*", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~2.0" + "phpbench/phpbench": "^0.13", + "phpstan/phpstan-phpunit": "^0.11", + "phpstan/phpstan-shim": "^0.11", + "phpunit/phpunit": "^7.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.2.x-dev" } }, "autoload": { @@ -1030,39 +1200,44 @@ } ], "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://github.com/doctrine/instantiator", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", "keywords": [ "constructor", "instantiate" ], - "time": "2015-06-14T21:17:01+00:00" + "time": "2019-10-21T16:45:58+00:00" }, { "name": "doctrine/lexer", - "version": "v1.0.1", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/doctrine/lexer.git", - "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c" + "reference": "5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c", - "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6", + "reference": "5242d66dbeb21a30dd8a3e66bf7a73b66e05e1f6", "shasum": "" }, "require": { - "php": ">=5.3.2" + "php": "^7.2" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "phpstan/phpstan": "^0.11.8", + "phpunit/phpunit": "^8.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.2.x-dev" } }, "autoload": { - "psr-0": { - "Doctrine\\Common\\Lexer\\": "lib/" + "psr-4": { + "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" } }, "notification-url": "https://packagist.org/downloads/", @@ -1070,85 +1245,86 @@ "MIT" ], "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, { "name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com" }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, { "name": "Johannes Schmitt", "email": "schmittjoh@gmail.com" } ], - "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.", - "homepage": "http://www.doctrine-project.org", + "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" + "parser", + "php" ], - "time": "2014-09-09T13:34:57+00:00" + "time": "2019-10-30T14:39:59+00:00" }, { "name": "friendsofphp/php-cs-fixer", - "version": "v2.11.1", + "version": "v2.16.1", "source": { "type": "git", "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", - "reference": "ad94441c17b8ef096e517acccdbf3238af8a2da8" + "reference": "c8afb599858876e95e8ebfcd97812d383fa23f02" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/ad94441c17b8ef096e517acccdbf3238af8a2da8", - "reference": "ad94441c17b8ef096e517acccdbf3238af8a2da8", + "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/c8afb599858876e95e8ebfcd97812d383fa23f02", + "reference": "c8afb599858876e95e8ebfcd97812d383fa23f02", "shasum": "" }, "require": { "composer/semver": "^1.4", + "composer/xdebug-handler": "^1.2", "doctrine/annotations": "^1.2", "ext-json": "*", "ext-tokenizer": "*", - "php": "^5.6 || >=7.0 <7.3", + "php": "^5.6 || ^7.0", "php-cs-fixer/diff": "^1.3", - "symfony/console": "^3.2 || ^4.0", - "symfony/event-dispatcher": "^3.0 || ^4.0", - "symfony/filesystem": "^3.0 || ^4.0", - "symfony/finder": "^3.0 || ^4.0", - "symfony/options-resolver": "^3.0 || ^4.0", + "symfony/console": "^3.4.17 || ^4.1.6 || ^5.0", + "symfony/event-dispatcher": "^3.0 || ^4.0 || ^5.0", + "symfony/filesystem": "^3.0 || ^4.0 || ^5.0", + "symfony/finder": "^3.0 || ^4.0 || ^5.0", + "symfony/options-resolver": "^3.0 || ^4.0 || ^5.0", "symfony/polyfill-php70": "^1.0", "symfony/polyfill-php72": "^1.4", - "symfony/process": "^3.0 || ^4.0", - "symfony/stopwatch": "^3.0 || ^4.0" - }, - "conflict": { - "hhvm": "*" + "symfony/process": "^3.0 || ^4.0 || ^5.0", + "symfony/stopwatch": "^3.0 || ^4.0 || ^5.0" }, "require-dev": { "johnkary/phpunit-speedtrap": "^1.1 || ^2.0 || ^3.0", "justinrainbow/json-schema": "^5.0", - "keradus/cli-executor": "^1.0", + "keradus/cli-executor": "^1.2", "mikey179/vfsstream": "^1.6", - "php-coveralls/php-coveralls": "^2.0", + "php-coveralls/php-coveralls": "^2.1", "php-cs-fixer/accessible-object": "^1.0", - "phpunit/phpunit": "^5.7.23 || ^6.4.3 || ^7.0", - "phpunitgoodpractices/traits": "^1.3.1", - "symfony/phpunit-bridge": "^3.2.2 || ^4.0" + "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.1", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.1", + "phpunit/phpunit": "^5.7.27 || ^6.5.14 || ^7.1", + "phpunitgoodpractices/traits": "^1.8", + "symfony/phpunit-bridge": "^4.3 || ^5.0", + "symfony/yaml": "^3.0 || ^4.0 || ^5.0" }, "suggest": { "ext-mbstring": "For handling non-UTF8 characters in cache signature.", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "For IsIdenticalString constraint.", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "For XmlMatchesXsd constraint.", "symfony/polyfill-mbstring": "When enabling `ext-mbstring` is not possible." }, "bin": [ "php-cs-fixer" ], "type": "application", - "extra": { - "branch-alias": { - "dev-master": "2.11-dev" - } - }, "autoload": { "psr-4": { "PhpCsFixer\\": "src/" @@ -1158,9 +1334,6 @@ "tests/Test/AbstractIntegrationCaseFactory.php", "tests/Test/AbstractIntegrationTestCase.php", "tests/Test/Assert/AssertTokensTrait.php", - "tests/Test/Constraint/SameStringsConstraint.php", - "tests/Test/Constraint/SameStringsConstraintForV5.php", - "tests/Test/Constraint/SameStringsConstraintForV7.php", "tests/Test/IntegrationCase.php", "tests/Test/IntegrationCaseFactory.php", "tests/Test/IntegrationCaseFactoryInterface.php", @@ -1173,37 +1346,37 @@ "MIT" ], "authors": [ - { - "name": "Dariusz Rumiński", - "email": "dariusz.ruminski@gmail.com" - }, { "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", - "time": "2018-03-21T17:41:26+00:00" + "time": "2019-11-25T22:10:32+00:00" }, { - "name": "mikey179/vfsStream", - "version": "v1.6.5", + "name": "mikey179/vfsstream", + "version": "v1.6.8", "source": { "type": "git", - "url": "https://github.com/mikey179/vfsStream.git", - "reference": "d5fec95f541d4d71c4823bb5e30cf9b9e5b96145" + "url": "https://github.com/bovigo/vfsStream.git", + "reference": "231c73783ebb7dd9ec77916c10037eff5a2b6efe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mikey179/vfsStream/zipball/d5fec95f541d4d71c4823bb5e30cf9b9e5b96145", - "reference": "d5fec95f541d4d71c4823bb5e30cf9b9e5b96145", + "url": "https://api.github.com/repos/bovigo/vfsStream/zipball/231c73783ebb7dd9ec77916c10037eff5a2b6efe", + "reference": "231c73783ebb7dd9ec77916c10037eff5a2b6efe", "shasum": "" }, "require": { "php": ">=5.3.0" }, "require-dev": { - "phpunit/phpunit": "~4.5" + "phpunit/phpunit": "^4.5|^5.0" }, "type": "library", "extra": { @@ -1229,29 +1402,32 @@ ], "description": "Virtual file system to mock the real file system in unit tests.", "homepage": "http://vfs.bovigo.org/", - "time": "2017-08-01T08:02:14+00:00" + "time": "2019-10-30T15:31:00+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.7.0", + "version": "1.9.5", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e" + "reference": "b2c28789e80a97badd14145fda39b545d83ca3ef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", - "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/b2c28789e80a97badd14145fda39b545d83ca3ef", + "reference": "b2c28789e80a97badd14145fda39b545d83ca3ef", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "php": "^7.1" + }, + "replace": { + "myclabs/deep-copy": "self.version" }, "require-dev": { "doctrine/collections": "^1.0", "doctrine/common": "^2.6", - "phpunit/phpunit": "^4.1" + "phpunit/phpunit": "^7.1" }, "type": "library", "autoload": { @@ -1274,37 +1450,33 @@ "object", "object graph" ], - "time": "2017-10-19T19:58:43+00:00" + "time": "2020-01-17T21:11:47+00:00" }, { "name": "paragonie/random_compat", - "version": "v2.0.12", + "version": "v9.99.99", "source": { "type": "git", "url": "https://github.com/paragonie/random_compat.git", - "reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb" + "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/258c89a6b97de7dfaf5b8c7607d0478e236b04fb", - "reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", + "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", "shasum": "" }, "require": { - "php": ">=5.2.0" + "php": "^7" }, "require-dev": { - "phpunit/phpunit": "4.*|5.*" + "phpunit/phpunit": "4.*|5.*", + "vimeo/psalm": "^1" }, "suggest": { "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." }, "type": "library", - "autoload": { - "files": [ - "lib/random.php" - ] - }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" @@ -1319,29 +1491,30 @@ "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", "keywords": [ "csprng", + "polyfill", "pseudorandom", "random" ], - "time": "2018-04-04T21:24:14+00:00" + "time": "2018-07-02T15:55:56+00:00" }, { "name": "phar-io/manifest", - "version": "1.0.1", + "version": "1.0.3", "source": { "type": "git", "url": "https://github.com/phar-io/manifest.git", - "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0" + "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/2df402786ab5368a0169091f61a7c1e0eb6852d0", - "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", + "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", "shasum": "" }, "require": { "ext-dom": "*", "ext-phar": "*", - "phar-io/version": "^1.0.1", + "phar-io/version": "^2.0", "php": "^5.6 || ^7.0" }, "type": "library", @@ -1377,20 +1550,20 @@ } ], "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "time": "2017-03-05T18:14:27+00:00" + "time": "2018-07-08T19:23:20+00:00" }, { "name": "phar-io/version", - "version": "1.0.1", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/phar-io/version.git", - "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df" + "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/a70c0ced4be299a63d32fa96d9281d03e94041df", - "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df", + "url": "https://api.github.com/repos/phar-io/version/zipball/45a2ec53a73c70ce41d55cedef9063630abaf1b6", + "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6", "shasum": "" }, "require": { @@ -1424,7 +1597,7 @@ } ], "description": "Library for handling version information and constraints", - "time": "2017-03-05T17:38:23+00:00" + "time": "2018-07-08T19:19:57+00:00" }, { "name": "php-cs-fixer/diff", @@ -1479,35 +1652,33 @@ }, { "name": "phpdocumentor/reflection-common", - "version": "1.0.1", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" + "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/63a995caa1ca9e5590304cd845c15ad6d482a62a", + "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a", "shasum": "" }, "require": { - "php": ">=5.5" + "php": ">=7.1" }, "require-dev": { - "phpunit/phpunit": "^4.6" + "phpunit/phpunit": "~6" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.x-dev" } }, "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src" - ] + "phpDocumentor\\Reflection\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1529,44 +1700,42 @@ "reflection", "static analysis" ], - "time": "2017-09-11T18:02:19+00:00" + "time": "2018-08-07T13:53:10+00:00" }, { "name": "phpdocumentor/reflection-docblock", - "version": "4.3.0", + "version": "5.0.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "94fd0001232e47129dd3504189fa1c7225010d08" + "reference": "a48807183a4b819072f26e347bbd0b5199a9d15f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94fd0001232e47129dd3504189fa1c7225010d08", - "reference": "94fd0001232e47129dd3504189fa1c7225010d08", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/a48807183a4b819072f26e347bbd0b5199a9d15f", + "reference": "a48807183a4b819072f26e347bbd0b5199a9d15f", "shasum": "" }, "require": { - "php": "^7.0", - "phpdocumentor/reflection-common": "^1.0.0", - "phpdocumentor/type-resolver": "^0.4.0", - "webmozart/assert": "^1.0" + "ext-filter": "^7.1", + "php": "^7.2", + "phpdocumentor/reflection-common": "^2.0", + "phpdocumentor/type-resolver": "^1.0", + "webmozart/assert": "^1" }, "require-dev": { - "doctrine/instantiator": "~1.0.5", - "mockery/mockery": "^1.0", - "phpunit/phpunit": "^6.4" + "doctrine/instantiator": "^1", + "mockery/mockery": "^1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.x-dev" + "dev-master": "5.x-dev" } }, "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] + "phpDocumentor\\Reflection\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -1577,44 +1746,47 @@ { "name": "Mike van Riel", "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "account@ijaap.nl" } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2017-11-30T07:14:17+00:00" + "time": "2020-02-09T09:16:15+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "0.4.0", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" + "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/2e32a6d48972b2c1976ed5d8967145b6cec4a4a9", + "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9", "shasum": "" }, "require": { - "php": "^5.5 || ^7.0", - "phpdocumentor/reflection-common": "^1.0" + "php": "^7.1", + "phpdocumentor/reflection-common": "^2.0" }, "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^5.2||^4.8.24" + "ext-tokenizer": "^7.1", + "mockery/mockery": "~1", + "phpunit/phpunit": "^7.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.x-dev" } }, "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] + "phpDocumentor\\Reflection\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -1627,42 +1799,43 @@ "email": "me@mikevanriel.com" } ], - "time": "2017-07-14T14:27:02+00:00" + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "time": "2019-08-22T18:11:29+00:00" }, { "name": "phpspec/prophecy", - "version": "1.7.5", + "version": "v1.10.2", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "dfd6be44111a7c41c2e884a336cc4f461b3b2401" + "reference": "b4400efc9d206e83138e2bb97ed7f5b14b831cd9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/dfd6be44111a7c41c2e884a336cc4f461b3b2401", - "reference": "dfd6be44111a7c41c2e884a336cc4f461b3b2401", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/b4400efc9d206e83138e2bb97ed7f5b14b831cd9", + "reference": "b4400efc9d206e83138e2bb97ed7f5b14b831cd9", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", - "sebastian/comparator": "^1.1|^2.0", - "sebastian/recursion-context": "^1.0|^2.0|^3.0" + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0", + "sebastian/comparator": "^1.2.3|^2.0|^3.0|^4.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0|^4.0" }, "require-dev": { - "phpspec/phpspec": "^2.5|^3.2", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5" + "phpspec/phpspec": "^2.5 || ^3.2", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.7.x-dev" + "dev-master": "1.10.x-dev" } }, "autoload": { - "psr-0": { - "Prophecy\\": "src/" + "psr-4": { + "Prophecy\\": "src/Prophecy" } }, "notification-url": "https://packagist.org/downloads/", @@ -1690,44 +1863,45 @@ "spy", "stub" ], - "time": "2018-02-19T10:16:54+00:00" + "time": "2020-01-20T15:57:02+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "5.3.2", + "version": "8.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "c89677919c5dd6d3b3852f230a663118762218ac" + "reference": "278b6e876467da2e6b5e5390a2310391618ebc10" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/c89677919c5dd6d3b3852f230a663118762218ac", - "reference": "c89677919c5dd6d3b3852f230a663118762218ac", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/278b6e876467da2e6b5e5390a2310391618ebc10", + "reference": "278b6e876467da2e6b5e5390a2310391618ebc10", "shasum": "" }, "require": { "ext-dom": "*", "ext-xmlwriter": "*", - "php": "^7.0", - "phpunit/php-file-iterator": "^1.4.2", - "phpunit/php-text-template": "^1.2.1", - "phpunit/php-token-stream": "^2.0.1", - "sebastian/code-unit-reverse-lookup": "^1.0.1", - "sebastian/environment": "^3.0", - "sebastian/version": "^2.0.1", - "theseer/tokenizer": "^1.1" + "php": "^7.3", + "phpunit/php-file-iterator": "^3.0", + "phpunit/php-text-template": "^2.0", + "phpunit/php-token-stream": "^4.0", + "sebastian/code-unit-reverse-lookup": "^2.0", + "sebastian/environment": "^5.0", + "sebastian/version": "^3.0", + "theseer/tokenizer": "^1.1.3" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^9.0" }, "suggest": { - "ext-xdebug": "^2.5.5" + "ext-pcov": "*", + "ext-xdebug": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.3.x-dev" + "dev-master": "8.0-dev" } }, "autoload": { @@ -1753,29 +1927,32 @@ "testing", "xunit" ], - "time": "2018-04-06T15:36:58+00:00" + "time": "2020-02-07T06:03:55+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "1.4.5", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" + "reference": "354d4a5faa7449a377a18b94a2026ca3415e3d7a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", - "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/354d4a5faa7449a377a18b94a2026ca3415e3d7a", + "reference": "354d4a5faa7449a377a18b94a2026ca3415e3d7a", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4.x-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -1790,7 +1967,7 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -1800,26 +1977,84 @@ "filesystem", "iterator" ], - "time": "2017-11-27T13:52:08+00:00" + "time": "2020-02-07T06:05:22+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "7579d5a1ba7f3ac11c80004d205877911315ae7a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/7579d5a1ba7f3ac11c80004d205877911315ae7a", + "reference": "7579d5a1ba7f3ac11c80004d205877911315ae7a", + "shasum": "" + }, + "require": { + "php": "^7.3" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^9.0" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "time": "2020-02-07T06:06:11+00:00" }, { "name": "phpunit/php-text-template", - "version": "1.2.1", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + "reference": "526dc996cc0ebdfa428cd2dfccd79b7b53fee346" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/526dc996cc0ebdfa428cd2dfccd79b7b53fee346", + "reference": "526dc996cc0ebdfa428cd2dfccd79b7b53fee346", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^7.3" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -1841,32 +2076,32 @@ "keywords": [ "template" ], - "time": "2015-06-21T13:50:34+00:00" + "time": "2020-02-01T07:43:44+00:00" }, { "name": "phpunit/php-timer", - "version": "1.0.9", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" + "reference": "4118013a4d0f97356eae8e7fb2f6c6472575d1df" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/4118013a4d0f97356eae8e7fb2f6c6472575d1df", + "reference": "4118013a4d0f97356eae8e7fb2f6c6472575d1df", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "php": "^7.3" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -1881,7 +2116,7 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -1890,33 +2125,33 @@ "keywords": [ "timer" ], - "time": "2017-02-26T11:10:40+00:00" + "time": "2020-02-07T06:08:11+00:00" }, { "name": "phpunit/php-token-stream", - "version": "2.0.2", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "791198a2c6254db10131eecfe8c06670700904db" + "reference": "b2560a0c33f7710e4d7f8780964193e8e8f8effe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/791198a2c6254db10131eecfe8c06670700904db", - "reference": "791198a2c6254db10131eecfe8c06670700904db", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/b2560a0c33f7710e4d7f8780964193e8e8f8effe", + "reference": "b2560a0c33f7710e4d7f8780964193e8e8f8effe", "shasum": "" }, "require": { "ext-tokenizer": "*", - "php": "^7.0" + "php": "^7.3" }, "require-dev": { - "phpunit/phpunit": "^6.2.4" + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -1939,57 +2174,56 @@ "keywords": [ "tokenizer" ], - "time": "2017-11-27T05:48:46+00:00" + "time": "2020-02-07T06:19:00+00:00" }, { "name": "phpunit/phpunit", - "version": "6.4.4", + "version": "9.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "562f7dc75d46510a4ed5d16189ae57fbe45a9932" + "reference": "68d7e5b17a6b9461e17c00446caa409863154f76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/562f7dc75d46510a4ed5d16189ae57fbe45a9932", - "reference": "562f7dc75d46510a4ed5d16189ae57fbe45a9932", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/68d7e5b17a6b9461e17c00446caa409863154f76", + "reference": "68d7e5b17a6b9461e17c00446caa409863154f76", "shasum": "" }, "require": { + "doctrine/instantiator": "^1.2.0", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", - "myclabs/deep-copy": "^1.6.1", - "phar-io/manifest": "^1.0.1", - "phar-io/version": "^1.0", - "php": "^7.0", - "phpspec/prophecy": "^1.7", - "phpunit/php-code-coverage": "^5.2.2", - "phpunit/php-file-iterator": "^1.4.2", - "phpunit/php-text-template": "^1.2.1", - "phpunit/php-timer": "^1.0.9", - "phpunit/phpunit-mock-objects": "^4.0.3", - "sebastian/comparator": "^2.0.2", - "sebastian/diff": "^2.0", - "sebastian/environment": "^3.1", - "sebastian/exporter": "^3.1", - "sebastian/global-state": "^2.0", - "sebastian/object-enumerator": "^3.0.3", - "sebastian/resource-operations": "^1.0", - "sebastian/version": "^2.0.1" - }, - "conflict": { - "phpdocumentor/reflection-docblock": "3.0.2", - "phpunit/dbunit": "<3.0" + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.9.1", + "phar-io/manifest": "^1.0.3", + "phar-io/version": "^2.0.1", + "php": "^7.3", + "phpspec/prophecy": "^1.8.1", + "phpunit/php-code-coverage": "^8.0", + "phpunit/php-file-iterator": "^3.0", + "phpunit/php-invoker": "^3.0", + "phpunit/php-text-template": "^2.0", + "phpunit/php-timer": "^3.0", + "sebastian/comparator": "^4.0", + "sebastian/diff": "^4.0", + "sebastian/environment": "^5.0", + "sebastian/exporter": "^4.0", + "sebastian/global-state": "^4.0", + "sebastian/object-enumerator": "^4.0", + "sebastian/resource-operations": "^3.0", + "sebastian/type": "^2.0", + "sebastian/version": "^3.0" }, "require-dev": { "ext-pdo": "*" }, "suggest": { - "ext-xdebug": "*", - "phpunit/php-invoker": "^1.1" + "ext-soap": "*", + "ext-xdebug": "*" }, "bin": [ "phpunit" @@ -1997,12 +2231,15 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "6.4.x-dev" + "dev-master": "9.0-dev" } }, "autoload": { "classmap": [ "src/" + ], + "files": [ + "src/Framework/Assert/Functions.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -2023,91 +2260,32 @@ "testing", "xunit" ], - "time": "2017-11-08T11:26:09+00:00" - }, - { - "name": "phpunit/phpunit-mock-objects", - "version": "4.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "2f789b59ab89669015ad984afa350c4ec577ade0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/2f789b59ab89669015ad984afa350c4ec577ade0", - "reference": "2f789b59ab89669015ad984afa350c4ec577ade0", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.0.5", - "php": "^7.0", - "phpunit/php-text-template": "^1.2.1", - "sebastian/exporter": "^3.0" - }, - "conflict": { - "phpunit/phpunit": "<6.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.0" - }, - "suggest": { - "ext-soap": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Mock Object library for PHPUnit", - "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", - "keywords": [ - "mock", - "xunit" - ], - "time": "2017-08-03T14:08:16+00:00" + "time": "2020-02-13T07:30:12+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", - "version": "1.0.1", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" + "reference": "5b5dbe0044085ac41df47e79d34911a15b96d82e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", - "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5b5dbe0044085ac41df47e79d34911a15b96d82e", + "reference": "5b5dbe0044085ac41df47e79d34911a15b96d82e", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "php": "^7.3" }, "require-dev": { - "phpunit/phpunit": "^5.7 || ^6.0" + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -2127,34 +2305,34 @@ ], "description": "Looks up which function or method a line of code belongs to", "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "time": "2017-03-04T06:30:41+00:00" + "time": "2020-02-07T06:20:13+00:00" }, { "name": "sebastian/comparator", - "version": "2.1.3", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9" + "reference": "85b3435da967696ed618ff745f32be3ff4a2b8e8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/34369daee48eafb2651bea869b4b15d75ccc35f9", - "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/85b3435da967696ed618ff745f32be3ff4a2b8e8", + "reference": "85b3435da967696ed618ff745f32be3ff4a2b8e8", "shasum": "" }, "require": { - "php": "^7.0", - "sebastian/diff": "^2.0 || ^3.0", - "sebastian/exporter": "^3.1" + "php": "^7.3", + "sebastian/diff": "^4.0", + "sebastian/exporter": "^4.0" }, "require-dev": { - "phpunit/phpunit": "^6.4" + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.1.x-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -2167,6 +2345,10 @@ "BSD-3-Clause" ], "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" @@ -2178,10 +2360,6 @@ { "name": "Bernhard Schussek", "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" } ], "description": "Provides the functionality to compare PHP values for equality", @@ -2191,32 +2369,33 @@ "compare", "equality" ], - "time": "2018-02-01T13:46:46+00:00" + "time": "2020-02-07T06:08:51+00:00" }, { "name": "sebastian/diff", - "version": "2.0.1", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "347c1d8b49c5c3ee30c7040ea6fc446790e6bddd" + "reference": "c0c26c9188b538bfa985ae10c9f05d278f12060d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/347c1d8b49c5c3ee30c7040ea6fc446790e6bddd", - "reference": "347c1d8b49c5c3ee30c7040ea6fc446790e6bddd", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c0c26c9188b538bfa985ae10c9f05d278f12060d", + "reference": "c0c26c9188b538bfa985ae10c9f05d278f12060d", "shasum": "" }, "require": { - "php": "^7.0" + "php": "^7.3" }, "require-dev": { - "phpunit/phpunit": "^6.2" + "phpunit/phpunit": "^9.0", + "symfony/process": "^4 || ^5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -2229,46 +2408,52 @@ "BSD-3-Clause" ], "authors": [ - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" } ], "description": "Diff implementation", "homepage": "https://github.com/sebastianbergmann/diff", "keywords": [ - "diff" + "diff", + "udiff", + "unidiff", + "unified diff" ], - "time": "2017-08-03T08:09:46+00:00" + "time": "2020-02-07T06:09:38+00:00" }, { "name": "sebastian/environment", - "version": "3.1.0", + "version": "5.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5" + "reference": "fea125c3bf7cab63a909990133d425e5a0a61e40" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/cd0871b3975fb7fc44d11314fd1ee20925fce4f5", - "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/fea125c3bf7cab63a909990133d425e5a0a61e40", + "reference": "fea125c3bf7cab63a909990133d425e5a0a61e40", "shasum": "" }, "require": { - "php": "^7.0" + "php": "^7.3" }, "require-dev": { - "phpunit/phpunit": "^6.1" + "phpunit/phpunit": "^9.0" + }, + "suggest": { + "ext-posix": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1.x-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -2293,34 +2478,34 @@ "environment", "hhvm" ], - "time": "2017-07-01T08:51:00+00:00" + "time": "2020-02-07T06:10:11+00:00" }, { "name": "sebastian/exporter", - "version": "3.1.0", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "234199f4528de6d12aaa58b612e98f7d36adb937" + "reference": "80c26562e964016538f832f305b2286e1ec29566" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/234199f4528de6d12aaa58b612e98f7d36adb937", - "reference": "234199f4528de6d12aaa58b612e98f7d36adb937", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/80c26562e964016538f832f305b2286e1ec29566", + "reference": "80c26562e964016538f832f305b2286e1ec29566", "shasum": "" }, "require": { - "php": "^7.0", - "sebastian/recursion-context": "^3.0" + "php": "^7.3", + "sebastian/recursion-context": "^4.0" }, "require-dev": { "ext-mbstring": "*", - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1.x-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -2333,6 +2518,10 @@ "BSD-3-Clause" ], "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" @@ -2341,17 +2530,13 @@ "name": "Volker Dusch", "email": "github@wallbash.com" }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, { "name": "Adam Harvey", "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" } ], "description": "Provides the functionality to export PHP variables for visualization", @@ -2360,27 +2545,30 @@ "export", "exporter" ], - "time": "2017-04-03T13:19:02+00:00" + "time": "2020-02-07T06:10:52+00:00" }, { "name": "sebastian/global-state", - "version": "2.0.0", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" + "reference": "bdb1e7c79e592b8c82cb1699be3c8743119b8a72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", - "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bdb1e7c79e592b8c82cb1699be3c8743119b8a72", + "reference": "bdb1e7c79e592b8c82cb1699be3c8743119b8a72", "shasum": "" }, "require": { - "php": "^7.0" + "php": "^7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "ext-dom": "*", + "phpunit/phpunit": "^9.0" }, "suggest": { "ext-uopz": "*" @@ -2388,7 +2576,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -2411,34 +2599,34 @@ "keywords": [ "global state" ], - "time": "2017-04-27T15:39:26+00:00" + "time": "2020-02-07T06:11:37+00:00" }, { "name": "sebastian/object-enumerator", - "version": "3.0.3", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5" + "reference": "e67516b175550abad905dc952f43285957ef4363" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5", - "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/e67516b175550abad905dc952f43285957ef4363", + "reference": "e67516b175550abad905dc952f43285957ef4363", "shasum": "" }, "require": { - "php": "^7.0", - "sebastian/object-reflector": "^1.1.1", - "sebastian/recursion-context": "^3.0" + "php": "^7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0.x-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -2458,32 +2646,32 @@ ], "description": "Traverses array structures and object graphs to enumerate all referenced objects", "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "time": "2017-08-03T12:35:26+00:00" + "time": "2020-02-07T06:12:23+00:00" }, { "name": "sebastian/object-reflector", - "version": "1.1.1", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "773f97c67f28de00d397be301821b06708fca0be" + "reference": "f4fd0835cabb0d4a6546d9fe291e5740037aa1e7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be", - "reference": "773f97c67f28de00d397be301821b06708fca0be", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/f4fd0835cabb0d4a6546d9fe291e5740037aa1e7", + "reference": "f4fd0835cabb0d4a6546d9fe291e5740037aa1e7", "shasum": "" }, "require": { - "php": "^7.0" + "php": "^7.3" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -2503,32 +2691,32 @@ ], "description": "Allows reflection of object attributes, including inherited and non-public ones", "homepage": "https://github.com/sebastianbergmann/object-reflector/", - "time": "2017-03-29T09:07:27+00:00" + "time": "2020-02-07T06:19:40+00:00" }, { "name": "sebastian/recursion-context", - "version": "3.0.0", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8" + "reference": "cdd86616411fc3062368b720b0425de10bd3d579" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", - "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cdd86616411fc3062368b720b0425de10bd3d579", + "reference": "cdd86616411fc3062368b720b0425de10bd3d579", "shasum": "" }, "require": { - "php": "^7.0" + "php": "^7.3" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0.x-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -2541,14 +2729,14 @@ "BSD-3-Clause" ], "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, { "name": "Adam Harvey", "email": "aharvey@php.net" @@ -2556,29 +2744,32 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2017-03-03T06:23:57+00:00" + "time": "2020-02-07T06:18:20+00:00" }, { "name": "sebastian/resource-operations", - "version": "1.0.0", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" + "reference": "8c98bf0dfa1f9256d0468b9803a1e1df31b6fa98" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", - "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/8c98bf0dfa1f9256d0468b9803a1e1df31b6fa98", + "reference": "8c98bf0dfa1f9256d0468b9803a1e1df31b6fa98", "shasum": "" }, "require": { - "php": ">=5.6.0" + "php": "^7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -2598,29 +2789,75 @@ ], "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "time": "2015-07-28T20:34:47+00:00" + "time": "2020-02-07T06:13:02+00:00" + }, + { + "name": "sebastian/type", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "9e8f42f740afdea51f5f4e8cec2035580e797ee1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/9e8f42f740afdea51f5f4e8cec2035580e797ee1", + "reference": "9e8f42f740afdea51f5f4e8cec2035580e797ee1", + "shasum": "" + }, + "require": { + "php": "^7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "time": "2020-02-07T06:13:43+00:00" }, { "name": "sebastian/version", - "version": "2.0.1", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" + "reference": "0411bde656dce64202b39c2f4473993a9081d39e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/0411bde656dce64202b39c2f4473993a9081d39e", + "reference": "0411bde656dce64202b39c2f4473993a9081d39e", "shasum": "" }, "require": { - "php": ">=5.6" + "php": "^7.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -2641,34 +2878,41 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2016-10-03T07:35:21+00:00" + "time": "2020-01-21T06:36:37+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v3.3.6", + "version": "v4.4.4", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "67535f1e3fd662bdc68d7ba317c93eecd973617e" + "reference": "9e3de195e5bc301704dd6915df55892f6dfc208b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/67535f1e3fd662bdc68d7ba317c93eecd973617e", - "reference": "67535f1e3fd662bdc68d7ba317c93eecd973617e", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/9e3de195e5bc301704dd6915df55892f6dfc208b", + "reference": "9e3de195e5bc301704dd6915df55892f6dfc208b", "shasum": "" }, "require": { - "php": ">=5.5.9" + "php": "^7.1.3", + "symfony/event-dispatcher-contracts": "^1.1" }, "conflict": { - "symfony/dependency-injection": "<3.3" + "symfony/dependency-injection": "<3.4" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "1.1" }, "require-dev": { "psr/log": "~1.0", - "symfony/config": "~2.8|~3.0", - "symfony/dependency-injection": "~3.3", - "symfony/expression-language": "~2.8|~3.0", - "symfony/stopwatch": "~2.8|~3.0" + "symfony/config": "^3.4|^4.0|^5.0", + "symfony/dependency-injection": "^3.4|^4.0|^5.0", + "symfony/expression-language": "^3.4|^4.0|^5.0", + "symfony/http-foundation": "^3.4|^4.0|^5.0", + "symfony/service-contracts": "^1.1|^2", + "symfony/stopwatch": "^3.4|^4.0|^5.0" }, "suggest": { "symfony/dependency-injection": "", @@ -2677,7 +2921,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "4.4-dev" } }, "autoload": { @@ -2704,29 +2948,87 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2017-06-09T14:53:08+00:00" + "time": "2020-01-10T21:54:01+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v1.1.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "c43ab685673fb6c8d84220c77897b1d6cdbe1d18" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/c43ab685673fb6c8d84220c77897b1d6cdbe1d18", + "reference": "c43ab685673fb6c8d84220c77897b1d6cdbe1d18", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "suggest": { + "psr/event-dispatcher": "", + "symfony/event-dispatcher-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "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": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2019-09-17T09:54:03+00:00" }, { "name": "symfony/options-resolver", - "version": "v3.3.6", + "version": "v5.0.4", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "ff48982d295bcac1fd861f934f041ebc73ae40f0" + "reference": "b1ab86ce52b0c0abe031367a173005a025e30e04" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/ff48982d295bcac1fd861f934f041ebc73ae40f0", - "reference": "ff48982d295bcac1fd861f934f041ebc73ae40f0", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/b1ab86ce52b0c0abe031367a173005a025e30e04", + "reference": "b1ab86ce52b0c0abe031367a173005a025e30e04", "shasum": "" }, "require": { - "php": ">=5.5.9" + "php": "^7.2.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -2758,30 +3060,30 @@ "configuration", "options" ], - "time": "2017-04-12T14:14:56+00:00" + "time": "2020-01-04T14:08:26+00:00" }, { "name": "symfony/polyfill-php70", - "version": "v1.8.0", + "version": "v1.14.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php70.git", - "reference": "77454693d8f10dd23bb24955cffd2d82db1007a6" + "reference": "419c4940024c30ccc033650373a1fe13890d3255" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/77454693d8f10dd23bb24955cffd2d82db1007a6", - "reference": "77454693d8f10dd23bb24955cffd2d82db1007a6", + "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/419c4940024c30ccc033650373a1fe13890d3255", + "reference": "419c4940024c30ccc033650373a1fe13890d3255", "shasum": "" }, "require": { - "paragonie/random_compat": "~1.0|~2.0", + "paragonie/random_compat": "~1.0|~2.0|~9.99", "php": ">=5.3.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.8-dev" + "dev-master": "1.14-dev" } }, "autoload": { @@ -2817,20 +3119,20 @@ "portable", "shim" ], - "time": "2018-04-26T10:06:28+00:00" + "time": "2020-01-13T11:15:53+00:00" }, { "name": "symfony/polyfill-php72", - "version": "v1.8.0", + "version": "v1.14.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "a4576e282d782ad82397f3e4ec1df8e0f0cafb46" + "reference": "46ecacf4751dd0dc81e4f6bf01dbf9da1dc1dadf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/a4576e282d782ad82397f3e4ec1df8e0f0cafb46", - "reference": "a4576e282d782ad82397f3e4ec1df8e0f0cafb46", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/46ecacf4751dd0dc81e4f6bf01dbf9da1dc1dadf", + "reference": "46ecacf4751dd0dc81e4f6bf01dbf9da1dc1dadf", "shasum": "" }, "require": { @@ -2839,7 +3141,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.8-dev" + "dev-master": "1.14-dev" } }, "autoload": { @@ -2872,29 +3174,30 @@ "portable", "shim" ], - "time": "2018-04-26T10:06:28+00:00" + "time": "2020-01-13T11:15:53+00:00" }, { "name": "symfony/stopwatch", - "version": "v3.3.6", + "version": "v5.0.4", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "602a15299dc01556013b07167d4f5d3a60e90d15" + "reference": "5d9add8034135b9a5f7b101d1e42c797e7f053e4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/602a15299dc01556013b07167d4f5d3a60e90d15", - "reference": "602a15299dc01556013b07167d4f5d3a60e90d15", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/5d9add8034135b9a5f7b101d1e42c797e7f053e4", + "reference": "5d9add8034135b9a5f7b101d1e42c797e7f053e4", "shasum": "" }, "require": { - "php": ">=5.5.9" + "php": "^7.2.5", + "symfony/service-contracts": "^1.0|^2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -2921,20 +3224,20 @@ ], "description": "Symfony Stopwatch Component", "homepage": "https://symfony.com", - "time": "2017-04-12T14:14:56+00:00" + "time": "2020-01-04T14:08:26+00:00" }, { "name": "theseer/tokenizer", - "version": "1.1.0", + "version": "1.1.3", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b" + "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/cb2f008f3f05af2893a87208fe6a6c4985483f8b", - "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/11336f6f84e16a720dae9d8e6ed5019efa85a0f9", + "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9", "shasum": "" }, "require": { @@ -2961,35 +3264,33 @@ } ], "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "time": "2017-04-07T12:08:54+00:00" + "time": "2019-06-13T22:48:21+00:00" }, { "name": "webmozart/assert", - "version": "1.3.0", + "version": "1.7.0", "source": { "type": "git", "url": "https://github.com/webmozart/assert.git", - "reference": "0df1908962e7a3071564e857d86874dad1ef204a" + "reference": "aed98a490f9a8f78468232db345ab9cf606cf598" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a", - "reference": "0df1908962e7a3071564e857d86874dad1ef204a", + "url": "https://api.github.com/repos/webmozart/assert/zipball/aed98a490f9a8f78468232db345ab9cf606cf598", + "reference": "aed98a490f9a8f78468232db345ab9cf606cf598", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "php": "^5.3.3 || ^7.0", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "vimeo/psalm": "<3.6.0" }, "require-dev": { - "phpunit/phpunit": "^4.6", - "sebastian/version": "^1.0.1" + "phpunit/phpunit": "^4.8.36 || ^7.5.13" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3-dev" - } - }, "autoload": { "psr-4": { "Webmozart\\Assert\\": "src/" @@ -3011,7 +3312,7 @@ "check", "validate" ], - "time": "2018-01-29T19:49:41+00:00" + "time": "2020-02-14T12:15:55+00:00" } ], "aliases": [], @@ -3020,10 +3321,9 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": "^7.0" + "php": "^7.2||^8.0" }, - "platform-dev": [], - "platform-overrides": { - "php": "7.0" + "platform-dev": { + "ext-json": "*" } } diff --git a/docs/_layouts/default.html b/docs/_layouts/default.html index 465c2bbb..cf29552e 100644 --- a/docs/_layouts/default.html +++ b/docs/_layouts/default.html @@ -48,6 +48,9 @@ code { font-size: 80%; } + dl { + margin-left: 1rem; + } diff --git a/docs/config.md b/docs/config.md index 1cec1f4c..38d2d5d7 100644 --- a/docs/config.md +++ b/docs/config.md @@ -4,7 +4,9 @@ permalink: config title: Config --- -## Config +# Config + +## Example ``` { @@ -15,10 +17,11 @@ title: Config "type": "composer", "url": "https://packagist.org" }], + "repositories-dep": [], "require": { "company/package1": "1.2.0", - "company/package2": "1.5.2", - "company/package3": "dev-master" + "company/package2": "^1.5.2", + "company/package3": "dev-master|dev-develop" }, "archive": { "directory": "dist", @@ -28,7 +31,10 @@ title: Config "prefix-url": "https://amazing.cdn.example.org", "whitelist": [ "company/package1" ], "blacklist": [ "company/package2" ], - "checksum": true + "checksum": true, + "ignore-filters": false, + "override-dist-type": true, + "rearchive": true }, "abandoned": { "company/package": true, @@ -45,6 +51,118 @@ title: Config "config": { }, + "strip-hosts": [], "notify-batch": "https://example.com/endpoint" } ``` + +## Keys + +### name + +The name of the Satis repository. Available inside the template as `{% raw %}{{ name }}{% endraw %}`. + +### description + +A brief description of the Satis repository. Available inside the template as `{% raw %}{{ description }}{% endraw %}` + +### homepage + +Available inside the template as `{% raw %}{{ url }}{% endraw %}`. + +### require + +Hash of package name (keys) and version constraint (values) that should be included in the output. + +### archive + +Configuration for creating package archives. + +directory +: The directory in which to output the archives. + +format +: The archive format to use. + +skip-dev +: Whether or not to create archives for development versions. + +absolute-directory +: The directory in which to output the archives (prioritized over **directory** if provided). + +prefix-url +: Hostname (and path) to prefix when generating source url for the archive (defaults to **homepage**). + +whitelist +: List of whitelisted packages (only matching packages will be output). A `*` can be used for wildcard matching. + +blacklist +: List of blacklisted packages (matching packages will be skipped). A `*` can be used for wildcard matching. + +checksum +: Whether or not to generate checksum values. + +ignore-filters +: Whether or not to ignore filters when looking for files in packages. + +override-dist-type +: If true, archive format will be used to substitute the original dist type. + +rearchive +: If true, rearchive packages with a tar or zip dist. + +### abandoned + +A list of packages that will visually be marked as abandoned. Optionally a replacement can be suggested. + +### require-all + +If true, selects all versions of all packages in all repositories defined. + +### require-dependencies + +If true, resolve and add all dependencies of each required package. + +### require-dev-dependencies + +If true, resolve and add all development dependencies of each required package. + +### only-dependencies + +If true, will only resolve and add dependencies, not the root projects listed in "require". + +### only-best-candidates + +Useful with require-dependencies, returns a minimal set of dependencies resulting in a constrained package list. + +### blacklist + +Define a list of packages and versions to suppress in the final packages list. Takes the same format as the `require` section. + +### require-dependency-filter + +If false, will include versions matching a dependency. + +### include-filename + +Filename to use for the json to include, defaults to `include/all${SHA1_HASH}.json`. + +### output-dir + +Directory in which to store repository data. + +### output-html + +If true, generate html output from templates. + +### twig-template + +Path to twig template used for generating html output. + +### providers + +If true, output package providers. This will generate a directory per vendor and a json file per package. + +### pretty-print + +Whether or not to use `JSON_PRETTY_PRINT` when generating json output. diff --git a/docs/contributing.md b/docs/contributing.md index c28cd0d9..bf6c6e71 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -4,7 +4,7 @@ permalink: contributing title: Contributing --- -## Contributing +# Contributing Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms. diff --git a/docs/index.md b/docs/index.md index 4092fa7d..50f74627 100644 --- a/docs/index.md +++ b/docs/index.md @@ -4,24 +4,30 @@ permalink: / title: Introduction --- -## Introduction +# Introduction [](https://github.com/composer/satis) [](https://packagist.org/packages/composer/satis) [](https://travis-ci.org/composer/satis) -Satis is an open source Composer repository generator. It is like an ultra-lightweight static file-based version of Packagist and can be used to host the metadata of your company's private packages, or your own. +Satis is an open source Composer repository generator. It is like an +ultra-lightweight static file-based version of Packagist and can be used to host +the metadata of your company's private packages, or your own. -You can get it from GitHub: +Install and run from source: git clone https://github.com/composer/satis + cd satis composer install + bin/satis -You can install it via CLI: +Install using Composer: - composer create-project composer/satis --stability=dev --keep-vcs + composer create-project composer/satis satis dev-master + cd satis + bin/satis -You can run it as a Docker container: +Run our Docker container: docker pull composer/satis - docker run --rm -it -v /build:/build composer/satis + docker run --rm -it -v :/build composer/satis diff --git a/docs/using.md b/docs/using.md index d195778f..ac57de31 100644 --- a/docs/using.md +++ b/docs/using.md @@ -4,4 +4,329 @@ permalink: using title: Using --- -## Using +# Using + +## Setup + +For example let's assume you have a few packages you want to reuse across your +company but don't really want to open-source. You would first define a Satis +configuration: a json file with an arbitrary name that lists your curated +[repositories](../05-repositories.md). + +Here is an example configuration, you see that it holds a few VCS repositories, +but those could be any types of [repositories](../05-repositories.md). Then it +uses `"require-all": true` which selects all versions of all packages in the +repositories you defined. + +The default file Satis looks for is `satis.json` in the root of the repository. + +```json +{ + "name": "My Repository", + "homepage": "http://packages.example.org", + "repositories": [ + { "type": "vcs", "url": "https://github.com/mycompany/privaterepo" }, + { "type": "vcs", "url": "http://svn.example.org/private/repo" }, + { "type": "vcs", "url": "https://github.com/mycompany/privaterepo2" } + ], + "require-all": true +} +``` + +If you want to cherry pick which packages you want, you can list all the +packages you want to have in your satis repository inside the classic composer +`require` key, using a `"*"` constraint to make sure all versions are selected, +or another constraint if you want really specific versions. + +```json +{ + "repositories": [ + { "type": "vcs", "url": "https://github.com/mycompany/privaterepo" }, + { "type": "vcs", "url": "http://svn.example.org/private/repo" }, + { "type": "vcs", "url": "https://github.com/mycompany/privaterepo2" } + ], + "require": { + "company/package": "*", + "company/package2": "*", + "company/package3": "2.0.0" + } +} +``` + +Once you've done this, you run: + + php bin/satis build + +When you ironed out that process, what you would typically do is run this +command as a cron job on a server. It would then update all your package info +much like Packagist does. + +Note that if your private packages are hosted on GitHub, your server should +have an ssh key that gives it access to those packages, and then you should add +the `--no-interaction` (or `-n`) flag to the command to make sure it falls back +to ssh key authentication instead of prompting for a password. This is also a +good trick for continuous integration servers. + +Set up a virtual-host that points to that `web/` directory, let's say it is +`packages.example.org`. Alternatively, with PHP >= 5.4.0, you can use the +built-in CLI server `php -S localhost:port -t satis-output-dir/` for a +temporary solution. + +### Partial Updates + +You can tell Satis to selectively update only particular packages or process +only a repository with a given URL. This cuts down the time it takes to rebuild +the `package.json` file and is helpful if you use (custom) webhooks to trigger +rebuilds whenever code is pushed into one of your repositories. + +To rebuild only particular packages, pass the package names on the command line +like so: + + php bin/satis build satis.json web/ this/package that/other-package + +Note that this will still need to pull and scan all of your VCS repositories +because any VCS repository might contain (on any branch) one of the selected +packages. + +If you want to scan only the selected package and not all VCS repositories you need +to declare a *name* for all your package (this only work on VCS repositories type) : + +```json +{ + "repositories": [ + { "name": "company/privaterepo", "type": "vcs", "url": "https://github.com/mycompany/privaterepo" }, + { "name": "private/repo", "type": "vcs", "url": "http://svn.example.org/private/repo" }, + { "name": "mycompany/privaterepo2", "type": "vcs", "url": "https://github.com/mycompany/privaterepo2" } + ] +} +``` + +If you want to scan only a single repository and update all packages found in +it, pass the VCS repository URL as an optional argument: + + php bin/satis build --repository-url https://only.my/repo.git satis.json web/ + +## Usage + +In your projects all you need to add now is your own composer repository using +the `packages.example.org` as URL, then you can require your private packages +and everything should work smoothly. You don't need to copy all your +repositories in every project anymore. Only that one unique repository that +will update itself. + +```json +{ + "repositories": [ { "type": "composer", "url": "http://packages.example.org/" } ], + "require": { + "company/package": "1.2.0", + "company/package2": "1.5.2", + "company/package3": "dev-master" + } +} +``` + +### Security + +To secure your private repository you can host it over SSH or SSL using a client +certificate. In your project you can use the `options` parameter to specify the +connection options for the server. + +Example using a custom repository using SSH (requires the SSH2 PECL extension): + +```json +{ + "repositories": [{ + "type": "composer", + "url": "ssh2.sftp://example.org", + "options": { + "ssh2": { + "username": "composer", + "pubkey_file": "/home/composer/.ssh/id_rsa.pub", + "privkey_file": "/home/composer/.ssh/id_rsa" + } + } + }] +} +``` + +> **Tip:** See [ssh2 context options] for more information. + +Example using SSL/TLS (HTTPS) using a client certificate: + +```json +{ + "repositories": [{ + "type": "composer", + "url": "https://example.org", + "options": { + "ssl": { + "local_cert": "/home/composer/.ssl/composer.pem" + } + } + }] +} +``` + +> **Tip:** See [ssl context options] for more information. + +Example using a custom HTTP Header field for token authentication: + +```json +{ + "repositories": [{ + "type": "composer", + "url": "https://example.org", + "options": { + "http": { + "header": [ + "API-TOKEN: YOUR-API-TOKEN" + ] + } + } + }] +} +``` + +### Authentication + +When your private repositories are password protected, you can store the +authentication details permanently. The first time Composer needs to +authenticate against some domain it will prompt you for a username/password and +then you will be asked whether you want to store it. + +The storage can be done either globally in the `COMPOSER_HOME/auth.json` file +(`COMPOSER_HOME` defaults to `~/.composer` or `%APPDATA%/Composer` on Windows) +or also in the project directory directly sitting besides your composer.json. + +You can also configure these by hand using the config command if you need to +configure a production machine to be able to run non-interactive installs. For +example to enter credentials for example.org one could type: + + composer config http-basic.example.org username password + +That will store it in the current directory's auth.json, but if you want it +available globally you can use the `--global` (`-g`) flag. + +### Downloads + +When GitHub, GitLab or BitBucket repositories are mirrored on your local satis, the +build process will include the location of the downloads these platforms make +available. This means that the repository and your setup depend on the +availability of these services. + +At the same time, this implies that all code which is hosted somewhere else (on +another service or for example in Subversion) will not have downloads available +and thus installations usually take a lot longer. + +To enable your satis installation to create downloads for all (Git, Mercurial +and Subversion) your packages, add the following to your `satis.json`: + +``` json +{ + "archive": { + "directory": "dist", + "format": "tar", + "prefix-url": "https://amazing.cdn.example.org", + "skip-dev": true + } +} +``` + +#### Options explained + + * `directory`: required, the location of the dist files (inside the + `output-dir`) + * `format`: optional, `zip` (default) or `tar` + * `prefix-url`: optional, location of the downloads, homepage (from + `satis.json`) followed by `directory` by default + * `skip-dev`: optional, `false` by default, when enabled (`true`) satis will + not create downloads for branches + * `absolute-directory`: optional, a _local_ directory where the dist files are + dumped instead of `output-dir`/`directory` + * `whitelist`: optional, if set as a list of package names, satis will only + dump the dist files of these packages (use `*` for wildcard matching) + * `blacklist`: optional, if set as a list of package names, satis will not + dump the dist files of these packages (use `*` for wildcard matching) + * `checksum`: optional, `true` by default, when disabled (`false`) satis will + not provide the sha1 checksum for the dist files + +Once enabled, all downloads (include those from GitHub and BitBucket) will be +replaced with a _local_ version. + +#### prefix-url + +Prefixing the URL with another host is especially helpful if the downloads end +up in a private Amazon S3 bucket or on a CDN host. A CDN would drastically +improve download times and therefore package installation. + +Example: A `prefix-url` of `https://my-bucket.s3.amazonaws.com` (and +`directory` set to `dist`) creates download URLs which look like the following: +`https://my-bucket.s3.amazonaws.com/dist/vendor-package-version-ref.zip`. + +### Web outputs + + * `output-html`: optional, `true` by default, when disabled (`false`) satis + will not generate the `output-dir`/index.html page. + * `twig-template`: optional, a path to a personalized [Twig] template for + the `output-dir`/index.html page. + +### Abandoned packages + +To enable your satis installation to indicate that some packages are abandoned, +add the following to your `satis.json`: + +```json +{ + "abandoned": { + "company/package": true, + "company/package2": "company/newpackage" + } +} +``` + +The `true` value indicates that the package is truly abandoned while the +`"company/newpackage"` value specifies that the package is replaced by the +`company/newpackage` package. + +Note that all packages set as abandoned in their own `composer.json` file will +be marked abandoned as well. + +### Resolving dependencies + +It is possible to make satis automatically resolve and add all dependencies for +your projects. This can be used with the Downloads functionality to have a +complete local mirror of packages. Add the following to your `satis.json`: + +```json +{ + "require-dependencies": true, + "require-dev-dependencies": true +} +``` + +When searching for packages, satis will attempt to resolve all the required +packages from the listed repositories. Therefore, if you are requiring a +package from Packagist, you will need to define it in your `satis.json`. + +Dev dependencies are packaged only if the `require-dev-dependencies` parameter +is set to true. + +### Other options + + * `providers`: optional, `false` by default, when enabled (`true`) each + package will be dumped into a separate include file which will be only + loaded by composer when the package is really required. Speeds up composer + handling for repositories with huge number of packages like f.i. packagist. + * `output-dir`: optional, defines where to output the repository files if not + provided as an argument when calling the `build` command. + * `config`: optional, lets you define all config options from composer, except + `archive-format` and `archive-dir` as the configuration is done through + [archive](#downloads) instead. See docs on [config schema] for more details. + * `notify-batch`: optional, specify a URL that will be called every time a + user installs a package. See [notify-batch]. + +[ssh2 context options]: https://secure.php.net/manual/en/wrappers.ssh2.php#refsect1-wrappers.ssh2-options +[ssl context options]: https://secure.php.net/manual/en/context.ssl.php +[Twig]: https://twig.sensiolabs.org/ +[config schema]: https://getcomposer.org/doc/04-schema.md#config +[notify-batch]: https://getcomposer.org/doc/05-repositories.md#notify-batch diff --git a/package.json b/package.json new file mode 100644 index 00000000..45e45eee --- /dev/null +++ b/package.json @@ -0,0 +1,19 @@ +{ + "devDependencies": { + "@symfony/webpack-encore": "^0.28.0", + "bootstrap": "^4.1.3", + "date-fns": "^2.0.0", + "jquery": "^3.3.1", + "node-sass": "^4.9.4", + "popper.js": "^1.14.3", + "sass-loader": "^8.0.0" + }, + "license": "MIT", + "private": true, + "scripts": { + "dev-server": "encore dev-server", + "dev": "encore dev", + "watch": "encore dev --watch", + "build": "encore production" + } +} diff --git a/php-cli.ini b/php-cli.ini new file mode 100644 index 00000000..015b71fb --- /dev/null +++ b/php-cli.ini @@ -0,0 +1,38 @@ +; Maximum amount of memory a script may consume +memory_limit = -1 + +; This directive informs PHP of which errors, warnings and notices you would like +; it to take action for. The recommended way of setting values for this +; directive is through the use of the error level constants and bitwise +; operators. +error_reporting = -1 + +; This directive controls whether or not and where PHP will output errors, +; notices and warnings too. Error output is very useful during development, but +; it could be very dangerous in production environments. Depending on the code +; which is triggering the error, sensitive information could potentially leak +; out of your application such as database usernames and passwords or worse. +; For production environments, we recommend logging errors rather than +; sending them to STDOUT. +display_errors = on + +; The display of errors which occur during PHP's startup sequence are handled +; separately from display_errors. PHP's default behavior is to suppress those +; errors from clients. Turning the display of startup errors on can be useful in +; debugging configuration problems. We strongly recommend you +; set this to 'off' for production servers. +display_startup_errors = on + +; Besides displaying errors, PHP can also log errors to locations such as a +; server-specific log, STDERR, or a location specified by the error_log +; directive found below. While errors should not be displayed on productions +; servers they should still be monitored and logging is a great way to do that. +log_errors = on + +; Log errors to specified file. PHP's default behavior is to leave this value +; empty. +error_log = /tmp/php.log + +; Set maximum length of log_errors. In error_log information about the source is +; added. The default is 1024 and 0 allows to not apply any maximum length at all. +log_errors_max_len = 0 diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 34c4da77..c49cc539 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,7 +1,7 @@ + diff --git a/res/satis-schema.json b/res/satis-schema.json index e274f3e7..6868680f 100644 --- a/res/satis-schema.json +++ b/res/satis-schema.json @@ -76,6 +76,14 @@ "ignore-filters": { "type": "boolean", "description": "Ignore filters when looking for files in the package." + }, + "override-dist-type": { + "type": "boolean", + "description": "If true, archive format will be used to substitute dist type when generating archive file name." + }, + "rearchive": { + "type": "boolean", + "description": "Create new archives for packages with a tar or zip dist, defaults to true" } } }, @@ -84,11 +92,26 @@ "description": "A set of additional repositories where packages can be found.", "additionalProperties": true }, + "repositories-dep": { + "type": ["object", "array"], + "description": "A set of additional repositories where packages for dependencies can be found.", + "additionalProperties": true + }, "minimum-stability": { "type": "string", "description": "The minimum stability the packages must have to be install-able. Possible values are: dev, alpha, beta, RC, stable.", "enum": [ "dev", "alpha", "beta", "rc", "RC", "stable" ] }, + "minimum-stability-per-package": { + "type": "object", + "description": "This is a hash of package name (keys) and minimum stability (values).", + "minProperties": 1, + "additionalProperties": { + "type": "string", + "description": "The minimum stability the package must have to be install-able. Possible values are: dev, alpha, beta, RC, stable. This overrides the \"minimum-stability\" global option for the specified package.", + "enum": [ "dev", "alpha", "beta", "rc", "RC", "stable" ] + } + }, "abandoned": { "type": "object", "description": "List of packages marked as abandoned for this repository, the mark can be boolean or a package name/URL pointing to a recommended alternative.", @@ -97,6 +120,15 @@ "description": "A valid Package name" } }, + "blacklist": { + "type": "object", + "description": "This is a hash of package name (keys) and version constraints (values) to exclude after selecting packages.", + "minProperties": 1, + "additionalProperties": { + "type": "string", + "description": "A valid version constraint" + } + }, "require-all": { "type": "boolean", "description": "If true, selects all versions of all packages in the repositories defined." @@ -109,6 +141,25 @@ "type": "boolean", "description": "If true, resolve and add all Dev dependencies of each required package." }, + "only-dependencies": { + "type": "boolean", + "description": "If true, will not require the root dependencies only their dependencies." + }, + "only-best-candidates": { + "type": "boolean", + "description": "If true, will only resolve best candidates amongst dependencies." + }, + "require-dependency-filter": { + "type": "boolean", + "description": "If false, will include all versions matching a dependency." + }, + "strip-hosts": { + "type": ["array", "boolean"], + "description": "List of domains, IPs, CIDR notations, '/local' (=localnet and other reserved) or '/private' (=private IPs) to be stripped from the output. If set and non-false, local file paths are removed too.", + "items": { + "type": "string" + } + }, "include-filename": { "type": "string", "description": "Specify filename instead of default include/all${SHA1_HASH}.json" @@ -201,7 +252,7 @@ }, "cache-vcs-dir": { "type": "string", - "description": "The location where vcs infos (git clones, github api calls, etc. when reading vcs repos) are cached, defaults to \"{$cache-dir}/vcs\"." + "description": "The location where vcs info (git clones, github api calls, etc. when reading vcs repos) are cached, defaults to \"{$cache-dir}/vcs\"." }, "cache-ttl": { "type": "integer", @@ -260,6 +311,10 @@ "_comment": { "type": ["array", "string"], "description": "A key to store comments in" + }, + "pretty-print": { + "type": "boolean", + "description": "Defaults to true. When false, the JSON_PRETTY_PRINT option will not be used on encoding." } } } diff --git a/src/Builder/ArchiveBuilder.php b/src/Builder/ArchiveBuilder.php index b7fa7cdf..b32c9e4a 100644 --- a/src/Builder/ArchiveBuilder.php +++ b/src/Builder/ArchiveBuilder.php @@ -1,5 +1,7 @@ - */ class ArchiveBuilder extends Builder { /** @var Composer A Composer instance. */ private $composer; - /** @var InputInterface */ private $input; - /** - * {@inheritdoc} - */ - public function dump(array $packages) + public function dump(array $packages): void { $helper = new ArchiveBuilderHelper($this->output, $this->config['archive']); $basedir = $helper->getDirectory($this->outputDir); $this->output->writeln(sprintf("Creating local downloads in '%s'", $basedir)); - $format = $this->config['archive']['format'] ?? 'zip'; $endpoint = $this->config['archive']['prefix-url'] ?? $this->config['homepage']; $includeArchiveChecksum = (bool) ($this->config['archive']['checksum'] ?? true); - $ignoreFilters = (bool) ($this->config['archive']['ignore-filters'] ?? false); $composerConfig = $this->composer->getConfig(); $factory = new Factory(); - /* @var \Composer\Downloader\DownloadManager $downloadManager */ + /* @var DownloadManager $downloadManager */ $downloadManager = $this->composer->getDownloadManager(); - /* @var \Composer\Package\Archiver\ArchiveManager $archiveManager */ + /* @var ArchiveManager $archiveManager */ $archiveManager = $factory->createArchiveManager($composerConfig, $downloadManager); $archiveManager->setOverwriteFiles(false); @@ -73,7 +68,7 @@ public function dump(array $packages) ); } - /* @var \Composer\Package\CompletePackage $package */ + /* @var CompletePackage $package */ foreach ($packages as $package) { if ($helper->isSkippable($package)) { continue; @@ -105,6 +100,7 @@ public function dump(array $packages) } $intermediatePath = preg_replace('#[^a-z0-9-_/]#i', '-', $package->getName()); + $packageName = $archiveManager->getPackageFilename($package); if ('pear-library' === $package->getType()) { @@ -115,8 +111,8 @@ public function dump(array $packages) realpath($basedir), $intermediatePath, $packageName, - pathinfo($package->getDistUrl(), PATHINFO_EXTENSION)) - ; + pathinfo($package->getDistUrl(), PATHINFO_EXTENSION) + ); if (!file_exists($path)) { $downloadDir = sys_get_temp_dir() . '/composer_archiver/' . $packageName; @@ -130,8 +126,10 @@ public function dump(array $packages) // Set archive format to `file` to tell composer to download it as is $archiveFormat = 'file'; } else { - $path = $archiveManager->archive($package, $format, sprintf('%s/%s', $basedir, $intermediatePath), null, $ignoreFilters); - $archiveFormat = $format; + $targetDir = sprintf('%s/%s', $basedir, $intermediatePath); + + $path = $this->archive($downloadManager, $archiveManager, $package, $targetDir); + $archiveFormat = pathinfo($path, PATHINFO_EXTENSION); } $archive = basename($path); @@ -167,29 +165,75 @@ public function dump(array $packages) } } - /** - * Sets the Composer instance. - * - * @param Composer $composer A Composer instance - * - * @return $this - */ - public function setComposer(Composer $composer) + public function setComposer(Composer $composer): self { $this->composer = $composer; return $this; } - /** - * @param InputInterface $input - * - * @return $this; - */ - public function setInput(InputInterface $input) + public function setInput(InputInterface $input): self { $this->input = $input; return $this; } + + private function archive(DownloadManager $downloadManager, ArchiveManager $archiveManager, PackageInterface $package, string $targetDir): string + { + $format = (string) ($this->config['archive']['format'] ?? 'zip'); + $ignoreFilters = (bool) ($this->config['archive']['ignore-filters'] ?? false); + $overrideDistType = (bool) ($this->config['archive']['override-dist-type'] ?? false); + $rearchive = (bool) ($this->config['archive']['rearchive'] ?? true); + + $filesystem = new Filesystem(); + $filesystem->ensureDirectoryExists($targetDir); + $targetDir = realpath($targetDir); + + if ($overrideDistType) { + $originalDistType = $package->getDistType(); + $package->setDistType($format); + $packageName = $overriddenPackageName = $archiveManager->getPackageFilename($package); + $package->setDistType($originalDistType); + } else { + $packageName = $archiveManager->getPackageFilename($package); + } + + $path = $targetDir . '/' . $packageName . '.' . $format; + if (file_exists($path)) { + return $path; + } + + if (!$rearchive && in_array($distType = $package->getDistType(), ['tar', 'zip'], true)) { + if ($overrideDistType) { + $packageName = $archiveManager->getPackageFilename($package); + } + + $path = $targetDir . '/' . $packageName . '.' . $distType; + if (file_exists($path)) { + return $path; + } + + $downloadDir = sys_get_temp_dir() . '/composer_archiver' . uniqid(); + $filesystem->ensureDirectoryExists($downloadDir); + $downloader = $downloadManager->getDownloader('file'); + $downloader->download($package, $downloadDir); + + $filesystem->ensureDirectoryExists(dirname($path)); + $filesystem->rename($downloadDir . '/' . pathinfo($package->getDistUrl(), PATHINFO_BASENAME), $path); + $filesystem->removeDirectory($downloadDir); + + return $path; + } + + if ($overrideDistType) { + $path = $targetDir . '/' . $packageName . '.' . $format; + $downloaded = $archiveManager->archive($package, $format, $targetDir, null, $ignoreFilters); + $filesystem->rename($downloaded, $path); + + return $path; + } + + return $archiveManager->archive($package, $format, $targetDir, null, $ignoreFilters); + } } diff --git a/src/Builder/ArchiveBuilderHelper.php b/src/Builder/ArchiveBuilderHelper.php index a2c14166..6936a902 100644 --- a/src/Builder/ArchiveBuilderHelper.php +++ b/src/Builder/ArchiveBuilderHelper.php @@ -1,5 +1,7 @@ - */ class ArchiveBuilderHelper { /** @var OutputInterface The output Interface. */ private $output; - /** @var array The 'archive' part of a configuration file. */ private $archiveConfig; - /** - * Helper Constructor. - * - * @param OutputInterface $output The output Interface - * @param array $archiveConfig The 'archive' part of a configuration file - */ public function __construct(OutputInterface $output, array $archiveConfig) { $this->output = $output; @@ -42,14 +32,7 @@ public function __construct(OutputInterface $output, array $archiveConfig) $this->archiveConfig['blacklist'] = (array) ($archiveConfig['blacklist'] ?? []); } - /** - * Gets the directory where to dump archives. - * - * @param string $outputDir The directory where to build - * - * @return string $directory The directory where to dump archives - */ - public function getDirectory($outputDir) + public function getDirectory(string $outputDir): string { if (isset($this->archiveConfig['absolute-directory'])) { $directory = $this->archiveConfig['absolute-directory']; @@ -60,14 +43,7 @@ public function getDirectory($outputDir) return $directory; } - /** - * Tells if a package has to be dumped or not. - * - * @param PackageInterface $package The package to be dumped - * - * @return bool false if the package has to be dumped - */ - public function isSkippable(PackageInterface $package) + public function isSkippable(PackageInterface $package): bool { if ('metapackage' === $package->getType()) { return true; @@ -98,17 +74,7 @@ public function isSkippable(PackageInterface $package) return false; } - /** - * Check if any of the names is in the list. - * - * Any * in the list is treated as a wildcard. - * - * @param array $names Names to check - * @param array $list List to check the names against - * - * @return bool true if any of the names is in the list - */ - protected function isOneOfNamesInList(array $names, array $list) + protected function isOneOfNamesInList(array $names, array $list): bool { $patterns = $this->convertListToRegexPatterns($list); @@ -121,15 +87,7 @@ protected function isOneOfNamesInList(array $names, array $list) return false; } - /** - * Check if the name matches any of the patterns. - * - * @param string $name Name to check - * @param array $patterns Patterns to check the name against - * - * @return bool true if the name matches any of the patterns - */ - protected function doesNameMatchOneOfPatterns($name, array $patterns) + protected function doesNameMatchOneOfPatterns(string $name, array $patterns): bool { foreach ($patterns as $pattern) { if (preg_match($pattern, $name)) { @@ -140,16 +98,7 @@ protected function doesNameMatchOneOfPatterns($name, array $patterns) return false; } - /** - * Convert a list to regex patterns for use in preg_ functions. - * - * Any * is replaced with .* and the rest is escaped. - * - * @param array $list List to convert to patterns - * - * @return array array of patterns - */ - protected function convertListToRegexPatterns(array $list) + protected function convertListToRegexPatterns(array $list): array { $patterns = []; diff --git a/src/Builder/Builder.php b/src/Builder/Builder.php index a1b2485a..70083b34 100644 --- a/src/Builder/Builder.php +++ b/src/Builder/Builder.php @@ -1,5 +1,7 @@ - */ abstract class Builder implements BuilderInterface { /** @var OutputInterface $output The output Interface. */ protected $output; - /** @var string $outputDir The directory where to build. */ protected $outputDir; - /** @var array $config The parameters from ./satis.json. */ protected $config; - /** @var bool $skipErrors Skips Exceptions if true. */ protected $skipErrors; - /** - * Base Constructor. - * - * @param OutputInterface $output The output Interface - * @param string $outputDir The directory where to build - * @param array $config The parameters from ./satis.json - * @param bool $skipErrors Skips Exceptions if true - */ - public function __construct(OutputInterface $output, $outputDir, $config, $skipErrors) + public function __construct(OutputInterface $output, string $outputDir, array $config, bool $skipErrors) { $this->output = $output; $this->outputDir = $outputDir; $this->config = $config; - $this->skipErrors = (bool) $skipErrors; + $this->skipErrors = $skipErrors; } } diff --git a/src/Builder/BuilderInterface.php b/src/Builder/BuilderInterface.php index 15c1c206..ba985f0b 100644 --- a/src/Builder/BuilderInterface.php +++ b/src/Builder/BuilderInterface.php @@ -1,5 +1,7 @@ - */ interface BuilderInterface { /** diff --git a/src/Builder/PackagesBuilder.php b/src/Builder/PackagesBuilder.php index dc3b257b..45d669fc 100644 --- a/src/Builder/PackagesBuilder.php +++ b/src/Builder/PackagesBuilder.php @@ -1,5 +1,7 @@ - */ class PackagesBuilder extends Builder { /** @var string packages.json file name. */ private $filename; - /** @var string included json filename template */ private $includeFileName; - + /** @var array */ private $writtenIncludeJsons = []; - /** - * Dedicated Packages Constructor. - * - * @param OutputInterface $output The output Interface - * @param string $outputDir The directory where to build - * @param array $config The parameters from ./satis.json - * @param bool $skipErrors Escapes Exceptions if true - */ - public function __construct(OutputInterface $output, $outputDir, $config, $skipErrors) + public function __construct(OutputInterface $output, string $outputDir, array $config, bool $skipErrors) { parent::__construct($output, $outputDir, $config, $skipErrors); @@ -47,11 +36,9 @@ public function __construct(OutputInterface $output, $outputDir, $config, $skipE } /** - * Builds the JSON stuff of the repository. - * - * @param \Composer\Package\PackageInterface[] $packages List of packages to dump + * @param PackageInterface[] $packages List of packages to dump */ - public function dump(array $packages) + public function dump(array $packages): void { $packagesByName = []; $dumper = new ArrayDumper(); @@ -95,15 +82,7 @@ public function dump(array $packages) $this->pruneIncludeDirectories(); } - /** - * Find packages replacing the $replaced packages - * - * @param array $packages - * @param string $replaced - * - * @return array - */ - private function findReplacements($packages, $replaced) + private function findReplacements(array $packages, string $replaced): array { $replacements = []; foreach ($packages as $packageName => $packageConfig) { @@ -118,10 +97,7 @@ private function findReplacements($packages, $replaced) return $replacements; } - /** - * Remove all files matching the includeUrl pattern next to just created include jsons - */ - private function pruneIncludeDirectories() + private function pruneIncludeDirectories(): void { $this->output->writeln('Pruning include directories'); $paths = []; @@ -181,23 +157,18 @@ function (\SplFileInfo $fileA, \SplFileInfo $fileB) { } } - /** - * Writes includes JSON Files. - * - * @param array $packages List of packages to dump - * @param string $includesUrl The includes url (optionally containing %hash%) - * @param string $hashAlgorithm Hash algorithm {@see hash()} - * - * @return array The object for includes key in packages.json - */ - private function dumpPackageIncludeJson(array $packages, $includesUrl, $hashAlgorithm = 'sha1') + private function dumpPackageIncludeJson(array $packages, string $includesUrl, string $hashAlgorithm = 'sha1'): array { $filename = str_replace('%hash%', 'prep', $includesUrl); $path = $tmpPath = $this->outputDir . '/' . ltrim($filename, '/'); $repoJson = new JsonFile($path); - $contents = $repoJson->encode(['packages' => $packages]) . "\n"; + $options = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES; + if ($this->config['pretty-print'] ?? true) { + $options |= JSON_PRETTY_PRINT; + } + $contents = $repoJson->encode(['packages' => $packages], $options) . "\n"; $hash = hash($hashAlgorithm, $contents); if (false !== strpos($includesUrl, '%hash%')) { @@ -209,9 +180,10 @@ private function dumpPackageIncludeJson(array $packages, $includesUrl, $hashAlgo $path = null; } } + if ($path) { $this->writeToFile($path, $contents); - $this->output->writeln("wrote packages to $path"); + $this->output->writeln("Wrote packages to $path"); } return [ @@ -220,15 +192,10 @@ private function dumpPackageIncludeJson(array $packages, $includesUrl, $hashAlgo } /** - * Write to a file - * - * @param string $path - * @param string $contents - * * @throws \UnexpectedValueException * @throws \Exception */ - private function writeToFile($path, $contents) + private function writeToFile(string $path, string $contents): void { $dir = dirname($path); if (!is_dir($dir)) { @@ -261,11 +228,9 @@ private function writeToFile($path, $contents) } /** - * Writes the packages.json of the repository. - * * @param array $repo Repository information */ - private function dumpPackagesJson($repo) + private function dumpPackagesJson(array $repo): void { if (isset($this->config['notify-batch'])) { $repo['notify-batch'] = $this->config['notify-batch']; diff --git a/src/Builder/WebBuilder.php b/src/Builder/WebBuilder.php index 5e06e9ff..60f17a15 100644 --- a/src/Builder/WebBuilder.php +++ b/src/Builder/WebBuilder.php @@ -1,5 +1,7 @@ - */ class WebBuilder extends Builder { /** @var RootPackageInterface Root package used to build the pages. */ private $rootPackage; - /** @var PackageInterface[] List of calculated required packages. */ private $dependencies; - - /** @var \Twig_Environment */ + /** @var Environment */ private $twig; - /** - * {@inheritdoc} - */ - public function dump(array $packages) + public function dump(array $packages): void { $mappedPackages = $this->getMappedPackageList($packages); @@ -64,60 +58,34 @@ public function dump(array $packages) file_put_contents($this->outputDir . '/index.html', $content); } - /** - * Defines the root package of the repository. - * - * @param RootPackageInterface $rootPackage The root package - * - * @return $this - */ - public function setRootPackage(RootPackageInterface $rootPackage) + public function setRootPackage(RootPackageInterface $rootPackage): self { $this->rootPackage = $rootPackage; return $this; } - /** - * Sets the twig environment. - * - * @param \Twig_Environment $twig - * - * @return $this - */ - public function setTwigEnvironment(\Twig_Environment $twig) + public function setTwigEnvironment(Environment $twig): self { $this->twig = $twig; return $this; } - /** - * Gets the twig environment. - * - * Creates default if needed. - * - * @return \Twig_Environment - */ - private function getTwigEnvironment() + private function getTwigEnvironment(): Environment { if (null === $this->twig) { $twigTemplate = $this->config['twig-template'] ?? null; $templateDir = $twigTemplate ? pathinfo($twigTemplate, PATHINFO_DIRNAME) : __DIR__ . '/../../views'; - $loader = new \Twig_Loader_Filesystem($templateDir); - $this->twig = new \Twig_Environment($loader); + $loader = new FilesystemLoader($templateDir); + $this->twig = new Environment($loader); } return $this->twig; } - /** - * Gets the twig template name. - * - * @return string - */ - private function getTwigTemplate() + private function getTwigTemplate(): string { $twigTemplate = $this->config['twig-template'] ?? null; @@ -131,7 +99,7 @@ private function getTwigTemplate() * * @return $this */ - private function setDependencies(array $packages) + private function setDependencies(array $packages): self { $dependencies = []; foreach ($packages as $package) { @@ -152,7 +120,7 @@ private function setDependencies(array $packages) * * @return array Grouped list of packages with versions */ - private function getMappedPackageList(array $packages) + private function getMappedPackageList(array $packages): array { $groupedPackages = $this->groupPackagesByName($packages); @@ -178,7 +146,7 @@ private function getMappedPackageList(array $packages) * * @return array List of packages grouped by name */ - private function groupPackagesByName(array $packages) + private function groupPackagesByName(array $packages): array { $groupedPackages = []; foreach ($packages as $package) { @@ -195,7 +163,7 @@ private function groupPackagesByName(array $packages) * * @return PackageInterface The package with the highest version */ - private function getHighestVersion(array $packages) + private function getHighestVersion(array $packages): ?PackageInterface { /** @var $highestVersion PackageInterface|null */ $highestVersion = null; @@ -215,7 +183,7 @@ private function getHighestVersion(array $packages) * * @return PackageInterface[] Sorted list of packages by version */ - private function getDescSortedVersions(array $packages) + private function getDescSortedVersions(array $packages): array { usort($packages, function (PackageInterface $a, PackageInterface $b) { return version_compare($b->getVersion(), $a->getVersion()); diff --git a/src/Console/Application.php b/src/Console/Application.php index e586193e..930653df 100644 --- a/src/Console/Application.php +++ b/src/Console/Application.php @@ -1,5 +1,7 @@ - */ class Application extends BaseApplication { /** @var IOInterface */ protected $io; - /** @var Composer */ protected $composer; @@ -38,10 +36,7 @@ public function __construct() parent::__construct('Satis', Satis::VERSION); } - /** - * {@inheritdoc} - */ - public function doRun(InputInterface $input, OutputInterface $output) + public function doRun(InputInterface $input, OutputInterface $output): int { $styles = Factory::createAdditionalStyles(); foreach ($styles as $name => $style) { @@ -55,13 +50,13 @@ public function doRun(InputInterface $input, OutputInterface $output) } /** - * @param bool $required Not used - * @param array|string|null $config either a configuration array or a filename to read from, - * if null it will read from the default filename + * @param bool $required + * @param array|string|null $config + * Either a configuration array or a filename to read from, if null it will read from the default filename * * @return Composer */ - public function getComposer($required = true, $config = null) + public function getComposer(bool $required = true, $config = null): Composer { if (null === $this->composer) { try { @@ -75,10 +70,7 @@ public function getComposer($required = true, $config = null) return $this->composer; } - /** - * {@inheritdoc} - */ - protected function getDefaultCommands() + protected function getDefaultCommands(): array { $commands = array_merge(parent::getDefaultCommands(), [ new Command\InitCommand(), diff --git a/src/Console/Command/AddCommand.php b/src/Console/Command/AddCommand.php index 1a34f8d2..1f4ad08b 100644 --- a/src/Console/Command/AddCommand.php +++ b/src/Console/Command/AddCommand.php @@ -1,5 +1,7 @@ - */ class AddCommand extends BaseCommand { protected function configure() @@ -34,6 +34,8 @@ protected function configure() ->setDefinition([ new InputArgument('url', InputArgument::REQUIRED, 'VCS repository URL'), new InputArgument('file', InputArgument::OPTIONAL, 'JSON file to use', './satis.json'), + new InputOption('type', null, InputOption::VALUE_OPTIONAL, 'VCS driver (see https://getcomposer.org/doc/05-repositories.md#git-alternatives)', 'vcs'), + new InputOption('name', null, InputOption::VALUE_OPTIONAL, 'The name of the repository, will be added to satis.json', null), ]) ->setHelp(<<<'EOT' The add command adds given repository URL to the json file @@ -44,19 +46,15 @@ protected function configure() ; } - /** - * @param InputInterface $input The input instance - * @param OutputInterface $output The output instance - * - * @return int - */ - protected function execute(InputInterface $input, OutputInterface $output) + protected function execute(InputInterface $input, OutputInterface $output): int { /** @var FormatterHelper $formatter */ $formatter = $this->getHelper('formatter'); $configFile = $input->getArgument('file'); $repositoryUrl = $input->getArgument('url'); + $vcsDriver = $input->getOption('type'); + $repositoryName = $input->getOption('name'); if (preg_match('{^https?://}i', $configFile)) { $output->writeln('Unable to write to remote file ' . $configFile . ''); @@ -71,7 +69,7 @@ protected function execute(InputInterface $input, OutputInterface $output) return 1; } - if (!$this->isRepositoryValid($repositoryUrl)) { + if (!$this->isRepositoryValid($repositoryUrl, $vcsDriver)) { $output->writeln('Invalid Repository URL: ' . $repositoryUrl . ''); return 3; @@ -84,13 +82,25 @@ protected function execute(InputInterface $input, OutputInterface $output) foreach ($config['repositories'] as $repository) { if (isset($repository['url']) && $repository['url'] == $repositoryUrl) { - $output->writeln('Repository already added to the file'); + $output->writeln('Repository url already added to the file'); return 4; } + + if (isset($repository['name']) && $repository['name'] == $repositoryName) { + $output->writeln('Repository name already added to the file'); + + return 5; + } + } + + $repositoryConfig = ['type' => $vcsDriver, 'url' => $repositoryUrl]; + + if (!empty($repositoryName)) { + $repositoryConfig['name'] = $repositoryName; } - $config['repositories'][] = ['type' => 'vcs', 'url' => $repositoryUrl]; + $config['repositories'][] = $repositoryConfig; $file->write($config); @@ -103,19 +113,12 @@ protected function execute(InputInterface $input, OutputInterface $output) return 0; } - /** - * Validate repository URL - * - * @param $repositoryUrl - * - * @return bool - */ - protected function isRepositoryValid($repositoryUrl) + protected function isRepositoryValid(string $repositoryUrl, string $type): bool { $io = new NullIO(); $config = Factory::createConfig(); $io->loadConfiguration($config); - $repository = new VcsRepository(['url' => $repositoryUrl], $io, $config); + $repository = new VcsRepository(['url' => $repositoryUrl, 'type' => $type], $io, $config); if (!($driver = $repository->getDriver())) { return false; diff --git a/src/Console/Command/BuildCommand.php b/src/Console/Command/BuildCommand.php index b16b502d..5312cba9 100644 --- a/src/Console/Command/BuildCommand.php +++ b/src/Console/Command/BuildCommand.php @@ -1,5 +1,7 @@ - */ class BuildCommand extends BaseCommand { protected function configure() @@ -45,6 +44,7 @@ protected function configure() new InputArgument('output-dir', InputArgument::OPTIONAL, 'Location where to output built files', null), new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Packages that should be built. If not provided, all packages are built.', null), new InputOption('repository-url', null, InputOption::VALUE_OPTIONAL, 'Only update the repository at given url', null), + new InputOption('repository-strict', null, InputOption::VALUE_NONE, 'Also apply the repository filter when resolving dependencies'), new InputOption('no-html-output', null, InputOption::VALUE_NONE, 'Turn off HTML view'), new InputOption('skip-errors', null, InputOption::VALUE_NONE, 'Skip Download or Archive errors'), new InputOption('stats', null, InputOption::VALUE_NONE, 'Display the download progress bar'), @@ -58,6 +58,7 @@ protected function configure() - "repositories": defines which repositories are searched for packages. +- "repositories-dep": define additional repositories for dependencies - "output-dir": where to output the repository files if not provided as an argument when calling build. - "require-all": boolean, if true, all packages present @@ -74,8 +75,12 @@ protected function configure() requirements' dependencies. - "require-dev-dependencies": works like require-dependencies but requires dev requirements rather than regular ones. +- "only-dependencies": only require dependencies - choose this if you want to build + a mirror of your project's dependencies without building packages for the main project repositories. - "config": all config options from composer, see http://getcomposer.org/doc/04-schema.md#config +- "strip-hosts": boolean or an array of domains, IPs, CIDR notations, '/local' (=localnet and other reserved) + or '/private' (=private IPs) to be stripped from the output. If set and non-false, local file paths are removed too. - "output-html": boolean, controls whether the repository has an html page as well or not. - "name": for html output, this defines the name of the @@ -86,6 +91,7 @@ protected function configure() building the html output. - "abandoned": Packages that are abandoned. As the key use the package name, as the value use true or the replacement package. +- "blacklist": Packages and versions which should be excluded from the final package list. - "notify-batch": Allows you to specify a URL that will be called every time a user installs a package, see https://getcomposer.org/doc/05-repositories.md#notify-batch @@ -97,16 +103,11 @@ protected function configure() } /** - * @param InputInterface $input The input instance - * @param OutputInterface $output The output instance - * * @throws JsonValidationException * @throws ParsingException * @throws \Exception - * - * @return int */ - protected function execute(InputInterface $input, OutputInterface $output) + protected function execute(InputInterface $input, OutputInterface $output): int { $verbose = $input->getOption('verbose'); $configFile = $input->getArgument('file'); @@ -175,7 +176,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $packageSelection = new PackageSelection($output, $outputDir, $config, $skipErrors); if (null !== $repositoryUrl) { - $packageSelection->setRepositoryFilter($repositoryUrl); + $packageSelection->setRepositoryFilter($repositoryUrl, (bool) $input->getOption('repository-strict')); } else { $packageSelection->setPackagesFilter($packagesFilter); } @@ -189,6 +190,8 @@ protected function execute(InputInterface $input, OutputInterface $output) $downloads->dump($packages); } + $packages = $packageSelection->clean(); + if ($packageSelection->hasFilterForPackages() || $packageSelection->hasRepositoryFilter()) { // in case of an active filter we need to load the dumped packages.json and merge the // updated packages in @@ -213,10 +216,7 @@ protected function execute(InputInterface $input, OutputInterface $output) return 0; } - /** - * @return Config - */ - private function getConfiguration() + private function getConfiguration(): Config { $config = new Config(); @@ -233,12 +233,7 @@ private function getConfiguration() return $config; } - /** - * @throws \RuntimeException - * - * @return string - */ - private function getComposerHome() + private function getComposerHome(): string { $home = getenv('COMPOSER_HOME'); if (!$home) { @@ -259,17 +254,10 @@ private function getComposerHome() } /** - * Validates the syntax and the schema of the current config json file - * according to satis-schema.json rules. - * - * @param string $configFile The json file to use - * * @throws ParsingException if the json file has an invalid syntax * @throws JsonValidationException if the json file doesn't match the schema - * - * @return bool true on success */ - private function check($configFile) + private function check(string $configFile): bool { $content = file_get_contents($configFile); @@ -292,6 +280,7 @@ private function check($configFile) foreach ((array) $validator->getErrors() as $error) { $errors[] = ($error['property'] ? $error['property'] . ' : ' : '') . $error['message']; } + throw new JsonValidationException('The json config file does not match the expected JSON schema', $errors); } diff --git a/src/Console/Command/InitCommand.php b/src/Console/Command/InitCommand.php index e5b0aab8..7b6b5c9f 100644 --- a/src/Console/Command/InitCommand.php +++ b/src/Console/Command/InitCommand.php @@ -1,5 +1,7 @@ - */ class InitCommand extends BaseCommand { protected function configure() @@ -44,13 +43,7 @@ protected function configure() ; } - /** - * Print welcome message - * - * @param InputInterface $input - * @param OutputInterface $output - */ - protected function initialize(InputInterface $input, OutputInterface $output) + protected function initialize(InputInterface $input, OutputInterface $output): void { /** @var FormatterHelper $formatter */ $formatter = $this->getHelper('formatter'); @@ -68,15 +61,7 @@ protected function initialize(InputInterface $input, OutputInterface $output) ]); } - /** - * Generate configuration file - * - * @param InputInterface $input The input instance - * @param OutputInterface $output The output instance - * - * @return int - */ - protected function execute(InputInterface $input, OutputInterface $output) + protected function execute(InputInterface $input, OutputInterface $output): int { /** @var FormatterHelper $formatter */ $formatter = $this->getHelper('formatter'); @@ -121,13 +106,7 @@ protected function execute(InputInterface $input, OutputInterface $output) return 0; } - /** - * Interact with user - * - * @param InputInterface $input - * @param OutputInterface $output - */ - protected function interact(InputInterface $input, OutputInterface $output) + protected function interact(InputInterface $input, OutputInterface $output): void { $this->prompt($input, $output, 'Repository name', 'name', function ($value) { if (!$value) { @@ -148,16 +127,7 @@ protected function interact(InputInterface $input, OutputInterface $output) }); } - /** - * Prompt for an input option. - * - * @param InputInterface $input - * @param OutputInterface $output - * @param string $prompt - * @param string $optionName For the default value and where the answer is set - * @param callable $validator - */ - protected function prompt(InputInterface $input, OutputInterface $output, $prompt, $optionName, $validator) + protected function prompt(InputInterface $input, OutputInterface $output, string $prompt, string $optionName, callable $validator) { /** @var QuestionHelper $helper */ $helper = $this->getHelper('question'); @@ -168,17 +138,9 @@ protected function prompt(InputInterface $input, OutputInterface $output, $promp $input->setOption($optionName, $helper->ask($input, $output, $question)); } - /** - * Build a question - * - * @param string $prompt - * @param string $default - * - * @return Question - */ - protected function getQuestion($prompt, $default) + protected function getQuestion(string $prompt, ?string $default): Question { - $prompt = ($default ? sprintf('%s (%s)', $prompt, $default) : $prompt) . ': '; + $prompt = ($default ? sprintf('%s (%s)', $prompt, null === $default ? 'null' : $default) : $prompt) . ': '; return new Question($prompt, $default); } diff --git a/src/Console/Command/PurgeCommand.php b/src/Console/Command/PurgeCommand.php index 1790867b..c501d8a3 100644 --- a/src/Console/Command/PurgeCommand.php +++ b/src/Console/Command/PurgeCommand.php @@ -1,5 +1,7 @@ getArgument('file'); $file = new JsonFile($configFile); @@ -62,44 +65,29 @@ protected function execute(InputInterface $input, OutputInterface $output) return 1; } - if (!$outputDir = $input->getArgument('output-dir')) { - throw new \InvalidArgumentException('The output dir must be specified as second argument'); - } - - $files = glob($outputDir . '/include/*.json'); - - if (empty($files)) { - $output->writeln('No log file'); - - return 1; + $outputDir = $input->getArgument('output-dir') ?? $config['output-dir'] ?? null; + if (null === $outputDir) { + throw new \InvalidArgumentException('The output dir must be specified as second argument or be configured inside ' . $input->getArgument('file')); } - $files = array_combine($files, array_map('filemtime', $files)); - arsort($files); + $packageSelection = new PackageSelection($output, $outputDir, $config, false); + $packages = $packageSelection->load(); - $file = file_get_contents(key($files)); - $json = json_decode($file, true); - - $prefix = $config['archive']['directory']; - if (isset($config['archive']['prefix-url'])) { - $prefix = sprintf('%s/%s/', $config['archive']['prefix-url'], $prefix); - } else { - $prefix = sprintf('%s/%s/', $config['homepage'], $prefix); - } + $prefix = sprintf( + '%s/%s/', + $config['archive']['prefix-url'] ?? $config['homepage'], + $config['archive']['directory'] + ); $length = strlen($prefix); $needed = []; - foreach ($json['packages'] as $package) { - foreach ($package as $version) { - if (!isset($version['dist']['url'])) { - continue; - } - - $url = $version['dist']['url']; - - if (substr($url, 0, $length) === $prefix) { - $needed[] = substr($url, $length); - } + foreach ($packages as $package) { + if (!$package->getDistType()) { + continue; + } + $url = $package->getDistUrl(); + if (substr($url, 0, $length) === $prefix) { + $needed[] = substr($url, $length); } } @@ -120,7 +108,8 @@ protected function execute(InputInterface $input, OutputInterface $output) /** @var SplFileInfo[] $unreferenced */ $unreferenced = []; foreach ($finder as $file) { - if (!in_array($file->getRelativePathname(), $needed)) { + $filename = strtr($file->getRelativePathname(), DIRECTORY_SEPARATOR, '/'); + if (!in_array($filename, $needed)) { $unreferenced[] = $file; } } @@ -140,26 +129,40 @@ protected function execute(InputInterface $input, OutputInterface $output) )); } - $finder = new Finder(); - $finder - ->directories() - ->ignoreDotFiles(true) - ->ignoreUnreadableDirs(true) - ->in($distDirectory) - ; - - foreach ($finder->getIterator() as $directory) { - if (!(new Finder())->in($directory->getPathname())->files()->count()) { - rmdir($directory->getPathname()); - $output->writeln(sprintf( - 'Removed empty directory: %s', - $directory->getPathname() - )); - } - } + $this->removeEmptyDirectories($output, $distDirectory); $output->writeln('Done.'); return 0; } + + private function removeEmptyDirectories(OutputInterface $output, string $dir, int $depth = 2): bool + { + $empty = true; + $children = @scandir($dir); + + if (false === $children) { + return false; + } + + foreach ($children as $child) { + if ('.' === $child || '..' === $child) { + continue; + } + + $path = $dir . DIRECTORY_SEPARATOR . $child; + + if (is_dir($path) + && $depth > 0 + && $this->removeEmptyDirectories($output, $path, $depth - 1) + && rmdir($path) + ) { + $output->writeln(sprintf('Removed empty directory: %s', $path)); + } else { + $empty = false; + } + } + + return $empty; + } } diff --git a/src/PackageSelection/PackageSelection.php b/src/PackageSelection/PackageSelection.php index 8ed1dca4..5d835ee6 100644 --- a/src/PackageSelection/PackageSelection.php +++ b/src/PackageSelection/PackageSelection.php @@ -1,5 +1,7 @@ - */ class PackageSelection { /** @var OutputInterface The output Interface. */ @@ -42,6 +43,9 @@ class PackageSelection /** @var string packages.json file name. */ private $filename; + /** @var array Array of additional repositories for dependencies */ + private $depRepositories; + /** @var bool Selects All Packages if true. */ private $requireAll; @@ -51,260 +55,252 @@ class PackageSelection /** @var bool required dev-dependencies if true. */ private $requireDevDependencies; + /** @var bool do not build packages only dependencies */ + private $onlyDependencies; + + /** @var bool only resolve best candidates in dependencies */ + private $onlyBestCandidates; + + /** @var bool Filter dependencies if true. */ + private $requireDependencyFilter; + /** @var string Minimum stability accepted for Packages in the list. */ private $minimumStability; + /** @var array Minimum stability accepted by Package. */ + private $minimumStabilityPerPackage; + /** @var array The active package filter to merge. */ private $packagesFilter = []; - /** @var string The active repository filter to merge. */ + /** @var string|null The active repository filter to merge. */ private $repositoryFilter; - /** @var array The selected packages from config */ + /** @var bool Apply the filter also for resolving dependencies. */ + private $repositoryFilterDep; + + /** @var PackageInterface[] The selected packages from config */ private $selected = []; /** @var array A list of packages marked as abandoned */ private $abandoned = []; + /** @var array A list of blacklisted package/constraints. */ + private $blacklist = []; + + /** @var array|bool Patterns from strip-hosts. */ + private $stripHosts = false; + + /** @var string The prefix of the distURLs when using archive. */ + private $archiveEndpoint; + /** @var string The homepage - needed to get the relative paths of the providers */ private $homepage; - /** - * Base Constructor. - * - * @param OutputInterface $output The output Interface - * @param string $outputDir The directory where to build - * @param array $config The parameters from ./satis.json - * @param bool $skipErrors Escapes Exceptions if true - */ - public function __construct(OutputInterface $output, $outputDir, $config, $skipErrors) + public function __construct(OutputInterface $output, string $outputDir, array $config, bool $skipErrors) { $this->output = $output; - $this->skipErrors = (bool) $skipErrors; + $this->skipErrors = $skipErrors; $this->filename = $outputDir . '/packages.json'; + $this->fetchOptions($config); } - private function fetchOptions($config) + public function setRepositoryFilter(?string $repositoryFilter, bool $forDependencies = false): void { - $this->requireAll = isset($config['require-all']) && true === $config['require-all']; - $this->requireDependencies = isset($config['require-dependencies']) && true === $config['require-dependencies']; - $this->requireDevDependencies = isset($config['require-dev-dependencies']) && true === $config['require-dev-dependencies']; - - if (!$this->requireAll && !isset($config['require'])) { - $this->output->writeln('No explicit requires defined, enabling require-all'); - $this->requireAll = true; - } - - $this->minimumStability = $config['minimum-stability'] ?? 'dev'; - $this->abandoned = $config['abandoned'] ?? []; - $this->homepage = $config['homepage'] ?? null; + $this->repositoryFilter = $repositoryFilter; + $this->repositoryFilterDep = (bool) $forDependencies; } - /** - * Sets the active repository filter to merge - * - * @param string $repositoryFilter The active repository filter to merge - */ - public function setRepositoryFilter($repositoryFilter) + public function hasRepositoryFilter(): bool { - $this->repositoryFilter = $repositoryFilter; + return null !== $this->repositoryFilter; } - /** - * Tells if repository list should be reduced to single repository - * - * @return bool true if repository filter is set - */ - public function hasRepositoryFilter() + public function hasBlacklist(): bool { - return null !== $this->repositoryFilter; + return count($this->blacklist) > 0; } - /** - * Sets the active package filter to merge - * - * @param array $packagesFilter The active package filter to merge - */ - public function setPackagesFilter(array $packagesFilter = []) + public function setPackagesFilter(array $packagesFilter = []): void { $this->packagesFilter = $packagesFilter; } - /** - * Tells if there is at least one package filter. - * - * @return bool true if there is at least one package filter - */ - public function hasFilterForPackages() + public function hasFilterForPackages(): bool { return count($this->packagesFilter) > 0; } /** - * Sets the list of packages to build. - * - * @param Composer $composer The Composer instance - * @param bool $verbose Output infos if true - * * @throws \InvalidArgumentException * @throws \Exception - * - * @return PackageInterface[] */ - public function select(Composer $composer, $verbose) + public function select(Composer $composer, bool $verbose): array { // run over all packages and store matching ones $this->output->writeln('Scanning packages'); - $repos = $composer->getRepositoryManager()->getRepositories(); - $pool = new Pool($this->minimumStability); + $repos = $initialRepos = $composer->getRepositoryManager()->getRepositories(); + + $stabilityFlags = array_map(function ($value) { + return BasePackage::$stabilities[$value]; + }, $this->minimumStabilityPerPackage); + + $pool = new Pool($this->minimumStability, $stabilityFlags); if ($this->hasRepositoryFilter()) { $repos = $this->filterRepositories($repos); - } - foreach ($repos as $repo) { - try { - $pool->addRepository($repo); - } catch (\Exception $exception) { - if (!$this->skipErrors) { - throw $exception; - } + if (0 === count($repos)) { + throw new \InvalidArgumentException(sprintf('Specified repository url "%s" does not exist.', $this->repositoryFilter)); + } - $this->output->writeln(sprintf("Skipping Exception '%s'.", $exception->getMessage())); + if (count($repos) > 1) { + throw new \InvalidArgumentException(sprintf('Found more than one repository for url "%s".', $this->repositoryFilter)); } } - if ($this->hasRepositoryFilter()) { + if ($this->hasFilterForPackages()) { + $repos = $this->filterPackages($repos); + if (0 === count($repos)) { - throw new \InvalidArgumentException(sprintf('Specified repository url "%s" does not exist.', $this->repositoryFilter)); - } elseif (count($repos) > 1) { - throw new \InvalidArgumentException(sprintf('Found more than one repository for url "%s".', $this->repositoryFilter)); + throw new \InvalidArgumentException(sprintf( + 'Could not find any package(s) matching: %s', + implode(', ', $this->packagesFilter) + )); + } + + if (count($repos) > 1) { + throw new \InvalidArgumentException(sprintf( + 'Found more than one package matching: %s', + implode(', ', $this->packagesFilter) + )); } } - $links = $this->requireAll ? $this->getAllLinks($repos, $this->minimumStability, $verbose) : $this->getFilteredLinks($composer); + $this->addRepositories($pool, $repos); - // process links if any - $depsLinks = []; + // determine the required packages + $rootLinks = $this->requireAll ? $this->getAllLinks($repos, $this->minimumStability, $verbose) : $this->getFilteredLinks($composer); - $i = 0; - while (isset($links[$i])) { - $link = $links[$i]; - ++$i; - $name = $link->getTarget(); - $matches = $pool->whatProvides($name, $link->getConstraint(), true); + // select the required packages and determine dependencies + $depsLinks = $this->selectLinks($pool, $rootLinks, true, $verbose); - foreach ($matches as $index => $package) { - // skip aliases - if ($package instanceof AliasPackage) { - $package = $package->getAliasOf(); - } - - // add matching package if not yet selected - if (!isset($this->selected[$package->getUniqueName()])) { - if ($verbose) { - $this->output->writeln('Selected ' . $package->getPrettyName() . ' (' . $package->getPrettyVersion() . ')'); - } - $this->selected[$package->getUniqueName()] = $package; - - if (!$this->requireAll) { - $required = $this->getRequired($package); - // append non-platform dependencies - foreach ($required as $dependencyLink) { - $target = $dependencyLink->getTarget(); - if (!preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $target)) { - $linkId = $target . ' ' . $dependencyLink->getConstraint(); - // prevent loading multiple times the same link - if (!isset($depsLinks[$linkId])) { - $links[] = $dependencyLink; - $depsLinks[$linkId] = true; - } - } - } - } - } + if ($this->requireDependencies || $this->requireDevDependencies) { + // dependencies of required packages might have changed and be part of filtered repos + if ($this->hasRepositoryFilter() && true !== $this->repositoryFilterDep) { + $this->addRepositories($pool, \array_filter($initialRepos, function ($r) use ($repos) { + return false === \in_array($r, $repos); + })); } - if (!$matches) { - $this->output->writeln('The ' . $name . ' ' . $link->getPrettyConstraint() . ' requirement did not match any package'); + // additional repositories for dependencies + if (!$this->hasRepositoryFilter() || true !== $this->repositoryFilterDep) { + $this->addRepositories($pool, $this->getDepRepos($composer)); } + + // select dependencies + $this->selectLinks($pool, $depsLinks, false, $verbose); } $this->setSelectedAsAbandoned(); + $this->pruneBlacklisted($pool, $verbose); + ksort($this->selected, SORT_STRING); return $this->selected; } /** - * Loads previously dumped Packages in order to merge with updates. - * * @return PackageInterface[] */ - public function load() + public function clean(): array + { + $this->applyStripHosts(); + + return $this->selected; + } + + /** + * @return PackageInterface[] + */ + public function load(): array { $packages = []; - $repoJson = new JsonFile($this->filename); - $dirName = dirname($this->filename); - - if ($repoJson->exists()) { - $loader = new ArrayLoader(); - $packagesJson = $repoJson->read(); - $jsonIncludes = isset($packagesJson['includes']) && is_array($packagesJson['includes']) - ? $packagesJson['includes'] - : []; - - if (isset($packagesJson['providers']) && is_array($packagesJson['providers']) && isset($packagesJson['providers-url'])) { - $baseUrl = $this->homepage ? parse_url(rtrim($this->homepage, '/'), PHP_URL_PATH) . '/' : null; - $baseUrlLength = strlen($baseUrl); - foreach ($packagesJson['providers'] as $packageName => $provider) { - $file = str_replace(['%package%', '%hash%'], [$packageName, $provider['sha256']], $packagesJson['providers-url']); - if ($baseUrl && substr($file, 0, $baseUrlLength) === $baseUrl) { - $file = substr($file, $baseUrlLength); - } - $jsonIncludes[$file] = $provider; + $rootJsonFile = new JsonFile($this->filename); + $dirname = dirname($this->filename); + + if (!$rootJsonFile->exists()) { + return $packages; + } + + $loader = new ArrayLoader(); + $rootConfig = $rootJsonFile->read(); + $includes = []; + + if (isset($rootConfig['includes']) && is_array($rootConfig['includes'])) { + $includes = $rootConfig['includes']; + } + + if (isset($rootConfig['providers']) && is_array($rootConfig['providers']) && isset($rootConfig['providers-url'])) { + $baseUrl = $this->homepage ? parse_url(rtrim($this->homepage, '/'), PHP_URL_PATH) . '/' : null; + $baseUrlLength = strlen($baseUrl); + + foreach ($rootConfig['providers'] as $package => $provider) { + $file = str_replace(['%package%', '%hash%'], [$package, $provider['sha256']], $rootConfig['providers-url']); + + if ($baseUrl && substr($file, 0, $baseUrlLength) === $baseUrl) { + $file = substr($file, $baseUrlLength); } + + $includes[$file] = $provider; } + } + + foreach (array_keys($includes) as $file) { + $includedJsonFile = new JsonFile($dirname . '/' . $file); + + if (!$includedJsonFile->exists()) { + $this->output->writeln(sprintf( + 'File \'%s\' does not exist, defined in "includes" in \'%s\'', + $includedJsonFile->getPath(), + $rootJsonFile->getPath() + )); + + continue; + } + + $includedConfig = $includedJsonFile->read(); - foreach ($jsonIncludes as $includeFile => $includeConfig) { - $includeJson = new JsonFile($dirName . '/' . $includeFile); + if (!isset($includedConfig['packages']) || !is_array($includedConfig['packages'])) { + continue; + } - if (!$includeJson->exists()) { - $this->output->writeln(sprintf( - 'File \'%s\' does not exist, defined in "includes" in \'%s\'', - $includeJson->getPath(), - $repoJson->getPath() - )); + $includedPackages = $includedConfig['packages']; + foreach ($includedPackages as $name => $versions) { + if (!is_array($versions)) { continue; } - $jsonPackages = $includeJson->read(); - $jsonPackages = isset($jsonPackages['packages']) && is_array($jsonPackages['packages']) - ? $jsonPackages['packages'] - : []; - - foreach ($jsonPackages as $jsonPackage) { - if (is_array($jsonPackage)) { - foreach ($jsonPackage as $jsonVersion) { - if (is_array($jsonVersion)) { - if (isset($jsonVersion['name']) && in_array($jsonVersion['name'], $this->packagesFilter)) { - continue; - } - $package = $loader->load($jsonVersion); + foreach ($versions as $package) { + if (!is_array($package)) { + continue; + } - // skip aliases - if ($package instanceof AliasPackage) { - $package = $package->getAliasOf(); - } + if (isset($package['name']) && in_array($package['name'], $this->packagesFilter)) { + continue; + } - $packages[$package->getUniqueName()] = $package; - } - } + $package = $loader->load($package); + + if ($package instanceof AliasPackage) { + $package = $package->getAliasOf(); } + + $packages[$package->getUniqueName()] = $package; } } } @@ -312,10 +308,243 @@ public function load() return $packages; } + private function fetchOptions(array $config): void + { + $this->depRepositories = $config['repositories-dep'] ?? []; + + $this->requireAll = isset($config['require-all']) && true === $config['require-all']; + $this->requireDependencies = isset($config['require-dependencies']) && true === $config['require-dependencies']; + $this->requireDevDependencies = isset($config['require-dev-dependencies']) && true === $config['require-dev-dependencies']; + $this->onlyDependencies = isset($config['only-dependencies']) && true === $config['only-dependencies']; + $this->onlyBestCandidates = isset($config['only-best-candidates']) && true === $config['only-best-candidates']; + $this->requireDependencyFilter = (bool) ($config['require-dependency-filter'] ?? true); + + if (!$this->requireAll && !isset($config['require'])) { + $this->output->writeln('No explicit requires defined, enabling require-all'); + $this->requireAll = true; + } + + $this->minimumStability = $config['minimum-stability'] ?? 'dev'; + $this->minimumStabilityPerPackage = $config['minimum-stability-per-package'] ?? []; + $this->abandoned = $config['abandoned'] ?? []; + $this->blacklist = $config['blacklist'] ?? []; + + $this->stripHosts = $this->createStripHostsPatterns($config['strip-hosts'] ?? false); + $this->archiveEndpoint = isset($config['archive']['directory']) ? ($config['archive']['prefix-url'] ?? $config['homepage']) . '/' : null; + + $this->homepage = $config['homepage'] ?? null; + } + /** - * Marks selected packages as abandoned by Configuration file + * @param array|false $stripHostsConfig + * + * @return array|false */ - private function setSelectedAsAbandoned() + private function createStripHostsPatterns($stripHostsConfig) + { + if (!is_array($stripHostsConfig)) { + return $stripHostsConfig; + } + + $patterns = []; + + foreach ($stripHostsConfig as $entry) { + if (!strlen($entry)) { + continue; + } + + if ('/private' === $entry || '/local' === $entry) { + $patterns[] = [$entry]; + continue; + } elseif (false !== strpos($entry, ':')) { + $type = 'ipv6'; + if (!defined('AF_INET6')) { + $this->output->writeln('Unable to use IPv6.'); + continue; + } + } elseif (0 === preg_match('#[^/.\\d]#', $entry)) { + $type = 'ipv4'; + } else { + $type = 'name'; + $host = '#^(?:.+\.)?' . preg_quote($entry, '#') . '$#ui'; + $patterns[] = [$type, $host]; + continue; + } + + @list($host, $mask) = explode('/', $entry, 2); + + $host = @inet_pton($host); + + if (false === $host || (int) $mask != $mask) { + $this->output->writeln(sprintf('Invalid subnet "%s"', $entry)); + continue; + } + + $host = unpack('N*', $host); + + if (null === $mask) { + $mask = 'ipv4' === $type ? 32 : 128; + } else { + $mask = (int) $mask; + + if ($mask < 0 || ('ipv4' === $type && $mask > 32) || ('ipv6' === $type && $mask > 128)) { + continue; + } + } + + $patterns[] = [$type, $host, $mask]; + } + + return $patterns; + } + + private function applyStripHosts(): void + { + if (false === $this->stripHosts) { + return; + } + + /** @var PackageInterface $package */ + foreach ($this->selected as $uniqueName => $package) { + $sources = []; + + if ($package->getSourceType()) { + $sources[] = 'source'; + } + + if ($package->getDistType()) { + $sources[] = 'dist'; + } + + foreach ($sources as $index => $type) { + $url = 'source' === $type ? $package->getSourceUrl() : $package->getDistUrl(); + + // skip distURL applied by ArchiveBuilder + if ('dist' === $type && null !== $this->archiveEndpoint + && substr($url, 0, strlen($this->archiveEndpoint)) === $this->archiveEndpoint + ) { + continue; + } + + if ($this->matchStripHostsPatterns($url)) { + if ('dist' === $type) { + // if the type is not set, ArrayDumper ignores the other properties + $package->setDistType(null); + } else { + $package->setSourceType(null); + } + + unset($sources[$index]); + + if (0 === count($sources)) { + $this->output->writeln(sprintf('%s has no source left after applying the strip-hosts filters and will be removed', $package->getUniqueName())); + + unset($this->selected[$uniqueName]); + } + } + } + } + } + + private function matchStripHostsPatterns(string $url): bool + { + if (Filesystem::isLocalPath($url)) { + return true; + } + + if (!is_array($this->stripHosts)) { + return false; + } + + $url = trim(parse_url($url, PHP_URL_HOST), '[]'); + + if (false !== filter_var($url, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { + $urltype = 'ipv4'; + } elseif (false !== filter_var($url, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { + $urltype = 'ipv6'; + } else { + $urltype = 'name'; + } + + if ('ipv4' === $urltype || 'ipv6' === $urltype) { + $urlunpack = unpack('N*', @inet_pton($url)); + } + + foreach ($this->stripHosts as $pattern) { + @list($type, $host, $mask) = $pattern; + + if ('/local' === $type) { + if (('name' === $urltype && 'localhost' === strtolower($url)) || ( + ('ipv4' === $urltype || 'ipv6' === $urltype) && + false === filter_var($url, FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE) + )) { + return true; + } + } elseif ('/private' === $type) { + if (('ipv4' === $urltype || 'ipv6' === $urltype) + && false === filter_var($url, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE) + ) { + return true; + } + } elseif ('ipv4' === $type || 'ipv6' === $type) { + if ($urltype === $type && $this->matchAddr($urlunpack, $host, $mask)) { + return true; + } + } elseif ('name' === $type) { + if ('name' === $urltype && preg_match($host, $url)) { + return true; + } + } + } + + return false; + } + + /** + * Test if two addresses have the same prefix + * + * @param int[] $addr1 Chunked addr + * @param int[] $addr2 Chunked addr + * @param int $len Length of the test + * @param int $chunklen Length of each chunk + * + * @return bool + */ + private function matchAddr($addr1, $addr2, $len = 0, $chunklen = 32): bool + { + for (; $len > 0; $len -= $chunklen, next($addr1), next($addr2)) { + $shift = $len >= $chunklen ? 0 : $chunklen - $len; + + if ((current($addr1) >> $shift) !== (current($addr2) >> $shift)) { + return false; + } + } + + return true; + } + + /** + * @param Pool $pool + * @param RepositoryInterface[] $repositories + * + * @throws \Exception + */ + private function addRepositories(Pool $pool, array $repositories): void + { + foreach ($repositories as $repository) { + try { + $pool->addRepository($repository); + } catch (\Exception $exception) { + if (!$this->skipErrors) { + throw $exception; + } + + $this->output->writeln(sprintf("Skipping Exception '%s'.", $exception->getMessage())); + } + } + } + + private function setSelectedAsAbandoned(): void { foreach ($this->selected as $name => $package) { if (array_key_exists($package->getName(), $this->abandoned)) { @@ -324,118 +553,255 @@ private function setSelectedAsAbandoned() } } + /** + * Removes selected packages which are blacklisted in configuration. + * + * @param Pool $pool + * @param bool $verbose + * + * @return PackageInterface[] + */ + private function pruneBlacklisted($pool, $verbose): array + { + $blacklisted = []; + if ($this->hasBlacklist()) { + $parser = new VersionParser(); + foreach ($this->selected as $selectedKey => $package) { + foreach ($this->blacklist as $blacklistName => $blacklistConstraint) { + $constraint = $parser->parseConstraints($blacklistConstraint); + if ($pool::MATCH === $pool->match($package, $blacklistName, $constraint, FALSE)) { + if ($verbose) { + $this->output->writeln('Blacklisted ' . $package->getPrettyName() . ' (' . $package->getPrettyVersion() . ')'); + } + $blacklisted[$selectedKey] = $package; + unset($this->selected[$selectedKey]); + } + } + } + } + return $blacklisted; + } + /** * Gets a list of filtered Links. * - * @param Composer $composer The Composer instance + * @param Composer $composer * * @return Link[] */ - private function getFilteredLinks(Composer $composer) + private function getFilteredLinks(Composer $composer): array { $links = array_values($composer->getPackage()->getRequires()); - // only pick up packages in our filter, if a filter has been set. - if ($this->hasFilterForPackages()) { - $packagesFilter = $this->packagesFilter; - $links = array_filter($links, function (Link $link) use ($packagesFilter) { - return in_array($link->getTarget(), $packagesFilter); - }); + if (!$this->hasFilterForPackages()) { + return $links; } + $packagesFilter = $this->packagesFilter; + $links = array_filter( + $links, + function (Link $link) use ($packagesFilter) { + return in_array($link->getTarget(), $packagesFilter); + } + ); + return array_values($links); } /** - * Gets all Links. - * - * This method is called when 'require-all' is set to true. + * @param RepositoryInterface[] $repositories + * @param string $minimumStability + * @param bool $verbose * - * @param array $repos List of all Repositories configured - * @param string $minimumStability The minimum stability each package must have to be selected - * @param bool $verbose Output infos if true + * @return Link[]|PackageInterface[] + */ + private function getAllLinks(array $repositories, string $minimumStability, bool $verbose): array + { + $links = []; + + foreach ($repositories as $repository) { + if ($repository instanceof ComposerRepository && $repository->hasProviders()) { + foreach ($repository->getProviderNames() as $name) { + $links[] = new Link('__root__', $name, new EmptyConstraint(), 'requires', '*'); + } + + continue; + } + + $packages = $this->getPackages($repository); + + foreach ($packages as $package) { + if ($package instanceof AliasPackage) { + continue; + } + + if (BasePackage::$stabilities[$package->getStability()] > BasePackage::$stabilities[$minimumStability]) { + if ($verbose) { + $this->output->writeln('Skipped ' . $package->getPrettyName() . ' (' . $package->getStability() . ')'); + } + + continue; + } + + $links[] = $package; + } + } + + return $links; + } + + /** + * @param Pool $pool + * @param Link[]|PackageInterface[] $links + * @param bool $isRoot + * @param bool $verbose * * @return Link[] */ - private function getAllLinks($repos, $minimumStability, $verbose) + private function selectLinks(Pool $pool, array $links, bool $isRoot, bool $verbose): array { - $links = []; + $depsLinks = $isRoot ? [] : $links; + + $policies = [ + new DefaultPolicy(true, false), + new DefaultPolicy(false, false), + new DefaultPolicy(true, true), + new DefaultPolicy(false, true), + ]; + + reset($links); + + while (null !== key($links)) { + $link = current($links); + + if (is_a($link, PackageInterface::class)) { + $matches = [$link]; + } elseif (is_a($link, Link::class)) { + $name = $link->getTarget(); + if (!$isRoot && $this->onlyBestCandidates) { + $selector = new VersionSelector($pool); + $matches = [$selector->findBestCandidate($name, $link->getConstraint()->getPrettyString())]; + } else { + $matches = $pool->whatProvides($name, $link->getConstraint(), true); + } - foreach ($repos as $repo) { - // collect links for composer repos with providers - if ($repo instanceof ComposerRepository && $repo->hasProviders()) { - foreach ($repo->getProviderNames() as $name) { - $links[] = new Link('__root__', $name, new MultiConstraint([]), 'requires', '*'); + if (0 === \count($matches)) { + $this->output->writeln('The ' . $name . ' ' . $link->getPrettyConstraint() . ' requirement did not match any package'); } - } else { - $packages = $this->getPackages($repo); + } - foreach ($packages as $package) { - // skip aliases - if ($package instanceof AliasPackage) { - continue; + if (!$isRoot && $this->requireDependencyFilter && \count($matches) > 1) { + // filter matches like Composer's installer + \array_walk($matches, function (&$package) { + $package = $package->getId(); + }); + $m = []; + foreach ($policies as $policy) { + $pm = $policy->selectPreferredPackages($pool, [], $matches); + if (isset($pm[0])) { + $m[] = $pool->packageById($pm[0]); } + } + $matches = $m; + } - if (BasePackage::$stabilities[$package->getStability()] > BasePackage::$stabilities[$minimumStability]) { + foreach ($matches as $package) { + // skip aliases + if ($package instanceof AliasPackage) { + $package = $package->getAliasOf(); + } + + $uniqueName = $package->getUniqueName(); + // add matching package if not yet selected + if (!isset($this->selected[$uniqueName])) { + if (false === $isRoot || false === $this->onlyDependencies) { if ($verbose) { - $this->output->writeln('Skipped ' . $package->getPrettyName() . ' (' . $package->getStability() . ')'); + $this->output->writeln('Selected ' . $package->getPrettyName() . ' (' . $package->getPrettyVersion() . ')'); } - continue; + $this->selected[$uniqueName] = $package; } - // add matching package if not yet selected - if (!isset($this->selected[$package->getUniqueName()])) { - if ($verbose) { - $this->output->writeln('Selected ' . $package->getPrettyName() . ' (' . $package->getPrettyVersion() . ')'); + $required = $this->getRequired($package, $isRoot); + // append non-platform dependencies + foreach ($required as $dependencyLink) { + $target = $dependencyLink->getTarget(); + if (!preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $target)) { + $linkId = $target . ' ' . $dependencyLink->getConstraint(); + // prevent loading multiple times the same link + if (!isset($depsLinks[$linkId])) { + if (false === $isRoot) { + $links[] = $dependencyLink; + } + $depsLinks[$linkId] = $dependencyLink; + } } - $this->selected[$package->getUniqueName()] = $package; } } } + + next($links); } - return $links; + return $depsLinks; } /** - * Gets All or filtered Packages of a Repository. + * @param Composer $composer * - * @param RepositoryInterface $repo a Repository + * @return RepositoryInterface[] + */ + private function getDepRepos(Composer $composer): array + { + $repositories = []; + + if (\is_array($this->depRepositories)) { + $repositoryManager = $composer->getRepositoryManager(); + + foreach ($this->depRepositories as $index => $config) { + $name = \is_int($index) && isset($config['url']) ? $config['url'] : $index; + $type = $config['type'] ?? ''; + $repositories[$index] = $repositoryManager->createRepository($type, $config, $name); + } + } + + return $repositories; + } + + /** + * @param RepositoryInterface $repo * * @return PackageInterface[] */ - private function getPackages(RepositoryInterface $repo) + private function getPackages(RepositoryInterface $repo): array { $packages = []; - if ($this->hasFilterForPackages()) { - // apply package filter if defined - foreach ($this->packagesFilter as $filter) { - $packages += $repo->findPackages($filter); - } - } else { - // process other repos directly - $packages = $repo->getPackages(); + if (!$this->hasFilterForPackages()) { + return $repo->getPackages(); + } + + foreach ($this->packagesFilter as $filter) { + $packages += $repo->findPackages($filter); } return $packages; } /** - * Gets the required Links if needed. - * - * @param PackageInterface $package A package + * @param PackageInterface $package + * @param bool $isRoot * * @return Link[] */ - private function getRequired(PackageInterface $package) + private function getRequired(PackageInterface $package, bool $isRoot): array { $required = []; if ($this->requireDependencies) { $required = $package->getRequires(); } - if ($this->requireDevDependencies) { + + if (($isRoot || !$this->requireDependencyFilter) && $this->requireDevDependencies) { $required = array_merge($required, $package->getDevRequires()); } @@ -443,28 +809,56 @@ private function getRequired(PackageInterface $package) } /** - * Filter given repositories. + * @param RepositoryInterface|ConfigurableRepositoryInterface[] $repositories * - * @param RepositoryInterface[] $repositories - * - * @return RepositoryInterface[] + * @return RepositoryInterface|ConfigurableRepositoryInterface[] */ - private function filterRepositories(array $repositories) + private function filterRepositories(array $repositories): array { $url = $this->repositoryFilter; - return array_filter($repositories, function ($repository) use ($url) { - if (!($repository instanceof ConfigurableRepositoryInterface)) { - return false; - } + return array_filter( + $repositories, + function ($repository) use ($url) { + if (!($repository instanceof ConfigurableRepositoryInterface)) { + return false; + } - $config = $repository->getRepoConfig(); + $config = $repository->getRepoConfig(); - if (!isset($config['url']) || $config['url'] !== $url) { - return false; + if (!isset($config['url']) || $config['url'] !== $url) { + return false; + } + + return true; } + ); + } - return true; - }); + /** + * @param RepositoryInterface|ConfigurableRepositoryInterface[] $repositories + * + * @return RepositoryInterface|ConfigurableRepositoryInterface[] + */ + private function filterPackages(array $repositories): array + { + $packages = $this->packagesFilter; + + return array_filter( + $repositories, + function ($repository) use ($packages) { + if (!($repository instanceof ConfigurableRepositoryInterface)) { + return false; + } + + $config = $repository->getRepoConfig(); + + if (!isset($config['name']) || !in_array($config['name'], $packages)) { + return false; + } + + return true; + } + ); } } diff --git a/src/Satis.php b/src/Satis.php index 3b731459..4e77013f 100644 --- a/src/Satis.php +++ b/src/Satis.php @@ -1,5 +1,7 @@ - */ class Satis { - const VERSION = '1.0.0'; + const VERSION = '2.0.0-dev'; } diff --git a/tests/Builder/ArchiveBuilderHelperTest.php b/tests/Builder/ArchiveBuilderHelperTest.php index 03fd105e..34a8d841 100644 --- a/tests/Builder/ArchiveBuilderHelperTest.php +++ b/tests/Builder/ArchiveBuilderHelperTest.php @@ -1,5 +1,7 @@ output = new NullOutput(); } @@ -51,7 +53,7 @@ public function dataDirectories() /** * @dataProvider dataDirectories */ - public function testDirectoryConfig($expected, $outputDir, $config) + public function testDirectoryConfig(string $expected, string $outputDir, array $config) { $helper = new ArchiveBuilderHelper($this->output, $config); $this->assertEquals($helper->getDirectory($outputDir), $expected); @@ -122,7 +124,7 @@ public function dataPackages() /** * @dataProvider dataPackages */ - public function testSkipDump($expected, $package, $config) + public function testSkipDump(bool $expected, Package $package, array $config) { $helper = new ArchiveBuilderHelper($this->output, $config); $this->assertEquals($helper->isSkippable($package), $expected); diff --git a/tests/Builder/ArchiveBuilderTest.php b/tests/Builder/ArchiveBuilderTest.php new file mode 100644 index 00000000..76f7015f --- /dev/null +++ b/tests/Builder/ArchiveBuilderTest.php @@ -0,0 +1,191 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Composer\Satis\Builder; + +use Composer\Composer; +use Composer\Config; +use Composer\Config\JsonConfigSource; +use Composer\Json\JsonFile; +use Composer\Package\CompletePackage; +use PHPUnit\Framework\TestCase; +use Symfony\Component\Console\Output\NullOutput; +use Symfony\Component\Filesystem\Filesystem; + +/** + * @author Michael Lee + */ +class ArchiveBuilderTest extends TestCase +{ + protected $composer; + + protected $output; + + protected $input; + + protected $outputDir; + + protected $satisConfig; + + protected $root; + + protected $home; + + protected $target; + + public function tearDown(): void + { + $fs = new Filesystem(); + $fs->remove($this->root); + } + + public function setUp(): void + { + $this->root = __DIR__ . '/vfs'; + $this->home = $this->root . '/home/ubuntu'; + $this->target = $this->home . '/satis.server/dist/monolog/monolog'; + + $composerConfig = new Config(true, $this->home . '/satis.server'); + $composerConfig->merge([ + 'cache-dir' => $this->home . '/.cache/composer', + 'data-dir' => $this->home . '/.local/share/composer', + 'home' => $this->home . '/.config/composer', + ]); + $composerConfig->setConfigSource(new JsonConfigSource(new JsonFile($this->home . '/.config/composer/config.json'))); + $composerConfig->setAuthConfigSource(new JsonConfigSource(new JsonFile($this->home . '/.config/composer/auth.json'))); + + $downloadManager = $this->getMockBuilder('Composer\Downloader\DownloadManager')->disableOriginalConstructor()->getMock(); + $downloadManager->method('download')->will( + $this->returnCallback( + function ($package, $source) { + $filesystem = new Filesystem(); + $filesystem->dumpFile(realpath($source) . '/' . 'README.md', '# The demo archive.'); + } + ) + ); + + $this->composer = new Composer(); + $this->composer->setConfig($composerConfig); + $this->composer->setDownloadManager($downloadManager); + + $this->input = $this->getMockBuilder('Symfony\Component\Console\Input\InputInterface')->disableOriginalConstructor()->getMock(); + $this->input->method('getOption')->with('stats')->willReturn($this->returnValue(false)); + + $this->output = new NullOutput(); + + $this->outputDir = $this->home . '/satis.server'; + + $this->satisConfig = [ + 'name' => 'monolog/monolog', + 'homepage' => 'https://github.com/Seldaek/monolog.git', + 'repositories' => [ + ['type' => 'composer', 'url' => 'https://packagist.org'], + ], + 'require' => [ + 'monolog/monolog' => '1.13.0', + ], + 'config' => [ + 'secure-http' => false, + ], + 'require-dependencies' => false, + 'require-dev-dependencies' => false, + 'archive' => [ + 'directory' => 'dist', + 'format' => 'tar', + 'prefix-url' => 'http://satis.localhost:4680', + 'skip-dev' => false, + ], + ]; + } + + /** + * @dataProvider getDataForTestDump + */ + public function testDumpWithDownloadedArchives(array $customConfig, array $packages, string $expectedFileName) + { + $this->initArchives(); + + $config = array_merge_recursive($this->satisConfig, $customConfig); + + $builder = new ArchiveBuilder($this->output, $this->outputDir, $config, true); + $builder->setInput($this->input); + $builder->setComposer($this->composer); + $builder->dump($packages); + + $this->assertSame($expectedFileName, basename($packages[0]->getDistUrl())); + } + + private function getPackages() + { + $package = new CompletePackage('monolog/monolog', '1.13.0.0', '1.13.0'); + $package->setId(9); + $package->setType('library'); + $package->setSourceType('git'); + $package->setSourceUrl('https://github.com/Seldaek/monolog.git'); + $package->setSourceReference('c41c218e239b50446fd883acb1ecfd4b770caeae'); + $package->setDistType('zip'); + $package->setDistUrl('https://api.github.com/repos/Seldaek/monolog/zipball/'); + $package->setDistReference('c41c218e239b50446fd883acb1ecfd4b770caeae'); + $package->setReleaseDate(new \DateTime('2015-03-05T01:12:12+00:00')); + $package->setExtra( + [ + 'branch-alias' => [ + 'dev-master' => '1.13.x-dev', + ], + ] + ); + $package->setNotificationUrl('https://packagist.org/downloads/'); + + return [$package]; + } + + public function getDataForTestDump() + { + return [ + [[], $this->getPackages(), 'monolog-monolog-c41c218e239b50446fd883acb1ecfd4b770caeae-zip-d4a976.tar'], + [['archive' => ['override-dist-type' => false]], $this->getPackages(), 'monolog-monolog-c41c218e239b50446fd883acb1ecfd4b770caeae-zip-d4a976.tar'], + [['archive' => ['override-dist-type' => true]], $this->getPackages(), 'monolog-monolog-c41c218e239b50446fd883acb1ecfd4b770caeae-tar-d4a976.tar'], + ]; + } + + /** + * @dataProvider getDataForTestDump + */ + public function testDumpWithoutDownloadedArchives(array $customConfig, array $packages, string $expectedFileName) + { + $this->removeArchives(); + + $config = array_merge_recursive($this->satisConfig, $customConfig); + $builder = new ArchiveBuilder($this->output, $this->outputDir, $config, true); + $builder->setInput($this->input); + $builder->setComposer($this->composer); + $builder->dump($packages); + + $this->assertSame($expectedFileName, basename($packages[0]->getDistUrl())); + } + + private function initArchives() + { + $fs = new Filesystem(); + $fs->mkdir($this->target, 0777); + $fs->dumpFile($this->target . '/monolog-monolog-c41c218e239b50446fd883acb1ecfd4b770caeae-zip-d4a976.tar', 'the package archive.'); + $fs->dumpFile($this->target . '/monolog-monolog-c41c218e239b50446fd883acb1ecfd4b770caeae-tar-d4a976.tar', 'the package archive.'); + } + + private function removeArchives() + { + $fs = new Filesystem(); + $fs->remove($this->target . '/monolog-monolog-c41c218e239b50446fd883acb1ecfd4b770caeae-zip-d4a976.tar'); + $fs->remove($this->target . '/monolog-monolog-c41c218e239b50446fd883acb1ecfd4b770caeae-tar-d4a976.tar'); + } +} diff --git a/tests/Builder/PackagesBuilderDumpTest.php b/tests/Builder/PackagesBuilderDumpTest.php index 27df5718..f8c49e81 100644 --- a/tests/Builder/PackagesBuilderDumpTest.php +++ b/tests/Builder/PackagesBuilderDumpTest.php @@ -1,5 +1,7 @@ root = vfsStream::setup('build'); } - protected static function createPackages($majorVersionNumber, $asArray = false) + protected static function createPackages(int $majorVersionNumber, bool $asArray = false) { $version = $majorVersionNumber . '.0'; $versionNormalized = $majorVersionNumber . '.0.0.0'; @@ -56,10 +58,7 @@ protected static function createPackages($majorVersionNumber, $asArray = false) return [new Package('vendor/name', $versionNormalized, $version)]; } - /** - * @param bool $providers - */ - public function testNominalCase($providers = false) + public function testNominalCase(bool $providers = false) { $packagesBuilder = new PackagesBuilder(new NullOutput(), vfsStream::url('build'), [ 'providers' => $providers, @@ -147,4 +146,49 @@ public function testNotifyBatch() $this->assertEquals('http://localhost:54715/notify', $packagesJson['notify-batch']); } + + public function prettyPrintProvider(): array + { + return [ + 'test pretty print enabled' => [ + JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE, + true, + ], + 'test pretty print disabled' => [ + JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE, + false, + ], + ]; + } + + /** + * @dataProvider prettyPrintProvider + */ + public function testPrettyPrintOption(int $jsonOptions, bool $shouldPrettyPrint = true) + { + $expected = [ + 'packages' => [ + 'vendor/name' => [ + '1.0' => [ + 'name' => 'vendor/name', + 'version' => '1.0', + 'version_normalized' => '1.0.0.0', + 'type' => 'library', + ], + ], + ], + ]; + + $packagesBuilder = new PackagesBuilder(new NullOutput(), vfsStream::url('build'), [ + 'repositories' => [['type' => 'composer', 'url' => 'http://localhost:54715']], + 'require' => ['vendor/name' => '*'], + 'pretty-print' => $shouldPrettyPrint, + 'include-filename' => 'out.json', + ], false); + $packages = self::createPackages(1); + $packagesBuilder->dump($packages); + $content = $this->root->getChild('build/out.json')->getContent(); + + self::assertEquals(trim(json_encode($expected, $jsonOptions)), trim($content)); + } } diff --git a/tests/Builder/WebBuilderDumpTest.php b/tests/Builder/WebBuilderDumpTest.php index 2fd28186..dffefb7f 100644 --- a/tests/Builder/WebBuilderDumpTest.php +++ b/tests/Builder/WebBuilderDumpTest.php @@ -1,5 +1,7 @@ rootPackage = new RootPackage('dummy root package', 0, 0); @@ -44,7 +46,7 @@ protected function setUp() $this->root = $this->setFileSystem(); } - protected function setFileSystem() + protected function setFileSystem(): vfsStreamDirectory { vfsStreamWrapper::register(); $root = vfsStream::newDirectory('build'); @@ -61,8 +63,8 @@ public function testNominalCase() $html = $this->root->getChild('build/index.html')->getContent(); - $this->assertRegExp('/dummy root package Composer repository<\/title>/', $html); - $this->assertRegExp('{\s*\s*]*>.+\s*vendor/name\s*\s*}si', $html); + $this->assertRegExp('/dummy root package<\/title>/', $html); + $this->assertRegExp('{\s*\s*]*>.+\s*vendor/name\s*\s*}si', $html); $this->assertFalse((bool) preg_match('//', $html)); } @@ -75,7 +77,7 @@ public function testRepositoryWithNoName() $html = $this->root->getChild('build/index.html')->getContent(); - $this->assertRegExp('/A Composer repository<\/title>/', $html); + $this->assertRegExp('/A<\/title>/', $html); } public function testDependencies() @@ -91,10 +93,7 @@ public function testDependencies() $this->assertRegExp('/dummytest<\/a>/', $html); } - /** - * @return array - */ - public function dataAbandoned() + public function dataAbandoned(): array { $data = []; @@ -117,7 +116,7 @@ public function dataAbandoned() * @param bool|string $abandoned * @param string $expected */ - public function testAbandoned($abandoned, $expected) + public function testAbandoned($abandoned, string $expected) { $webBuilder = new WebBuilder(new NullOutput(), vfsStream::url('build'), [], false); $webBuilder->setRootPackage($this->rootPackage); diff --git a/tests/Builder/WebBuilderTest.php b/tests/Builder/WebBuilderTest.php index 31fcd5dd..7b00f944 100644 --- a/tests/Builder/WebBuilderTest.php +++ b/tests/Builder/WebBuilderTest.php @@ -1,5 +1,7 @@ @@ -24,12 +28,12 @@ class WebBuilderTest extends TestCase /** @var WebBuilder */ protected $webBuilder; - public function setUp() + public function setUp(): void { $this->webBuilder = new WebBuilder(new NullOutput(), 'build', [], false); } - public function dataGetDescSortedVersions() + public function dataGetDescSortedVersions(): array { $data = []; @@ -55,7 +59,7 @@ public function dataGetDescSortedVersions() public function testTwigEnvironment() { - $twig = new \Twig_Environment(new \Twig_Loader_Array([])); + $twig = new Environment(new ArrayLoader([])); $this->webBuilder->setTwigEnvironment($twig); $reflection = new \ReflectionClass($this->webBuilder); @@ -71,7 +75,7 @@ public function testTwigEnvironmentDefault() $method = $reflection->getMethod('getTwigEnvironment'); $method->setAccessible(true); - $this->assertInstanceOf('\Twig_Environment', $method->invoke($this->webBuilder)); + $this->assertInstanceOf('\Twig\Environment', $method->invoke($this->webBuilder)); } public function testTwigTemplate() diff --git a/tests/PackageSelection/PackageSelectionLoadTest.php b/tests/PackageSelection/PackageSelectionLoadTest.php index 2b4e7738..6638a3bd 100644 --- a/tests/PackageSelection/PackageSelectionLoadTest.php +++ b/tests/PackageSelection/PackageSelectionLoadTest.php @@ -1,5 +1,7 @@ [ @@ -53,14 +55,22 @@ protected function setUp() $this->root = $this->setFileSystem(); - $this->selection = new PackageSelection(new NullOutput(), vfsStream::url('build'), [ - 'repositories' => [['type' => 'composer', 'url' => 'http://localhost:54715']], - 'require' => ['vendor/name' => '*'], - ], false); + $this->selection = new PackageSelection( + new NullOutput(), + vfsStream::url('build'), + [ + 'repositories' => [ + ['type' => 'composer', 'url' => 'http://localhost:54715'] + ], + 'require' => ['vendor/name' => '*'], + ], + false + ); + $this->selection->setPackagesFilter(['vendor/name']); } - protected function setFileSystem() + protected function setFileSystem(): vfsStreamDirectory { vfsStreamWrapper::register(); $root = vfsStream::newDirectory('build'); diff --git a/tests/PackageSelection/PackageSelectionTest.php b/tests/PackageSelection/PackageSelectionTest.php index 44f282e2..297ad5a5 100644 --- a/tests/PackageSelection/PackageSelectionTest.php +++ b/tests/PackageSelection/PackageSelectionTest.php @@ -1,5 +1,7 @@ assertSame($expected, $method->invokeArgs($builder, [$repository])); } - /** - * @return array - */ - public function dataGetRequired() + public function dataGetRequired(): array { $package = new Package('vendor/name', '1.0.0.0', '1.0'); $link = new Link('test', 'name'); @@ -147,13 +144,8 @@ public function dataGetRequired() /** * @dataProvider dataGetRequired - * - * @param array $expected - * @param Package $package - * @param bool $requireDependencies - * @param bool $requireDevDependencies */ - public function testGetRequired($expected, $package, $requireDependencies, $requireDevDependencies) + public function testGetRequired(array $expected, Package $package, bool $requireDependencies, bool $requireDevDependencies) { $builder = new PackageSelection(new NullOutput(), 'build', [], false); @@ -169,13 +161,10 @@ public function testGetRequired($expected, $package, $requireDependencies, $requ $property->setAccessible(true); $property->setValue($builder, $requireDevDependencies); - $this->assertSame($expected, $method->invokeArgs($builder, [$package])); + $this->assertSame($expected, $method->invokeArgs($builder, [$package, true])); } - /** - * @return array - */ - public function dataSetSelectedAsAbandoned() + public function dataSetSelectedAsAbandoned(): array { $package = new CompletePackage('vendor/name', '1.0.0.0', '1.0'); $packageAbandoned1 = new CompletePackage('vendor/name', '1.0.0.0', '1.0'); @@ -205,11 +194,8 @@ public function dataSetSelectedAsAbandoned() /** * @dataProvider dataSetSelectedAsAbandoned - * - * @param array $expected - * @param array $config */ - public function testSetSelectedAsAbandoned($expected, $config) + public function testSetSelectedAsAbandoned(array $expected, array $config) { $package = new CompletePackage('vendor/name', '1.0.0.0', '1.0'); @@ -229,4 +215,604 @@ public function testSetSelectedAsAbandoned($expected, $config) $this->assertEquals($expected, $property->getValue($builder)); } + + public function dataPruneBlacklisted(): array + { + $package0 = new Package('vendor/name', '1.0.0.0', '1.0'); + $package1 = new Package('vendor/name', '1.1.0.0', '1.1'); + $package2 = new Package('vendor/name', '1.2.0.0', '1.2'); + $packageOther = new Package('vendor/other', '1.0.0.0', '1.0'); + + $data = []; + $selected = [$package0, $package1, $package2, $packageOther]; + + $data['Blacklist Whole Project'] = [ + [$packageOther], + $selected, + ['vendor/name' => '*'], + ]; + + $data['Blacklist One Package'] = [ + [$package0, $package2, $packageOther], + $selected, + ['vendor/name' => '1.1'], + ]; + + $data['Blacklist Newer Packages'] = [ + [$package0, $package1, $packageOther], + $selected, + ['vendor/name' => '>1.1'], + ]; + + return $data; + } + + /** + * @dataProvider dataPruneBlacklisted + */ + public function testPruneBlacklisted(array $expected, array $selected, array $config) + { + $pool = new Pool(); + $builder = new PackageSelection(new NullOutput(), 'build', [ + 'blacklist' => $config, + ], false); + $reflection = new \ReflectionClass(get_class($builder)); + + $property = $reflection->getProperty('selected'); + $property->setAccessible(true); + $property->setValue($builder, $selected); + + $method = $reflection->getMethod('pruneBlacklisted'); + $method->setAccessible(true); + $method->invokeArgs($builder, [$pool, false]); + + $this->assertEquals(array_values($expected), array_values($property->getValue($builder))); + } + + public function dataSelect(): array + { + $packages = [ + 'alpha' => [ + 'name' => 'vendor/project-alpha', + 'version' => '1.2.3.0', + ], + 'alpha-dev' => [ + 'name' => 'vendor/project-alpha', + 'version' => '1.2.3.1-dev', + ], + 'beta' => [ + 'name' => 'vendor/project-beta', + 'version' => '1.2.3.0', + ], + 'beta-dev' => [ + 'name' => 'vendor/project-beta', + 'version' => '1.2.3.1-dev', + ], + 'gamma1' => [ + 'name' => 'vendor/project-gamma', + 'version' => '1.2.3.0', + ], + 'gamma2' => [ + 'name' => 'vendor/project-gamma', + 'version' => '2.3.4.0', + ], + 'gamma3' => [ + 'name' => 'vendor/project-gamma', + 'version' => '3.4.5.0', + ], + 'gamma4' => [ + 'name' => 'vendor/project-gamma', + 'version' => '4.5.6.0', + ], + 'delta' => [ + 'name' => 'vendor/project-delta', + 'version' => '1.2.3.0', + 'require' => [ + 'vendor/project-alpha' => '^1', + 'vendor/project-gamma' => '^1', + ], + ], + 'epsilon' => [ + 'name' => 'vendor/project-epsilon', + 'version' => '1.2.3.0', + 'require' => [ + 'vendor/project-alpha' => '^1', + ], + 'require-dev' => [ + 'vendor/project-gamma' => '^4', + ], + ], + 'zeta' => [ + 'name' => 'vendor/project-zeta', + 'version' => '1.2.3.0', + 'require' => [ + 'vendor/project-epsilon' => '^1', + ], + ], + 'eta' => [ + 'name' => 'vendor/project-eta', + 'version' => '1.2.3.0', + 'require' => [ + 'vendor/project-gamma' => '>=1', + ], + ], + ]; + + $repo['everything'] = [ + 'type' => 'package', + 'url' => 'example.org/everything', + 'package' => \array_values($packages), + ]; + $repo['gamma'] = [ + 'type' => 'package', + 'url' => 'example.org/project-gamma', + 'package' => [ + $packages['gamma1'], + $packages['gamma2'], + $packages['gamma3'], + $packages['gamma4'], + ], + ]; + $repo['delta'] = [ + 'type' => 'package', + 'url' => 'example.org/project-delta', + 'package' => $packages['delta'], + ]; + + foreach ($packages as &$p) { + $p = $p['name'] . '-' . $p['version']; + } + + $data = []; + + $data['Require-all'] = [ + $packages, + [ + 'repositories' => [ + $repo['everything'], + ], + ], + ]; + + $data['Require'] = [ + [ + $packages['alpha'], + $packages['gamma1'], + $packages['gamma2'], + $packages['gamma3'], + $packages['gamma4'], + ], + [ + 'minimum-stability' => 'stable', + 'repositories' => [ + $repo['everything'], + ], + 'require' => [ + 'vendor/project-alpha' => '>=1', + 'vendor/project-gamma' => '>=1', + ], + ], + ]; + + $data['Require dependencies'] = [ + [ + $packages['delta'], + $packages['alpha'], + $packages['gamma1'], + ], + [ + 'minimum-stability' => 'stable', + 'repositories' => [ + $repo['everything'], + ], + 'require' => [ + 'vendor/project-delta' => '>=1', + ], + 'require-dependencies' => true, + ], + ]; + + $data['Require dependencies and dev-dependencies'] = [ + [ + $packages['epsilon'], + $packages['alpha'], + $packages['gamma4'], + ], + [ + 'minimum-stability' => 'stable', + 'repositories' => [ + $repo['everything'], + ], + 'require' => [ + 'vendor/project-epsilon' => '>=1', + ], + 'require-dependencies' => true, + 'require-dev-dependencies' => true, + ], + ]; + + $data['Require only dependencies'] = [ + [ + $packages['alpha'], + $packages['epsilon'], + $packages['gamma1'], + $packages['gamma4'], + ], + [ + 'minimum-stability' => 'stable', + 'repositories' => [ + $repo['everything'], + ], + 'require' => [ + 'vendor/project-epsilon' => '*', + 'vendor/project-zeta' => '*', + 'vendor/project-eta' => '*', + ], + 'require-dependencies' => true, + 'require-dev-dependencies' => true, + 'only-dependencies' => true, + ], + ]; + + $data['Traverse dependencies but not dev-dependencies'] = [ + [ + $packages['zeta'], + $packages['epsilon'], + $packages['alpha'], + ], + [ + 'minimum-stability' => 'stable', + 'repositories' => [ + $repo['everything'], + ], + 'require' => [ + 'vendor/project-zeta' => '>=1', + ], + 'require-dependencies' => true, + 'require-dev-dependencies' => true, + ], + ]; + + $data['Reduce required dependencies'] = [ + [ + $packages['eta'], + $packages['gamma1'], + $packages['gamma4'], + ], + [ + 'minimum-stability' => 'stable', + 'repositories' => [ + $repo['everything'], + ], + 'require' => [ + 'vendor/project-eta' => '>=1', + ], + 'require-dependencies' => true, + ], + ]; + + $data['Load from repositories-dep'] = [ + [ + $packages['gamma1'], + $packages['gamma2'], + $packages['gamma3'], + $packages['gamma4'], + $packages['delta'], + $packages['alpha'], + ], + [ + 'minimum-stability' => 'stable', + 'repositories' => [ + $repo['gamma'], + $repo['delta'], + ], + 'repositories-dep' => [ + $repo['everything'], + ], + 'require-dependencies' => true, + ], + ]; + + $data['Set minimum-stability for a specific package'] = [ + [ + $packages['alpha'], + $packages['alpha-dev'], + $packages['beta'], + ], + [ + 'minimum-stability' => 'stable', + 'minimum-stability-per-package' => [ + 'vendor/project-alpha' => 'dev', + ], + 'repositories' => [ + $repo['everything'], + ], + 'require' => [ + 'vendor/project-alpha' => '*', + 'vendor/project-beta' => '*', + ], + ], + ]; + + return $data; + } + + /** + * @dataProvider dataSelect + */ + public function testSelect(array $expected, array $config, ?string $filterRepo = null, ?array $filterPackages = null) + { + unset(Config::$defaultRepositories['packagist'], Config::$defaultRepositories['packagist.org']); + + $composer = (new Factory())->createComposer(new NullIO(), $config, true, null, false); + + $selection = new PackageSelection(new NullOutput(), 'build', $config, false); + $selection->setRepositoryFilter($filterRepo); + $selection->setPackagesFilter($filterPackages ?? []); + + $selectionRef = new \ReflectionClass(\get_class($selection)); + + $select = $selectionRef->getMethod('select'); + $select->setAccessible(true); + $select->invokeArgs($selection, [$composer, true]); + + $selected = $selectionRef->getProperty('selected'); + $selected->setAccessible(true); + + \sort($expected, \SORT_STRING); + $this->assertEquals($expected, \array_keys($selected->getValue($selection))); + } + + public function dataClean(): array + { + $packages = [ + 'alpha' => [ + 'dist' => [ + 'type' => 'zip', + 'url' => 'http://127.0.0.1/output/dist/alpha.zip', + ], + 'source' => [ + 'type' => 'git', + 'url' => './git-repo', + ], + ], + 'beta' => [ + 'dist' => [ + 'type' => 'zip', + 'url' => 'http://192.168.0.2/output/dist/beta.zip', + ], + 'source' => [ + 'type' => 'git', + 'url' => 'http://localhost/beta.git', + ], + ], + 'gamma' => [ + 'dist' => [ + 'type' => 'zip', + 'url' => 'http://192.168.0.1/output/dist/gamma.zip', + ], + 'source' => [ + 'type' => 'git', + 'url' => 'http://192.168.1.1/gamma.git', + ], + ], + 'delta' => [ + 'dist' => [ + 'type' => 'zip', + 'url' => 'http://example.org/output/dist/delta.zip', + ], + 'source' => [ + 'type' => 'git', + 'url' => 'http://source.example.org/delta.git', + ], + ], + 'epsilon' => [ + 'dist' => [ + 'type' => 'zip', + 'url' => 'http://[abcd::]/output/dist/epsilon.zip', + ], + 'source' => [ + 'type' => 'git', + 'url' => 'http://[::1]/epsilon.git', + ], + ], + ]; + + $data['Keep everything'] = [ + [ + 'alpha' => ['http://127.0.0.1/output/dist/alpha.zip', './git-repo'], + 'beta' => ['http://192.168.0.2/output/dist/beta.zip', 'http://localhost/beta.git'], + 'gamma' => ['http://192.168.0.1/output/dist/gamma.zip', 'http://192.168.1.1/gamma.git'], + 'delta' => ['http://example.org/output/dist/delta.zip', 'http://source.example.org/delta.git'], + 'epsilon' => ['http://[abcd::]/output/dist/epsilon.zip', 'http://[::1]/epsilon.git'], + ], + [], + $packages, + ]; + + $data['Remove local file URLs'] = [ + [ + 'alpha' => ['http://127.0.0.1/output/dist/alpha.zip', null], + 'beta' => ['http://192.168.0.2/output/dist/beta.zip', 'http://localhost/beta.git'], + 'gamma' => ['http://192.168.0.1/output/dist/gamma.zip', 'http://192.168.1.1/gamma.git'], + 'delta' => ['http://example.org/output/dist/delta.zip', 'http://source.example.org/delta.git'], + 'epsilon' => ['http://[abcd::]/output/dist/epsilon.zip', 'http://[::1]/epsilon.git'], + ], + [ + 'strip-hosts' => true, + ], + $packages, + ]; + + $data['Remove local IPs'] = [ + [ + 'beta' => ['http://192.168.0.2/output/dist/beta.zip', null], + 'gamma' => ['http://192.168.0.1/output/dist/gamma.zip', 'http://192.168.1.1/gamma.git'], + 'delta' => ['http://example.org/output/dist/delta.zip', 'http://source.example.org/delta.git'], + 'epsilon' => ['http://[abcd::]/output/dist/epsilon.zip', null], + ], + [ + 'strip-hosts' => ['/local'], + ], + $packages, + ]; + + $data['Remove private IPs'] = [ + [ + 'alpha' => ['http://127.0.0.1/output/dist/alpha.zip', null], + 'beta' => [null, 'http://localhost/beta.git'], + 'delta' => ['http://example.org/output/dist/delta.zip', 'http://source.example.org/delta.git'], + 'epsilon' => ['http://[abcd::]/output/dist/epsilon.zip', 'http://[::1]/epsilon.git'], + ], + [ + 'strip-hosts' => ['/private'], + ], + $packages, + ]; + + $data['Remove IPv4 with CIDR notation'] = [ + [ + 'alpha' => ['http://127.0.0.1/output/dist/alpha.zip', null], + 'beta' => [null, 'http://localhost/beta.git'], + 'gamma' => [null, 'http://192.168.1.1/gamma.git'], + 'delta' => ['http://example.org/output/dist/delta.zip', 'http://source.example.org/delta.git'], + 'epsilon' => ['http://[abcd::]/output/dist/epsilon.zip', 'http://[::1]/epsilon.git'], + ], + [ + 'strip-hosts' => ['192.168.0.0/24'], + ], + $packages, + ]; + + $data['Remove IPv6 address'] = [ + [ + 'alpha' => ['http://127.0.0.1/output/dist/alpha.zip', null], + 'beta' => ['http://192.168.0.2/output/dist/beta.zip', 'http://localhost/beta.git'], + 'gamma' => ['http://192.168.0.1/output/dist/gamma.zip', 'http://192.168.1.1/gamma.git'], + 'delta' => ['http://example.org/output/dist/delta.zip', 'http://source.example.org/delta.git'], + 'epsilon' => [null, 'http://[::1]/epsilon.git'], + ], + [ + 'strip-hosts' => ['abcd::'], + ], + $packages, + ]; + + $data['Remove domain'] = [ + [ + 'alpha' => ['http://127.0.0.1/output/dist/alpha.zip', null], + 'beta' => ['http://192.168.0.2/output/dist/beta.zip', 'http://localhost/beta.git'], + 'gamma' => ['http://192.168.0.1/output/dist/gamma.zip', 'http://192.168.1.1/gamma.git'], + 'epsilon' => ['http://[abcd::]/output/dist/epsilon.zip', 'http://[::1]/epsilon.git'], + ], + [ + 'strip-hosts' => ['example.org'], + ], + $packages, + ]; + + $data['Preserve distURL from ArchiveBuilder'] = [ + [ + 'alpha' => ['http://127.0.0.1/output/dist/alpha.zip', null], + 'beta' => [null, 'http://localhost/beta.git'], + 'gamma' => ['http://192.168.0.1/output/dist/gamma.zip', null], + 'delta' => ['http://example.org/output/dist/delta.zip', 'http://source.example.org/delta.git'], + 'epsilon' => ['http://[abcd::]/output/dist/epsilon.zip', 'http://[::1]/epsilon.git'], + ], + [ + 'strip-hosts' => ['/private'], + 'archive' => [ + 'directory' => 'dist', + 'prefix-url' => 'http://192.168.0.1', + ], + ], + $packages, + ]; + + return $data; + } + + /** + * @dataProvider dataClean + */ + public function testClean(array $expected, array $config, array $packages) + { + $selection = new PackageSelection(new NullOutput(), 'build', $config, false); + $selectionRef = new \ReflectionClass(\get_class($selection)); + + foreach ($packages as $i => $p) { + $packages[$i] = new Package($i, '1.0.0.0', '1.0'); + $packages[$i]->setDistType($p['dist']['type']); + $packages[$i]->setDistUrl($p['dist']['url']); + $packages[$i]->setSourceType($p['source']['type']); + $packages[$i]->setSourceUrl($p['source']['url']); + } + + $selected = $selectionRef->getProperty('selected'); + $selected->setAccessible(true); + $selected->setValue($selection, $packages); + + $clean = $selectionRef->getMethod('clean'); + $clean->setAccessible(true); + + $cleanPackages = $clean->invokeArgs($selection, []); + $sources = []; + foreach ($cleanPackages as $name => $package) { + $sources[$name] = [ + (null !== $package->getDistType()) ? $package->getDistUrl() : null, + (null !== $package->getSourceType()) ? $package->getSourceUrl() : null, + ]; + } + + $this->assertEquals($expected, $sources); + } + + public function testOnlyBestCandidates() + { + $pool = new Pool(); + $repository = new ArrayRepository(); + + $packageA0 = new Package('vendor/a', '1.0.0.0', '1.0'); + $packageA1 = new Package('vendor/a', '1.1.0.0', '1.1'); + $packageB0 = new Package('vendor/b', '1.0.0.0', '1.0'); + $packageB1 = new Package('vendor/b', '1.1.0.0', '1.1'); + $packageB2 = new Package('vendor/b', '1.2.0.0', '1.2'); + $packageC0 = new Package('vendor/c', '1.0.0.0', '1.0'); + $packageC1 = new Package('vendor/c', '1.1.0.0', '1.1'); + + $constraint1 = new Constraint('=', '1.1'); + $link1 = new Link('vendor/a', 'vendor/b', $constraint1); + $packageA0->setRequires([$link1]); + + $constraint2 = new Constraint('<=', '1.1'); + $link2 = new Link('vendor/b', 'vendor/c', $constraint2); + $packageB1->setRequires([$link2]); + + $repository->addPackage($packageA0); + $repository->addPackage($packageA1); + $repository->addPackage($packageB0); + $repository->addPackage($packageB1); + $repository->addPackage($packageB2); + $repository->addPackage($packageC0); + $repository->addPackage($packageC1); + $pool->addRepository($repository); + + $rootConstraint = new Constraint('=', '1.0'); + $rootLink = new Link('top', 'vendor/a', $rootConstraint); + + $config = [ + 'only-best-candidates' => TRUE, + 'require-dependencies' => TRUE, + ]; + $builder = new PackageSelection(new NullOutput(), 'build', $config, false); + $reflection = new \ReflectionClass(get_class($builder)); + $method = $reflection->getMethod('selectLinks'); + $method->setAccessible(true); + $method->invokeArgs($builder, [$pool, [$rootLink], FALSE, FALSE]); + + $property = $reflection->getProperty('selected'); + $property->setAccessible(true); + + $this->assertEquals(array_values([$packageA0, $packageB1, $packageC1]), array_values($property->getValue($builder))); + } } diff --git a/views/assets/bootstrap.min.css b/views/assets/bootstrap.min.css deleted file mode 100644 index ed3905e0..00000000 --- a/views/assets/bootstrap.min.css +++ /dev/null @@ -1,6 +0,0 @@ -/*! - * Bootstrap v3.3.7 (http://getbootstrap.com) - * Copyright 2011-2016 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=checkbox]:focus,input[type=radio]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{background-color:transparent;border:0}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled.focus,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled].focus,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled.focus,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled].focus,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled.focus,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled].focus,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled.focus,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled].focus,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled.focus,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled].focus,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled.focus,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled].focus,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{padding-right:15px;padding-left:15px;border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;filter:alpha(opacity=0);opacity:0;line-break:auto}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);line-break:auto}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);background-color:rgba(0,0,0,0);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.modal-header:after,.modal-header:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.modal-header:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}} -/*# sourceMappingURL=bootstrap.min.css.map */ \ No newline at end of file diff --git a/views/assets/bootstrap.min.js b/views/assets/bootstrap.min.js deleted file mode 100644 index 9bcd2fcc..00000000 --- a/views/assets/bootstrap.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/*! - * Bootstrap v3.3.7 (http://getbootstrap.com) - * Copyright 2011-2016 Twitter, Inc. - * Licensed under the MIT license - */ -if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>3)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){if(a(b.target).is(this))return b.handleObj.handler.apply(this,arguments)}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.7",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a("#"===f?[]:f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.7",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c).prop(c,!0)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c).prop(c,!1))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")?(c.prop("checked")&&(a=!1),b.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==c.prop("type")&&(c.prop("checked")!==this.$element.hasClass("active")&&(a=!1),this.$element.toggleClass("active")),c.prop("checked",this.$element.hasClass("active")),a&&c.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target).closest(".btn");b.call(d,"toggle"),a(c.target).is('input[type="radio"], input[type="checkbox"]')||(c.preventDefault(),d.is("input,button")?d.trigger("focus"):d.find("input:visible,button:visible").first().trigger("focus"))}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.7",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));if(!(a>this.$items.length-1||a<0))return this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){if(!this.sliding)return this.slide("next")},c.prototype.prev=function(){if(!this.sliding)return this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.7",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass("open")&&(c&&"click"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event("hide.bs.dropdown",f)),c.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger(a.Event("hidden.bs.dropdown",f)))))}))}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.7",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=b(e),g=f.hasClass("open");if(c(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",c);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),f.toggleClass("open").trigger(a.Event("shown.bs.dropdown",h))}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(".disabled, :disabled")){var e=b(d),g=e.hasClass("open");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find(".dropdown-menu"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&jdocument.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:""})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},c.prototype.checkScrollbar=function(){var a=window.innerWidth;if(!a){var b=document.documentElement.getBoundingClientRect();a=b.right-Math.abs(b.left)}this.bodyIsOverflowing=document.body.clientWidth',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);if(c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),!c.isInStateTrue())return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-mo.width?"left":"left"==h&&k.left-lg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null,a.$element=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;!e&&/destroy|hide/.test(b)||(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.7",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.7",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b=e[a]&&(void 0===e[a+1]||b .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.7",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return e=a-d&&"bottom"},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); \ No newline at end of file diff --git a/views/assets/css/style.scss b/views/assets/css/style.scss new file mode 100644 index 00000000..6675bf8c --- /dev/null +++ b/views/assets/css/style.scss @@ -0,0 +1,45 @@ +// Imports all of Bootstrap +// @import '~bootstrap/scss/bootstrap'; + +// Imports only used Bootstrap +@import "~bootstrap/scss/functions"; +@import "~bootstrap/scss/variables"; +@import "~bootstrap/scss/mixins"; +@import "~bootstrap/scss/root"; +@import "~bootstrap/scss/reboot"; +@import "~bootstrap/scss/type"; +// @import "~bootstrap/scss/images"; +@import "~bootstrap/scss/code"; +@import "~bootstrap/scss/grid"; +// @import "~bootstrap/scss/tables"; +@import "~bootstrap/scss/forms"; +@import "~bootstrap/scss/buttons"; +@import "~bootstrap/scss/transitions"; +// @import "~bootstrap/scss/dropdown"; +// @import "~bootstrap/scss/button-group"; +// @import "~bootstrap/scss/input-group"; +// @import "~bootstrap/scss/custom-forms"; +// @import "~bootstrap/scss/nav"; +// @import "~bootstrap/scss/navbar"; +@import "~bootstrap/scss/card"; +// @import "~bootstrap/scss/breadcrumb"; +// @import "~bootstrap/scss/pagination"; +@import "~bootstrap/scss/badge"; +// @import "~bootstrap/scss/jumbotron"; +// @import "~bootstrap/scss/alert"; +// @import "~bootstrap/scss/progress"; +// @import "~bootstrap/scss/media"; +// @import "~bootstrap/scss/list-group"; +// @import "~bootstrap/scss/close"; +// @import "~bootstrap/scss/modal"; +// @import "~bootstrap/scss/tooltip"; +// @import "~bootstrap/scss/popover"; +// @import "~bootstrap/scss/carousel"; +@import "~bootstrap/scss/utilities"; +@import "~bootstrap/scss/print"; + +pre.file { + border-left: 2px solid $primary; + background-color: $light; + padding: map-get($spacers, 2); +} \ No newline at end of file diff --git a/views/assets/jquery.slim.min.js b/views/assets/jquery.slim.min.js deleted file mode 100644 index a240ca9b..00000000 --- a/views/assets/jquery.slim.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! jQuery v3.1.1 -ajax,-ajax/jsonp,-ajax/load,-ajax/parseXML,-ajax/script,-ajax/var/location,-ajax/var/nonce,-ajax/var/rquery,-ajax/xhr,-manipulation/_evalUrl,-event/ajax,-effects,-effects/animatedSelector,-effects/Tween,-deprecated | (c) jQuery Foundation | jquery.org/license */ -!function(a,b){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){"use strict";var c=[],d=a.document,e=Object.getPrototypeOf,f=c.slice,g=c.concat,h=c.push,i=c.indexOf,j={},k=j.toString,l=j.hasOwnProperty,m=l.toString,n=m.call(Object),o={};function p(a,b){b=b||d;var c=b.createElement("script");c.text=a,b.head.appendChild(c).parentNode.removeChild(c)}var q="3.1.1 -ajax,-ajax/jsonp,-ajax/load,-ajax/parseXML,-ajax/script,-ajax/var/location,-ajax/var/nonce,-ajax/var/rquery,-ajax/xhr,-manipulation/_evalUrl,-event/ajax,-effects,-effects/animatedSelector,-effects/Tween,-deprecated",r=function(a,b){return new r.fn.init(a,b)},s=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,t=/^-ms-/,u=/-([a-z])/g,v=function(a,b){return b.toUpperCase()};r.fn=r.prototype={jquery:q,constructor:r,length:0,toArray:function(){return f.call(this)},get:function(a){return null==a?f.call(this):a<0?this[a+this.length]:this[a]},pushStack:function(a){var b=r.merge(this.constructor(),a);return b.prevObject=this,b},each:function(a){return r.each(this,a)},map:function(a){return this.pushStack(r.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(f.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(a<0?b:0);return this.pushStack(c>=0&&c0&&b-1 in a)}var x=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=function(a,b){for(var c=0,d=a.length;c+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(N),U=new RegExp("^"+L+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L+"|[*])"),ATTR:new RegExp("^"+M),PSEUDO:new RegExp("^"+N),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),aa=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:d<0?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ba=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ca=function(a,b){return b?"\0"===a?"\ufffd":a.slice(0,-1)+"\\"+a.charCodeAt(a.length-1).toString(16)+" ":"\\"+a},da=function(){m()},ea=ta(function(a){return a.disabled===!0&&("form"in a||"label"in a)},{dir:"parentNode",next:"legend"});try{G.apply(D=H.call(v.childNodes),v.childNodes),D[v.childNodes.length].nodeType}catch(fa){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s=b&&b.ownerDocument,w=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==w&&9!==w&&11!==w)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==w&&(l=Z.exec(a)))if(f=l[1]){if(9===w){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(s&&(j=s.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(l[2])return G.apply(d,b.getElementsByTagName(a)),d;if((f=l[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==w)s=b,r=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(ba,ca):b.setAttribute("id",k=u),o=g(a),h=o.length;while(h--)o[h]="#"+k+" "+sa(o[h]);r=o.join(","),s=$.test(a)&&qa(b.parentNode)||b}if(r)try{return G.apply(d,s.querySelectorAll(r)),d}catch(x){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(P,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("fieldset");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&a.sourceIndex-b.sourceIndex;if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return function(b){return"form"in b?b.parentNode&&b.disabled===!1?"label"in b?"label"in b.parentNode?b.parentNode.disabled===a:b.disabled===a:b.isDisabled===a||b.isDisabled!==!a&&ea(b)===a:b.disabled===a:"label"in b&&b.disabled===a}}function pa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function qa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return!!b&&"HTML"!==b.nodeName},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),v!==n&&(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(n.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){return a.getAttribute("id")===b}},d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}}):(d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}},d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c,d,e,f=b.getElementById(a);if(f){if(c=f.getAttributeNode("id"),c&&c.value===a)return[f];e=b.getElementsByName(a),d=0;while(f=e[d++])if(c=f.getAttributeNode("id"),c&&c.value===a)return[f]}return[]}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){if("undefined"!=typeof b.getElementsByClassName&&p)return b.getElementsByClassName(a)},r=[],q=[],(c.qsa=Y.test(n.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){a.innerHTML="";var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+K+"*[*^$|!~]?="),2!==a.querySelectorAll(":enabled").length&&q.push(":enabled",":disabled"),o.appendChild(a).disabled=!0,2!==a.querySelectorAll(":disabled").length&&q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Y.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"*"),s.call(a,"[s!='']:x"),r.push("!=",N)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Y.test(o.compareDocumentPosition),t=b||Y.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?I(k,a)-I(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?I(k,a)-I(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?la(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(S,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.escape=function(a){return(a+"").replace(ba,ca)},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(_,aa),a[3]=(a[3]||a[4]||a[5]||"").replace(_,aa),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return V.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&T.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(_,aa).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:!b||(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(O," ")+" ").indexOf(c)>-1:"|="===b&&(e===c||e.slice(0,c.length+1)===c+"-"))}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(P,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(_,aa),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return U.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(_,aa).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:oa(!1),disabled:oa(!0),checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:pa(function(){return[0]}),last:pa(function(a,b){return[b-1]}),eq:pa(function(a,b,c){return[c<0?c+b:c]}),even:pa(function(a,b){for(var c=0;c=0;)a.push(d);return a}),gt:pa(function(a,b,c){for(var d=c<0?c+b:c;++d1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function va(a,b,c){for(var d=0,e=b.length;d-1&&(f[j]=!(g[j]=l))}}else r=wa(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ya(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ta(function(a){return a===b},h,!0),l=ta(function(a){return I(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];i1&&ua(m),i>1&&sa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(P,"$1"),c,i0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=E.call(i));u=wa(u)}G.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&ga.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=ya(b[c]),f[u]?d.push(f):e.push(f);f=A(a,za(e,d)),f.selector=a}return f},i=ga.select=function(a,b,c,e){var f,i,j,k,l,m="function"==typeof a&&a,n=!e&&g(a=m.selector||a);if(c=c||[],1===n.length){if(i=n[0]=n[0].slice(0),i.length>2&&"ID"===(j=i[0]).type&&9===b.nodeType&&p&&d.relative[i[1].type]){if(b=(d.find.ID(j.matches[0].replace(_,aa),b)||[])[0],!b)return c;m&&(b=b.parentNode),a=a.slice(i.shift().value.length)}f=V.needsContext.test(a)?0:i.length;while(f--){if(j=i[f],d.relative[k=j.type])break;if((l=d.find[k])&&(e=l(j.matches[0].replace(_,aa),$.test(i[0].type)&&qa(b.parentNode)||b))){if(i.splice(f,1),a=e.length&&sa(i),!a)return G.apply(c,e),c;break}}}return(m||h(a,n))(e,b,!p,c,!b||$.test(a)&&qa(b.parentNode)||b),c},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("fieldset"))}),ja(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){if(!c)return a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){if(!c&&"input"===a.nodeName.toLowerCase())return a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(J,function(a,b,c){var d;if(!c)return a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);r.find=x,r.expr=x.selectors,r.expr[":"]=r.expr.pseudos,r.uniqueSort=r.unique=x.uniqueSort,r.text=x.getText,r.isXMLDoc=x.isXML,r.contains=x.contains,r.escapeSelector=x.escape;var y=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&r(a).is(c))break;d.push(a)}return d},z=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},A=r.expr.match.needsContext,B=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i,C=/^.[^:#\[\.,]*$/;function D(a,b,c){return r.isFunction(b)?r.grep(a,function(a,d){return!!b.call(a,d,a)!==c}):b.nodeType?r.grep(a,function(a){return a===b!==c}):"string"!=typeof b?r.grep(a,function(a){return i.call(b,a)>-1!==c}):C.test(b)?r.filter(b,a,c):(b=r.filter(b,a),r.grep(a,function(a){return i.call(b,a)>-1!==c&&1===a.nodeType}))}r.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?r.find.matchesSelector(d,a)?[d]:[]:r.find.matches(a,r.grep(b,function(a){return 1===a.nodeType}))},r.fn.extend({find:function(a){var b,c,d=this.length,e=this;if("string"!=typeof a)return this.pushStack(r(a).filter(function(){for(b=0;b1?r.uniqueSort(c):c},filter:function(a){return this.pushStack(D(this,a||[],!1))},not:function(a){return this.pushStack(D(this,a||[],!0))},is:function(a){return!!D(this,"string"==typeof a&&A.test(a)?r(a):a||[],!1).length}});var E,F=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,G=r.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||E,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:F.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof r?b[0]:b,r.merge(this,r.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),B.test(e[1])&&r.isPlainObject(b))for(e in b)r.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&(this[0]=f,this.length=1),this}return a.nodeType?(this[0]=a,this.length=1,this):r.isFunction(a)?void 0!==c.ready?c.ready(a):a(r):r.makeArray(a,this)};G.prototype=r.fn,E=r(d);var H=/^(?:parents|prev(?:Until|All))/,I={children:!0,contents:!0,next:!0,prev:!0};r.fn.extend({has:function(a){var b=r(a,this),c=b.length;return this.filter(function(){for(var a=0;a-1:1===c.nodeType&&r.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?r.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?i.call(r(a),this[0]):i.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(r.uniqueSort(r.merge(this.get(),r(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function J(a,b){while((a=a[b])&&1!==a.nodeType);return a}r.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return y(a,"parentNode")},parentsUntil:function(a,b,c){return y(a,"parentNode",c)},next:function(a){return J(a,"nextSibling")},prev:function(a){return J(a,"previousSibling")},nextAll:function(a){return y(a,"nextSibling")},prevAll:function(a){return y(a,"previousSibling")},nextUntil:function(a,b,c){return y(a,"nextSibling",c)},prevUntil:function(a,b,c){return y(a,"previousSibling",c)},siblings:function(a){return z((a.parentNode||{}).firstChild,a)},children:function(a){return z(a.firstChild)},contents:function(a){return a.contentDocument||r.merge([],a.childNodes)}},function(a,b){r.fn[a]=function(c,d){var e=r.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=r.filter(d,e)),this.length>1&&(I[a]||r.uniqueSort(e),H.test(a)&&e.reverse()),this.pushStack(e)}});var K=/[^\x20\t\r\n\f]+/g;function L(a){var b={};return r.each(a.match(K)||[],function(a,c){b[c]=!0}),b}r.Callbacks=function(a){a="string"==typeof a?L(a):r.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h-1)f.splice(c,1),c<=h&&h--}),this},has:function(a){return a?r.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||b||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j};function M(a){return a}function N(a){throw a}function O(a,b,c){var d;try{a&&r.isFunction(d=a.promise)?d.call(a).done(b).fail(c):a&&r.isFunction(d=a.then)?d.call(a,b,c):b.call(void 0,a)}catch(a){c.call(void 0,a)}}r.extend({Deferred:function(b){var c=[["notify","progress",r.Callbacks("memory"),r.Callbacks("memory"),2],["resolve","done",r.Callbacks("once memory"),r.Callbacks("once memory"),0,"resolved"],["reject","fail",r.Callbacks("once memory"),r.Callbacks("once memory"),1,"rejected"]],d="pending",e={state:function(){return d},always:function(){return f.done(arguments).fail(arguments),this},"catch":function(a){return e.then(null,a)},pipe:function(){var a=arguments;return r.Deferred(function(b){r.each(c,function(c,d){var e=r.isFunction(a[d[4]])&&a[d[4]];f[d[1]](function(){var a=e&&e.apply(this,arguments);a&&r.isFunction(a.promise)?a.promise().progress(b.notify).done(b.resolve).fail(b.reject):b[d[0]+"With"](this,e?[a]:arguments)})}),a=null}).promise()},then:function(b,d,e){var f=0;function g(b,c,d,e){return function(){var h=this,i=arguments,j=function(){var a,j;if(!(b=f&&(d!==N&&(h=void 0,i=[a]),c.rejectWith(h,i))}};b?k():(r.Deferred.getStackHook&&(k.stackTrace=r.Deferred.getStackHook()),a.setTimeout(k))}}return r.Deferred(function(a){c[0][3].add(g(0,a,r.isFunction(e)?e:M,a.notifyWith)),c[1][3].add(g(0,a,r.isFunction(b)?b:M)),c[2][3].add(g(0,a,r.isFunction(d)?d:N))}).promise()},promise:function(a){return null!=a?r.extend(a,e):e}},f={};return r.each(c,function(a,b){var g=b[2],h=b[5];e[b[1]]=g.add,h&&g.add(function(){d=h},c[3-a][2].disable,c[0][2].lock),g.add(b[3].fire),f[b[0]]=function(){return f[b[0]+"With"](this===f?void 0:this,arguments),this},f[b[0]+"With"]=g.fireWith}),e.promise(f),b&&b.call(f,f),f},when:function(a){var b=arguments.length,c=b,d=Array(c),e=f.call(arguments),g=r.Deferred(),h=function(a){return function(c){d[a]=this,e[a]=arguments.length>1?f.call(arguments):c,--b||g.resolveWith(d,e)}};if(b<=1&&(O(a,g.done(h(c)).resolve,g.reject),"pending"===g.state()||r.isFunction(e[c]&&e[c].then)))return g.then();while(c--)O(e[c],h(c),g.reject);return g.promise()}});var P=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;r.Deferred.exceptionHook=function(b,c){a.console&&a.console.warn&&b&&P.test(b.name)&&a.console.warn("jQuery.Deferred exception: "+b.message,b.stack,c)},r.readyException=function(b){a.setTimeout(function(){throw b})};var Q=r.Deferred();r.fn.ready=function(a){return Q.then(a)["catch"](function(a){r.readyException(a)}),this},r.extend({isReady:!1,readyWait:1, -holdReady:function(a){a?r.readyWait++:r.ready(!0)},ready:function(a){(a===!0?--r.readyWait:r.isReady)||(r.isReady=!0,a!==!0&&--r.readyWait>0||Q.resolveWith(d,[r]))}}),r.ready.then=Q.then;function R(){d.removeEventListener("DOMContentLoaded",R),a.removeEventListener("load",R),r.ready()}"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(r.ready):(d.addEventListener("DOMContentLoaded",R),a.addEventListener("load",R));var S=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===r.type(c)){e=!0;for(h in c)S(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,r.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(r(a),c)})),b))for(;h1,null,!0)},removeData:function(a){return this.each(function(){W.remove(this,a)})}}),r.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=V.get(a,b),c&&(!d||r.isArray(c)?d=V.access(a,b,r.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=r.queue(a,b),d=c.length,e=c.shift(),f=r._queueHooks(a,b),g=function(){r.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return V.get(a,c)||V.access(a,c,{empty:r.Callbacks("once memory").add(function(){V.remove(a,[b+"queue",c])})})}}),r.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length\x20\t\r\n\f]+)/i,ka=/^$|\/(?:java|ecma)script/i,la={option:[1,"",""],thead:[1,"",""],col:[2,"",""],tr:[2,"",""],td:[3,"",""],_default:[0,"",""]};la.optgroup=la.option,la.tbody=la.tfoot=la.colgroup=la.caption=la.thead,la.th=la.td;function ma(a,b){var c;return c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[],void 0===b||b&&r.nodeName(a,b)?r.merge([a],c):c}function na(a,b){for(var c=0,d=a.length;c-1)e&&e.push(f);else if(j=r.contains(f.ownerDocument,f),g=ma(l.appendChild(f),"script"),j&&na(g),c){k=0;while(f=g[k++])ka.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),o.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="x",o.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var qa=d.documentElement,ra=/^key/,sa=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,ta=/^([^.]*)(?:\.(.+)|)/;function ua(){return!0}function va(){return!1}function wa(){try{return d.activeElement}catch(a){}}function xa(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)xa(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=va;else if(!e)return a;return 1===f&&(g=e,e=function(a){return r().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=r.guid++)),a.each(function(){r.event.add(this,b,e,d,c)})}r.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=V.get(a);if(q){c.handler&&(f=c,c=f.handler,e=f.selector),e&&r.find.matchesSelector(qa,e),c.guid||(c.guid=r.guid++),(i=q.events)||(i=q.events={}),(g=q.handle)||(g=q.handle=function(b){return"undefined"!=typeof r&&r.event.triggered!==b.type?r.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(K)||[""],j=b.length;while(j--)h=ta.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n&&(l=r.event.special[n]||{},n=(e?l.delegateType:l.bindType)||n,l=r.event.special[n]||{},k=r.extend({type:n,origType:p,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&r.expr.match.needsContext.test(e),namespace:o.join(".")},f),(m=i[n])||(m=i[n]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,o,g)!==!1||a.addEventListener&&a.addEventListener(n,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),r.event.global[n]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=V.hasData(a)&&V.get(a);if(q&&(i=q.events)){b=(b||"").match(K)||[""],j=b.length;while(j--)if(h=ta.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n){l=r.event.special[n]||{},n=(d?l.delegateType:l.bindType)||n,m=i[n]||[],h=h[2]&&new RegExp("(^|\\.)"+o.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&p!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,o,q.handle)!==!1||r.removeEvent(a,n,q.handle),delete i[n])}else for(n in i)r.event.remove(a,n+b[j],c,d,!0);r.isEmptyObject(i)&&V.remove(a,"handle events")}},dispatch:function(a){var b=r.event.fix(a),c,d,e,f,g,h,i=new Array(arguments.length),j=(V.get(this,"events")||{})[b.type]||[],k=r.event.special[b.type]||{};for(i[0]=b,c=1;c=1))for(;j!==this;j=j.parentNode||this)if(1===j.nodeType&&("click"!==a.type||j.disabled!==!0)){for(f=[],g={},c=0;c-1:r.find(e,this,null,[j]).length),g[e]&&f.push(d);f.length&&h.push({elem:j,handlers:f})}return j=this,i\x20\t\r\n\f]*)[^>]*)\/>/gi,za=/ diff --git a/views/package.html.twig b/views/package.html.twig index 2b73be9c..a98dc928 100644 --- a/views/package.html.twig +++ b/views/package.html.twig @@ -1,13 +1,15 @@ - - - - - - - - {{ package.highest.name }} - - +{% set row_class = 'row mb-0' %} +{% set col1_class = 'col-sm-3 col-md-2' %} +{% set col2_class = 'col-sm-9 col-md-10' %} + + + + + + + + {{ package.highest.name }} + {% if package.abandoned %} @@ -20,67 +22,65 @@ {% endif %} {% endif %} - - + {% if package.highest.description %} {{ package.highest.description }} {% endif %} + + + + {% if package.highest.keywords %} - - Keywords - {{ package.highest.keywords|join(', ') }} - + Keywords + + {% for keyword in package.highest.keywords|sort %} + {{ keyword }} + {% endfor %} + {% endif %} {% if package.highest.homepage %} - - Homepage - {{ package.highest.homepage }} - + Homepage + + {{ package.highest.homepage }} + {% endif %} {% if package.highest.license %} - - License - {{ package.highest.license|join(', ') }} - + License + {{ package.highest.license|join(', ') }} {% endif %} {% if package.highest.authors %} - - Authors - + Authors + {% for author in package.highest.authors %} - {%- if author.homepage -%} - {{ author.name }} - {%- else -%} - {{ author.name }} - {%- endif -%} - {%- if not loop.last -%}, {% endif -%} + {%- if author.homepage -%} + {{ author.name }} + {%- else -%} + {{ author.name }} + {%- endif -%} + {%- if not loop.last -%}, {% endif -%} {% endfor %} - - + {% endif %} {% if package.highest.support %} - - Support - - + Support + + {% for support_type, support_url in package.highest.support %} {{ support_type|capitalize }}: {{ support_url }} {% endfor %} - - + {% endif %} - - Releases - + Releases + {% for version in package.versions %} {% set branch_alias = attribute(version.extra['branch-alias'], version.prettyVersion) %} @@ -88,28 +88,29 @@ {% set branch_alias = ", branch-alias: " ~ branch_alias %} {%- endif -%} - {%- if version.distType -%} + {%- if package.highest.type == 'metapackage' -%} + {{ version.prettyVersion }} + {%- elseif version.distType -%} {{ version.prettyVersion }} {%- else -%} {{ version.prettyVersion }} {%- endif -%} {%- if not loop.last -%}, {% endif -%} {% endfor %} - - + {% set package_dependencies = attribute(dependencies, name) %} + {% if package_dependencies and package_dependencies|length %} - - Required by - - + Required by + + {% for dependency in package_dependencies %} {{ dependency }} {% endfor %} - - + {% endif %} + diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 00000000..3c866179 --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,15 @@ +const Encore = require('@symfony/webpack-encore') + +Encore + .addEntry('app', './views/assets/js/app.js') + .addStyleEntry('style', './views/assets/css/style.scss') + .cleanupOutputBeforeBuild() + .disableSingleRuntimeChunk() + .enableSassLoader() + .enableSourceMaps(!Encore.isProduction()) + .setOutputPath('views/build/') + .setPublicPath('/build') + +const config = Encore.getWebpackConfig() + +module.exports = config
/', $html)); } @@ -75,7 +77,7 @@ public function testRepositoryWithNoName() $html = $this->root->getChild('build/index.html')->getContent(); - $this->assertRegExp('/
@@ -20,67 +22,65 @@ {% endif %}
{{ package.highest.description }}