├── 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 | []()
5 | []()
6 | [](https://packagist.org/packages/phpcasperjs/phpcasperjs)
7 | [](http://doge.mit-license.org)
8 |
9 | [](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 |
--------------------------------------------------------------------------------