diff --git a/CHANGELOG b/CHANGELOG index 3e48ece9..a381c822 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,8 +1,9 @@ -Version 0.8.1 (2019-??-??) +Version 0.8.1 (2019-10-28) ========================== Bug fixes: - Don't crash updating feeds cached solely via ETag +- Don't fail importing new folders from OPML files - Don't fail adding a feed which collides with another via redirection - Don't fail on very long text-search queries containing question marks when using PostgreSQL or MySQL diff --git a/README.md b/README.md index 22e8e51b..0658d785 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Information on how to install and use the software can be found in [the manual]( # Installing from source -The main repository for The Arsse can be found at [code.mensbeam.com](https://code.mensbeam.com/MensBeam/arsse/), with a mirror also available [at GitHub](https://github.com/meansbeam/arsse/). The main repository is preferred, as the GitHub mirror can sometimes be out of date. +The main repository for The Arsse can be found at [code.mensbeam.com](https://code.mensbeam.com/MensBeam/arsse/), with a mirror also available [at GitHub](https://github.com/mensbeam/arsse/). The main repository is preferred, as the GitHub mirror can sometimes be out of date. [Composer](https://getcomposer.org/) is required to manage PHP dependencies. After cloning the repository or downloading a source code tarball, running `composer install` will download all the required dependencies, and will advise if any PHP extensions need to be installed. If not installing as a programming environment, running `composer install --no-dev` is recommended. @@ -88,7 +88,7 @@ There is also a `test:quick` Robo task which excludes slower tests, and a `test: ### Test coverage -Computing the coverage of tests can be done by running `./robo coverage`. Either [phpdbg](https://php.net/manual/en/book.phpdbg.php) or [Xdebug](https://xdebug.org) is required for this. An HTML-format coverage report will be written to `/tests/coverage/`. +Computing the coverage of tests can be done by running `./robo coverage`, after which an HTML-format coverage report will be written to `/tests/coverage/`. Either [Xdebug](https://xdebug.org) or [phpdbg](https://php.net/manual/en/book.phpdbg.php) is required for this. Xdebug is generally recommended as it is better maintained, though phpdbg is significantly faster. If using Xdebug, the extension need not be enabled globally; PHPUnit will enable it when needed. ## Enforcing coding style @@ -105,8 +105,6 @@ The Arsse's user manual, made using [Daux](https://daux.io/), can be compiled by The manual employs a custom theme derived from the standard Daux theme. If the standard Daux theme receives improvements, the custom theme can be rebuilt by running `./robo manual:theme`. This requires that [NodeJS](https://nodejs.org) and [Yarn](https://yarnpkg.com/) be installed, but JavaScript tools are not required to modify The Arsse itself, nor the content of the manual. -The Robo task `manual:css` will recompile the theme's stylesheet without rebuilding the entire theme. - ## Packaging a release Producing a release package is done by running `./robo package`. This performs the following operations: diff --git a/RoboFile.php b/RoboFile.php index e47c8fc7..f382090e 100644 --- a/RoboFile.php +++ b/RoboFile.php @@ -5,6 +5,7 @@ use Robo\Result; const BASE = __DIR__.\DIRECTORY_SEPARATOR; const BASE_TEST = BASE."tests".\DIRECTORY_SEPARATOR; define("IS_WIN", defined("PHP_WINDOWS_VERSION_MAJOR")); +define("IS_MAC", php_uname("s") === "Darwin"); function norm(string $path): string { $out = realpath($path); @@ -92,12 +93,13 @@ class RoboFile extends \Robo\Tasks { $dbg = dirname(\PHP_BINARY)."\\phpdbg.exe"; $dbg = file_exists($dbg) ? $dbg : ""; } else { - $dbg = trim(`which phpdbg`); + $dbg = trim(`which phpdbg 2>/dev/null`); } if ($dbg) { return escapeshellarg($dbg)." -qrr"; } else { - return escapeshellarg(\PHP_BINARY); + $ext = IS_WIN ? "dll" : (IS_MAC ? "dylib" : "so"); + return escapeshellarg(\PHP_BINARY)." -d zend_extension=xdebug.$ext"; } } @@ -196,6 +198,7 @@ class RoboFile extends \Robo\Tasks { $execpath = escapeshellarg(norm(BASE."vendor/bin/daux")); $t = $this->collectionBuilder(); $t->taskExec($execpath)->arg("generate")->option("-d", BASE."manual")->args($args); + $t->taskDeleteDir(BASE."manual/daux_libraries"); $t->taskDeleteDir(BASE."manual/theme"); $t->taskDeleteDir(BASE."manual/themes/src"); return $t->run(); @@ -213,80 +216,20 @@ class RoboFile extends \Robo\Tasks { * Daux's theme changes */ public function manualTheme(array $args): Result { - $languages = ["php", "bash", "shell", "xml", "nginx", "apache"]; + $postcss = escapeshellarg(norm(BASE."node_modules/.bin/postcss")); + $themesrc = norm(BASE."docs/theme/src/").\DIRECTORY_SEPARATOR; $themeout = norm(BASE."docs/theme/arsse/").\DIRECTORY_SEPARATOR; $dauxjs = norm(BASE."vendor-bin/daux/vendor/daux/daux.io/themes/daux/js/").\DIRECTORY_SEPARATOR; // start a collection; this stops after the first failure $t = $this->collectionBuilder(); - $tmp = $t->tmpDir().\DIRECTORY_SEPARATOR; - // rebuild the stylesheet - $t->addCode([$this, "manualCss"]); - // copy JavaScript files from the Daux theme - foreach (glob($dauxjs."daux*") as $file) { - $t->taskFilesystemStack()->copy($file, $themeout.basename($file), true); - } - // download highlight.js - $t->addCode(function() use ($languages, $tmp, $themeout) { - // compile the list of desired language (enumerated above) into an application/x-www-form-urlencoded body - $post = http_build_query((function($langs) { - $out = []; - foreach ($langs as $l) { - $out[$l.".js"] = "on"; - } - return $out; - })($languages)); - // get the two cross-site request forgery tokens the Highlight.js Web site requires - $conn = @fopen("https://highlightjs.org/download/", "r"); - if ($conn === false) { - throw new Exception("Unable to download Highlight.js"); - } - foreach (stream_get_meta_data($conn)['wrapper_data'] as $field) { - if (preg_match("/^Set-Cookie: csrftoken=([^;]+)/i", $field, $cookie)) { - break; - } - } - $token = stream_get_contents($conn); - preg_match("/ [ - 'method' => "POST", - 'content' => $post, - 'header' => [ - "Referer: https://highlightjs.org/download/", - "Cookie: csrftoken={$cookie[1]}", - "Content-Type: application/x-www-form-urlencoded", - ], - ]])); - if ($hljs === false) { - throw new Exception("Unable to download Highlight.js"); - } else { - file_put_contents($tmp."highlightjs.zip", $hljs); - } - // extract the downloaded zip file and keep only the JS file - $this->taskExtract($tmp."highlightjs.zip")->to($tmp."hljs")->run(); - $this->taskFilesystemStack()->copy($tmp."hljs".\DIRECTORY_SEPARATOR."highlight.pack.js", $themeout."highlight.pack.js")->run(); - }, "downloadHighlightjs"); - // execute the collection - return $t->run(); - } - - /** Rebuilds the manual theme's stylesheet only - * - * This requires Node and Yarn to be installed. - */ - public function manualCss(): Result { - // start a collection; this stops after the first failure - $t = $this->collectionBuilder(); - $tmp = $t->tmpDir().\DIRECTORY_SEPARATOR; // install dependencies via Yarn $t->taskExec("yarn install"); // compile the stylesheet - $postcss = escapeshellarg(norm(BASE."node_modules/.bin/postcss")); - $themesrc = norm(BASE."docs/theme/src/").\DIRECTORY_SEPARATOR; - $themeout = norm(BASE."docs/theme/arsse/").\DIRECTORY_SEPARATOR; $t->taskExec($postcss)->arg($themesrc."arsse.scss")->option("-o", $themeout."arsse.css"); + // copy JavaScript files from the Daux theme + foreach (glob($dauxjs."daux*.js") as $file) { + $t->taskFilesystemStack()->copy($file, $themeout.basename($file), true); + } // execute the collection return $t->run(); } diff --git a/composer.lock b/composer.lock index 54a74444..c33f781e 100644 --- a/composer.lock +++ b/composer.lock @@ -347,16 +347,16 @@ }, { "name": "zendframework/zend-diactoros", - "version": "2.1.3", + "version": "2.1.5", "source": { "type": "git", "url": "https://github.com/zendframework/zend-diactoros.git", - "reference": "279723778c40164bcf984a2df12ff2c6ec5e61c1" + "reference": "6dcf9e760a6b476f3e9d80abbc9ce9c4aa921f9c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-diactoros/zipball/279723778c40164bcf984a2df12ff2c6ec5e61c1", - "reference": "279723778c40164bcf984a2df12ff2c6ec5e61c1", + "url": "https://api.github.com/repos/zendframework/zend-diactoros/zipball/6dcf9e760a6b476f3e9d80abbc9ce9c4aa921f9c", + "reference": "6dcf9e760a6b476f3e9d80abbc9ce9c4aa921f9c", "shasum": "" }, "require": { @@ -369,6 +369,7 @@ "psr/http-message-implementation": "1.0" }, "require-dev": { + "ext-curl": "*", "ext-dom": "*", "ext-libxml": "*", "http-interop/http-factory-tests": "^0.5.0", @@ -409,7 +410,7 @@ "psr", "psr-7" ], - "time": "2019-07-10T16:13:25+00:00" + "time": "2019-10-10T17:38:20+00:00" }, { "name": "zendframework/zend-httphandlerrunner", diff --git a/docs/en/020_Getting_Started/040_Database_Setup/010_PostgreSQL.md b/docs/en/020_Getting_Started/040_Database_Setup/010_PostgreSQL.md index 7dc1af28..51272426 100644 --- a/docs/en/020_Getting_Started/040_Database_Setup/010_PostgreSQL.md +++ b/docs/en/020_Getting_Started/040_Database_Setup/010_PostgreSQL.md @@ -22,7 +22,7 @@ sudo -u postgres psql -c "CREATE USER arsseuser WITH PASSWORD 'super secret pass sudo -u postgres psql -c "CREATE DATABASE arssedb WITH OWNER arsseuser" ``` -Tha Arsse must then be configured to use the created database. A suitable [configuration file](/en/Getting_Started/Configuration) might look like this: +The Arsse must then be configured to use the created database. A suitable [configuration file](/en/Getting_Started/Configuration) might look like this: ```php :first-child,.s-content dl dd>:first-child,.s-content dl dt>:first-child,.s-content ol>:first-child,.s-content table td>:first-child,.s-content table th>:first-child,.s-content ul>:first-child{margin-top:0}.s-content blockquote>:last-child,.s-content dl dd>:last-child,.s-content dl dt>:last-child,.s-content ol>:last-child,.s-content table td>:last-child,.s-content table th>:last-child,.s-content ul>:last-child{margin-bottom:0}.s-content img{max-width:100%;display:block;margin:0 auto}.s-content code{font-family:Monaco,Menlo,Consolas,"Lucida Console","Courier New",monospace;padding-top:.1rem;padding-bottom:.1rem;background:#f9f5f4;border-radius:0;box-shadow:none;display:inline-block;padding:.5ch;border:0}.s-content code:after,.s-content code:before{letter-spacing:-.2em;content:"\00a0"}.s-content pre{background:#fdf6e3;line-height:1.5em;overflow:auto;border:0;border-radius:0;padding:.75em 2em;margin:0 -20px 20px}.s-content pre code{margin:0;padding:0;white-space:pre;box-shadow:none}.s-content pre code,.s-content pre tt{background-color:transparent;border:0}.s-content ins,.s-content u{text-decoration:none;border-bottom:1px solid #15284b}.s-content del a,.s-content ins a,.s-content u a{color:inherit}@media (min-width:1150px){.Columns__right--float .Columns__right__content{height:100%;overflow:auto;padding:0!important;background-color:transparent!important;position:relative}.Columns__right--float .Columns__right__content article{width:100%;min-height:100%;overflow:auto;position:relative;z-index:1}.Columns__right--float .Columns__right__content article:before{content:"";width:50%;min-height:100%;overflow:auto;background-color:#fff;display:block;margin:0;position:absolute;z-index:-1}.Columns__right--float .Page__header,.Columns__right--float .Pager,.Columns__right--float .s-content blockquote,.Columns__right--float .s-content dl,.Columns__right--float .s-content h2,.Columns__right--float .s-content h3,.Columns__right--float .s-content h4,.Columns__right--float .s-content h5,.Columns__right--float .s-content h6,.Columns__right--float .s-content hr,.Columns__right--float .s-content ol,.Columns__right--float .s-content p,.Columns__right--float .s-content table,.Columns__right--float .s-content ul{float:left;clear:left;width:47%;margin-left:1.5%;margin-right:1.5%}.Columns__right--float .s-content table{background-color:#fff;white-space:normal}.Columns__right--float .s-content table code,.Columns__right--float .s-content table pre{white-space:normal}.Columns__right--float .s-content blockquote:before,.Columns__right--float .s-content dl:before,.Columns__right--float .s-content h2:before,.Columns__right--float .s-content h3:before,.Columns__right--float .s-content h4:before,.Columns__right--float .s-content h5:before,.Columns__right--float .s-content h6:before,.Columns__right--float .s-content hr:before,.Columns__right--float .s-content ol:before,.Columns__right--float .s-content p:before,.Columns__right--float .s-content ul:before{width:100%;height:10px;display:block;clear:both}.Columns__right--float .s-content blockquote p,.Columns__right--float .s-content blockquote pre{float:none;display:block}.Columns__right--float .s-content blockquote dl,.Columns__right--float .s-content blockquote h2,.Columns__right--float .s-content blockquote h3,.Columns__right--float .s-content blockquote h4,.Columns__right--float .s-content blockquote h5,.Columns__right--float .s-content blockquote h6,.Columns__right--float .s-content blockquote hr,.Columns__right--float .s-content blockquote ol,.Columns__right--float .s-content blockquote ul,.Columns__right--float .s-content dl dl,.Columns__right--float .s-content dl h2,.Columns__right--float .s-content dl h3,.Columns__right--float .s-content dl h4,.Columns__right--float .s-content dl h5,.Columns__right--float .s-content dl h6,.Columns__right--float .s-content dl hr,.Columns__right--float .s-content dl ol,.Columns__right--float .s-content dl p,.Columns__right--float .s-content dl pre,.Columns__right--float .s-content dl ul,.Columns__right--float .s-content h2 dl,.Columns__right--float .s-content h2 h2,.Columns__right--float .s-content h2 h3,.Columns__right--float .s-content h2 h4,.Columns__right--float .s-content h2 h5,.Columns__right--float .s-content h2 h6,.Columns__right--float .s-content h2 hr,.Columns__right--float .s-content h2 ol,.Columns__right--float .s-content h2 p,.Columns__right--float .s-content h2 pre,.Columns__right--float .s-content h2 ul,.Columns__right--float .s-content h3 dl,.Columns__right--float .s-content h3 h2,.Columns__right--float .s-content h3 h3,.Columns__right--float .s-content h3 h4,.Columns__right--float .s-content h3 h5,.Columns__right--float .s-content h3 h6,.Columns__right--float .s-content h3 hr,.Columns__right--float .s-content h3 ol,.Columns__right--float .s-content h3 p,.Columns__right--float .s-content h3 pre,.Columns__right--float .s-content h3 ul,.Columns__right--float .s-content h4 dl,.Columns__right--float .s-content h4 h2,.Columns__right--float .s-content h4 h3,.Columns__right--float .s-content h4 h4,.Columns__right--float .s-content h4 h5,.Columns__right--float .s-content h4 h6,.Columns__right--float .s-content h4 hr,.Columns__right--float .s-content h4 ol,.Columns__right--float .s-content h4 p,.Columns__right--float .s-content h4 pre,.Columns__right--float .s-content h4 ul,.Columns__right--float .s-content h5 dl,.Columns__right--float .s-content h5 h2,.Columns__right--float .s-content h5 h3,.Columns__right--float .s-content h5 h4,.Columns__right--float .s-content h5 h5,.Columns__right--float .s-content h5 h6,.Columns__right--float .s-content h5 hr,.Columns__right--float .s-content h5 ol,.Columns__right--float .s-content h5 p,.Columns__right--float .s-content h5 pre,.Columns__right--float .s-content h5 ul,.Columns__right--float .s-content h6 dl,.Columns__right--float .s-content h6 h2,.Columns__right--float .s-content h6 h3,.Columns__right--float .s-content h6 h4,.Columns__right--float .s-content h6 h5,.Columns__right--float .s-content h6 h6,.Columns__right--float .s-content h6 hr,.Columns__right--float .s-content h6 ol,.Columns__right--float .s-content h6 p,.Columns__right--float .s-content h6 pre,.Columns__right--float .s-content h6 ul,.Columns__right--float .s-content hr dl,.Columns__right--float .s-content hr h2,.Columns__right--float .s-content hr h3,.Columns__right--float .s-content hr h4,.Columns__right--float .s-content hr h5,.Columns__right--float .s-content hr h6,.Columns__right--float .s-content hr hr,.Columns__right--float .s-content hr ol,.Columns__right--float .s-content hr p,.Columns__right--float .s-content hr pre,.Columns__right--float .s-content hr ul,.Columns__right--float .s-content ol dl,.Columns__right--float .s-content ol h2,.Columns__right--float .s-content ol h3,.Columns__right--float .s-content ol h4,.Columns__right--float .s-content ol h5,.Columns__right--float .s-content ol h6,.Columns__right--float .s-content ol hr,.Columns__right--float .s-content ol ol,.Columns__right--float .s-content ol p,.Columns__right--float .s-content ol pre,.Columns__right--float .s-content ol ul,.Columns__right--float .s-content p dl,.Columns__right--float .s-content p h2,.Columns__right--float .s-content p h3,.Columns__right--float .s-content p h4,.Columns__right--float .s-content p h5,.Columns__right--float .s-content p h6,.Columns__right--float .s-content p hr,.Columns__right--float .s-content p ol,.Columns__right--float .s-content p p,.Columns__right--float .s-content p pre,.Columns__right--float .s-content p ul,.Columns__right--float .s-content ul dl,.Columns__right--float .s-content ul h2,.Columns__right--float .s-content ul h3,.Columns__right--float .s-content ul h4,.Columns__right--float .s-content ul h5,.Columns__right--float .s-content ul h6,.Columns__right--float .s-content ul hr,.Columns__right--float .s-content ul ol,.Columns__right--float .s-content ul p,.Columns__right--float .s-content ul pre,.Columns__right--float .s-content ul ul{width:auto;float:none;display:block}.Columns__right--float .s-content hr{border-color:#ddd}.Columns__right--float .s-content blockquote p,.Columns__right--float .s-content blockquote pre,.Columns__right--float .s-content li p,.Columns__right--float .s-content li pre{width:100%}.Columns__right--float .s-content pre{float:left;clear:right;width:50%;border:0;border-left:10px solid #fff;margin:0 0 10px;padding:0}.Columns__right--float .s-content pre code{padding:0 .5em}}a.Link--external:after{content:" " url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAVklEQVR4Xn3PgQkAMQhDUXfqTu7kTtkpd5RA8AInfArtQ2iRXFWT2QedAfttj2FsPIOE1eCOlEuoWWjgzYaB/IkeGOrxXhqB+uA9Bfcm0lAZuh+YIeAD+cAqSz4kCMUAAAAASUVORK5CYII=)}a.Link--broken{color:red}p{margin:0 0 1em}.Button{display:inline-block;text-align:center;vertical-align:middle;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;margin-bottom:0}.Button--small{font-size:12px;line-height:1.5;border-radius:3px}.Button--default{color:#333;background-color:#fff;border-color:#ccc}.Button--default.Button--active{color:#333;background-color:#e6e6e6;border-color:#adadad}.ButtonGroup{position:relative;display:inline-block;vertical-align:middle}.ButtonGroup .Button+.Button{margin-left:-1px}.ButtonGroup>.Button{position:relative;float:left}.ButtonGroup>.Button:focus,.ButtonGroup>.Button:hover{z-index:2}.ButtonGroup>.Button.Button--active,.ButtonGroup>.Button:active{z-index:3}.ButtonGroup>.Button:not(:first-child):not(:last-child){border-radius:0}.ButtonGroup>.Button:first-child{margin-left:0}.ButtonGroup>.Button:first-child:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.ButtonGroup>.Button:last-child:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.Brand,.Navbar{background-color:#e63c2f}.Brand{display:block;padding:.75em .6em;font-size:2rem;text-shadow:none;font-family:"League Gothic",-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Arial,sans-serif;color:#15284b}.Navbar{box-shadow:0 1px 5px rgba(0,0,0,.25);margin-bottom:0}.CodeToggler{padding:0 20px}.CodeToggler__text{font-size:12px;line-height:1.5;padding:6px 10px 6px 0;display:inline-block;vertical-align:middle}.no-js .CodeToggler{display:none}.Nav{margin:0;padding:0}.Nav__arrow{display:inline-block;position:relative;width:16px;margin-left:-16px}.Nav__arrow:before{position:absolute;display:block;content:"";margin:-.25em 0 0 -.4em;left:50%;top:50%;border-right:.15em solid #15284b;border-top:.15em solid #15284b;transform:rotate(45deg);transition-duration:.3s}.Nav__item,.Nav__item a{display:block}.Nav__item a{margin:0;padding:6px 15px 6px 20px;font-family:"League Gothic",-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Arial,sans-serif;font-weight:400;color:#15284b;text-shadow:none}.Nav__item a:hover{color:#15284b;text-shadow:none;background-color:#93b7bb}.Nav .Nav{margin-left:15px}html:not(.no-js) .Nav .Nav{height:0;transition:height 400ms ease-in-out;overflow:hidden}.Nav .Nav .Nav__item a{margin:0 0 0 -15px;padding:3px 30px;font-family:"Cabin","Trebuchet MS",-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Arial,sans-serif;color:#15284b;opacity:.7}.Nav .Nav .Nav__item a:hover{opacity:1}.Nav .Nav .Nav__item--active a{color:#15284b}.Nav__item--active>a,.Nav__item--open>a{background-color:#93b7bb}.Nav__item--open>a>.Nav__arrow:before{margin-left:-.25em;transform:rotate(135deg)}.Page__header{margin:0 0 10px;padding:0}.Page__header:after,.Page__header:before{content:" ";display:table}.Page__header:after{clear:both}.Page__header h1{margin:0;padding:0;line-height:57px}.Page__header--separator{height:.6em}.Page__header a,ul.TableOfContents a{text-decoration:none}.Page__header .EditOn,.Page__header .ModifiedDate{float:left;font-size:10px;color:gray}.Page__header .EditOn{float:right}.Links,.Twitter{padding:0 20px}.Links a{font-family:"League Gothic",-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Arial,sans-serif;font-weight:400;color:#15284b;line-height:2em}.PoweredBy{padding:0 20px 1rem;font-size:1.309rem}.Search{position:relative}.Search__field{display:block;width:100%;height:34px;padding:6px 30px 6px 20px;color:#555;border-width:0 0 1px;border-bottom:1px solid #ccc;background:#fff;transition:border-color ease-in-out .15s}.Search__field:focus{border-color:#93b7bb;outline:0}.Search__icon{position:absolute;right:9px;top:9px;width:16px;height:16px}.Navbar .Search{float:right;margin:8px 20px}.Navbar .Search__field{box-shadow:inset 0 1px 1px rgba(0,0,0,.075);border-width:0;border-radius:4px;padding-left:10px}.TableOfContentsContainer__title{margin-bottom:0!important}.TableOfContentsContainer__content>.TableOfContents{margin-top:0}ul.TableOfContents{float:none;font-size:16px;padding-left:1.5em;border-left:6px solid #e8d5d3}ul.TableOfContents p{margin-bottom:0}ul.TableOfContents .TableOfContents{border-left-width:0}.Columns__right--full .TableOfContentsContainer{float:right;min-width:300px;max-width:25%;padding-left:1em}.Columns__right--full .TableOfContentsContainer .TableOfContentsContainer__content>.TableOfContents{border-right:2px solid #e8d5d3}.Columns__right--full .TableOfContentsContainer .TableOfContents{list-style-type:none;padding-left:0}.Columns__right--full .TableOfContentsContainer a{display:block;padding:.2em 0;border-bottom:1px solid #e8d5d3}.Columns__right--full .TableOfContentsContainer li a{padding-left:.75em}.Columns__right--full .TableOfContentsContainer li li a{padding-left:1.5em}.Columns__right--full .TableOfContentsContainer li li li a{padding-left:2.25em}.Columns__right--full .TableOfContentsContainer li li li li a{padding-left:3em}.Pager{padding-left:0;margin:1em 0;list-style:none;text-align:center}.Pager:after,.Pager:before{content:" ";display:table}.Pager,.Pager:after{clear:both}.Pager li{display:inline}.Pager li>a{display:inline-block;padding:5px 14px;background-color:#fff}.Pager li>a:focus,.Pager li>a:hover{text-decoration:none}.Pager--next>a{float:right}.Pager--prev>a{float:left}.Checkbox{position:relative;display:block;padding-left:30px;cursor:pointer}.Checkbox input{position:absolute;z-index:-1;opacity:0}.Checkbox__indicator{position:absolute;top:50%;left:0;width:20px;height:20px;margin-top:-10px;background:#e6e6e6}.Checkbox__indicator:after{position:absolute;display:none;content:""}.Checkbox input:focus~.Checkbox__indicator,.Checkbox:hover input~.Checkbox__indicator{background:#ccc}.Checkbox input:checked~.Checkbox__indicator{background:#15284b}.Checkbox input:checked~.Checkbox__indicator:after{display:block}.Checkbox input:checked:focus~.Checkbox__indicator,.Checkbox:hover input:not([disabled]):checked~.Checkbox__indicator{background:#93b7bb}.Checkbox input:disabled~.Checkbox__indicator{pointer-events:none;opacity:.6;background:#e6e6e6}.Checkbox .Checkbox__indicator:after{top:4px;left:8px;width:5px;height:10px;transform:rotate(45deg);border:solid #fff;border-width:0 2px 2px 0}.Checkbox input:disabled~.Checkbox__indicator:after{border-color:#7b7b7b}.Hidden{display:none}.Container{margin-right:auto;margin-left:auto}.Container--inner{width:80%;margin:0 auto}@media (min-width:1200px){.Container{width:1170px}}@media (min-width:992px){.Container{width:970px}}@media (min-width:769px){.Container{width:750px}}@media (min-width:1200px){.Container{width:1170px}}.Homepage{background-color:#fff;border-radius:0;border:0;color:#15284b;overflow:hidden;padding-bottom:0;margin-bottom:0;box-shadow:none}.HomepageTitle h2{width:80%;font-size:30px;margin:20px auto;text-align:center}.HomepageImage img{display:block;max-width:80%;margin:0 auto;height:auto}.HomepageButtons{padding:20px 0;background-color:#e8d5d3;text-align:center}.HomepageButtons:after,.HomepageButtons:before{content:" ";display:table}.HomepageButtons:after{clear:both}.HomepageButtons .Button--hero{padding:20px 30px;border-radius:0;text-shadow:none;opacity:.8;margin:0 10px;text-transform:uppercase;border:5px solid #15284b;font-family:"League Gothic",-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Arial,sans-serif;background-image:none;-webkit-filter:none;filter:none;box-shadow:none}@media (max-width:768px){.HomepageButtons .Button--hero{display:block;margin-bottom:10px}}.HomepageButtons .Button--hero:hover{opacity:1}.HomepageButtons .Button--hero.Button--secondary{background-color:#93b7bb;color:#15284b}.HomepageButtons .Button--hero.Button--primary{background-color:#15284b;color:#e8d5d3}.HomepageContent{background-color:#fff;padding:40px 0}.HomepageContent ol li,.HomepageContent ul li{list-style:none;margin-bottom:.5em;position:relative}.HomepageContent ol li:before,.HomepageContent ul li:before{position:absolute;top:50%;left:-1.5em;content:"";width:0;height:0;border:.5em solid transparent;border-left:.5em solid #93b7bb;float:left;display:block;margin-top:-.5em}.HomepageContent .HeroText,.HomepageFooter__links li a{font-size:16px;font-family:"League Gothic",-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Arial,sans-serif}.HomepageContent .HeroText{margin-bottom:20px;font-weight:300;line-height:1.4}@media (min-width:769px){.HomepageContent{padding:40px 20px}.HomepageContent .HeroText{font-size:21px}.HomepageContent .Row{margin:0 -15px}.HomepageContent .Row__half,.HomepageContent .Row__quarter,.HomepageContent .Row__third{float:left;position:relative;min-height:1px;padding-left:15px;padding-right:15px}.HomepageContent .Row__third{width:33.333333%}.HomepageContent .Row__half{width:50%}.HomepageContent .Row__quarter{width:25%}}.HomepageFooter{background-color:#15284b;color:#93b7bb;border:0;box-shadow:none}.HomepageFooter:after,.HomepageFooter:before{content:" ";display:table}.HomepageFooter:after{clear:both}@media (max-width:768px){.HomepageFooter{padding:0 20px;text-align:center}.HomepageFooter .HomepageFooter__links{padding-left:0;list-style-type:none}}@media (min-width:769px){.HomepageFooter .HomepageFooter__links{float:left}.HomepageFooter .HomepageFooter__twitter{float:right}}.HomepageFooter__links,.HomepageFooter__twitter{margin:40px 0}.HomepageFooter__links li a{line-height:32px;font-weight:700}.HomepageFooter__links li a:hover{text-decoration:underline}.HomepageFooter .Twitter{margin-bottom:20px}@media print{*{text-shadow:none!important;color:#000!important;background:0 0!important;box-shadow:none!important}h1,h2,h3,h4,h5,h6{page-break-after:avoid;page-break-before:auto}blockquote,img,pre{page-break-inside:avoid}blockquote,pre{font-style:italic;border:1px solid #999}img{border:0}a,a:visited{text-decoration:underline}abbr[title]:after{content:" (" attr(title) ")"}q{quotes:none}.s-content a[href^="#"]:after,q:before{content:""}q:after{content:" (" attr(cite) ")"}.PageBreak{display:block;page-break-before:always}.NoPrint,.Pager,aside{display:none}.Columns__right{width:100%!important}.s-content a:after{content:" (" attr(href) ")";font-size:80%;word-wrap:break-word}h1 a[href]:after{font-size:50%}}@font-face{font-family:'League Gothic';src:url(fonts/leaguegothic.woff2) format('woff2'),url(fonts/leaguegothic.woff) format('woff');font-style:normal;font-display:swap}@font-face{font-family:'Cabin';src:url(fonts/cabin-regular.woff2) format('woff2'),url(fonts/cabin-regular.woff) format('woff');font-weight:400;font-style:normal;font-display:swap}@font-face{font-family:'Cabin';src:url(fonts/cabin-italic.woff2) format('woff2'),url(fonts/cabin-italic.woff) format('woff');font-style:italic;font-display:swap}@font-face{font-family:'Cabin';src:url(fonts/cabin-bold.woff2) format('woff2'),url(fonts/cabin-bold.woff) format('woff');font-weight:700;font-style:normal;font-display:swap}.s-content code::after,.s-content code::before,a.Link--external::after{content:''}pre .s-content code{display:inline}.s-content table tbody,.s-content table thead{background-color:#fff}.s-content table tr:nth-child(2n) td{background-color:#f9f5f4}.s-content table td,.s-content table th{border:0}.Nav__item .Nav__item,.s-content table{font-size:1rem}.Brand,h1,h2,h3,h4,h5,h6{font-weight:400}.Button,.Pager li>a{border-radius:0}.HomepageButtons .Button--hero{font-weight:400;font-size:1.309rem}.Page__header{border-bottom:2px solid #e8d5d3}.Pager li>a{border:2px solid #e8d5d3}.Pager li>a:focus,.Pager li>a:hover{background-color:#e8d5d3}.Pager--prev a::before{content:"\2190\00a0"}.Pager--next a::after{content:"\00a0\2192"}.Navbar{height:auto;box-shadow:none}.Navbar .Brand{float:none;line-height:inherit;height:auto}.Homepage{padding-top:10px!important}.Nav__item{font-size:1.309rem}.Nav .Nav .Nav__item a .Nav__arrow:before,.Nav__arrow:before{font-family:"League Gothic",-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Arial,sans-serif;width:1ch;height:1ch}.TableOfContentsContainer__title{border-bottom:4px solid #e8d5d3}.clients thead tr:first-child th{text-align:left}.clients thead tr:first-child th:first-child{width:15%}.clients thead tr:first-child th:nth-child(3){width:50%;text-align:center}.clients thead tr+tr th{width:16.66%;text-align:center}.clients tbody td:nth-child(3),.clients tbody td:nth-child(4),.clients tbody td:nth-child(5){text-align:center}.clients tbody td.Y{color:#2c9a42}.clients tbody td.N{color:#e63c2f}.hljs,.s-content pre{background:#15284b;color:#e8d5d3}.hljs{display:block;overflow-x:auto;padding:.5em}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.hljs-comment,.hljs-quote{color:#978e9c}.hljs-addition,.hljs-keyword,.hljs-selector-tag{color:#acb39a}.hljs-doctag,.hljs-literal,.hljs-meta .hljs-meta-string,.hljs-number,.hljs-regexp,.hljs-string{color:#93b7bb}.hljs-name,.hljs-section,.hljs-selector-class,.hljs-selector-id,.hljs-title{color:#82b7e5}.hljs-attr,.hljs-attribute,.hljs-class .hljs-title,.hljs-template-variable,.hljs-type,.hljs-variable{color:#c5b031}.hljs-bullet,.hljs-link,.hljs-meta,.hljs-meta .hljs-keyword,.hljs-selector-attr,.hljs-selector-pseudo,.hljs-subst,.hljs-symbol{color:#ea8031}.hljs-built_in,.hljs-deletion{color:#e63c2f}.hljs-formula{background:#686986}@media (min-width:850px){.Columns__left{border:0}} \ No newline at end of file +html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;font-size:14px}body{margin:0;padding:0}article,aside,details,figcaption,figure,footer,header,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block}audio:not([controls]){display:none;height:0}progress,sub,sup{vertical-align:baseline}.s-content pre code:after,.s-content pre code:before,[hidden],template{display:none}a{background-color:transparent;-webkit-text-decoration-skip:objects;text-decoration:none;color:#e63c2f}a:active,a:hover{outline-width:0}abbr[title]{border-bottom:none;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}.s-content blockquote cite,dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}svg:not(:root){overflow:hidden}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}figure{margin:1em 40px}hr{box-sizing:content-box;height:0;clear:both;margin:1em 0;border:0;border-top:1px solid #ddd}button,input,select,textarea{font:inherit;margin:0}optgroup{font-weight:700}button,hr,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{color:inherit;display:table;max-width:100%;white-space:normal}textarea{overflow:auto}[type=checkbox],[type=radio],legend{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-input-placeholder{color:inherit;opacity:.54}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}*,:after,:before{box-sizing:border-box}@media (min-width:850px){html{font-size:16px}}body,html{height:100%;background-color:#fff;color:#15284b}.Columns__left{background-color:#e8d5d3}.Columns__right__content{padding:10px;background-color:#fff}@media (max-width:768px){html:not(.no-js) .Collapsible__content{height:0;overflow:hidden;transition:height 400ms ease-in-out}}.Collapsible__trigger{margin:12px;padding:7px 10px;background-color:transparent;border:0;float:right;background-image:none;-webkit-filter:none;filter:none;box-shadow:none}.Collapsible__trigger__bar{display:block;width:18px;height:2px;margin-top:2px;margin-bottom:3px;background-color:#e8d5d3}.Collapsible__trigger:hover{background-color:#93b7bb;box-shadow:none}.Collapsible__trigger:hover .Collapsible__trigger__bar{background-color:#15284b}@media screen and (min-width:769px){body{background-color:#15284b}.Navbar{position:fixed;z-index:1030;width:100%}.Collapsible__trigger{display:none!important}.Collapsible__content{display:block!important}.Columns{height:100%}.Columns:after,.Columns:before{content:" ";display:table}.Columns:after{clear:both}.Columns__left,.Columns__right{position:relative;min-height:1px;float:left;overflow:auto;height:100%}.Columns__left{width:25%;border-right:1px solid #e7e7e9;overflow-x:hidden}.Columns__right{width:75%}.Columns__right__content{padding:0 20px 20px;min-height:100%}}.Page{max-width:860px}body{font-family:"Cabin","Trebuchet MS",-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Arial,sans-serif;font-feature-settings:"kern" 1;-webkit-font-kerning:normal;font-kerning:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;line-height:1.618}h1,h2,h3,h4,h5,h6{font-family:"League Gothic",-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Arial,sans-serif}.s-content h1,.s-content h2,.s-content h3,.s-content h4,.s-content h5,.s-content h6{cursor:text;line-height:1.4em;margin:2em 0 .5em}.s-content h1 code,.s-content h1 tt,.s-content h2 code,.s-content h2 tt,.s-content h3 code,.s-content h3 tt,.s-content h4 code,.s-content h4 tt,.s-content h5 code,.s-content h5 tt,.s-content h6 code,.s-content h6 tt{font-size:inherit}.s-content h1 i,.s-content h2 i,.s-content h3 i,.s-content h4 i,.s-content h5 i,.s-content h6 i{font-size:.7em}.s-content h1 p,.s-content h2 p,.s-content h3 p,.s-content h4 p,.s-content h5 p,.s-content h6 p{margin-top:0}.s-content h1{margin-top:0;font-size:2.618rem}.s-content h2{font-size:2rem}.s-content h3{font-size:1.618rem}.s-content h4,.s-content h5,.s-content h6,.s-content small{font-size:1.309rem}.s-content a{text-decoration:underline}.s-content p{margin-bottom:1.3em}.s-content ol,.s-content ul{padding-left:2em}.s-content ul p,.s-content ul ul{margin:0}.s-content dl{padding:0}.s-content dl dt{font-weight:700;font-style:italic;padding:0;margin:15px 0 5px}.s-content dl dt:first-child{padding:0}.s-content dl dd{margin:0 0 15px;padding:0 15px}.s-content blockquote{margin:.75em 2em;padding:.5em 1em;font-style:italic;border-left:.25em solid #15284b}.s-content blockquote cite:before{content:"\2014";padding-right:.5em}.s-content table{width:100%;padding:0;margin-bottom:1em;border-collapse:separate;border-spacing:2px;border:2px solid #b3aab1}.s-content table+table{margin-top:1em}.s-content table tr{background-color:#fff;margin:0;padding:0;border-top:0}.s-content table tr:nth-child(2n){background-color:transparent}.s-content table th{font-weight:700;background:#e8d5d3}.s-content table td,.s-content table th{margin:0;padding:.5em}.s-content blockquote>:first-child,.s-content dl dd>:first-child,.s-content dl dt>:first-child,.s-content ol>:first-child,.s-content table td>:first-child,.s-content table th>:first-child,.s-content ul>:first-child{margin-top:0}.s-content blockquote>:last-child,.s-content dl dd>:last-child,.s-content dl dt>:last-child,.s-content ol>:last-child,.s-content table td>:last-child,.s-content table th>:last-child,.s-content ul>:last-child{margin-bottom:0}.s-content img{max-width:100%;display:block;margin:0 auto}.s-content code{font-family:Monaco,Menlo,Consolas,"Lucida Console","Courier New",monospace;padding-top:.1rem;padding-bottom:.1rem;background:#f9f5f4;border-radius:0;box-shadow:none;display:inline-block;padding:.5ch;border:0}.s-content code:after,.s-content code:before{letter-spacing:-.2em;content:"\00a0"}.s-content pre{background:#f5f2f0;line-height:1.5em;overflow:auto;border:0;border-radius:0;padding:.75em 20px;margin:0 -20px 20px}.s-content pre code{margin:0;padding:0;white-space:pre;box-shadow:none}.s-content pre code,.s-content pre tt{background-color:transparent;border:0}.s-content ins,.s-content u{text-decoration:none;border-bottom:1px solid #15284b}.s-content del a,.s-content ins a,.s-content u a{color:inherit}a.Link--external:after{content:" " url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAVklEQVR4Xn3PgQkAMQhDUXfqTu7kTtkpd5RA8AInfArtQ2iRXFWT2QedAfttj2FsPIOE1eCOlEuoWWjgzYaB/IkeGOrxXhqB+uA9Bfcm0lAZuh+YIeAD+cAqSz4kCMUAAAAASUVORK5CYII=)}a.Link--broken{color:red}p{margin:0 0 1em}.Button{display:inline-block;text-align:center;vertical-align:middle;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;margin-bottom:0}.Button--small{font-size:12px;line-height:1.5;border-radius:3px}.Button--default{color:#333;background-color:#fff;border-color:#ccc}.Button--default.Button--active{color:#333;background-color:#e6e6e6;border-color:#adadad}.Brand,.Navbar{background-color:#e63c2f}.Brand{display:block;padding:.75em .6em;font-size:2rem;text-shadow:none;font-family:"League Gothic",-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Arial,sans-serif;color:#15284b}.Navbar{box-shadow:0 1px 5px rgba(0,0,0,.25);margin-bottom:0}.CodeToggler{padding:0 20px}.CodeToggler__text{font-size:12px;line-height:1.5;padding:6px 10px 6px 0;display:inline-block;vertical-align:middle}.no-js .CodeToggler{display:none}.Nav{margin:0;padding:0}.Nav__arrow{display:inline-block;position:relative;width:16px;margin-left:-16px}.Nav__arrow:before{position:absolute;display:block;content:"";margin:-.25em 0 0 -.4em;left:50%;top:50%;border-right:.15em solid #15284b;border-top:.15em solid #15284b;transform:rotate(45deg);transition-duration:.3s}.Nav__item,.Nav__item a{display:block}.Nav__item a{margin:0;padding:6px 15px 6px 20px;font-family:"League Gothic",-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Arial,sans-serif;font-weight:400;color:#15284b;text-shadow:none}.Nav__item a:hover{color:#15284b;text-shadow:none;background-color:#93b7bb}.Nav .Nav{margin-left:15px}html:not(.no-js) .Nav .Nav{height:0;transition:height 400ms ease-in-out;overflow:hidden}.Nav .Nav .Nav__item a{margin:0 0 0 -15px;padding:3px 30px;font-family:"Cabin","Trebuchet MS",-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Arial,sans-serif;color:#15284b;opacity:.7}.HomepageButtons .Button--hero:hover,.Nav .Nav .Nav__item a:hover{opacity:1}.Nav .Nav .Nav__item--active a{color:#15284b}.Nav__item--active>a,.Nav__item--open>a{background-color:#93b7bb}.Nav__item--open>a>.Nav__arrow:before{margin-left:-.25em;transform:rotate(135deg)}.Page__header{margin:0 0 10px;padding:0}.Page__header:after,.Page__header:before{content:" ";display:table}.Page__header:after{clear:both}.Page__header h1{margin:0;padding:0;line-height:57px}.Page__header--separator{height:.6em}.Page__header a{text-decoration:none}.Page__header .EditOn,.Page__header .ModifiedDate{float:left;font-size:10px;color:gray}.Page__header .EditOn{float:right}.Links,.Twitter{padding:0 20px}.Links a{font-family:"League Gothic",-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Arial,sans-serif;font-weight:400;color:#15284b;line-height:2em}.Twitter{font:11px/18px "Helvetica Neue",Arial,sans-serif}.Twitter__button{text-decoration:none;display:inline-block;vertical-align:top;zoom:1;position:relative;height:20px;box-sizing:border-box;padding:1px 8px 1px 6px;background-color:#1b95e0;color:#fff;border-radius:3px;font-weight:500;cursor:pointer}.Twitter__button .Twitter__button__label{display:inline-block;vertical-align:top;zoom:1;margin-left:3px;white-space:nowrap}.Twitter__button svg{position:relative;top:2px;display:inline-block;width:14px;height:14px}.PoweredBy{padding:0 20px 1rem;font-size:1.309rem}.Search{position:relative}.Search__field{display:block;width:100%;height:34px;padding:6px 30px 6px 20px;color:#555;border-width:0 0 1px;border-bottom:1px solid #ccc;background:#fff;transition:border-color ease-in-out .15s}.Search__field:focus{border-color:#93b7bb;outline:0}.Search__icon{position:absolute;right:9px;top:9px;width:16px;height:16px}.Navbar .Search{float:right;margin:8px 20px}.Navbar .Search__field{box-shadow:inset 0 1px 1px rgba(0,0,0,.075);border-width:0;border-radius:4px;padding-left:10px}.TableOfContentsContainer{float:right;min-width:300px;max-width:25%;padding-left:1em}.TableOfContentsContainer__title{margin-bottom:0!important}.TableOfContentsContainer__content{border:1px solid #efefef;border-width:4px 2px 2px 6px}.TableOfContentsContainer__content>.TableOfContents>li+li{border-top:1px solid #ddd}ul.TableOfContents{font-size:1rem;padding-left:0;margin:0;list-style-type:none;border-left:6px solid #e8d5d3}ul.TableOfContents p{margin-bottom:0}ul.TableOfContents a{text-decoration:none;display:block;padding:.2em 0 .2em .75em}ul.TableOfContents .TableOfContents{padding-left:.75em}.Pager{padding-left:0;margin:1em 0;list-style:none;text-align:center}.Pager:after,.Pager:before{content:" ";display:table}.Pager,.Pager:after{clear:both}.Pager li{display:inline}.Pager li>a{display:inline-block;padding:5px 14px;background-color:#fff}.Pager li>a:focus,.Pager li>a:hover{text-decoration:none}.Pager--next>a{float:right}.Pager--prev>a{float:left}.Checkbox{position:relative;display:block;padding-left:30px;cursor:pointer}.Checkbox input{position:absolute;z-index:-1;opacity:0}.Checkbox__indicator{position:absolute;top:50%;left:0;width:20px;height:20px;margin-top:-10px;background:#e6e6e6}.Checkbox__indicator:after{position:absolute;display:none;content:""}.Checkbox input:focus~.Checkbox__indicator,.Checkbox:hover input~.Checkbox__indicator{background:#ccc}.Checkbox input:checked~.Checkbox__indicator{background:#15284b}.Checkbox input:checked~.Checkbox__indicator:after{display:block}.Checkbox input:checked:focus~.Checkbox__indicator,.Checkbox:hover input:not([disabled]):checked~.Checkbox__indicator{background:#93b7bb}.Checkbox input:disabled~.Checkbox__indicator{pointer-events:none;opacity:.6;background:#e6e6e6}.Checkbox .Checkbox__indicator:after{top:4px;left:8px;width:5px;height:10px;transform:rotate(45deg);border:solid #fff;border-width:0 2px 2px 0}.Checkbox input:disabled~.Checkbox__indicator:after{border-color:#7b7b7b}.Hidden{display:none}.Container{margin-right:auto;margin-left:auto}.Container--inner{width:80%;margin:0 auto}@media (min-width:1200px){.Container{width:1170px}}@media (min-width:992px){.Container{width:970px}}@media (min-width:769px){.Container{width:750px}}.Homepage{background-color:#fff;border-radius:0;border:0;color:#15284b;overflow:hidden;padding-bottom:0;margin-bottom:0;box-shadow:none}.HomepageTitle h2{width:80%;font-size:30px;margin:20px auto;text-align:center}.HomepageImage img{display:block;max-width:80%;margin:0 auto;height:auto}.HomepageButtons{padding:20px 0;background-color:#e8d5d3;text-align:center}.HomepageButtons:after,.HomepageButtons:before{content:" ";display:table}.HomepageButtons:after{clear:both}.HomepageButtons .Button--hero{padding:20px 30px;border-radius:0;text-shadow:none;opacity:.8;margin:0 10px;text-transform:uppercase;border:5px solid #15284b;font-family:"League Gothic",-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Arial,sans-serif;background-image:none;-webkit-filter:none;filter:none;box-shadow:none}@media (max-width:768px){.HomepageButtons .Button--hero{display:block;margin-bottom:10px}}.HomepageButtons .Button--hero.Button--secondary{background-color:#93b7bb;color:#15284b}.HomepageButtons .Button--hero.Button--primary{background-color:#15284b;color:#e8d5d3}.HomepageContent{background-color:#fff;padding:40px 0}.HomepageContent ol li,.HomepageContent ul li{list-style:none;margin-bottom:.5em;position:relative}.HomepageContent ol li:before,.HomepageContent ul li:before{position:absolute;top:50%;left:-1.5em;content:"";width:0;height:0;border:.5em solid transparent;border-left:.5em solid #93b7bb;float:left;display:block;margin-top:-.5em}.HomepageContent .HeroText,.HomepageFooter__links li a{font-size:16px;font-family:"League Gothic",-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Arial,sans-serif}.HomepageContent .HeroText{margin-bottom:20px;font-weight:300;line-height:1.4}@media (min-width:769px){.HomepageContent{padding:40px 20px}.HomepageContent .HeroText{font-size:21px}.HomepageContent .Row{margin:0 -15px}.HomepageContent .Row__half,.HomepageContent .Row__quarter,.HomepageContent .Row__third{float:left;position:relative;min-height:1px;padding-left:15px;padding-right:15px}.HomepageContent .Row__third{width:33.333333%}.HomepageContent .Row__half{width:50%}.HomepageContent .Row__quarter{width:25%}}.HomepageFooter{background-color:#15284b;color:#93b7bb;border:0;box-shadow:none}.HomepageFooter:after,.HomepageFooter:before{content:" ";display:table}.HomepageFooter:after{clear:both}@media (max-width:768px){.HomepageFooter{padding:0 20px;text-align:center}.HomepageFooter .HomepageFooter__links{padding-left:0;list-style-type:none}}@media (min-width:769px){.HomepageFooter .HomepageFooter__links{float:left}.HomepageFooter .HomepageFooter__twitter{float:right}}.HomepageFooter__links,.HomepageFooter__twitter{margin:40px 0}.HomepageFooter__links li a{line-height:32px;font-weight:700}.HomepageFooter__links li a:hover{text-decoration:underline}.HomepageFooter .Twitter__button{margin-bottom:20px}@media print{*{text-shadow:none!important;color:#000!important;background:0 0!important;box-shadow:none!important}h1,h2,h3,h4,h5,h6{page-break-after:avoid;page-break-before:auto}blockquote,img,pre{page-break-inside:avoid}blockquote,pre{font-style:italic;border:1px solid #999}img{border:0}a,a:visited{text-decoration:underline}abbr[title]:after{content:" (" attr(title) ")"}q{quotes:none}.s-content a[href^="#"]:after,q:before{content:""}q:after{content:" (" attr(cite) ")"}.PageBreak{display:block;page-break-before:always}.NoPrint,.Pager,aside{display:none}.Columns__right{width:100%!important}.s-content a:after{content:" (" attr(href) ")";font-size:80%;word-wrap:break-word}h1 a[href]:after{font-size:50%}}@font-face{font-family:'League Gothic';src:url(fonts/leaguegothic.woff2) format('woff2'),url(fonts/leaguegothic.woff) format('woff');font-style:normal;font-display:swap}@font-face{font-family:'Cabin';src:url(fonts/cabin-regular.woff2) format('woff2'),url(fonts/cabin-regular.woff) format('woff');font-weight:400;font-style:normal;font-display:swap}@font-face{font-family:'Cabin';src:url(fonts/cabin-italic.woff2) format('woff2'),url(fonts/cabin-italic.woff) format('woff');font-style:italic;font-display:swap}@font-face{font-family:'Cabin';src:url(fonts/cabin-bold.woff2) format('woff2'),url(fonts/cabin-bold.woff) format('woff');font-weight:700;font-style:normal;font-display:swap}.s-content code::after,.s-content code::before,a.Link--external::after{content:''}pre .s-content code{display:inline}.s-content table tbody,.s-content table thead{background-color:#fff}.s-content table tr:nth-child(2n) td{background-color:#f9f5f4}.s-content table td,.s-content table th{border:0}.Nav__item .Nav__item,.s-content table{font-size:1rem}.Brand,h1,h2,h3,h4,h5,h6{font-weight:400}.Button,.Pager li>a{border-radius:0}.HomepageButtons .Button--hero{font-weight:400;font-size:1.309rem}.Page__header{border-bottom:2px solid #e8d5d3}.Pager li>a{border:2px solid #e8d5d3}.Pager li>a:focus,.Pager li>a:hover{background-color:#e8d5d3}.Pager--prev a::before{content:"\2190\00a0"}.Pager--next a::after{content:"\00a0\2192"}.Navbar{height:auto;box-shadow:none}.Navbar .Brand{float:none;line-height:inherit;height:auto}.Homepage{padding-top:10px!important}.Nav__item{font-size:1.309rem}.Nav .Nav .Nav__item a .Nav__arrow:before,.Nav__arrow:before{font-family:"League Gothic",-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Arial,sans-serif;width:1ch;height:1ch}.TableOfContentsContainer__title{border-bottom:4px solid #e8d5d3}.Columns__right--full .TableOfContentsContainer .TableOfContentsContainer__content>.TableOfContents{border-right:2px solid #e8d5d3}.Columns__right--full .TableOfContentsContainer a{border-bottom:1px solid #e8d5d3}.clients thead tr:first-child th{text-align:left}.clients thead tr:first-child th:first-child{width:15%}.clients thead tr:first-child th:nth-child(3){width:50%;text-align:center}.clients thead tr+tr th{width:16.66%;text-align:center}.clients tbody td:nth-child(3),.clients tbody td:nth-child(4),.clients tbody td:nth-child(5){text-align:center}.clients tbody td.Y{color:#2c9a42}.clients tbody td.N{color:#e63c2f}.hljs,.s-content pre{background:#15284b;color:#e8d5d3}.hljs{display:block;overflow-x:auto;padding:.5em}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.hljs-comment,.hljs-quote{color:#978e9c}.hljs-addition,.hljs-keyword,.hljs-selector-tag{color:#acb39a}.hljs-doctag,.hljs-literal,.hljs-meta .hljs-meta-string,.hljs-number,.hljs-regexp,.hljs-string{color:#93b7bb}.hljs-name,.hljs-section,.hljs-selector-class,.hljs-selector-id,.hljs-title{color:#82b7e5}.hljs-attr,.hljs-attribute,.hljs-class .hljs-title,.hljs-template-variable,.hljs-type,.hljs-variable{color:#c5b031}.hljs-bullet,.hljs-link,.hljs-meta,.hljs-meta .hljs-keyword,.hljs-selector-attr,.hljs-selector-pseudo,.hljs-subst,.hljs-symbol{color:#ea8031}.hljs-built_in,.hljs-deletion{color:#e63c2f}.hljs-formula{background:#686986}@media (min-width:850px){.Columns__left{border:0}} \ No newline at end of file diff --git a/docs/theme/arsse/config.json b/docs/theme/arsse/config.json index 15289802..74f6dd2f 100644 --- a/docs/theme/arsse/config.json +++ b/docs/theme/arsse/config.json @@ -1,8 +1,7 @@ { "favicon": "favicon.png", "js": [ - "highlight.pack.js", - "daux.js" + "daux.min.js" ], "css": [ "arsse.css" diff --git a/docs/theme/arsse/daux.js b/docs/theme/arsse/daux.js deleted file mode 100644 index d215f909..00000000 --- a/docs/theme/arsse/daux.js +++ /dev/null @@ -1,182 +0,0 @@ -/** global localStorage, hljs */ - -if (hljs) { - hljs.initHighlightingOnLoad(); -} - -(function() { - var codeBlocks = document.querySelectorAll(".s-content pre"); - var toggleCodeSection = document.querySelector(".CodeToggler"); - if (!toggleCodeSection) { - return; - } else if (!codeBlocks.length) { - toggleCodeSection.classList.add("Hidden"); - return; - } - - var toggleCodeBlockBtnList = toggleCodeSection.querySelectorAll(".CodeToggler__button"); - var toggleCodeBlockBtnSet = toggleCodeSection.querySelector(".CodeToggler__button--main"); // available when floating is disabled - var toggleCodeBlockBtnHide = toggleCodeSection.querySelector(".CodeToggler__button--hide"); - var toggleCodeBlockBtnBelow = toggleCodeSection.querySelector(".CodeToggler__button--below"); - var toggleCodeBlockBtnFloat = toggleCodeSection.querySelector(".CodeToggler__button--float"); - var codeBlockView = document.querySelector(".Columns__right"); - var floating = document.body.classList.contains("with-float"); - - function setCodeBlockStyle(codeBlockState) { - for (var a = 0; a < toggleCodeBlockBtnList.length; a++) { - toggleCodeBlockBtnList[a].classList.remove("Button--active"); - } - switch (codeBlockState) { - case true: // Show code blocks below (flowed); checkbox - var hidden = false; - break; - case false: // Hidden code blocks; checkbox - var hidden = true; - break; - case 2: // Show code blocks inline (floated) - toggleCodeBlockBtnFloat.classList.add("Button--active"); - codeBlockView.classList.add("Columns__right--float"); - codeBlockView.classList.remove("Columns__right--full"); - var hidden = false; - break; - case 1: // Show code blocks below (flowed) - case "checked": - toggleCodeBlockBtnBelow.classList.add("Button--active"); - codeBlockView.classList.remove("Columns__right--float"); - codeBlockView.classList.add("Columns__right--full"); - var hidden = false; - break; - case 0: // Hidden code blocks - default: - toggleCodeBlockBtnHide.classList.add("Button--active"); - codeBlockView.classList.remove("Columns__right--float"); - codeBlockView.classList.add("Columns__right--full"); - var hidden = true; - break; - } - for (var a = 0; a < codeBlocks.length; a++) { - if (hidden) { - codeBlocks[a].classList.add("Hidden"); - } else { - codeBlocks[a].classList.remove("Hidden"); - } - } - try { - localStorage.setItem("codeBlockState", +codeBlockState); - } catch (e) { - // local storage operations can fail with the file:// protocol - } - } - if (!floating) { - toggleCodeBlockBtnSet.addEventListener("change", function(ev) {setCodeBlockStyle(ev.target.checked);}, false); - } else { - toggleCodeBlockBtnHide.addEventListener("click", function() {setCodeBlockStyle(0);}, false); - toggleCodeBlockBtnBelow.addEventListener("click", function() {setCodeBlockStyle(1);}, false); - toggleCodeBlockBtnFloat.addEventListener("click", function() {setCodeBlockStyle(2);}, false); - } - - try { - var codeBlockState = localStorage.getItem("codeBlockState"); - } catch (e) { - // local storage operations can fail with the file:// protocol - var codeBlockState = null; - } - if (!codeBlockState) { - codeBlockState = floating ? 2 : 1; - } else { - codeBlockState = parseInt(codeBlockState); - } - if (!floating) { - codeBlockState = !!codeBlockState; - } - - setCodeBlockStyle(codeBlockState); -})(); - -(function() { - function debounce(func, wait) { - var timeout; - return function() { - var context = this, args = arguments; - var later = function() { - timeout = null; - }; - - clearTimeout(timeout); - timeout = setTimeout(later, wait); - }; - }; - - var navItems = document.querySelectorAll('.Nav__item.has-children i.Nav__arrow'); - - function _toggleSubMenu(ev) { - if (ev.preventDefault !== undefined) { - ev.preventDefault(); - } - - var parent = ev.target.parentNode.parentNode; - var subNav = parent.querySelector('ul.Nav'); - - if (ev.preventDefault !== undefined && parent.classList.contains('Nav__item--open')) { - // Temporarily set the height so the transition can work. - subNav.style.height = subNav.scrollHeight + 'px'; - subNav.style.transitionDuration = Math.max(subNav.scrollHeight, 150) + 'ms'; - subNav.style.height = '0px'; - parent.classList.remove('Nav__item--open'); - } else { - if (ev.preventDefault !== undefined) { - subNav.style.transitionDuration = Math.max(subNav.scrollHeight, 150) + 'ms'; - // After the transition finishes set the height to auto so child - // menus can expand properly. - subNav.addEventListener('transitionend', _setHeightToAuto); - subNav.style.height = subNav.scrollHeight + 'px'; - parent.classList.add('Nav__item--open'); - } else { - // When running at page load the transitions don't need to fire and - // the classList doesn't need to be altered. - subNav.style.height = 'auto'; - } - } - } - - function _setHeightToAuto(ev) { - if (ev.target.style.height !== '0px') { - ev.target.style.height = 'auto'; - } - - ev.target.removeEventListener('transitionend', _setHeightToAuto); - } - - // Go in reverse here because on page load the child nav items need to be - // opened first before their parents so the height on the parents can be - // calculated properly. - for (var i = navItems.length - 1, cur; i >= 0; i--) { - cur = navItems[i]; - cur.addEventListener('click', _toggleSubMenu); - - if (cur.parentNode.parentNode.classList.contains('Nav__item--open')) { - _toggleSubMenu({ target: cur }); - } - } -})(); - -(function() { - var trigger = document.querySelector('.Collapsible__trigger'); - - if (!trigger) { - return; - } - - content = document.querySelector('.Collapsible__content'); - - trigger.addEventListener('click', function(ev) { - if (content.classList.contains('Collapsible__content--open')) { - content.style.height = 0; - content.classList.remove('Collapsible__content--open'); - } else { - content.style.transitionDuration = Math.max(content.scrollHeight, 150) + 'ms'; - content.style.height = content.scrollHeight + 'px'; - content.classList.add('Collapsible__content--open'); - } - }); -})(); diff --git a/docs/theme/arsse/daux.min.js b/docs/theme/arsse/daux.min.js new file mode 100644 index 00000000..fd875881 --- /dev/null +++ b/docs/theme/arsse/daux.min.js @@ -0,0 +1,2 @@ +var e=document.querySelectorAll(".s-content pre"),t=document.querySelector(".CodeToggler"),n="daux_code_blocks_hidden";function a(t){for(var a=0;a code:not(.hljs)");if(l.length){var i=document.getElementsByTagName("head")[0],c=document.createElement("script");c.type="text/javascript",c.async=!0,c.src="".concat(window.base_url,"daux_libraries/highlight.pack.js"),c.onload=function(e){[].forEach.call(l,window.hljs.highlightBlock)},i.appendChild(c)}function s(e){var t=void 0!==e.preventDefault;t&&e.preventDefault();var n=function(e){for(var t=e;(t=t.parentNode)&&9!==t.nodeType;)if(1===t.nodeType&&t.classList.contains("Nav__item"))return t;throw new Error("Could not find a NavItem...")}(e.target),a=n.querySelector("ul.Nav");t&&n.classList.contains("Nav__item--open")?(a.style.height="".concat(a.scrollHeight,"px"),a.style.transitionDuration="150ms",a.style.height="0px",n.classList.remove("Nav__item--open")):t?(a.style.transitionDuration="150ms",a.addEventListener("transitionend",(function e(t){"0px"!==t.target.style.height&&(t.target.style.height="auto"),t.target.removeEventListener("transitionend",e)})),a.style.height="".concat(a.scrollHeight,"px"),n.classList.add("Nav__item--open")):a.style.height="auto"}for(var d,u=document.querySelectorAll(".Nav__item.has-children i.Nav__arrow"),h=u.length-1;h>=0;h--)(d=u[h]).addEventListener("click",s),d.parentNode.parentNode.classList.contains("Nav__item--open")&&s({target:d});var g=document.querySelectorAll(".Nav__item__link--nopage"),v=!0,p=!1,_=void 0;try{for(var y,m=g[Symbol.iterator]();!(v=(y=m.next()).done);v=!0){y.value.addEventListener("click",s)}}catch(e){p=!0,_=e}finally{try{v||null==m.return||m.return()}finally{if(p)throw _}} +//# sourceMappingURL=daux.min.js.map diff --git a/docs/theme/arsse/highlight.pack.js b/docs/theme/arsse/highlight.pack.js deleted file mode 100644 index f1096b4e..00000000 --- a/docs/theme/arsse/highlight.pack.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! highlight.js v9.15.10 | BSD3 License | git.io/hljslicense */ -!function(e){var n="object"==typeof window&&window||"object"==typeof self&&self;"undefined"==typeof exports||exports.nodeType?n&&(n.hljs=e({}),"function"==typeof define&&define.amd&&define([],function(){return n.hljs})):e(exports)}(function(a){var f=[],u=Object.keys,N={},c={},n=/^(no-?highlight|plain|text)$/i,s=/\blang(?:uage)?-([\w-]+)\b/i,t=/((^(<[^>]+>|\t|)+|(?:\n)))/gm,r={case_insensitive:"cI",lexemes:"l",contains:"c",keywords:"k",subLanguage:"sL",className:"cN",begin:"b",beginKeywords:"bK",end:"e",endsWithParent:"eW",illegal:"i",excludeBegin:"eB",excludeEnd:"eE",returnBegin:"rB",returnEnd:"rE",relevance:"r",variants:"v",IDENT_RE:"IR",UNDERSCORE_IDENT_RE:"UIR",NUMBER_RE:"NR",C_NUMBER_RE:"CNR",BINARY_NUMBER_RE:"BNR",RE_STARTERS_RE:"RSR",BACKSLASH_ESCAPE:"BE",APOS_STRING_MODE:"ASM",QUOTE_STRING_MODE:"QSM",PHRASAL_WORDS_MODE:"PWM",C_LINE_COMMENT_MODE:"CLCM",C_BLOCK_COMMENT_MODE:"CBCM",HASH_COMMENT_MODE:"HCM",NUMBER_MODE:"NM",C_NUMBER_MODE:"CNM",BINARY_NUMBER_MODE:"BNM",CSS_NUMBER_MODE:"CSSNM",REGEXP_MODE:"RM",TITLE_MODE:"TM",UNDERSCORE_TITLE_MODE:"UTM",COMMENT:"C",beginRe:"bR",endRe:"eR",illegalRe:"iR",lexemesRe:"lR",terminators:"t",terminator_end:"tE"},b="",h={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0};function _(e){return e.replace(/&/g,"&").replace(//g,">")}function E(e){return e.nodeName.toLowerCase()}function v(e,n){var t=e&&e.exec(n);return t&&0===t.index}function l(e){return n.test(e)}function g(e){var n,t={},r=Array.prototype.slice.call(arguments,1);for(n in e)t[n]=e[n];return r.forEach(function(e){for(n in e)t[n]=e[n]}),t}function R(e){var a=[];return function e(n,t){for(var r=n.firstChild;r;r=r.nextSibling)3===r.nodeType?t+=r.nodeValue.length:1===r.nodeType&&(a.push({event:"start",offset:t,node:r}),t=e(r,t),E(r).match(/br|hr|img|input/)||a.push({event:"stop",offset:t,node:r}));return t}(e,0),a}function i(e){if(r&&!e.langApiRestored){for(var n in e.langApiRestored=!0,r)e[n]&&(e[r[n]]=e[n]);(e.c||[]).concat(e.v||[]).forEach(i)}}function m(o){function s(e){return e&&e.source||e}function c(e,n){return new RegExp(s(e),"m"+(o.cI?"i":"")+(n?"g":""))}!function n(t,e){if(!t.compiled){if(t.compiled=!0,t.k=t.k||t.bK,t.k){function r(t,e){o.cI&&(e=e.toLowerCase()),e.split(" ").forEach(function(e){var n=e.split("|");a[n[0]]=[t,n[1]?Number(n[1]):1]})}var a={};"string"==typeof t.k?r("keyword",t.k):u(t.k).forEach(function(e){r(e,t.k[e])}),t.k=a}t.lR=c(t.l||/\w+/,!0),e&&(t.bK&&(t.b="\\b("+t.bK.split(" ").join("|")+")\\b"),t.b||(t.b=/\B|\b/),t.bR=c(t.b),t.endSameAsBegin&&(t.e=t.b),t.e||t.eW||(t.e=/\B|\b/),t.e&&(t.eR=c(t.e)),t.tE=s(t.e)||"",t.eW&&e.tE&&(t.tE+=(t.e?"|":"")+e.tE)),t.i&&(t.iR=c(t.i)),null==t.r&&(t.r=1),t.c||(t.c=[]),t.c=Array.prototype.concat.apply([],t.c.map(function(e){return function(n){return n.v&&!n.cached_variants&&(n.cached_variants=n.v.map(function(e){return g(n,{v:null},e)})),n.cached_variants||n.eW&&[g(n)]||[n]}("self"===e?t:e)})),t.c.forEach(function(e){n(e,t)}),t.starts&&n(t.starts,e);var i=t.c.map(function(e){return e.bK?"\\.?(?:"+e.b+")\\.?":e.b}).concat([t.tE,t.i]).map(s).filter(Boolean);t.t=i.length?c(function(e,n){for(var t=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./,r=0,a="",i=0;i')+n+(t?"":b):n}function o(){E+=null!=l.sL?function(){var e="string"==typeof l.sL;if(e&&!N[l.sL])return _(g);var n=e?C(l.sL,g,!0,f[l.sL]):O(g,l.sL.length?l.sL:void 0);return 0")+'"');return g+=n,n.length||1}var s=B(e);if(!s)throw new Error('Unknown language: "'+e+'"');m(s);var a,l=t||s,f={},E="";for(a=l;a!==s;a=a.parent)a.cN&&(E=c(a.cN,"",!0)+E);var g="",R=0;try{for(var d,p,M=0;l.t.lastIndex=M,d=l.t.exec(n);)p=r(n.substring(M,d.index),d[0]),M=d.index+p;for(r(n.substr(M)),a=l;a.parent;a=a.parent)a.cN&&(E+=b);return{r:R,value:E,language:e,top:l}}catch(e){if(e.message&&-1!==e.message.indexOf("Illegal"))return{r:0,value:_(n)};throw e}}function O(t,e){e=e||h.languages||u(N);var r={r:0,value:_(t)},a=r;return e.filter(B).filter(M).forEach(function(e){var n=C(e,t,!1);n.language=e,n.r>a.r&&(a=n),n.r>r.r&&(a=r,r=n)}),a.language&&(r.second_best=a),r}function d(e){return h.tabReplace||h.useBR?e.replace(t,function(e,n){return h.useBR&&"\n"===e?"
":h.tabReplace?n.replace(/\t/g,h.tabReplace):""}):e}function o(e){var n,t,r,a,i,o=function(e){var n,t,r,a,i=e.className+" ";if(i+=e.parentNode?e.parentNode.className:"",t=s.exec(i))return B(t[1])?t[1]:"no-highlight";for(n=0,r=(i=i.split(/\s+/)).length;n/g,"\n"):n=e,i=n.textContent,r=o?C(o,i,!0):O(i),(t=R(n)).length&&((a=document.createElementNS("http://www.w3.org/1999/xhtml","div")).innerHTML=r.value,r.value=function(e,n,t){var r=0,a="",i=[];function o(){return e.length&&n.length?e[0].offset!==n[0].offset?e[0].offset"}function u(e){a+=""}function s(e){("start"===e.event?c:u)(e.node)}for(;e.length||n.length;){var l=o();if(a+=_(t.substring(r,l[0].offset)),r=l[0].offset,l===e){for(i.reverse().forEach(u);s(l.splice(0,1)[0]),(l=o())===e&&l.length&&l[0].offset===r;);i.reverse().forEach(c)}else"start"===l[0].event?i.push(l[0].node):i.pop(),s(l.splice(0,1)[0])}return a+_(t.substr(r))}(t,R(a),i)),r.value=d(r.value),e.innerHTML=r.value,e.className=function(e,n,t){var r=n?c[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),-1===e.indexOf(r)&&a.push(r),a.join(" ").trim()}(e.className,o,r.language),e.result={language:r.language,re:r.r},r.second_best&&(e.second_best={language:r.second_best.language,re:r.second_best.r}))}function p(){if(!p.called){p.called=!0;var e=document.querySelectorAll("pre code");f.forEach.call(e,o)}}function B(e){return e=(e||"").toLowerCase(),N[e]||N[c[e]]}function M(e){var n=B(e);return n&&!n.disableAutodetect}return a.highlight=C,a.highlightAuto=O,a.fixMarkup=d,a.highlightBlock=o,a.configure=function(e){h=g(h,e)},a.initHighlighting=p,a.initHighlightingOnLoad=function(){addEventListener("DOMContentLoaded",p,!1),addEventListener("load",p,!1)},a.registerLanguage=function(n,e){var t=N[n]=e(a);i(t),t.aliases&&t.aliases.forEach(function(e){c[e]=n})},a.listLanguages=function(){return u(N)},a.getLanguage=B,a.autoDetection=M,a.inherit=g,a.IR=a.IDENT_RE="[a-zA-Z]\\w*",a.UIR=a.UNDERSCORE_IDENT_RE="[a-zA-Z_]\\w*",a.NR=a.NUMBER_RE="\\b\\d+(\\.\\d+)?",a.CNR=a.C_NUMBER_RE="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",a.BNR=a.BINARY_NUMBER_RE="\\b(0b[01]+)",a.RSR=a.RE_STARTERS_RE="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",a.BE=a.BACKSLASH_ESCAPE={b:"\\\\[\\s\\S]",r:0},a.ASM=a.APOS_STRING_MODE={cN:"string",b:"'",e:"'",i:"\\n",c:[a.BE]},a.QSM=a.QUOTE_STRING_MODE={cN:"string",b:'"',e:'"',i:"\\n",c:[a.BE]},a.PWM=a.PHRASAL_WORDS_MODE={b:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},a.C=a.COMMENT=function(e,n,t){var r=a.inherit({cN:"comment",b:e,e:n,c:[]},t||{});return r.c.push(a.PWM),r.c.push({cN:"doctag",b:"(?:TODO|FIXME|NOTE|BUG|XXX):",r:0}),r},a.CLCM=a.C_LINE_COMMENT_MODE=a.C("//","$"),a.CBCM=a.C_BLOCK_COMMENT_MODE=a.C("/\\*","\\*/"),a.HCM=a.HASH_COMMENT_MODE=a.C("#","$"),a.NM=a.NUMBER_MODE={cN:"number",b:a.NR,r:0},a.CNM=a.C_NUMBER_MODE={cN:"number",b:a.CNR,r:0},a.BNM=a.BINARY_NUMBER_MODE={cN:"number",b:a.BNR,r:0},a.CSSNM=a.CSS_NUMBER_MODE={cN:"number",b:a.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},a.RM=a.REGEXP_MODE={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[a.BE,{b:/\[/,e:/\]/,r:0,c:[a.BE]}]},a.TM=a.TITLE_MODE={cN:"title",b:a.IR,r:0},a.UTM=a.UNDERSCORE_TITLE_MODE={cN:"title",b:a.UIR,r:0},a.METHOD_GUARD={b:"\\.\\s*"+a.UIR,r:0},a});hljs.registerLanguage("bash",function(e){var t={cN:"variable",v:[{b:/\$[\w\d#@][\w\d_]*/},{b:/\$\{(.*?)}/}]},s={cN:"string",b:/"/,e:/"/,c:[e.BE,t,{cN:"variable",b:/\$\(/,e:/\)/,c:[e.BE]}]};return{aliases:["sh","zsh"],l:/\b-?[a-z\._]+\b/,k:{keyword:"if then else elif fi for while in do done case esac function",literal:"true false",built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp",_:"-ne -eq -lt -gt -f -d -e -s -l -a"},c:[{cN:"meta",b:/^#![^\n]+sh\s*$/,r:10},{cN:"function",b:/\w[\w\d_]*\s*\(\s*\)\s*\{/,rB:!0,c:[e.inherit(e.TM,{b:/\w[\w\d_]*/})],r:0},e.HCM,s,{cN:"",b:/\\"/},{cN:"string",b:/'/,e:/'/},t]}});hljs.registerLanguage("shell",function(s){return{aliases:["console"],c:[{cN:"meta",b:"^\\s{0,3}[\\w\\d\\[\\]()@-]*[>%$#]",starts:{e:"$",sL:"bash"}}]}});hljs.registerLanguage("php",function(e){var c={b:"\\$+[a-zA-Z_-ÿ][a-zA-Z0-9_-ÿ]*"},i={cN:"meta",b:/<\?(php)?|\?>/},t={cN:"string",c:[e.BE,i],v:[{b:'b"',e:'"'},{b:"b'",e:"'"},e.inherit(e.ASM,{i:null}),e.inherit(e.QSM,{i:null})]},a={v:[e.BNM,e.CNM]};return{aliases:["php","php3","php4","php5","php6","php7"],cI:!0,k:"and include_once list abstract global private echo interface as static endswitch array null if endwhile or const for endforeach self var while isset public protected exit foreach throw elseif include __FILE__ empty require_once do xor return parent clone use __CLASS__ __LINE__ else break print eval new catch __METHOD__ case exception default die require __FUNCTION__ enddeclare final try switch continue endfor endif declare unset true false trait goto instanceof insteadof __DIR__ __NAMESPACE__ yield finally",c:[e.HCM,e.C("//","$",{c:[i]}),e.C("/\\*","\\*/",{c:[{cN:"doctag",b:"@[A-Za-z]+"}]}),e.C("__halt_compiler.+?;",!1,{eW:!0,k:"__halt_compiler",l:e.UIR}),{cN:"string",b:/<<<['"]?\w+['"]?$/,e:/^\w+;?$/,c:[e.BE,{cN:"subst",v:[{b:/\$\w+/},{b:/\{\$/,e:/\}/}]}]},i,{cN:"keyword",b:/\$this\b/},c,{b:/(::|->)+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/},{cN:"function",bK:"function",e:/[;{]/,eE:!0,i:"\\$|\\[|%",c:[e.UTM,{cN:"params",b:"\\(",e:"\\)",c:["self",c,e.CBCM,t,a]}]},{cN:"class",bK:"class interface",e:"{",eE:!0,i:/[:\(\$"]/,c:[{bK:"extends implements"},e.UTM]},{bK:"namespace",e:";",i:/[\.']/,c:[e.UTM]},{bK:"use",e:";",c:[e.UTM]},{b:"=>"},t,a]}});hljs.registerLanguage("apache",function(e){var r={cN:"number",b:"[\\$%]\\d+"};return{aliases:["apacheconf"],cI:!0,c:[e.HCM,{cN:"section",b:""},{cN:"attribute",b:/\w+/,r:0,k:{nomarkup:"order deny allow setenv rewriterule rewriteengine rewritecond documentroot sethandler errordocument loadmodule options header listen serverroot servername"},starts:{e:/$/,r:0,k:{literal:"on off all"},c:[{cN:"meta",b:"\\s\\[",e:"\\]$"},{cN:"variable",b:"[\\$%]\\{",e:"\\}",c:["self",r]},r,e.QSM]}}],i:/\S/}});hljs.registerLanguage("xml",function(s){var e={eW:!0,i:/`]+/}]}]}]};return{aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist","wsf"],cI:!0,c:[{cN:"meta",b:"",r:10,c:[{b:"\\[",e:"\\]"}]},s.C("\x3c!--","--\x3e",{r:10}),{b:"<\\!\\[CDATA\\[",e:"\\]\\]>",r:10},{cN:"meta",b:/<\?xml/,e:/\?>/,r:10},{b:/<\?(php)?/,e:/\?>/,sL:"php",c:[{b:"/\\*",e:"\\*/",skip:!0},{b:'b"',e:'"',skip:!0},{b:"b'",e:"'",skip:!0},s.inherit(s.ASM,{i:null,cN:null,c:null,skip:!0}),s.inherit(s.QSM,{i:null,cN:null,c:null,skip:!0})]},{cN:"tag",b:"|$)",e:">",k:{name:"style"},c:[e],starts:{e:"",rE:!0,sL:["css","xml"]}},{cN:"tag",b:"|$)",e:">",k:{name:"script"},c:[e],starts:{e:"<\/script>",rE:!0,sL:["actionscript","javascript","handlebars","xml","vbscript"]}},{cN:"tag",b:"",c:[{cN:"name",b:/[^\/><\s]+/,r:0},e]}]}});hljs.registerLanguage("nginx",function(e){var r={cN:"variable",v:[{b:/\$\d+/},{b:/\$\{/,e:/}/},{b:"[\\$\\@]"+e.UIR}]},b={eW:!0,l:"[a-z/_]+",k:{literal:"on off yes no true false none blocked debug info notice warn error crit select break last permanent redirect kqueue rtsig epoll poll /dev/poll"},r:0,i:"=>",c:[e.HCM,{cN:"string",c:[e.BE,r],v:[{b:/"/,e:/"/},{b:/'/,e:/'/}]},{b:"([a-z]+):/",e:"\\s",eW:!0,eE:!0,c:[r]},{cN:"regexp",c:[e.BE,r],v:[{b:"\\s\\^",e:"\\s|{|;",rE:!0},{b:"~\\*?\\s+",e:"\\s|{|;",rE:!0},{b:"\\*(\\.[a-z\\-]+)+"},{b:"([a-z\\-]+\\.)+\\*"}]},{cN:"number",b:"\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d{1,5})?\\b"},{cN:"number",b:"\\b\\d+[kKmMgGdshdwy]*\\b",r:0},r]};return{aliases:["nginxconf"],c:[e.HCM,{b:e.UIR+"\\s+{",rB:!0,e:"{",c:[{cN:"section",b:e.UIR}],r:0},{b:e.UIR+"\\s",e:";|{",rB:!0,c:[{cN:"attribute",b:e.UIR,starts:b}],r:0}],i:"[^\\s\\}]"}}); \ No newline at end of file diff --git a/docs/theme/src/arsse.scss b/docs/theme/src/arsse.scss index 6f6f8c69..43a26c19 100644 --- a/docs/theme/src/arsse.scss +++ b/docs/theme/src/arsse.scss @@ -1,12 +1,12 @@ /* Daux imports; fonts are omitted */ -@import "../../../vendor-bin/daux/vendor/daux/daux.io/themes/daux/scss/vendor/normalize.scss"; -@import "../../../vendor-bin/daux/vendor/daux/daux.io/themes/daux/scss/_variables.scss"; -@import "../../../vendor-bin/daux/vendor/daux/daux.io/themes/daux/scss/_mixins.scss"; -@import "../../../vendor-bin/daux/vendor/daux/daux.io/themes/daux/scss/_structure.scss"; -@import "../../../vendor-bin/daux/vendor/daux/daux.io/themes/daux/scss/_typography.scss"; -@import "../../../vendor-bin/daux/vendor/daux/daux.io/themes/daux/scss/_components.scss"; -@import "../../../vendor-bin/daux/vendor/daux/daux.io/themes/daux/scss/_homepage.scss"; -@import "../../../vendor-bin/daux/vendor/daux/daux.io/themes/daux/scss/_print.scss" print; +@import "../../../vendor-bin/daux/vendor/daux/daux.io/src/css/theme_daux/vendor/normalize.scss"; +@import "../../../vendor-bin/daux/vendor/daux/daux.io/src/css/theme_daux/_variables.scss"; +@import "../../../vendor-bin/daux/vendor/daux/daux.io/src/css/theme_daux/_mixins.scss"; +@import "../../../vendor-bin/daux/vendor/daux/daux.io/src/css/theme_daux/_structure.scss"; +@import "../../../vendor-bin/daux/vendor/daux/daux.io/src/css/theme_daux/_typography.scss"; +@import "../../../vendor-bin/daux/vendor/daux/daux.io/src/css/theme_daux/_components.scss"; +@import "../../../vendor-bin/daux/vendor/daux/daux.io/src/css/theme_daux/_homepage.scss"; +@import "../../../vendor-bin/daux/vendor/daux/daux.io/src/css/theme_daux/_print.scss" print; diff --git a/lib/Arsse.php b/lib/Arsse.php index 82c43327..68088311 100644 --- a/lib/Arsse.php +++ b/lib/Arsse.php @@ -7,7 +7,7 @@ declare(strict_types=1); namespace JKingWeb\Arsse; class Arsse { - const VERSION = "0.8.0"; + const VERSION = "0.8.1"; /** @var Lang */ public static $lang; diff --git a/lib/CLI.php b/lib/CLI.php index bbd99300..702b9f52 100644 --- a/lib/CLI.php +++ b/lib/CLI.php @@ -206,7 +206,7 @@ USAGE_TEXT; $this->logError($e->getMessage()); return $e->getCode(); } - } + } // @codeCoverageIgnore /** @codeCoverageIgnore */ protected function logError(string $msg) { @@ -248,7 +248,7 @@ USAGE_TEXT; case "": return $this->userList(); } - } + } // @codeCoverageIgnore protected function userAddOrSetPassword(string $method, string $user, string $password = null, string $oldpass = null): int { $passwd = Arsse::$user->$method(...array_slice(func_get_args(), 1)); diff --git a/lib/Conf.php b/lib/Conf.php index 15a8345d..13635c89 100644 --- a/lib/Conf.php +++ b/lib/Conf.php @@ -264,6 +264,7 @@ class Conf { $type |= Value::M_NULL; } } else { + // catch-all for custom properties $type = Value::T_MIXED; // @codeCoverageIgnore } $out[$p->name] = ['name' => $match[0], 'const' => $type]; @@ -286,6 +287,7 @@ class Conf { } switch (self::EXPECTED_TYPES[$key] ?? gettype($this->$key)) { case "integer": + // no properties are currently typed as integers return Value::normalize($value, Value::T_INT | $mode); // @codeCoverageIgnore case "double": return Value::normalize($value, Value::T_FLOAT | $mode); @@ -293,6 +295,7 @@ class Conf { case "object": return $value; default: + // this should never occur throw new Conf\Exception("ambiguousDefault", ['param' => $key]); // @codeCoverageIgnore } } diff --git a/lib/Database.php b/lib/Database.php index b50f0409..4036f91d 100644 --- a/lib/Database.php +++ b/lib/Database.php @@ -78,21 +78,6 @@ class Database { return debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3)[2]['function']; } - /** Lists the available database drivers, as an associative array with - * fully-qualified class names as keys, and human-readable descriptions as values - */ - public static function driverList(): array { - $sep = \DIRECTORY_SEPARATOR; - $path = __DIR__.$sep."Db".$sep; - $classes = []; - foreach (glob($path."*".$sep."Driver.php") as $file) { - $name = basename(dirname($file)); - $class = NS_BASE."Db\\$name\\Driver"; - $classes[$class] = $class::driverName(); - } - return $classes; - } - /** Returns the current (actual) schema version of the database; compared against self::SCHEMA_VERSION to know when an upgrade is required */ public function driverSchemaVersion(): int { return $this->db->schemaVersion(); diff --git a/lib/Db/AbstractStatement.php b/lib/Db/AbstractStatement.php index cc8ce422..45b6801e 100644 --- a/lib/Db/AbstractStatement.php +++ b/lib/Db/AbstractStatement.php @@ -46,23 +46,14 @@ abstract class AbstractStatement implements Statement { return $query; } - public function retypeArray(array $bindings, bool $append = false): bool { - if (!$append) { - $this->types = []; - } - foreach ($bindings as $binding) { - if (is_array($binding)) { - // recursively flatten any arrays, which may be provided for SET or IN() clauses - $this->retypeArray($binding, true); - } else { - $bindId = self::TYPES[trim(strtolower($binding))] ?? 0; - assert($bindId, new Exception("paramTypeInvalid", $binding)); - $this->types[] = $bindId; - } - } - if (!$append) { - $this->prepare(static::mungeQuery($this->query, $this->types)); + public function retypeArray(array $bindings): bool { + $this->types = []; + foreach (ValueInfo::flatten($bindings) as $binding) { // recursively flatten any arrays, which may be provided for SET or IN() clauses + $bindId = self::TYPES[trim(strtolower($binding))] ?? 0; + assert($bindId, new Exception("paramTypeInvalid", $binding)); + $this->types[] = $bindId; } + $this->prepare(static::mungeQuery($this->query, $this->types)); return true; } @@ -79,26 +70,22 @@ abstract class AbstractStatement implements Statement { } } - protected function bindValues(array $values, int $offset = null): int { - $a = (int) $offset; - foreach ($values as $value) { - if (is_array($value)) { - // recursively flatten any arrays, which may be provided for SET or IN() clauses - $a += $this->bindValues($value, $a); - } elseif (array_key_exists($a, $this->types)) { + protected function bindValues(array $values): bool { + // recursively flatten any arrays, which may be provided for SET or IN() clauses + $values = ValueInfo::flatten($values); + foreach ($values as $a => $value) { + if (array_key_exists($a, $this->types)) { $value = $this->cast($value, $this->types[$a]); $this->bindValue($value, $this->types[$a] % self::T_NOT_NULL, ++$a); } else { throw new Exception("paramTypeMissing", $a+1); } } - // once the last value is bound, check that all parameters have been supplied values and bind null for any missing ones + // once all values are bound, check that all parameters have been supplied values and bind null for any missing ones // SQLite will happily substitute null for a missing value, but other engines (viz. PostgreSQL) produce an error - if (is_null($offset)) { - while ($a < sizeof($this->types)) { - $this->bindValue(null, $this->types[$a] % self::T_NOT_NULL, ++$a); - } + for ($a = sizeof($values); $a < sizeof($this->types); $a++) { + $this->bindValue(null, $this->types[$a] % self::T_NOT_NULL, $a + 1); } - return $a - $offset; + return true; } } diff --git a/lib/Db/SQLite3/AbstractPDODriver.php b/lib/Db/SQLite3/AbstractPDODriver.php index a743a254..bc7ea614 100644 --- a/lib/Db/SQLite3/AbstractPDODriver.php +++ b/lib/Db/SQLite3/AbstractPDODriver.php @@ -7,5 +7,7 @@ declare(strict_types=1); namespace JKingWeb\Arsse\Db\SQLite3; abstract class AbstractPDODriver extends Driver { + // this class exists solely so SQLite's PDO driver can call methods of the generic PDO driver via parent::method() + // if there's a better way to do this, please FIXME ;) use \JKingWeb\Arsse\Db\PDODriver; } diff --git a/lib/ImportExport/AbstractImportExport.php b/lib/ImportExport/AbstractImportExport.php index f882ea16..19fa5fc7 100644 --- a/lib/ImportExport/AbstractImportExport.php +++ b/lib/ImportExport/AbstractImportExport.php @@ -57,7 +57,7 @@ abstract class AbstractImportExport { } if (!isset($folderMap[$id])) { // if no existing folder exists, add one - $folderMap[$id] = Arsse::$db->folderAdd($user, ['name' => $f['name'], 'parent' -> $parent]); + $folderMap[$id] = Arsse::$db->folderAdd($user, ['name' => $f['name'], 'parent' => $parent]); } } // process newsfeed subscriptions @@ -118,21 +118,21 @@ abstract class AbstractImportExport { foreach (array_diff(array_column($feedsDb, "id"), $feedMap) as $id) { try { Arsse::$db->subscriptionRemove($user, $id); - } catch (InputException $e) { + } catch (InputException $e) { // @codeCoverageIgnore // ignore errors } } foreach (array_diff(array_column($foldersDb, "id"), $folderMap) as $id) { try { Arsse::$db->folderRemove($user, $id); - } catch (InputException $e) { + } catch (InputException $e) { // @codeCoverageIgnore // ignore errors } } foreach (array_diff(array_column($tagsDb, "name"), array_keys($tagMap)) as $id) { try { Arsse::$db->tagRemove($user, $id, true); - } catch (InputException $e) { + } catch (InputException $e) { // @codeCoverageIgnore // ignore errors } } diff --git a/lib/Misc/Query.php b/lib/Misc/Query.php index 55d2cac8..95b5c2c0 100644 --- a/lib/Misc/Query.php +++ b/lib/Misc/Query.php @@ -29,61 +29,63 @@ class Query { $this->setBody($body, $types, $values); } - public function setBody(string $body = "", $types = null, $values = null): bool { + public function setBody(string $body = "", $types = null, $values = null): self { $this->qBody = $body; if (!is_null($types)) { $this->tBody[] = $types; $this->vBody[] = $values; } - return true; + return $this; } - public function setCTE(string $tableSpec, string $body, $types = null, $values = null): bool { + public function setCTE(string $tableSpec, string $body, $types = null, $values = null): self { $this->qCTE[] = "$tableSpec as ($body)"; if (!is_null($types)) { $this->tCTE[] = $types; $this->vCTE[] = $values; } - return true; + return $this; } - public function setWhere(string $where, $types = null, $values = null): bool { + public function setWhere(string $where, $types = null, $values = null): self { $this->qWhere[] = $where; if (!is_null($types)) { $this->tWhere[] = $types; $this->vWhere[] = $values; } - return true; + return $this; } - public function setWhereNot(string $where, $types = null, $values = null): bool { + public function setWhereNot(string $where, $types = null, $values = null): self { $this->qWhereNot[] = $where; if (!is_null($types)) { $this->tWhereNot[] = $types; $this->vWhereNot[] = $values; } - return true; + return $this; } - public function setGroup(string ...$column): bool { + public function setGroup(string ...$column): self { foreach ($column as $col) { $this->group[] = $col; } - return true; + return $this; } - public function setOrder(string $order): bool { - $this->order[] = $order; - return true; + public function setOrder(string ...$order): self { + foreach ($order as $o) { + $this->order[] = $o; + } + return $this; } - public function setLimit(int $limit, int $offset = 0): bool { + public function setLimit(int $limit, int $offset = 0): self { $this->limit = $limit; $this->offset = $offset; - return true; + return $this; } - public function pushCTE(string $tableSpec): bool { + public function pushCTE(string $tableSpec): self { // this function takes the query body and converts it to a common table expression, putting it at the bottom of the existing CTE stack // all WHERE, ORDER BY, and LIMIT parts belong to the new CTE and are removed from the main query $this->setCTE($tableSpec, $this->buildQueryBody(), [$this->tBody, $this->tWhere, $this->tWhereNot], [$this->vBody, $this->vWhere, $this->vWhereNot]); @@ -98,7 +100,7 @@ class Query { $this->order = []; $this->group = []; $this->setLimit(0, 0); - return true; + return $this; } public function __toString(): string { @@ -117,11 +119,11 @@ class Query { } public function getTypes(): array { - return [$this->tCTE, $this->tBody, $this->tWhere, $this->tWhereNot]; + return ValueInfo::flatten([$this->tCTE, $this->tBody, $this->tWhere, $this->tWhereNot]); } public function getValues(): array { - return [$this->vCTE, $this->vBody, $this->vWhere, $this->vWhereNot]; + return ValueInfo::flatten([$this->vCTE, $this->vBody, $this->vWhere, $this->vWhereNot]); } protected function buildQueryBody(): string { @@ -144,9 +146,9 @@ class Query { if (sizeof($this->order)) { $out .= " ORDER BY ".implode(", ", $this->order); } - // add LIMIT and OFFSET if the former is specified - if ($this->limit > 0) { - $out .= " LIMIT ".$this->limit; + // add LIMIT and OFFSET if either is specified + if ($this->limit > 0 || $this->offset > 0) { + $out .= " LIMIT ".($this->limit < 1 ? -1 : $this->limit); if ($this->offset > 0) { $out .= " OFFSET ".$this->offset; } diff --git a/lib/Misc/URL.php b/lib/Misc/URL.php index da49effb..4a4459ce 100644 --- a/lib/Misc/URL.php +++ b/lib/Misc/URL.php @@ -145,7 +145,7 @@ class URL { } /** Appends data to a URL's query component - * + * * @param string $url The input URL * @param string $data The data to append. This should already be escaped where necessary and not start with any delimiter * @param string $glue The query subcomponent delimiter, usually "&". If the URL has no query, "?" will be prepended instead diff --git a/lib/Misc/ValueInfo.php b/lib/Misc/ValueInfo.php index 752704d0..1b3d2608 100644 --- a/lib/Misc/ValueInfo.php +++ b/lib/Misc/ValueInfo.php @@ -397,6 +397,17 @@ class ValueInfo { } } + public static function flatten(array $arr): array { + $arr = array_values($arr); + for ($a = 0; $a < sizeof($arr); $a++) { + if (is_array($arr[$a])) { + array_splice($arr, $a, 1, $arr[$a]); + $a--; + } + } + return $arr; + } + public static function int($value): int { $out = 0; if (is_null($value)) { diff --git a/lib/REST/Fever/API.php b/lib/REST/Fever/API.php index a83b3e1a..1569c928 100644 --- a/lib/REST/Fever/API.php +++ b/lib/REST/Fever/API.php @@ -209,7 +209,8 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler { // indexed arrays $p->appendChild($this->makeXMLIndexed($v, $d->createElement($k), substr($k, 0, strlen($k) - 1))); } else { - $p->appendChild($this->makeXMLAssoc($v, $d->createElement($k))); + // this case is never encountered with Fever's output + $p->appendChild($this->makeXMLAssoc($v, $d->createElement($k))); // @codeCoverageIgnore } } return $p; diff --git a/lib/Service.php b/lib/Service.php index 93d4e9ba..ed234d68 100644 --- a/lib/Service.php +++ b/lib/Service.php @@ -12,30 +12,14 @@ class Service { const DRIVER_NAMES = [ 'serial' => \JKingWeb\Arsse\Service\Serial\Driver::class, 'subprocess' => \JKingWeb\Arsse\Service\Subprocess\Driver::class, - 'curl' => \JKingWeb\Arsse\Service\Curl\Driver::class, ]; /** @var Service\Driver */ protected $drv; - /** @var \DateInterval */ - protected $interval; - - public static function driverList(): array { - $sep = \DIRECTORY_SEPARATOR; - $path = __DIR__.$sep."Service".$sep; - $classes = []; - foreach (glob($path."*".$sep."Driver.php") as $file) { - $name = basename(dirname($file)); - $class = NS_BASE."User\\$name\\Driver"; - $classes[$class] = $class::driverName(); - } - return $classes; - } public function __construct() { $driver = Arsse::$conf->serviceDriver; $this->drv = new $driver(); - $this->interval = Arsse::$conf->serviceFrequency; } public function watch(bool $loop = true): \DateTimeInterface { @@ -46,17 +30,19 @@ class Service { $list = Arsse::$db->feedListStale(); if ($list) { $this->drv->queue(...$list); + unset($list); $this->drv->exec(); $this->drv->clean(); - unset($list); } static::cleanupPost(); - $t->add($this->interval); + $t->add(Arsse::$conf->serviceFrequency); + // @codeCoverageIgnoreStart if ($loop) { do { @time_sleep_until($t->getTimestamp()); } while ($t->getTimestamp() > time()); } + // @codeCoverageIgnoreEnd } while ($loop); return $t; } diff --git a/lib/Service/Driver.php b/lib/Service/Driver.php index 0f633838..e2dcf929 100644 --- a/lib/Service/Driver.php +++ b/lib/Service/Driver.php @@ -11,5 +11,5 @@ interface Driver { public static function requirementsMet(): bool; public function queue(int ...$feeds): int; public function exec(): int; - public function clean(): bool; + public function clean(): int; } diff --git a/lib/Service/Serial/Driver.php b/lib/Service/Serial/Driver.php index df3580c8..dc2c74f0 100644 --- a/lib/Service/Serial/Driver.php +++ b/lib/Service/Serial/Driver.php @@ -36,8 +36,9 @@ class Driver implements \JKingWeb\Arsse\Service\Driver { return Arsse::$conf->serviceQueueWidth - sizeof($this->queue); } - public function clean(): bool { + public function clean(): int { + $out = sizeof($this->queue); $this->queue = []; - return true; + return $out; } } diff --git a/lib/Service/Subprocess/Driver.php b/lib/Service/Subprocess/Driver.php index 5e79ed09..0986f2c0 100644 --- a/lib/Service/Subprocess/Driver.php +++ b/lib/Service/Subprocess/Driver.php @@ -33,7 +33,7 @@ class Driver implements \JKingWeb\Arsse\Service\Driver { $id = (int) array_shift($this->queue); $php = escapeshellarg(\PHP_BINARY); $arsse = escapeshellarg($_SERVER['argv'][0]); - array_push($pp, popen("$php $arsse feed refresh $id", "r")); + array_push($pp, $this->execCmd("$php $arsse feed refresh $id")); } while ($pp) { $p = array_pop($pp); @@ -43,8 +43,14 @@ class Driver implements \JKingWeb\Arsse\Service\Driver { return Arsse::$conf->serviceQueueWidth - sizeof($this->queue); } - public function clean(): bool { + /** @codeCoverageIgnore */ + protected function execCmd(string $cmd) { + return popen($cmd, "r"); + } + + public function clean(): int { + $out = sizeof($this->queue); $this->queue = []; - return true; + return $out; } } diff --git a/lib/User.php b/lib/User.php index 691d6faf..713f17c3 100644 --- a/lib/User.php +++ b/lib/User.php @@ -20,18 +20,6 @@ class User { */ protected $u; - public static function driverList(): array { - $sep = \DIRECTORY_SEPARATOR; - $path = __DIR__.$sep."User".$sep; - $classes = []; - foreach (glob($path."*".$sep."Driver.php") as $file) { - $name = basename(dirname($file)); - $class = NS_BASE."User\\$name\\Driver"; - $classes[$class] = $class::driverName(); - } - return $classes; - } - public function __construct(\JKingWeb\Arsse\User\Driver $driver = null) { $this->u = $driver ?? new Arsse::$conf->userDriver; } diff --git a/tests/cases/Database/SeriesMiscellany.php b/tests/cases/Database/SeriesMiscellany.php index a7591bbe..e91b83b3 100644 --- a/tests/cases/Database/SeriesMiscellany.php +++ b/tests/cases/Database/SeriesMiscellany.php @@ -19,13 +19,6 @@ trait SeriesMiscellany { protected function tearDownSeriesMiscellany() { } - public function testListDrivers() { - $exp = [ - 'JKingWeb\\Arsse\\Db\\SQLite3\\Driver' => Arsse::$lang->msg("Driver.Db.SQLite3.Name"), - ]; - $this->assertArraySubset($exp, Database::driverList()); - } - public function testInitializeDatabase() { static::dbRaze(static::$drv); $d = new Database(true); diff --git a/tests/cases/Db/MySQL/TestCreation.php b/tests/cases/Db/MySQL/TestCreation.php index 823a5a38..52834587 100644 --- a/tests/cases/Db/MySQL/TestCreation.php +++ b/tests/cases/Db/MySQL/TestCreation.php @@ -22,7 +22,7 @@ class TestCreation extends \JKingWeb\Arsse\Test\AbstractTest { public function testFailToConnect() { // for the sake of simplicity we don't distinguish between failure modes, but the MySQL-supplied error messages do self::setConf([ - 'dbMySQLPass' => (string) rand(), + 'dbMySQLHost' => "example.invalid", ]); $this->assertException("connectionFailure", "Db"); new Driver; diff --git a/tests/cases/Db/MySQL/TestDatabase.php b/tests/cases/Db/MySQL/TestDatabase.php index 4364170d..9ad47edb 100644 --- a/tests/cases/Db/MySQL/TestDatabase.php +++ b/tests/cases/Db/MySQL/TestDatabase.php @@ -10,7 +10,6 @@ namespace JKingWeb\Arsse\TestCase\Db\MySQL; * @group slow * @group coverageOptional * @covers \JKingWeb\Arsse\Database - * @covers \JKingWeb\Arsse\Misc\Query */ class TestDatabase extends \JKingWeb\Arsse\TestCase\Database\AbstractTest { use \JKingWeb\Arsse\Test\DatabaseDrivers\MySQL; diff --git a/tests/cases/Db/MySQLPDO/TestCreation.php b/tests/cases/Db/MySQLPDO/TestCreation.php index 5ca4e7df..aa9b8492 100644 --- a/tests/cases/Db/MySQLPDO/TestCreation.php +++ b/tests/cases/Db/MySQLPDO/TestCreation.php @@ -22,7 +22,7 @@ class TestCreation extends \JKingWeb\Arsse\Test\AbstractTest { public function testFailToConnect() { // for the sake of simplicity we don't distinguish between failure modes, but the MySQL-supplied error messages do self::setConf([ - 'dbMySQLPass' => (string) rand(), + 'dbMySQLHost' => "example.invalid", ]); $this->assertException("connectionFailure", "Db"); new Driver; diff --git a/tests/cases/Db/MySQLPDO/TestDatabase.php b/tests/cases/Db/MySQLPDO/TestDatabase.php index 6a7550ea..e7345550 100644 --- a/tests/cases/Db/MySQLPDO/TestDatabase.php +++ b/tests/cases/Db/MySQLPDO/TestDatabase.php @@ -11,7 +11,6 @@ namespace JKingWeb\Arsse\TestCase\Db\MySQLPDO; * @group optional * @group coverageOptional * @covers \JKingWeb\Arsse\Database - * @covers \JKingWeb\Arsse\Misc\Query */ class TestDatabase extends \JKingWeb\Arsse\TestCase\Database\AbstractTest { use \JKingWeb\Arsse\Test\DatabaseDrivers\MySQLPDO; diff --git a/tests/cases/Db/PostgreSQL/TestCreation.php b/tests/cases/Db/PostgreSQL/TestCreation.php index 720e32be..cbc7fb2c 100644 --- a/tests/cases/Db/PostgreSQL/TestCreation.php +++ b/tests/cases/Db/PostgreSQL/TestCreation.php @@ -65,7 +65,7 @@ class TestCreation extends \JKingWeb\Arsse\Test\AbstractTest { public function testFailToConnect() { // we cannnot distinguish between different connection failure modes self::setConf([ - 'dbPostgreSQLPass' => (string) rand(), + 'dbPostgreSQLHost' => "example.invalid", ]); $this->assertException("connectionFailure", "Db"); new Driver; diff --git a/tests/cases/Db/PostgreSQL/TestDatabase.php b/tests/cases/Db/PostgreSQL/TestDatabase.php index 9fda4d97..e72c2a28 100644 --- a/tests/cases/Db/PostgreSQL/TestDatabase.php +++ b/tests/cases/Db/PostgreSQL/TestDatabase.php @@ -10,7 +10,6 @@ namespace JKingWeb\Arsse\TestCase\Db\PostgreSQL; * @group slow * @group coverageOptional * @covers \JKingWeb\Arsse\Database - * @covers \JKingWeb\Arsse\Misc\Query */ class TestDatabase extends \JKingWeb\Arsse\TestCase\Database\AbstractTest { use \JKingWeb\Arsse\Test\DatabaseDrivers\PostgreSQL; diff --git a/tests/cases/Db/PostgreSQLPDO/TestCreation.php b/tests/cases/Db/PostgreSQLPDO/TestCreation.php index a9babc11..5e2ad7b1 100644 --- a/tests/cases/Db/PostgreSQLPDO/TestCreation.php +++ b/tests/cases/Db/PostgreSQLPDO/TestCreation.php @@ -65,7 +65,7 @@ class TestCreation extends \JKingWeb\Arsse\Test\AbstractTest { public function testFailToConnect() { // PDO dies not distinguish between different connection failure modes self::setConf([ - 'dbPostgreSQLPass' => (string) rand(), + 'dbPostgreSQLHost' => "example.invalid", ]); $this->assertException("connectionFailure", "Db"); new Driver; diff --git a/tests/cases/Db/PostgreSQLPDO/TestDatabase.php b/tests/cases/Db/PostgreSQLPDO/TestDatabase.php index 6f8ef2a1..22afa5d9 100644 --- a/tests/cases/Db/PostgreSQLPDO/TestDatabase.php +++ b/tests/cases/Db/PostgreSQLPDO/TestDatabase.php @@ -11,7 +11,6 @@ namespace JKingWeb\Arsse\TestCase\Db\PostgreSQLPDO; * @group optional * @group coverageOptional * @covers \JKingWeb\Arsse\Database - * @covers \JKingWeb\Arsse\Misc\Query */ class TestDatabase extends \JKingWeb\Arsse\TestCase\Database\AbstractTest { use \JKingWeb\Arsse\Test\DatabaseDrivers\PostgreSQLPDO; diff --git a/tests/cases/Db/SQLite3/TestDatabase.php b/tests/cases/Db/SQLite3/TestDatabase.php index eab0970e..ea302218 100644 --- a/tests/cases/Db/SQLite3/TestDatabase.php +++ b/tests/cases/Db/SQLite3/TestDatabase.php @@ -9,7 +9,6 @@ namespace JKingWeb\Arsse\TestCase\Db\SQLite3; /** * @group optional * @covers \JKingWeb\Arsse\Database - * @covers \JKingWeb\Arsse\Misc\Query */ class TestDatabase extends \JKingWeb\Arsse\TestCase\Database\AbstractTest { use \JKingWeb\Arsse\Test\DatabaseDrivers\SQLite3; diff --git a/tests/cases/Db/SQLite3PDO/TestDatabase.php b/tests/cases/Db/SQLite3PDO/TestDatabase.php index 079bcc14..751647ae 100644 --- a/tests/cases/Db/SQLite3PDO/TestDatabase.php +++ b/tests/cases/Db/SQLite3PDO/TestDatabase.php @@ -8,7 +8,6 @@ namespace JKingWeb\Arsse\TestCase\Db\SQLite3PDO; /** * @covers \JKingWeb\Arsse\Database - * @covers \JKingWeb\Arsse\Misc\Query */ class TestDatabase extends \JKingWeb\Arsse\TestCase\Database\AbstractTest { use \JKingWeb\Arsse\Test\DatabaseDrivers\SQLite3PDO; diff --git a/tests/cases/ImportExport/TestImportExport.php b/tests/cases/ImportExport/TestImportExport.php index c8af2c19..6c7de1f1 100644 --- a/tests/cases/ImportExport/TestImportExport.php +++ b/tests/cases/ImportExport/TestImportExport.php @@ -212,11 +212,13 @@ class TestImportExport extends \JKingWeb\Arsse\Test\AbstractTest { ['id' => 4, 'name' => "Politics", 'parent' => 0], ['id' => 5, 'name' => "Local", 'parent' => 4], ['id' => 6, 'name' => "National", 'parent' => 4], + ['id' => 7, 'name' => "Nature", 'parent' => 0], // new folder ]]; \Phake::when($this->proc)->parse->thenReturn($in); $this->proc->import("john.doe@example.com", "", false, true); $exp = $this->primeExpectations($this->data, $this->checkTables); $exp['arsse_subscriptions']['rows'][3] = [4, "john.doe@example.com", null, 4, "CBC"]; + $exp['arsse_folders']['rows'][] = [7, "john.doe@example.com", null, "Nature"]; $this->compareExpectations($this->drv, $exp); } diff --git a/tests/cases/Lang/testComplex.php b/tests/cases/Lang/TestComplex.php similarity index 100% rename from tests/cases/Lang/testComplex.php rename to tests/cases/Lang/TestComplex.php diff --git a/tests/cases/Misc/TestQuery.php b/tests/cases/Misc/TestQuery.php new file mode 100644 index 00000000..a1588f1b --- /dev/null +++ b/tests/cases/Misc/TestQuery.php @@ -0,0 +1,115 @@ +assertSame("select * from table where a = ?", $q->getQuery()); + $this->assertSame(["int"], $q->getTypes()); + $this->assertSame([3], $q->getValues()); + } + + public function testWhereQuery() { + // simple where clause + $q = (new Query("select * from table"))->setWhere("a = ?", "int", 3); + $this->assertSame("select * from table WHERE a = ?", $q->getQuery()); + $this->assertSame(["int"], $q->getTypes()); + $this->assertSame([3], $q->getValues()); + // compound where clause + $q = (new Query("select * from table"))->setWhere("a = ?", "int", 3)->setWhere("b = ?", "str", 4); + $this->assertSame("select * from table WHERE a = ? AND b = ?", $q->getQuery()); + $this->assertSame(["int", "str"], $q->getTypes()); + $this->assertSame([3, 4], $q->getValues()); + // negative where clause + $q = (new Query("select * from table"))->setWhereNot("a = ?", "int", 3); + $this->assertSame("select * from table WHERE NOT (a = ?)", $q->getQuery()); + $this->assertSame(["int"], $q->getTypes()); + $this->assertSame([3], $q->getValues()); + // compound negative where clause + $q = (new Query("select * from table"))->setWhereNot("a = ?", "int", 3)->setWhereNot("b = ?", "str", 4); + $this->assertSame("select * from table WHERE NOT (a = ? OR b = ?)", $q->getQuery()); + $this->assertSame(["int", "str"], $q->getTypes()); + $this->assertSame([3, 4], $q->getValues()); + // mixed where clause + $q = (new Query("select * from table"))->setWhereNot("a = ?", "int", 1)->setWhere("b = ?", "str", 2)->setWhereNot("c = ?", "int", 3)->setWhere("d = ?", "str", 4); + $this->assertSame("select * from table WHERE b = ? AND d = ? AND NOT (a = ? OR c = ?)", $q->getQuery()); + $this->assertSame(["str", "str", "int", "int"], $q->getTypes()); + $this->assertSame([2, 4, 1, 3], $q->getValues()); + } + + public function testGroupedQuery() { + $q = (new Query("select col1, col2, count(*) as count from table"))->setGroup("col1", "col2"); + $this->assertSame("select col1, col2, count(*) as count from table GROUP BY col1, col2", $q->getQuery()); + $this->assertSame([], $q->getTypes()); + $this->assertSame([], $q->getValues()); + } + + public function testOrderedQuery() { + $q = (new Query("select col1, col2, col3 from table"))->setOrder("col1 desc", "col2")->setOrder("col3 asc"); + $this->assertSame("select col1, col2, col3 from table ORDER BY col1 desc, col2, col3 asc", $q->getQuery()); + $this->assertSame([], $q->getTypes()); + $this->assertSame([], $q->getValues()); + } + + public function testLimitedQuery() { + // no offset + $q = (new Query("select * from table"))->setLimit(5); + $this->assertSame("select * from table LIMIT 5", $q->getQuery()); + $this->assertSame([], $q->getTypes()); + $this->assertSame([], $q->getValues()); + // with offset + $q = (new Query("select * from table"))->setLimit(5, 10); + $this->assertSame("select * from table LIMIT 5 OFFSET 10", $q->getQuery()); + $this->assertSame([], $q->getTypes()); + $this->assertSame([], $q->getValues()); + // no limit with offset + $q = (new Query("select * from table"))->setLimit(0, 10); + $this->assertSame("select * from table LIMIT -1 OFFSET 10", $q->getQuery()); + $this->assertSame([], $q->getTypes()); + $this->assertSame([], $q->getValues()); + } + + public function testQueryWithCommonTableExpression() { + $q = (new Query("select * from table where a in (select * from cte where a = ?)", "int", 1))->setCTE("cte", "select * from other_table where a = ? and b = ?", ["str", "str"], [2, 3]); + $this->assertSame("WITH RECURSIVE cte as (select * from other_table where a = ? and b = ?) select * from table where a in (select * from cte where a = ?)", $q->getQuery()); + $this->assertSame(["str", "str", "int"], $q->getTypes()); + $this->assertSame([2, 3, 1], $q->getValues()); + // multiple CTEs + $q = (new Query("select * from table where a in (select * from cte1 join cte2 using (a) where a = ?)", "int", 1))->setCTE("cte1", "select * from other_table where a = ? and b = ?", ["str", "str"], [2, 3])->setCTE("cte2", "select * from other_table where c between ? and ?", ["datetime", "datetime"], [4, 5]); + $this->assertSame("WITH RECURSIVE cte1 as (select * from other_table where a = ? and b = ?), cte2 as (select * from other_table where c between ? and ?) select * from table where a in (select * from cte1 join cte2 using (a) where a = ?)", $q->getQuery()); + $this->assertSame(["str", "str", "datetime", "datetime", "int"], $q->getTypes()); + $this->assertSame([2, 3, 4, 5, 1], $q->getValues()); + } + + public function testQueryWithPushedCommonTableExpression() { + $q = (new Query("select * from table1"))->setWhere("a between ? and ?", ["datetime", "datetime"], [1, 2]) + ->setCTE("cte1", "select * from table2 where a = ? and b = ?", ["str", "str"], [3, 4]) + ->pushCTE("cte2") + ->setBody("select * from table3 join cte1 using (a) join cte2 using (a) where a = ?", "int", 5); + $this->assertSame("WITH RECURSIVE cte1 as (select * from table2 where a = ? and b = ?), cte2 as (select * from table1 WHERE a between ? and ?) select * from table3 join cte1 using (a) join cte2 using (a) where a = ?", $q->getQuery()); + $this->assertSame(["str", "str", "datetime", "datetime", "int"], $q->getTypes()); + $this->assertSame([3, 4, 1, 2, 5], $q->getValues()); + } + + public function testComplexQuery() { + $q = (new query("select *, ? as const from table", "datetime", 1)) + ->setWhereNot("b = ?", "bool", 2) + ->setGroup("col1", "col2") + ->setWhere("a = ?", "str", 3) + ->setLimit(4, 5) + ->setOrder("col3") + ->setCTE("cte", "select ? as const", "int", 6); + $this->assertSame("WITH RECURSIVE cte as (select ? as const) select *, ? as const from table WHERE a = ? AND NOT (b = ?) GROUP BY col1, col2 ORDER BY col3 LIMIT 4 OFFSET 5", $q->getQuery()); + $this->assertSame(["int", "datetime", "str", "bool"], $q->getTypes()); + $this->assertSame([6, 1, 3, 2], $q->getValues()); + } +} diff --git a/tests/cases/Misc/TestURL.php b/tests/cases/Misc/TestURL.php index 8260c0b0..e045d309 100644 --- a/tests/cases/Misc/TestURL.php +++ b/tests/cases/Misc/TestURL.php @@ -91,4 +91,21 @@ class TestURL extends \JKingWeb\Arsse\Test\AbstractTest { ["/#ack", "", "/#ack"], ]; } + + /** @dataProvider provideAbsolutes */ + public function testDetermineAbsoluteness(bool $exp, string $url) { + $this->assertSame($exp, URL::absolute($url)); + } + + public function provideAbsolutes() { + return [ + [true, "http://example.com/"], + [true, "HTTP://example.com/"], + [false, "//example.com/"], + [false, "/example"], + [false, "example.com/"], + [false, "example.com"], + [false, "http:///example"], + ]; + } } diff --git a/tests/cases/Misc/TestValueInfo.php b/tests/cases/Misc/TestValueInfo.php index 9bf12bad..2d5ffc4e 100644 --- a/tests/cases/Misc/TestValueInfo.php +++ b/tests/cases/Misc/TestValueInfo.php @@ -639,4 +639,10 @@ class TestValueInfo extends \JKingWeb\Arsse\Test\AbstractTest { $out->f = $msec; return $out; } + + public function testFlattenArray() { + $arr = [1, [2, 3, [4, 5]], 6, [[7, 8], 9, 10]]; + $exp = range(1, 10); + $this->assertSame($exp, I::flatten($arr)); + } } diff --git a/tests/cases/Service/TestSerial.php b/tests/cases/Service/TestSerial.php new file mode 100644 index 00000000..5a960788 --- /dev/null +++ b/tests/cases/Service/TestSerial.php @@ -0,0 +1,47 @@ +assertTrue(Driver::requirementsMet()); + $this->assertInstanceOf(DriverInterface::class, new Driver); + } + + public function testFetchDriverName() { + $this->assertTrue(strlen(Driver::driverName()) > 0); + } + + public function testEnqueueFeeds() { + $d = new Driver; + $this->assertSame(3, $d->queue(1, 2, 3)); + $this->assertSame(5, $d->queue(4, 5)); + $this->assertSame(5, $d->clean()); + $this->assertSame(1, $d->queue(5)); + } + + public function testRefreshFeeds() { + $d = new Driver; + $d->queue(1, 4, 3); + $this->assertSame(Arsse::$conf->serviceQueueWidth, $d->exec()); + \Phake::verify(Arsse::$db)->feedUpdate(1); + \Phake::verify(Arsse::$db)->feedUpdate(4); + \Phake::verify(Arsse::$db)->feedUpdate(3); + } +} diff --git a/tests/cases/Service/TestService.php b/tests/cases/Service/TestService.php index 3f6ea6b3..102a9ce5 100644 --- a/tests/cases/Service/TestService.php +++ b/tests/cases/Service/TestService.php @@ -39,4 +39,45 @@ class TestService extends \JKingWeb\Arsse\Test\AbstractTest { $this->assertTrue(Service::hasCheckedIn()); $this->assertFalse(Service::hasCheckedIn()); } + + public function testPerformPreCleanup() { + $this->assertTrue(Service::cleanupPre()); + \Phake::verify(Arsse::$db)->feedCleanup(); + \Phake::verify(Arsse::$db)->sessionCleanup(); + } + + public function testPerformShortPostCleanup() { + \Phake::when(Arsse::$db)->articleCleanup()->thenReturn(0); + $this->assertTrue(Service::cleanupPost()); + \Phake::verify(Arsse::$db)->articleCleanup(); + \Phake::verify(Arsse::$db, \Phake::times(0))->driverMaintenance(); + } + + public function testPerformFullPostCleanup() { + \Phake::when(Arsse::$db)->articleCleanup()->thenReturn(1); + $this->assertTrue(Service::cleanupPost()); + \Phake::verify(Arsse::$db)->articleCleanup(); + \Phake::verify(Arsse::$db)->driverMaintenance(); + } + + public function testRefreshFeeds() { + // set up mock database actions + \Phake::when(Arsse::$db)->metaSet->thenReturn(true); + \Phake::when(Arsse::$db)->feedCleanup->thenReturn(true); + \Phake::when(Arsse::$db)->sessionCleanup->thenReturn(true); + \Phake::when(Arsse::$db)->articleCleanup->thenReturn(0); + \Phake::when(Arsse::$db)->feedListStale->thenReturn([1,2,3]); + // perform the test + $d = \Phake::mock(\JKingWeb\Arsse\Service\Driver::class); + $s = new \JKingWeb\Arsse\Test\Service($d); + $this->assertInstanceOf(\DateTimeInterface::class, $s->watch(false)); + // verify invocations + \Phake::verify($d)->queue(1, 2, 3); + \Phake::verify($d)->exec(); + \Phake::verify($d)->clean(); + \Phake::verify(Arsse::$db)->feedCleanup(); + \Phake::verify(Arsse::$db)->sessionCleanup(); + \Phake::verify(Arsse::$db)->articleCleanup(); + \Phake::verify(Arsse::$db)->metaSet("service_last_checkin", $this->anything(), "datetime"); + } } diff --git a/tests/cases/Service/TestSubprocess.php b/tests/cases/Service/TestSubprocess.php new file mode 100644 index 00000000..c02c4b26 --- /dev/null +++ b/tests/cases/Service/TestSubprocess.php @@ -0,0 +1,48 @@ +assertTrue(Driver::requirementsMet()); + $this->assertInstanceOf(DriverInterface::class, new Driver); + } + + public function testFetchDriverName() { + $this->assertTrue(strlen(Driver::driverName()) > 0); + } + + public function testEnqueueFeeds() { + $d = new Driver; + $this->assertSame(3, $d->queue(1, 2, 3)); + $this->assertSame(5, $d->queue(4, 5)); + $this->assertSame(5, $d->clean()); + $this->assertSame(1, $d->queue(5)); + } + + public function testRefreshFeeds() { + $d = \Phake::partialMock(Driver::class); + \Phake::when($d)->execCmd->thenReturnCallback(function(string $cmd) { + // FIXME: Does this work in Windows? + return popen("echo ".escapeshellarg($cmd), "r"); + }); + $this->assertSame(3, $d->queue(1, 4, 3)); + $this->assertSame(Arsse::$conf->serviceQueueWidth, $d->exec()); + \Phake::verify($d, \Phake::times(3))->execCmd; + } +} diff --git a/tests/cases/TestArsse.php b/tests/cases/TestArsse.php new file mode 100644 index 00000000..f28e7ee8 --- /dev/null +++ b/tests/cases/TestArsse.php @@ -0,0 +1,50 @@ +import(['lang' => "test"]); + Arsse::load($conf2); + $this->assertSame($conf2, Arsse::$conf); + $this->assertSame($lang, Arsse::$lang); + $this->assertSame($db, Arsse::$db); + $this->assertSame($user, Arsse::$user); + \Phake::verify($lang)->set("test"); + } + + public function testLoadNewData() { + if (!\JKingWeb\Arsse\Db\SQLite3\Driver::requirementsMet() && !\JKingWeb\Arsse\Db\SQLite3\PDODriver::requirementsMet()) { + $this->markTestSkipped("A functional SQLite interface is required for this test"); + } + $conf = (new Conf)->import(['dbSQLite3File' => ":memory:"]); + Arsse::load($conf); + $this->assertInstanceOf(Conf::class, Arsse::$conf); + $this->assertInstanceOf(Lang::class, Arsse::$lang); + $this->assertInstanceOf(Database::class, Arsse::$db); + $this->assertInstanceOf(User::class, Arsse::$user); + } +} diff --git a/tests/cases/User/TestUser.php b/tests/cases/User/TestUser.php index 1398b177..49fc4723 100644 --- a/tests/cases/User/TestUser.php +++ b/tests/cases/User/TestUser.php @@ -24,13 +24,6 @@ class TestUser extends \JKingWeb\Arsse\Test\AbstractTest { $this->drv = \Phake::mock(Driver::class); } - public function testListDrivers() { - $exp = [ - 'JKingWeb\\Arsse\\User\\Internal\\Driver' => Arsse::$lang->msg("Driver.User.Internal.Name"), - ]; - $this->assertArraySubset($exp, User::driverList()); - } - public function testConstruct() { $this->assertInstanceOf(User::class, new User($this->drv)); $this->assertInstanceOf(User::class, new User); diff --git a/tests/lib/AbstractTest.php b/tests/lib/AbstractTest.php index a2e66a31..f3a1ffbb 100644 --- a/tests/lib/AbstractTest.php +++ b/tests/lib/AbstractTest.php @@ -74,7 +74,7 @@ abstract class AbstractTest extends \PHPUnit\Framework\TestCase { if (isset($params)) { if (is_array($params)) { $params = implode("&", array_map(function($v, $k) { - return rawurlencode($k).(isset($v) ? "=".rawurlencode($v) : ""); + return rawurlencode($k).(isset($v) ? "=".rawurlencode($v) : ""); }, $params, array_keys($params))); } $url = URL::queryAppend($url, (string) $params); @@ -90,7 +90,7 @@ abstract class AbstractTest extends \PHPUnit\Framework\TestCase { if (is_string($body) && in_array(strtolower($type), ["", "application/x-www-form-urlencoded"])) { parse_str($body, $parsedBody); } elseif (!is_string($body) && in_array(strtolower($type), ["application/json", "text/json"])) { - $body = json_encode($body, \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE); + $body = json_encode($body, \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE); } elseif (!is_string($body) && in_array(strtolower($type), ["", "application/x-www-form-urlencoded"])) { $parsedBody = $body; $body = http_build_query($body, "a", "&"); diff --git a/tests/lib/Lang/Setup.php b/tests/lib/Lang/Setup.php index 381806f5..e70ccb03 100644 --- a/tests/lib/Lang/Setup.php +++ b/tests/lib/Lang/Setup.php @@ -9,6 +9,7 @@ namespace JKingWeb\Arsse\Test\Lang; use JKingWeb\Arsse\Lang; use JKingWeb\Arsse\Arsse; use org\bovigo\vfs\vfsStream; +use Webmozart\Glob\Glob; trait Setup { public function setUp() { @@ -36,7 +37,10 @@ trait Setup { // set up a file without read access chmod($this->path."ru.php", 0000); // make the test Lang class use the vfs files - $this->l = new TestLang($this->path); + $this->l = \Phake::partialMock(Lang::class, $this->path); + \Phake::when($this->l)->globFiles->thenReturnCallback(function(string $path): array { + return Glob::glob($this->path."*.php"); + }); // create a mock Lang object so as not to create a dependency loop self::clearData(false); Arsse::$lang = \Phake::mock(Lang::class); diff --git a/tests/lib/Lang/TestLang.php b/tests/lib/Lang/TestLang.php deleted file mode 100644 index 3022535e..00000000 --- a/tests/lib/Lang/TestLang.php +++ /dev/null @@ -1,15 +0,0 @@ -path."*.php"); - } -} diff --git a/tests/lib/Service.php b/tests/lib/Service.php new file mode 100644 index 00000000..cfd11f4d --- /dev/null +++ b/tests/lib/Service.php @@ -0,0 +1,13 @@ +drv = $drv; + } +} diff --git a/tests/phpunit.dist.xml b/tests/phpunit.dist.xml index 28d2f899..1ede519d 100644 --- a/tests/phpunit.dist.xml +++ b/tests/phpunit.dist.xml @@ -45,6 +45,7 @@ cases/Misc/TestValueInfo.php cases/Misc/TestDate.php + cases/Misc/TestQuery.php cases/Misc/TestContext.php cases/Misc/TestURL.php cases/Misc/TestHTTP.php @@ -128,7 +129,10 @@ cases/Service/TestService.php + cases/Service/TestSerial.php + cases/Service/TestSubprocess.php cases/CLI/TestCLI.php + cases/TestArsse.php cases/ImportExport/TestFile.php diff --git a/vendor-bin/csfixer/composer.lock b/vendor-bin/csfixer/composer.lock index faa225f1..93447597 100644 --- a/vendor-bin/csfixer/composer.lock +++ b/vendor-bin/csfixer/composer.lock @@ -114,16 +114,16 @@ }, { "name": "doctrine/annotations", - "version": "v1.6.1", + "version": "v1.8.0", "source": { "type": "git", "url": "https://github.com/doctrine/annotations.git", - "reference": "53120e0eb10355388d6ccbe462f1fea34ddadb24" + "reference": "904dca4eb10715b92569fbcd79e201d5c349b6bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/53120e0eb10355388d6ccbe462f1fea34ddadb24", - "reference": "53120e0eb10355388d6ccbe462f1fea34ddadb24", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/904dca4eb10715b92569fbcd79e201d5c349b6bc", + "reference": "904dca4eb10715b92569fbcd79e201d5c349b6bc", "shasum": "" }, "require": { @@ -132,12 +132,12 @@ }, "require-dev": { "doctrine/cache": "1.*", - "phpunit/phpunit": "^6.4" + "phpunit/phpunit": "^7.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.6.x-dev" + "dev-master": "1.7.x-dev" } }, "autoload": { @@ -150,6 +150,10 @@ "MIT" ], "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, { "name": "Roman Borschel", "email": "roman@code-factory.org" @@ -158,10 +162,6 @@ "name": "Benjamin Eberlei", "email": "kontakt@beberlei.de" }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, { "name": "Jonathan Wage", "email": "jonwage@gmail.com" @@ -178,32 +178,34 @@ "docblock", "parser" ], - "time": "2019-03-25T19:12:02+00:00" + "time": "2019-10-01T18:55:10+00:00" }, { "name": "doctrine/lexer", - "version": "1.0.2", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/doctrine/lexer.git", - "reference": "1febd6c3ef84253d7c815bed85fc622ad207a9f8" + "reference": "e17f069ede36f7534b95adec71910ed1b49c74ea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/1febd6c3ef84253d7c815bed85fc622ad207a9f8", - "reference": "1febd6c3ef84253d7c815bed85fc622ad207a9f8", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/e17f069ede36f7534b95adec71910ed1b49c74ea", + "reference": "e17f069ede36f7534b95adec71910ed1b49c74ea", "shasum": "" }, "require": { - "php": ">=5.3.2" + "php": "^7.2" }, "require-dev": { - "phpunit/phpunit": "^4.5" + "doctrine/coding-standard": "^6.0", + "phpstan/phpstan": "^0.11.8", + "phpunit/phpunit": "^8.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.1.x-dev" } }, "autoload": { @@ -216,14 +218,14 @@ "MIT" ], "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, { "name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com" }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, { "name": "Johannes Schmitt", "email": "schmittjoh@gmail.com" @@ -238,20 +240,20 @@ "parser", "php" ], - "time": "2019-06-08T11:03:04+00:00" + "time": "2019-07-30T19:33:28+00:00" }, { "name": "friendsofphp/php-cs-fixer", - "version": "v2.15.1", + "version": "v2.15.3", "source": { "type": "git", "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", - "reference": "20064511ab796593a3990669eff5f5b535001f7c" + "reference": "705490b0f282f21017d73561e9498d2b622ee34c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/20064511ab796593a3990669eff5f5b535001f7c", - "reference": "20064511ab796593a3990669eff5f5b535001f7c", + "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/705490b0f282f21017d73561e9498d2b622ee34c", + "reference": "705490b0f282f21017d73561e9498d2b622ee34c", "shasum": "" }, "require": { @@ -281,9 +283,10 @@ "php-cs-fixer/accessible-object": "^1.0", "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.1", "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.1", - "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1", + "phpunit/phpunit": "^5.7.27 || ^6.5.14 || ^7.1", "phpunitgoodpractices/traits": "^1.8", - "symfony/phpunit-bridge": "^4.3" + "symfony/phpunit-bridge": "^4.3", + "symfony/yaml": "^3.0 || ^4.0" }, "suggest": { "ext-mbstring": "For handling non-UTF8 characters in cache signature.", @@ -316,17 +319,17 @@ "MIT" ], "authors": [ - { - "name": "Dariusz Rumiński", - "email": "dariusz.ruminski@gmail.com" - }, { "name": "Fabien Potencier", "email": "fabien@symfony.com" + }, + { + "name": "Dariusz Rumiński", + "email": "dariusz.ruminski@gmail.com" } ], "description": "A tool to automatically fix PHP code style", - "time": "2019-06-01T10:32:12+00:00" + "time": "2019-08-31T12:51:54+00:00" }, { "name": "paragonie/random_compat", @@ -522,16 +525,16 @@ }, { "name": "symfony/console", - "version": "v4.3.2", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "b592b26a24265a35172d8a2094d8b10f22b7cc39" + "reference": "929ddf360d401b958f611d44e726094ab46a7369" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/b592b26a24265a35172d8a2094d8b10f22b7cc39", - "reference": "b592b26a24265a35172d8a2094d8b10f22b7cc39", + "url": "https://api.github.com/repos/symfony/console/zipball/929ddf360d401b958f611d44e726094ab46a7369", + "reference": "929ddf360d401b958f611d44e726094ab46a7369", "shasum": "" }, "require": { @@ -593,20 +596,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2019-06-13T11:03:18+00:00" + "time": "2019-10-07T12:36:49+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v4.3.2", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "d257021c1ab28d48d24a16de79dfab445ce93398" + "reference": "6229f58993e5a157f6096fc7145c0717d0be8807" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d257021c1ab28d48d24a16de79dfab445ce93398", - "reference": "d257021c1ab28d48d24a16de79dfab445ce93398", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/6229f58993e5a157f6096fc7145c0717d0be8807", + "reference": "6229f58993e5a157f6096fc7145c0717d0be8807", "shasum": "" }, "require": { @@ -663,20 +666,20 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2019-06-13T11:03:18+00:00" + "time": "2019-10-01T16:40:32+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v1.1.5", + "version": "v1.1.7", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "c61766f4440ca687de1084a5c00b08e167a2575c" + "reference": "c43ab685673fb6c8d84220c77897b1d6cdbe1d18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/c61766f4440ca687de1084a5c00b08e167a2575c", - "reference": "c61766f4440ca687de1084a5c00b08e167a2575c", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/c43ab685673fb6c8d84220c77897b1d6cdbe1d18", + "reference": "c43ab685673fb6c8d84220c77897b1d6cdbe1d18", "shasum": "" }, "require": { @@ -721,20 +724,20 @@ "interoperability", "standards" ], - "time": "2019-06-20T06:46:26+00:00" + "time": "2019-09-17T09:54:03+00:00" }, { "name": "symfony/filesystem", - "version": "v4.3.2", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "b9896d034463ad6fd2bf17e2bf9418caecd6313d" + "reference": "9abbb7ef96a51f4d7e69627bc6f63307994e4263" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/b9896d034463ad6fd2bf17e2bf9418caecd6313d", - "reference": "b9896d034463ad6fd2bf17e2bf9418caecd6313d", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/9abbb7ef96a51f4d7e69627bc6f63307994e4263", + "reference": "9abbb7ef96a51f4d7e69627bc6f63307994e4263", "shasum": "" }, "require": { @@ -771,20 +774,20 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2019-06-23T08:51:25+00:00" + "time": "2019-08-20T14:07:54+00:00" }, { "name": "symfony/finder", - "version": "v4.3.2", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "33c21f7d5d3dc8a140c282854a7e13aeb5d0f91a" + "reference": "5e575faa95548d0586f6bedaeabec259714e44d1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/33c21f7d5d3dc8a140c282854a7e13aeb5d0f91a", - "reference": "33c21f7d5d3dc8a140c282854a7e13aeb5d0f91a", + "url": "https://api.github.com/repos/symfony/finder/zipball/5e575faa95548d0586f6bedaeabec259714e44d1", + "reference": "5e575faa95548d0586f6bedaeabec259714e44d1", "shasum": "" }, "require": { @@ -820,20 +823,20 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2019-06-13T11:03:18+00:00" + "time": "2019-09-16T11:29:48+00:00" }, { "name": "symfony/options-resolver", - "version": "v4.3.2", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "40762ead607c8f792ee4516881369ffa553fee6f" + "reference": "81c2e120522a42f623233968244baebd6b36cb6a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/40762ead607c8f792ee4516881369ffa553fee6f", - "reference": "40762ead607c8f792ee4516881369ffa553fee6f", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/81c2e120522a42f623233968244baebd6b36cb6a", + "reference": "81c2e120522a42f623233968244baebd6b36cb6a", "shasum": "" }, "require": { @@ -874,20 +877,20 @@ "configuration", "options" ], - "time": "2019-06-13T11:01:17+00:00" + "time": "2019-08-08T09:29:19+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.11.0", + "version": "v1.12.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "82ebae02209c21113908c229e9883c419720738a" + "reference": "550ebaac289296ce228a706d0867afc34687e3f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/82ebae02209c21113908c229e9883c419720738a", - "reference": "82ebae02209c21113908c229e9883c419720738a", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/550ebaac289296ce228a706d0867afc34687e3f4", + "reference": "550ebaac289296ce228a706d0867afc34687e3f4", "shasum": "" }, "require": { @@ -899,7 +902,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11-dev" + "dev-master": "1.12-dev" } }, "autoload": { @@ -916,12 +919,12 @@ ], "authors": [ { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" }, { - "name": "Gert de Pagter", - "email": "backendtea@gmail.com" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], "description": "Symfony polyfill for ctype functions", @@ -932,20 +935,20 @@ "polyfill", "portable" ], - "time": "2019-02-06T07:57:58+00:00" + "time": "2019-08-06T08:03:45+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.11.0", + "version": "v1.12.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "fe5e94c604826c35a32fa832f35bd036b6799609" + "reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fe5e94c604826c35a32fa832f35bd036b6799609", - "reference": "fe5e94c604826c35a32fa832f35bd036b6799609", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/b42a2f66e8f1b15ccf25652c3424265923eb4f17", + "reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17", "shasum": "" }, "require": { @@ -957,7 +960,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11-dev" + "dev-master": "1.12-dev" } }, "autoload": { @@ -991,20 +994,20 @@ "portable", "shim" ], - "time": "2019-02-06T07:57:58+00:00" + "time": "2019-08-06T08:03:45+00:00" }, { "name": "symfony/polyfill-php70", - "version": "v1.11.0", + "version": "v1.12.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php70.git", - "reference": "bc4858fb611bda58719124ca079baff854149c89" + "reference": "54b4c428a0054e254223797d2713c31e08610831" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/bc4858fb611bda58719124ca079baff854149c89", - "reference": "bc4858fb611bda58719124ca079baff854149c89", + "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/54b4c428a0054e254223797d2713c31e08610831", + "reference": "54b4c428a0054e254223797d2713c31e08610831", "shasum": "" }, "require": { @@ -1014,7 +1017,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11-dev" + "dev-master": "1.12-dev" } }, "autoload": { @@ -1050,20 +1053,20 @@ "portable", "shim" ], - "time": "2019-02-06T07:57:58+00:00" + "time": "2019-08-06T08:03:45+00:00" }, { "name": "symfony/polyfill-php72", - "version": "v1.11.0", + "version": "v1.12.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "ab50dcf166d5f577978419edd37aa2bb8eabce0c" + "reference": "04ce3335667451138df4307d6a9b61565560199e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/ab50dcf166d5f577978419edd37aa2bb8eabce0c", - "reference": "ab50dcf166d5f577978419edd37aa2bb8eabce0c", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/04ce3335667451138df4307d6a9b61565560199e", + "reference": "04ce3335667451138df4307d6a9b61565560199e", "shasum": "" }, "require": { @@ -1072,7 +1075,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11-dev" + "dev-master": "1.12-dev" } }, "autoload": { @@ -1105,20 +1108,20 @@ "portable", "shim" ], - "time": "2019-02-06T07:57:58+00:00" + "time": "2019-08-06T08:03:45+00:00" }, { "name": "symfony/polyfill-php73", - "version": "v1.11.0", + "version": "v1.12.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "d1fb4abcc0c47be136208ad9d68bf59f1ee17abd" + "reference": "2ceb49eaccb9352bff54d22570276bb75ba4a188" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/d1fb4abcc0c47be136208ad9d68bf59f1ee17abd", - "reference": "d1fb4abcc0c47be136208ad9d68bf59f1ee17abd", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/2ceb49eaccb9352bff54d22570276bb75ba4a188", + "reference": "2ceb49eaccb9352bff54d22570276bb75ba4a188", "shasum": "" }, "require": { @@ -1127,7 +1130,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11-dev" + "dev-master": "1.12-dev" } }, "autoload": { @@ -1163,20 +1166,20 @@ "portable", "shim" ], - "time": "2019-02-06T07:57:58+00:00" + "time": "2019-08-06T08:03:45+00:00" }, { "name": "symfony/process", - "version": "v4.3.2", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "856d35814cf287480465bb7a6c413bb7f5f5e69c" + "reference": "50556892f3cc47d4200bfd1075314139c4c9ff4b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/856d35814cf287480465bb7a6c413bb7f5f5e69c", - "reference": "856d35814cf287480465bb7a6c413bb7f5f5e69c", + "url": "https://api.github.com/repos/symfony/process/zipball/50556892f3cc47d4200bfd1075314139c4c9ff4b", + "reference": "50556892f3cc47d4200bfd1075314139c4c9ff4b", "shasum": "" }, "require": { @@ -1212,20 +1215,20 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2019-05-30T16:10:05+00:00" + "time": "2019-09-26T21:17:10+00:00" }, { "name": "symfony/service-contracts", - "version": "v1.1.5", + "version": "v1.1.7", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "f391a00de78ec7ec8cf5cdcdae59ec7b883edb8d" + "reference": "ffcde9615dc5bb4825b9f6aed07716f1f57faae0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f391a00de78ec7ec8cf5cdcdae59ec7b883edb8d", - "reference": "f391a00de78ec7ec8cf5cdcdae59ec7b883edb8d", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/ffcde9615dc5bb4825b9f6aed07716f1f57faae0", + "reference": "ffcde9615dc5bb4825b9f6aed07716f1f57faae0", "shasum": "" }, "require": { @@ -1270,20 +1273,20 @@ "interoperability", "standards" ], - "time": "2019-06-13T11:15:36+00:00" + "time": "2019-09-17T11:12:18+00:00" }, { "name": "symfony/stopwatch", - "version": "v4.3.2", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "6b100e9309e8979cf1978ac1778eb155c1f7d93b" + "reference": "1e4ff456bd625be5032fac9be4294e60442e9b71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/6b100e9309e8979cf1978ac1778eb155c1f7d93b", - "reference": "6b100e9309e8979cf1978ac1778eb155c1f7d93b", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/1e4ff456bd625be5032fac9be4294e60442e9b71", + "reference": "1e4ff456bd625be5032fac9be4294e60442e9b71", "shasum": "" }, "require": { @@ -1320,7 +1323,7 @@ ], "description": "Symfony Stopwatch Component", "homepage": "https://symfony.com", - "time": "2019-05-27T08:16:38+00:00" + "time": "2019-08-07T11:52:19+00:00" } ], "packages-dev": [], diff --git a/vendor-bin/daux/composer.json b/vendor-bin/daux/composer.json index 99a71b3e..723bdf0e 100644 --- a/vendor-bin/daux/composer.json +++ b/vendor-bin/daux/composer.json @@ -1,5 +1,5 @@ { "require": { - "daux/daux.io": "^0.10.1" + "daux/daux.io": "^0.11" } } diff --git a/vendor-bin/daux/composer.lock b/vendor-bin/daux/composer.lock index 860913bf..d2befae3 100644 --- a/vendor-bin/daux/composer.lock +++ b/vendor-bin/daux/composer.lock @@ -4,20 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "c53b1115bf13a026ec792e74b04fe703", + "content-hash": "6d944ffdc165b3e6f14e71a82b67a57d", "packages": [ { "name": "daux/daux.io", - "version": "0.10.1", + "version": "0.11.1", "source": { "type": "git", "url": "https://github.com/dauxio/daux.io.git", - "reference": "298eef8f9c4d4d380f5e7beb5472b4bff80566d0" + "reference": "e796fad8627b7a2c95d1caf80e8e7b19969133e9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dauxio/daux.io/zipball/298eef8f9c4d4d380f5e7beb5472b4bff80566d0", - "reference": "298eef8f9c4d4d380f5e7beb5472b4bff80566d0", + "url": "https://api.github.com/repos/dauxio/daux.io/zipball/e796fad8627b7a2c95d1caf80e8e7b19969133e9", + "reference": "e796fad8627b7a2c95d1caf80e8e7b19969133e9", "shasum": "" }, "require": { @@ -26,6 +26,7 @@ "league/plates": "~3.1", "myclabs/deep-copy": "^1.5", "php": ">=7.1.3", + "scrivo/highlight.php": "^9.15", "symfony/console": "^4.0", "symfony/http-foundation": "^4.0", "symfony/polyfill-intl-icu": "^1.10", @@ -74,7 +75,7 @@ "markdown", "md" ], - "time": "2019-08-28T13:42:34+00:00" + "time": "2019-09-23T20:10:07+00:00" }, { "name": "guzzlehttp/guzzle", @@ -575,17 +576,84 @@ "time": "2019-03-08T08:55:37+00:00" }, { - "name": "symfony/console", - "version": "v4.3.4", + "name": "scrivo/highlight.php", + "version": "v9.15.10.0", "source": { "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "de63799239b3881b8a08f8481b22348f77ed7b36" + "url": "https://github.com/scrivo/highlight.php.git", + "reference": "9ad3adb4456dc91196327498dbbce6aa1ba1239e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/de63799239b3881b8a08f8481b22348f77ed7b36", - "reference": "de63799239b3881b8a08f8481b22348f77ed7b36", + "url": "https://api.github.com/repos/scrivo/highlight.php/zipball/9ad3adb4456dc91196327498dbbce6aa1ba1239e", + "reference": "9ad3adb4456dc91196327498dbbce6aa1ba1239e", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-mbstring": "*", + "php": ">=5.4" + }, + "require-dev": { + "phpunit/phpunit": "^4.8|^5.7", + "symfony/finder": "^2.8" + }, + "suggest": { + "ext-dom": "Needed to make use of the features in the utilities namespace" + }, + "type": "library", + "autoload": { + "psr-0": { + "Highlight\\": "", + "HighlightUtilities\\": "" + }, + "files": [ + "HighlightUtilities/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Geert Bergman", + "homepage": "http://www.scrivo.org/", + "role": "Project Author" + }, + { + "name": "Vladimir Jimenez", + "homepage": "https://allejo.io", + "role": "Contributor" + }, + { + "name": "Martin Folkers", + "homepage": "https://twobrain.io", + "role": "Contributor" + } + ], + "description": "Server side syntax highlighter that supports 185 languages. It's a PHP port of highlight.js", + "keywords": [ + "code", + "highlight", + "highlight.js", + "highlight.php", + "syntax" + ], + "time": "2019-08-27T04:27:48+00:00" + }, + { + "name": "symfony/console", + "version": "v4.3.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "929ddf360d401b958f611d44e726094ab46a7369" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/929ddf360d401b958f611d44e726094ab46a7369", + "reference": "929ddf360d401b958f611d44e726094ab46a7369", "shasum": "" }, "require": { @@ -647,20 +715,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2019-08-26T08:26:39+00:00" + "time": "2019-10-07T12:36:49+00:00" }, { "name": "symfony/http-foundation", - "version": "v4.3.4", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "d804bea118ff340a12e22a79f9c7e7eb56b35adc" + "reference": "76590ced16d4674780863471bae10452b79210a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/d804bea118ff340a12e22a79f9c7e7eb56b35adc", - "reference": "d804bea118ff340a12e22a79f9c7e7eb56b35adc", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/76590ced16d4674780863471bae10452b79210a5", + "reference": "76590ced16d4674780863471bae10452b79210a5", "shasum": "" }, "require": { @@ -702,20 +770,20 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", - "time": "2019-08-26T08:55:16+00:00" + "time": "2019-10-04T19:48:13+00:00" }, { "name": "symfony/intl", - "version": "v4.3.4", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/intl.git", - "reference": "8db5505703c5bdb23d524fd994dad2f781966538" + "reference": "818771ff6acef04cdce05023ddfc39b7078014bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/intl/zipball/8db5505703c5bdb23d524fd994dad2f781966538", - "reference": "8db5505703c5bdb23d524fd994dad2f781966538", + "url": "https://api.github.com/repos/symfony/intl/zipball/818771ff6acef04cdce05023ddfc39b7078014bf", + "reference": "818771ff6acef04cdce05023ddfc39b7078014bf", "shasum": "" }, "require": { @@ -777,20 +845,20 @@ "l10n", "localization" ], - "time": "2019-08-26T08:26:39+00:00" + "time": "2019-10-04T21:18:34+00:00" }, { "name": "symfony/mime", - "version": "v4.3.4", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "987a05df1c6ac259b34008b932551353f4f408df" + "reference": "32f71570547b91879fdbd9cf50317d556ae86916" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/987a05df1c6ac259b34008b932551353f4f408df", - "reference": "987a05df1c6ac259b34008b932551353f4f408df", + "url": "https://api.github.com/repos/symfony/mime/zipball/32f71570547b91879fdbd9cf50317d556ae86916", + "reference": "32f71570547b91879fdbd9cf50317d556ae86916", "shasum": "" }, "require": { @@ -836,7 +904,7 @@ "mime", "mime-type" ], - "time": "2019-08-22T08:16:11+00:00" + "time": "2019-09-19T17:00:15+00:00" }, { "name": "symfony/polyfill-ctype", @@ -1190,16 +1258,16 @@ }, { "name": "symfony/process", - "version": "v4.3.4", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "e89969c00d762349f078db1128506f7f3dcc0d4a" + "reference": "50556892f3cc47d4200bfd1075314139c4c9ff4b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/e89969c00d762349f078db1128506f7f3dcc0d4a", - "reference": "e89969c00d762349f078db1128506f7f3dcc0d4a", + "url": "https://api.github.com/repos/symfony/process/zipball/50556892f3cc47d4200bfd1075314139c4c9ff4b", + "reference": "50556892f3cc47d4200bfd1075314139c4c9ff4b", "shasum": "" }, "require": { @@ -1235,20 +1303,20 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2019-08-26T08:26:39+00:00" + "time": "2019-09-26T21:17:10+00:00" }, { "name": "symfony/service-contracts", - "version": "v1.1.6", + "version": "v1.1.7", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "ea7263d6b6d5f798b56a45a5b8d686725f2719a3" + "reference": "ffcde9615dc5bb4825b9f6aed07716f1f57faae0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/ea7263d6b6d5f798b56a45a5b8d686725f2719a3", - "reference": "ea7263d6b6d5f798b56a45a5b8d686725f2719a3", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/ffcde9615dc5bb4825b9f6aed07716f1f57faae0", + "reference": "ffcde9615dc5bb4825b9f6aed07716f1f57faae0", "shasum": "" }, "require": { @@ -1293,20 +1361,20 @@ "interoperability", "standards" ], - "time": "2019-08-20T14:44:19+00:00" + "time": "2019-09-17T11:12:18+00:00" }, { "name": "symfony/yaml", - "version": "v4.3.4", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "5a0b7c32dc3ec56fd4abae8a4a71b0cf05013686" + "reference": "41e16350a2a1c7383c4735aa2f9fce74cf3d1178" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/5a0b7c32dc3ec56fd4abae8a4a71b0cf05013686", - "reference": "5a0b7c32dc3ec56fd4abae8a4a71b0cf05013686", + "url": "https://api.github.com/repos/symfony/yaml/zipball/41e16350a2a1c7383c4735aa2f9fce74cf3d1178", + "reference": "41e16350a2a1c7383c4735aa2f9fce74cf3d1178", "shasum": "" }, "require": { @@ -1352,7 +1420,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2019-08-20T14:27:59+00:00" + "time": "2019-09-11T15:41:19+00:00" }, { "name": "webuni/commonmark-table-extension", diff --git a/vendor-bin/phpunit/composer.lock b/vendor-bin/phpunit/composer.lock index e27b08c1..558318c8 100644 --- a/vendor-bin/phpunit/composer.lock +++ b/vendor-bin/phpunit/composer.lock @@ -114,23 +114,23 @@ }, { "name": "mikey179/vfsstream", - "version": "v1.6.6", + "version": "v1.6.7", "source": { "type": "git", "url": "https://github.com/bovigo/vfsStream.git", - "reference": "095238a0711c974ae5b4ebf4c4534a23f3f6c99d" + "reference": "2b544ac3a21bcc4dde5d90c4ae8d06f4319055fb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bovigo/vfsStream/zipball/095238a0711c974ae5b4ebf4c4534a23f3f6c99d", - "reference": "095238a0711c974ae5b4ebf4c4534a23f3f6c99d", + "url": "https://api.github.com/repos/bovigo/vfsStream/zipball/2b544ac3a21bcc4dde5d90c4ae8d06f4319055fb", + "reference": "2b544ac3a21bcc4dde5d90c4ae8d06f4319055fb", "shasum": "" }, "require": { "php": ">=5.3.0" }, "require-dev": { - "phpunit/phpunit": "~4.5" + "phpunit/phpunit": "^4.5|^5.0" }, "type": "library", "extra": { @@ -156,20 +156,20 @@ ], "description": "Virtual file system to mock the real file system in unit tests.", "homepage": "http://vfs.bovigo.org/", - "time": "2019-04-08T13:54:32+00:00" + "time": "2019-08-01T01:38:37+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.9.1", + "version": "1.9.3", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72" + "reference": "007c053ae6f31bba39dfa19a7726f56e9763bbea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72", - "reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/007c053ae6f31bba39dfa19a7726f56e9763bbea", + "reference": "007c053ae6f31bba39dfa19a7726f56e9763bbea", "shasum": "" }, "require": { @@ -204,7 +204,7 @@ "object", "object graph" ], - "time": "2019-04-07T13:18:21+00:00" + "time": "2019-08-09T12:45:53+00:00" }, { "name": "phake/phake", @@ -368,35 +368,33 @@ }, { "name": "phpdocumentor/reflection-common", - "version": "1.0.1", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" + "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/63a995caa1ca9e5590304cd845c15ad6d482a62a", + "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a", "shasum": "" }, "require": { - "php": ">=5.5" + "php": ">=7.1" }, "require-dev": { - "phpunit/phpunit": "^4.6" + "phpunit/phpunit": "~6" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.x-dev" } }, "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src" - ] + "phpDocumentor\\Reflection\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -418,30 +416,30 @@ "reflection", "static analysis" ], - "time": "2017-09-11T18:02:19+00:00" + "time": "2018-08-07T13:53:10+00:00" }, { "name": "phpdocumentor/reflection-docblock", - "version": "4.3.1", + "version": "4.3.2", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c" + "reference": "b83ff7cfcfee7827e1e78b637a5904fe6a96698e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c", - "reference": "bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/b83ff7cfcfee7827e1e78b637a5904fe6a96698e", + "reference": "b83ff7cfcfee7827e1e78b637a5904fe6a96698e", "shasum": "" }, "require": { "php": "^7.0", - "phpdocumentor/reflection-common": "^1.0.0", - "phpdocumentor/type-resolver": "^0.4.0", + "phpdocumentor/reflection-common": "^1.0.0 || ^2.0.0", + "phpdocumentor/type-resolver": "~0.4 || ^1.0.0", "webmozart/assert": "^1.0" }, "require-dev": { - "doctrine/instantiator": "~1.0.5", + "doctrine/instantiator": "^1.0.5", "mockery/mockery": "^1.0", "phpunit/phpunit": "^6.4" }, @@ -469,41 +467,40 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2019-04-30T17:48:53+00:00" + "time": "2019-09-12T14:27:41+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "0.4.0", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" + "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/2e32a6d48972b2c1976ed5d8967145b6cec4a4a9", + "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9", "shasum": "" }, "require": { - "php": "^5.5 || ^7.0", - "phpdocumentor/reflection-common": "^1.0" + "php": "^7.1", + "phpdocumentor/reflection-common": "^2.0" }, "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^5.2||^4.8.24" + "ext-tokenizer": "^7.1", + "mockery/mockery": "~1", + "phpunit/phpunit": "^7.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.x-dev" } }, "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] + "phpDocumentor\\Reflection\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -516,26 +513,27 @@ "email": "me@mikevanriel.com" } ], - "time": "2017-07-14T14:27:02+00:00" + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "time": "2019-08-22T18:11:29+00:00" }, { "name": "phpspec/prophecy", - "version": "1.8.1", + "version": "1.9.0", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76" + "reference": "f6811d96d97bdf400077a0cc100ae56aa32b9203" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/1927e75f4ed19131ec9bcc3b002e07fb1173ee76", - "reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/f6811d96d97bdf400077a0cc100ae56aa32b9203", + "reference": "f6811d96d97bdf400077a0cc100ae56aa32b9203", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0", "sebastian/comparator": "^1.1|^2.0|^3.0", "sebastian/recursion-context": "^1.0|^2.0|^3.0" }, @@ -579,7 +577,7 @@ "spy", "stub" ], - "time": "2019-06-13T12:50:23+00:00" + "time": "2019-10-03T11:07:50+00:00" }, { "name": "phpunit/php-code-coverage", @@ -786,16 +784,16 @@ }, { "name": "phpunit/php-token-stream", - "version": "3.0.2", + "version": "3.1.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "c4a66b97f040e3e20b3aa2a243230a1c3a9f7c8c" + "reference": "995192df77f63a59e47f025390d2d1fdf8f425ff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/c4a66b97f040e3e20b3aa2a243230a1c3a9f7c8c", - "reference": "c4a66b97f040e3e20b3aa2a243230a1c3a9f7c8c", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/995192df77f63a59e47f025390d2d1fdf8f425ff", + "reference": "995192df77f63a59e47f025390d2d1fdf8f425ff", "shasum": "" }, "require": { @@ -808,7 +806,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -831,20 +829,20 @@ "keywords": [ "tokenizer" ], - "time": "2019-07-08T05:24:54+00:00" + "time": "2019-09-17T06:23:10+00:00" }, { "name": "phpunit/phpunit", - "version": "7.5.14", + "version": "7.5.16", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "2834789aeb9ac182ad69bfdf9ae91856a59945ff" + "reference": "316afa6888d2562e04aeb67ea7f2017a0eb41661" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2834789aeb9ac182ad69bfdf9ae91856a59945ff", - "reference": "2834789aeb9ac182ad69bfdf9ae91856a59945ff", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/316afa6888d2562e04aeb67ea7f2017a0eb41661", + "reference": "316afa6888d2562e04aeb67ea7f2017a0eb41661", "shasum": "" }, "require": { @@ -904,8 +902,8 @@ "authors": [ { "name": "Sebastian Bergmann", - "role": "lead", - "email": "sebastian@phpunit.de" + "email": "sebastian@phpunit.de", + "role": "lead" } ], "description": "The PHP Unit Testing framework.", @@ -915,7 +913,7 @@ "testing", "xunit" ], - "time": "2019-07-15T06:24:08+00:00" + "time": "2019-09-14T09:08:39+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -1137,16 +1135,16 @@ }, { "name": "sebastian/exporter", - "version": "3.1.0", + "version": "3.1.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "234199f4528de6d12aaa58b612e98f7d36adb937" + "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/234199f4528de6d12aaa58b612e98f7d36adb937", - "reference": "234199f4528de6d12aaa58b612e98f7d36adb937", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/68609e1261d215ea5b21b7987539cbfbe156ec3e", + "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e", "shasum": "" }, "require": { @@ -1173,6 +1171,10 @@ "BSD-3-Clause" ], "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" @@ -1181,17 +1183,13 @@ "name": "Volker Dusch", "email": "github@wallbash.com" }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, { "name": "Adam Harvey", "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" } ], "description": "Provides the functionality to export PHP variables for visualization", @@ -1200,7 +1198,7 @@ "export", "exporter" ], - "time": "2017-04-03T13:19:02+00:00" + "time": "2019-09-14T09:02:43+00:00" }, { "name": "sebastian/global-state", @@ -1485,16 +1483,16 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.11.0", + "version": "v1.12.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "82ebae02209c21113908c229e9883c419720738a" + "reference": "550ebaac289296ce228a706d0867afc34687e3f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/82ebae02209c21113908c229e9883c419720738a", - "reference": "82ebae02209c21113908c229e9883c419720738a", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/550ebaac289296ce228a706d0867afc34687e3f4", + "reference": "550ebaac289296ce228a706d0867afc34687e3f4", "shasum": "" }, "require": { @@ -1506,7 +1504,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11-dev" + "dev-master": "1.12-dev" } }, "autoload": { @@ -1523,12 +1521,12 @@ ], "authors": [ { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" }, { - "name": "Gert de Pagter", - "email": "backendtea@gmail.com" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], "description": "Symfony polyfill for ctype functions", @@ -1539,7 +1537,7 @@ "polyfill", "portable" ], - "time": "2019-02-06T07:57:58+00:00" + "time": "2019-08-06T08:03:45+00:00" }, { "name": "theseer/tokenizer", @@ -1583,16 +1581,16 @@ }, { "name": "webmozart/assert", - "version": "1.4.0", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/webmozart/assert.git", - "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9" + "reference": "88e6d84706d09a236046d686bbea96f07b3a34f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/83e253c8e0be5b0257b881e1827274667c5c17a9", - "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9", + "url": "https://api.github.com/repos/webmozart/assert/zipball/88e6d84706d09a236046d686bbea96f07b3a34f4", + "reference": "88e6d84706d09a236046d686bbea96f07b3a34f4", "shasum": "" }, "require": { @@ -1600,8 +1598,7 @@ "symfony/polyfill-ctype": "^1.8" }, "require-dev": { - "phpunit/phpunit": "^4.6", - "sebastian/version": "^1.0.1" + "phpunit/phpunit": "^4.8.36 || ^7.5.13" }, "type": "library", "extra": { @@ -1630,7 +1627,7 @@ "check", "validate" ], - "time": "2018-12-25T11:19:39+00:00" + "time": "2019-08-24T08:43:50+00:00" }, { "name": "webmozart/glob", diff --git a/vendor-bin/robo/composer.lock b/vendor-bin/robo/composer.lock index 33c71e2c..6ebab025 100644 --- a/vendor-bin/robo/composer.lock +++ b/vendor-bin/robo/composer.lock @@ -376,16 +376,16 @@ }, { "name": "consolidation/robo", - "version": "1.4.9", + "version": "1.4.10", "source": { "type": "git", "url": "https://github.com/consolidation/Robo.git", - "reference": "5c6b3840a45afda1cbffbb3bb1f94dd5f9f83345" + "reference": "e5a6ca64cf1324151873672e484aceb21f365681" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/consolidation/Robo/zipball/5c6b3840a45afda1cbffbb3bb1f94dd5f9f83345", - "reference": "5c6b3840a45afda1cbffbb3bb1f94dd5f9f83345", + "url": "https://api.github.com/repos/consolidation/Robo/zipball/e5a6ca64cf1324151873672e484aceb21f365681", + "reference": "e5a6ca64cf1324151873672e484aceb21f365681", "shasum": "" }, "require": { @@ -480,7 +480,7 @@ } ], "description": "Modern task runner", - "time": "2019-03-19T18:07:19+00:00" + "time": "2019-07-29T15:40:50+00:00" }, { "name": "consolidation/self-update", @@ -1092,16 +1092,16 @@ }, { "name": "symfony/console", - "version": "v4.3.2", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "b592b26a24265a35172d8a2094d8b10f22b7cc39" + "reference": "929ddf360d401b958f611d44e726094ab46a7369" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/b592b26a24265a35172d8a2094d8b10f22b7cc39", - "reference": "b592b26a24265a35172d8a2094d8b10f22b7cc39", + "url": "https://api.github.com/repos/symfony/console/zipball/929ddf360d401b958f611d44e726094ab46a7369", + "reference": "929ddf360d401b958f611d44e726094ab46a7369", "shasum": "" }, "require": { @@ -1163,20 +1163,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2019-06-13T11:03:18+00:00" + "time": "2019-10-07T12:36:49+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v4.3.2", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "d257021c1ab28d48d24a16de79dfab445ce93398" + "reference": "6229f58993e5a157f6096fc7145c0717d0be8807" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d257021c1ab28d48d24a16de79dfab445ce93398", - "reference": "d257021c1ab28d48d24a16de79dfab445ce93398", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/6229f58993e5a157f6096fc7145c0717d0be8807", + "reference": "6229f58993e5a157f6096fc7145c0717d0be8807", "shasum": "" }, "require": { @@ -1233,20 +1233,20 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2019-06-13T11:03:18+00:00" + "time": "2019-10-01T16:40:32+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v1.1.5", + "version": "v1.1.7", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "c61766f4440ca687de1084a5c00b08e167a2575c" + "reference": "c43ab685673fb6c8d84220c77897b1d6cdbe1d18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/c61766f4440ca687de1084a5c00b08e167a2575c", - "reference": "c61766f4440ca687de1084a5c00b08e167a2575c", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/c43ab685673fb6c8d84220c77897b1d6cdbe1d18", + "reference": "c43ab685673fb6c8d84220c77897b1d6cdbe1d18", "shasum": "" }, "require": { @@ -1291,20 +1291,20 @@ "interoperability", "standards" ], - "time": "2019-06-20T06:46:26+00:00" + "time": "2019-09-17T09:54:03+00:00" }, { "name": "symfony/filesystem", - "version": "v4.3.2", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "b9896d034463ad6fd2bf17e2bf9418caecd6313d" + "reference": "9abbb7ef96a51f4d7e69627bc6f63307994e4263" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/b9896d034463ad6fd2bf17e2bf9418caecd6313d", - "reference": "b9896d034463ad6fd2bf17e2bf9418caecd6313d", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/9abbb7ef96a51f4d7e69627bc6f63307994e4263", + "reference": "9abbb7ef96a51f4d7e69627bc6f63307994e4263", "shasum": "" }, "require": { @@ -1341,20 +1341,20 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2019-06-23T08:51:25+00:00" + "time": "2019-08-20T14:07:54+00:00" }, { "name": "symfony/finder", - "version": "v4.3.2", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "33c21f7d5d3dc8a140c282854a7e13aeb5d0f91a" + "reference": "5e575faa95548d0586f6bedaeabec259714e44d1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/33c21f7d5d3dc8a140c282854a7e13aeb5d0f91a", - "reference": "33c21f7d5d3dc8a140c282854a7e13aeb5d0f91a", + "url": "https://api.github.com/repos/symfony/finder/zipball/5e575faa95548d0586f6bedaeabec259714e44d1", + "reference": "5e575faa95548d0586f6bedaeabec259714e44d1", "shasum": "" }, "require": { @@ -1390,20 +1390,20 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2019-06-13T11:03:18+00:00" + "time": "2019-09-16T11:29:48+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.11.0", + "version": "v1.12.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "82ebae02209c21113908c229e9883c419720738a" + "reference": "550ebaac289296ce228a706d0867afc34687e3f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/82ebae02209c21113908c229e9883c419720738a", - "reference": "82ebae02209c21113908c229e9883c419720738a", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/550ebaac289296ce228a706d0867afc34687e3f4", + "reference": "550ebaac289296ce228a706d0867afc34687e3f4", "shasum": "" }, "require": { @@ -1415,7 +1415,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11-dev" + "dev-master": "1.12-dev" } }, "autoload": { @@ -1432,12 +1432,12 @@ ], "authors": [ { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" }, { - "name": "Gert de Pagter", - "email": "backendtea@gmail.com" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], "description": "Symfony polyfill for ctype functions", @@ -1448,20 +1448,20 @@ "polyfill", "portable" ], - "time": "2019-02-06T07:57:58+00:00" + "time": "2019-08-06T08:03:45+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.11.0", + "version": "v1.12.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "fe5e94c604826c35a32fa832f35bd036b6799609" + "reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fe5e94c604826c35a32fa832f35bd036b6799609", - "reference": "fe5e94c604826c35a32fa832f35bd036b6799609", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/b42a2f66e8f1b15ccf25652c3424265923eb4f17", + "reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17", "shasum": "" }, "require": { @@ -1473,7 +1473,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11-dev" + "dev-master": "1.12-dev" } }, "autoload": { @@ -1507,20 +1507,20 @@ "portable", "shim" ], - "time": "2019-02-06T07:57:58+00:00" + "time": "2019-08-06T08:03:45+00:00" }, { "name": "symfony/polyfill-php73", - "version": "v1.11.0", + "version": "v1.12.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "d1fb4abcc0c47be136208ad9d68bf59f1ee17abd" + "reference": "2ceb49eaccb9352bff54d22570276bb75ba4a188" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/d1fb4abcc0c47be136208ad9d68bf59f1ee17abd", - "reference": "d1fb4abcc0c47be136208ad9d68bf59f1ee17abd", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/2ceb49eaccb9352bff54d22570276bb75ba4a188", + "reference": "2ceb49eaccb9352bff54d22570276bb75ba4a188", "shasum": "" }, "require": { @@ -1529,7 +1529,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11-dev" + "dev-master": "1.12-dev" } }, "autoload": { @@ -1565,20 +1565,20 @@ "portable", "shim" ], - "time": "2019-02-06T07:57:58+00:00" + "time": "2019-08-06T08:03:45+00:00" }, { "name": "symfony/process", - "version": "v3.4.29", + "version": "v3.4.32", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "d129c017e8602507688ef2c3007951a16c1a8407" + "reference": "344dc588b163ff58274f1769b90b75237f32ed16" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/d129c017e8602507688ef2c3007951a16c1a8407", - "reference": "d129c017e8602507688ef2c3007951a16c1a8407", + "url": "https://api.github.com/repos/symfony/process/zipball/344dc588b163ff58274f1769b90b75237f32ed16", + "reference": "344dc588b163ff58274f1769b90b75237f32ed16", "shasum": "" }, "require": { @@ -1614,20 +1614,20 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2019-05-30T15:47:52+00:00" + "time": "2019-09-25T14:09:38+00:00" }, { "name": "symfony/service-contracts", - "version": "v1.1.5", + "version": "v1.1.7", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "f391a00de78ec7ec8cf5cdcdae59ec7b883edb8d" + "reference": "ffcde9615dc5bb4825b9f6aed07716f1f57faae0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f391a00de78ec7ec8cf5cdcdae59ec7b883edb8d", - "reference": "f391a00de78ec7ec8cf5cdcdae59ec7b883edb8d", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/ffcde9615dc5bb4825b9f6aed07716f1f57faae0", + "reference": "ffcde9615dc5bb4825b9f6aed07716f1f57faae0", "shasum": "" }, "require": { @@ -1672,20 +1672,20 @@ "interoperability", "standards" ], - "time": "2019-06-13T11:15:36+00:00" + "time": "2019-09-17T11:12:18+00:00" }, { "name": "symfony/yaml", - "version": "v4.3.2", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "c60ecf5ba842324433b46f58dc7afc4487dbab99" + "reference": "41e16350a2a1c7383c4735aa2f9fce74cf3d1178" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/c60ecf5ba842324433b46f58dc7afc4487dbab99", - "reference": "c60ecf5ba842324433b46f58dc7afc4487dbab99", + "url": "https://api.github.com/repos/symfony/yaml/zipball/41e16350a2a1c7383c4735aa2f9fce74cf3d1178", + "reference": "41e16350a2a1c7383c4735aa2f9fce74cf3d1178", "shasum": "" }, "require": { @@ -1731,7 +1731,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2019-04-06T14:04:46+00:00" + "time": "2019-09-11T15:41:19+00:00" } ], "packages-dev": [],