diff --git a/.gitignore b/.gitignore index b386531f0..1f3de0e3a 100644 --- a/.gitignore +++ b/.gitignore @@ -4,8 +4,9 @@ build/coverage build/logs build/pdepend cache.properties -phpunit.xml +/tests/_files/tmp /vendor /composer.lock /composer.phar /.idea +/.php_cs.cache diff --git a/.php_cs b/.php_cs new file mode 100644 index 000000000..de5cde180 --- /dev/null +++ b/.php_cs @@ -0,0 +1,69 @@ +files() + ->in('src') + ->in('tests') + ->exclude('_files') + ->name('*.php'); + +return Symfony\CS\Config\Config::create() + ->setUsingCache(true) + ->level(\Symfony\CS\FixerInterface::NONE_LEVEL) + ->fixers( + array( + 'align_double_arrow', + 'align_equals', + 'braces', + 'concat_with_spaces', + 'duplicate_semicolon', + 'elseif', + 'empty_return', + 'encoding', + 'eof_ending', + 'extra_empty_lines', + 'function_call_space', + 'function_declaration', + 'indentation', + 'join_function', + 'line_after_namespace', + 'linefeed', + 'list_commas', + 'lowercase_constants', + 'lowercase_keywords', + 'method_argument_space', + 'multiple_use', + 'namespace_no_leading_whitespace', + 'no_blank_lines_after_class_opening', + 'no_empty_lines_after_phpdocs', + 'parenthesis', + 'php_closing_tag', + 'phpdoc_indent', + 'phpdoc_no_access', + 'phpdoc_no_empty_return', + 'phpdoc_no_package', + 'phpdoc_params', + 'phpdoc_scalar', + 'phpdoc_separation', + 'phpdoc_to_comment', + 'phpdoc_trim', + 'phpdoc_types', + 'phpdoc_var_without_name', + 'remove_lines_between_uses', + 'return', + 'self_accessor', + 'short_array_syntax', + 'short_tag', + 'single_line_after_imports', + 'single_quote', + 'spaces_before_semicolon', + 'spaces_cast', + 'ternary_spaces', + 'trailing_spaces', + 'trim_array_spaces', + 'unused_use', + 'visibility', + 'whitespacy_lines' + ) + ) + ->finder($finder); + diff --git a/.travis.yml b/.travis.yml index ad88a08d5..be89e1948 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,20 +1,22 @@ language: php php: - - 5.3.3 - - 5.3 - - 5.4 - - 5.5 - 5.6 + - 7.0 + - nightly -before_script: - - COMPOSER_ROOT_VERSION=dev-master composer install --prefer-source +sudo: false -script: vendor/bin/phpunit --configuration ./build/travis-ci.xml +before_install: + - composer self-update + +install: + - travis_retry composer install --no-interaction --prefer-source + +script: + + - vendor/bin/phpunit --configuration build notifications: email: false - irc: - channels: - - "irc.freenode.org#phpunit" - use_notice: true + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 40dbc25e7..76a434585 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,5 +1 @@ -Pull Requests for bug fixes should be made against the current release branch (2.0). - -Pull Requests for new features should be made against master. - -For further notes please refer to [https://github.com/sebastianbergmann/phpunit/blob/master/CONTRIBUTING.md](https://github.com/sebastianbergmann/phpunit/blob/master/CONTRIBUTING.md) +Please refer to [https://github.com/sebastianbergmann/phpunit/blob/master/CONTRIBUTING.md](https://github.com/sebastianbergmann/phpunit/blob/master/CONTRIBUTING.md) for details on how to contribute to this project. diff --git a/ChangeLog-2.2.md b/ChangeLog-2.2.md new file mode 100644 index 000000000..353b6f650 --- /dev/null +++ b/ChangeLog-2.2.md @@ -0,0 +1,56 @@ +# Changes in PHP_CodeCoverage 2.2 + +All notable changes of the PHP_CodeCoverage 2.2 release series are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [2.2.4] - 2015-10-06 + +### Fixed + +* Fixed [#391](https://github.com/sebastianbergmann/php-code-coverage/pull/391): Missing `` tag + +## [2.2.3] - 2015-09-14 + +### Fixed + +* Fixed [#368](https://github.com/sebastianbergmann/php-code-coverage/pull/368): Blacklists and whitelists are not merged when merging data sets +* Fixed [#370](https://github.com/sebastianbergmann/php-code-coverage/issues/370): Confusing statistics for source file that declares a class without methods +* Fixed [#372](https://github.com/sebastianbergmann/php-code-coverage/pull/372): Nested classes and functions are not handled correctly +* Fixed [#382](https://github.com/sebastianbergmann/php-code-coverage/issues/382): Crap4J report generates incorrect XML logfile + +## [2.2.2] - 2015-08-04 + +### Added + +* Reintroduced the `PHP_CodeCoverage_Driver_HHVM` driver as an extension of `PHP_CodeCoverage_Driver_Xdebug` that does not use `xdebug_start_code_coverage()` with options not supported by HHVM + +### Changed + +* Bumped required version of `sebastian/environment` to 1.3.2 for [#365](https://github.com/sebastianbergmann/php-code-coverage/issues/365) + +## [2.2.1] - 2015-08-02 + +### Changed + +* Bumped required version of `sebastian/environment` to 1.3.1 for [#365](https://github.com/sebastianbergmann/php-code-coverage/issues/365) + +## [2.2.0] - 2015-08-01 + +### Added + +* Added a driver for PHPDBG (requires PHP 7) +* Added `PHP_CodeCoverage::setDisableIgnoredLines()` to disable the ignoring of lines using annotations such as `@codeCoverageIgnore` + +### Changed + +* Annotating a method with `@deprecated` now has the same effect as annotating it with `@codeCoverageIgnore` + +### Removed + +* The dedicated driver for HHVM, `PHP_CodeCoverage_Driver_HHVM` has been removed + +[2.2.4]: https://github.com/sebastianbergmann/php-code-coverage/compare/2.2.3...2.2.4 +[2.2.3]: https://github.com/sebastianbergmann/php-code-coverage/compare/2.2.2...2.2.3 +[2.2.2]: https://github.com/sebastianbergmann/php-code-coverage/compare/2.2.1...2.2.2 +[2.2.1]: https://github.com/sebastianbergmann/php-code-coverage/compare/2.2.0...2.2.1 +[2.2.0]: https://github.com/sebastianbergmann/php-code-coverage/compare/2.1...2.2.0 + diff --git a/ChangeLog-3.0.md b/ChangeLog-3.0.md new file mode 100644 index 000000000..a39fa8d47 --- /dev/null +++ b/ChangeLog-3.0.md @@ -0,0 +1,31 @@ +# Changes in PHP_CodeCoverage 3.0 + +All notable changes of the PHP_CodeCoverage 3.0 release series are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [3.0.2] - 2015-11-12 + +### Changed + +* It is now optional that `@deprecated` code is ignored + +## [3.0.1] - 2015-10-06 + +### Fixed + +* Fixed [#391](https://github.com/sebastianbergmann/php-code-coverage/pull/391): Missing `` tag + +## [3.0.0] - 2015-10-02 + +### Changed + +* It is now mandatory to configure a whitelist + +### Removed + +* The blacklist functionality has been removed +* PHP_CodeCoverage is no longer supported on PHP 5.3, PHP 5.4, and PHP 5.5 + +[3.0.2]: https://github.com/sebastianbergmann/php-code-coverage/compare/3.0.1...3.0.2 +[3.0.1]: https://github.com/sebastianbergmann/php-code-coverage/compare/3.0.0...3.0.1 +[3.0.0]: https://github.com/sebastianbergmann/php-code-coverage/compare/2.2...3.0.0 + diff --git a/ChangeLog-3.1.md b/ChangeLog-3.1.md new file mode 100644 index 000000000..f7a0de904 --- /dev/null +++ b/ChangeLog-3.1.md @@ -0,0 +1,30 @@ +# Changes in PHP_CodeCoverage 3.1 + +All notable changes of the PHP_CodeCoverage 3.1 release series are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [3.1.1] - 2016-02-04 + +### Changed + +* Allow version 2.0.x of `sebastian/version` dependency + +## [3.1.0] - 2016-01-11 + +### Added + +* Implemented [#234](https://github.com/sebastianbergmann/php-code-coverage/issues/234): Optionally raise an exception when a specified unit of code is not executed + +### Changed + +* The Clover XML report now contains cyclomatic complexity information +* The Clover XML report now contains method visibility information +* Cleanup and refactoring of various areas of code +* Added missing test cases + +### Removed + +* The functionality controlled by the `mapTestClassNameToCoveredClassName` setting has been removed + +[3.1.1]: https://github.com/sebastianbergmann/php-code-coverage/compare/3.1.0...3.1.1 +[3.1.0]: https://github.com/sebastianbergmann/php-code-coverage/compare/3.0...3.1.0 + diff --git a/ChangeLog-3.2.md b/ChangeLog-3.2.md new file mode 100644 index 000000000..34c65cf49 --- /dev/null +++ b/ChangeLog-3.2.md @@ -0,0 +1,23 @@ +# Changes in PHP_CodeCoverage 3.2 + +All notable changes of the PHP_CodeCoverage 3.2 release series are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [3.2.1] - 2016-02-18 + +### Changed + +* Updated dependency information in `composer.json` + +## [3.2.0] - 2016-02-13 + +### Added + +* Added optional check for missing `@covers` annotation when the usage of `@covers` annotations is forced + +### Changed + +* Improved `PHP_CodeCoverage_UnintentionallyCoveredCodeException` message + +[3.2.1]: https://github.com/sebastianbergmann/php-code-coverage/compare/3.2.0...3.2.1 +[3.2.0]: https://github.com/sebastianbergmann/php-code-coverage/compare/3.1...3.2.0 + diff --git a/ChangeLog-3.3.md b/ChangeLog-3.3.md new file mode 100644 index 000000000..7a5f84fbe --- /dev/null +++ b/ChangeLog-3.3.md @@ -0,0 +1,19 @@ +# Changes in PHP_CodeCoverage 3.3 + +All notable changes of the PHP_CodeCoverage 3.3 release series are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [3.3.1] - 2016-04-08 + +### Fixed + +* Fixed handling of lines that contain `declare` statements + +## [3.3.0] - 2016-03-03 + +### Added + +* Added support for whitelisting classes for the unintentionally covered code unit check + +[3.3.1]: https://github.com/sebastianbergmann/php-code-coverage/compare/3.3.0...3.3.1 +[3.3.0]: https://github.com/sebastianbergmann/php-code-coverage/compare/3.2...3.3.0 + diff --git a/ChangeLog-4.0.md b/ChangeLog-4.0.md new file mode 100644 index 000000000..f2156cf5e --- /dev/null +++ b/ChangeLog-4.0.md @@ -0,0 +1,12 @@ +# Changes in PHP_CodeCoverage 4.0 + +All notable changes of the PHP_CodeCoverage 4.0 release series are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles. + +## [4.0.0] - 2016-MM-DD + +### Changed + +* This component now uses namespaces + +[4.0.0]: https://github.com/sebastianbergmann/php-code-coverage/compare/3.3...4.0.0 + diff --git a/README.md b/README.md index 6ca608a40..bf055749e 100644 --- a/README.md +++ b/README.md @@ -7,16 +7,27 @@ ## Requirements -* PHP 5.3.3 is required but using the latest version of PHP is highly recommended -* [Xdebug](http://xdebug.org/) 2.1.3 is required but using the latest version of Xdebug is highly recommended +PHP 5.6 is required but using the latest version of PHP is highly recommended. + +### PHP 5 + +[Xdebug](http://xdebug.org/) is the only source of raw code coverage data supported for PHP 5. Version 2.2.1 of Xdebug is required but using the latest version is highly recommended. + +### PHP 7 + +Version 2.4.0 (or later) of [Xdebug](http://xdebug.org/) as well as [phpdbg](http://phpdbg.com/docs) are supported sources of raw code coverage data for PHP 7. + +### HHVM + +A version of HHVM that implements the Xdebug API for code coverage (`xdebug_*_code_coverage()`) is required. ## Installation -To add PHP_CodeCoverage as a local, per-project dependency to your project, simply add a dependency on `phpunit/php-code-coverage` to your project's `composer.json` file. Here is a minimal example of a `composer.json` file that just defines a dependency on PHP_CodeCoverage 2.0: +To add PHP_CodeCoverage as a local, per-project dependency to your project, simply add a dependency on `phpunit/php-code-coverage` to your project's `composer.json` file. Here is a minimal example of a `composer.json` file that just defines a dependency on PHP_CodeCoverage 3.0: { "require": { - "phpunit/php-code-coverage": "~2.0" + "phpunit/php-code-coverage": "^4" } } @@ -37,4 +48,3 @@ $writer->process($coverage, '/tmp/clover.xml'); $writer = new PHP_CodeCoverage_Report_HTML; $writer->process($coverage, '/tmp/code-coverage-report'); ``` - diff --git a/build/phpunit.xml b/build/phpunit.xml new file mode 100644 index 000000000..fa15d5d4c --- /dev/null +++ b/build/phpunit.xml @@ -0,0 +1,16 @@ + + + + ../tests/tests + + + + + ../src + + + diff --git a/build/travis-ci.xml b/build/travis-ci.xml deleted file mode 100644 index 15e879fa6..000000000 --- a/build/travis-ci.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - ../tests/PHP - - - - - - - - - - ../src - - - diff --git a/composer.json b/composer.json index 77d41ce79..0590c64fd 100644 --- a/composer.json +++ b/composer.json @@ -20,21 +20,24 @@ "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "irc": "irc://irc.freenode.net/phpunit" }, + "minimum-stability": "dev", + "prefer-stable": true, "require": { - "php": ">=5.3.3", + "php": "^5.6 || ^7.0", "phpunit/php-file-iterator": "~1.3", - "phpunit/php-token-stream": "~1.3", + "phpunit/php-token-stream": "^1.4.2", "phpunit/php-text-template": "~1.2", - "sebastian/environment": "~1.0", - "sebastian/version": "~1.0" + "sebastian/code-unit-reverse-lookup": "~1.0", + "sebastian/environment": "^1.3.2", + "sebastian/version": "~1.0|~2.0" }, "require-dev": { - "phpunit/phpunit": "~4", + "phpunit/phpunit": "^5.4", "ext-xdebug": ">=2.1.4" }, "suggest": { "ext-dom": "*", - "ext-xdebug": ">=2.2.1", + "ext-xdebug": ">=2.4.0", "ext-xmlwriter": "*" }, "autoload": { @@ -44,7 +47,7 @@ }, "extra": { "branch-alias": { - "dev-master": "2.2.x-dev" + "dev-master": "4.0.x-dev" } } } diff --git a/phpunit.xml.dist b/phpunit.xml.dist deleted file mode 100644 index f5fa606e2..000000000 --- a/phpunit.xml.dist +++ /dev/null @@ -1,23 +0,0 @@ - - - - - tests/PHP - - - - - - - - - - - - src - - - - diff --git a/scripts/auto_append.php b/scripts/auto_append.php deleted file mode 100644 index 6cd768d31..000000000 --- a/scripts/auto_append.php +++ /dev/null @@ -1,5 +0,0 @@ -stop(); - -$writer = new PHP_CodeCoverage_Report_HTML; -$writer->process($coverage, '/tmp/coverage'); diff --git a/scripts/auto_prepend.php b/scripts/auto_prepend.php deleted file mode 100644 index 7a8887a5b..000000000 --- a/scripts/auto_prepend.php +++ /dev/null @@ -1,10 +0,0 @@ -filter(); - -$filter->addFileToBlacklist(__FILE__); -$filter->addFileToBlacklist(dirname(__FILE__) . '/auto_append.php'); - -$coverage->start($_SERVER['SCRIPT_FILENAME']); diff --git a/src/CodeCoverage.php b/src/CodeCoverage.php index a77333c93..4550e468d 100644 --- a/src/CodeCoverage.php +++ b/src/CodeCoverage.php @@ -1,6 +1,6 @@ * @@ -8,25 +8,37 @@ * file that was distributed with this source code. */ +namespace SebastianBergmann\CodeCoverage; + +use SebastianBergmann\CodeCoverage\Driver\Driver; +use SebastianBergmann\CodeCoverage\Driver\Xdebug; +use SebastianBergmann\CodeCoverage\Driver\HHVM; +use SebastianBergmann\CodeCoverage\Driver\PHPDBG; +use SebastianBergmann\CodeCoverage\Node\Builder; +use SebastianBergmann\CodeCoverage\Node\Directory; +use SebastianBergmann\CodeUnitReverseLookup\Wizard; use SebastianBergmann\Environment\Runtime; /** * Provides collection functionality for PHP code coverage information. - * - * @since Class available since Release 1.0.0 */ -class PHP_CodeCoverage +class CodeCoverage { /** - * @var PHP_CodeCoverage_Driver + * @var Driver */ private $driver; /** - * @var PHP_CodeCoverage_Filter + * @var Filter */ private $filter; + /** + * @var Wizard + */ + private $wizard; + /** * @var bool */ @@ -45,7 +57,12 @@ class PHP_CodeCoverage /** * @var bool */ - private $mapTestClassNameToCoveredClassName = false; + private $checkForUnexecutedCoveredCode = false; + + /** + * @var bool + */ + private $checkForMissingCoversAnnotation = false; /** * @var bool @@ -57,6 +74,11 @@ class PHP_CodeCoverage */ private $processUncoveredFilesFromWhitelist = false; + /** + * @var bool + */ + private $ignoreDeprecatedCode = false; + /** * @var mixed */ @@ -67,12 +89,12 @@ class PHP_CodeCoverage * * @var array */ - private $data = array(); + private $data = []; /** * @var array */ - private $ignoredLines = array(); + private $ignoredLines = []; /** * @var bool @@ -84,47 +106,47 @@ class PHP_CodeCoverage * * @var array */ - private $tests = array(); + private $tests = []; + + /** + * @var string[] + */ + private $unintentionallyCoveredSubclassesWhitelist = []; /** * Constructor. * - * @param PHP_CodeCoverage_Driver $driver - * @param PHP_CodeCoverage_Filter $filter - * @throws PHP_CodeCoverage_Exception + * @param Driver $driver + * @param Filter $filter + * + * @throws RuntimeException */ - public function __construct(PHP_CodeCoverage_Driver $driver = null, PHP_CodeCoverage_Filter $filter = null) + public function __construct(Driver $driver = null, Filter $filter = null) { if ($driver === null) { - $runtime = new Runtime; - - if (!$runtime->hasXdebug()) { - throw new PHP_CodeCoverage_Exception('No code coverage driver available'); - } - - $driver = new PHP_CodeCoverage_Driver_Xdebug; + $driver = $this->selectDriver(); } if ($filter === null) { - $filter = new PHP_CodeCoverage_Filter; + $filter = new Filter; } $this->driver = $driver; $this->filter = $filter; + + $this->wizard = new Wizard; } /** - * Returns the PHP_CodeCoverage_Report_Node_* object graph - * for this PHP_CodeCoverage object. + * Returns the code coverage information as a graph of node objects. * - * @return PHP_CodeCoverage_Report_Node_Directory - * @since Method available since Release 1.1.0 + * @return Directory */ public function getReport() { - $factory = new PHP_CodeCoverage_Report_Factory; + $builder = new Builder; - return $factory->create($this); + return $builder->build($this); } /** @@ -133,14 +155,14 @@ public function getReport() public function clear() { $this->currentId = null; - $this->data = array(); - $this->tests = array(); + $this->data = []; + $this->tests = []; } /** - * Returns the PHP_CodeCoverage_Filter used. + * Returns the filter object used. * - * @return PHP_CodeCoverage_Filter + * @return Filter */ public function filter() { @@ -151,9 +173,9 @@ public function filter() * Returns the collected code coverage data. * Set $raw = true to bypass all filters. * - * @param bool $raw + * @param bool $raw + * * @return array - * @since Method available since Release 1.1.0 */ public function getData($raw = false) { @@ -161,12 +183,6 @@ public function getData($raw = false) $this->addUncoveredFilesFromWhitelist(); } - // We need to apply the blacklist filter a second time - // when no whitelist is used. - if (!$raw && !$this->filter->hasWhitelist()) { - $this->applyListsFilter($this->data); - } - return $this->data; } @@ -174,7 +190,6 @@ public function getData($raw = false) * Sets the coverage data. * * @param array $data - * @since Method available since Release 2.0.0 */ public function setData(array $data) { @@ -185,7 +200,6 @@ public function setData(array $data) * Returns the test data. * * @return array - * @since Method available since Release 1.1.0 */ public function getTests() { @@ -196,7 +210,6 @@ public function getTests() * Sets the test data. * * @param array $tests - * @since Method available since Release 2.0.0 */ public function setTests(array $tests) { @@ -206,14 +219,15 @@ public function setTests(array $tests) /** * Start collection of code coverage information. * - * @param mixed $id - * @param bool $clear - * @throws PHP_CodeCoverage_Exception + * @param mixed $id + * @param bool $clear + * + * @throws InvalidArgumentException */ public function start($id, $clear = false) { if (!is_bool($clear)) { - throw PHP_CodeCoverage_Util_InvalidArgumentHelper::factory( + throw InvalidArgumentException::create( 1, 'boolean' ); @@ -231,23 +245,25 @@ public function start($id, $clear = false) /** * Stop collection of code coverage information. * - * @param bool $append - * @param mixed $linesToBeCovered - * @param array $linesToBeUsed + * @param bool $append + * @param mixed $linesToBeCovered + * @param array $linesToBeUsed + * * @return array - * @throws PHP_CodeCoverage_Exception + * + * @throws InvalidArgumentException */ - public function stop($append = true, $linesToBeCovered = array(), array $linesToBeUsed = array()) + public function stop($append = true, $linesToBeCovered = [], array $linesToBeUsed = []) { if (!is_bool($append)) { - throw PHP_CodeCoverage_Util_InvalidArgumentHelper::factory( + throw InvalidArgumentException::create( 1, 'boolean' ); } if (!is_array($linesToBeCovered) && $linesToBeCovered !== false) { - throw PHP_CodeCoverage_Util_InvalidArgumentHelper::factory( + throw InvalidArgumentException::create( 2, 'array or false' ); @@ -264,21 +280,22 @@ public function stop($append = true, $linesToBeCovered = array(), array $linesTo /** * Appends code coverage data. * - * @param array $data - * @param mixed $id - * @param bool $append - * @param mixed $linesToBeCovered - * @param array $linesToBeUsed - * @throws PHP_CodeCoverage_Exception + * @param array $data + * @param mixed $id + * @param bool $append + * @param mixed $linesToBeCovered + * @param array $linesToBeUsed + * + * @throws RuntimeException */ - public function append(array $data, $id = null, $append = true, $linesToBeCovered = array(), array $linesToBeUsed = array()) + public function append(array $data, $id = null, $append = true, $linesToBeCovered = [], array $linesToBeUsed = []) { if ($id === null) { $id = $this->currentId; } if ($id === null) { - throw new PHP_CodeCoverage_Exception; + throw new RuntimeException; } $this->applyListsFilter($data); @@ -304,25 +321,25 @@ public function append(array $data, $id = null, $append = true, $linesToBeCovere $size = 'unknown'; $status = null; - if ($id instanceof PHPUnit_Framework_TestCase) { + if ($id instanceof \PHPUnit_Framework_TestCase) { $_size = $id->getSize(); - if ($_size == PHPUnit_Util_Test::SMALL) { + if ($_size == \PHPUnit_Util_Test::SMALL) { $size = 'small'; - } elseif ($_size == PHPUnit_Util_Test::MEDIUM) { + } elseif ($_size == \PHPUnit_Util_Test::MEDIUM) { $size = 'medium'; - } elseif ($_size == PHPUnit_Util_Test::LARGE) { + } elseif ($_size == \PHPUnit_Util_Test::LARGE) { $size = 'large'; } $status = $id->getStatus(); $id = get_class($id) . '::' . $id->getName(); - } elseif ($id instanceof PHPUnit_Extensions_PhptTestCase) { + } elseif ($id instanceof \PHPUnit_Extensions_PhptTestCase) { $size = 'large'; $id = $id->getName(); } - $this->tests[$id] = array('size' => $size, 'status' => $status); + $this->tests[$id] = ['size' => $size, 'status' => $status]; foreach ($data as $file => $lines) { if (!$this->filter->isFile($file)) { @@ -330,7 +347,7 @@ public function append(array $data, $id = null, $append = true, $linesToBeCovere } foreach ($lines as $k => $v) { - if ($v == 1) { + if ($v == Driver::LINE_EXECUTED) { if (empty($this->data[$file][$k]) || !in_array($id, $this->data[$file][$k])) { $this->data[$file][$k][] = $id; } @@ -340,12 +357,16 @@ public function append(array $data, $id = null, $append = true, $linesToBeCovere } /** - * Merges the data from another instance of PHP_CodeCoverage. + * Merges the data from another instance. * - * @param PHP_CodeCoverage $that + * @param CodeCoverage $that */ - public function merge(PHP_CodeCoverage $that) + public function merge(CodeCoverage $that) { + $this->filter->setWhitelistedFiles( + array_merge($this->filter->getWhitelistedFiles(), $that->filter()->getWhitelistedFiles()) + ); + foreach ($that->data as $file => $lines) { if (!isset($this->data[$file])) { if (!$this->filter->isFiltered($file)) { @@ -369,25 +390,17 @@ public function merge(PHP_CodeCoverage $that) } $this->tests = array_merge($this->tests, $that->getTests()); - - $this->filter->setBlacklistedFiles( - array_merge($this->filter->getBlacklistedFiles(), $that->filter()->getBlacklistedFiles()) - ); - - $this->filter->setWhitelistedFiles( - array_merge($this->filter->getWhitelistedFiles(), $that->filter()->getWhitelistedFiles()) - ); } /** - * @param bool $flag - * @throws PHP_CodeCoverage_Exception - * @since Method available since Release 1.1.0 + * @param bool $flag + * + * @throws InvalidArgumentException */ public function setCacheTokens($flag) { if (!is_bool($flag)) { - throw PHP_CodeCoverage_Util_InvalidArgumentHelper::factory( + throw InvalidArgumentException::create( 1, 'boolean' ); @@ -397,7 +410,7 @@ public function setCacheTokens($flag) } /** - * @since Method available since Release 1.1.0 + * @return bool */ public function getCacheTokens() { @@ -405,14 +418,14 @@ public function getCacheTokens() } /** - * @param bool $flag - * @throws PHP_CodeCoverage_Exception - * @since Method available since Release 2.0.0 + * @param bool $flag + * + * @throws InvalidArgumentException */ public function setCheckForUnintentionallyCoveredCode($flag) { if (!is_bool($flag)) { - throw PHP_CodeCoverage_Util_InvalidArgumentHelper::factory( + throw InvalidArgumentException::create( 1, 'boolean' ); @@ -422,13 +435,14 @@ public function setCheckForUnintentionallyCoveredCode($flag) } /** - * @param bool $flag - * @throws PHP_CodeCoverage_Exception + * @param bool $flag + * + * @throws InvalidArgumentException */ public function setForceCoversAnnotation($flag) { if (!is_bool($flag)) { - throw PHP_CodeCoverage_Util_InvalidArgumentHelper::factory( + throw InvalidArgumentException::create( 1, 'boolean' ); @@ -438,29 +452,59 @@ public function setForceCoversAnnotation($flag) } /** - * @param bool $flag - * @throws PHP_CodeCoverage_Exception + * @param bool $flag + * + * @throws InvalidArgumentException */ - public function setMapTestClassNameToCoveredClassName($flag) + public function setCheckForMissingCoversAnnotation($flag) { if (!is_bool($flag)) { - throw PHP_CodeCoverage_Util_InvalidArgumentHelper::factory( + throw InvalidArgumentException::create( 1, 'boolean' ); } - $this->mapTestClassNameToCoveredClassName = $flag; + $this->checkForMissingCoversAnnotation = $flag; + } + + /** + * @param bool $flag + * + * @throws InvalidArgumentException + */ + public function setCheckForUnexecutedCoveredCode($flag) + { + if (!is_bool($flag)) { + throw InvalidArgumentException::create( + 1, + 'boolean' + ); + } + + $this->checkForUnexecutedCoveredCode = $flag; + } + + /** + * @deprecated + * + * @param bool $flag + * + * @throws InvalidArgumentException + */ + public function setMapTestClassNameToCoveredClassName($flag) + { } /** - * @param bool $flag - * @throws PHP_CodeCoverage_Exception + * @param bool $flag + * + * @throws InvalidArgumentException */ public function setAddUncoveredFilesFromWhitelist($flag) { if (!is_bool($flag)) { - throw PHP_CodeCoverage_Util_InvalidArgumentHelper::factory( + throw InvalidArgumentException::create( 1, 'boolean' ); @@ -470,13 +514,14 @@ public function setAddUncoveredFilesFromWhitelist($flag) } /** - * @param bool $flag - * @throws PHP_CodeCoverage_Exception + * @param bool $flag + * + * @throws InvalidArgumentException */ public function setProcessUncoveredFilesFromWhitelist($flag) { if (!is_bool($flag)) { - throw PHP_CodeCoverage_Util_InvalidArgumentHelper::factory( + throw InvalidArgumentException::create( 1, 'boolean' ); @@ -486,13 +531,14 @@ public function setProcessUncoveredFilesFromWhitelist($flag) } /** - * @param bool $flag - * @throws PHP_CodeCoverage_Exception + * @param bool $flag + * + * @throws InvalidArgumentException */ public function setDisableIgnoredLines($flag) { if (!is_bool($flag)) { - throw PHP_CodeCoverage_Util_InvalidArgumentHelper::factory( + throw InvalidArgumentException::create( 1, 'boolean' ); @@ -501,19 +547,50 @@ public function setDisableIgnoredLines($flag) $this->disableIgnoredLines = $flag; } + /** + * @param bool $flag + * + * @throws InvalidArgumentException + */ + public function setIgnoreDeprecatedCode($flag) + { + if (!is_bool($flag)) { + throw InvalidArgumentException::create( + 1, + 'boolean' + ); + } + + $this->ignoreDeprecatedCode = $flag; + } + + /** + * @param array $whitelist + */ + public function setUnintentionallyCoveredSubclassesWhitelist(array $whitelist) + { + $this->unintentionallyCoveredSubclassesWhitelist = $whitelist; + } + /** * Applies the @covers annotation filtering. * - * @param array $data - * @param mixed $linesToBeCovered - * @param array $linesToBeUsed - * @throws PHP_CodeCoverage_Exception_UnintentionallyCoveredCode + * @param array $data + * @param mixed $linesToBeCovered + * @param array $linesToBeUsed + * + * @throws MissingCoversAnnotationException + * @throws UnintentionallyCoveredCodeException */ private function applyCoversAnnotationFilter(array &$data, $linesToBeCovered, array $linesToBeUsed) { if ($linesToBeCovered === false || ($this->forceCoversAnnotation && empty($linesToBeCovered))) { - $data = array(); + if ($this->checkForMissingCoversAnnotation) { + throw new MissingCoversAnnotationException; + } + + $data = []; return; } @@ -530,6 +607,10 @@ private function applyCoversAnnotationFilter(array &$data, $linesToBeCovered, ar ); } + if ($this->checkForUnexecutedCoveredCode) { + $this->performUnexecutedCoveredCodeCheck($data, $linesToBeCovered, $linesToBeUsed); + } + $data = array_intersect_key($data, $linesToBeCovered); foreach (array_keys($data) as $filename) { @@ -543,7 +624,7 @@ private function applyCoversAnnotationFilter(array &$data, $linesToBeCovered, ar } /** - * Applies the blacklist/whitelist filtering. + * Applies the whitelist filtering. * * @param array $data */ @@ -576,16 +657,15 @@ private function applyIgnoredLinesFilter(array &$data) /** * @param array $data - * @since Method available since Release 1.1.0 */ private function initializeFilesThatAreSeenTheFirstTime(array $data) { foreach ($data as $file => $lines) { if ($this->filter->isFile($file) && !isset($this->data[$file])) { - $this->data[$file] = array(); + $this->data[$file] = []; foreach ($lines as $k => $v) { - $this->data[$file][$k] = $v == -2 ? null : array(); + $this->data[$file][$k] = $v == -2 ? null : []; } } } @@ -596,7 +676,7 @@ private function initializeFilesThatAreSeenTheFirstTime(array $data) */ private function addUncoveredFilesFromWhitelist() { - $data = array(); + $data = []; $uncoveredFiles = array_diff( $this->filter->getWhitelist(), array_keys($this->data) @@ -614,12 +694,12 @@ private function addUncoveredFilesFromWhitelist() $uncoveredFiles ); } else { - $data[$uncoveredFile] = array(); + $data[$uncoveredFile] = []; $lines = count(file($uncoveredFile)); for ($i = 1; $i <= $lines; $i++) { - $data[$uncoveredFile][$i] = -1; + $data[$uncoveredFile][$i] = Driver::LINE_NOT_EXECUTED; } } } @@ -642,8 +722,8 @@ private function processUncoveredFileFromWhitelist($uncoveredFile, array &$data, if (!isset($data[$file]) && in_array($file, $uncoveredFiles)) { foreach (array_keys($fileCoverage) as $key) { - if ($fileCoverage[$key] == 1) { - $fileCoverage[$key] = -1; + if ($fileCoverage[$key] == Driver::LINE_EXECUTED) { + $fileCoverage[$key] = Driver::LINE_NOT_EXECUTED; } } @@ -655,22 +735,23 @@ private function processUncoveredFileFromWhitelist($uncoveredFile, array &$data, /** * Returns the lines of a source file that should be ignored. * - * @param string $filename + * @param string $filename + * * @return array - * @throws PHP_CodeCoverage_Exception - * @since Method available since Release 2.0.0 + * + * @throws InvalidArgumentException */ private function getLinesToBeIgnored($filename) { if (!is_string($filename)) { - throw PHP_CodeCoverage_Util_InvalidArgumentHelper::factory( + throw InvalidArgumentException::create( 1, 'string' ); } if (!isset($this->ignoredLines[$filename])) { - $this->ignoredLines[$filename] = array(); + $this->ignoredLines[$filename] = []; if ($this->disableIgnoredLines) { return $this->ignoredLines[$filename]; @@ -688,9 +769,9 @@ private function getLinesToBeIgnored($filename) } if ($this->cacheTokens) { - $tokens = PHP_Token_Stream_CachingFactory::get($filename); + $tokens = \PHP_Token_Stream_CachingFactory::get($filename); } else { - $tokens = new PHP_Token_Stream($filename); + $tokens = new \PHP_Token_Stream($filename); } $classes = array_merge($tokens->getClasses(), $tokens->getTraits()); @@ -741,19 +822,21 @@ private function getLinesToBeIgnored($filename) case 'PHP_Token_TRAIT': case 'PHP_Token_CLASS': case 'PHP_Token_FUNCTION': + /* @var \PHP_Token_Interface $token */ + $docblock = $token->getDocblock(); $this->ignoredLines[$filename][] = $token->getLine(); - if (strpos($docblock, '@codeCoverageIgnore') || strpos($docblock, '@deprecated')) { + if (strpos($docblock, '@codeCoverageIgnore') || ($this->ignoreDeprecatedCode && strpos($docblock, '@deprecated'))) { $endLine = $token->getEndLine(); for ($i = $token->getLine(); $i <= $endLine; $i++) { $this->ignoredLines[$filename][] = $i; } - } elseif ($token instanceof PHP_Token_INTERFACE || - $token instanceof PHP_Token_TRAIT || - $token instanceof PHP_Token_CLASS) { + } elseif ($token instanceof \PHP_Token_INTERFACE || + $token instanceof \PHP_Token_TRAIT || + $token instanceof \PHP_Token_CLASS) { if (empty($classes[$token->getName()]['methods'])) { for ($i = $token->getLine(); $i <= $token->getEndLine(); @@ -795,6 +878,7 @@ private function getLinesToBeIgnored($filename) $this->ignoredLines[$filename][] = $token->getEndLine(); // Intentional fallthrough + case 'PHP_Token_DECLARE': case 'PHP_Token_OPEN_TAG': case 'PHP_Token_CLOSE_TAG': case 'PHP_Token_USE': @@ -825,11 +909,11 @@ private function getLinesToBeIgnored($filename) } /** - * @param array $data - * @param array $linesToBeCovered - * @param array $linesToBeUsed - * @throws PHP_CodeCoverage_Exception_UnintentionallyCoveredCode - * @since Method available since Release 2.0.0 + * @param array $data + * @param array $linesToBeCovered + * @param array $linesToBeUsed + * + * @throws UnintentionallyCoveredCodeException */ private function performUnintentionallyCoveredCodeCheck(array &$data, array $linesToBeCovered, array $linesToBeUsed) { @@ -838,42 +922,79 @@ private function performUnintentionallyCoveredCodeCheck(array &$data, array $lin $linesToBeUsed ); - $message = ''; + $unintentionallyCoveredUnits = []; foreach ($data as $file => $_data) { foreach ($_data as $line => $flag) { - if ($flag == 1 && - (!isset($allowedLines[$file]) || - !isset($allowedLines[$file][$line]))) { - $message .= sprintf( - '- %s:%d' . PHP_EOL, - $file, - $line - ); + if ($flag == 1 && !isset($allowedLines[$file][$line])) { + $unintentionallyCoveredUnits[] = $this->wizard->lookup($file, $line); } } } - if (!empty($message)) { - throw new PHP_CodeCoverage_Exception_UnintentionallyCoveredCode( - $message + $unintentionallyCoveredUnits = $this->processUnintentionallyCoveredUnits($unintentionallyCoveredUnits); + + if (!empty($unintentionallyCoveredUnits)) { + throw new UnintentionallyCoveredCodeException( + $unintentionallyCoveredUnits ); } } /** - * @param array $linesToBeCovered - * @param array $linesToBeUsed + * @param array $data + * @param array $linesToBeCovered + * @param array $linesToBeUsed + * + * @throws CoveredCodeNotExecutedException + */ + private function performUnexecutedCoveredCodeCheck(array &$data, array $linesToBeCovered, array $linesToBeUsed) + { + $expectedLines = $this->getAllowedLines( + $linesToBeCovered, + $linesToBeUsed + ); + + foreach ($data as $file => $_data) { + foreach (array_keys($_data) as $line) { + if (!isset($expectedLines[$file][$line])) { + continue; + } + + unset($expectedLines[$file][$line]); + } + } + + $message = ''; + + foreach ($expectedLines as $file => $lines) { + if (empty($lines)) { + continue; + } + + foreach (array_keys($lines) as $line) { + $message .= sprintf('- %s:%d' . PHP_EOL, $file, $line); + } + } + + if (!empty($message)) { + throw new CoveredCodeNotExecutedException($message); + } + } + + /** + * @param array $linesToBeCovered + * @param array $linesToBeUsed + * * @return array - * @since Method available since Release 2.0.0 */ private function getAllowedLines(array $linesToBeCovered, array $linesToBeUsed) { - $allowedLines = array(); + $allowedLines = []; foreach (array_keys($linesToBeCovered) as $file) { if (!isset($allowedLines[$file])) { - $allowedLines[$file] = array(); + $allowedLines[$file] = []; } $allowedLines[$file] = array_merge( @@ -884,7 +1005,7 @@ private function getAllowedLines(array $linesToBeCovered, array $linesToBeUsed) foreach (array_keys($linesToBeUsed) as $file) { if (!isset($allowedLines[$file])) { - $allowedLines[$file] = array(); + $allowedLines[$file] = []; } $allowedLines[$file] = array_merge( @@ -901,4 +1022,56 @@ private function getAllowedLines(array $linesToBeCovered, array $linesToBeUsed) return $allowedLines; } + + /** + * @return Driver + * + * @throws RuntimeException + */ + private function selectDriver() + { + $runtime = new Runtime; + + if (!$runtime->canCollectCodeCoverage()) { + throw new RuntimeException('No code coverage driver available'); + } + + if ($runtime->isHHVM()) { + return new HHVM; + } elseif ($runtime->isPHPDBG()) { + return new PHPDBG; + } else { + return new Xdebug; + } + } + + /** + * @param array $unintentionallyCoveredUnits + * + * @return array + */ + private function processUnintentionallyCoveredUnits(array $unintentionallyCoveredUnits) + { + $unintentionallyCoveredUnits = array_unique($unintentionallyCoveredUnits); + sort($unintentionallyCoveredUnits); + + foreach (array_keys($unintentionallyCoveredUnits) as $k => $v) { + $unit = explode('::', $unintentionallyCoveredUnits[$k]); + + if (count($unit) != 2) { + continue; + } + + $class = new \ReflectionClass($unit[0]); + + foreach ($this->unintentionallyCoveredSubclassesWhitelist as $whitelisted) { + if ($class->isSubclassOf($whitelisted)) { + unset($unintentionallyCoveredUnits[$k]); + break; + } + } + } + + return array_values($unintentionallyCoveredUnits); + } } diff --git a/src/CodeCoverage/Driver.php b/src/CodeCoverage/Driver.php deleted file mode 100644 index 0c5f6d5ac..000000000 --- a/src/CodeCoverage/Driver.php +++ /dev/null @@ -1,29 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/** - * Interface for code coverage drivers. - * - * @since Class available since Release 1.0.0 - */ -interface PHP_CodeCoverage_Driver -{ - /** - * Start collection of code coverage information. - */ - public function start(); - - /** - * Stop collection of code coverage information. - * - * @return array - */ - public function stop(); -} diff --git a/src/CodeCoverage/Exception.php b/src/CodeCoverage/Exception.php deleted file mode 100644 index bded3c095..000000000 --- a/src/CodeCoverage/Exception.php +++ /dev/null @@ -1,18 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/** - * Exception class for PHP_CodeCoverage component. - * - * @since Class available since Release 1.1.0 - */ -class PHP_CodeCoverage_Exception extends RuntimeException -{ -} diff --git a/src/CodeCoverage/Exception/UnintentionallyCoveredCode.php b/src/CodeCoverage/Exception/UnintentionallyCoveredCode.php deleted file mode 100644 index 463785ef1..000000000 --- a/src/CodeCoverage/Exception/UnintentionallyCoveredCode.php +++ /dev/null @@ -1,18 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/** - * Exception that is raised when code is unintentionally covered. - * - * @since Class available since Release 2.0.0 - */ -class PHP_CodeCoverage_Exception_UnintentionallyCoveredCode extends PHP_CodeCoverage_Exception -{ -} diff --git a/src/CodeCoverage/Report/HTML/Renderer/Directory.php b/src/CodeCoverage/Report/HTML/Renderer/Directory.php deleted file mode 100644 index 4415c520d..000000000 --- a/src/CodeCoverage/Report/HTML/Renderer/Directory.php +++ /dev/null @@ -1,97 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/** - * Renders a PHP_CodeCoverage_Report_Node_Directory node. - * - * @since Class available since Release 1.1.0 - */ -class PHP_CodeCoverage_Report_HTML_Renderer_Directory extends PHP_CodeCoverage_Report_HTML_Renderer -{ - /** - * @param PHP_CodeCoverage_Report_Node_Directory $node - * @param string $file - */ - public function render(PHP_CodeCoverage_Report_Node_Directory $node, $file) - { - $template = new Text_Template($this->templatePath . 'directory.html', '{{', '}}'); - - $this->setCommonTemplateVariables($template, $node); - - $items = $this->renderItem($node, true); - - foreach ($node->getDirectories() as $item) { - $items .= $this->renderItem($item); - } - - foreach ($node->getFiles() as $item) { - $items .= $this->renderItem($item); - } - - $template->setVar( - array( - 'id' => $node->getId(), - 'items' => $items - ) - ); - - $template->renderTo($file); - } - - /** - * @param PHP_CodeCoverage_Report_Node $item - * @param bool $total - * @return string - */ - protected function renderItem(PHP_CodeCoverage_Report_Node $item, $total = false) - { - $data = array( - 'numClasses' => $item->getNumClassesAndTraits(), - 'numTestedClasses' => $item->getNumTestedClassesAndTraits(), - 'numMethods' => $item->getNumMethods(), - 'numTestedMethods' => $item->getNumTestedMethods(), - 'linesExecutedPercent' => $item->getLineExecutedPercent(false), - 'linesExecutedPercentAsString' => $item->getLineExecutedPercent(), - 'numExecutedLines' => $item->getNumExecutedLines(), - 'numExecutableLines' => $item->getNumExecutableLines(), - 'testedMethodsPercent' => $item->getTestedMethodsPercent(false), - 'testedMethodsPercentAsString' => $item->getTestedMethodsPercent(), - 'testedClassesPercent' => $item->getTestedClassesAndTraitsPercent(false), - 'testedClassesPercentAsString' => $item->getTestedClassesAndTraitsPercent() - ); - - if ($total) { - $data['name'] = 'Total'; - } else { - if ($item instanceof PHP_CodeCoverage_Report_Node_Directory) { - $data['name'] = sprintf( - '%s', - $item->getName(), - $item->getName() - ); - - $data['icon'] = ' '; - } else { - $data['name'] = sprintf( - '%s', - $item->getName(), - $item->getName() - ); - - $data['icon'] = ' '; - } - } - - return $this->renderItemTemplate( - new Text_Template($this->templatePath . 'directory_item.html', '{{', '}}'), - $data - ); - } -} diff --git a/src/CodeCoverage/Report/HTML/Renderer/Template/css/bootstrap.min.css b/src/CodeCoverage/Report/HTML/Renderer/Template/css/bootstrap.min.css deleted file mode 100644 index cd1c616ad..000000000 --- a/src/CodeCoverage/Report/HTML/Renderer/Template/css/bootstrap.min.css +++ /dev/null @@ -1,5 +0,0 @@ -/*! - * Bootstrap v3.3.4 (http://getbootstrap.com) - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - *//*! normalize.css v3.0.2 | MIT License | git.io/normalize */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}select{background:#fff!important}.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:"\2a"}.glyphicon-plus:before{content:"\2b"}.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:thin dotted;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:hover{color:#286090}.text-success{color:#3c763d}a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}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:thin dotted;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[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],input[type=time],input[type=datetime-local],input[type=month]{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}select.form-group-sm .form-control{height:30px;line-height:30px}select[multiple].form-group-sm .form-control,textarea.form-group-sm .form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:5px 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}select.form-group-lg .form-control{height:46px;line-height:46px}select[multiple].form-group-lg .form-control,textarea.form-group-lg .form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:10px 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}.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.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:14.33px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px}}.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:thin dotted;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{pointer-events:none;cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.active,.btn-default.focus,.btn-default:active,.btn-default:focus,.btn-default:hover,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,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.active,.btn-primary.focus,.btn-primary:active,.btn-primary:focus,.btn-primary:hover,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,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.active,.btn-success.focus,.btn-success:active,.btn-success:focus,.btn-success:hover,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,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.active,.btn-info.focus,.btn-info:active,.btn-info:focus,.btn-info:hover,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,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.active,.btn-warning.focus,.btn-warning:active,.btn-warning:focus,.btn-warning:hover,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,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.active,.btn-danger.focus,.btn-danger:active,.btn-danger:focus,.btn-danger:hover,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,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-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 solid}.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-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-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-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-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{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{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:2;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}.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}.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:baseline;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:30px 15px;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{border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding:48px 0}.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-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{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}.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{color:#3c763d}a.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.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{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.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{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.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{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.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{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-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{min-height:16.43px;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-weight:400;line-height:1.4;filter:alpha(opacity=0);opacity:0}.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;text-decoration:none;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-weight:400;line-height:1.42857143;text-align:left;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)}.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:1000;perspective:1000}.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);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}.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;margin-top:-10px;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:-15px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-15px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-15px}.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,.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,.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}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}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}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}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}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}} \ No newline at end of file diff --git a/src/Driver/Driver.php b/src/Driver/Driver.php new file mode 100644 index 000000000..8d9ef5357 --- /dev/null +++ b/src/Driver/Driver.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SebastianBergmann\CodeCoverage\Driver; + +/** + * Interface for code coverage drivers. + */ +interface Driver +{ + /** + * @var int + * + * @see http://xdebug.org/docs/code_coverage + */ + const LINE_EXECUTED = 1; + + /** + * @var int + * + * @see http://xdebug.org/docs/code_coverage + */ + const LINE_NOT_EXECUTED = -1; + + /** + * @var int + * + * @see http://xdebug.org/docs/code_coverage + */ + const LINE_NOT_EXECUTABLE = -2; + + /** + * Start collection of code coverage information. + */ + public function start(); + + /** + * Stop collection of code coverage information. + * + * @return array + */ + public function stop(); +} diff --git a/src/Driver/HHVM.php b/src/Driver/HHVM.php new file mode 100644 index 000000000..76758cb6e --- /dev/null +++ b/src/Driver/HHVM.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SebastianBergmann\CodeCoverage\Driver; + +/** + * Driver for HHVM's code coverage functionality. + * + * @codeCoverageIgnore + */ +class HHVM extends Xdebug +{ + /** + * Start collection of code coverage information. + */ + public function start() + { + xdebug_start_code_coverage(); + } +} diff --git a/src/Driver/PHPDBG.php b/src/Driver/PHPDBG.php new file mode 100644 index 000000000..6e1cdd943 --- /dev/null +++ b/src/Driver/PHPDBG.php @@ -0,0 +1,109 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SebastianBergmann\CodeCoverage\Driver; + +use SebastianBergmann\CodeCoverage\RuntimeException; + +/** + * Driver for PHPDBG's code coverage functionality. + * + * @codeCoverageIgnore + */ +class PHPDBG implements Driver +{ + /** + * Constructor. + */ + public function __construct() + { + if (PHP_SAPI !== 'phpdbg') { + throw new RuntimeException( + 'This driver requires the PHPDBG SAPI' + ); + } + + if (!function_exists('phpdbg_start_oplog')) { + throw new RuntimeException( + 'This build of PHPDBG does not support code coverage' + ); + } + } + + /** + * Start collection of code coverage information. + */ + public function start() + { + phpdbg_start_oplog(); + } + + /** + * Stop collection of code coverage information. + * + * @return array + */ + public function stop() + { + static $fetchedLines = []; + + $dbgData = phpdbg_end_oplog(); + + if ($fetchedLines == []) { + $sourceLines = phpdbg_get_executable(); + } else { + $newFiles = array_diff( + get_included_files(), + array_keys($fetchedLines) + ); + + if ($newFiles) { + $sourceLines = phpdbg_get_executable( + ['files' => $newFiles] + ); + } else { + $sourceLines = []; + } + } + + foreach ($sourceLines as $file => $lines) { + foreach ($lines as $lineNo => $numExecuted) { + $sourceLines[$file][$lineNo] = self::LINE_NOT_EXECUTED; + } + } + + $fetchedLines = array_merge($fetchedLines, $sourceLines); + + return $this->detectExecutedLines($fetchedLines, $dbgData); + } + + /** + * Convert phpdbg based data into the format CodeCoverage expects + * + * @param array $sourceLines + * @param array $dbgData + * + * @return array + */ + private function detectExecutedLines(array $sourceLines, array $dbgData) + { + foreach ($dbgData as $file => $coveredLines) { + foreach ($coveredLines as $lineNo => $numExecuted) { + // phpdbg also reports $lineNo=0 when e.g. exceptions get thrown. + // make sure we only mark lines executed which are actually executable. + if (isset($sourceLines[$file][$lineNo])) { + $sourceLines[$file][$lineNo] = self::LINE_EXECUTED; + } + } + } + + return $sourceLines; + } +} diff --git a/src/CodeCoverage/Driver/Xdebug.php b/src/Driver/Xdebug.php similarity index 74% rename from src/CodeCoverage/Driver/Xdebug.php rename to src/Driver/Xdebug.php index 0cd7b9adc..98dab1391 100644 --- a/src/CodeCoverage/Driver/Xdebug.php +++ b/src/Driver/Xdebug.php @@ -1,6 +1,6 @@ * @@ -8,13 +8,16 @@ * file that was distributed with this source code. */ +namespace SebastianBergmann\CodeCoverage\Driver; + +use SebastianBergmann\CodeCoverage\RuntimeException; + /** * Driver for Xdebug's code coverage functionality. * - * @since Class available since Release 1.0.0 * @codeCoverageIgnore */ -class PHP_CodeCoverage_Driver_Xdebug implements PHP_CodeCoverage_Driver +class Xdebug implements Driver { /** * Constructor. @@ -22,12 +25,12 @@ class PHP_CodeCoverage_Driver_Xdebug implements PHP_CodeCoverage_Driver public function __construct() { if (!extension_loaded('xdebug')) { - throw new PHP_CodeCoverage_Exception('This driver requires Xdebug'); + throw new RuntimeException('This driver requires Xdebug'); } - if (version_compare(phpversion('xdebug'), '2.2.0-dev', '>=') && + if (version_compare(phpversion('xdebug'), '2.2.1', '>=') && !ini_get('xdebug.coverage_enable')) { - throw new PHP_CodeCoverage_Exception( + throw new RuntimeException( 'xdebug.coverage_enable=On has to be set in php.ini' ); } @@ -55,9 +58,9 @@ public function stop() } /** - * @param array $data + * @param array $data + * * @return array - * @since Method available since Release 2.0.0 */ private function cleanup(array $data) { @@ -68,7 +71,7 @@ private function cleanup(array $data) $numLines = $this->getNumberOfLinesInFile($file); foreach (array_keys($data[$file]) as $line) { - if (isset($data[$file][$line]) && $line > $numLines) { + if ($line > $numLines) { unset($data[$file][$line]); } } @@ -79,9 +82,9 @@ private function cleanup(array $data) } /** - * @param string $file + * @param string $file + * * @return int - * @since Method available since Release 2.0.0 */ private function getNumberOfLinesInFile($file) { diff --git a/src/Exception/CoveredCodeNotExecutedException.php b/src/Exception/CoveredCodeNotExecutedException.php new file mode 100644 index 000000000..ca28a231b --- /dev/null +++ b/src/Exception/CoveredCodeNotExecutedException.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SebastianBergmann\CodeCoverage; + +/** + * Exception that is raised when covered code is not executed. + */ +class CoveredCodeNotExecutedException extends RuntimeException +{ +} diff --git a/src/CodeCoverage/Report/XML/Directory.php b/src/Exception/Exception.php similarity index 52% rename from src/CodeCoverage/Report/XML/Directory.php rename to src/Exception/Exception.php index 8e292b506..a3ba4c4c6 100644 --- a/src/CodeCoverage/Report/XML/Directory.php +++ b/src/Exception/Exception.php @@ -1,6 +1,6 @@ * @@ -8,9 +8,11 @@ * file that was distributed with this source code. */ +namespace SebastianBergmann\CodeCoverage; + /** - * @since Class available since Release 2.0.0 + * Exception interface for php-code-coverage component. */ -class PHP_CodeCoverage_Report_XML_Directory extends PHP_CodeCoverage_Report_XML_Node +interface Exception { } diff --git a/src/CodeCoverage/Util/InvalidArgumentHelper.php b/src/Exception/InvalidArgumentException.php similarity index 58% rename from src/CodeCoverage/Util/InvalidArgumentHelper.php rename to src/Exception/InvalidArgumentException.php index d66e49928..1733f6cb5 100644 --- a/src/CodeCoverage/Util/InvalidArgumentHelper.php +++ b/src/Exception/InvalidArgumentException.php @@ -1,6 +1,6 @@ * @@ -8,24 +8,22 @@ * file that was distributed with this source code. */ -/** - * Factory for PHP_CodeCoverage_Exception objects that are used to describe - * invalid arguments passed to a function or method. - * - * @since Class available since Release 1.2.0 - */ -class PHP_CodeCoverage_Util_InvalidArgumentHelper +namespace SebastianBergmann\CodeCoverage; + +class InvalidArgumentException extends \InvalidArgumentException implements Exception { /** * @param int $argument * @param string $type * @param mixed $value + * + * @return InvalidArgumentException */ - public static function factory($argument, $type, $value = null) + public static function create($argument, $type, $value = null) { - $stack = debug_backtrace(false); + $stack = debug_backtrace(0); - return new PHP_CodeCoverage_Exception( + return new self( sprintf( 'Argument #%d%sof %s::%s() must be a %s', $argument, diff --git a/src/Exception/MissingCoversAnnotationException.php b/src/Exception/MissingCoversAnnotationException.php new file mode 100644 index 000000000..7bc5cf3e8 --- /dev/null +++ b/src/Exception/MissingCoversAnnotationException.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SebastianBergmann\CodeCoverage; + +/** + * Exception that is raised when @covers must be used but is not. + */ +class MissingCoversAnnotationException extends RuntimeException +{ +} diff --git a/src/Exception/RuntimeException.php b/src/Exception/RuntimeException.php new file mode 100644 index 000000000..c143db7da --- /dev/null +++ b/src/Exception/RuntimeException.php @@ -0,0 +1,15 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SebastianBergmann\CodeCoverage; + +class RuntimeException extends \RuntimeException implements Exception +{ +} diff --git a/src/Exception/UnintentionallyCoveredCodeException.php b/src/Exception/UnintentionallyCoveredCodeException.php new file mode 100644 index 000000000..3ea542b1f --- /dev/null +++ b/src/Exception/UnintentionallyCoveredCodeException.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SebastianBergmann\CodeCoverage; + +/** + * Exception that is raised when code is unintentionally covered. + */ +class UnintentionallyCoveredCodeException extends RuntimeException +{ + /** + * @var array + */ + private $unintentionallyCoveredUnits = []; + + /** + * @param array $unintentionallyCoveredUnits + */ + public function __construct(array $unintentionallyCoveredUnits) + { + $this->unintentionallyCoveredUnits = $unintentionallyCoveredUnits; + + parent::__construct($this->toString()); + } + + /** + * @return array + */ + public function getUnintentionallyCoveredUnits() + { + return $this->unintentionallyCoveredUnits; + } + + /** + * @return string + */ + private function toString() + { + $message = ''; + + foreach ($this->unintentionallyCoveredUnits as $unit) { + $message .= '- ' . $unit . "\n"; + } + + return $message; + } +} diff --git a/src/CodeCoverage/Filter.php b/src/Filter.php similarity index 50% rename from src/CodeCoverage/Filter.php rename to src/Filter.php index fd5b6aa21..771a657ae 100644 --- a/src/CodeCoverage/Filter.php +++ b/src/Filter.php @@ -1,6 +1,6 @@ * @@ -8,96 +8,19 @@ * file that was distributed with this source code. */ +namespace SebastianBergmann\CodeCoverage; + /** - * Filter for blacklisting and whitelisting of code coverage information. - * - * @since Class available since Release 1.0.0 + * Filter for whitelisting of code coverage information. */ -class PHP_CodeCoverage_Filter +class Filter { - /** - * Source files that are blacklisted. - * - * @var array - */ - private $blacklistedFiles = array(); - /** * Source files that are whitelisted. * * @var array */ - private $whitelistedFiles = array(); - - /** - * Adds a directory to the blacklist (recursively). - * - * @param string $directory - * @param string $suffix - * @param string $prefix - */ - public function addDirectoryToBlacklist($directory, $suffix = '.php', $prefix = '') - { - $facade = new File_Iterator_Facade; - $files = $facade->getFilesAsArray($directory, $suffix, $prefix); - - foreach ($files as $file) { - $this->addFileToBlacklist($file); - } - } - - /** - * Adds a file to the blacklist. - * - * @param string $filename - */ - public function addFileToBlacklist($filename) - { - $this->blacklistedFiles[realpath($filename)] = true; - } - - /** - * Adds files to the blacklist. - * - * @param array $files - */ - public function addFilesToBlacklist(array $files) - { - foreach ($files as $file) { - $this->addFileToBlacklist($file); - } - } - - /** - * Removes a directory from the blacklist (recursively). - * - * @param string $directory - * @param string $suffix - * @param string $prefix - */ - public function removeDirectoryFromBlacklist($directory, $suffix = '.php', $prefix = '') - { - $facade = new File_Iterator_Facade; - $files = $facade->getFilesAsArray($directory, $suffix, $prefix); - - foreach ($files as $file) { - $this->removeFileFromBlacklist($file); - } - } - - /** - * Removes a file from the blacklist. - * - * @param string $filename - */ - public function removeFileFromBlacklist($filename) - { - $filename = realpath($filename); - - if (isset($this->blacklistedFiles[$filename])) { - unset($this->blacklistedFiles[$filename]); - } - } + private $whitelistedFiles = []; /** * Adds a directory to the whitelist (recursively). @@ -108,7 +31,7 @@ public function removeFileFromBlacklist($filename) */ public function addDirectoryToWhitelist($directory, $suffix = '.php', $prefix = '') { - $facade = new File_Iterator_Facade; + $facade = new \File_Iterator_Facade; $files = $facade->getFilesAsArray($directory, $suffix, $prefix); foreach ($files as $file) { @@ -147,7 +70,7 @@ public function addFilesToWhitelist(array $files) */ public function removeDirectoryFromWhitelist($directory, $suffix = '.php', $prefix = '') { - $facade = new File_Iterator_Facade; + $facade = new \File_Iterator_Facade; $files = $facade->getFilesAsArray($directory, $suffix, $prefix); foreach ($files as $file) { @@ -164,15 +87,15 @@ public function removeFileFromWhitelist($filename) { $filename = realpath($filename); - if (isset($this->whitelistedFiles[$filename])) { - unset($this->whitelistedFiles[$filename]); - } + unset($this->whitelistedFiles[$filename]); } /** * Checks whether a filename is a real filename. * * @param string $filename + * + * @return bool */ public function isFile($filename) { @@ -193,12 +116,9 @@ public function isFile($filename) /** * Checks whether or not a file is filtered. * - * When the whitelist is empty (default), blacklisting is used. - * When the whitelist is not empty, whitelisting is used. + * @param string $filename * - * @param string $filename * @return bool - * @throws PHP_CodeCoverage_Exception */ public function isFiltered($filename) { @@ -208,21 +128,7 @@ public function isFiltered($filename) $filename = realpath($filename); - if (!empty($this->whitelistedFiles)) { - return !isset($this->whitelistedFiles[$filename]); - } - - return isset($this->blacklistedFiles[$filename]); - } - - /** - * Returns the list of blacklisted files. - * - * @return array - */ - public function getBlacklist() - { - return array_keys($this->blacklistedFiles); + return !isset($this->whitelistedFiles[$filename]); } /** @@ -239,40 +145,16 @@ public function getWhitelist() * Returns whether this filter has a whitelist. * * @return bool - * @since Method available since Release 1.1.0 */ public function hasWhitelist() { return !empty($this->whitelistedFiles); } - /** - * Returns the blacklisted files. - * - * @return array - * @since Method available since Release 2.0.0 - */ - public function getBlacklistedFiles() - { - return $this->blacklistedFiles; - } - - /** - * Sets the blacklisted files. - * - * @param array $blacklistedFiles - * @since Method available since Release 2.0.0 - */ - public function setBlacklistedFiles($blacklistedFiles) - { - $this->blacklistedFiles = $blacklistedFiles; - } - /** * Returns the whitelisted files. * * @return array - * @since Method available since Release 2.0.0 */ public function getWhitelistedFiles() { @@ -283,7 +165,6 @@ public function getWhitelistedFiles() * Sets the whitelisted files. * * @param array $whitelistedFiles - * @since Method available since Release 2.0.0 */ public function setWhitelistedFiles($whitelistedFiles) { diff --git a/src/CodeCoverage/Report/Node.php b/src/Node/AbstractNode.php similarity index 84% rename from src/CodeCoverage/Report/Node.php rename to src/Node/AbstractNode.php index c57f74425..f3608058e 100644 --- a/src/CodeCoverage/Report/Node.php +++ b/src/Node/AbstractNode.php @@ -1,6 +1,6 @@ * @@ -8,45 +8,47 @@ * file that was distributed with this source code. */ +namespace SebastianBergmann\CodeCoverage\Node; + +use SebastianBergmann\CodeCoverage\Util; + /** * Base class for nodes in the code coverage information tree. - * - * @since Class available since Release 1.1.0 */ -abstract class PHP_CodeCoverage_Report_Node implements Countable +abstract class AbstractNode implements \Countable { /** * @var string */ - protected $name; + private $name; /** * @var string */ - protected $path; + private $path; /** * @var array */ - protected $pathArray; + private $pathArray; /** - * @var PHP_CodeCoverage_Report_Node + * @var AbstractNode */ - protected $parent; + private $parent; /** * @var string */ - protected $id; + private $id; /** * Constructor. * - * @param string $name - * @param PHP_CodeCoverage_Report_Node $parent + * @param string $name + * @param AbstractNode $parent */ - public function __construct($name, PHP_CodeCoverage_Report_Node $parent = null) + public function __construct($name, AbstractNode $parent = null) { if (substr($name, -1) == '/') { $name = substr($name, 0, -1); @@ -111,7 +113,7 @@ public function getPathAsArray() { if ($this->pathArray === null) { if ($this->parent === null) { - $this->pathArray = array(); + $this->pathArray = []; } else { $this->pathArray = $this->parent->getPathAsArray(); } @@ -123,7 +125,7 @@ public function getPathAsArray() } /** - * @return PHP_CodeCoverage_Report_Node + * @return AbstractNode */ public function getParent() { @@ -133,12 +135,13 @@ public function getParent() /** * Returns the percentage of classes that has been tested. * - * @param bool $asString + * @param bool $asString + * * @return int */ public function getTestedClassesPercent($asString = true) { - return PHP_CodeCoverage_Util::percent( + return Util::percent( $this->getNumTestedClasses(), $this->getNumClasses(), $asString @@ -148,12 +151,13 @@ public function getTestedClassesPercent($asString = true) /** * Returns the percentage of traits that has been tested. * - * @param bool $asString + * @param bool $asString + * * @return int */ public function getTestedTraitsPercent($asString = true) { - return PHP_CodeCoverage_Util::percent( + return Util::percent( $this->getNumTestedTraits(), $this->getNumTraits(), $asString @@ -163,13 +167,13 @@ public function getTestedTraitsPercent($asString = true) /** * Returns the percentage of traits that has been tested. * - * @param bool $asString + * @param bool $asString + * * @return int - * @since Method available since Release 1.2.0 */ public function getTestedClassesAndTraitsPercent($asString = true) { - return PHP_CodeCoverage_Util::percent( + return Util::percent( $this->getNumTestedClassesAndTraits(), $this->getNumClassesAndTraits(), $asString @@ -179,12 +183,13 @@ public function getTestedClassesAndTraitsPercent($asString = true) /** * Returns the percentage of methods that has been tested. * - * @param bool $asString + * @param bool $asString + * * @return int */ public function getTestedMethodsPercent($asString = true) { - return PHP_CodeCoverage_Util::percent( + return Util::percent( $this->getNumTestedMethods(), $this->getNumMethods(), $asString @@ -194,12 +199,13 @@ public function getTestedMethodsPercent($asString = true) /** * Returns the percentage of executed lines. * - * @param bool $asString + * @param bool $asString + * * @return int */ public function getLineExecutedPercent($asString = true) { - return PHP_CodeCoverage_Util::percent( + return Util::percent( $this->getNumExecutedLines(), $this->getNumExecutableLines(), $asString @@ -210,7 +216,6 @@ public function getLineExecutedPercent($asString = true) * Returns the number of classes and traits. * * @return int - * @since Method available since Release 1.2.0 */ public function getNumClassesAndTraits() { @@ -221,7 +226,6 @@ public function getNumClassesAndTraits() * Returns the number of tested classes and traits. * * @return int - * @since Method available since Release 1.2.0 */ public function getNumTestedClassesAndTraits() { @@ -232,7 +236,6 @@ public function getNumTestedClassesAndTraits() * Returns the classes and traits of this node. * * @return array - * @since Method available since Release 1.2.0 */ public function getClassesAndTraits() { diff --git a/src/CodeCoverage/Report/Factory.php b/src/Node/Builder.php similarity index 85% rename from src/CodeCoverage/Report/Factory.php rename to src/Node/Builder.php index b28964e8a..8a6a65c1b 100644 --- a/src/CodeCoverage/Report/Factory.php +++ b/src/Node/Builder.php @@ -1,6 +1,6 @@ * @@ -8,22 +8,22 @@ * file that was distributed with this source code. */ -/** - * Factory for PHP_CodeCoverage_Report_Node_* object graphs. - * - * @since Class available since Release 1.1.0 - */ -class PHP_CodeCoverage_Report_Factory +namespace SebastianBergmann\CodeCoverage\Node; + +use SebastianBergmann\CodeCoverage\CodeCoverage; + +class Builder { /** - * @param PHP_CodeCoverage $coverage - * @return PHP_CodeCoverage_Report_Node_Directory + * @param CodeCoverage $coverage + * + * @return Directory */ - public function create(PHP_CodeCoverage $coverage) + public function build(CodeCoverage $coverage) { $files = $coverage->getData(); $commonPath = $this->reducePaths($files); - $root = new PHP_CodeCoverage_Report_Node_Directory( + $root = new Directory( $commonPath, null ); @@ -39,12 +39,12 @@ public function create(PHP_CodeCoverage $coverage) } /** - * @param PHP_CodeCoverage_Report_Node_Directory $root - * @param array $items - * @param array $tests - * @param bool $cacheTokens + * @param Directory $root + * @param array $items + * @param array $tests + * @param bool $cacheTokens */ - private function addItems(PHP_CodeCoverage_Report_Node_Directory $root, array $items, array $tests, $cacheTokens) + private function addItems(Directory $root, array $items, array $tests, $cacheTokens) { foreach ($items as $key => $value) { if (substr($key, -2) == '/f') { @@ -100,12 +100,13 @@ private function addItems(PHP_CodeCoverage_Report_Node_Directory $root, array $i * ) * * - * @param array $files + * @param array $files + * * @return array */ private function buildDirectoryStructure($files) { - $result = array(); + $result = []; foreach ($files as $path => $file) { $path = explode('/', $path); @@ -165,7 +166,8 @@ private function buildDirectoryStructure($files) * ) * * - * @param array $files + * @param array $files + * * @return string */ private function reducePaths(&$files) diff --git a/src/CodeCoverage/Report/Node/Directory.php b/src/Node/Directory.php similarity index 82% rename from src/CodeCoverage/Report/Node/Directory.php rename to src/Node/Directory.php index dd71ecb57..6a9f28db5 100644 --- a/src/CodeCoverage/Report/Node/Directory.php +++ b/src/Node/Directory.php @@ -1,6 +1,6 @@ * @@ -8,102 +8,104 @@ * file that was distributed with this source code. */ +namespace SebastianBergmann\CodeCoverage\Node; + +use SebastianBergmann\CodeCoverage\InvalidArgumentException; + /** * Represents a directory in the code coverage information tree. - * - * @since Class available since Release 1.1.0 */ -class PHP_CodeCoverage_Report_Node_Directory extends PHP_CodeCoverage_Report_Node implements IteratorAggregate +class Directory extends AbstractNode implements \IteratorAggregate { /** - * @var PHP_CodeCoverage_Report_Node[] + * @var AbstractNode[] */ - protected $children = array(); + private $children = []; /** - * @var PHP_CodeCoverage_Report_Node_Directory[] + * @var Directory[] */ - protected $directories = array(); + private $directories = []; /** - * @var PHP_CodeCoverage_Report_Node_File[] + * @var File[] */ - protected $files = array(); + private $files = []; /** * @var array */ - protected $classes; + private $classes; /** * @var array */ - protected $traits; + private $traits; /** * @var array */ - protected $functions; + private $functions; /** * @var array */ - protected $linesOfCode = null; + private $linesOfCode = null; /** * @var int */ - protected $numFiles = -1; + private $numFiles = -1; /** * @var int */ - protected $numExecutableLines = -1; + private $numExecutableLines = -1; /** * @var int */ - protected $numExecutedLines = -1; + private $numExecutedLines = -1; /** * @var int */ - protected $numClasses = -1; + private $numClasses = -1; /** * @var int */ - protected $numTestedClasses = -1; + private $numTestedClasses = -1; /** * @var int */ - protected $numTraits = -1; + private $numTraits = -1; /** * @var int */ - protected $numTestedTraits = -1; + private $numTestedTraits = -1; /** * @var int */ - protected $numMethods = -1; + private $numMethods = -1; /** * @var int */ - protected $numTestedMethods = -1; + private $numTestedMethods = -1; /** * @var int */ - protected $numFunctions = -1; + private $numFunctions = -1; /** * @var int */ - protected $numTestedFunctions = -1; + private $numTestedFunctions = -1; /** * Returns the number of files in/under this node. @@ -126,21 +128,22 @@ public function count() /** * Returns an iterator for this node. * - * @return RecursiveIteratorIterator + * @return \RecursiveIteratorIterator */ public function getIterator() { - return new RecursiveIteratorIterator( - new PHP_CodeCoverage_Report_Node_Iterator($this), - RecursiveIteratorIterator::SELF_FIRST + return new \RecursiveIteratorIterator( + new Iterator($this), + \RecursiveIteratorIterator::SELF_FIRST ); } /** * Adds a new directory. * - * @param string $name - * @return PHP_CodeCoverage_Report_Node_Directory + * @param string $name + * + * @return Directory */ public function addDirectory($name) { @@ -155,16 +158,18 @@ public function addDirectory($name) /** * Adds a new file. * - * @param string $name - * @param array $coverageData - * @param array $testData - * @param bool $cacheTokens - * @return PHP_CodeCoverage_Report_Node_File - * @throws PHP_CodeCoverage_Exception + * @param string $name + * @param array $coverageData + * @param array $testData + * @param bool $cacheTokens + * + * @return File + * + * @throws InvalidArgumentException */ public function addFile($name, array $coverageData, array $testData, $cacheTokens) { - $file = new PHP_CodeCoverage_Report_Node_File( + $file = new File( $name, $this, $coverageData, @@ -219,7 +224,7 @@ public function getChildNodes() public function getClasses() { if ($this->classes === null) { - $this->classes = array(); + $this->classes = []; foreach ($this->children as $child) { $this->classes = array_merge( @@ -240,7 +245,7 @@ public function getClasses() public function getTraits() { if ($this->traits === null) { - $this->traits = array(); + $this->traits = []; foreach ($this->children as $child) { $this->traits = array_merge( @@ -261,7 +266,7 @@ public function getTraits() public function getFunctions() { if ($this->functions === null) { - $this->functions = array(); + $this->functions = []; foreach ($this->children as $child) { $this->functions = array_merge( @@ -282,7 +287,7 @@ public function getFunctions() public function getLinesOfCode() { if ($this->linesOfCode === null) { - $this->linesOfCode = array('loc' => 0, 'cloc' => 0, 'ncloc' => 0); + $this->linesOfCode = ['loc' => 0, 'cloc' => 0, 'ncloc' => 0]; foreach ($this->children as $child) { $linesOfCode = $child->getLinesOfCode(); diff --git a/src/CodeCoverage/Report/Node/File.php b/src/Node/File.php similarity index 80% rename from src/CodeCoverage/Report/Node/File.php rename to src/Node/File.php index 03b3d8cf8..b94f20765 100644 --- a/src/CodeCoverage/Report/Node/File.php +++ b/src/Node/File.php @@ -1,6 +1,6 @@ * @@ -8,107 +8,110 @@ * file that was distributed with this source code. */ +namespace SebastianBergmann\CodeCoverage\Node; + +use SebastianBergmann\CodeCoverage\InvalidArgumentException; + /** * Represents a file in the code coverage information tree. - * - * @since Class available since Release 1.1.0 */ -class PHP_CodeCoverage_Report_Node_File extends PHP_CodeCoverage_Report_Node +class File extends AbstractNode { /** * @var array */ - protected $coverageData; + private $coverageData; /** * @var array */ - protected $testData; + private $testData; /** * @var int */ - protected $numExecutableLines = 0; + private $numExecutableLines = 0; /** * @var int */ - protected $numExecutedLines = 0; + private $numExecutedLines = 0; /** * @var array */ - protected $classes = array(); + private $classes = []; /** * @var array */ - protected $traits = array(); + private $traits = []; /** * @var array */ - protected $functions = array(); + private $functions = []; /** * @var array */ - protected $linesOfCode = array(); + private $linesOfCode = []; /** * @var int */ - protected $numTestedTraits = 0; + private $numTestedTraits = 0; /** * @var int */ - protected $numTestedClasses = 0; + private $numTestedClasses = 0; /** * @var int */ - protected $numMethods = null; + private $numMethods = null; /** * @var int */ - protected $numTestedMethods = null; + private $numTestedMethods = null; /** * @var int */ - protected $numTestedFunctions = null; + private $numTestedFunctions = null; /** * @var array */ - protected $startLines = array(); + private $startLines = []; /** * @var array */ - protected $endLines = array(); + private $endLines = []; /** * @var bool */ - protected $cacheTokens; + private $cacheTokens; /** * Constructor. * - * @param string $name - * @param PHP_CodeCoverage_Report_Node $parent - * @param array $coverageData - * @param array $testData - * @param bool $cacheTokens - * @throws PHP_CodeCoverage_Exception - */ - public function __construct($name, PHP_CodeCoverage_Report_Node $parent, array $coverageData, array $testData, $cacheTokens) + * @param string $name + * @param AbstractNode $parent + * @param array $coverageData + * @param array $testData + * @param bool $cacheTokens + * + * @throws InvalidArgumentException + */ + public function __construct($name, AbstractNode $parent, array $coverageData, array $testData, $cacheTokens) { if (!is_bool($cacheTokens)) { - throw PHP_CodeCoverage_Util_InvalidArgumentHelper::factory( + throw InvalidArgumentException::create( 1, 'boolean' ); @@ -351,10 +354,12 @@ public function getNumTestedFunctions() */ protected function calculateStatistics() { + $classStack = $functionStack = []; + if ($this->cacheTokens) { - $tokens = PHP_Token_Stream_CachingFactory::get($this->getPath()); + $tokens = \PHP_Token_Stream_CachingFactory::get($this->getPath()); } else { - $tokens = new PHP_Token_Stream($this->getPath()); + $tokens = new \PHP_Token_Stream($this->getPath()); } $this->processClasses($tokens); @@ -367,6 +372,10 @@ protected function calculateStatistics() if (isset($this->startLines[$lineNumber])) { // Start line of a class. if (isset($this->startLines[$lineNumber]['className'])) { + if (isset($currentClass)) { + $classStack[] = &$currentClass; + } + $currentClass = &$this->startLines[$lineNumber]; } // Start line of a trait. elseif (isset($this->startLines[$lineNumber]['traitName'])) { @@ -376,12 +385,15 @@ protected function calculateStatistics() $currentMethod = &$this->startLines[$lineNumber]; } // Start line of a function. elseif (isset($this->startLines[$lineNumber]['functionName'])) { + if (isset($currentFunction)) { + $functionStack[] = &$currentFunction; + } + $currentFunction = &$this->startLines[$lineNumber]; } } - if (isset($this->coverageData[$lineNumber]) && - $this->coverageData[$lineNumber] !== null) { + if (isset($this->coverageData[$lineNumber])) { if (isset($currentClass)) { $currentClass['executableLines']++; } @@ -425,6 +437,13 @@ protected function calculateStatistics() // End line of a class. if (isset($this->endLines[$lineNumber]['className'])) { unset($currentClass); + + if ($classStack) { + end($classStack); + $key = key($classStack); + $currentClass = &$classStack[$key]; + unset($classStack[$key]); + } } // End line of a trait. elseif (isset($this->endLines[$lineNumber]['traitName'])) { unset($currentTrait); @@ -434,6 +453,13 @@ protected function calculateStatistics() } // End line of a function. elseif (isset($this->endLines[$lineNumber]['functionName'])) { unset($currentFunction); + + if ($functionStack) { + end($functionStack); + $key = key($functionStack); + $currentFunction = &$functionStack[$key]; + unset($functionStack[$key]); + } } } } @@ -508,9 +534,9 @@ protected function calculateStatistics() } /** - * @param PHP_Token_Stream $tokens + * @param \PHP_Token_Stream $tokens */ - protected function processClasses(PHP_Token_Stream $tokens) + protected function processClasses(\PHP_Token_Stream $tokens) { $classes = $tokens->getClasses(); unset($tokens); @@ -518,9 +544,9 @@ protected function processClasses(PHP_Token_Stream $tokens) $link = $this->getId() . '.html#'; foreach ($classes as $className => $class) { - $this->classes[$className] = array( + $this->classes[$className] = [ 'className' => $className, - 'methods' => array(), + 'methods' => [], 'startLine' => $class['startLine'], 'executableLines' => 0, 'executedLines' => 0, @@ -529,24 +555,13 @@ protected function processClasses(PHP_Token_Stream $tokens) 'crap' => 0, 'package' => $class['package'], 'link' => $link . $class['startLine'] - ); + ]; $this->startLines[$class['startLine']] = &$this->classes[$className]; $this->endLines[$class['endLine']] = &$this->classes[$className]; foreach ($class['methods'] as $methodName => $method) { - $this->classes[$className]['methods'][$methodName] = array( - 'methodName' => $methodName, - 'signature' => $method['signature'], - 'startLine' => $method['startLine'], - 'endLine' => $method['endLine'], - 'executableLines' => 0, - 'executedLines' => 0, - 'ccn' => $method['ccn'], - 'coverage' => 0, - 'crap' => 0, - 'link' => $link . $method['startLine'] - ); + $this->classes[$className]['methods'][$methodName] = $this->newMethod($methodName, $method, $link); $this->startLines[$method['startLine']] = &$this->classes[$className]['methods'][$methodName]; $this->endLines[$method['endLine']] = &$this->classes[$className]['methods'][$methodName]; @@ -555,9 +570,9 @@ protected function processClasses(PHP_Token_Stream $tokens) } /** - * @param PHP_Token_Stream $tokens + * @param \PHP_Token_Stream $tokens */ - protected function processTraits(PHP_Token_Stream $tokens) + protected function processTraits(\PHP_Token_Stream $tokens) { $traits = $tokens->getTraits(); unset($tokens); @@ -565,9 +580,9 @@ protected function processTraits(PHP_Token_Stream $tokens) $link = $this->getId() . '.html#'; foreach ($traits as $traitName => $trait) { - $this->traits[$traitName] = array( + $this->traits[$traitName] = [ 'traitName' => $traitName, - 'methods' => array(), + 'methods' => [], 'startLine' => $trait['startLine'], 'executableLines' => 0, 'executedLines' => 0, @@ -576,24 +591,13 @@ protected function processTraits(PHP_Token_Stream $tokens) 'crap' => 0, 'package' => $trait['package'], 'link' => $link . $trait['startLine'] - ); + ]; $this->startLines[$trait['startLine']] = &$this->traits[$traitName]; $this->endLines[$trait['endLine']] = &$this->traits[$traitName]; foreach ($trait['methods'] as $methodName => $method) { - $this->traits[$traitName]['methods'][$methodName] = array( - 'methodName' => $methodName, - 'signature' => $method['signature'], - 'startLine' => $method['startLine'], - 'endLine' => $method['endLine'], - 'executableLines' => 0, - 'executedLines' => 0, - 'ccn' => $method['ccn'], - 'coverage' => 0, - 'crap' => 0, - 'link' => $link . $method['startLine'] - ); + $this->traits[$traitName]['methods'][$methodName] = $this->newMethod($methodName, $method, $link); $this->startLines[$method['startLine']] = &$this->traits[$traitName]['methods'][$methodName]; $this->endLines[$method['endLine']] = &$this->traits[$traitName]['methods'][$methodName]; @@ -602,9 +606,9 @@ protected function processTraits(PHP_Token_Stream $tokens) } /** - * @param PHP_Token_Stream $tokens + * @param \PHP_Token_Stream $tokens */ - protected function processFunctions(PHP_Token_Stream $tokens) + protected function processFunctions(\PHP_Token_Stream $tokens) { $functions = $tokens->getFunctions(); unset($tokens); @@ -612,7 +616,7 @@ protected function processFunctions(PHP_Token_Stream $tokens) $link = $this->getId() . '.html#'; foreach ($functions as $functionName => $function) { - $this->functions[$functionName] = array( + $this->functions[$functionName] = [ 'functionName' => $functionName, 'signature' => $function['signature'], 'startLine' => $function['startLine'], @@ -622,7 +626,7 @@ protected function processFunctions(PHP_Token_Stream $tokens) 'coverage' => 0, 'crap' => 0, 'link' => $link . $function['startLine'] - ); + ]; $this->startLines[$function['startLine']] = &$this->functions[$functionName]; $this->endLines[$function['endLine']] = &$this->functions[$functionName]; @@ -633,10 +637,10 @@ protected function processFunctions(PHP_Token_Stream $tokens) * Calculates the Change Risk Anti-Patterns (CRAP) index for a unit of code * based on its cyclomatic complexity and percentage of code coverage. * - * @param int $ccn - * @param float $coverage + * @param int $ccn + * @param float $coverage + * * @return string - * @since Method available since Release 1.2.0 */ protected function crap($ccn, $coverage) { @@ -653,4 +657,28 @@ protected function crap($ccn, $coverage) pow($ccn, 2) * pow(1 - $coverage/100, 3) + $ccn ); } + + /** + * @param string $methodName + * @param array $method + * @param string $link + * + * @return array + */ + private function newMethod($methodName, array $method, $link) + { + return [ + 'methodName' => $methodName, + 'visibility' => $method['visibility'], + 'signature' => $method['signature'], + 'startLine' => $method['startLine'], + 'endLine' => $method['endLine'], + 'executableLines' => 0, + 'executedLines' => 0, + 'ccn' => $method['ccn'], + 'coverage' => 0, + 'crap' => 0, + 'link' => $link . $method['startLine'], + ]; + } } diff --git a/src/CodeCoverage/Report/Node/Iterator.php b/src/Node/Iterator.php similarity index 68% rename from src/CodeCoverage/Report/Node/Iterator.php rename to src/Node/Iterator.php index f468b6b8b..e24638059 100644 --- a/src/CodeCoverage/Report/Node/Iterator.php +++ b/src/Node/Iterator.php @@ -1,6 +1,6 @@ * @@ -8,29 +8,27 @@ * file that was distributed with this source code. */ +namespace SebastianBergmann\CodeCoverage\Node; + /** - * Recursive iterator for PHP_CodeCoverage_Report_Node object graphs. - * - * @since Class available since Release 1.1.0 + * Recursive iterator for node object graphs. */ -class PHP_CodeCoverage_Report_Node_Iterator implements RecursiveIterator +class Iterator implements \RecursiveIterator { /** * @var int */ - protected $position; + private $position; /** - * @var PHP_CodeCoverage_Report_Node[] + * @var AbstractNode[] */ - protected $nodes; + private $nodes; /** - * Constructor. - * - * @param PHP_CodeCoverage_Report_Node_Directory $node + * @param Directory $node */ - public function __construct(PHP_CodeCoverage_Report_Node_Directory $node) + public function __construct(Directory $node) { $this->nodes = $node->getChildNodes(); } @@ -66,7 +64,7 @@ public function key() /** * Returns the current element. * - * @return PHPUnit_Framework_Test + * @return \PHPUnit_Framework_Test */ public function current() { @@ -84,7 +82,7 @@ public function next() /** * Returns the sub iterator for the current element. * - * @return PHP_CodeCoverage_Report_Node_Iterator + * @return Iterator */ public function getChildren() { @@ -100,6 +98,6 @@ public function getChildren() */ public function hasChildren() { - return $this->nodes[$this->position] instanceof PHP_CodeCoverage_Report_Node_Directory; + return $this->nodes[$this->position] instanceof Directory; } } diff --git a/src/CodeCoverage/Report/Clover.php b/src/Report/Clover.php similarity index 85% rename from src/CodeCoverage/Report/Clover.php rename to src/Report/Clover.php index c0ea8d821..7b0fa38e9 100644 --- a/src/CodeCoverage/Report/Clover.php +++ b/src/Report/Clover.php @@ -1,6 +1,6 @@ * @@ -8,22 +8,26 @@ * file that was distributed with this source code. */ +namespace SebastianBergmann\CodeCoverage\Report; + +use SebastianBergmann\CodeCoverage\CodeCoverage; +use SebastianBergmann\CodeCoverage\Node\File; + /** - * Generates a Clover XML logfile from an PHP_CodeCoverage object. - * - * @since Class available since Release 1.0.0 + * Generates a Clover XML logfile from a code coverage object. */ -class PHP_CodeCoverage_Report_Clover +class Clover { /** - * @param PHP_CodeCoverage $coverage - * @param string $target - * @param string $name + * @param CodeCoverage $coverage + * @param string $target + * @param string $name + * * @return string */ - public function process(PHP_CodeCoverage $coverage, $target = null, $name = null) + public function process(CodeCoverage $coverage, $target = null, $name = null) { - $xmlDocument = new DOMDocument('1.0', 'UTF-8'); + $xmlDocument = new \DOMDocument('1.0', 'UTF-8'); $xmlDocument->formatOutput = true; $xmlCoverage = $xmlDocument->createElement('coverage'); @@ -39,23 +43,24 @@ public function process(PHP_CodeCoverage $coverage, $target = null, $name = null $xmlCoverage->appendChild($xmlProject); - $packages = array(); + $packages = []; $report = $coverage->getReport(); unset($coverage); foreach ($report as $item) { - $namespace = 'global'; - - if (!$item instanceof PHP_CodeCoverage_Report_Node_File) { + if (!$item instanceof File) { continue; } + /* @var File $item */ + $xmlFile = $xmlDocument->createElement('file'); $xmlFile->setAttribute('name', $item->getPath()); - $classes = $item->getClassesAndTraits(); - $coverage = $item->getCoverageData(); - $lines = array(); + $classes = $item->getClassesAndTraits(); + $coverage = $item->getCoverageData(); + $lines = []; + $namespace = 'global'; foreach ($classes as $className => $class) { $classStatements = 0; @@ -84,12 +89,14 @@ public function process(PHP_CodeCoverage $coverage, $target = null, $name = null } } - $lines[$method['startLine']] = array( - 'count' => $methodCount, - 'crap' => $method['crap'], - 'type' => 'method', - 'name' => $methodName - ); + $lines[$method['startLine']] = [ + 'ccn' => $method['ccn'], + 'count' => $methodCount, + 'crap' => $method['crap'], + 'type' => 'method', + 'visibility' => $method['visibility'], + 'name' => $methodName + ]; } if (!empty($class['package']['namespace'])) { @@ -131,6 +138,7 @@ public function process(PHP_CodeCoverage $coverage, $target = null, $name = null $xmlFile->appendChild($xmlClass); $xmlMetrics = $xmlDocument->createElement('metrics'); + $xmlMetrics->setAttribute('complexity', $class['ccn']); $xmlMetrics->setAttribute('methods', $classMethods); $xmlMetrics->setAttribute('coveredmethods', $coveredMethods); $xmlMetrics->setAttribute('conditionals', 0); @@ -160,9 +168,9 @@ public function process(PHP_CodeCoverage $coverage, $target = null, $name = null continue; } - $lines[$line] = array( + $lines[$line] = [ 'count' => count($data), 'type' => 'stmt' - ); + ]; } ksort($lines); @@ -176,6 +184,14 @@ public function process(PHP_CodeCoverage $coverage, $target = null, $name = null $xmlLine->setAttribute('name', $data['name']); } + if (isset($data['visibility'])) { + $xmlLine->setAttribute('visibility', $data['visibility']); + } + + if (isset($data['ccn'])) { + $xmlLine->setAttribute('complexity', $data['ccn']); + } + if (isset($data['crap'])) { $xmlLine->setAttribute('crap', $data['crap']); } diff --git a/src/CodeCoverage/Report/Crap4j.php b/src/Report/Crap4j.php similarity index 85% rename from src/CodeCoverage/Report/Crap4j.php rename to src/Report/Crap4j.php index 2deced2ce..00180d0ea 100644 --- a/src/CodeCoverage/Report/Crap4j.php +++ b/src/Report/Crap4j.php @@ -1,6 +1,6 @@ * @@ -8,10 +8,13 @@ * file that was distributed with this source code. */ -/** - * @since Class available since Release 2.0.0 - */ -class PHP_CodeCoverage_Report_Crap4j +namespace SebastianBergmann\CodeCoverage\Report; + +use SebastianBergmann\CodeCoverage\CodeCoverage; +use SebastianBergmann\CodeCoverage\Node\File; +use SebastianBergmann\CodeCoverage\InvalidArgumentException; + +class Crap4j { /** * @var int @@ -24,7 +27,7 @@ class PHP_CodeCoverage_Report_Crap4j public function __construct($threshold = 30) { if (!is_int($threshold)) { - throw PHP_CodeCoverage_Util_InvalidArgumentHelper::factory( + throw InvalidArgumentException::create( 1, 'integer' ); @@ -34,14 +37,15 @@ public function __construct($threshold = 30) } /** - * @param PHP_CodeCoverage $coverage - * @param string $target - * @param string $name + * @param CodeCoverage $coverage + * @param string $target + * @param string $name + * * @return string */ - public function process(PHP_CodeCoverage $coverage, $target = null, $name = null) + public function process(CodeCoverage $coverage, $target = null, $name = null) { - $document = new DOMDocument('1.0', 'UTF-8'); + $document = new \DOMDocument('1.0', 'UTF-8'); $document->formatOutput = true; $root = $document->createElement('crap_result'); @@ -65,7 +69,7 @@ public function process(PHP_CodeCoverage $coverage, $target = null, $name = null foreach ($report as $item) { $namespace = 'global'; - if (!$item instanceof PHP_CodeCoverage_Report_Node_File) { + if (!$item instanceof File) { continue; } @@ -116,7 +120,7 @@ public function process(PHP_CodeCoverage $coverage, $target = null, $name = null if ($fullMethodCount > 0) { $crapMethodPercent = $this->roundValue((100 * $fullCrapMethodCount) / $fullMethodCount); } else { - $crapMethodPercent = ''; + $crapMethodPercent = 0; } $stats->appendChild($document->createElement('crapMethodPercent', $crapMethodPercent)); @@ -136,9 +140,10 @@ public function process(PHP_CodeCoverage $coverage, $target = null, $name = null } /** - * @param float $crapValue - * @param int $cyclomaticComplexity - * @param float $coveragePercent + * @param float $crapValue + * @param int $cyclomaticComplexity + * @param float $coveragePercent + * * @return float */ private function getCrapLoad($crapValue, $cyclomaticComplexity, $coveragePercent) @@ -154,7 +159,8 @@ private function getCrapLoad($crapValue, $cyclomaticComplexity, $coveragePercent } /** - * @param float $value + * @param float $value + * * @return float */ private function roundValue($value) diff --git a/src/CodeCoverage/Report/HTML.php b/src/Report/Html/Facade.php similarity index 81% rename from src/CodeCoverage/Report/HTML.php rename to src/Report/Html/Facade.php index 80916ef3d..d1453ad41 100644 --- a/src/CodeCoverage/Report/HTML.php +++ b/src/Report/Html/Facade.php @@ -1,6 +1,6 @@ * @@ -8,12 +8,15 @@ * file that was distributed with this source code. */ +namespace SebastianBergmann\CodeCoverage\Report\Html; + +use SebastianBergmann\CodeCoverage\CodeCoverage; +use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode; + /** - * Generates an HTML report from an PHP_CodeCoverage object. - * - * @since Class available since Release 1.0.0 + * Generates an HTML report from a code coverage object. */ -class PHP_CodeCoverage_Report_HTML +class Facade { /** * @var string @@ -47,22 +50,14 @@ public function __construct($lowUpperBound = 50, $highLowerBound = 90, $generato $this->generator = $generator; $this->highLowerBound = $highLowerBound; $this->lowUpperBound = $lowUpperBound; - - $this->templatePath = sprintf( - '%s%sHTML%sRenderer%sTemplate%s', - dirname(__FILE__), - DIRECTORY_SEPARATOR, - DIRECTORY_SEPARATOR, - DIRECTORY_SEPARATOR, - DIRECTORY_SEPARATOR - ); + $this->templatePath = __DIR__ . '/Renderer/Template/'; } /** - * @param PHP_CodeCoverage $coverage - * @param string $target + * @param CodeCoverage $coverage + * @param string $target */ - public function process(PHP_CodeCoverage $coverage, $target) + public function process(CodeCoverage $coverage, $target) { $target = $this->getDirectory($target); $report = $coverage->getReport(); @@ -74,7 +69,7 @@ public function process(PHP_CodeCoverage $coverage, $target) $date = date('D M j G:i:s T Y', $_SERVER['REQUEST_TIME']); - $dashboard = new PHP_CodeCoverage_Report_HTML_Renderer_Dashboard( + $dashboard = new Dashboard( $this->templatePath, $this->generator, $date, @@ -82,7 +77,7 @@ public function process(PHP_CodeCoverage $coverage, $target) $this->highLowerBound ); - $directory = new PHP_CodeCoverage_Report_HTML_Renderer_Directory( + $directory = new Directory( $this->templatePath, $this->generator, $date, @@ -90,7 +85,7 @@ public function process(PHP_CodeCoverage $coverage, $target) $this->highLowerBound ); - $file = new PHP_CodeCoverage_Report_HTML_Renderer_File( + $file = new File( $this->templatePath, $this->generator, $date, @@ -104,7 +99,7 @@ public function process(PHP_CodeCoverage $coverage, $target) foreach ($report as $node) { $id = $node->getId(); - if ($node instanceof PHP_CodeCoverage_Report_Node_Directory) { + if ($node instanceof DirectoryNode) { if (!file_exists($target . $id)) { mkdir($target . $id, 0777, true); } @@ -153,10 +148,11 @@ private function copyFiles($target) } /** - * @param string $directory + * @param string $directory + * * @return string - * @throws PHP_CodeCoverage_Exception - * @since Method available since Release 1.2.0 + * + * @throws RuntimeException */ private function getDirectory($directory) { @@ -172,7 +168,7 @@ private function getDirectory($directory) return $directory; } - throw new PHP_CodeCoverage_Exception( + throw new RuntimeException( sprintf( 'Directory "%s" does not exist.', $directory diff --git a/src/CodeCoverage/Report/HTML/Renderer.php b/src/Report/Html/Renderer.php similarity index 73% rename from src/CodeCoverage/Report/HTML/Renderer.php rename to src/Report/Html/Renderer.php index e0c776ad8..7fe5c466c 100644 --- a/src/CodeCoverage/Report/HTML/Renderer.php +++ b/src/Report/Html/Renderer.php @@ -1,6 +1,6 @@ * @@ -8,14 +8,18 @@ * file that was distributed with this source code. */ +namespace SebastianBergmann\CodeCoverage\Report\Html; + +use SebastianBergmann\CodeCoverage\Node\AbstractNode; +use SebastianBergmann\CodeCoverage\Node\File as FileNode; +use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode; use SebastianBergmann\Environment\Runtime; +use SebastianBergmann\Version; /** - * Base class for PHP_CodeCoverage_Report_Node renderers. - * - * @since Class available since Release 1.1.0 + * Base class for node renderers. */ -abstract class PHP_CodeCoverage_Report_HTML_Renderer +abstract class Renderer { /** * @var string @@ -58,7 +62,7 @@ abstract class PHP_CodeCoverage_Report_HTML_Renderer */ public function __construct($templatePath, $generator, $date, $lowUpperBound, $highLowerBound) { - $version = new SebastianBergmann\Version('3.0', dirname(dirname(dirname(dirname(__DIR__))))); + $version = new Version('4.0', dirname(dirname(dirname(dirname(__DIR__))))); $this->templatePath = $templatePath; $this->generator = $generator; @@ -69,16 +73,14 @@ public function __construct($templatePath, $generator, $date, $lowUpperBound, $h } /** - * @param Text_Template $template - * @param array $data + * @param \Text_Template $template + * @param array $data + * * @return string */ - protected function renderItemTemplate(Text_Template $template, array $data) + protected function renderItemTemplate(\Text_Template $template, array $data) { $numSeparator = ' / '; - $classesBar = ' '; - $classesLevel = 'None'; - $classesNumber = ' '; if (isset($data['numClasses']) && $data['numClasses'] > 0) { $classesLevel = $this->getColorLevel($data['testedClassesPercent']); @@ -89,12 +91,12 @@ protected function renderItemTemplate(Text_Template $template, array $data) $classesBar = $this->getCoverageBar( $data['testedClassesPercent'] ); + } else { + $classesLevel = 'success'; + $classesNumber = '0' . $numSeparator . '0'; + $classesBar = $this->getCoverageBar(100); } - $methodsBar = ' '; - $methodsLevel = 'None'; - $methodsNumber = ' '; - if ($data['numMethods'] > 0) { $methodsLevel = $this->getColorLevel($data['testedMethodsPercent']); @@ -104,12 +106,13 @@ protected function renderItemTemplate(Text_Template $template, array $data) $methodsBar = $this->getCoverageBar( $data['testedMethodsPercent'] ); + } else { + $methodsLevel = 'success'; + $methodsNumber = '0' . $numSeparator . '0'; + $methodsBar = $this->getCoverageBar(100); + $data['testedMethodsPercentAsString'] = '100.00%'; } - $linesBar = ' '; - $linesLevel = 'None'; - $linesNumber = ' '; - if ($data['numExecutableLines'] > 0) { $linesLevel = $this->getColorLevel($data['linesExecutedPercent']); @@ -119,10 +122,15 @@ protected function renderItemTemplate(Text_Template $template, array $data) $linesBar = $this->getCoverageBar( $data['linesExecutedPercent'] ); + } else { + $linesLevel = 'success'; + $linesNumber = '0' . $numSeparator . '0'; + $linesBar = $this->getCoverageBar(100); + $data['linesExecutedPercentAsString'] = '100.00%'; } $template->setVar( - array( + [ 'icon' => isset($data['icon']) ? $data['icon'] : '', 'crap' => isset($data['crap']) ? $data['crap'] : '', 'name' => $data['name'], @@ -138,22 +146,22 @@ protected function renderItemTemplate(Text_Template $template, array $data) 'classes_tested_percent' => isset($data['testedClassesPercentAsString']) ? $data['testedClassesPercentAsString'] : '', 'classes_level' => $classesLevel, 'classes_number' => $classesNumber - ) + ] ); return $template->render(); } /** - * @param Text_Template $template - * @param PHP_CodeCoverage_Report_Node $node + * @param \Text_Template $template + * @param AbstractNode $node */ - protected function setCommonTemplateVariables(Text_Template $template, PHP_CodeCoverage_Report_Node $node) + protected function setCommonTemplateVariables(\Text_Template $template, AbstractNode $node) { $runtime = new Runtime; $template->setVar( - array( + [ 'id' => $node->getId(), 'full_path' => $node->getPath(), 'path_to_root' => $this->getPathToRoot($node), @@ -166,18 +174,18 @@ protected function setCommonTemplateVariables(Text_Template $template, PHP_CodeC 'generator' => $this->generator, 'low_upper_bound' => $this->lowUpperBound, 'high_lower_bound' => $this->highLowerBound - ) + ] ); } - protected function getBreadcrumbs(PHP_CodeCoverage_Report_Node $node) + protected function getBreadcrumbs(AbstractNode $node) { $breadcrumbs = ''; $path = $node->getPathAsArray(); - $pathToRoot = array(); + $pathToRoot = []; $max = count($path); - if ($node instanceof PHP_CodeCoverage_Report_Node_File) { + if ($node instanceof FileNode) { $max--; } @@ -199,21 +207,21 @@ protected function getBreadcrumbs(PHP_CodeCoverage_Report_Node $node) return $breadcrumbs; } - protected function getActiveBreadcrumb(PHP_CodeCoverage_Report_Node $node) + protected function getActiveBreadcrumb(AbstractNode $node) { $buffer = sprintf( '
  • %s
  • ' . "\n", $node->getName() ); - if ($node instanceof PHP_CodeCoverage_Report_Node_Directory) { + if ($node instanceof DirectoryNode) { $buffer .= '
  • (Dashboard)
  • ' . "\n"; } return $buffer; } - protected function getInactiveBreadcrumb(PHP_CodeCoverage_Report_Node $node, $pathToRoot) + protected function getInactiveBreadcrumb(AbstractNode $node, $pathToRoot) { return sprintf( '
  • %s
  • ' . "\n", @@ -222,13 +230,13 @@ protected function getInactiveBreadcrumb(PHP_CodeCoverage_Report_Node $node, $pa ); } - protected function getPathToRoot(PHP_CodeCoverage_Report_Node $node) + protected function getPathToRoot(AbstractNode $node) { $id = $node->getId(); $depth = substr_count($id, '/'); if ($id != 'index' && - $node instanceof PHP_CodeCoverage_Report_Node_Directory) { + $node instanceof DirectoryNode) { $depth++; } @@ -239,19 +247,20 @@ protected function getCoverageBar($percent) { $level = $this->getColorLevel($percent); - $template = new Text_Template( + $template = new \Text_Template( $this->templatePath . 'coverage_bar.html', '{{', '}}' ); - $template->setVar(array('level' => $level, 'percent' => sprintf('%.2F', $percent))); + $template->setVar(['level' => $level, 'percent' => sprintf('%.2F', $percent)]); return $template->render(); } /** - * @param int $percent + * @param int $percent + * * @return string */ protected function getColorLevel($percent) diff --git a/src/CodeCoverage/Report/HTML/Renderer/Dashboard.php b/src/Report/Html/Renderer/Dashboard.php similarity index 84% rename from src/CodeCoverage/Report/HTML/Renderer/Dashboard.php rename to src/Report/Html/Renderer/Dashboard.php index a29b7f3d7..7cde17559 100644 --- a/src/CodeCoverage/Report/HTML/Renderer/Dashboard.php +++ b/src/Report/Html/Renderer/Dashboard.php @@ -1,6 +1,6 @@ * @@ -8,21 +8,24 @@ * file that was distributed with this source code. */ +namespace SebastianBergmann\CodeCoverage\Report\Html; + +use SebastianBergmann\CodeCoverage\Node\AbstractNode; +use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode; + /** - * Renders the dashboard for a PHP_CodeCoverage_Report_Node_Directory node. - * - * @since Class available since Release 1.1.0 + * Renders the dashboard for a directory node. */ -class PHP_CodeCoverage_Report_HTML_Renderer_Dashboard extends PHP_CodeCoverage_Report_HTML_Renderer +class Dashboard extends Renderer { /** - * @param PHP_CodeCoverage_Report_Node_Directory $node - * @param string $file + * @param DirectoryNode $node + * @param string $file */ - public function render(PHP_CodeCoverage_Report_Node_Directory $node, $file) + public function render(DirectoryNode $node, $file) { $classes = $node->getClassesAndTraits(); - $template = new Text_Template( + $template = new \Text_Template( $this->templatePath . 'dashboard.html', '{{', '}}' @@ -37,7 +40,7 @@ public function render(PHP_CodeCoverage_Report_Node_Directory $node, $file) $projectRisks = $this->projectRisks($classes, $baseLink); $template->setVar( - array( + [ 'insufficient_coverage_classes' => $insufficientCoverage['class'], 'insufficient_coverage_methods' => $insufficientCoverage['method'], 'project_risks_classes' => $projectRisks['class'], @@ -46,7 +49,7 @@ public function render(PHP_CodeCoverage_Report_Node_Directory $node, $file) 'complexity_method' => $complexity['method'], 'class_coverage_distribution' => $coverageDistribution['class'], 'method_coverage_distribution' => $coverageDistribution['method'] - ) + ] ); $template->renderTo($file); @@ -55,13 +58,14 @@ public function render(PHP_CodeCoverage_Report_Node_Directory $node, $file) /** * Returns the data for the Class/Method Complexity charts. * - * @param array $classes - * @param string $baseLink + * @param array $classes + * @param string $baseLink + * * @return array */ protected function complexity(array $classes, $baseLink) { - $result = array('class' => array(), 'method' => array()); + $result = ['class' => [], 'method' => []]; foreach ($classes as $className => $class) { foreach ($class['methods'] as $methodName => $method) { @@ -69,7 +73,7 @@ protected function complexity(array $classes, $baseLink) $methodName = $className . '::' . $methodName; } - $result['method'][] = array( + $result['method'][] = [ $method['coverage'], $method['ccn'], sprintf( @@ -77,10 +81,10 @@ protected function complexity(array $classes, $baseLink) str_replace($baseLink, '', $method['link']), $methodName ) - ); + ]; } - $result['class'][] = array( + $result['class'][] = [ $class['coverage'], $class['ccn'], sprintf( @@ -88,25 +92,26 @@ protected function complexity(array $classes, $baseLink) str_replace($baseLink, '', $class['link']), $className ) - ); + ]; } - return array( + return [ 'class' => json_encode($result['class']), 'method' => json_encode($result['method']) - ); + ]; } /** * Returns the data for the Class / Method Coverage Distribution chart. * - * @param array $classes + * @param array $classes + * * @return array */ protected function coverageDistribution(array $classes) { - $result = array( - 'class' => array( + $result = [ + 'class' => [ '0%' => 0, '0-10%' => 0, '10-20%' => 0, @@ -119,8 +124,8 @@ protected function coverageDistribution(array $classes) '80-90%' => 0, '90-100%' => 0, '100%' => 0 - ), - 'method' => array( + ], + 'method' => [ '0%' => 0, '0-10%' => 0, '10-20%' => 0, @@ -133,8 +138,8 @@ protected function coverageDistribution(array $classes) '80-90%' => 0, '90-100%' => 0, '100%' => 0 - ) - ); + ] + ]; foreach ($classes as $class) { foreach ($class['methods'] as $methodName => $method) { @@ -160,24 +165,25 @@ protected function coverageDistribution(array $classes) } } - return array( + return [ 'class' => json_encode(array_values($result['class'])), 'method' => json_encode(array_values($result['method'])) - ); + ]; } /** * Returns the classes / methods with insufficient coverage. * - * @param array $classes - * @param string $baseLink + * @param array $classes + * @param string $baseLink + * * @return array */ protected function insufficientCoverage(array $classes, $baseLink) { - $leastTestedClasses = array(); - $leastTestedMethods = array(); - $result = array('class' => '', 'method' => ''); + $leastTestedClasses = []; + $leastTestedMethods = []; + $result = ['class' => '', 'method' => '']; foreach ($classes as $className => $class) { foreach ($class['methods'] as $methodName => $method) { @@ -213,7 +219,7 @@ protected function insufficientCoverage(array $classes, $baseLink) list($class, $method) = explode('::', $methodName); $result['method'] .= sprintf( - ' %s%d%%' . "\n", + ' %s%d%%' . "\n", str_replace($baseLink, '', $classes[$class]['methods'][$method]['link']), $methodName, $method, @@ -227,15 +233,16 @@ protected function insufficientCoverage(array $classes, $baseLink) /** * Returns the project risks according to the CRAP index. * - * @param array $classes - * @param string $baseLink + * @param array $classes + * @param string $baseLink + * * @return array */ protected function projectRisks(array $classes, $baseLink) { - $classRisks = array(); - $methodRisks = array(); - $result = array('class' => '', 'method' => ''); + $classRisks = []; + $methodRisks = []; + $result = ['class' => '', 'method' => '']; foreach ($classes as $className => $class) { foreach ($class['methods'] as $methodName => $method) { @@ -284,7 +291,7 @@ protected function projectRisks(array $classes, $baseLink) return $result; } - protected function getActiveBreadcrumb(PHP_CodeCoverage_Report_Node $node) + protected function getActiveBreadcrumb(AbstractNode $node) { return sprintf( '
  • %s
  • ' . "\n" . diff --git a/src/Report/Html/Renderer/Directory.php b/src/Report/Html/Renderer/Directory.php new file mode 100644 index 000000000..a4b1b96f4 --- /dev/null +++ b/src/Report/Html/Renderer/Directory.php @@ -0,0 +1,101 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SebastianBergmann\CodeCoverage\Report\Html; + +use SebastianBergmann\CodeCoverage\Node\AbstractNode as Node; +use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode; + +/** + * Renders a directory node. + */ +class Directory extends Renderer +{ + /** + * @param DirectoryNode $node + * @param string $file + */ + public function render(DirectoryNode $node, $file) + { + $template = new \Text_Template($this->templatePath . 'directory.html', '{{', '}}'); + + $this->setCommonTemplateVariables($template, $node); + + $items = $this->renderItem($node, true); + + foreach ($node->getDirectories() as $item) { + $items .= $this->renderItem($item); + } + + foreach ($node->getFiles() as $item) { + $items .= $this->renderItem($item); + } + + $template->setVar( + [ + 'id' => $node->getId(), + 'items' => $items + ] + ); + + $template->renderTo($file); + } + + /** + * @param Node $node + * @param bool $total + * + * @return string + */ + protected function renderItem(Node $node, $total = false) + { + $data = [ + 'numClasses' => $node->getNumClassesAndTraits(), + 'numTestedClasses' => $node->getNumTestedClassesAndTraits(), + 'numMethods' => $node->getNumMethods(), + 'numTestedMethods' => $node->getNumTestedMethods(), + 'linesExecutedPercent' => $node->getLineExecutedPercent(false), + 'linesExecutedPercentAsString' => $node->getLineExecutedPercent(), + 'numExecutedLines' => $node->getNumExecutedLines(), + 'numExecutableLines' => $node->getNumExecutableLines(), + 'testedMethodsPercent' => $node->getTestedMethodsPercent(false), + 'testedMethodsPercentAsString' => $node->getTestedMethodsPercent(), + 'testedClassesPercent' => $node->getTestedClassesAndTraitsPercent(false), + 'testedClassesPercentAsString' => $node->getTestedClassesAndTraitsPercent() + ]; + + if ($total) { + $data['name'] = 'Total'; + } else { + if ($node instanceof DirectoryNode) { + $data['name'] = sprintf( + '%s', + $node->getName(), + $node->getName() + ); + + $data['icon'] = ' '; + } else { + $data['name'] = sprintf( + '%s', + $node->getName(), + $node->getName() + ); + + $data['icon'] = ' '; + } + } + + return $this->renderItemTemplate( + new \Text_Template($this->templatePath . 'directory_item.html', '{{', '}}'), + $data + ); + } +} diff --git a/src/CodeCoverage/Report/HTML/Renderer/File.php b/src/Report/Html/Renderer/File.php similarity index 83% rename from src/CodeCoverage/Report/HTML/Renderer/File.php rename to src/Report/Html/Renderer/File.php index cc8278b36..e6b11ef03 100644 --- a/src/CodeCoverage/Report/HTML/Renderer/File.php +++ b/src/Report/Html/Renderer/File.php @@ -1,6 +1,6 @@ * @@ -8,34 +8,15 @@ * file that was distributed with this source code. */ -// @codeCoverageIgnoreStart -if (!defined('T_TRAIT')) { - define('T_TRAIT', 1001); -} - -if (!defined('T_INSTEADOF')) { - define('T_INSTEADOF', 1002); -} - -if (!defined('T_CALLABLE')) { - define('T_CALLABLE', 1003); -} - -if (!defined('T_FINALLY')) { - define('T_FINALLY', 1004); -} +namespace SebastianBergmann\CodeCoverage\Report\Html; -if (!defined('T_YIELD')) { - define('T_YIELD', 1005); -} -// @codeCoverageIgnoreEnd +use SebastianBergmann\CodeCoverage\Node\File as FileNode; +use SebastianBergmann\CodeCoverage\Util; /** - * Renders a PHP_CodeCoverage_Report_Node_File node. - * - * @since Class available since Release 1.1.0 + * Renders a file node. */ -class PHP_CodeCoverage_Report_HTML_Renderer_File extends PHP_CodeCoverage_Report_HTML_Renderer +class File extends Renderer { /** * @var int @@ -63,24 +44,22 @@ public function __construct($templatePath, $generator, $date, $lowUpperBound, $h $this->htmlspecialcharsFlags = ENT_COMPAT; - if (PHP_VERSION_ID >= 50400 && defined('ENT_SUBSTITUTE')) { - $this->htmlspecialcharsFlags = $this->htmlspecialcharsFlags | ENT_HTML401 | ENT_SUBSTITUTE; - } + $this->htmlspecialcharsFlags = $this->htmlspecialcharsFlags | ENT_HTML401 | ENT_SUBSTITUTE; } /** - * @param PHP_CodeCoverage_Report_Node_File $node - * @param string $file + * @param FileNode $node + * @param string $file */ - public function render(PHP_CodeCoverage_Report_Node_File $node, $file) + public function render(FileNode $node, $file) { - $template = new Text_Template($this->templatePath . 'file.html', '{{', '}}'); + $template = new \Text_Template($this->templatePath . 'file.html', '{{', '}}'); $template->setVar( - array( + [ 'items' => $this->renderItems($node), 'lines' => $this->renderSource($node) - ) + ] ); $this->setCommonTemplateVariables($template, $node); @@ -89,14 +68,15 @@ public function render(PHP_CodeCoverage_Report_Node_File $node, $file) } /** - * @param PHP_CodeCoverage_Report_Node_File $node + * @param FileNode $node + * * @return string */ - protected function renderItems(PHP_CodeCoverage_Report_Node_File $node) + protected function renderItems(FileNode $node) { - $template = new Text_Template($this->templatePath . 'file_item.html', '{{', '}}'); + $template = new \Text_Template($this->templatePath . 'file_item.html', '{{', '}}'); - $methodItemTemplate = new Text_Template( + $methodItemTemplate = new \Text_Template( $this->templatePath . 'method_item.html', '{{', '}}' @@ -104,7 +84,7 @@ protected function renderItems(PHP_CodeCoverage_Report_Node_File $node) $items = $this->renderItemTemplate( $template, - array( + [ 'name' => 'Total', 'numClasses' => $node->getNumClassesAndTraits(), 'numTestedClasses' => $node->getNumTestedClassesAndTraits(), @@ -119,7 +99,7 @@ protected function renderItems(PHP_CodeCoverage_Report_Node_File $node) 'testedClassesPercent' => $node->getTestedClassesAndTraitsPercent(false), 'testedClassesPercentAsString' => $node->getTestedClassesAndTraitsPercent(), 'crap' => 'CRAP' - ) + ] ); $items .= $this->renderFunctionItems( @@ -143,12 +123,13 @@ protected function renderItems(PHP_CodeCoverage_Report_Node_File $node) } /** - * @param array $items - * @param Text_Template $template - * @param Text_Template $methodItemTemplate + * @param array $items + * @param \Text_Template $template + * @param \Text_Template $methodItemTemplate + * * @return string */ - protected function renderTraitOrClassItems(array $items, Text_Template $template, Text_Template $methodItemTemplate) + protected function renderTraitOrClassItems(array $items, \Text_Template $template, \Text_Template $methodItemTemplate) { if (empty($items)) { return ''; @@ -168,46 +149,46 @@ protected function renderTraitOrClassItems(array $items, Text_Template $template $buffer .= $this->renderItemTemplate( $template, - array( + [ 'name' => $name, 'numClasses' => 1, 'numTestedClasses' => $numTestedMethods == $numMethods ? 1 : 0, 'numMethods' => $numMethods, 'numTestedMethods' => $numTestedMethods, - 'linesExecutedPercent' => PHP_CodeCoverage_Util::percent( + 'linesExecutedPercent' => Util::percent( $item['executedLines'], $item['executableLines'], false ), - 'linesExecutedPercentAsString' => PHP_CodeCoverage_Util::percent( + 'linesExecutedPercentAsString' => Util::percent( $item['executedLines'], $item['executableLines'], true ), 'numExecutedLines' => $item['executedLines'], 'numExecutableLines' => $item['executableLines'], - 'testedMethodsPercent' => PHP_CodeCoverage_Util::percent( + 'testedMethodsPercent' => Util::percent( $numTestedMethods, $numMethods, false ), - 'testedMethodsPercentAsString' => PHP_CodeCoverage_Util::percent( + 'testedMethodsPercentAsString' => Util::percent( $numTestedMethods, $numMethods, true ), - 'testedClassesPercent' => PHP_CodeCoverage_Util::percent( + 'testedClassesPercent' => Util::percent( $numTestedMethods == $numMethods ? 1 : 0, 1, false ), - 'testedClassesPercentAsString' => PHP_CodeCoverage_Util::percent( + 'testedClassesPercentAsString' => Util::percent( $numTestedMethods == $numMethods ? 1 : 0, 1, true ), 'crap' => $item['crap'] - ) + ] ); foreach ($item['methods'] as $method) { @@ -223,11 +204,12 @@ protected function renderTraitOrClassItems(array $items, Text_Template $template } /** - * @param array $functions - * @param Text_Template $template + * @param array $functions + * @param \Text_Template $template + * * @return string */ - protected function renderFunctionItems(array $functions, Text_Template $template) + protected function renderFunctionItems(array $functions, \Text_Template $template) { if (empty($functions)) { return ''; @@ -246,16 +228,17 @@ protected function renderFunctionItems(array $functions, Text_Template $template } /** - * @param Text_Template $template + * @param \Text_Template $template + * * @return string */ - protected function renderFunctionOrMethodItem(Text_Template $template, array $item, $indent = '') + protected function renderFunctionOrMethodItem(\Text_Template $template, array $item, $indent = '') { $numTestedItems = $item['executedLines'] == $item['executableLines'] ? 1 : 0; return $this->renderItemTemplate( $template, - array( + [ 'name' => sprintf( '%s%s', $indent, @@ -265,38 +248,39 @@ protected function renderFunctionOrMethodItem(Text_Template $template, array $it ), 'numMethods' => 1, 'numTestedMethods' => $numTestedItems, - 'linesExecutedPercent' => PHP_CodeCoverage_Util::percent( + 'linesExecutedPercent' => Util::percent( $item['executedLines'], $item['executableLines'], false ), - 'linesExecutedPercentAsString' => PHP_CodeCoverage_Util::percent( + 'linesExecutedPercentAsString' => Util::percent( $item['executedLines'], $item['executableLines'], true ), 'numExecutedLines' => $item['executedLines'], 'numExecutableLines' => $item['executableLines'], - 'testedMethodsPercent' => PHP_CodeCoverage_Util::percent( + 'testedMethodsPercent' => Util::percent( $numTestedItems, 1, false ), - 'testedMethodsPercentAsString' => PHP_CodeCoverage_Util::percent( + 'testedMethodsPercentAsString' => Util::percent( $numTestedItems, 1, true ), 'crap' => $item['crap'] - ) + ] ); } /** - * @param PHP_CodeCoverage_Report_Node_File $node + * @param FileNode $node + * * @return string */ - protected function renderSource(PHP_CodeCoverage_Report_Node_File $node) + protected function renderSource(FileNode $node) { $coverageData = $node->getCoverageData(); $testData = $node->getTestData(); @@ -406,14 +390,15 @@ protected function renderSource(PHP_CodeCoverage_Report_Node_File $node) } /** - * @param string $file + * @param string $file + * * @return array */ protected function loadFile($file) { $buffer = file_get_contents($file); $tokens = token_get_all($buffer); - $result = array(''); + $result = ['']; $i = 0; $stringFlag = false; $fileEndsWithNewLine = substr($buffer, -1) == "\n"; @@ -439,11 +424,11 @@ protected function loadFile($file) continue; } - list ($token, $value) = $token; + list($token, $value) = $token; $value = str_replace( - array("\t", ' '), - array('    ', ' '), + ["\t", ' '], + ['    ', ' '], htmlspecialchars($value, $this->htmlspecialcharsFlags) ); diff --git a/src/CodeCoverage/Report/HTML/Renderer/Template/coverage_bar.html.dist b/src/Report/Html/Renderer/Template/coverage_bar.html.dist similarity index 100% rename from src/CodeCoverage/Report/HTML/Renderer/Template/coverage_bar.html.dist rename to src/Report/Html/Renderer/Template/coverage_bar.html.dist diff --git a/src/Report/Html/Renderer/Template/css/bootstrap.min.css b/src/Report/Html/Renderer/Template/css/bootstrap.min.css new file mode 100644 index 000000000..670b1f5f0 --- /dev/null +++ b/src/Report/Html/Renderer/Template/css/bootstrap.min.css @@ -0,0 +1,5 @@ +/*! + * Bootstrap v3.3.4 (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + *//*! normalize.css v3.0.2 | MIT License | git.io/normalize */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}select{background:#fff!important}.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:"\2a"} .glyphicon-plus:before{content:"\2b"} .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:thin dotted;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:hover{color:#286090} .text-success{color:#3c763d} a.text-success:hover{color:#2b542c} .text-info{color:#31708f} a.text-info:hover{color:#245269} .text-warning{color:#8a6d3b} a.text-warning:hover{color:#66512c} .text-danger{color:#a94442} a.text-danger:hover{color:#843534} .bg-primary{color:#fff;background-color:#337ab7} a.bg-primary:hover{background-color:#286090} .bg-success{background-color:#dff0d8} a.bg-success:hover{background-color:#c1e2b3} .bg-info{background-color:#d9edf7} a.bg-info:hover{background-color:#afd9ee} .bg-warning{background-color:#fcf8e3} a.bg-warning:hover{background-color:#f7ecb5} .bg-danger{background-color:#f2dede} 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:thin dotted;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[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],input[type=time],input[type=datetime-local],input[type=month]{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} select.form-group-sm .form-control{height:30px;line-height:30px} select[multiple].form-group-sm .form-control,textarea.form-group-sm .form-control{height:auto} .form-group-sm .form-control-static{height:30px;min-height:32px;padding:5px 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} select.form-group-lg .form-control{height:46px;line-height:46px} select[multiple].form-group-lg .form-control,textarea.form-group-lg .form-control{height:auto} .form-group-lg .form-control-static{height:46px;min-height:38px;padding:10px 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} .input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px} .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:14.33px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px}} .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:thin dotted;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{pointer-events:none;cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65} .btn-default{color:#333;background-color:#fff;border-color:#ccc} .btn-default.active,.btn-default.focus,.btn-default:active,.btn-default:focus,.btn-default:hover,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad} .btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none} .btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,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.active,.btn-primary.focus,.btn-primary:active,.btn-primary:focus,.btn-primary:hover,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74} .btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none} .btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,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.active,.btn-success.focus,.btn-success:active,.btn-success:focus,.btn-success:hover,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439} .btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none} .btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,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.active,.btn-info.focus,.btn-info:active,.btn-info:focus,.btn-info:hover,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc} .btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none} .btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,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.active,.btn-warning.focus,.btn-warning:active,.btn-warning:focus,.btn-warning:hover,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512} .btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none} .btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,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.active,.btn-danger.focus,.btn-danger:active,.btn-danger:focus,.btn-danger:hover,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925} .btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none} .btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,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-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 solid} .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-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-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-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-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{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{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:2;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} .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} .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:baseline;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:30px 15px;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{border-radius:6px} .jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding:48px 0}.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-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{color:#555} a.list-group-item .list-group-item-heading{color:#333} a.list-group-item:focus,a.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5} .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{color:#3c763d} a.list-group-item-success .list-group-item-heading{color:inherit} a.list-group-item-success:focus,a.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{color:#fff;background-color:#3c763d;border-color:#3c763d} .list-group-item-info{color:#31708f;background-color:#d9edf7} a.list-group-item-info{color:#31708f} a.list-group-item-info .list-group-item-heading{color:inherit} a.list-group-item-info:focus,a.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{color:#fff;background-color:#31708f;border-color:#31708f} .list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3} a.list-group-item-warning{color:#8a6d3b} a.list-group-item-warning .list-group-item-heading{color:inherit} a.list-group-item-warning:focus,a.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{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b} .list-group-item-danger{color:#a94442;background-color:#f2dede} a.list-group-item-danger{color:#a94442} a.list-group-item-danger .list-group-item-heading{color:inherit} a.list-group-item-danger:focus,a.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{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-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{min-height:16.43px;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-weight:400;line-height:1.4;filter:alpha(opacity=0);opacity:0} .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;text-decoration:none;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-weight:400;line-height:1.42857143;text-align:left;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)} .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:1000;perspective:1000}.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);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} .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;margin-top:-10px;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:-15px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-15px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-15px}.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,.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,.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}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}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}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}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}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}} \ No newline at end of file diff --git a/src/CodeCoverage/Report/HTML/Renderer/Template/css/nv.d3.min.css b/src/Report/Html/Renderer/Template/css/nv.d3.min.css similarity index 100% rename from src/CodeCoverage/Report/HTML/Renderer/Template/css/nv.d3.min.css rename to src/Report/Html/Renderer/Template/css/nv.d3.min.css diff --git a/src/CodeCoverage/Report/HTML/Renderer/Template/css/style.css b/src/Report/Html/Renderer/Template/css/style.css similarity index 100% rename from src/CodeCoverage/Report/HTML/Renderer/Template/css/style.css rename to src/Report/Html/Renderer/Template/css/style.css diff --git a/src/CodeCoverage/Report/HTML/Renderer/Template/dashboard.html.dist b/src/Report/Html/Renderer/Template/dashboard.html.dist similarity index 97% rename from src/CodeCoverage/Report/HTML/Renderer/Template/dashboard.html.dist rename to src/Report/Html/Renderer/Template/dashboard.html.dist index ed1898867..06fc0052b 100644 --- a/src/CodeCoverage/Report/HTML/Renderer/Template/dashboard.html.dist +++ b/src/Report/Html/Renderer/Template/dashboard.html.dist @@ -134,7 +134,7 @@ diff --git a/src/CodeCoverage/Report/HTML/Renderer/Template/directory.html.dist b/src/Report/Html/Renderer/Template/directory.html.dist similarity index 90% rename from src/CodeCoverage/Report/HTML/Renderer/Template/directory.html.dist rename to src/Report/Html/Renderer/Template/directory.html.dist index efe743f51..60c41070f 100644 --- a/src/CodeCoverage/Report/HTML/Renderer/Template/directory.html.dist +++ b/src/Report/Html/Renderer/Template/directory.html.dist @@ -50,7 +50,7 @@ High: {{high_lower_bound}}% to 100%

    - Generated by PHP_CodeCoverage {{version}} using {{runtime_name}} {{runtime_version}}{{generator}} at {{date}}. + Generated by php-code-coverage {{version}} using {{runtime_name}} {{runtime_version}}{{generator}} at {{date}}.

    diff --git a/src/CodeCoverage/Report/HTML/Renderer/Template/directory_item.html.dist b/src/Report/Html/Renderer/Template/directory_item.html.dist similarity index 100% rename from src/CodeCoverage/Report/HTML/Renderer/Template/directory_item.html.dist rename to src/Report/Html/Renderer/Template/directory_item.html.dist diff --git a/src/CodeCoverage/Report/HTML/Renderer/Template/file.html.dist b/src/Report/Html/Renderer/Template/file.html.dist similarity index 93% rename from src/CodeCoverage/Report/HTML/Renderer/Template/file.html.dist rename to src/Report/Html/Renderer/Template/file.html.dist index 59a068430..93039e3bd 100644 --- a/src/CodeCoverage/Report/HTML/Renderer/Template/file.html.dist +++ b/src/Report/Html/Renderer/Template/file.html.dist @@ -55,7 +55,7 @@ Dead Code

    - Generated by PHP_CodeCoverage {{version}} using {{runtime_name}} {{runtime_version}}{{generator}} at {{date}}. + Generated by php-code-coverage {{version}} using {{runtime_name}} {{runtime_version}}{{generator}} at {{date}}.

    diff --git a/src/CodeCoverage/Report/HTML/Renderer/Template/file_item.html.dist b/src/Report/Html/Renderer/Template/file_item.html.dist similarity index 100% rename from src/CodeCoverage/Report/HTML/Renderer/Template/file_item.html.dist rename to src/Report/Html/Renderer/Template/file_item.html.dist diff --git a/src/CodeCoverage/Report/HTML/Renderer/Template/fonts/glyphicons-halflings-regular.eot b/src/Report/Html/Renderer/Template/fonts/glyphicons-halflings-regular.eot similarity index 100% rename from src/CodeCoverage/Report/HTML/Renderer/Template/fonts/glyphicons-halflings-regular.eot rename to src/Report/Html/Renderer/Template/fonts/glyphicons-halflings-regular.eot diff --git a/src/CodeCoverage/Report/HTML/Renderer/Template/fonts/glyphicons-halflings-regular.svg b/src/Report/Html/Renderer/Template/fonts/glyphicons-halflings-regular.svg similarity index 100% rename from src/CodeCoverage/Report/HTML/Renderer/Template/fonts/glyphicons-halflings-regular.svg rename to src/Report/Html/Renderer/Template/fonts/glyphicons-halflings-regular.svg diff --git a/src/CodeCoverage/Report/HTML/Renderer/Template/fonts/glyphicons-halflings-regular.ttf b/src/Report/Html/Renderer/Template/fonts/glyphicons-halflings-regular.ttf similarity index 100% rename from src/CodeCoverage/Report/HTML/Renderer/Template/fonts/glyphicons-halflings-regular.ttf rename to src/Report/Html/Renderer/Template/fonts/glyphicons-halflings-regular.ttf diff --git a/src/CodeCoverage/Report/HTML/Renderer/Template/fonts/glyphicons-halflings-regular.woff b/src/Report/Html/Renderer/Template/fonts/glyphicons-halflings-regular.woff similarity index 100% rename from src/CodeCoverage/Report/HTML/Renderer/Template/fonts/glyphicons-halflings-regular.woff rename to src/Report/Html/Renderer/Template/fonts/glyphicons-halflings-regular.woff diff --git a/src/CodeCoverage/Report/HTML/Renderer/Template/fonts/glyphicons-halflings-regular.woff2 b/src/Report/Html/Renderer/Template/fonts/glyphicons-halflings-regular.woff2 similarity index 100% rename from src/CodeCoverage/Report/HTML/Renderer/Template/fonts/glyphicons-halflings-regular.woff2 rename to src/Report/Html/Renderer/Template/fonts/glyphicons-halflings-regular.woff2 diff --git a/src/CodeCoverage/Report/HTML/Renderer/Template/js/bootstrap.min.js b/src/Report/Html/Renderer/Template/js/bootstrap.min.js similarity index 100% rename from src/CodeCoverage/Report/HTML/Renderer/Template/js/bootstrap.min.js rename to src/Report/Html/Renderer/Template/js/bootstrap.min.js diff --git a/src/CodeCoverage/Report/HTML/Renderer/Template/js/d3.min.js b/src/Report/Html/Renderer/Template/js/d3.min.js similarity index 100% rename from src/CodeCoverage/Report/HTML/Renderer/Template/js/d3.min.js rename to src/Report/Html/Renderer/Template/js/d3.min.js diff --git a/src/CodeCoverage/Report/HTML/Renderer/Template/js/holder.min.js b/src/Report/Html/Renderer/Template/js/holder.min.js similarity index 100% rename from src/CodeCoverage/Report/HTML/Renderer/Template/js/holder.min.js rename to src/Report/Html/Renderer/Template/js/holder.min.js diff --git a/src/CodeCoverage/Report/HTML/Renderer/Template/js/html5shiv.min.js b/src/Report/Html/Renderer/Template/js/html5shiv.min.js similarity index 100% rename from src/CodeCoverage/Report/HTML/Renderer/Template/js/html5shiv.min.js rename to src/Report/Html/Renderer/Template/js/html5shiv.min.js diff --git a/src/CodeCoverage/Report/HTML/Renderer/Template/js/jquery.min.js b/src/Report/Html/Renderer/Template/js/jquery.min.js similarity index 100% rename from src/CodeCoverage/Report/HTML/Renderer/Template/js/jquery.min.js rename to src/Report/Html/Renderer/Template/js/jquery.min.js diff --git a/src/CodeCoverage/Report/HTML/Renderer/Template/js/nv.d3.min.js b/src/Report/Html/Renderer/Template/js/nv.d3.min.js similarity index 100% rename from src/CodeCoverage/Report/HTML/Renderer/Template/js/nv.d3.min.js rename to src/Report/Html/Renderer/Template/js/nv.d3.min.js diff --git a/src/CodeCoverage/Report/HTML/Renderer/Template/js/respond.min.js b/src/Report/Html/Renderer/Template/js/respond.min.js similarity index 100% rename from src/CodeCoverage/Report/HTML/Renderer/Template/js/respond.min.js rename to src/Report/Html/Renderer/Template/js/respond.min.js diff --git a/src/CodeCoverage/Report/HTML/Renderer/Template/method_item.html.dist b/src/Report/Html/Renderer/Template/method_item.html.dist similarity index 100% rename from src/CodeCoverage/Report/HTML/Renderer/Template/method_item.html.dist rename to src/Report/Html/Renderer/Template/method_item.html.dist diff --git a/src/CodeCoverage/Report/PHP.php b/src/Report/PHP.php similarity index 62% rename from src/CodeCoverage/Report/PHP.php rename to src/Report/PHP.php index f4e5a0f95..0adb0a383 100644 --- a/src/CodeCoverage/Report/PHP.php +++ b/src/Report/PHP.php @@ -1,6 +1,6 @@ * @@ -8,36 +8,37 @@ * file that was distributed with this source code. */ +namespace SebastianBergmann\CodeCoverage\Report; + +use SebastianBergmann\CodeCoverage\CodeCoverage; + /** - * Uses var_export() to write a PHP_CodeCoverage object to a file. - * - * @since Class available since Release 1.1.0 + * Uses var_export() to write a SebastianBergmann\CodeCoverage\CodeCoverage object to a file. */ -class PHP_CodeCoverage_Report_PHP +class PHP { /** - * @param PHP_CodeCoverage $coverage - * @param string $target + * @param CodeCoverage $coverage + * @param string $target + * * @return string */ - public function process(PHP_CodeCoverage $coverage, $target = null) + public function process(CodeCoverage $coverage, $target = null) { $filter = $coverage->filter(); $output = sprintf( 'setData(%s); $coverage->setTests(%s); $filter = $coverage->filter(); -$filter->setBlacklistedFiles(%s); $filter->setWhitelistedFiles(%s); return $coverage;', var_export($coverage->getData(true), 1), var_export($coverage->getTests(), 1), - var_export($filter->getBlacklistedFiles(), 1), var_export($filter->getWhitelistedFiles(), 1) ); diff --git a/src/CodeCoverage/Report/Text.php b/src/Report/Text.php similarity index 85% rename from src/CodeCoverage/Report/Text.php rename to src/Report/Text.php index 7dc254521..08ae0ea26 100644 --- a/src/CodeCoverage/Report/Text.php +++ b/src/Report/Text.php @@ -1,6 +1,6 @@ * @@ -8,28 +8,32 @@ * file that was distributed with this source code. */ +namespace SebastianBergmann\CodeCoverage\Report; + +use SebastianBergmann\CodeCoverage\CodeCoverage; +use SebastianBergmann\CodeCoverage\Node\File; +use SebastianBergmann\CodeCoverage\Util; + /** - * Generates human readable output from an PHP_CodeCoverage object. + * Generates human readable output from a code coverage object. * * The output gets put into a text file our written to the CLI. - * - * @since Class available since Release 1.1.0 */ -class PHP_CodeCoverage_Report_Text +class Text { - protected $lowUpperBound; - protected $highLowerBound; - protected $showUncoveredFiles; - protected $showOnlySummary; + private $lowUpperBound; + private $highLowerBound; + private $showUncoveredFiles; + private $showOnlySummary; - protected $colors = array( + private $colors = [ 'green' => "\x1b[30;42m", 'yellow' => "\x1b[30;43m", 'red' => "\x1b[37;41m", 'header' => "\x1b[1;37;40m", 'reset' => "\x1b[0m", 'eol' => "\x1b[2K", - ); + ]; public function __construct($lowUpperBound, $highLowerBound, $showUncoveredFiles, $showOnlySummary) { @@ -40,24 +44,25 @@ public function __construct($lowUpperBound, $highLowerBound, $showUncoveredFiles } /** - * @param PHP_CodeCoverage $coverage - * @param bool $showColors + * @param CodeCoverage $coverage + * @param bool $showColors + * * @return string */ - public function process(PHP_CodeCoverage $coverage, $showColors = false) + public function process(CodeCoverage $coverage, $showColors = false) { $output = PHP_EOL . PHP_EOL; $report = $coverage->getReport(); unset($coverage); - $colors = array( + $colors = [ 'header' => '', 'classes' => '', 'methods' => '', 'lines' => '', 'reset' => '', 'eol' => '' - ); + ]; if ($showColors) { $colors['classes'] = $this->getCoverageColor( @@ -79,7 +84,7 @@ public function process(PHP_CodeCoverage $coverage, $showColors = false) $classes = sprintf( ' Classes: %6s (%d/%d)', - PHP_CodeCoverage_Util::percent( + Util::percent( $report->getNumTestedClassesAndTraits(), $report->getNumClassesAndTraits(), true @@ -90,7 +95,7 @@ public function process(PHP_CodeCoverage $coverage, $showColors = false) $methods = sprintf( ' Methods: %6s (%d/%d)', - PHP_CodeCoverage_Util::percent( + Util::percent( $report->getNumTestedMethods(), $report->getNumMethods(), true @@ -101,7 +106,7 @@ public function process(PHP_CodeCoverage $coverage, $showColors = false) $lines = sprintf( ' Lines: %6s (%d/%d)', - PHP_CodeCoverage_Util::percent( + Util::percent( $report->getNumExecutedLines(), $report->getNumExecutableLines(), true @@ -110,7 +115,7 @@ public function process(PHP_CodeCoverage $coverage, $showColors = false) $report->getNumExecutableLines() ); - $padding = max(array_map('strlen', array($classes, $methods, $lines))); + $padding = max(array_map('strlen', [$classes, $methods, $lines])); if ($this->showOnlySummary) { $title = 'Code Coverage Report Summary:'; @@ -135,14 +140,14 @@ public function process(PHP_CodeCoverage $coverage, $showColors = false) return $output . PHP_EOL; } - $classCoverage = array(); + $classCoverage = []; foreach ($report as $item) { - if (!$item instanceof PHP_CodeCoverage_Report_Node_File) { + if (!$item instanceof File) { continue; } - $classes = $item->getClassesAndTraits(); + $classes = $item->getClassesAndTraits(); foreach ($classes as $className => $class) { $classStatements = 0; @@ -171,14 +176,14 @@ public function process(PHP_CodeCoverage $coverage, $showColors = false) $namespace = ''; } - $classCoverage[$namespace . $className] = array( + $classCoverage[$namespace . $className] = [ 'namespace' => $namespace, 'className ' => $className, 'methodsCovered' => $coveredMethods, 'methodCount' => $classMethods, 'statementsCovered' => $coveredClassStatements, 'statementCount' => $classStatements, - ); + ]; } } @@ -209,7 +214,7 @@ public function process(PHP_CodeCoverage $coverage, $showColors = false) protected function getCoverageColor($numberOfCoveredElements, $totalNumberOfElements) { - $coverage = PHP_CodeCoverage_Util::percent( + $coverage = Util::percent( $numberOfCoveredElements, $totalNumberOfElements ); @@ -223,11 +228,11 @@ protected function getCoverageColor($numberOfCoveredElements, $totalNumberOfElem return $this->colors['red']; } - protected function printCoverageCounts($numberOfCoveredElements, $totalNumberOfElements, $presicion) + protected function printCoverageCounts($numberOfCoveredElements, $totalNumberOfElements, $precision) { - $format = '%' . $presicion . 's'; + $format = '%' . $precision . 's'; - return PHP_CodeCoverage_Util::percent( + return Util::percent( $numberOfCoveredElements, $totalNumberOfElements, true, diff --git a/src/CodeCoverage/Report/XML/File/Coverage.php b/src/Report/Xml/Coverage.php similarity index 74% rename from src/CodeCoverage/Report/XML/File/Coverage.php rename to src/Report/Xml/Coverage.php index 29a4e2ba8..1a65fbe2e 100644 --- a/src/CodeCoverage/Report/XML/File/Coverage.php +++ b/src/Report/Xml/Coverage.php @@ -1,6 +1,6 @@ * @@ -8,18 +8,19 @@ * file that was distributed with this source code. */ -/** - * @since Class available since Release 2.0.0 - */ -class PHP_CodeCoverage_Report_XML_File_Coverage +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +use SebastianBergmann\CodeCoverage\RuntimeException; + +class Coverage { /** - * @var XMLWriter + * @var \XMLWriter */ private $writer; /** - * @var DOMElement + * @var \DOMElement */ private $contextNode; @@ -28,11 +29,11 @@ class PHP_CodeCoverage_Report_XML_File_Coverage */ private $finalized = false; - public function __construct(DOMElement $context, $line) + public function __construct(\DOMElement $context, $line) { $this->contextNode = $context; - $this->writer = new XMLWriter(); + $this->writer = new \XMLWriter; $this->writer->openMemory(); $this->writer->startElementNs(null, $context->nodeName, 'http://schema.phpunit.de/coverage/1.0'); $this->writer->writeAttribute('nr', $line); @@ -41,7 +42,7 @@ public function __construct(DOMElement $context, $line) public function addTest($test) { if ($this->finalized) { - throw new PHP_CodeCoverage_Exception('Coverage Report already finalized'); + throw new RuntimeException('Coverage Report already finalized'); } $this->writer->startElement('covered'); diff --git a/src/Report/Xml/Directory.php b/src/Report/Xml/Directory.php new file mode 100644 index 000000000..71d5a40ca --- /dev/null +++ b/src/Report/Xml/Directory.php @@ -0,0 +1,15 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +class Directory extends Node +{ +} diff --git a/src/CodeCoverage/Report/XML.php b/src/Report/Xml/Facade.php similarity index 75% rename from src/CodeCoverage/Report/XML.php rename to src/Report/Xml/Facade.php index 5177b2bda..34c8ad52f 100644 --- a/src/CodeCoverage/Report/XML.php +++ b/src/Report/Xml/Facade.php @@ -1,6 +1,6 @@ * @@ -8,10 +8,15 @@ * file that was distributed with this source code. */ -/** - * @since Class available since Release 2.0.0 - */ -class PHP_CodeCoverage_Report_XML +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +use SebastianBergmann\CodeCoverage\CodeCoverage; +use SebastianBergmann\CodeCoverage\Node\AbstractNode; +use SebastianBergmann\CodeCoverage\Node\Directory as DirectoryNode; +use SebastianBergmann\CodeCoverage\Node\File as FileNode; +use SebastianBergmann\CodeCoverage\RuntimeException; + +class Facade { /** * @var string @@ -19,11 +24,17 @@ class PHP_CodeCoverage_Report_XML private $target; /** - * @var PHP_CodeCoverage_Report_XML_Project + * @var Project */ private $project; - public function process(PHP_CodeCoverage $coverage, $target) + /** + * @param CodeCoverage $coverage + * @param string $target + * + * @throws RuntimeException + */ + public function process(CodeCoverage $coverage, $target) { if (substr($target, -1, 1) != DIRECTORY_SEPARATOR) { $target .= DIRECTORY_SEPARATOR; @@ -34,7 +45,7 @@ public function process(PHP_CodeCoverage $coverage, $target) $report = $coverage->getReport(); - $this->project = new PHP_CodeCoverage_Report_XML_Project( + $this->project = new Project( $coverage->getReport()->getName() ); @@ -47,51 +58,54 @@ public function process(PHP_CodeCoverage $coverage, $target) $index->save($target . '/index.xml'); } - private function initTargetDirectory($dir) + /** + * @param string $directory + */ + private function initTargetDirectory($directory) { - if (file_exists($dir)) { - if (!is_dir($dir)) { - throw new PHP_CodeCoverage_Exception( - "'$dir' exists but is not a directory." + if (file_exists($directory)) { + if (!is_dir($directory)) { + throw new RuntimeException( + "'$directory' exists but is not a directory." ); } - if (!is_writable($dir)) { - throw new PHP_CodeCoverage_Exception( - "'$dir' exists but is not writable." + if (!is_writable($directory)) { + throw new RuntimeException( + "'$directory' exists but is not writable." ); } - } elseif (!@mkdir($dir, 0777, true)) { - throw new PHP_CodeCoverage_Exception( - "'$dir' could not be created." + } elseif (!@mkdir($directory, 0777, true)) { + throw new RuntimeException( + "'$directory' could not be created." ); } } - private function processDirectory(PHP_CodeCoverage_Report_Node_Directory $directory, PHP_CodeCoverage_Report_XML_Node $context) + private function processDirectory(DirectoryNode $directory, Node $context) { $dirObject = $context->addDirectory($directory->getName()); $this->setTotals($directory, $dirObject->getTotals()); foreach ($directory as $node) { - if ($node instanceof PHP_CodeCoverage_Report_Node_Directory) { + if ($node instanceof DirectoryNode) { $this->processDirectory($node, $dirObject); continue; } - if ($node instanceof PHP_CodeCoverage_Report_Node_File) { + if ($node instanceof FileNode) { $this->processFile($node, $dirObject); continue; } - throw new PHP_CodeCoverage_Exception( + throw new RuntimeException( 'Unknown node type for XML report' ); } } - private function processFile(PHP_CodeCoverage_Report_Node_File $file, PHP_CodeCoverage_Report_XML_Directory $context) + private function processFile(FileNode $file, Directory $context) { $fileObject = $context->addFile( $file->getName(), @@ -100,9 +114,7 @@ private function processFile(PHP_CodeCoverage_Report_Node_File $file, PHP_CodeCo $this->setTotals($file, $fileObject->getTotals()); - $fileReport = new PHP_CodeCoverage_Report_XML_File_Report( - $file->getName() - ); + $fileReport = new Report($file->getName()); $this->setTotals($file, $fileReport->getTotals()); @@ -138,7 +150,7 @@ private function processFile(PHP_CodeCoverage_Report_Node_File $file, PHP_CodeCo $fileDom->save($this->target . $file->getId() . '.xml'); } - private function processUnit($unit, PHP_CodeCoverage_Report_XML_File_Report $report) + private function processUnit($unit, Report $report) { if (isset($unit['className'])) { $unitObject = $report->getClassObject($unit['className']); @@ -176,7 +188,7 @@ private function processUnit($unit, PHP_CodeCoverage_Report_XML_File_Report $rep } } - private function processFunction($function, PHP_CodeCoverage_Report_XML_File_Report $report) + private function processFunction($function, Report $report) { $functionObject = $report->getFunctionObject($function['functionName']); @@ -199,7 +211,7 @@ private function processTests(array $tests) } } - private function setTotals(PHP_CodeCoverage_Report_Node $node, PHP_CodeCoverage_Report_XML_Totals $totals) + private function setTotals(AbstractNode $node, Totals $totals) { $loc = $node->getLinesOfCode(); diff --git a/src/CodeCoverage/Report/XML/File.php b/src/Report/Xml/File.php similarity index 78% rename from src/CodeCoverage/Report/XML/File.php rename to src/Report/Xml/File.php index 3c72bab20..5d6d71dec 100644 --- a/src/CodeCoverage/Report/XML/File.php +++ b/src/Report/Xml/File.php @@ -1,6 +1,6 @@ * @@ -8,22 +8,21 @@ * file that was distributed with this source code. */ -/** - * @since Class available since Release 2.0.0 - */ -class PHP_CodeCoverage_Report_XML_File +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +class File { /** - * @var DOMDocument + * @var \DOMDocument */ protected $dom; /** - * @var DOMElement + * @var \DOMElement */ protected $contextNode; - public function __construct(DOMElement $context) + public function __construct(\DOMElement $context) { $this->dom = $context->ownerDocument; $this->contextNode = $context; @@ -42,7 +41,7 @@ public function getTotals() ); } - return new PHP_CodeCoverage_Report_XML_Totals($totalsContainer); + return new Totals($totalsContainer); } public function getLineCoverage($line) @@ -68,6 +67,6 @@ public function getLineCoverage($line) ) ); - return new PHP_CodeCoverage_Report_XML_File_Coverage($lineNode, $line); + return new Coverage($lineNode, $line); } } diff --git a/src/CodeCoverage/Report/XML/File/Method.php b/src/Report/Xml/Method.php similarity index 83% rename from src/CodeCoverage/Report/XML/File/Method.php rename to src/Report/Xml/Method.php index 917628fd1..10eb762fd 100644 --- a/src/CodeCoverage/Report/XML/File/Method.php +++ b/src/Report/Xml/Method.php @@ -1,6 +1,6 @@ * @@ -8,17 +8,16 @@ * file that was distributed with this source code. */ -/** - * @since Class available since Release 2.0.0 - */ -class PHP_CodeCoverage_Report_XML_File_Method +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +class Method { /** - * @var DOMElement + * @var \DOMElement */ private $contextNode; - public function __construct(DOMElement $context, $name) + public function __construct(\DOMElement $context, $name) { $this->contextNode = $context; diff --git a/src/CodeCoverage/Report/XML/Node.php b/src/Report/Xml/Node.php similarity index 76% rename from src/CodeCoverage/Report/XML/Node.php rename to src/Report/Xml/Node.php index 43dda57ce..43776f1d0 100644 --- a/src/CodeCoverage/Report/XML/Node.php +++ b/src/Report/Xml/Node.php @@ -1,6 +1,6 @@ * @@ -8,27 +8,26 @@ * file that was distributed with this source code. */ -/** - * @since Class available since Release 2.0.0 - */ -class PHP_CodeCoverage_Report_XML_Node +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +class Node { /** - * @var DOMDocument + * @var \DOMDocument */ private $dom; /** - * @var DOMElement + * @var \DOMElement */ private $contextNode; - public function __construct(DOMElement $context) + public function __construct(\DOMElement $context) { $this->setContextNode($context); } - protected function setContextNode(DOMElement $context) + protected function setContextNode(\DOMElement $context) { $this->dom = $context->ownerDocument; $this->contextNode = $context; @@ -57,7 +56,7 @@ public function getTotals() ); } - return new PHP_CodeCoverage_Report_XML_Totals($totalsContainer); + return new Totals($totalsContainer); } public function addDirectory($name) @@ -70,7 +69,7 @@ public function addDirectory($name) $dirNode->setAttribute('name', $name); $this->getContextNode()->appendChild($dirNode); - return new PHP_CodeCoverage_Report_XML_Directory($dirNode); + return new Directory($dirNode); } public function addFile($name, $href) @@ -84,6 +83,6 @@ public function addFile($name, $href) $fileNode->setAttribute('href', $href); $this->getContextNode()->appendChild($fileNode); - return new PHP_CodeCoverage_Report_XML_File($fileNode); + return new File($fileNode); } } diff --git a/src/CodeCoverage/Report/XML/Project.php b/src/Report/Xml/Project.php similarity index 82% rename from src/CodeCoverage/Report/XML/Project.php rename to src/Report/Xml/Project.php index b8dae04d1..17bf1e66e 100644 --- a/src/CodeCoverage/Report/XML/Project.php +++ b/src/Report/Xml/Project.php @@ -1,6 +1,6 @@ * @@ -8,10 +8,9 @@ * file that was distributed with this source code. */ -/** - * @since Class available since Release 2.0.0 - */ -class PHP_CodeCoverage_Report_XML_Project extends PHP_CodeCoverage_Report_XML_Node +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +class Project extends Node { public function __construct($name) { @@ -21,7 +20,7 @@ public function __construct($name) private function init() { - $dom = new DOMDocument; + $dom = new \DOMDocument; $dom->loadXML(''); $this->setContextNode( @@ -53,7 +52,7 @@ public function getTests() ); } - return new PHP_CodeCoverage_Report_XML_Tests($testsNode); + return new Tests($testsNode); } public function asDom() diff --git a/src/CodeCoverage/Report/XML/File/Report.php b/src/Report/Xml/Report.php similarity index 79% rename from src/CodeCoverage/Report/XML/File/Report.php rename to src/Report/Xml/Report.php index a6fe7ecf0..4c3e3e55b 100644 --- a/src/CodeCoverage/Report/XML/File/Report.php +++ b/src/Report/Xml/Report.php @@ -1,6 +1,6 @@ * @@ -8,14 +8,13 @@ * file that was distributed with this source code. */ -/** - * @since Class available since Release 2.0.0 - */ -class PHP_CodeCoverage_Report_XML_File_Report extends PHP_CodeCoverage_Report_XML_File +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +class Report extends File { public function __construct($name) { - $this->dom = new DOMDocument; + $this->dom = new \DOMDocument; $this->dom->loadXML(''); $this->contextNode = $this->dom->getElementsByTagNameNS( @@ -45,7 +44,7 @@ public function getFunctionObject($name) ) ); - return new PHP_CodeCoverage_Report_XML_File_Method($node, $name); + return new Method($node, $name); } public function getClassObject($name) @@ -67,6 +66,6 @@ private function getUnitObject($tagName, $name) ) ); - return new PHP_CodeCoverage_Report_XML_File_Unit($node, $name); + return new Unit($node, $name); } } diff --git a/src/CodeCoverage/Report/XML/Tests.php b/src/Report/Xml/Tests.php similarity index 84% rename from src/CodeCoverage/Report/XML/Tests.php rename to src/Report/Xml/Tests.php index bca884ea6..5ce20714a 100644 --- a/src/CodeCoverage/Report/XML/Tests.php +++ b/src/Report/Xml/Tests.php @@ -1,6 +1,6 @@ * @@ -8,23 +8,22 @@ * file that was distributed with this source code. */ -/** - * @since Class available since Release 2.0.0 - */ -class PHP_CodeCoverage_Report_XML_Tests +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +class Tests { private $contextNode; - private $codeMap = array( + private $codeMap = [ 0 => 'PASSED', // PHPUnit_Runner_BaseTestRunner::STATUS_PASSED 1 => 'SKIPPED', // PHPUnit_Runner_BaseTestRunner::STATUS_SKIPPED 2 => 'INCOMPLETE', // PHPUnit_Runner_BaseTestRunner::STATUS_INCOMPLETE 3 => 'FAILURE', // PHPUnit_Runner_BaseTestRunner::STATUS_FAILURE 4 => 'ERROR', // PHPUnit_Runner_BaseTestRunner::STATUS_ERROR 5 => 'RISKY' // PHPUnit_Runner_BaseTestRunner::STATUS_RISKY - ); + ]; - public function __construct(DOMElement $context) + public function __construct(\DOMElement $context) { $this->contextNode = $context; } @@ -37,10 +36,10 @@ public function addTest($test, array $result) 'test' ) ); + $node->setAttribute('name', $test); $node->setAttribute('size', $result['size']); $node->setAttribute('result', (int) $result['status']); $node->setAttribute('status', $this->codeMap[(int) $result['status']]); - } } diff --git a/src/CodeCoverage/Report/XML/Totals.php b/src/Report/Xml/Totals.php similarity index 82% rename from src/CodeCoverage/Report/XML/Totals.php rename to src/Report/Xml/Totals.php index d6073d95f..a1eaa9e3a 100644 --- a/src/CodeCoverage/Report/XML/Totals.php +++ b/src/Report/Xml/Totals.php @@ -1,6 +1,6 @@ * @@ -8,42 +8,43 @@ * file that was distributed with this source code. */ -/** - * @since Class available since Release 2.0.0 - */ -class PHP_CodeCoverage_Report_XML_Totals +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +use SebastianBergmann\CodeCoverage\Util; + +class Totals { /** - * @var DOMNode + * @var \DOMNode */ private $container; /** - * @var DOMElement + * @var \DOMElement */ private $linesNode; /** - * @var DOMElement + * @var \DOMElement */ private $methodsNode; /** - * @var DOMElement + * @var \DOMElement */ private $functionsNode; /** - * @var DOMElement + * @var \DOMElement */ private $classesNode; /** - * @var DOMElement + * @var \DOMElement */ private $traitsNode; - public function __construct(DOMElement $container) + public function __construct(\DOMElement $container) { $this->container = $container; $dom = $container->ownerDocument; @@ -94,7 +95,7 @@ public function setNumLines($loc, $cloc, $ncloc, $executable, $executed) $this->linesNode->setAttribute('executed', $executed); $this->linesNode->setAttribute( 'percent', - PHP_CodeCoverage_Util::percent($executed, $executable, true) + Util::percent($executed, $executable, true) ); } @@ -104,7 +105,7 @@ public function setNumClasses($count, $tested) $this->classesNode->setAttribute('tested', $tested); $this->classesNode->setAttribute( 'percent', - PHP_CodeCoverage_Util::percent($tested, $count, true) + Util::percent($tested, $count, true) ); } @@ -114,7 +115,7 @@ public function setNumTraits($count, $tested) $this->traitsNode->setAttribute('tested', $tested); $this->traitsNode->setAttribute( 'percent', - PHP_CodeCoverage_Util::percent($tested, $count, true) + Util::percent($tested, $count, true) ); } @@ -124,7 +125,7 @@ public function setNumMethods($count, $tested) $this->methodsNode->setAttribute('tested', $tested); $this->methodsNode->setAttribute( 'percent', - PHP_CodeCoverage_Util::percent($tested, $count, true) + Util::percent($tested, $count, true) ); } @@ -134,7 +135,7 @@ public function setNumFunctions($count, $tested) $this->functionsNode->setAttribute('tested', $tested); $this->functionsNode->setAttribute( 'percent', - PHP_CodeCoverage_Util::percent($tested, $count, true) + Util::percent($tested, $count, true) ); } } diff --git a/src/CodeCoverage/Report/XML/File/Unit.php b/src/Report/Xml/Unit.php similarity index 88% rename from src/CodeCoverage/Report/XML/File/Unit.php rename to src/Report/Xml/Unit.php index 769d9dabb..854f84483 100644 --- a/src/CodeCoverage/Report/XML/File/Unit.php +++ b/src/Report/Xml/Unit.php @@ -1,6 +1,6 @@ * @@ -8,17 +8,16 @@ * file that was distributed with this source code. */ -/** - * @since Class available since Release 2.0.0 - */ -class PHP_CodeCoverage_Report_XML_File_Unit +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +class Unit { /** - * @var DOMElement + * @var \DOMElement */ private $contextNode; - public function __construct(DOMElement $context, $name) + public function __construct(\DOMElement $context, $name) { $this->contextNode = $context; @@ -92,6 +91,6 @@ public function addMethod($name) ) ); - return new PHP_CodeCoverage_Report_XML_File_Method($node, $name); + return new Method($node, $name); } } diff --git a/src/CodeCoverage/Util.php b/src/Util.php similarity index 74% rename from src/CodeCoverage/Util.php rename to src/Util.php index eadb3c92c..89164f771 100644 --- a/src/CodeCoverage/Util.php +++ b/src/Util.php @@ -1,6 +1,6 @@ * @@ -8,17 +8,20 @@ * file that was distributed with this source code. */ +namespace SebastianBergmann\CodeCoverage; + /** * Utility methods. - * - * @since Class available since Release 1.0.0 */ -class PHP_CodeCoverage_Util +class Util { /** - * @param float $a - * @param float $b - * @return float ($a / $b) * 100 + * @param float $a + * @param float $b + * @param bool $asString + * @param bool $fixedWidth + * + * @return float|int|string */ public static function percent($a, $b, $asString = false, $fixedWidth = false) { diff --git a/tests/PHP/CodeCoverage/Report/FactoryTest.php b/tests/PHP/CodeCoverage/Report/FactoryTest.php deleted file mode 100644 index fc3e2511a..000000000 --- a/tests/PHP/CodeCoverage/Report/FactoryTest.php +++ /dev/null @@ -1,222 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -if (!defined('TEST_FILES_PATH')) { - define( - 'TEST_FILES_PATH', - dirname(dirname(dirname(dirname(__FILE__)))) . DIRECTORY_SEPARATOR . - '_files' . DIRECTORY_SEPARATOR - ); -} - -require_once TEST_FILES_PATH . '../TestCase.php'; - -/** - * Tests for the PHP_CodeCoverage_Report_Factory class. - * - * @since Class available since Release 1.1.0 - */ -class PHP_CodeCoverage_Report_FactoryTest extends PHP_CodeCoverage_TestCase -{ - protected $factory; - - protected function setUp() - { - $this->factory = new PHP_CodeCoverage_Report_Factory; - } - - public function testSomething() - { - $root = $this->getCoverageForBankAccount()->getReport(); - - $expectedPath = rtrim(TEST_FILES_PATH, DIRECTORY_SEPARATOR); - $this->assertEquals($expectedPath, $root->getName()); - $this->assertEquals($expectedPath, $root->getPath()); - $this->assertEquals(10, $root->getNumExecutableLines()); - $this->assertEquals(5, $root->getNumExecutedLines()); - $this->assertEquals(1, $root->getNumClasses()); - $this->assertEquals(0, $root->getNumTestedClasses()); - $this->assertEquals(4, $root->getNumMethods()); - $this->assertEquals(3, $root->getNumTestedMethods()); - $this->assertEquals('0.00%', $root->getTestedClassesPercent()); - $this->assertEquals('75.00%', $root->getTestedMethodsPercent()); - $this->assertEquals('50.00%', $root->getLineExecutedPercent()); - $this->assertEquals(0, $root->getNumFunctions()); - $this->assertEquals(0, $root->getNumTestedFunctions()); - $this->assertNull($root->getParent()); - $this->assertEquals(array(), $root->getDirectories()); - #$this->assertEquals(array(), $root->getFiles()); - #$this->assertEquals(array(), $root->getChildNodes()); - - $this->assertEquals( - array( - 'BankAccount' => array( - 'methods' => array( - 'getBalance' => array( - 'signature' => 'getBalance()', - 'startLine' => 6, - 'endLine' => 9, - 'executableLines' => 1, - 'executedLines' => 1, - 'ccn' => 1, - 'coverage' => 100, - 'crap' => '1', - 'link' => 'BankAccount.php.html#6', - 'methodName' => 'getBalance' - ), - 'setBalance' => array( - 'signature' => 'setBalance($balance)', - 'startLine' => 11, - 'endLine' => 18, - 'executableLines' => 5, - 'executedLines' => 0, - 'ccn' => 2, - 'coverage' => 0, - 'crap' => 6, - 'link' => 'BankAccount.php.html#11', - 'methodName' => 'setBalance' - ), - 'depositMoney' => array( - 'signature' => 'depositMoney($balance)', - 'startLine' => 20, - 'endLine' => 25, - 'executableLines' => 2, - 'executedLines' => 2, - 'ccn' => 1, - 'coverage' => 100, - 'crap' => '1', - 'link' => 'BankAccount.php.html#20', - 'methodName' => 'depositMoney' - ), - 'withdrawMoney' => array( - 'signature' => 'withdrawMoney($balance)', - 'startLine' => 27, - 'endLine' => 32, - 'executableLines' => 2, - 'executedLines' => 2, - 'ccn' => 1, - 'coverage' => 100, - 'crap' => '1', - 'link' => 'BankAccount.php.html#27', - 'methodName' => 'withdrawMoney' - ), - ), - 'startLine' => 2, - 'executableLines' => 10, - 'executedLines' => 5, - 'ccn' => 5, - 'coverage' => 50, - 'crap' => '8.12', - 'package' => array( - 'namespace' => '', - 'fullPackage' => '', - 'category' => '', - 'package' => '', - 'subpackage' => '' - ), - 'link' => 'BankAccount.php.html#2', - 'className' => 'BankAccount' - ) - ), - $root->getClasses() - ); - - $this->assertEquals(array(), $root->getFunctions()); - } - - /** - * @covers PHP_CodeCoverage_Report_Factory::buildDirectoryStructure - */ - public function testBuildDirectoryStructure() - { - $method = new ReflectionMethod( - 'PHP_CodeCoverage_Report_Factory', - 'buildDirectoryStructure' - ); - - $method->setAccessible(true); - - $this->assertEquals( - array( - 'src' => array( - 'Money.php/f' => array(), - 'MoneyBag.php/f' => array() - ) - ), - $method->invoke( - $this->factory, - array('src/Money.php' => array(), 'src/MoneyBag.php' => array()) - ) - ); - } - - /** - * @covers PHP_CodeCoverage_Report_Factory::reducePaths - * @dataProvider reducePathsProvider - */ - public function testReducePaths($reducedPaths, $commonPath, $paths) - { - $method = new ReflectionMethod( - 'PHP_CodeCoverage_Report_Factory', - 'reducePaths' - ); - - $method->setAccessible(true); - - $_commonPath = $method->invokeArgs($this->factory, array(&$paths)); - - $this->assertEquals($reducedPaths, $paths); - $this->assertEquals($commonPath, $_commonPath); - } - - public function reducePathsProvider() - { - return array( - array( - array( - 'Money.php' => array(), - 'MoneyBag.php' => array() - ), - '/home/sb/Money', - array( - '/home/sb/Money/Money.php' => array(), - '/home/sb/Money/MoneyBag.php' => array() - ) - ), - array( - array( - 'Money.php' => array() - ), - '/home/sb/Money/', - array( - '/home/sb/Money/Money.php' => array() - ) - ), - array( - array(), - '.', - array() - ), - array( - array( - 'Money.php' => array(), - 'MoneyBag.php' => array(), - 'Cash.phar/Cash.php' => array(), - ), - '/home/sb/Money', - array( - '/home/sb/Money/Money.php' => array(), - '/home/sb/Money/MoneyBag.php' => array(), - 'phar:///home/sb/Money/Cash.phar/Cash.php' => array(), - ), - ), - ); - } -} diff --git a/tests/PHP/CodeCoverage/UtilTest.php b/tests/PHP/CodeCoverage/UtilTest.php deleted file mode 100644 index 0b4caea97..000000000 --- a/tests/PHP/CodeCoverage/UtilTest.php +++ /dev/null @@ -1,30 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/** - * Tests for the PHP_CodeCoverage_Util class. - * - * @since Class available since Release 1.0.0 - */ -class PHP_CodeCoverage_UtilTest extends PHPUnit_Framework_TestCase -{ - /** - * @covers PHP_CodeCoverage_Util::percent - */ - public function testPercent() - { - $this->assertEquals(100, PHP_CodeCoverage_Util::percent(100, 0)); - $this->assertEquals(100, PHP_CodeCoverage_Util::percent(100, 100)); - $this->assertEquals( - '100.00%', - PHP_CodeCoverage_Util::percent(100, 100, true) - ); - } -} diff --git a/tests/TestCase.php b/tests/TestCase.php index 09899dca0..cd18a8245 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -1,6 +1,6 @@ * @@ -8,20 +8,31 @@ * file that was distributed with this source code. */ +namespace SebastianBergmann\CodeCoverage; + +use SebastianBergmann\CodeCoverage\Driver\Xdebug; + /** * Abstract base class for test case classes. * * @since Class available since Release 1.0.0 */ -abstract class PHP_CodeCoverage_TestCase extends PHPUnit_Framework_TestCase +abstract class TestCase extends \PHPUnit_Framework_TestCase { + protected static $TEST_TMP_PATH; + + public static function setUpBeforeClass() + { + self::$TEST_TMP_PATH = TEST_FILES_PATH . 'tmp'; + } + protected function getXdebugDataForBankAccount() { - return array( - array( - TEST_FILES_PATH . 'BankAccount.php' => array( - 8 => 1, - 9 => -2, + return [ + [ + TEST_FILES_PATH . 'BankAccount.php' => [ + 8 => 1, + 9 => -2, 13 => -1, 14 => -1, 15 => -1, @@ -33,27 +44,27 @@ protected function getXdebugDataForBankAccount() 29 => -1, 31 => -1, 32 => -2 - ) - ), - array( - TEST_FILES_PATH . 'BankAccount.php' => array( - 8 => 1, + ] + ], + [ + TEST_FILES_PATH . 'BankAccount.php' => [ + 8 => 1, 13 => 1, 16 => 1, 29 => 1, - ) - ), - array( - TEST_FILES_PATH . 'BankAccount.php' => array( - 8 => 1, + ] + ], + [ + TEST_FILES_PATH . 'BankAccount.php' => [ + 8 => 1, 13 => 1, 16 => 1, 22 => 1, - ) - ), - array( - TEST_FILES_PATH . 'BankAccount.php' => array( - 8 => 1, + ] + ], + [ + TEST_FILES_PATH . 'BankAccount.php' => [ + 8 => 1, 13 => 1, 14 => 1, 15 => 1, @@ -62,16 +73,18 @@ protected function getXdebugDataForBankAccount() 24 => 1, 29 => 1, 31 => 1, - ) - ) - ); + ] + ] + ]; } protected function getCoverageForBankAccount() { $data = $this->getXdebugDataForBankAccount(); + require_once TEST_FILES_PATH . '/BankAccountTest.php'; + + $stub = $this->createMock(Xdebug::class); - $stub = $this->getMock('PHP_CodeCoverage_Driver_Xdebug'); $stub->expects($this->any()) ->method('stop') ->will($this->onConsecutiveCalls( @@ -81,49 +94,52 @@ protected function getCoverageForBankAccount() $data[3] )); - $coverage = new PHP_CodeCoverage($stub, new PHP_CodeCoverage_Filter); + $filter = new Filter; + $filter->addFileToWhitelist(TEST_FILES_PATH . 'BankAccount.php'); + + $coverage = new CodeCoverage($stub, $filter); $coverage->start( - new BankAccountTest('testBalanceIsInitiallyZero'), + new \BankAccountTest('testBalanceIsInitiallyZero'), true ); $coverage->stop( true, - array(TEST_FILES_PATH . 'BankAccount.php' => range(6, 9)) + [TEST_FILES_PATH . 'BankAccount.php' => range(6, 9)] ); $coverage->start( - new BankAccountTest('testBalanceCannotBecomeNegative') + new \BankAccountTest('testBalanceCannotBecomeNegative') ); $coverage->stop( true, - array(TEST_FILES_PATH . 'BankAccount.php' => range(27, 32)) + [TEST_FILES_PATH . 'BankAccount.php' => range(27, 32)] ); $coverage->start( - new BankAccountTest('testBalanceCannotBecomeNegative2') + new \BankAccountTest('testBalanceCannotBecomeNegative2') ); $coverage->stop( true, - array(TEST_FILES_PATH . 'BankAccount.php' => range(20, 25)) + [TEST_FILES_PATH . 'BankAccount.php' => range(20, 25)] ); $coverage->start( - new BankAccountTest('testDepositWithdrawMoney') + new \BankAccountTest('testDepositWithdrawMoney') ); $coverage->stop( true, - array( + [ TEST_FILES_PATH . 'BankAccount.php' => array_merge( range(6, 9), range(20, 25), range(27, 32) ) - ) + ] ); return $coverage; @@ -133,7 +149,8 @@ protected function getCoverageForBankAccountForFirstTwoTests() { $data = $this->getXdebugDataForBankAccount(); - $stub = $this->getMock('PHP_CodeCoverage_Driver_Xdebug'); + $stub = $this->createMock(Xdebug::class); + $stub->expects($this->any()) ->method('stop') ->will($this->onConsecutiveCalls( @@ -141,25 +158,28 @@ protected function getCoverageForBankAccountForFirstTwoTests() $data[1] )); - $coverage = new PHP_CodeCoverage($stub, new PHP_CodeCoverage_Filter); + $filter = new Filter; + $filter->addFileToWhitelist(TEST_FILES_PATH . 'BankAccount.php'); + + $coverage = new CodeCoverage($stub, $filter); $coverage->start( - new BankAccountTest('testBalanceIsInitiallyZero'), + new \BankAccountTest('testBalanceIsInitiallyZero'), true ); $coverage->stop( true, - array(TEST_FILES_PATH . 'BankAccount.php' => range(6, 9)) + [TEST_FILES_PATH . 'BankAccount.php' => range(6, 9)] ); $coverage->start( - new BankAccountTest('testBalanceCannotBecomeNegative') + new \BankAccountTest('testBalanceCannotBecomeNegative') ); $coverage->stop( true, - array(TEST_FILES_PATH . 'BankAccount.php' => range(27, 32)) + [TEST_FILES_PATH . 'BankAccount.php' => range(27, 32)] ); return $coverage; @@ -169,7 +189,8 @@ protected function getCoverageForBankAccountForLastTwoTests() { $data = $this->getXdebugDataForBankAccount(); - $stub = $this->getMock('PHP_CodeCoverage_Driver_Xdebug'); + $stub = $this->createMock(Xdebug::class); + $stub->expects($this->any()) ->method('stop') ->will($this->onConsecutiveCalls( @@ -177,30 +198,33 @@ protected function getCoverageForBankAccountForLastTwoTests() $data[3] )); - $coverage = new PHP_CodeCoverage($stub, new PHP_CodeCoverage_Filter); + $filter = new Filter; + $filter->addFileToWhitelist(TEST_FILES_PATH . 'BankAccount.php'); + + $coverage = new CodeCoverage($stub, $filter); $coverage->start( - new BankAccountTest('testBalanceCannotBecomeNegative2') + new \BankAccountTest('testBalanceCannotBecomeNegative2') ); $coverage->stop( true, - array(TEST_FILES_PATH . 'BankAccount.php' => range(20, 25)) + [TEST_FILES_PATH . 'BankAccount.php' => range(20, 25)] ); $coverage->start( - new BankAccountTest('testDepositWithdrawMoney') + new \BankAccountTest('testDepositWithdrawMoney') ); $coverage->stop( true, - array( + [ TEST_FILES_PATH . 'BankAccount.php' => array_merge( range(6, 9), range(20, 25), range(27, 32) ) - ) + ] ); return $coverage; @@ -208,43 +232,46 @@ protected function getCoverageForBankAccountForLastTwoTests() protected function getExpectedDataArrayForBankAccount() { - return array( - TEST_FILES_PATH . 'BankAccount.php' => array( - 8 => array( + return [ + TEST_FILES_PATH . 'BankAccount.php' => [ + 8 => [ 0 => 'BankAccountTest::testBalanceIsInitiallyZero', 1 => 'BankAccountTest::testDepositWithdrawMoney' - ), - 9 => null, - 13 => array(), - 14 => array(), - 15 => array(), - 16 => array(), - 18 => array(), - 22 => array( + ], + 9 => null, + 13 => [], + 14 => [], + 15 => [], + 16 => [], + 18 => [], + 22 => [ 0 => 'BankAccountTest::testBalanceCannotBecomeNegative2', 1 => 'BankAccountTest::testDepositWithdrawMoney' - ), - 24 => array( + ], + 24 => [ 0 => 'BankAccountTest::testDepositWithdrawMoney', - ), + ], 25 => null, - 29 => array( + 29 => [ 0 => 'BankAccountTest::testBalanceCannotBecomeNegative', 1 => 'BankAccountTest::testDepositWithdrawMoney' - ), - 31 => array( + ], + 31 => [ 0 => 'BankAccountTest::testDepositWithdrawMoney' - ), + ], 32 => null - ) - ); + ] + ]; } protected function getCoverageForFileWithIgnoredLines() { - $coverage = new PHP_CodeCoverage( + $filter = new Filter; + $filter->addFileToWhitelist(TEST_FILES_PATH . 'source_with_ignore.php'); + + $coverage = new CodeCoverage( $this->setUpXdebugStubForFileWithIgnoredLines(), - new PHP_CodeCoverage_Filter + $filter ); $coverage->start('FileWithIgnoredLines', true); @@ -255,18 +282,19 @@ protected function getCoverageForFileWithIgnoredLines() protected function setUpXdebugStubForFileWithIgnoredLines() { - $stub = $this->getMock('PHP_CodeCoverage_Driver_Xdebug'); + $stub = $this->createMock(Xdebug::class); + $stub->expects($this->any()) ->method('stop') ->will($this->returnValue( - array( - TEST_FILES_PATH . 'source_with_ignore.php' => array( + [ + TEST_FILES_PATH . 'source_with_ignore.php' => [ 2 => 1, 4 => -1, 6 => -1, 7 => 1 - ) - ) + ] + ] )); return $stub; @@ -274,9 +302,12 @@ protected function setUpXdebugStubForFileWithIgnoredLines() protected function getCoverageForClassWithAnonymousFunction() { - $coverage = new PHP_CodeCoverage( + $filter = new Filter; + $filter->addFileToWhitelist(TEST_FILES_PATH . 'source_with_class_and_anonymous_function.php'); + + $coverage = new CodeCoverage( $this->setUpXdebugStubForClassWithAnonymousFunction(), - new PHP_CodeCoverage_Filter + $filter ); $coverage->start('ClassWithAnonymousFunction', true); @@ -287,12 +318,13 @@ protected function getCoverageForClassWithAnonymousFunction() protected function setUpXdebugStubForClassWithAnonymousFunction() { - $stub = $this->getMock('PHP_CodeCoverage_Driver_Xdebug'); + $stub = $this->createMock(Xdebug::class); + $stub->expects($this->any()) ->method('stop') ->will($this->returnValue( - array( - TEST_FILES_PATH . 'source_with_class_and_anonymous_function.php' => array( + [ + TEST_FILES_PATH . 'source_with_class_and_anonymous_function.php' => [ 7 => 1, 9 => 1, 10 => -1, @@ -302,8 +334,8 @@ protected function setUpXdebugStubForClassWithAnonymousFunction() 14 => 1, 17 => 1, 18 => 1 - ) - ) + ] + ] )); return $stub; diff --git a/tests/_files/BankAccount-clover.xml b/tests/_files/BankAccount-clover.xml index 578a7ccc1..0986fdf71 100644 --- a/tests/_files/BankAccount-clover.xml +++ b/tests/_files/BankAccount-clover.xml @@ -3,20 +3,20 @@ - + - + - + - + - + diff --git a/tests/_files/BankAccount-crap4j.xml b/tests/_files/BankAccount-crap4j.xml new file mode 100644 index 000000000..f2f56eabb --- /dev/null +++ b/tests/_files/BankAccount-crap4j.xml @@ -0,0 +1,59 @@ + + + BankAccount + %s + + Method Crap Stats + 4 + 0 + 0 + 9 + 0 + + + + global + BankAccount + getBalance + getBalance() + getBalance() + 1 + 1 + 100 + 0 + + + global + BankAccount + setBalance + setBalance($balance) + setBalance($balance) + 6 + 2 + 0 + 0 + + + global + BankAccount + depositMoney + depositMoney($balance) + depositMoney($balance) + 1 + 1 + 100 + 0 + + + global + BankAccount + withdrawMoney + withdrawMoney($balance) + withdrawMoney($balance) + 1 + 1 + 100 + 0 + + + diff --git a/tests/_files/BankAccount-text.txt b/tests/_files/BankAccount-text.txt new file mode 100644 index 000000000..892d83464 --- /dev/null +++ b/tests/_files/BankAccount-text.txt @@ -0,0 +1,12 @@ + + +Code Coverage Report: + %s + + Summary: + Classes: 0.00% (0/1) + Methods: 75.00% (3/4) + Lines: 50.00% (5/10) + +BankAccount + Methods: 75.00% ( 3/ 4) Lines: 50.00% ( 5/ 10) diff --git a/tests/_files/CoverageTwoDefaultClassAnnotations.php b/tests/_files/CoverageTwoDefaultClassAnnotations.php index 7c743db92..7ffc5c992 100644 --- a/tests/_files/CoverageTwoDefaultClassAnnotations.php +++ b/tests/_files/CoverageTwoDefaultClassAnnotations.php @@ -6,7 +6,6 @@ */ class CoverageTwoDefaultClassAnnotations { - /** * @covers Foo\CoveredClass:: */ diff --git a/tests/_files/Report/HTML/CoverageForBankAccount/BankAccount.php.html b/tests/_files/Report/HTML/CoverageForBankAccount/BankAccount.php.html new file mode 100644 index 000000000..8cb228134 --- /dev/null +++ b/tests/_files/Report/HTML/CoverageForBankAccount/BankAccount.php.html @@ -0,0 +1,267 @@ + + + + + Code Coverage for %s/BankAccount.php + + + + + + +
    +
    +
    +
    + +
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
     
    Code Coverage
     
    Classes and Traits
    Functions and Methods
    Lines
    Total
    +
    + 0.00% covered (danger) +
    +
    +
    0.00%
    0 / 1
    +
    + 75.00% covered (warning) +
    +
    +
    75.00%
    3 / 4
    CRAP
    +
    + 50.00% covered (danger) +
    +
    +
    50.00%
    5 / 10
    BankAccount
    +
    + 0.00% covered (danger) +
    +
    +
    0.00%
    0 / 1
    +
    + 75.00% covered (warning) +
    +
    +
    75.00%
    3 / 4
    8.12
    +
    + 50.00% covered (danger) +
    +
    +
    50.00%
    5 / 10
     getBalance
    +
    + 100.00% covered (success) +
    +
    +
    100.00%
    1 / 1
    1
    +
    + 100.00% covered (success) +
    +
    +
    100.00%
    1 / 1
     setBalance
    +
    + 0.00% covered (danger) +
    +
    +
    0.00%
    0 / 1
    6
    +
    + 0.00% covered (danger) +
    +
    +
    0.00%
    0 / 5
     depositMoney
    +
    + 100.00% covered (success) +
    +
    +
    100.00%
    1 / 1
    1
    +
    + 100.00% covered (success) +
    +
    +
    100.00%
    2 / 2
     withdrawMoney
    +
    + 100.00% covered (success) +
    +
    +
    100.00%
    1 / 1
    1
    +
    + 100.00% covered (success) +
    +
    +
    100.00%
    2 / 2
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    <?php
    class BankAccount
    {
        protected $balance = 0;
        public function getBalance()
        {
            return $this->balance;
        }
        protected function setBalance($balance)
        {
            if ($balance >= 0) {
                $this->balance = $balance;
            } else {
                throw new RuntimeException;
            }
        }
        public function depositMoney($balance)
        {
            $this->setBalance($this->getBalance() + $balance);
            return $this->getBalance();
        }
        public function withdrawMoney($balance)
        {
            $this->setBalance($this->getBalance() - $balance);
            return $this->getBalance();
        }
    }
    +
    +
    +

    Legend

    +

    + Executed + Not Executed + Dead Code +

    +

    + Generated by php-code-coverage %s using %s at %s. +

    + +
    +
    + + + + + + diff --git a/tests/_files/Report/HTML/CoverageForBankAccount/dashboard.html b/tests/_files/Report/HTML/CoverageForBankAccount/dashboard.html new file mode 100644 index 000000000..2f0d97f42 --- /dev/null +++ b/tests/_files/Report/HTML/CoverageForBankAccount/dashboard.html @@ -0,0 +1,290 @@ + + + + + Dashboard for %s + + + + + + + +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +

    Classes

    +
    +
    +
    +
    +

    Coverage Distribution

    +
    + +
    +
    +
    +

    Complexity

    +
    + +
    +
    +
    +
    +
    +

    Insufficient Coverage

    +
    + + + + + + + + + + + +
    ClassCoverage
    BankAccount50%
    +
    +
    +
    +

    Project Risks

    +
    + + + + + + + + + + + +
    ClassCRAP
    BankAccount8
    +
    +
    +
    +
    +
    +

    Methods

    +
    +
    +
    +
    +

    Coverage Distribution

    +
    + +
    +
    +
    +

    Complexity

    +
    + +
    +
    +
    +
    +
    +

    Insufficient Coverage

    +
    + + + + + + + + + + + +
    MethodCoverage
    setBalance0%
    +
    +
    +
    +

    Project Risks

    +
    + + + + + + + + + + + +
    MethodCRAP
    setBalance6
    +
    +
    +
    + +
    + + + + + + + + diff --git a/tests/_files/Report/HTML/CoverageForBankAccount/index.html b/tests/_files/Report/HTML/CoverageForBankAccount/index.html new file mode 100644 index 000000000..662b9679d --- /dev/null +++ b/tests/_files/Report/HTML/CoverageForBankAccount/index.html @@ -0,0 +1,119 @@ + + + + + Code Coverage for %s + + + + + + +
    +
    +
    +
    + +
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
     
    Code Coverage
     
    Lines
    Functions and Methods
    Classes and Traits
    Total
    +
    + 50.00% covered (danger) +
    +
    +
    50.00%
    5 / 10
    +
    + 75.00% covered (warning) +
    +
    +
    75.00%
    3 / 4
    +
    + 0.00% covered (danger) +
    +
    +
    0.00%
    0 / 1
    BankAccount.php
    +
    + 50.00% covered (danger) +
    +
    +
    50.00%
    5 / 10
    +
    + 75.00% covered (warning) +
    +
    +
    75.00%
    3 / 4
    +
    + 0.00% covered (danger) +
    +
    +
    0.00%
    0 / 1
    +
    +
    +

    Legend

    +

    + Low: 0% to 50% + Medium: 50% to 90% + High: 90% to 100% +

    +

    + Generated by php-code-coverage %s using %s at %s. +

    +
    +
    + + + + + diff --git a/tests/_files/Report/HTML/CoverageForClassWithAnonymousFunction/dashboard.html b/tests/_files/Report/HTML/CoverageForClassWithAnonymousFunction/dashboard.html new file mode 100644 index 000000000..95ce2399a --- /dev/null +++ b/tests/_files/Report/HTML/CoverageForClassWithAnonymousFunction/dashboard.html @@ -0,0 +1,288 @@ + + + + + Dashboard for %s + + + + + + + +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +

    Classes

    +
    +
    +
    +
    +

    Coverage Distribution

    +
    + +
    +
    +
    +

    Complexity

    +
    + +
    +
    +
    +
    +
    +

    Insufficient Coverage

    +
    + + + + + + + + + + + +
    ClassCoverage
    CoveredClassWithAnonymousFunctionInStaticMethod87%
    +
    +
    +
    +

    Project Risks

    +
    + + + + + + + + + + +
    ClassCRAP
    +
    +
    +
    +
    +
    +

    Methods

    +
    +
    +
    +
    +

    Coverage Distribution

    +
    + +
    +
    +
    +

    Complexity

    +
    + +
    +
    +
    +
    +
    +

    Insufficient Coverage

    +
    + + + + + + + + + + + +
    MethodCoverage
    runAnonymous66%
    +
    +
    +
    +

    Project Risks

    +
    + + + + + + + + + + +
    MethodCRAP
    +
    +
    +
    + +
    + + + + + + + + diff --git a/tests/_files/Report/HTML/CoverageForClassWithAnonymousFunction/index.html b/tests/_files/Report/HTML/CoverageForClassWithAnonymousFunction/index.html new file mode 100644 index 000000000..d579da6ad --- /dev/null +++ b/tests/_files/Report/HTML/CoverageForClassWithAnonymousFunction/index.html @@ -0,0 +1,119 @@ + + + + + Code Coverage for %s + + + + + + +
    +
    +
    +
    + +
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
     
    Code Coverage
     
    Lines
    Functions and Methods
    Classes and Traits
    Total
    +
    + 87.50% covered (warning) +
    +
    +
    87.50%
    7 / 8
    +
    + 50.00% covered (danger) +
    +
    +
    50.00%
    1 / 2
    +
    + 0.00% covered (danger) +
    +
    +
    0.00%
    0 / 1
    source_with_class_and_anonymous_function.php
    +
    + 87.50% covered (warning) +
    +
    +
    87.50%
    7 / 8
    +
    + 50.00% covered (danger) +
    +
    +
    50.00%
    1 / 2
    +
    + 0.00% covered (danger) +
    +
    +
    0.00%
    0 / 1
    +
    +
    +

    Legend

    +

    + Low: 0% to 50% + Medium: 50% to 90% + High: 90% to 100% +

    +

    + Generated by php-code-coverage %s using %s at %s. +

    +
    +
    + + + + + diff --git a/tests/_files/Report/HTML/CoverageForClassWithAnonymousFunction/source_with_class_and_anonymous_function.php.html b/tests/_files/Report/HTML/CoverageForClassWithAnonymousFunction/source_with_class_and_anonymous_function.php.html new file mode 100644 index 000000000..5f0c6a6c8 --- /dev/null +++ b/tests/_files/Report/HTML/CoverageForClassWithAnonymousFunction/source_with_class_and_anonymous_function.php.html @@ -0,0 +1,211 @@ + + + + + Code Coverage for %s/source_with_class_and_anonymous_function.php + + + + + + +
    +
    +
    +
    + +
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
     
    Code Coverage
     
    Classes and Traits
    Functions and Methods
    Lines
    Total
    +
    + 0.00% covered (danger) +
    +
    +
    0.00%
    0 / 1
    +
    + 50.00% covered (danger) +
    +
    +
    50.00%
    1 / 2
    CRAP
    +
    + 87.50% covered (warning) +
    +
    +
    87.50%
    7 / 8
    CoveredClassWithAnonymousFunctionInStaticMethod
    +
    + 0.00% covered (danger) +
    +
    +
    0.00%
    0 / 1
    +
    + 50.00% covered (danger) +
    +
    +
    50.00%
    1 / 2
    2.01
    +
    + 87.50% covered (warning) +
    +
    +
    87.50%
    7 / 8
     runAnonymous
    +
    + 0.00% covered (danger) +
    +
    +
    0.00%
    0 / 1
    1.04
    +
    + 66.67% covered (warning) +
    +
    +
    66.67%
    2 / 3
     anonymous function
    +
    + 100.00% covered (success) +
    +
    +
    100.00%
    1 / 1
    1
    +
    + 100.00% covered (success) +
    +
    +
    100.00%
    2 / 2
    + + + + + + + + + + + + + + + + + + + + + + + +
    <?php
    class CoveredClassWithAnonymousFunctionInStaticMethod
    {
        public static function runAnonymous()
        {
            $filter = ['abc124', 'abc123', '123'];
            array_walk(
                $filter,
                function (&$val, $key) {
                    $val = preg_replace('|[^0-9]|', '', $val);
                }
            );
            // Should be covered
            $extravar = true;
        }
    }
    +
    +
    +

    Legend

    +

    + Executed + Not Executed + Dead Code +

    +

    + Generated by php-code-coverage %s using %s at %s. +

    + +
    +
    + + + + + + diff --git a/tests/_files/Report/HTML/CoverageForFileWithIgnoredLines/dashboard.html b/tests/_files/Report/HTML/CoverageForFileWithIgnoredLines/dashboard.html new file mode 100644 index 000000000..6b982131c --- /dev/null +++ b/tests/_files/Report/HTML/CoverageForFileWithIgnoredLines/dashboard.html @@ -0,0 +1,286 @@ + + + + + Dashboard for %s + + + + + + + +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +

    Classes

    +
    +
    +
    +
    +

    Coverage Distribution

    +
    + +
    +
    +
    +

    Complexity

    +
    + +
    +
    +
    +
    +
    +

    Insufficient Coverage

    +
    + + + + + + + + + + +
    ClassCoverage
    +
    +
    +
    +

    Project Risks

    +
    + + + + + + + + + + +
    ClassCRAP
    +
    +
    +
    +
    +
    +

    Methods

    +
    +
    +
    +
    +

    Coverage Distribution

    +
    + +
    +
    +
    +

    Complexity

    +
    + +
    +
    +
    +
    +
    +

    Insufficient Coverage

    +
    + + + + + + + + + + +
    MethodCoverage
    +
    +
    +
    +

    Project Risks

    +
    + + + + + + + + + + +
    MethodCRAP
    +
    +
    +
    + +
    + + + + + + + + diff --git a/tests/_files/Report/HTML/CoverageForFileWithIgnoredLines/index.html b/tests/_files/Report/HTML/CoverageForFileWithIgnoredLines/index.html new file mode 100644 index 000000000..850163fc6 --- /dev/null +++ b/tests/_files/Report/HTML/CoverageForFileWithIgnoredLines/index.html @@ -0,0 +1,119 @@ + + + + + Code Coverage for %s + + + + + + +
    +
    +
    +
    + +
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
     
    Code Coverage
     
    Lines
    Functions and Methods
    Classes and Traits
    Total
    +
    + 50.00% covered (danger) +
    +
    +
    50.00%
    1 / 2
    +
    + 100.00% covered (success) +
    +
    +
    100.00%
    0 / 0
    +
    + 100.00% covered (success) +
    +
    +
    100.00%
    2 / 2
    source_with_ignore.php
    +
    + 50.00% covered (danger) +
    +
    +
    50.00%
    1 / 2
    +
    + 100.00% covered (success) +
    +
    +
    100.00%
    0 / 0
    +
    + 100.00% covered (success) +
    +
    +
    100.00%
    2 / 2
    +
    +
    +

    Legend

    +

    + Low: 0% to 50% + Medium: 50% to 90% + High: 90% to 100% +

    +

    + Generated by php-code-coverage %s using %s at %s. +

    +
    +
    + + + + + diff --git a/tests/_files/Report/HTML/CoverageForFileWithIgnoredLines/source_with_ignore.php.html b/tests/_files/Report/HTML/CoverageForFileWithIgnoredLines/source_with_ignore.php.html new file mode 100644 index 000000000..5493c6e4a --- /dev/null +++ b/tests/_files/Report/HTML/CoverageForFileWithIgnoredLines/source_with_ignore.php.html @@ -0,0 +1,279 @@ + + + + + Code Coverage for %s/source_with_ignore.php + + + + + + +
    +
    +
    +
    + +
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
     
    Code Coverage
     
    Classes and Traits
    Functions and Methods
    Lines
    Total
    +
    + 100.00% covered (success) +
    +
    +
    100.00%
    2 / 2
    +
    + 100.00% covered (success) +
    +
    +
    100.00%
    0 / 0
    CRAP
    +
    + 50.00% covered (danger) +
    +
    +
    50.00%
    1 / 2
    baz
    +
    + 100.00% covered (success) +
    +
    +
    100.00%
    1 / 1
    0
    +
    + 100.00% covered (success) +
    +
    +
    100.00%
    0 / 0
    Foo
    +
    + 100.00% covered (success) +
    +
    +
    100.00%
    1 / 1
    +
    + 100.00% covered (success) +
    +
    +
    100.00%
    1 / 1
    1
    +
    + 100.00% covered (success) +
    +
    +
    100.00%
    0 / 0
     bar
    +
    + 100.00% covered (success) +
    +
    +
    100.00%
    1 / 1
    1
    +
    + 100.00% covered (success) +
    +
    +
    100.00%
    0 / 0
    Bar
    +
    + 100.00% covered (success) +
    +
    +
    100.00%
    1 / 1
    +
    + 100.00% covered (success) +
    +
    +
    100.00%
    1 / 1
    1
    +
    + 100.00% covered (success) +
    +
    +
    100.00%
    0 / 0
     foo
    +
    + 100.00% covered (success) +
    +
    +
    100.00%
    1 / 1
    1
    +
    + 100.00% covered (success) +
    +
    +
    100.00%
    0 / 0
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    <?php
    if ($neverHappens) {
        // @codeCoverageIgnoreStart
        print '*';
        // @codeCoverageIgnoreEnd
    }
    /**
     * @codeCoverageIgnore
     */
    class Foo
    {
        public function bar()
        {
        }
    }
    class Bar
    {
        /**
         * @codeCoverageIgnore
         */
        public function foo()
        {
        }
    }
    function baz()
    {
        print '*'; // @codeCoverageIgnore
    }
    interface Bor
    {
        public function foo();
    }
    +
    +
    +

    Legend

    +

    + Executed + Not Executed + Dead Code +

    +

    + Generated by php-code-coverage %s using %s at %s. +

    + +
    +
    + + + + + + diff --git a/tests/_files/Report/XML/CoverageForBankAccount/BankAccount.php.xml b/tests/_files/Report/XML/CoverageForBankAccount/BankAccount.php.xml new file mode 100644 index 000000000..d5c5d2e5f --- /dev/null +++ b/tests/_files/Report/XML/CoverageForBankAccount/BankAccount.php.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/_files/Report/XML/CoverageForBankAccount/index.xml b/tests/_files/Report/XML/CoverageForBankAccount/index.xml new file mode 100644 index 000000000..27fc5b405 --- /dev/null +++ b/tests/_files/Report/XML/CoverageForBankAccount/index.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/_files/Report/XML/CoverageForClassWithAnonymousFunction/index.xml b/tests/_files/Report/XML/CoverageForClassWithAnonymousFunction/index.xml new file mode 100644 index 000000000..6f9cd19c4 --- /dev/null +++ b/tests/_files/Report/XML/CoverageForClassWithAnonymousFunction/index.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/_files/Report/XML/CoverageForClassWithAnonymousFunction/source_with_class_and_anonymous_function.php.xml b/tests/_files/Report/XML/CoverageForClassWithAnonymousFunction/source_with_class_and_anonymous_function.php.xml new file mode 100644 index 000000000..d42452474 --- /dev/null +++ b/tests/_files/Report/XML/CoverageForClassWithAnonymousFunction/source_with_class_and_anonymous_function.php.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/_files/Report/XML/CoverageForFileWithIgnoredLines/index.xml b/tests/_files/Report/XML/CoverageForFileWithIgnoredLines/index.xml new file mode 100644 index 000000000..35c0745d5 --- /dev/null +++ b/tests/_files/Report/XML/CoverageForFileWithIgnoredLines/index.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/_files/Report/XML/CoverageForFileWithIgnoredLines/source_with_ignore.php.xml b/tests/_files/Report/XML/CoverageForFileWithIgnoredLines/source_with_ignore.php.xml new file mode 100644 index 000000000..509990f87 --- /dev/null +++ b/tests/_files/Report/XML/CoverageForFileWithIgnoredLines/source_with_ignore.php.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/_files/class-with-anonymous-function-clover.xml b/tests/_files/class-with-anonymous-function-clover.xml index ac43b8061..d6a8b4085 100644 --- a/tests/_files/class-with-anonymous-function-clover.xml +++ b/tests/_files/class-with-anonymous-function-clover.xml @@ -3,13 +3,13 @@ - + - + - + diff --git a/tests/_files/class-with-anonymous-function-crap4j.xml b/tests/_files/class-with-anonymous-function-crap4j.xml new file mode 100644 index 000000000..696496dab --- /dev/null +++ b/tests/_files/class-with-anonymous-function-crap4j.xml @@ -0,0 +1,37 @@ + + + CoverageForClassWithAnonymousFunction + %s + + Method Crap Stats + 2 + 0 + 0 + 2.04 + 0 + + + + global + CoveredClassWithAnonymousFunctionInStaticMethod + runAnonymous + runAnonymous() + runAnonymous() + 1.04 + 1 + 66.67 + 0 + + + global + CoveredClassWithAnonymousFunctionInStaticMethod + anonymous function + anonymous function (&$val, $key) + anonymous function (&$val, $key) + 1 + 1 + 100 + 0 + + + diff --git a/tests/_files/class-with-anonymous-function-text.txt b/tests/_files/class-with-anonymous-function-text.txt new file mode 100644 index 000000000..0eb257e5f --- /dev/null +++ b/tests/_files/class-with-anonymous-function-text.txt @@ -0,0 +1,12 @@ + + +Code Coverage Report: + %s + + Summary: + Classes: 0.00% (0/1) + Methods: 50.00% (1/2) + Lines: 87.50% (7/8) + +CoveredClassWithAnonymousFunctionInStaticMethod + Methods: 50.00% ( 1/ 2) Lines: 80.00% ( 4/ 5) diff --git a/tests/_files/ignored-lines-clover.xml b/tests/_files/ignored-lines-clover.xml index cda929cd3..81a9aaa3d 100644 --- a/tests/_files/ignored-lines-clover.xml +++ b/tests/_files/ignored-lines-clover.xml @@ -3,10 +3,10 @@ - + - + diff --git a/tests/_files/ignored-lines-crap4j.xml b/tests/_files/ignored-lines-crap4j.xml new file mode 100644 index 000000000..2607b59ac --- /dev/null +++ b/tests/_files/ignored-lines-crap4j.xml @@ -0,0 +1,37 @@ + + + CoverageForFileWithIgnoredLines + %s + + Method Crap Stats + 2 + 0 + 0 + 2 + 0 + + + + global + Foo + bar + bar() + bar() + 1 + 1 + 100 + 0 + + + global + Bar + foo + foo() + foo() + 1 + 1 + 100 + 0 + + + diff --git a/tests/_files/ignored-lines-text.txt b/tests/_files/ignored-lines-text.txt new file mode 100644 index 000000000..428303873 --- /dev/null +++ b/tests/_files/ignored-lines-text.txt @@ -0,0 +1,10 @@ + + +Code Coverage Report: + %s + + Summary: + Classes: 100.00% (2/2) + Methods: (0/0) + Lines: 50.00% (1/2) + diff --git a/tests/_files/source_with_class_and_anonymous_function.php b/tests/_files/source_with_class_and_anonymous_function.php index eaba387d6..72aa938e9 100644 --- a/tests/_files/source_with_class_and_anonymous_function.php +++ b/tests/_files/source_with_class_and_anonymous_function.php @@ -4,7 +4,7 @@ class CoveredClassWithAnonymousFunctionInStaticMethod { public static function runAnonymous() { - $filter = array('abc124', 'abc123', '123'); + $filter = ['abc124', 'abc123', '123']; array_walk( $filter, diff --git a/tests/_files/source_with_namespace.php b/tests/_files/source_with_namespace.php index ebe98ee15..fb9dfa340 100644 --- a/tests/_files/source_with_namespace.php +++ b/tests/_files/source_with_namespace.php @@ -15,6 +15,6 @@ function &foo($bar) { $baz = function () {}; $a = true ? true : false; - $b = "{$a}"; - $c = "${b}"; + $b = "{$a}"; + $c = "${b}"; } diff --git a/tests/_files/source_without_namespace.php b/tests/_files/source_without_namespace.php index 24d78e594..a291e7449 100644 --- a/tests/_files/source_without_namespace.php +++ b/tests/_files/source_without_namespace.php @@ -13,6 +13,6 @@ function &foo($bar) { $baz = function () {}; $a = true ? true : false; - $b = "{$a}"; - $c = "${b}"; + $b = "{$a}"; + $c = "${b}"; } diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 000000000..8e6d4134f --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,5 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SebastianBergmann\CodeCoverage\Report; + +use SebastianBergmann\CodeCoverage\TestCase; +use SebastianBergmann\CodeCoverage\Node\Builder; + +class BuilderTest extends TestCase +{ + protected $factory; + + protected function setUp() + { + $this->factory = new Builder; + } + + public function testSomething() + { + $root = $this->getCoverageForBankAccount()->getReport(); + + $expectedPath = rtrim(TEST_FILES_PATH, DIRECTORY_SEPARATOR); + $this->assertEquals($expectedPath, $root->getName()); + $this->assertEquals($expectedPath, $root->getPath()); + $this->assertEquals(10, $root->getNumExecutableLines()); + $this->assertEquals(5, $root->getNumExecutedLines()); + $this->assertEquals(1, $root->getNumClasses()); + $this->assertEquals(0, $root->getNumTestedClasses()); + $this->assertEquals(4, $root->getNumMethods()); + $this->assertEquals(3, $root->getNumTestedMethods()); + $this->assertEquals('0.00%', $root->getTestedClassesPercent()); + $this->assertEquals('75.00%', $root->getTestedMethodsPercent()); + $this->assertEquals('50.00%', $root->getLineExecutedPercent()); + $this->assertEquals(0, $root->getNumFunctions()); + $this->assertEquals(0, $root->getNumTestedFunctions()); + $this->assertNull($root->getParent()); + $this->assertEquals([], $root->getDirectories()); + #$this->assertEquals(array(), $root->getFiles()); + #$this->assertEquals(array(), $root->getChildNodes()); + + $this->assertEquals( + [ + 'BankAccount' => [ + 'methods' => [ + 'getBalance' => [ + 'signature' => 'getBalance()', + 'startLine' => 6, + 'endLine' => 9, + 'executableLines' => 1, + 'executedLines' => 1, + 'ccn' => 1, + 'coverage' => 100, + 'crap' => '1', + 'link' => 'BankAccount.php.html#6', + 'methodName' => 'getBalance', + 'visibility' => 'public', + ], + 'setBalance' => [ + 'signature' => 'setBalance($balance)', + 'startLine' => 11, + 'endLine' => 18, + 'executableLines' => 5, + 'executedLines' => 0, + 'ccn' => 2, + 'coverage' => 0, + 'crap' => 6, + 'link' => 'BankAccount.php.html#11', + 'methodName' => 'setBalance', + 'visibility' => 'protected', + ], + 'depositMoney' => [ + 'signature' => 'depositMoney($balance)', + 'startLine' => 20, + 'endLine' => 25, + 'executableLines' => 2, + 'executedLines' => 2, + 'ccn' => 1, + 'coverage' => 100, + 'crap' => '1', + 'link' => 'BankAccount.php.html#20', + 'methodName' => 'depositMoney', + 'visibility' => 'public', + ], + 'withdrawMoney' => [ + 'signature' => 'withdrawMoney($balance)', + 'startLine' => 27, + 'endLine' => 32, + 'executableLines' => 2, + 'executedLines' => 2, + 'ccn' => 1, + 'coverage' => 100, + 'crap' => '1', + 'link' => 'BankAccount.php.html#27', + 'methodName' => 'withdrawMoney', + 'visibility' => 'public', + ], + ], + 'startLine' => 2, + 'executableLines' => 10, + 'executedLines' => 5, + 'ccn' => 5, + 'coverage' => 50, + 'crap' => '8.12', + 'package' => [ + 'namespace' => '', + 'fullPackage' => '', + 'category' => '', + 'package' => '', + 'subpackage' => '' + ], + 'link' => 'BankAccount.php.html#2', + 'className' => 'BankAccount' + ] + ], + $root->getClasses() + ); + + $this->assertEquals([], $root->getFunctions()); + } + + public function testBuildDirectoryStructure() + { + $method = new \ReflectionMethod( + Builder::class, + 'buildDirectoryStructure' + ); + + $method->setAccessible(true); + + $this->assertEquals( + [ + 'src' => [ + 'Money.php/f' => [], + 'MoneyBag.php/f' => [] + ] + ], + $method->invoke( + $this->factory, + ['src/Money.php' => [], 'src/MoneyBag.php' => []] + ) + ); + } + + /** + * @dataProvider reducePathsProvider + */ + public function testReducePaths($reducedPaths, $commonPath, $paths) + { + $method = new \ReflectionMethod( + Builder::class, + 'reducePaths' + ); + + $method->setAccessible(true); + + $_commonPath = $method->invokeArgs($this->factory, [&$paths]); + + $this->assertEquals($reducedPaths, $paths); + $this->assertEquals($commonPath, $_commonPath); + } + + public function reducePathsProvider() + { + return [ + [ + [ + 'Money.php' => [], + 'MoneyBag.php' => [] + ], + '/home/sb/Money', + [ + '/home/sb/Money/Money.php' => [], + '/home/sb/Money/MoneyBag.php' => [] + ] + ], + [ + [ + 'Money.php' => [] + ], + '/home/sb/Money/', + [ + '/home/sb/Money/Money.php' => [] + ] + ], + [ + [], + '.', + [] + ], + [ + [ + 'Money.php' => [], + 'MoneyBag.php' => [], + 'Cash.phar/Cash.php' => [], + ], + '/home/sb/Money', + [ + '/home/sb/Money/Money.php' => [], + '/home/sb/Money/MoneyBag.php' => [], + 'phar:///home/sb/Money/Cash.phar/Cash.php' => [], + ], + ], + ]; + } +} diff --git a/tests/PHP/CodeCoverage/Report/CloverTest.php b/tests/tests/CloverTest.php similarity index 55% rename from tests/PHP/CodeCoverage/Report/CloverTest.php rename to tests/tests/CloverTest.php index 8d860bd2d..85743abcf 100644 --- a/tests/PHP/CodeCoverage/Report/CloverTest.php +++ b/tests/tests/CloverTest.php @@ -1,6 +1,6 @@ * @@ -8,29 +8,18 @@ * file that was distributed with this source code. */ -if (!defined('TEST_FILES_PATH')) { - define( - 'TEST_FILES_PATH', - dirname(dirname(dirname(__FILE__))) . DIRECTORY_SEPARATOR . - '_files' . DIRECTORY_SEPARATOR - ); -} +namespace SebastianBergmann\CodeCoverage\Report; -require_once TEST_FILES_PATH . '../TestCase.php'; +use SebastianBergmann\CodeCoverage\TestCase; /** - * Tests for the PHP_CodeCoverage_Report_Clover class. - * - * @since Class available since Release 1.0.0 + * @covers SebastianBergmann\CodeCoverage\Report\Clover */ -class PHP_CodeCoverage_Report_CloverTest extends PHP_CodeCoverage_TestCase +class CloverTest extends TestCase { - /** - * @covers PHP_CodeCoverage_Report_Clover - */ public function testCloverForBankAccountTest() { - $clover = new PHP_CodeCoverage_Report_Clover; + $clover = new Clover; $this->assertStringMatchesFormatFile( TEST_FILES_PATH . 'BankAccount-clover.xml', @@ -38,12 +27,9 @@ public function testCloverForBankAccountTest() ); } - /** - * @covers PHP_CodeCoverage_Report_Clover - */ public function testCloverForFileWithIgnoredLines() { - $clover = new PHP_CodeCoverage_Report_Clover; + $clover = new Clover; $this->assertStringMatchesFormatFile( TEST_FILES_PATH . 'ignored-lines-clover.xml', @@ -51,12 +37,9 @@ public function testCloverForFileWithIgnoredLines() ); } - /** - * @covers PHP_CodeCoverage_Report_Clover - */ public function testCloverForClassWithAnonymousFunction() { - $clover = new PHP_CodeCoverage_Report_Clover; + $clover = new Clover; $this->assertStringMatchesFormatFile( TEST_FILES_PATH . 'class-with-anonymous-function-clover.xml', diff --git a/tests/PHP/CodeCoverageTest.php b/tests/tests/CodeCoverageTest.php similarity index 53% rename from tests/PHP/CodeCoverageTest.php rename to tests/tests/CodeCoverageTest.php index f9bf12e58..26438fe90 100644 --- a/tests/PHP/CodeCoverageTest.php +++ b/tests/tests/CodeCoverageTest.php @@ -1,6 +1,6 @@ * @@ -8,65 +8,93 @@ * file that was distributed with this source code. */ -if (!defined('TEST_FILES_PATH')) { - define( - 'TEST_FILES_PATH', - dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . - '_files' . DIRECTORY_SEPARATOR - ); -} +namespace SebastianBergmann\CodeCoverage; -require_once TEST_FILES_PATH . '../TestCase.php'; -require_once TEST_FILES_PATH . 'BankAccount.php'; -require_once TEST_FILES_PATH . 'BankAccountTest.php'; +use SebastianBergmann\CodeCoverage\Driver\PHPDBG; +use SebastianBergmann\CodeCoverage\Driver\Xdebug; /** - * Tests for the PHP_CodeCoverage class. - * - * @since Class available since Release 1.0.0 + * @covers SebastianBergmann\CodeCoverage\CodeCoverage */ -class PHP_CodeCoverageTest extends PHP_CodeCoverage_TestCase +class CodeCoverageTest extends TestCase { /** - * @var PHP_CodeCoverage + * @var CodeCoverage */ private $coverage; protected function setUp() { - $this->coverage = new PHP_CodeCoverage; + $this->coverage = new CodeCoverage; } - /** - * @covers PHP_CodeCoverage::__construct - * @covers PHP_CodeCoverage::filter - */ - public function testConstructor() + public function testCanBeConstructedForXdebugWithoutGivenFilterObject() { + if (PHP_SAPI == 'phpdbg') { + $this->markTestSkipped('Requires PHP CLI and Xdebug'); + } + $this->assertAttributeInstanceOf( - 'PHP_CodeCoverage_Driver_Xdebug', + Xdebug::class, 'driver', $this->coverage ); $this->assertAttributeInstanceOf( - 'PHP_CodeCoverage_Filter', + Filter::class, 'filter', $this->coverage ); } - /** - * @covers PHP_CodeCoverage::__construct - * @covers PHP_CodeCoverage::filter - */ - public function testConstructor2() + public function testCanBeConstructedForXdebugWithGivenFilterObject() + { + if (PHP_SAPI == 'phpdbg') { + $this->markTestSkipped('Requires PHP CLI and Xdebug'); + } + + $filter = new Filter; + $coverage = new CodeCoverage(null, $filter); + + $this->assertAttributeInstanceOf( + Xdebug::class, + 'driver', + $coverage + ); + + $this->assertSame($filter, $coverage->filter()); + } + + public function testCanBeConstructedForPhpdbgWithoutGivenFilterObject() + { + if (PHP_SAPI != 'phpdbg') { + $this->markTestSkipped('Requires PHPDBG'); + } + + $this->assertAttributeInstanceOf( + PHPDBG::class, + 'driver', + $this->coverage + ); + + $this->assertAttributeInstanceOf( + Filter::class, + 'filter', + $this->coverage + ); + } + + public function testCanBeConstructedForPhpdbgWithGivenFilterObject() { - $filter = new PHP_CodeCoverage_Filter; - $coverage = new PHP_CodeCoverage(null, $filter); + if (PHP_SAPI != 'phpdbg') { + $this->markTestSkipped('Requires PHPDBG'); + } + + $filter = new Filter; + $coverage = new CodeCoverage(null, $filter); $this->assertAttributeInstanceOf( - 'PHP_CodeCoverage_Driver_Xdebug', + PHPDBG::class, 'driver', $coverage ); @@ -75,53 +103,45 @@ public function testConstructor2() } /** - * @covers PHP_CodeCoverage::start - * @expectedException PHP_CodeCoverage_Exception + * @expectedException SebastianBergmann\CodeCoverage\Exception */ - public function testStartThrowsExceptionForInvalidArgument() + public function testCannotStartWithInvalidArgument() { - $this->coverage->start(null, array(), null); + $this->coverage->start(null, null); } /** - * @covers PHP_CodeCoverage::stop - * @expectedException PHP_CodeCoverage_Exception + * @expectedException SebastianBergmann\CodeCoverage\Exception */ - public function testStopThrowsExceptionForInvalidArgument() + public function testCannotStopWithInvalidFirstArgument() { $this->coverage->stop(null); } /** - * @covers PHP_CodeCoverage::stop - * @expectedException PHP_CodeCoverage_Exception + * @expectedException SebastianBergmann\CodeCoverage\Exception */ - public function testStopThrowsExceptionForInvalidArgument2() + public function testCannotStopWithInvalidSecondArgument() { $this->coverage->stop(true, null); } /** - * @covers PHP_CodeCoverage::append - * @expectedException PHP_CodeCoverage_Exception + * @expectedException SebastianBergmann\CodeCoverage\Exception */ - public function testAppendThrowsExceptionForInvalidArgument() + public function testCannotAppendWithInvalidArgument() { - $this->coverage->append(array(), null); + $this->coverage->append([], null); } /** - * @covers PHP_CodeCoverage::setCacheTokens - * @expectedException PHP_CodeCoverage_Exception + * @expectedException SebastianBergmann\CodeCoverage\Exception */ public function testSetCacheTokensThrowsExceptionForInvalidArgument() { $this->coverage->setCacheTokens(null); } - /** - * @covers PHP_CodeCoverage::setCacheTokens - */ public function testSetCacheTokens() { $this->coverage->setCacheTokens(true); @@ -129,17 +149,13 @@ public function testSetCacheTokens() } /** - * @covers PHP_CodeCoverage::setCheckForUnintentionallyCoveredCode - * @expectedException PHP_CodeCoverage_Exception + * @expectedException SebastianBergmann\CodeCoverage\Exception */ public function testSetCheckForUnintentionallyCoveredCodeThrowsExceptionForInvalidArgument() { $this->coverage->setCheckForUnintentionallyCoveredCode(null); } - /** - * @covers PHP_CodeCoverage::setCheckForUnintentionallyCoveredCode - */ public function testSetCheckForUnintentionallyCoveredCode() { $this->coverage->setCheckForUnintentionallyCoveredCode(true); @@ -151,17 +167,31 @@ public function testSetCheckForUnintentionallyCoveredCode() } /** - * @covers PHP_CodeCoverage::setForceCoversAnnotation - * @expectedException PHP_CodeCoverage_Exception + * @expectedException SebastianBergmann\CodeCoverage\Exception */ public function testSetForceCoversAnnotationThrowsExceptionForInvalidArgument() { $this->coverage->setForceCoversAnnotation(null); } + public function testSetCheckForMissingCoversAnnotation() + { + $this->coverage->setCheckForMissingCoversAnnotation(true); + $this->assertAttributeEquals( + true, + 'checkForMissingCoversAnnotation', + $this->coverage + ); + } + /** - * @covers PHP_CodeCoverage::setForceCoversAnnotation + * @expectedException SebastianBergmann\CodeCoverage\Exception */ + public function testSetCheckForMissingCoversAnnotationThrowsExceptionForInvalidArgument() + { + $this->coverage->setCheckForMissingCoversAnnotation(null); + } + public function testSetForceCoversAnnotation() { $this->coverage->setForceCoversAnnotation(true); @@ -173,17 +203,31 @@ public function testSetForceCoversAnnotation() } /** - * @covers PHP_CodeCoverage::setAddUncoveredFilesFromWhitelist - * @expectedException PHP_CodeCoverage_Exception + * @expectedException SebastianBergmann\CodeCoverage\Exception */ - public function testSetAddUncoveredFilesFromWhitelistThrowsExceptionForInvalidArgument() + public function testSetCheckForUnexecutedCoveredCodeThrowsExceptionForInvalidArgument() { - $this->coverage->setAddUncoveredFilesFromWhitelist(null); + $this->coverage->setCheckForUnexecutedCoveredCode(null); + } + + public function testSetCheckForUnexecutedCoveredCode() + { + $this->coverage->setCheckForUnexecutedCoveredCode(true); + $this->assertAttributeEquals( + true, + 'checkForUnexecutedCoveredCode', + $this->coverage + ); } /** - * @covers PHP_CodeCoverage::setAddUncoveredFilesFromWhitelist + * @expectedException SebastianBergmann\CodeCoverage\Exception */ + public function testSetAddUncoveredFilesFromWhitelistThrowsExceptionForInvalidArgument() + { + $this->coverage->setAddUncoveredFilesFromWhitelist(null); + } + public function testSetAddUncoveredFilesFromWhitelist() { $this->coverage->setAddUncoveredFilesFromWhitelist(true); @@ -195,17 +239,13 @@ public function testSetAddUncoveredFilesFromWhitelist() } /** - * @covers PHP_CodeCoverage::setProcessUncoveredFilesFromWhitelist - * @expectedException PHP_CodeCoverage_Exception + * @expectedException SebastianBergmann\CodeCoverage\Exception */ public function testSetProcessUncoveredFilesFromWhitelistThrowsExceptionForInvalidArgument() { $this->coverage->setProcessUncoveredFilesFromWhitelist(null); } - /** - * @covers PHP_CodeCoverage::setProcessUncoveredFilesFromWhitelist - */ public function testSetProcessUncoveredFilesFromWhitelist() { $this->coverage->setProcessUncoveredFilesFromWhitelist(true); @@ -216,49 +256,33 @@ public function testSetProcessUncoveredFilesFromWhitelist() ); } - /** - * @covers PHP_CodeCoverage::setMapTestClassNameToCoveredClassName - */ - public function testSetMapTestClassNameToCoveredClassName() + public function testSetIgnoreDeprecatedCode() { - $this->coverage->setMapTestClassNameToCoveredClassName(true); + $this->coverage->setIgnoreDeprecatedCode(true); $this->assertAttributeEquals( true, - 'mapTestClassNameToCoveredClassName', + 'ignoreDeprecatedCode', $this->coverage ); } /** - * @covers PHP_CodeCoverage::setMapTestClassNameToCoveredClassName - * @expectedException PHP_CodeCoverage_Exception + * @expectedException SebastianBergmann\CodeCoverage\Exception */ - public function testSetMapTestClassNameToCoveredClassNameThrowsExceptionForInvalidArgument() + public function testSetIgnoreDeprecatedCodeThrowsExceptionForInvalidArgument() { - $this->coverage->setMapTestClassNameToCoveredClassName(null); + $this->coverage->setIgnoreDeprecatedCode(null); } - /** - * @covers PHP_CodeCoverage::clear - */ public function testClear() { $this->coverage->clear(); $this->assertAttributeEquals(null, 'currentId', $this->coverage); - $this->assertAttributeEquals(array(), 'data', $this->coverage); - $this->assertAttributeEquals(array(), 'tests', $this->coverage); + $this->assertAttributeEquals([], 'data', $this->coverage); + $this->assertAttributeEquals([], 'tests', $this->coverage); } - /** - * @covers PHP_CodeCoverage::start - * @covers PHP_CodeCoverage::stop - * @covers PHP_CodeCoverage::append - * @covers PHP_CodeCoverage::applyListsFilter - * @covers PHP_CodeCoverage::initializeFilesThatAreSeenTheFirstTime - * @covers PHP_CodeCoverage::applyCoversAnnotationFilter - * @covers PHP_CodeCoverage::getTests - */ public function testCollect() { $coverage = $this->getCoverageForBankAccount(); @@ -268,27 +292,23 @@ public function testCollect() $coverage->getData() ); - if (version_compare(PHPUnit_Runner_Version::id(), '4.7', '>=')) { + if (version_compare(\PHPUnit_Runner_Version::id(), '4.7', '>=')) { $size = 'unknown'; } else { $size = 'small'; } $this->assertEquals( - array( - 'BankAccountTest::testBalanceIsInitiallyZero' => array('size' => $size, 'status' => null), - 'BankAccountTest::testBalanceCannotBecomeNegative' => array('size' => $size, 'status' => null), - 'BankAccountTest::testBalanceCannotBecomeNegative2' => array('size' => $size, 'status' => null), - 'BankAccountTest::testDepositWithdrawMoney' => array('size' => $size, 'status' => null) - ), + [ + 'BankAccountTest::testBalanceIsInitiallyZero' => ['size' => $size, 'status' => null], + 'BankAccountTest::testBalanceCannotBecomeNegative' => ['size' => $size, 'status' => null], + 'BankAccountTest::testBalanceCannotBecomeNegative2' => ['size' => $size, 'status' => null], + 'BankAccountTest::testDepositWithdrawMoney' => ['size' => $size, 'status' => null] + ], $coverage->getTests() ); } - /** - * @covers PHP_CodeCoverage::getData - * @covers PHP_CodeCoverage::merge - */ public function testMerge() { $coverage = $this->getCoverageForBankAccountForFirstTwoTests(); @@ -300,15 +320,11 @@ public function testMerge() ); } - /** - * @covers PHP_CodeCoverage::getData - * @covers PHP_CodeCoverage::merge - */ public function testMerge2() { - $coverage = new PHP_CodeCoverage( - $this->getMock('PHP_CodeCoverage_Driver_Xdebug'), - new PHP_CodeCoverage_Filter + $coverage = new CodeCoverage( + $this->createMock(Xdebug::class), + new Filter ); $coverage->merge($this->getCoverageForBankAccount()); @@ -319,13 +335,10 @@ public function testMerge2() ); } - /** - * @covers PHP_CodeCoverage::getLinesToBeIgnored - */ public function testGetLinesToBeIgnored() { $this->assertEquals( - array( + [ 1, 3, 4, @@ -360,7 +373,7 @@ public function testGetLinesToBeIgnored() 36, 37, 38 - ), + ], $this->getLinesToBeIgnored()->invoke( $this->coverage, TEST_FILES_PATH . 'source_with_ignore.php' @@ -368,13 +381,10 @@ public function testGetLinesToBeIgnored() ); } - /** - * @covers PHP_CodeCoverage::getLinesToBeIgnored - */ public function testGetLinesToBeIgnored2() { $this->assertEquals( - array(1, 5), + [1, 5], $this->getLinesToBeIgnored()->invoke( $this->coverage, TEST_FILES_PATH . 'source_without_ignore.php' @@ -382,13 +392,10 @@ public function testGetLinesToBeIgnored2() ); } - /** - * @covers PHP_CodeCoverage::getLinesToBeIgnored - */ public function testGetLinesToBeIgnored3() { $this->assertEquals( - array( + [ 1, 2, 3, @@ -400,7 +407,7 @@ public function testGetLinesToBeIgnored3() 16, 19, 20 - ), + ], $this->getLinesToBeIgnored()->invoke( $this->coverage, TEST_FILES_PATH . 'source_with_class_and_anonymous_function.php' @@ -408,13 +415,10 @@ public function testGetLinesToBeIgnored3() ); } - /** - * @covers PHP_CodeCoverage::getLinesToBeIgnored - */ public function testGetLinesToBeIgnoredOneLineAnnotations() { $this->assertEquals( - array( + [ 1, 2, 3, @@ -446,7 +450,7 @@ public function testGetLinesToBeIgnoredOneLineAnnotations() 33, 34, 37 - ), + ], $this->getLinesToBeIgnored()->invoke( $this->coverage, TEST_FILES_PATH . 'source_with_oneline_annotations.php' @@ -455,12 +459,12 @@ public function testGetLinesToBeIgnoredOneLineAnnotations() } /** - * @return ReflectionMethod + * @return \ReflectionMethod */ private function getLinesToBeIgnored() { - $getLinesToBeIgnored = new ReflectionMethod( - 'PHP_CodeCoverage', + $getLinesToBeIgnored = new \ReflectionMethod( + 'SebastianBergmann\CodeCoverage\CodeCoverage', 'getLinesToBeIgnored' ); @@ -469,19 +473,75 @@ private function getLinesToBeIgnored() return $getLinesToBeIgnored; } - /** - * @covers PHP_CodeCoverage::getLinesToBeIgnored - */ public function testGetLinesToBeIgnoredWhenIgnoreIsDisabled() { $this->coverage->setDisableIgnoredLines(true); $this->assertEquals( - array(), + [], $this->getLinesToBeIgnored()->invoke( $this->coverage, TEST_FILES_PATH . 'source_with_ignore.php' ) ); } + + /** + * @expectedException SebastianBergmann\CodeCoverage\CoveredCodeNotExecutedException + */ + public function testAppendThrowsExceptionIfCoveredCodeWasNotExecuted() + { + $this->coverage->filter()->addDirectoryToWhitelist(TEST_FILES_PATH); + $this->coverage->setCheckForUnexecutedCoveredCode(true); + + $data = [ + TEST_FILES_PATH . 'BankAccount.php' => [ + 29 => -1, + 31 => -1 + ] + ]; + + $linesToBeCovered = [ + TEST_FILES_PATH . 'BankAccount.php' => [ + 22, + 24 + ] + ]; + + $linesToBeUsed = []; + + $this->coverage->append($data, 'File1.php', true, $linesToBeCovered, $linesToBeUsed); + } + + /** + * @expectedException SebastianBergmann\CodeCoverage\CoveredCodeNotExecutedException + */ + public function testAppendThrowsExceptionIfUsedCodeWasNotExecuted() + { + $this->coverage->filter()->addDirectoryToWhitelist(TEST_FILES_PATH); + $this->coverage->setCheckForUnexecutedCoveredCode(true); + + $data = [ + TEST_FILES_PATH . 'BankAccount.php' => [ + 29 => -1, + 31 => -1 + ] + ]; + + $linesToBeCovered = [ + TEST_FILES_PATH . 'BankAccount.php' => [ + 29, + 31 + ] + ]; + + $linesToBeUsed = [ + TEST_FILES_PATH . 'BankAccount.php' => [ + 22, + 24 + ] + ]; + + $this->coverage->append($data, 'File1.php', true, $linesToBeCovered, $linesToBeUsed); + } } diff --git a/tests/tests/Crap4jTest.php b/tests/tests/Crap4jTest.php new file mode 100644 index 000000000..faa1ac51e --- /dev/null +++ b/tests/tests/Crap4jTest.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SebastianBergmann\CodeCoverage\Report; + +use SebastianBergmann\CodeCoverage\TestCase; + +/** + * @covers SebastianBergmann\CodeCoverage\Report\Crap4j + */ +class Crap4jTest extends TestCase +{ + public function testForBankAccountTest() + { + $crap4j = new Crap4j; + + $this->assertStringMatchesFormatFile( + TEST_FILES_PATH . 'BankAccount-crap4j.xml', + $crap4j->process($this->getCoverageForBankAccount(), null, 'BankAccount') + ); + } + + public function testForFileWithIgnoredLines() + { + $crap4j = new Crap4j; + + $this->assertStringMatchesFormatFile( + TEST_FILES_PATH . 'ignored-lines-crap4j.xml', + $crap4j->process($this->getCoverageForFileWithIgnoredLines(), null, 'CoverageForFileWithIgnoredLines') + ); + } + + public function testForClassWithAnonymousFunction() + { + $crap4j = new Crap4j; + + $this->assertStringMatchesFormatFile( + TEST_FILES_PATH . 'class-with-anonymous-function-crap4j.xml', + $crap4j->process($this->getCoverageForClassWithAnonymousFunction(), null, 'CoverageForClassWithAnonymousFunction') + ); + } +} diff --git a/tests/PHP/CodeCoverage/FilterTest.php b/tests/tests/FilterTest.php similarity index 57% rename from tests/PHP/CodeCoverage/FilterTest.php rename to tests/tests/FilterTest.php index 66f8bb42f..47ff21a0f 100644 --- a/tests/PHP/CodeCoverage/FilterTest.php +++ b/tests/tests/FilterTest.php @@ -1,6 +1,6 @@ * @@ -8,29 +8,25 @@ * file that was distributed with this source code. */ -if (!defined('TEST_FILES_PATH')) { - define( - 'TEST_FILES_PATH', - dirname(dirname(dirname(__FILE__))) . DIRECTORY_SEPARATOR . - '_files' . DIRECTORY_SEPARATOR - ); -} +namespace SebastianBergmann\CodeCoverage; -/** - * Tests for the PHP_CodeCoverage_Filter class. - * - * @since Class available since Release 1.0.0 - */ -class PHP_CodeCoverage_FilterTest extends PHPUnit_Framework_TestCase +class FilterTest extends \PHPUnit_Framework_TestCase { - protected $filter; - protected $files; + /** + * @var Filter + */ + private $filter; + + /** + * @var array + */ + private $files = []; protected function setUp() { - $this->filter = unserialize('O:23:"PHP_CodeCoverage_Filter":0:{}'); + $this->filter = unserialize('O:37:"SebastianBergmann\CodeCoverage\Filter":0:{}'); - $this->files = array( + $this->files = [ TEST_FILES_PATH . 'BankAccount.php', TEST_FILES_PATH . 'BankAccountTest.php', TEST_FILES_PATH . 'CoverageClassExtendedTest.php', @@ -72,112 +68,38 @@ protected function setUp() TEST_FILES_PATH . 'source_with_oneline_annotations.php', TEST_FILES_PATH . 'source_without_ignore.php', TEST_FILES_PATH . 'source_without_namespace.php' - ); + ]; } /** - * @covers PHP_CodeCoverage_Filter::addFileToBlacklist - * @covers PHP_CodeCoverage_Filter::getBlacklist - */ - public function testAddingAFileToTheBlacklistWorks() - { - $this->filter->addFileToBlacklist($this->files[0]); - - $this->assertEquals( - array($this->files[0]), - $this->filter->getBlacklist() - ); - } - - /** - * @covers PHP_CodeCoverage_Filter::removeFileFromBlacklist - * @covers PHP_CodeCoverage_Filter::getBlacklist - */ - public function testRemovingAFileFromTheBlacklistWorks() - { - $this->filter->addFileToBlacklist($this->files[0]); - $this->filter->removeFileFromBlacklist($this->files[0]); - - $this->assertEquals(array(), $this->filter->getBlacklist()); - } - - /** - * @covers PHP_CodeCoverage_Filter::addDirectoryToBlacklist - * @covers PHP_CodeCoverage_Filter::getBlacklist - * @depends testAddingAFileToTheBlacklistWorks - */ - public function testAddingADirectoryToTheBlacklistWorks() - { - $this->filter->addDirectoryToBlacklist(TEST_FILES_PATH); - - $blacklist = $this->filter->getBlacklist(); - sort($blacklist); - - $this->assertEquals($this->files, $blacklist); - } - - /** - * @covers PHP_CodeCoverage_Filter::addFilesToBlacklist - * @covers PHP_CodeCoverage_Filter::getBlacklist - */ - public function testAddingFilesToTheBlacklistWorks() - { - $facade = new File_Iterator_Facade; - $files = $facade->getFilesAsArray( - TEST_FILES_PATH, - $suffixes = '.php' - ); - - $this->filter->addFilesToBlacklist($files); - - $blacklist = $this->filter->getBlacklist(); - sort($blacklist); - - $this->assertEquals($this->files, $blacklist); - } - - /** - * @covers PHP_CodeCoverage_Filter::removeDirectoryFromBlacklist - * @covers PHP_CodeCoverage_Filter::getBlacklist - * @depends testAddingADirectoryToTheBlacklistWorks - */ - public function testRemovingADirectoryFromTheBlacklistWorks() - { - $this->filter->addDirectoryToBlacklist(TEST_FILES_PATH); - $this->filter->removeDirectoryFromBlacklist(TEST_FILES_PATH); - - $this->assertEquals(array(), $this->filter->getBlacklist()); - } - - /** - * @covers PHP_CodeCoverage_Filter::addFileToWhitelist - * @covers PHP_CodeCoverage_Filter::getWhitelist + * @covers SebastianBergmann\CodeCoverage\Filter::addFileToWhitelist + * @covers SebastianBergmann\CodeCoverage\Filter::getWhitelist */ public function testAddingAFileToTheWhitelistWorks() { $this->filter->addFileToWhitelist($this->files[0]); $this->assertEquals( - array($this->files[0]), + [$this->files[0]], $this->filter->getWhitelist() ); } /** - * @covers PHP_CodeCoverage_Filter::removeFileFromWhitelist - * @covers PHP_CodeCoverage_Filter::getWhitelist + * @covers SebastianBergmann\CodeCoverage\Filter::removeFileFromWhitelist + * @covers SebastianBergmann\CodeCoverage\Filter::getWhitelist */ public function testRemovingAFileFromTheWhitelistWorks() { $this->filter->addFileToWhitelist($this->files[0]); $this->filter->removeFileFromWhitelist($this->files[0]); - $this->assertEquals(array(), $this->filter->getWhitelist()); + $this->assertEquals([], $this->filter->getWhitelist()); } /** - * @covers PHP_CodeCoverage_Filter::addDirectoryToWhitelist - * @covers PHP_CodeCoverage_Filter::getWhitelist + * @covers SebastianBergmann\CodeCoverage\Filter::addDirectoryToWhitelist + * @covers SebastianBergmann\CodeCoverage\Filter::getWhitelist * @depends testAddingAFileToTheWhitelistWorks */ public function testAddingADirectoryToTheWhitelistWorks() @@ -191,13 +113,14 @@ public function testAddingADirectoryToTheWhitelistWorks() } /** - * @covers PHP_CodeCoverage_Filter::addFilesToWhitelist - * @covers PHP_CodeCoverage_Filter::getBlacklist + * @covers SebastianBergmann\CodeCoverage\Filter::addFilesToWhitelist + * @covers SebastianBergmann\CodeCoverage\Filter::getWhitelist */ public function testAddingFilesToTheWhitelistWorks() { - $facade = new File_Iterator_Facade; - $files = $facade->getFilesAsArray( + $facade = new \File_Iterator_Facade; + + $files = $facade->getFilesAsArray( TEST_FILES_PATH, $suffixes = '.php' ); @@ -211,8 +134,8 @@ public function testAddingFilesToTheWhitelistWorks() } /** - * @covers PHP_CodeCoverage_Filter::removeDirectoryFromWhitelist - * @covers PHP_CodeCoverage_Filter::getWhitelist + * @covers SebastianBergmann\CodeCoverage\Filter::removeDirectoryFromWhitelist + * @covers SebastianBergmann\CodeCoverage\Filter::getWhitelist * @depends testAddingADirectoryToTheWhitelistWorks */ public function testRemovingADirectoryFromTheWhitelistWorks() @@ -220,11 +143,11 @@ public function testRemovingADirectoryFromTheWhitelistWorks() $this->filter->addDirectoryToWhitelist(TEST_FILES_PATH); $this->filter->removeDirectoryFromWhitelist(TEST_FILES_PATH); - $this->assertEquals(array(), $this->filter->getWhitelist()); + $this->assertEquals([], $this->filter->getWhitelist()); } /** - * @covers PHP_CodeCoverage_Filter::isFile + * @covers SebastianBergmann\CodeCoverage\Filter::isFile */ public function testIsFile() { @@ -238,16 +161,7 @@ public function testIsFile() } /** - * @covers PHP_CodeCoverage_Filter::isFiltered - */ - public function testBlacklistedFileIsFiltered() - { - $this->filter->addFileToBlacklist($this->files[0]); - $this->assertTrue($this->filter->isFiltered($this->files[0])); - } - - /** - * @covers PHP_CodeCoverage_Filter::isFiltered + * @covers SebastianBergmann\CodeCoverage\Filter::isFiltered */ public function testWhitelistedFileIsNotFiltered() { @@ -256,7 +170,7 @@ public function testWhitelistedFileIsNotFiltered() } /** - * @covers PHP_CodeCoverage_Filter::isFiltered + * @covers SebastianBergmann\CodeCoverage\Filter::isFiltered */ public function testNotWhitelistedFileIsFiltered() { @@ -265,8 +179,8 @@ public function testNotWhitelistedFileIsFiltered() } /** - * @covers PHP_CodeCoverage_Filter::isFiltered - * @covers PHP_CodeCoverage_Filter::isFile + * @covers SebastianBergmann\CodeCoverage\Filter::isFiltered + * @covers SebastianBergmann\CodeCoverage\Filter::isFile */ public function testNonFilesAreFiltered() { @@ -276,6 +190,5 @@ public function testNonFilesAreFiltered() $this->assertTrue($this->filter->isFiltered('runtime-created function')); $this->assertTrue($this->filter->isFiltered('assert code')); $this->assertTrue($this->filter->isFiltered('regexp code')); - $this->assertFalse($this->filter->isFiltered(__FILE__)); } } diff --git a/tests/tests/HTMLTest.php b/tests/tests/HTMLTest.php new file mode 100644 index 000000000..56c5d0a76 --- /dev/null +++ b/tests/tests/HTMLTest.php @@ -0,0 +1,104 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SebastianBergmann\CodeCoverage\Report\Html; + +use SebastianBergmann\CodeCoverage\Report\Html\Facade; +use SebastianBergmann\CodeCoverage\TestCase; + +class HTMLTest extends TestCase +{ + private static $TEST_REPORT_PATH_SOURCE; + + public static function setUpBeforeClass() + { + parent::setUpBeforeClass(); + + self::$TEST_REPORT_PATH_SOURCE = TEST_FILES_PATH . 'Report' . DIRECTORY_SEPARATOR . 'HTML'; + } + + protected function tearDown() + { + parent::tearDown(); + + $tmpFilesIterator = new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator(self::$TEST_TMP_PATH, \RecursiveDirectoryIterator::SKIP_DOTS), + \RecursiveIteratorIterator::CHILD_FIRST + ); + + foreach ($tmpFilesIterator as $path => $fileInfo) { + /* @var \SplFileInfo $fileInfo */ + $pathname = $fileInfo->getPathname(); + $fileInfo->isDir() ? rmdir($pathname) : unlink($pathname); + } + } + + public function testForBankAccountTest() + { + $expectedFilesPath = self::$TEST_REPORT_PATH_SOURCE . DIRECTORY_SEPARATOR . 'CoverageForBankAccount'; + + $report = new Facade; + $report->process($this->getCoverageForBankAccount(), self::$TEST_TMP_PATH); + + $this->assertFilesEquals($expectedFilesPath, self::$TEST_TMP_PATH); + } + + public function testForFileWithIgnoredLines() + { + $expectedFilesPath = self::$TEST_REPORT_PATH_SOURCE . DIRECTORY_SEPARATOR . 'CoverageForFileWithIgnoredLines'; + + $report = new Facade; + $report->process($this->getCoverageForFileWithIgnoredLines(), self::$TEST_TMP_PATH); + + $this->assertFilesEquals($expectedFilesPath, self::$TEST_TMP_PATH); + } + + public function testForClassWithAnonymousFunction() + { + $expectedFilesPath = + self::$TEST_REPORT_PATH_SOURCE . DIRECTORY_SEPARATOR . 'CoverageForClassWithAnonymousFunction'; + + $report = new Facade; + $report->process($this->getCoverageForClassWithAnonymousFunction(), self::$TEST_TMP_PATH); + + $this->assertFilesEquals($expectedFilesPath, self::$TEST_TMP_PATH); + } + + /** + * @param string $expectedFilesPath + * @param string $actualFilesPath + */ + private function assertFilesEquals($expectedFilesPath, $actualFilesPath) + { + $expectedFilesIterator = new \FilesystemIterator($expectedFilesPath); + $actualFilesIterator = new \RegexIterator(new \FilesystemIterator($actualFilesPath), '/.html/'); + + $this->assertEquals( + iterator_count($expectedFilesIterator), + iterator_count($actualFilesIterator), + 'Generated files and expected files not match' + ); + + foreach ($expectedFilesIterator as $path => $fileInfo) { + /* @var \SplFileInfo $fileInfo */ + $filename = $fileInfo->getFilename(); + + $actualFile = $actualFilesPath . DIRECTORY_SEPARATOR . $filename; + + $this->assertFileExists($actualFile); + + $this->assertStringMatchesFormatFile( + $fileInfo->getPathname(), + str_replace(PHP_EOL, "\n", file_get_contents($actualFile)), + "${filename} not match" + ); + } + } +} diff --git a/tests/tests/TextTest.php b/tests/tests/TextTest.php new file mode 100644 index 000000000..04da00ab3 --- /dev/null +++ b/tests/tests/TextTest.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SebastianBergmann\CodeCoverage\Report; + +use SebastianBergmann\CodeCoverage\TestCase; + +/** + * @covers SebastianBergmann\CodeCoverage\Report\Text + */ +class TextTest extends TestCase +{ + public function testTextForBankAccountTest() + { + $text = new Text(50, 90, false, false); + + $this->assertStringMatchesFormatFile( + TEST_FILES_PATH . 'BankAccount-text.txt', + str_replace(PHP_EOL, "\n", $text->process($this->getCoverageForBankAccount())) + ); + } + + public function testTextForFileWithIgnoredLines() + { + $text = new Text(50, 90, false, false); + + $this->assertStringMatchesFormatFile( + TEST_FILES_PATH . 'ignored-lines-text.txt', + str_replace(PHP_EOL, "\n", $text->process($this->getCoverageForFileWithIgnoredLines())) + ); + } + + public function testTextForClassWithAnonymousFunction() + { + $text = new Text(50, 90, false, false); + + $this->assertStringMatchesFormatFile( + TEST_FILES_PATH . 'class-with-anonymous-function-text.txt', + str_replace(PHP_EOL, "\n", $text->process($this->getCoverageForClassWithAnonymousFunction())) + ); + } +} diff --git a/tests/tests/UtilTest.php b/tests/tests/UtilTest.php new file mode 100644 index 000000000..c29b693ee --- /dev/null +++ b/tests/tests/UtilTest.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SebastianBergmann\CodeCoverage; + +/** + * @covers SebastianBergmann\CodeCoverage\Util + */ +class UtilTest extends \PHPUnit_Framework_TestCase +{ + public function testPercent() + { + $this->assertEquals(100, Util::percent(100, 0)); + $this->assertEquals(100, Util::percent(100, 100)); + $this->assertEquals( + '100.00%', + Util::percent(100, 100, true) + ); + } +} diff --git a/tests/tests/XMLTest.php b/tests/tests/XMLTest.php new file mode 100644 index 000000000..7ce8db334 --- /dev/null +++ b/tests/tests/XMLTest.php @@ -0,0 +1,99 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SebastianBergmann\CodeCoverage\Report\Xml; + +use SebastianBergmann\CodeCoverage\TestCase; + +class XMLTest extends TestCase +{ + private static $TEST_REPORT_PATH_SOURCE; + + public static function setUpBeforeClass() + { + parent::setUpBeforeClass(); + + self::$TEST_REPORT_PATH_SOURCE = TEST_FILES_PATH . 'Report' . DIRECTORY_SEPARATOR . 'XML'; + } + + protected function tearDown() + { + parent::tearDown(); + + $tmpFilesIterator = new \FilesystemIterator(self::$TEST_TMP_PATH); + + foreach ($tmpFilesIterator as $path => $fileInfo) { + /* @var \SplFileInfo $fileInfo */ + unlink($fileInfo->getPathname()); + } + } + + public function testForBankAccountTest() + { + $expectedFilesPath = self::$TEST_REPORT_PATH_SOURCE . DIRECTORY_SEPARATOR . 'CoverageForBankAccount'; + + $xml = new Facade; + $xml->process($this->getCoverageForBankAccount(), self::$TEST_TMP_PATH); + + $this->assertFilesEquals($expectedFilesPath, self::$TEST_TMP_PATH); + } + + public function testForFileWithIgnoredLines() + { + $expectedFilesPath = self::$TEST_REPORT_PATH_SOURCE . DIRECTORY_SEPARATOR . 'CoverageForFileWithIgnoredLines'; + + $xml = new Facade; + $xml->process($this->getCoverageForFileWithIgnoredLines(), self::$TEST_TMP_PATH); + + $this->assertFilesEquals($expectedFilesPath, self::$TEST_TMP_PATH); + } + + public function testForClassWithAnonymousFunction() + { + $expectedFilesPath = + self::$TEST_REPORT_PATH_SOURCE . DIRECTORY_SEPARATOR . 'CoverageForClassWithAnonymousFunction'; + + $xml = new Facade; + $xml->process($this->getCoverageForClassWithAnonymousFunction(), self::$TEST_TMP_PATH); + + $this->assertFilesEquals($expectedFilesPath, self::$TEST_TMP_PATH); + } + + /** + * @param string $expectedFilesPath + * @param string $actualFilesPath + */ + private function assertFilesEquals($expectedFilesPath, $actualFilesPath) + { + $expectedFilesIterator = new \FilesystemIterator($expectedFilesPath); + $actualFilesIterator = new \FilesystemIterator($actualFilesPath); + + $this->assertEquals( + iterator_count($expectedFilesIterator), + iterator_count($actualFilesIterator), + 'Generated files and expected files not match' + ); + + foreach ($expectedFilesIterator as $path => $fileInfo) { + /* @var \SplFileInfo $fileInfo */ + $filename = $fileInfo->getFilename(); + + $actualFile = $actualFilesPath . DIRECTORY_SEPARATOR . $filename; + + $this->assertFileExists($actualFile); + + $this->assertStringMatchesFormatFile( + $fileInfo->getPathname(), + file_get_contents($actualFile), + "${filename} not match" + ); + } + } +}