├── bin ├── phpunit ├── phpcs └── phpcbf ├── .gitignore ├── .twgit ├── phpcs.xml ├── .travis.yml ├── composer.json ├── phpunit.xml.dist ├── LICENSE ├── README.md ├── Tests └── CasperTest.php ├── src └── Casper.php └── composer.lock /bin/phpunit: -------------------------------------------------------------------------------- 1 | ../vendor/phpunit/phpunit/phpunit -------------------------------------------------------------------------------- /bin/phpcs: -------------------------------------------------------------------------------- 1 | ../vendor/squizlabs/php_codesniffer/scripts/phpcs -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | .twgit_features_subject 3 | bin/* 4 | -------------------------------------------------------------------------------- /.twgit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | TWGIT_STABLE='master' 4 | -------------------------------------------------------------------------------- /bin/phpcbf: -------------------------------------------------------------------------------- 1 | ../vendor/squizlabs/php_codesniffer/scripts/phpcbf -------------------------------------------------------------------------------- /phpcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | The coding standard for php-casperjs. 4 | 5 | src 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - '5.5' 5 | - '5.6' 6 | - '7.0' 7 | - hhvm 8 | 9 | install: 10 | - npm install phantomjs 11 | - npm install casperjs 12 | - npm install slimerjs 13 | - composer install 14 | 15 | notifications: 16 | on_success: always 17 | on_failure: always 18 | 19 | addons: 20 | firefox: latest 21 | 22 | env: 23 | - SLIMERJSLAUNCHER=$HOME/firefox-latest/firefox/firefox 24 | 25 | before_script: 26 | - "export DISPLAY=:99.0" 27 | - "sh -e /etc/init.d/xvfb start" 28 | - sleep 3 # give xvfb some time to start 29 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "phpcasperjs/phpcasperjs", 3 | "description": "Simple PHP wrapper for CasperJS", 4 | "homepage": "https://github.com/alwex/php-casperjs", 5 | "keywords": ["phpunit", "test", "browser"], 6 | "type": "library", 7 | "license": "MIT", 8 | "authors": [ 9 | { 10 | "name": "GUIDET Alexandre", 11 | "email": "alwex@free.fr" 12 | } 13 | ], 14 | "config": { 15 | "bin-dir": "bin" 16 | }, 17 | "require": { 18 | "php": ">=5.3.0" 19 | }, 20 | "require-dev": { 21 | "phpunit/phpunit": "4.*", 22 | "squizlabs/php_codesniffer": "2.*" 23 | }, 24 | "autoload": { 25 | "psr-4": {"Browser\\": "src/"} 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | 15 | ./Tests/ 16 | 17 | 18 | 19 | 20 | 21 | ./ 22 | 23 | ./vendor 24 | ./Tests 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2013 Alexandre Guidet 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | php-casperjs 2 | ============ 3 | 4 | [![Travis branch](https://img.shields.io/travis/alwex/php-casperjs/stable.svg)]() 5 | [![Packagist](https://img.shields.io/packagist/dt/phpcasperjs/phpcasperjs.svg?maxAge=2592000)]() 6 | [![Version](http://img.shields.io/packagist/v/phpcasperjs/phpcasperjs.svg?style=flat)](https://packagist.org/packages/phpcasperjs/phpcasperjs) 7 | [![License](http://img.shields.io/:license-mit-blue.svg)](http://doge.mit-license.org) 8 | 9 | [![SensioLabsInsight](https://insight.sensiolabs.com/projects/64289c40-f11c-49ef-b295-2e7ec784d64a/big.png)](https://insight.sensiolabs.com/projects/64289c40-f11c-49ef-b295-2e7ec784d64a) 10 | 11 | php-casperjs is a simple PHP wrapper for the fine library CasperJS designed to automate 12 | user testing against web pages. 13 | 14 | It is easy to integrate into PHPUnit test case. 15 | 16 | Making webcrawler has never been so easy! 17 | 18 | Installation 19 | ------------ 20 | 21 | Before using php-casperjs, you need to install both library: 22 | 23 | 1 - **PhantomJS** http://phantomjs.org/download.html 24 | 25 | 2 - **CasperJS** http://docs.casperjs.org/en/latest/installation.html 26 | 27 | ```shell 28 | npm install phantomjs 29 | npm install casperjs 30 | ``` 31 | 32 | then 33 | 34 | ```shell 35 | composer require phpcasperjs/phpcasperjs 36 | ``` 37 | 38 | Usage 39 | ----- 40 | 41 | ```php 42 | setOptions([ 51 | 'ignore-ssl-errors' => 'yes' 52 | ]); 53 | 54 | // navigate to google web page 55 | $casper->start('http://www.google.com'); 56 | 57 | // fill the search form and submit it with input's name 58 | $casper->fillForm( 59 | 'form[action="/search"]', 60 | array( 61 | 'q' => 'search' 62 | ), 63 | true); 64 | 65 | // or with javascript selectors: 66 | $casper->fillFormSelectors( 67 | 'form.form-class', 68 | array( 69 | 'input#email-id' => 'user-email', 70 | 'input#password-id' => 'user-password' 71 | ),true); 72 | 73 | // wait for 5 seconds (have a coffee) 74 | $casper->wait(5000); 75 | 76 | // wait for text if needed for 3 seconds 77 | $casper->waitForText('Yahoo', 3000); 78 | 79 | // or wait for selector 80 | $casper->waitForSelector('.gbqfb', 3000); 81 | 82 | // make a screenshot of the google logo 83 | $casper->captureSelector('#hplogo', '/tmp/logo.png'); 84 | 85 | // or take a screenshot of a custom area 86 | $casper->capture( 87 | array( 88 | 'top' => 0, 89 | 'left' => 0, 90 | 'width' => 800, 91 | 'height' => 600 92 | ), 93 | '/tmp/custom-capture.png' 94 | ); 95 | 96 | // click the first result 97 | $casper->click('h3.r a'); 98 | 99 | // switch to the first iframe 100 | $casper->switchToChildFrame(0); 101 | 102 | // make some stuff inside the iframe 103 | $casper->fillForm('#myForm', array( 104 | 'search' => 'my search', 105 | )); 106 | 107 | // go back to parent 108 | $casper->switchToParentFrame(); 109 | 110 | // run the casper script 111 | $casper->run(); 112 | 113 | // check the urls casper get through 114 | var_dump($casper->getRequestedUrls()); 115 | 116 | // need to debug? just check the casper output 117 | var_dump($casper->getOutput()); 118 | 119 | ``` 120 | 121 | If you want to see your crawler in action, set the engine to slimerjs 122 | 123 | ```php 124 | $casper = new Casper(); 125 | $casper->setOptions(['engine' => 'slimerjs']); 126 | ``` 127 | -------------------------------------------------------------------------------- /Tests/CasperTest.php: -------------------------------------------------------------------------------- 1 | assertInstanceOf('Browser\Casper', $casper); 21 | } 22 | 23 | public function testStart_onGoogleSearchPage() 24 | { 25 | $casper = new Casper(self::$casperBinPath); 26 | 27 | $casper->start('http://www.google.com'); 28 | $casper->fillForm( 29 | 'form[action="/search"]', 30 | array( 31 | 'q' => 'search' 32 | ), 33 | true); 34 | $casper->click('h3.r a'); 35 | $casper->run(); 36 | 37 | $this->assertTrue(is_array($casper->getOutput())); 38 | $this->assertTrue(sizeof($casper->getOutput()) > 0); 39 | $this->assertNotNull($casper->getCurrentUrl()); 40 | } 41 | 42 | public function testStart_onGoogleSearchPageWithSlimerJS() 43 | { 44 | $casper = new Casper(self::$casperBinPath); 45 | 46 | $casper->setOptions(['engine' => 'slimerjs']); 47 | $casper->start('http://www.google.com'); 48 | $casper->fillForm( 49 | 'form[action="/search"]', 50 | array( 51 | 'q' => 'search' 52 | ), 53 | true); 54 | $casper->click('h3.r a'); 55 | $casper->run(); 56 | 57 | $this->assertTrue(is_array($casper->getOutput())); 58 | $this->assertTrue(sizeof($casper->getOutput()) > 0); 59 | $this->assertNotNull($casper->getCurrentUrl()); 60 | } 61 | 62 | public function testStart_onGoogleSearchPageWithIgnoreSSLErrorOption() 63 | { 64 | $casper = new Casper(self::$casperBinPath); 65 | $casper->setOptions(array( 66 | 'ignore-ssl-errors' => 'yes' 67 | )); 68 | 69 | $casper->start('http://www.google.com'); 70 | $casper->fillForm( 71 | 'form[action="/search"]', 72 | array( 73 | 'q' => 'search' 74 | ), 75 | true); 76 | $casper->click('h3.r a'); 77 | $casper->run(); 78 | 79 | $this->assertTrue(is_array($casper->getOutput())); 80 | $this->assertTrue(sizeof($casper->getOutput()) > 0); 81 | $this->assertNotNull($casper->getCurrentUrl()); 82 | } 83 | 84 | public function testGetRequestedUrls() 85 | { 86 | $urls = array(); 87 | 88 | $casper = new Casper(self::$casperBinPath); 89 | 90 | $casper->start('http://www.google.com'); 91 | $casper->fillForm( 92 | 'form[action="/search"]', 93 | array( 94 | 'q' => 'search' 95 | ), 96 | true); 97 | $casper->click('h3.r a'); 98 | $casper->run(); 99 | 100 | $this->assertNotEmpty($casper->getRequestedUrls()); 101 | $this->assertContains('http://www.google.com/', $casper->getRequestedUrls()); 102 | } 103 | 104 | public function testWaitForText() 105 | { 106 | $casper = new Casper(self::$casperBinPath); 107 | 108 | $casper->start('http://www.google.com'); 109 | $casper->fillForm( 110 | 'form[action="/search"]', 111 | array( 112 | 'q' => 'search' 113 | ), 114 | true); 115 | $casper->waitForText('Yahoo', 20000); 116 | $casper->click('h3.r a'); 117 | $casper->run(); 118 | 119 | $this->assertNotEmpty($casper->getRequestedUrls()); 120 | $this->assertContains('http://www.google.com/', $casper->getRequestedUrls()); 121 | } 122 | 123 | public function testWait() 124 | { 125 | $startSecond = time(); 126 | 127 | $casper = new Casper(self::$casperBinPath); 128 | 129 | $casper->start('http://www.google.com'); 130 | $casper->wait(3000); 131 | $casper->run(); 132 | 133 | $endSecond = time(); 134 | 135 | $this->assertTrue($endSecond - $startSecond > 2); 136 | } 137 | 138 | public function testWaitForSelector() 139 | { 140 | $casper = new Casper(self::$casperBinPath); 141 | 142 | $casper->start('http://www.google.com'); 143 | $casper->fillForm( 144 | 'form[action="/search"]', 145 | array( 146 | 'q' => 'search' 147 | ), 148 | true); 149 | $casper->waitForSelector('.gbqfb', 2000); 150 | $casper->click('h3.r a'); 151 | $casper->run(); 152 | 153 | $this->assertNotEmpty($casper->getRequestedUrls()); 154 | $this->assertContains('http://www.google.com/', $casper->getRequestedUrls()); 155 | } 156 | 157 | public function testCaptureSelector() 158 | { 159 | $filename = '/tmp/casperjs-test.png'; 160 | 161 | $casper = new Casper(self::$casperBinPath); 162 | 163 | $casper->start('http://www.google.com'); 164 | $casper->captureSelector('#hplogo', $filename); 165 | $casper->run(); 166 | 167 | $this->assertFileExists($filename); 168 | unlink($filename); 169 | $this->assertFileNotExists($filename); 170 | } 171 | 172 | public function testCapture() 173 | { 174 | $filename = '/tmp/casperjs-test.png'; 175 | 176 | $casper = new Casper(self::$casperBinPath); 177 | 178 | $casper->start('http://www.google.com'); 179 | $casper->capture( 180 | array( 181 | 'top' => 0, 182 | 'left' => 0, 183 | 'width' => 800, 184 | 'height' => 600 185 | ), 186 | $filename 187 | ); 188 | $casper->run(); 189 | 190 | $this->assertFileExists($filename); 191 | unlink($filename); 192 | $this->assertFileNotExists($filename); 193 | } 194 | 195 | public function testSwitchToChildFrame() 196 | { 197 | $html = <<< HTML 198 | 199 | 200 | 201 | 202 | iframe 1 203 | 204 | 205 | 206 | 207 | 208 | HTML; 209 | 210 | $filename = '/tmp/iframe1.html'; 211 | 212 | file_put_contents($filename, $html); 213 | 214 | $year = date('Y'); 215 | $year++; 216 | 217 | $casper = new Casper(self::$casperBinPath); 218 | 219 | $casper->start('file:///tmp/iframe1.html') 220 | ->switchToChildFrame(0) 221 | ->fillForm('#tokenizerForm', array( 222 | 'tokenizerForm\:cardNumber' => 'testing', 223 | 'tokenizerForm\:cardHolder' => 'Jean Valjean', 224 | 'tokenizerForm\:cardExpiryYear' => $year, 225 | 'tokenizerForm\:cardSecurityCode' => '123', 226 | )) 227 | ->switchToParentFrame() 228 | ->capture( 229 | array( 230 | 'top' => 0, 231 | 'left' => 0, 232 | 'width' => 800, 233 | 'height' => 600 234 | ), 235 | '/tmp/testage.png' 236 | ) 237 | ->run(); 238 | 239 | $found = false; 240 | foreach ($casper->getOutput() as $logLine) { 241 | if (preg_match('/Set "tokenizerForm:cardNumber" field value to testing/', $logLine)) { 242 | $found = true; 243 | } 244 | } 245 | 246 | $this->assertTrue($found); 247 | 248 | $this->assertFileExists($filename); 249 | unlink($filename); 250 | $this->assertFileNotExists($filename); 251 | 252 | } 253 | 254 | public function testEvaluate() 255 | { 256 | $evaluateHtml = << 258 | 259 | 260 | 261 | test evaluate 262 | 263 | 264 | link to google 265 | 266 | 267 | TEXT; 268 | $filename = '/tmp/test-evaluate.html'; 269 | 270 | file_put_contents($filename, $evaluateHtml); 271 | 272 | $casper = new Casper(self::$casperBinPath); 273 | $casper->start($filename) 274 | ->click('#theLink') 275 | ->run(); 276 | 277 | $this->assertContains('google', $casper->getCurrentUrl()); 278 | 279 | $casper = new Casper(self::$casperBinPath); 280 | $casper->start($filename) 281 | ->evaluate('document.getElementById("theLink").href="http://www.yahoo.com";') 282 | ->click('#theLink') 283 | ->run(); 284 | 285 | $this->assertContains('yahoo.com', $casper->getCurrentUrl()); 286 | 287 | @unlink($filename); 288 | } 289 | 290 | public function testDoubleClick() 291 | { 292 | $evaluateHtml = << 294 | 295 | 296 | 297 | test evaluate 298 | 299 | 300 | 306 | test 307 | 308 | 309 | 310 | TEXT; 311 | $filename = '/tmp/test-click.html'; 312 | file_put_contents($filename, $evaluateHtml); 313 | 314 | $casper = new Casper(self::$casperBinPath); 315 | $casper->start($filename) 316 | ->click("#theLink") 317 | ->run(); 318 | 319 | @unlink($filename); 320 | } 321 | 322 | public function testInjectCustomScript() 323 | { 324 | $casper = new Casper(self::$casperBinPath); 325 | $casper->start('about:blank') 326 | ->addToScript(<<run(); 331 | 332 | $found = false; 333 | foreach ($casper->getOutput() as $logLine) { 334 | if (preg_match('/ABCDEFGH/', $logLine)) { 335 | $found = true; 336 | } 337 | } 338 | 339 | $this->assertTrue($found); 340 | } 341 | 342 | /** 343 | * @return array 344 | */ 345 | public function getEngines() 346 | { 347 | return [ 348 | ['phantomjs'], 349 | ['slimerjs'], 350 | ]; 351 | } 352 | 353 | /** 354 | * @dataProvider getEngines 355 | * @param string $engine 356 | */ 357 | public function testHeaders($engine) 358 | { 359 | $casper = new Casper(self::$casperBinPath); 360 | 361 | $casper->setOptions(['engine' => $engine]); 362 | 363 | $casper->start('http://www.google.com'); 364 | $casper->run(); 365 | 366 | $headers = $casper->getHeaders(); 367 | $keys = array_column($headers, 'name'); 368 | 369 | $this->assertContains('Date', $keys); 370 | $this->assertContains('Content-Type', $keys); 371 | $this->assertContains('Cache-Control', $keys); 372 | } 373 | 374 | /** 375 | * @dataProvider getEngines 376 | * @param string $engine 377 | */ 378 | public function testGetStatus($engine) 379 | { 380 | $casper = new Casper(self::$casperBinPath); 381 | 382 | $casper->setOptions(['engine' => $engine]); 383 | 384 | $casper->start('https://www.w3.org/'); 385 | $casper->run(); 386 | 387 | $status = $casper->getStatus(); 388 | 389 | $this->assertSame(200, $status); 390 | } 391 | 392 | /** 393 | * @dataProvider getEngines 394 | * @param string $engine 395 | */ 396 | public function testGetStatusText($engine) 397 | { 398 | $casper = new Casper(self::$casperBinPath); 399 | 400 | $casper->setOptions(['engine' => $engine]); 401 | 402 | $casper->start('https://www.w3.org/'); 403 | $casper->run(); 404 | 405 | $statusText = $casper->getStatusText(); 406 | 407 | $this->assertSame('OK', $statusText); 408 | } 409 | 410 | /** 411 | * @dataProvider getEngines 412 | * @param string $engine 413 | */ 414 | public function testGetCookies($engine) 415 | { 416 | $casper = new Casper(self::$casperBinPath); 417 | 418 | $casper->setOptions(['engine' => $engine]); 419 | 420 | $casper->start('https://twitter.com'); 421 | $casper->run(); 422 | 423 | $cookies = $casper->getCookies(); 424 | 425 | $firstCookie = call_user_func_array('array_merge', $cookies); 426 | 427 | $domains = array_unique(array_column($cookies, 'domain')); 428 | 429 | $this->assertArrayHasKey('domain', $firstCookie); 430 | $this->assertArrayHasKey('expires', $firstCookie); 431 | $this->assertArrayHasKey('expiry', $firstCookie); 432 | $this->assertArrayHasKey('httponly', $firstCookie); 433 | $this->assertArrayHasKey('name', $firstCookie); 434 | $this->assertArrayHasKey('path', $firstCookie); 435 | $this->assertArrayHasKey('secure', $firstCookie); 436 | $this->assertArrayHasKey('value', $firstCookie); 437 | 438 | $this->assertContains('.twitter.com', $domains); 439 | } 440 | } 441 | -------------------------------------------------------------------------------- /src/Casper.php: -------------------------------------------------------------------------------- 1 | path2casper = $path2casper; 43 | } 44 | if ($tempDir) { 45 | $this->tempDir = $tempDir; 46 | } 47 | } 48 | 49 | /** 50 | * @param $path 51 | * @return $this 52 | */ 53 | public function setPath2Casper($path) 54 | { 55 | $this->path2casper = $path; 56 | 57 | return $this; 58 | } 59 | 60 | /** 61 | * @return null|string 62 | */ 63 | public function getPath2Casper() 64 | { 65 | return $this->path2casper; 66 | } 67 | 68 | /** 69 | * @param array $headers 70 | * @return $this 71 | */ 72 | public function setHeaders(array $headers) 73 | { 74 | $headersScript = " 75 | casper.page.customHeaders = { 76 | "; 77 | if (!empty($headers)) { 78 | $headerLines = []; 79 | foreach ($headers as $header => $value) { 80 | // Current version of casperjs will not decode gzipped output 81 | if ($header == 'Accept-Encoding') { 82 | continue; 83 | } 84 | $headerLine = " '{$header}': '"; 85 | $headerLine .= (is_array($value)) ? implode(',', $value) : $value; 86 | $headerLine .= "'"; 87 | $headerLines[] = $headerLine; 88 | } 89 | $headersScript .= implode(",\n", $headerLines) . "\n"; 90 | } 91 | $headersScript .= "};"; 92 | $this->script .= $headersScript; 93 | 94 | return $this; 95 | } 96 | 97 | /** 98 | * Set the UserAgent 99 | * 100 | * @param string $userAgent 101 | */ 102 | public function setUserAgent($userAgent) 103 | { 104 | $this->userAgent = $userAgent; 105 | } 106 | 107 | /** 108 | * enable debug logging into syslog 109 | * 110 | * @param bool $debug 111 | * 112 | * @return Casper 113 | */ 114 | public function setDebug($debug) 115 | { 116 | $this->debug = $debug; 117 | 118 | return $this; 119 | } 120 | 121 | public function setViewPort($width, $height) 122 | { 123 | $this->viewPortWidth = $width; 124 | 125 | $fragment = <<script .= $fragment; 133 | 134 | return $this; 135 | } 136 | 137 | 138 | /** 139 | * 140 | * @return boolean 141 | */ 142 | public function isDebug() 143 | { 144 | return $this->debug; 145 | } 146 | 147 | /** 148 | * set specific options to casperJS 149 | * 150 | * @param array $options 151 | */ 152 | public function setOptions(array $options) 153 | { 154 | $this->options = $options; 155 | } 156 | 157 | /** 158 | * @param array $output 159 | * 160 | * @return Casper 161 | */ 162 | private function setOutput($output) 163 | { 164 | $this->output = $output; 165 | 166 | return $this; 167 | } 168 | 169 | /** 170 | * @return array 171 | */ 172 | public function getOutput() 173 | { 174 | return $this->output; 175 | } 176 | 177 | /** 178 | * clear the current casper script 179 | */ 180 | private function clear() 181 | { 182 | $this->script = ''; 183 | $this->output = array(); 184 | $this->requestedUrls = array(); 185 | $this->currentUrl = ''; 186 | } 187 | 188 | /** 189 | * open the specified url 190 | * 191 | * @param string $url 192 | * 193 | * @return \Browser\Casper 194 | */ 195 | public function start($url) 196 | { 197 | $this->clear(); 198 | 199 | $fragment = <<userAgent'); 208 | casper.start().then(function() { 209 | this.open('$url', { 210 | headers: { 211 | 'Accept': 'text/html' 212 | } 213 | }); 214 | }); 215 | 216 | FRAGMENT; 217 | 218 | $this->script = $fragment; 219 | 220 | return $this; 221 | } 222 | 223 | /** 224 | * Open URL after the initial opening 225 | * 226 | * @param $url 227 | * 228 | * @return $this 229 | */ 230 | public function thenOpen($url) 231 | { 232 | $fragment = <<script .= $fragment; 238 | 239 | return $this; 240 | } 241 | 242 | /** 243 | * fill the form with the array of data 244 | * then submit it if submit is true 245 | * 246 | * @param string $selector 247 | * @param array $data 248 | * @param string|bool $submit 249 | * 250 | * @return \Browser\Casper 251 | */ 252 | public function fillForm($selector, $data = array(), $submit = false) 253 | { 254 | $jsonData = json_encode($data); 255 | $jsonSubmit = ($submit) ? 'true' : 'false'; 256 | 257 | $fragment = <<script .= $fragment; 264 | 265 | return $this; 266 | } 267 | 268 | public function fillFormSelectors($selector, $data = array(), $submit = false) 269 | { 270 | $jsonData = json_encode($data); 271 | $jsonSubmit = ($submit) ? 'true' : 'false'; 272 | 273 | $fragment = <<script .= $fragment; 280 | 281 | return $this; 282 | } 283 | 284 | /** 285 | * Sends native keyboard events 286 | * to the element matching the provided selector: 287 | * 288 | * @param string $selector 289 | * @param string $string 290 | * 291 | * @return \Browser\Casper 292 | */ 293 | public function sendKeys($selector, $string) 294 | { 295 | $jsonData = json_encode($string); 296 | 297 | $fragment = <<script .= $fragment; 305 | 306 | return $this; 307 | } 308 | 309 | /** 310 | * wait until the text $text 311 | * appear on the page 312 | * 313 | * @param string $text 314 | * @param integer $timeout 315 | * 316 | * @return \Browser\Casper 317 | */ 318 | public function waitForText($text, $timeout = 5000) 319 | { 320 | $fragment = <<script .= $fragment; 335 | 336 | return $this; 337 | } 338 | 339 | /** 340 | * @param int $timeout 341 | * @return $this 342 | */ 343 | public function wait($timeout = 5000) 344 | { 345 | $fragment = <<script .= $fragment; 356 | 357 | return $this; 358 | } 359 | 360 | /** 361 | * @param $selector 362 | * @param int $timeout 363 | * @return $this 364 | */ 365 | public function waitForSelector($selector, $timeout = 5000) 366 | { 367 | $fragment = <<script .= $fragment; 382 | 383 | return $this; 384 | } 385 | 386 | /** 387 | * @param $selector 388 | * @return $this 389 | */ 390 | public function click($selector) 391 | { 392 | $fragment = <<script .= $fragment; 400 | 401 | return $this; 402 | } 403 | 404 | /** 405 | * take a screenshot of the page 406 | * area containing the selector 407 | * 408 | * @param string $selector 409 | * @param string $filename 410 | * 411 | * @return $this 412 | */ 413 | public function captureSelector($selector, $filename) 414 | { 415 | $fragment = <<script .= $fragment; 423 | 424 | return $this; 425 | } 426 | 427 | 428 | /** 429 | * take a screenshot of the page 430 | * area defined by 431 | * array(top left width height) 432 | * 433 | * @param array $area 434 | * @param string $filename 435 | * 436 | * @return $this 437 | */ 438 | public function capture(array $area, $filename) 439 | { 440 | $top = $area['top']; 441 | $left = $area['left']; 442 | $width = $area['width']; 443 | $height = $area['height']; 444 | 445 | $fragment = <<script .= $fragment; 458 | 459 | return $this; 460 | } 461 | 462 | /** 463 | * take a screenshot of the whole page 464 | * area defined by viewport width 465 | * and rendered height 466 | * 467 | * @param string $filename 468 | * 469 | * @return $this 470 | */ 471 | public function capturePage($filename) 472 | { 473 | 474 | $fragment = <<viewPortWidth, 480 | height: this.evaluate(function() { 481 | return __utils__.getDocumentHeight(); 482 | }), 483 | }); 484 | }); 485 | FRAGMENT; 486 | 487 | $this->script .= $fragment; 488 | 489 | return $this; 490 | } 491 | 492 | /** 493 | * switch to the child frame number $id 494 | * 495 | * @param string $id 496 | * 497 | * @return $this 498 | */ 499 | public function switchToChildFrame($id) 500 | { 501 | $fragment = <<script .= $fragment; 509 | 510 | return $this; 511 | } 512 | 513 | /** 514 | * get back to parent frame 515 | * 516 | * @return $this 517 | */ 518 | public function switchToParentFrame() 519 | { 520 | $fragment = <<script .= $fragment; 528 | 529 | return $this; 530 | } 531 | 532 | /** 533 | * @param $function 534 | * @return $this 535 | */ 536 | public function evaluate($function) 537 | { 538 | $fragment = <<script .= $fragment; 548 | 549 | return $this; 550 | } 551 | 552 | /** 553 | * @param $js 554 | * @return $this 555 | */ 556 | public function addToScript($js) 557 | { 558 | $fragment = <<script .= $fragment; 563 | 564 | return $this; 565 | } 566 | 567 | /** 568 | * run the casperJS script and return the stdOut 569 | * in using the output variable 570 | * 571 | * @return array 572 | * @throws \Exception 573 | */ 574 | public function run() 575 | { 576 | $output = array(); 577 | 578 | $fragment = <<TAG_CURRENT_URL' + this.getCurrentUrl()); 581 | this.echo('$this->TAG_CURRENT_TITLE' + this.getTitle()); 582 | this.echo('$this->TAG_CURRENT_PAGE_CONTENT' + this.getPageContent().replace(new RegExp('\\r?\\n','g'), '')); 583 | this.echo('$this->TAG_CURRENT_HTML' + this.getHTML().replace(new RegExp('\\r?\\n','g'), '')); 584 | this.echo('$this->TAG_CURRENT_HEADERS' + JSON.stringify(this.currentResponse.headers)); 585 | this.echo('$this->TAG_CURRENT_STATUS' + this.currentResponse.status); 586 | this.echo('$this->TAG_CURRENT_STATUS_TEXT' + this.currentResponse.statusText); 587 | this.echo('$this->TAG_CURRENT_COOKIES' + JSON.stringify(phantom.cookies)); 588 | }); 589 | 590 | casper.run(); 591 | 592 | FRAGMENT; 593 | 594 | $this->script .= $fragment; 595 | $filename = tempnam($this->tempDir, 'php-casperjs-'); 596 | 597 | file_put_contents($filename, $this->script); 598 | 599 | // options parsing 600 | $options = ''; 601 | foreach ($this->options as $option => $value) { 602 | $options .= ' --' . $option . '=' . $value; 603 | } 604 | 605 | exec($this->path2casper . 'casperjs ' . $filename . $options, $output); 606 | if (empty($output)) { 607 | throw new \Exception('Can not find CasperJS.'); 608 | } 609 | 610 | $this->setOutput($output); 611 | $this->processOutput(); 612 | 613 | unlink($filename); 614 | 615 | return $output; 616 | } 617 | 618 | /** 619 | * process the output after navigation 620 | * and fill the differents attributes for 621 | * later usage 622 | */ 623 | private function processOutput() 624 | { 625 | foreach ($this->getOutput() as $outputLine) { 626 | if (strpos($outputLine, $this->TAG_CURRENT_URL) !== false) { 627 | $this->currentUrl = str_replace( 628 | $this->TAG_CURRENT_URL, 629 | '', 630 | $outputLine 631 | ); 632 | } 633 | 634 | if (strpos($outputLine, "Navigation requested: url=") !== false) { 635 | $frag0 = explode('Navigation requested: url=', $outputLine); 636 | $frag1 = explode(', type=', $frag0[1]); 637 | $this->requestedUrls[] = $frag1[0]; 638 | } 639 | 640 | if ($this->isDebug()) { 641 | syslog(LOG_INFO, '[PHP-CASPERJS] ' . $outputLine); 642 | } 643 | if (strpos( 644 | $outputLine, 645 | $this->TAG_CURRENT_PAGE_CONTENT 646 | ) !== false 647 | ) { 648 | $this->currentPageContent = str_replace( 649 | $this->TAG_CURRENT_PAGE_CONTENT, 650 | '', 651 | $outputLine 652 | ); 653 | } 654 | 655 | if (strpos($outputLine, $this->TAG_CURRENT_HTML) !== false) { 656 | $this->currentHtml = str_replace( 657 | $this->TAG_CURRENT_HTML, 658 | '', 659 | $outputLine 660 | ); 661 | } 662 | 663 | if (strpos($outputLine, " steps in ") !== false) { 664 | $frag = explode(' steps in ', $outputLine); 665 | $this->loadTime = $frag[1]; 666 | } 667 | 668 | if (0 === strpos($outputLine, $this->TAG_CURRENT_HEADERS)) { 669 | $this->headers = json_decode(str_replace($this->TAG_CURRENT_HEADERS, '', $outputLine), true); 670 | } 671 | 672 | if (0 === strpos($outputLine, $this->TAG_CURRENT_STATUS)) { 673 | $this->status = (int) str_replace($this->TAG_CURRENT_STATUS, '', $outputLine); 674 | } 675 | 676 | if (0 === strpos($outputLine, $this->TAG_CURRENT_STATUS_TEXT)) { 677 | $this->statusText = trim(str_replace($this->TAG_CURRENT_STATUS_TEXT, '', $outputLine)); 678 | } 679 | 680 | if (0 === strpos($outputLine, $this->TAG_CURRENT_COOKIES)) { 681 | $this->cookies = json_decode(str_replace($this->TAG_CURRENT_COOKIES, '', $outputLine), true); 682 | } 683 | } 684 | } 685 | 686 | public function getCurrentUrl() 687 | { 688 | return $this->currentUrl; 689 | } 690 | 691 | public function getRequestedUrls() 692 | { 693 | return $this->requestedUrls; 694 | } 695 | 696 | public function getCurrentPageContent() 697 | { 698 | return $this->currentPageContent; 699 | } 700 | 701 | public function getHTML() 702 | { 703 | return $this->currentHtml; 704 | } 705 | 706 | public function getLoadTime() 707 | { 708 | return $this->loadTime; 709 | } 710 | 711 | /** 712 | * @return array 713 | */ 714 | public function getHeaders() 715 | { 716 | return $this->headers; 717 | } 718 | 719 | /** 720 | * @return int 721 | */ 722 | public function getStatus() 723 | { 724 | return $this->status; 725 | } 726 | 727 | /** 728 | * @return string 729 | */ 730 | public function getStatusText() 731 | { 732 | return $this->statusText; 733 | } 734 | 735 | /** 736 | * @return array 737 | */ 738 | public function getCookies() 739 | { 740 | return $this->cookies; 741 | } 742 | } 743 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 5 | "This file is @generated automatically" 6 | ], 7 | "hash": "62f005ff756ddc1cf962dfdd3e282bb1", 8 | "content-hash": "8f1facac589ec41e82725f2bf9788419", 9 | "packages": [], 10 | "packages-dev": [ 11 | { 12 | "name": "doctrine/instantiator", 13 | "version": "1.0.5", 14 | "source": { 15 | "type": "git", 16 | "url": "https://github.com/doctrine/instantiator.git", 17 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" 18 | }, 19 | "dist": { 20 | "type": "zip", 21 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", 22 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", 23 | "shasum": "" 24 | }, 25 | "require": { 26 | "php": ">=5.3,<8.0-DEV" 27 | }, 28 | "require-dev": { 29 | "athletic/athletic": "~0.1.8", 30 | "ext-pdo": "*", 31 | "ext-phar": "*", 32 | "phpunit/phpunit": "~4.0", 33 | "squizlabs/php_codesniffer": "~2.0" 34 | }, 35 | "type": "library", 36 | "extra": { 37 | "branch-alias": { 38 | "dev-master": "1.0.x-dev" 39 | } 40 | }, 41 | "autoload": { 42 | "psr-4": { 43 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" 44 | } 45 | }, 46 | "notification-url": "https://packagist.org/downloads/", 47 | "license": [ 48 | "MIT" 49 | ], 50 | "authors": [ 51 | { 52 | "name": "Marco Pivetta", 53 | "email": "ocramius@gmail.com", 54 | "homepage": "http://ocramius.github.com/" 55 | } 56 | ], 57 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 58 | "homepage": "https://github.com/doctrine/instantiator", 59 | "keywords": [ 60 | "constructor", 61 | "instantiate" 62 | ], 63 | "time": "2015-06-14 21:17:01" 64 | }, 65 | { 66 | "name": "phpdocumentor/reflection-common", 67 | "version": "1.0", 68 | "source": { 69 | "type": "git", 70 | "url": "https://github.com/phpDocumentor/ReflectionCommon.git", 71 | "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c" 72 | }, 73 | "dist": { 74 | "type": "zip", 75 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c", 76 | "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c", 77 | "shasum": "" 78 | }, 79 | "require": { 80 | "php": ">=5.5" 81 | }, 82 | "require-dev": { 83 | "phpunit/phpunit": "^4.6" 84 | }, 85 | "type": "library", 86 | "extra": { 87 | "branch-alias": { 88 | "dev-master": "1.0.x-dev" 89 | } 90 | }, 91 | "autoload": { 92 | "psr-4": { 93 | "phpDocumentor\\Reflection\\": [ 94 | "src" 95 | ] 96 | } 97 | }, 98 | "notification-url": "https://packagist.org/downloads/", 99 | "license": [ 100 | "MIT" 101 | ], 102 | "authors": [ 103 | { 104 | "name": "Jaap van Otterdijk", 105 | "email": "opensource@ijaap.nl" 106 | } 107 | ], 108 | "description": "Common reflection classes used by phpdocumentor to reflect the code structure", 109 | "homepage": "http://www.phpdoc.org", 110 | "keywords": [ 111 | "FQSEN", 112 | "phpDocumentor", 113 | "phpdoc", 114 | "reflection", 115 | "static analysis" 116 | ], 117 | "time": "2015-12-27 11:43:31" 118 | }, 119 | { 120 | "name": "phpdocumentor/reflection-docblock", 121 | "version": "3.1.1", 122 | "source": { 123 | "type": "git", 124 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", 125 | "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e" 126 | }, 127 | "dist": { 128 | "type": "zip", 129 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/8331b5efe816ae05461b7ca1e721c01b46bafb3e", 130 | "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e", 131 | "shasum": "" 132 | }, 133 | "require": { 134 | "php": ">=5.5", 135 | "phpdocumentor/reflection-common": "^1.0@dev", 136 | "phpdocumentor/type-resolver": "^0.2.0", 137 | "webmozart/assert": "^1.0" 138 | }, 139 | "require-dev": { 140 | "mockery/mockery": "^0.9.4", 141 | "phpunit/phpunit": "^4.4" 142 | }, 143 | "type": "library", 144 | "autoload": { 145 | "psr-4": { 146 | "phpDocumentor\\Reflection\\": [ 147 | "src/" 148 | ] 149 | } 150 | }, 151 | "notification-url": "https://packagist.org/downloads/", 152 | "license": [ 153 | "MIT" 154 | ], 155 | "authors": [ 156 | { 157 | "name": "Mike van Riel", 158 | "email": "me@mikevanriel.com" 159 | } 160 | ], 161 | "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", 162 | "time": "2016-09-30 07:12:33" 163 | }, 164 | { 165 | "name": "phpdocumentor/type-resolver", 166 | "version": "0.2.1", 167 | "source": { 168 | "type": "git", 169 | "url": "https://github.com/phpDocumentor/TypeResolver.git", 170 | "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb" 171 | }, 172 | "dist": { 173 | "type": "zip", 174 | "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", 175 | "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", 176 | "shasum": "" 177 | }, 178 | "require": { 179 | "php": ">=5.5", 180 | "phpdocumentor/reflection-common": "^1.0" 181 | }, 182 | "require-dev": { 183 | "mockery/mockery": "^0.9.4", 184 | "phpunit/phpunit": "^5.2||^4.8.24" 185 | }, 186 | "type": "library", 187 | "extra": { 188 | "branch-alias": { 189 | "dev-master": "1.0.x-dev" 190 | } 191 | }, 192 | "autoload": { 193 | "psr-4": { 194 | "phpDocumentor\\Reflection\\": [ 195 | "src/" 196 | ] 197 | } 198 | }, 199 | "notification-url": "https://packagist.org/downloads/", 200 | "license": [ 201 | "MIT" 202 | ], 203 | "authors": [ 204 | { 205 | "name": "Mike van Riel", 206 | "email": "me@mikevanriel.com" 207 | } 208 | ], 209 | "time": "2016-11-25 06:54:22" 210 | }, 211 | { 212 | "name": "phpspec/prophecy", 213 | "version": "v1.6.2", 214 | "source": { 215 | "type": "git", 216 | "url": "https://github.com/phpspec/prophecy.git", 217 | "reference": "6c52c2722f8460122f96f86346600e1077ce22cb" 218 | }, 219 | "dist": { 220 | "type": "zip", 221 | "url": "https://api.github.com/repos/phpspec/prophecy/zipball/6c52c2722f8460122f96f86346600e1077ce22cb", 222 | "reference": "6c52c2722f8460122f96f86346600e1077ce22cb", 223 | "shasum": "" 224 | }, 225 | "require": { 226 | "doctrine/instantiator": "^1.0.2", 227 | "php": "^5.3|^7.0", 228 | "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", 229 | "sebastian/comparator": "^1.1", 230 | "sebastian/recursion-context": "^1.0|^2.0" 231 | }, 232 | "require-dev": { 233 | "phpspec/phpspec": "^2.0", 234 | "phpunit/phpunit": "^4.8 || ^5.6.5" 235 | }, 236 | "type": "library", 237 | "extra": { 238 | "branch-alias": { 239 | "dev-master": "1.6.x-dev" 240 | } 241 | }, 242 | "autoload": { 243 | "psr-0": { 244 | "Prophecy\\": "src/" 245 | } 246 | }, 247 | "notification-url": "https://packagist.org/downloads/", 248 | "license": [ 249 | "MIT" 250 | ], 251 | "authors": [ 252 | { 253 | "name": "Konstantin Kudryashov", 254 | "email": "ever.zet@gmail.com", 255 | "homepage": "http://everzet.com" 256 | }, 257 | { 258 | "name": "Marcello Duarte", 259 | "email": "marcello.duarte@gmail.com" 260 | } 261 | ], 262 | "description": "Highly opinionated mocking framework for PHP 5.3+", 263 | "homepage": "https://github.com/phpspec/prophecy", 264 | "keywords": [ 265 | "Double", 266 | "Dummy", 267 | "fake", 268 | "mock", 269 | "spy", 270 | "stub" 271 | ], 272 | "time": "2016-11-21 14:58:47" 273 | }, 274 | { 275 | "name": "phpunit/php-code-coverage", 276 | "version": "2.2.4", 277 | "source": { 278 | "type": "git", 279 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 280 | "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" 281 | }, 282 | "dist": { 283 | "type": "zip", 284 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", 285 | "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", 286 | "shasum": "" 287 | }, 288 | "require": { 289 | "php": ">=5.3.3", 290 | "phpunit/php-file-iterator": "~1.3", 291 | "phpunit/php-text-template": "~1.2", 292 | "phpunit/php-token-stream": "~1.3", 293 | "sebastian/environment": "^1.3.2", 294 | "sebastian/version": "~1.0" 295 | }, 296 | "require-dev": { 297 | "ext-xdebug": ">=2.1.4", 298 | "phpunit/phpunit": "~4" 299 | }, 300 | "suggest": { 301 | "ext-dom": "*", 302 | "ext-xdebug": ">=2.2.1", 303 | "ext-xmlwriter": "*" 304 | }, 305 | "type": "library", 306 | "extra": { 307 | "branch-alias": { 308 | "dev-master": "2.2.x-dev" 309 | } 310 | }, 311 | "autoload": { 312 | "classmap": [ 313 | "src/" 314 | ] 315 | }, 316 | "notification-url": "https://packagist.org/downloads/", 317 | "license": [ 318 | "BSD-3-Clause" 319 | ], 320 | "authors": [ 321 | { 322 | "name": "Sebastian Bergmann", 323 | "email": "sb@sebastian-bergmann.de", 324 | "role": "lead" 325 | } 326 | ], 327 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 328 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 329 | "keywords": [ 330 | "coverage", 331 | "testing", 332 | "xunit" 333 | ], 334 | "time": "2015-10-06 15:47:00" 335 | }, 336 | { 337 | "name": "phpunit/php-file-iterator", 338 | "version": "1.4.2", 339 | "source": { 340 | "type": "git", 341 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 342 | "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5" 343 | }, 344 | "dist": { 345 | "type": "zip", 346 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5", 347 | "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5", 348 | "shasum": "" 349 | }, 350 | "require": { 351 | "php": ">=5.3.3" 352 | }, 353 | "type": "library", 354 | "extra": { 355 | "branch-alias": { 356 | "dev-master": "1.4.x-dev" 357 | } 358 | }, 359 | "autoload": { 360 | "classmap": [ 361 | "src/" 362 | ] 363 | }, 364 | "notification-url": "https://packagist.org/downloads/", 365 | "license": [ 366 | "BSD-3-Clause" 367 | ], 368 | "authors": [ 369 | { 370 | "name": "Sebastian Bergmann", 371 | "email": "sb@sebastian-bergmann.de", 372 | "role": "lead" 373 | } 374 | ], 375 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 376 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 377 | "keywords": [ 378 | "filesystem", 379 | "iterator" 380 | ], 381 | "time": "2016-10-03 07:40:28" 382 | }, 383 | { 384 | "name": "phpunit/php-text-template", 385 | "version": "1.2.1", 386 | "source": { 387 | "type": "git", 388 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 389 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" 390 | }, 391 | "dist": { 392 | "type": "zip", 393 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 394 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 395 | "shasum": "" 396 | }, 397 | "require": { 398 | "php": ">=5.3.3" 399 | }, 400 | "type": "library", 401 | "autoload": { 402 | "classmap": [ 403 | "src/" 404 | ] 405 | }, 406 | "notification-url": "https://packagist.org/downloads/", 407 | "license": [ 408 | "BSD-3-Clause" 409 | ], 410 | "authors": [ 411 | { 412 | "name": "Sebastian Bergmann", 413 | "email": "sebastian@phpunit.de", 414 | "role": "lead" 415 | } 416 | ], 417 | "description": "Simple template engine.", 418 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 419 | "keywords": [ 420 | "template" 421 | ], 422 | "time": "2015-06-21 13:50:34" 423 | }, 424 | { 425 | "name": "phpunit/php-timer", 426 | "version": "1.0.8", 427 | "source": { 428 | "type": "git", 429 | "url": "https://github.com/sebastianbergmann/php-timer.git", 430 | "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260" 431 | }, 432 | "dist": { 433 | "type": "zip", 434 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260", 435 | "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260", 436 | "shasum": "" 437 | }, 438 | "require": { 439 | "php": ">=5.3.3" 440 | }, 441 | "require-dev": { 442 | "phpunit/phpunit": "~4|~5" 443 | }, 444 | "type": "library", 445 | "autoload": { 446 | "classmap": [ 447 | "src/" 448 | ] 449 | }, 450 | "notification-url": "https://packagist.org/downloads/", 451 | "license": [ 452 | "BSD-3-Clause" 453 | ], 454 | "authors": [ 455 | { 456 | "name": "Sebastian Bergmann", 457 | "email": "sb@sebastian-bergmann.de", 458 | "role": "lead" 459 | } 460 | ], 461 | "description": "Utility class for timing", 462 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 463 | "keywords": [ 464 | "timer" 465 | ], 466 | "time": "2016-05-12 18:03:57" 467 | }, 468 | { 469 | "name": "phpunit/php-token-stream", 470 | "version": "1.4.9", 471 | "source": { 472 | "type": "git", 473 | "url": "https://github.com/sebastianbergmann/php-token-stream.git", 474 | "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b" 475 | }, 476 | "dist": { 477 | "type": "zip", 478 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3b402f65a4cc90abf6e1104e388b896ce209631b", 479 | "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b", 480 | "shasum": "" 481 | }, 482 | "require": { 483 | "ext-tokenizer": "*", 484 | "php": ">=5.3.3" 485 | }, 486 | "require-dev": { 487 | "phpunit/phpunit": "~4.2" 488 | }, 489 | "type": "library", 490 | "extra": { 491 | "branch-alias": { 492 | "dev-master": "1.4-dev" 493 | } 494 | }, 495 | "autoload": { 496 | "classmap": [ 497 | "src/" 498 | ] 499 | }, 500 | "notification-url": "https://packagist.org/downloads/", 501 | "license": [ 502 | "BSD-3-Clause" 503 | ], 504 | "authors": [ 505 | { 506 | "name": "Sebastian Bergmann", 507 | "email": "sebastian@phpunit.de" 508 | } 509 | ], 510 | "description": "Wrapper around PHP's tokenizer extension.", 511 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/", 512 | "keywords": [ 513 | "tokenizer" 514 | ], 515 | "time": "2016-11-15 14:06:22" 516 | }, 517 | { 518 | "name": "phpunit/phpunit", 519 | "version": "4.8.35", 520 | "source": { 521 | "type": "git", 522 | "url": "https://github.com/sebastianbergmann/phpunit.git", 523 | "reference": "791b1a67c25af50e230f841ee7a9c6eba507dc87" 524 | }, 525 | "dist": { 526 | "type": "zip", 527 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/791b1a67c25af50e230f841ee7a9c6eba507dc87", 528 | "reference": "791b1a67c25af50e230f841ee7a9c6eba507dc87", 529 | "shasum": "" 530 | }, 531 | "require": { 532 | "ext-dom": "*", 533 | "ext-json": "*", 534 | "ext-pcre": "*", 535 | "ext-reflection": "*", 536 | "ext-spl": "*", 537 | "php": ">=5.3.3", 538 | "phpspec/prophecy": "^1.3.1", 539 | "phpunit/php-code-coverage": "~2.1", 540 | "phpunit/php-file-iterator": "~1.4", 541 | "phpunit/php-text-template": "~1.2", 542 | "phpunit/php-timer": "^1.0.6", 543 | "phpunit/phpunit-mock-objects": "~2.3", 544 | "sebastian/comparator": "~1.2.2", 545 | "sebastian/diff": "~1.2", 546 | "sebastian/environment": "~1.3", 547 | "sebastian/exporter": "~1.2", 548 | "sebastian/global-state": "~1.0", 549 | "sebastian/version": "~1.0", 550 | "symfony/yaml": "~2.1|~3.0" 551 | }, 552 | "suggest": { 553 | "phpunit/php-invoker": "~1.1" 554 | }, 555 | "bin": [ 556 | "phpunit" 557 | ], 558 | "type": "library", 559 | "extra": { 560 | "branch-alias": { 561 | "dev-master": "4.8.x-dev" 562 | } 563 | }, 564 | "autoload": { 565 | "classmap": [ 566 | "src/" 567 | ] 568 | }, 569 | "notification-url": "https://packagist.org/downloads/", 570 | "license": [ 571 | "BSD-3-Clause" 572 | ], 573 | "authors": [ 574 | { 575 | "name": "Sebastian Bergmann", 576 | "email": "sebastian@phpunit.de", 577 | "role": "lead" 578 | } 579 | ], 580 | "description": "The PHP Unit Testing framework.", 581 | "homepage": "https://phpunit.de/", 582 | "keywords": [ 583 | "phpunit", 584 | "testing", 585 | "xunit" 586 | ], 587 | "time": "2017-02-06 05:18:07" 588 | }, 589 | { 590 | "name": "phpunit/phpunit-mock-objects", 591 | "version": "2.3.8", 592 | "source": { 593 | "type": "git", 594 | "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", 595 | "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" 596 | }, 597 | "dist": { 598 | "type": "zip", 599 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", 600 | "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", 601 | "shasum": "" 602 | }, 603 | "require": { 604 | "doctrine/instantiator": "^1.0.2", 605 | "php": ">=5.3.3", 606 | "phpunit/php-text-template": "~1.2", 607 | "sebastian/exporter": "~1.2" 608 | }, 609 | "require-dev": { 610 | "phpunit/phpunit": "~4.4" 611 | }, 612 | "suggest": { 613 | "ext-soap": "*" 614 | }, 615 | "type": "library", 616 | "extra": { 617 | "branch-alias": { 618 | "dev-master": "2.3.x-dev" 619 | } 620 | }, 621 | "autoload": { 622 | "classmap": [ 623 | "src/" 624 | ] 625 | }, 626 | "notification-url": "https://packagist.org/downloads/", 627 | "license": [ 628 | "BSD-3-Clause" 629 | ], 630 | "authors": [ 631 | { 632 | "name": "Sebastian Bergmann", 633 | "email": "sb@sebastian-bergmann.de", 634 | "role": "lead" 635 | } 636 | ], 637 | "description": "Mock Object library for PHPUnit", 638 | "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", 639 | "keywords": [ 640 | "mock", 641 | "xunit" 642 | ], 643 | "time": "2015-10-02 06:51:40" 644 | }, 645 | { 646 | "name": "sebastian/comparator", 647 | "version": "1.2.4", 648 | "source": { 649 | "type": "git", 650 | "url": "https://github.com/sebastianbergmann/comparator.git", 651 | "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" 652 | }, 653 | "dist": { 654 | "type": "zip", 655 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", 656 | "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", 657 | "shasum": "" 658 | }, 659 | "require": { 660 | "php": ">=5.3.3", 661 | "sebastian/diff": "~1.2", 662 | "sebastian/exporter": "~1.2 || ~2.0" 663 | }, 664 | "require-dev": { 665 | "phpunit/phpunit": "~4.4" 666 | }, 667 | "type": "library", 668 | "extra": { 669 | "branch-alias": { 670 | "dev-master": "1.2.x-dev" 671 | } 672 | }, 673 | "autoload": { 674 | "classmap": [ 675 | "src/" 676 | ] 677 | }, 678 | "notification-url": "https://packagist.org/downloads/", 679 | "license": [ 680 | "BSD-3-Clause" 681 | ], 682 | "authors": [ 683 | { 684 | "name": "Jeff Welch", 685 | "email": "whatthejeff@gmail.com" 686 | }, 687 | { 688 | "name": "Volker Dusch", 689 | "email": "github@wallbash.com" 690 | }, 691 | { 692 | "name": "Bernhard Schussek", 693 | "email": "bschussek@2bepublished.at" 694 | }, 695 | { 696 | "name": "Sebastian Bergmann", 697 | "email": "sebastian@phpunit.de" 698 | } 699 | ], 700 | "description": "Provides the functionality to compare PHP values for equality", 701 | "homepage": "http://www.github.com/sebastianbergmann/comparator", 702 | "keywords": [ 703 | "comparator", 704 | "compare", 705 | "equality" 706 | ], 707 | "time": "2017-01-29 09:50:25" 708 | }, 709 | { 710 | "name": "sebastian/diff", 711 | "version": "1.4.1", 712 | "source": { 713 | "type": "git", 714 | "url": "https://github.com/sebastianbergmann/diff.git", 715 | "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" 716 | }, 717 | "dist": { 718 | "type": "zip", 719 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", 720 | "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", 721 | "shasum": "" 722 | }, 723 | "require": { 724 | "php": ">=5.3.3" 725 | }, 726 | "require-dev": { 727 | "phpunit/phpunit": "~4.8" 728 | }, 729 | "type": "library", 730 | "extra": { 731 | "branch-alias": { 732 | "dev-master": "1.4-dev" 733 | } 734 | }, 735 | "autoload": { 736 | "classmap": [ 737 | "src/" 738 | ] 739 | }, 740 | "notification-url": "https://packagist.org/downloads/", 741 | "license": [ 742 | "BSD-3-Clause" 743 | ], 744 | "authors": [ 745 | { 746 | "name": "Kore Nordmann", 747 | "email": "mail@kore-nordmann.de" 748 | }, 749 | { 750 | "name": "Sebastian Bergmann", 751 | "email": "sebastian@phpunit.de" 752 | } 753 | ], 754 | "description": "Diff implementation", 755 | "homepage": "https://github.com/sebastianbergmann/diff", 756 | "keywords": [ 757 | "diff" 758 | ], 759 | "time": "2015-12-08 07:14:41" 760 | }, 761 | { 762 | "name": "sebastian/environment", 763 | "version": "1.3.8", 764 | "source": { 765 | "type": "git", 766 | "url": "https://github.com/sebastianbergmann/environment.git", 767 | "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea" 768 | }, 769 | "dist": { 770 | "type": "zip", 771 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea", 772 | "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea", 773 | "shasum": "" 774 | }, 775 | "require": { 776 | "php": "^5.3.3 || ^7.0" 777 | }, 778 | "require-dev": { 779 | "phpunit/phpunit": "^4.8 || ^5.0" 780 | }, 781 | "type": "library", 782 | "extra": { 783 | "branch-alias": { 784 | "dev-master": "1.3.x-dev" 785 | } 786 | }, 787 | "autoload": { 788 | "classmap": [ 789 | "src/" 790 | ] 791 | }, 792 | "notification-url": "https://packagist.org/downloads/", 793 | "license": [ 794 | "BSD-3-Clause" 795 | ], 796 | "authors": [ 797 | { 798 | "name": "Sebastian Bergmann", 799 | "email": "sebastian@phpunit.de" 800 | } 801 | ], 802 | "description": "Provides functionality to handle HHVM/PHP environments", 803 | "homepage": "http://www.github.com/sebastianbergmann/environment", 804 | "keywords": [ 805 | "Xdebug", 806 | "environment", 807 | "hhvm" 808 | ], 809 | "time": "2016-08-18 05:49:44" 810 | }, 811 | { 812 | "name": "sebastian/exporter", 813 | "version": "1.2.2", 814 | "source": { 815 | "type": "git", 816 | "url": "https://github.com/sebastianbergmann/exporter.git", 817 | "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" 818 | }, 819 | "dist": { 820 | "type": "zip", 821 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", 822 | "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", 823 | "shasum": "" 824 | }, 825 | "require": { 826 | "php": ">=5.3.3", 827 | "sebastian/recursion-context": "~1.0" 828 | }, 829 | "require-dev": { 830 | "ext-mbstring": "*", 831 | "phpunit/phpunit": "~4.4" 832 | }, 833 | "type": "library", 834 | "extra": { 835 | "branch-alias": { 836 | "dev-master": "1.3.x-dev" 837 | } 838 | }, 839 | "autoload": { 840 | "classmap": [ 841 | "src/" 842 | ] 843 | }, 844 | "notification-url": "https://packagist.org/downloads/", 845 | "license": [ 846 | "BSD-3-Clause" 847 | ], 848 | "authors": [ 849 | { 850 | "name": "Jeff Welch", 851 | "email": "whatthejeff@gmail.com" 852 | }, 853 | { 854 | "name": "Volker Dusch", 855 | "email": "github@wallbash.com" 856 | }, 857 | { 858 | "name": "Bernhard Schussek", 859 | "email": "bschussek@2bepublished.at" 860 | }, 861 | { 862 | "name": "Sebastian Bergmann", 863 | "email": "sebastian@phpunit.de" 864 | }, 865 | { 866 | "name": "Adam Harvey", 867 | "email": "aharvey@php.net" 868 | } 869 | ], 870 | "description": "Provides the functionality to export PHP variables for visualization", 871 | "homepage": "http://www.github.com/sebastianbergmann/exporter", 872 | "keywords": [ 873 | "export", 874 | "exporter" 875 | ], 876 | "time": "2016-06-17 09:04:28" 877 | }, 878 | { 879 | "name": "sebastian/global-state", 880 | "version": "1.1.1", 881 | "source": { 882 | "type": "git", 883 | "url": "https://github.com/sebastianbergmann/global-state.git", 884 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" 885 | }, 886 | "dist": { 887 | "type": "zip", 888 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", 889 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", 890 | "shasum": "" 891 | }, 892 | "require": { 893 | "php": ">=5.3.3" 894 | }, 895 | "require-dev": { 896 | "phpunit/phpunit": "~4.2" 897 | }, 898 | "suggest": { 899 | "ext-uopz": "*" 900 | }, 901 | "type": "library", 902 | "extra": { 903 | "branch-alias": { 904 | "dev-master": "1.0-dev" 905 | } 906 | }, 907 | "autoload": { 908 | "classmap": [ 909 | "src/" 910 | ] 911 | }, 912 | "notification-url": "https://packagist.org/downloads/", 913 | "license": [ 914 | "BSD-3-Clause" 915 | ], 916 | "authors": [ 917 | { 918 | "name": "Sebastian Bergmann", 919 | "email": "sebastian@phpunit.de" 920 | } 921 | ], 922 | "description": "Snapshotting of global state", 923 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 924 | "keywords": [ 925 | "global state" 926 | ], 927 | "time": "2015-10-12 03:26:01" 928 | }, 929 | { 930 | "name": "sebastian/recursion-context", 931 | "version": "1.0.2", 932 | "source": { 933 | "type": "git", 934 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 935 | "reference": "913401df809e99e4f47b27cdd781f4a258d58791" 936 | }, 937 | "dist": { 938 | "type": "zip", 939 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791", 940 | "reference": "913401df809e99e4f47b27cdd781f4a258d58791", 941 | "shasum": "" 942 | }, 943 | "require": { 944 | "php": ">=5.3.3" 945 | }, 946 | "require-dev": { 947 | "phpunit/phpunit": "~4.4" 948 | }, 949 | "type": "library", 950 | "extra": { 951 | "branch-alias": { 952 | "dev-master": "1.0.x-dev" 953 | } 954 | }, 955 | "autoload": { 956 | "classmap": [ 957 | "src/" 958 | ] 959 | }, 960 | "notification-url": "https://packagist.org/downloads/", 961 | "license": [ 962 | "BSD-3-Clause" 963 | ], 964 | "authors": [ 965 | { 966 | "name": "Jeff Welch", 967 | "email": "whatthejeff@gmail.com" 968 | }, 969 | { 970 | "name": "Sebastian Bergmann", 971 | "email": "sebastian@phpunit.de" 972 | }, 973 | { 974 | "name": "Adam Harvey", 975 | "email": "aharvey@php.net" 976 | } 977 | ], 978 | "description": "Provides functionality to recursively process PHP variables", 979 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context", 980 | "time": "2015-11-11 19:50:13" 981 | }, 982 | { 983 | "name": "sebastian/version", 984 | "version": "1.0.6", 985 | "source": { 986 | "type": "git", 987 | "url": "https://github.com/sebastianbergmann/version.git", 988 | "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" 989 | }, 990 | "dist": { 991 | "type": "zip", 992 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", 993 | "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", 994 | "shasum": "" 995 | }, 996 | "type": "library", 997 | "autoload": { 998 | "classmap": [ 999 | "src/" 1000 | ] 1001 | }, 1002 | "notification-url": "https://packagist.org/downloads/", 1003 | "license": [ 1004 | "BSD-3-Clause" 1005 | ], 1006 | "authors": [ 1007 | { 1008 | "name": "Sebastian Bergmann", 1009 | "email": "sebastian@phpunit.de", 1010 | "role": "lead" 1011 | } 1012 | ], 1013 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 1014 | "homepage": "https://github.com/sebastianbergmann/version", 1015 | "time": "2015-06-21 13:59:46" 1016 | }, 1017 | { 1018 | "name": "squizlabs/php_codesniffer", 1019 | "version": "2.8.0", 1020 | "source": { 1021 | "type": "git", 1022 | "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", 1023 | "reference": "86dd55a522238211f9f3631e3361703578941d9a" 1024 | }, 1025 | "dist": { 1026 | "type": "zip", 1027 | "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/86dd55a522238211f9f3631e3361703578941d9a", 1028 | "reference": "86dd55a522238211f9f3631e3361703578941d9a", 1029 | "shasum": "" 1030 | }, 1031 | "require": { 1032 | "ext-simplexml": "*", 1033 | "ext-tokenizer": "*", 1034 | "ext-xmlwriter": "*", 1035 | "php": ">=5.1.2" 1036 | }, 1037 | "require-dev": { 1038 | "phpunit/phpunit": "~4.0" 1039 | }, 1040 | "bin": [ 1041 | "scripts/phpcs", 1042 | "scripts/phpcbf" 1043 | ], 1044 | "type": "library", 1045 | "extra": { 1046 | "branch-alias": { 1047 | "dev-master": "2.x-dev" 1048 | } 1049 | }, 1050 | "autoload": { 1051 | "classmap": [ 1052 | "CodeSniffer.php", 1053 | "CodeSniffer/CLI.php", 1054 | "CodeSniffer/Exception.php", 1055 | "CodeSniffer/File.php", 1056 | "CodeSniffer/Fixer.php", 1057 | "CodeSniffer/Report.php", 1058 | "CodeSniffer/Reporting.php", 1059 | "CodeSniffer/Sniff.php", 1060 | "CodeSniffer/Tokens.php", 1061 | "CodeSniffer/Reports/", 1062 | "CodeSniffer/Tokenizers/", 1063 | "CodeSniffer/DocGenerators/", 1064 | "CodeSniffer/Standards/AbstractPatternSniff.php", 1065 | "CodeSniffer/Standards/AbstractScopeSniff.php", 1066 | "CodeSniffer/Standards/AbstractVariableSniff.php", 1067 | "CodeSniffer/Standards/IncorrectPatternException.php", 1068 | "CodeSniffer/Standards/Generic/Sniffs/", 1069 | "CodeSniffer/Standards/MySource/Sniffs/", 1070 | "CodeSniffer/Standards/PEAR/Sniffs/", 1071 | "CodeSniffer/Standards/PSR1/Sniffs/", 1072 | "CodeSniffer/Standards/PSR2/Sniffs/", 1073 | "CodeSniffer/Standards/Squiz/Sniffs/", 1074 | "CodeSniffer/Standards/Zend/Sniffs/" 1075 | ] 1076 | }, 1077 | "notification-url": "https://packagist.org/downloads/", 1078 | "license": [ 1079 | "BSD-3-Clause" 1080 | ], 1081 | "authors": [ 1082 | { 1083 | "name": "Greg Sherwood", 1084 | "role": "lead" 1085 | } 1086 | ], 1087 | "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", 1088 | "homepage": "http://www.squizlabs.com/php-codesniffer", 1089 | "keywords": [ 1090 | "phpcs", 1091 | "standards" 1092 | ], 1093 | "time": "2017-02-02 03:30:00" 1094 | }, 1095 | { 1096 | "name": "symfony/yaml", 1097 | "version": "v3.2.4", 1098 | "source": { 1099 | "type": "git", 1100 | "url": "https://github.com/symfony/yaml.git", 1101 | "reference": "9724c684646fcb5387d579b4bfaa63ee0b0c64c8" 1102 | }, 1103 | "dist": { 1104 | "type": "zip", 1105 | "url": "https://api.github.com/repos/symfony/yaml/zipball/9724c684646fcb5387d579b4bfaa63ee0b0c64c8", 1106 | "reference": "9724c684646fcb5387d579b4bfaa63ee0b0c64c8", 1107 | "shasum": "" 1108 | }, 1109 | "require": { 1110 | "php": ">=5.5.9" 1111 | }, 1112 | "require-dev": { 1113 | "symfony/console": "~2.8|~3.0" 1114 | }, 1115 | "suggest": { 1116 | "symfony/console": "For validating YAML files using the lint command" 1117 | }, 1118 | "type": "library", 1119 | "extra": { 1120 | "branch-alias": { 1121 | "dev-master": "3.2-dev" 1122 | } 1123 | }, 1124 | "autoload": { 1125 | "psr-4": { 1126 | "Symfony\\Component\\Yaml\\": "" 1127 | }, 1128 | "exclude-from-classmap": [ 1129 | "/Tests/" 1130 | ] 1131 | }, 1132 | "notification-url": "https://packagist.org/downloads/", 1133 | "license": [ 1134 | "MIT" 1135 | ], 1136 | "authors": [ 1137 | { 1138 | "name": "Fabien Potencier", 1139 | "email": "fabien@symfony.com" 1140 | }, 1141 | { 1142 | "name": "Symfony Community", 1143 | "homepage": "https://symfony.com/contributors" 1144 | } 1145 | ], 1146 | "description": "Symfony Yaml Component", 1147 | "homepage": "https://symfony.com", 1148 | "time": "2017-02-16 22:46:52" 1149 | }, 1150 | { 1151 | "name": "webmozart/assert", 1152 | "version": "1.2.0", 1153 | "source": { 1154 | "type": "git", 1155 | "url": "https://github.com/webmozart/assert.git", 1156 | "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f" 1157 | }, 1158 | "dist": { 1159 | "type": "zip", 1160 | "url": "https://api.github.com/repos/webmozart/assert/zipball/2db61e59ff05fe5126d152bd0655c9ea113e550f", 1161 | "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f", 1162 | "shasum": "" 1163 | }, 1164 | "require": { 1165 | "php": "^5.3.3 || ^7.0" 1166 | }, 1167 | "require-dev": { 1168 | "phpunit/phpunit": "^4.6", 1169 | "sebastian/version": "^1.0.1" 1170 | }, 1171 | "type": "library", 1172 | "extra": { 1173 | "branch-alias": { 1174 | "dev-master": "1.3-dev" 1175 | } 1176 | }, 1177 | "autoload": { 1178 | "psr-4": { 1179 | "Webmozart\\Assert\\": "src/" 1180 | } 1181 | }, 1182 | "notification-url": "https://packagist.org/downloads/", 1183 | "license": [ 1184 | "MIT" 1185 | ], 1186 | "authors": [ 1187 | { 1188 | "name": "Bernhard Schussek", 1189 | "email": "bschussek@gmail.com" 1190 | } 1191 | ], 1192 | "description": "Assertions to validate method input/output with nice error messages.", 1193 | "keywords": [ 1194 | "assert", 1195 | "check", 1196 | "validate" 1197 | ], 1198 | "time": "2016-11-23 20:04:58" 1199 | } 1200 | ], 1201 | "aliases": [], 1202 | "minimum-stability": "stable", 1203 | "stability-flags": [], 1204 | "prefer-stable": false, 1205 | "prefer-lowest": false, 1206 | "platform": { 1207 | "php": ">=5.3.0" 1208 | }, 1209 | "platform-dev": [] 1210 | } 1211 | --------------------------------------------------------------------------------