├── .gitignore ├── .travis.yml ├── LICENSE.MD ├── README.MD ├── composer.json ├── composer.lock ├── examples ├── autoload.php ├── iterator.php ├── single_page.php └── single_page_with_id.php ├── phpunit.xml.dist ├── src └── Usabilla │ └── API │ ├── Client │ └── UsabillaClient.php │ ├── Description │ └── UsabillaDescription.php │ ├── EventSubscriber │ └── SignatureSubscriber.php │ └── Signature │ └── Signature.php └── tests └── Usabilla └── Tests └── API ├── Client └── UsabillaClientTest.php ├── Description └── UsabillaDescriptionTest.php ├── EventSubscriber └── SignatureSubscriberTest.php └── Signature └── SignatureTest.php /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | vendor/ 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - "5.6" 5 | 6 | before_script: 7 | - composer install --dev 8 | 9 | after_script: 10 | - vendor/bin/test-reporter --stdout > codeclimate.json 11 | - "curl -X POST -d @codeclimate.json -H 'Content-Type: application/json' -H 'User-Agent: Code Climate (PHP Test Reporter v0.1.1)' https://codeclimate.com/test_reports" 12 | 13 | addons: 14 | code_climate: 15 | repo_token: 3f6cdd21259a61b22c0c355e09d41d0ee2bb5568fa744071de89bf4df7d1a8e6 16 | -------------------------------------------------------------------------------- /LICENSE.MD: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Usabilla 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 | # Usabilla PHP Client 2 | 3 | [![Build Status](https://travis-ci.org/usabilla/api-php.svg?branch=master)](https://travis-ci.org/usabilla/api-php) [![Code Climate](https://codeclimate.com/github/usabilla/api-php/badges/gpa.svg)](https://codeclimate.com/github/usabilla/api-php) [![Test Coverage](https://codeclimate.com/github/usabilla/api-php/badges/coverage.svg)](https://codeclimate.com/github/usabilla/api-php) 4 | 5 | This package allows PHP developers to gain access to the Usabilla resources such as buttons, feedback items, campaigns and their results. This packages is heavily inspired by the [AWS PHP Client](https://github.com/aws/aws-sdk-php). 6 | 7 | ## Resources 8 | 9 | * [API Documentation](http://developers.usabilla.com) – For in-depth getting started and usage information. 10 | 11 | ## Features 12 | 13 | * Built for PHP 5.6+ and compliant with [PSR-4](http://www.php-fig.org/psr/psr-4/). 14 | * Built on [Guzzle Services](https://github.com/guzzle/guzzle-services). 15 | * Installable through Composer. 16 | 17 | ## Getting Started 18 | 1. Install Composer by following installation instructions on: https://getcomposer.org/download/ 19 | 2. [Request Usabilla API credentials](https://app.usabilla.com/member/account/settings#public_api). 20 | 3. Run `composer require usabilla/usabilla-api-php` on your project. 21 | 22 | ## Quick Example 23 | 24 | ### Request 5 feedback items belonging to a button. 25 | 26 | ```php 27 | 'BUTTON_ID', 'limit' => 5]; 38 | 39 | // Gets the command. 40 | $command = $client->getCommand('GetWebsiteFeedbackItems', $params); 41 | 42 | // Executes the command. 43 | $response = $client->execute($command); 44 | 45 | // Prints the received response. 46 | print_r($response); 47 | ``` 48 | 49 | ### Using Command Line 50 | 51 | You can use the command line to retrieve results from the API using scripts found in the [example folder](examples/): 52 | 53 | * Using single_page.php : 54 | `php single_page.php {command} {access-key} {secret-key}` 55 | 56 | * Using single_page_with_id.php : 57 | `php single_page_with_id.php {command} {id} {access-key} {secret-key}` 58 | 59 | ### More examples: 60 | 61 | * [Results iterator example](examples/iterator.php) 62 | * [Single results page example](examples/single_page.php) 63 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "usabilla/usabilla-api-php", 3 | "homepage": "https://www.usabilla.com", 4 | "type": "library", 5 | "license": "Apache-2.0", 6 | "require": { 7 | "php": ">=5.6", 8 | "guzzlehttp/guzzle-services": "0.5.*" 9 | }, 10 | "require-dev": { 11 | "phpunit/phpunit": "5.*", 12 | "codeclimate/php-test-reporter": "0.3.*" 13 | }, 14 | "autoload": { 15 | "psr-4": { 16 | "": "src/" 17 | } 18 | }, 19 | "autoload-dev": { 20 | "psr-4": { 21 | "": "tests/" 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /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": "c342eda1de0c90b9de8e534e1c845dd2", 8 | "content-hash": "781a58fc720c718844ff9b5c4f5d8290", 9 | "packages": [ 10 | { 11 | "name": "guzzlehttp/command", 12 | "version": "0.7.1", 13 | "source": { 14 | "type": "git", 15 | "url": "https://github.com/guzzle/command.git", 16 | "reference": "2e8286ff81f75f97b00f7dcc2f51e2efafb373bd" 17 | }, 18 | "dist": { 19 | "type": "zip", 20 | "url": "https://api.github.com/repos/guzzle/command/zipball/2e8286ff81f75f97b00f7dcc2f51e2efafb373bd", 21 | "reference": "2e8286ff81f75f97b00f7dcc2f51e2efafb373bd", 22 | "shasum": "" 23 | }, 24 | "require": { 25 | "guzzlehttp/guzzle": "~5.0", 26 | "php": ">=5.4.0" 27 | }, 28 | "require-dev": { 29 | "phpunit/phpunit": "~4.0" 30 | }, 31 | "type": "library", 32 | "extra": { 33 | "branch-alias": { 34 | "dev-master": "0.7-dev" 35 | } 36 | }, 37 | "autoload": { 38 | "psr-4": { 39 | "GuzzleHttp\\Command\\": "src/" 40 | } 41 | }, 42 | "notification-url": "https://packagist.org/downloads/", 43 | "license": [ 44 | "MIT" 45 | ], 46 | "authors": [ 47 | { 48 | "name": "Michael Dowling", 49 | "email": "mtdowling@gmail.com", 50 | "homepage": "https://github.com/mtdowling" 51 | } 52 | ], 53 | "description": "Provides the foundation for building command based web service clients", 54 | "time": "2015-01-14 18:54:57" 55 | }, 56 | { 57 | "name": "guzzlehttp/guzzle", 58 | "version": "5.3.1", 59 | "source": { 60 | "type": "git", 61 | "url": "https://github.com/guzzle/guzzle.git", 62 | "reference": "70f1fa53b71c4647bf2762c09068a95f77e12fb8" 63 | }, 64 | "dist": { 65 | "type": "zip", 66 | "url": "https://api.github.com/repos/guzzle/guzzle/zipball/70f1fa53b71c4647bf2762c09068a95f77e12fb8", 67 | "reference": "70f1fa53b71c4647bf2762c09068a95f77e12fb8", 68 | "shasum": "" 69 | }, 70 | "require": { 71 | "guzzlehttp/ringphp": "^1.1", 72 | "php": ">=5.4.0" 73 | }, 74 | "require-dev": { 75 | "ext-curl": "*", 76 | "phpunit/phpunit": "^4.0" 77 | }, 78 | "type": "library", 79 | "autoload": { 80 | "psr-4": { 81 | "GuzzleHttp\\": "src/" 82 | } 83 | }, 84 | "notification-url": "https://packagist.org/downloads/", 85 | "license": [ 86 | "MIT" 87 | ], 88 | "authors": [ 89 | { 90 | "name": "Michael Dowling", 91 | "email": "mtdowling@gmail.com", 92 | "homepage": "https://github.com/mtdowling" 93 | } 94 | ], 95 | "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients", 96 | "homepage": "http://guzzlephp.org/", 97 | "keywords": [ 98 | "client", 99 | "curl", 100 | "framework", 101 | "http", 102 | "http client", 103 | "rest", 104 | "web service" 105 | ], 106 | "time": "2016-07-15 19:28:39" 107 | }, 108 | { 109 | "name": "guzzlehttp/guzzle-services", 110 | "version": "0.5.0", 111 | "source": { 112 | "type": "git", 113 | "url": "https://github.com/guzzle/guzzle-services.git", 114 | "reference": "5402867628d266748db88f05c90ede54fd1d884c" 115 | }, 116 | "dist": { 117 | "type": "zip", 118 | "url": "https://api.github.com/repos/guzzle/guzzle-services/zipball/5402867628d266748db88f05c90ede54fd1d884c", 119 | "reference": "5402867628d266748db88f05c90ede54fd1d884c", 120 | "shasum": "" 121 | }, 122 | "require": { 123 | "guzzlehttp/command": "0.7.*", 124 | "php": ">=5.4.0" 125 | }, 126 | "require-dev": { 127 | "phpunit/phpunit": "~4.0" 128 | }, 129 | "type": "library", 130 | "extra": { 131 | "branch-alias": { 132 | "dev-master": "0.4-dev" 133 | } 134 | }, 135 | "autoload": { 136 | "psr-4": { 137 | "GuzzleHttp\\Command\\Guzzle\\": "src/" 138 | } 139 | }, 140 | "notification-url": "https://packagist.org/downloads/", 141 | "license": [ 142 | "MIT" 143 | ], 144 | "authors": [ 145 | { 146 | "name": "Michael Dowling", 147 | "email": "mtdowling@gmail.com", 148 | "homepage": "https://github.com/mtdowling" 149 | } 150 | ], 151 | "description": "Provides an implementation of the Guzzle Command library that uses Guzzle service descriptions to describe web services, serialize requests, and parse responses into easy to use model structures.", 152 | "time": "2014-12-23 19:13:18" 153 | }, 154 | { 155 | "name": "guzzlehttp/ringphp", 156 | "version": "1.1.0", 157 | "source": { 158 | "type": "git", 159 | "url": "https://github.com/guzzle/RingPHP.git", 160 | "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b" 161 | }, 162 | "dist": { 163 | "type": "zip", 164 | "url": "https://api.github.com/repos/guzzle/RingPHP/zipball/dbbb91d7f6c191e5e405e900e3102ac7f261bc0b", 165 | "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b", 166 | "shasum": "" 167 | }, 168 | "require": { 169 | "guzzlehttp/streams": "~3.0", 170 | "php": ">=5.4.0", 171 | "react/promise": "~2.0" 172 | }, 173 | "require-dev": { 174 | "ext-curl": "*", 175 | "phpunit/phpunit": "~4.0" 176 | }, 177 | "suggest": { 178 | "ext-curl": "Guzzle will use specific adapters if cURL is present" 179 | }, 180 | "type": "library", 181 | "extra": { 182 | "branch-alias": { 183 | "dev-master": "1.1-dev" 184 | } 185 | }, 186 | "autoload": { 187 | "psr-4": { 188 | "GuzzleHttp\\Ring\\": "src/" 189 | } 190 | }, 191 | "notification-url": "https://packagist.org/downloads/", 192 | "license": [ 193 | "MIT" 194 | ], 195 | "authors": [ 196 | { 197 | "name": "Michael Dowling", 198 | "email": "mtdowling@gmail.com", 199 | "homepage": "https://github.com/mtdowling" 200 | } 201 | ], 202 | "description": "Provides a simple API and specification that abstracts away the details of HTTP into a single PHP function.", 203 | "time": "2015-05-20 03:37:09" 204 | }, 205 | { 206 | "name": "guzzlehttp/streams", 207 | "version": "3.0.0", 208 | "source": { 209 | "type": "git", 210 | "url": "https://github.com/guzzle/streams.git", 211 | "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5" 212 | }, 213 | "dist": { 214 | "type": "zip", 215 | "url": "https://api.github.com/repos/guzzle/streams/zipball/47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5", 216 | "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5", 217 | "shasum": "" 218 | }, 219 | "require": { 220 | "php": ">=5.4.0" 221 | }, 222 | "require-dev": { 223 | "phpunit/phpunit": "~4.0" 224 | }, 225 | "type": "library", 226 | "extra": { 227 | "branch-alias": { 228 | "dev-master": "3.0-dev" 229 | } 230 | }, 231 | "autoload": { 232 | "psr-4": { 233 | "GuzzleHttp\\Stream\\": "src/" 234 | } 235 | }, 236 | "notification-url": "https://packagist.org/downloads/", 237 | "license": [ 238 | "MIT" 239 | ], 240 | "authors": [ 241 | { 242 | "name": "Michael Dowling", 243 | "email": "mtdowling@gmail.com", 244 | "homepage": "https://github.com/mtdowling" 245 | } 246 | ], 247 | "description": "Provides a simple abstraction over streams of data", 248 | "homepage": "http://guzzlephp.org/", 249 | "keywords": [ 250 | "Guzzle", 251 | "stream" 252 | ], 253 | "time": "2014-10-12 19:18:40" 254 | }, 255 | { 256 | "name": "react/promise", 257 | "version": "v2.4.1", 258 | "source": { 259 | "type": "git", 260 | "url": "https://github.com/reactphp/promise.git", 261 | "reference": "8025426794f1944de806618671d4fa476dc7626f" 262 | }, 263 | "dist": { 264 | "type": "zip", 265 | "url": "https://api.github.com/repos/reactphp/promise/zipball/8025426794f1944de806618671d4fa476dc7626f", 266 | "reference": "8025426794f1944de806618671d4fa476dc7626f", 267 | "shasum": "" 268 | }, 269 | "require": { 270 | "php": ">=5.4.0" 271 | }, 272 | "type": "library", 273 | "extra": { 274 | "branch-alias": { 275 | "dev-master": "2.0-dev" 276 | } 277 | }, 278 | "autoload": { 279 | "psr-4": { 280 | "React\\Promise\\": "src/" 281 | }, 282 | "files": [ 283 | "src/functions_include.php" 284 | ] 285 | }, 286 | "notification-url": "https://packagist.org/downloads/", 287 | "license": [ 288 | "MIT" 289 | ], 290 | "authors": [ 291 | { 292 | "name": "Jan Sorgalla", 293 | "email": "jsorgalla@gmail.com" 294 | } 295 | ], 296 | "description": "A lightweight implementation of CommonJS Promises/A for PHP", 297 | "time": "2016-05-03 17:50:52" 298 | } 299 | ], 300 | "packages-dev": [ 301 | { 302 | "name": "codeclimate/php-test-reporter", 303 | "version": "v0.3.2", 304 | "source": { 305 | "type": "git", 306 | "url": "https://github.com/codeclimate/php-test-reporter.git", 307 | "reference": "3a2d3ebdc1df5acf372458c15041af240a6fc016" 308 | }, 309 | "dist": { 310 | "type": "zip", 311 | "url": "https://api.github.com/repos/codeclimate/php-test-reporter/zipball/3a2d3ebdc1df5acf372458c15041af240a6fc016", 312 | "reference": "3a2d3ebdc1df5acf372458c15041af240a6fc016", 313 | "shasum": "" 314 | }, 315 | "require": { 316 | "ext-curl": "*", 317 | "php": ">=5.3", 318 | "satooshi/php-coveralls": "1.0.*", 319 | "symfony/console": ">=2.0" 320 | }, 321 | "require-dev": { 322 | "ext-xdebug": "*", 323 | "phpunit/phpunit": "3.7.*@stable" 324 | }, 325 | "bin": [ 326 | "composer/bin/test-reporter" 327 | ], 328 | "type": "library", 329 | "extra": { 330 | "branch-alias": { 331 | "dev-master": "0.3.x-dev" 332 | } 333 | }, 334 | "autoload": { 335 | "psr-0": { 336 | "CodeClimate\\Component": "src/", 337 | "CodeClimate\\Bundle": "src/" 338 | } 339 | }, 340 | "notification-url": "https://packagist.org/downloads/", 341 | "license": [ 342 | "MIT" 343 | ], 344 | "authors": [ 345 | { 346 | "name": "Code Climate", 347 | "email": "hello@codeclimate.com", 348 | "homepage": "https://codeclimate.com" 349 | } 350 | ], 351 | "description": "PHP client for reporting test coverage to Code Climate", 352 | "homepage": "https://github.com/codeclimate/php-test-reporter", 353 | "keywords": [ 354 | "codeclimate", 355 | "coverage" 356 | ], 357 | "time": "2016-04-19 16:54:33" 358 | }, 359 | { 360 | "name": "doctrine/instantiator", 361 | "version": "1.0.5", 362 | "source": { 363 | "type": "git", 364 | "url": "https://github.com/doctrine/instantiator.git", 365 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" 366 | }, 367 | "dist": { 368 | "type": "zip", 369 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", 370 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", 371 | "shasum": "" 372 | }, 373 | "require": { 374 | "php": ">=5.3,<8.0-DEV" 375 | }, 376 | "require-dev": { 377 | "athletic/athletic": "~0.1.8", 378 | "ext-pdo": "*", 379 | "ext-phar": "*", 380 | "phpunit/phpunit": "~4.0", 381 | "squizlabs/php_codesniffer": "~2.0" 382 | }, 383 | "type": "library", 384 | "extra": { 385 | "branch-alias": { 386 | "dev-master": "1.0.x-dev" 387 | } 388 | }, 389 | "autoload": { 390 | "psr-4": { 391 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" 392 | } 393 | }, 394 | "notification-url": "https://packagist.org/downloads/", 395 | "license": [ 396 | "MIT" 397 | ], 398 | "authors": [ 399 | { 400 | "name": "Marco Pivetta", 401 | "email": "ocramius@gmail.com", 402 | "homepage": "http://ocramius.github.com/" 403 | } 404 | ], 405 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 406 | "homepage": "https://github.com/doctrine/instantiator", 407 | "keywords": [ 408 | "constructor", 409 | "instantiate" 410 | ], 411 | "time": "2015-06-14 21:17:01" 412 | }, 413 | { 414 | "name": "guzzle/guzzle", 415 | "version": "v3.9.3", 416 | "source": { 417 | "type": "git", 418 | "url": "https://github.com/guzzle/guzzle3.git", 419 | "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9" 420 | }, 421 | "dist": { 422 | "type": "zip", 423 | "url": "https://api.github.com/repos/guzzle/guzzle3/zipball/0645b70d953bc1c067bbc8d5bc53194706b628d9", 424 | "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9", 425 | "shasum": "" 426 | }, 427 | "require": { 428 | "ext-curl": "*", 429 | "php": ">=5.3.3", 430 | "symfony/event-dispatcher": "~2.1" 431 | }, 432 | "replace": { 433 | "guzzle/batch": "self.version", 434 | "guzzle/cache": "self.version", 435 | "guzzle/common": "self.version", 436 | "guzzle/http": "self.version", 437 | "guzzle/inflection": "self.version", 438 | "guzzle/iterator": "self.version", 439 | "guzzle/log": "self.version", 440 | "guzzle/parser": "self.version", 441 | "guzzle/plugin": "self.version", 442 | "guzzle/plugin-async": "self.version", 443 | "guzzle/plugin-backoff": "self.version", 444 | "guzzle/plugin-cache": "self.version", 445 | "guzzle/plugin-cookie": "self.version", 446 | "guzzle/plugin-curlauth": "self.version", 447 | "guzzle/plugin-error-response": "self.version", 448 | "guzzle/plugin-history": "self.version", 449 | "guzzle/plugin-log": "self.version", 450 | "guzzle/plugin-md5": "self.version", 451 | "guzzle/plugin-mock": "self.version", 452 | "guzzle/plugin-oauth": "self.version", 453 | "guzzle/service": "self.version", 454 | "guzzle/stream": "self.version" 455 | }, 456 | "require-dev": { 457 | "doctrine/cache": "~1.3", 458 | "monolog/monolog": "~1.0", 459 | "phpunit/phpunit": "3.7.*", 460 | "psr/log": "~1.0", 461 | "symfony/class-loader": "~2.1", 462 | "zendframework/zend-cache": "2.*,<2.3", 463 | "zendframework/zend-log": "2.*,<2.3" 464 | }, 465 | "suggest": { 466 | "guzzlehttp/guzzle": "Guzzle 5 has moved to a new package name. The package you have installed, Guzzle 3, is deprecated." 467 | }, 468 | "type": "library", 469 | "extra": { 470 | "branch-alias": { 471 | "dev-master": "3.9-dev" 472 | } 473 | }, 474 | "autoload": { 475 | "psr-0": { 476 | "Guzzle": "src/", 477 | "Guzzle\\Tests": "tests/" 478 | } 479 | }, 480 | "notification-url": "https://packagist.org/downloads/", 481 | "license": [ 482 | "MIT" 483 | ], 484 | "authors": [ 485 | { 486 | "name": "Michael Dowling", 487 | "email": "mtdowling@gmail.com", 488 | "homepage": "https://github.com/mtdowling" 489 | }, 490 | { 491 | "name": "Guzzle Community", 492 | "homepage": "https://github.com/guzzle/guzzle/contributors" 493 | } 494 | ], 495 | "description": "PHP HTTP client. This library is deprecated in favor of https://packagist.org/packages/guzzlehttp/guzzle", 496 | "homepage": "http://guzzlephp.org/", 497 | "keywords": [ 498 | "client", 499 | "curl", 500 | "framework", 501 | "http", 502 | "http client", 503 | "rest", 504 | "web service" 505 | ], 506 | "time": "2015-03-18 18:23:50" 507 | }, 508 | { 509 | "name": "myclabs/deep-copy", 510 | "version": "1.5.5", 511 | "source": { 512 | "type": "git", 513 | "url": "https://github.com/myclabs/DeepCopy.git", 514 | "reference": "399c1f9781e222f6eb6cc238796f5200d1b7f108" 515 | }, 516 | "dist": { 517 | "type": "zip", 518 | "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/399c1f9781e222f6eb6cc238796f5200d1b7f108", 519 | "reference": "399c1f9781e222f6eb6cc238796f5200d1b7f108", 520 | "shasum": "" 521 | }, 522 | "require": { 523 | "php": ">=5.4.0" 524 | }, 525 | "require-dev": { 526 | "doctrine/collections": "1.*", 527 | "phpunit/phpunit": "~4.1" 528 | }, 529 | "type": "library", 530 | "autoload": { 531 | "psr-4": { 532 | "DeepCopy\\": "src/DeepCopy/" 533 | } 534 | }, 535 | "notification-url": "https://packagist.org/downloads/", 536 | "license": [ 537 | "MIT" 538 | ], 539 | "description": "Create deep copies (clones) of your objects", 540 | "homepage": "https://github.com/myclabs/DeepCopy", 541 | "keywords": [ 542 | "clone", 543 | "copy", 544 | "duplicate", 545 | "object", 546 | "object graph" 547 | ], 548 | "time": "2016-10-31 17:19:45" 549 | }, 550 | { 551 | "name": "phpdocumentor/reflection-common", 552 | "version": "1.0", 553 | "source": { 554 | "type": "git", 555 | "url": "https://github.com/phpDocumentor/ReflectionCommon.git", 556 | "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c" 557 | }, 558 | "dist": { 559 | "type": "zip", 560 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c", 561 | "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c", 562 | "shasum": "" 563 | }, 564 | "require": { 565 | "php": ">=5.5" 566 | }, 567 | "require-dev": { 568 | "phpunit/phpunit": "^4.6" 569 | }, 570 | "type": "library", 571 | "extra": { 572 | "branch-alias": { 573 | "dev-master": "1.0.x-dev" 574 | } 575 | }, 576 | "autoload": { 577 | "psr-4": { 578 | "phpDocumentor\\Reflection\\": [ 579 | "src" 580 | ] 581 | } 582 | }, 583 | "notification-url": "https://packagist.org/downloads/", 584 | "license": [ 585 | "MIT" 586 | ], 587 | "authors": [ 588 | { 589 | "name": "Jaap van Otterdijk", 590 | "email": "opensource@ijaap.nl" 591 | } 592 | ], 593 | "description": "Common reflection classes used by phpdocumentor to reflect the code structure", 594 | "homepage": "http://www.phpdoc.org", 595 | "keywords": [ 596 | "FQSEN", 597 | "phpDocumentor", 598 | "phpdoc", 599 | "reflection", 600 | "static analysis" 601 | ], 602 | "time": "2015-12-27 11:43:31" 603 | }, 604 | { 605 | "name": "phpdocumentor/reflection-docblock", 606 | "version": "3.1.1", 607 | "source": { 608 | "type": "git", 609 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", 610 | "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e" 611 | }, 612 | "dist": { 613 | "type": "zip", 614 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/8331b5efe816ae05461b7ca1e721c01b46bafb3e", 615 | "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e", 616 | "shasum": "" 617 | }, 618 | "require": { 619 | "php": ">=5.5", 620 | "phpdocumentor/reflection-common": "^1.0@dev", 621 | "phpdocumentor/type-resolver": "^0.2.0", 622 | "webmozart/assert": "^1.0" 623 | }, 624 | "require-dev": { 625 | "mockery/mockery": "^0.9.4", 626 | "phpunit/phpunit": "^4.4" 627 | }, 628 | "type": "library", 629 | "autoload": { 630 | "psr-4": { 631 | "phpDocumentor\\Reflection\\": [ 632 | "src/" 633 | ] 634 | } 635 | }, 636 | "notification-url": "https://packagist.org/downloads/", 637 | "license": [ 638 | "MIT" 639 | ], 640 | "authors": [ 641 | { 642 | "name": "Mike van Riel", 643 | "email": "me@mikevanriel.com" 644 | } 645 | ], 646 | "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", 647 | "time": "2016-09-30 07:12:33" 648 | }, 649 | { 650 | "name": "phpdocumentor/type-resolver", 651 | "version": "0.2.1", 652 | "source": { 653 | "type": "git", 654 | "url": "https://github.com/phpDocumentor/TypeResolver.git", 655 | "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb" 656 | }, 657 | "dist": { 658 | "type": "zip", 659 | "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", 660 | "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", 661 | "shasum": "" 662 | }, 663 | "require": { 664 | "php": ">=5.5", 665 | "phpdocumentor/reflection-common": "^1.0" 666 | }, 667 | "require-dev": { 668 | "mockery/mockery": "^0.9.4", 669 | "phpunit/phpunit": "^5.2||^4.8.24" 670 | }, 671 | "type": "library", 672 | "extra": { 673 | "branch-alias": { 674 | "dev-master": "1.0.x-dev" 675 | } 676 | }, 677 | "autoload": { 678 | "psr-4": { 679 | "phpDocumentor\\Reflection\\": [ 680 | "src/" 681 | ] 682 | } 683 | }, 684 | "notification-url": "https://packagist.org/downloads/", 685 | "license": [ 686 | "MIT" 687 | ], 688 | "authors": [ 689 | { 690 | "name": "Mike van Riel", 691 | "email": "me@mikevanriel.com" 692 | } 693 | ], 694 | "time": "2016-11-25 06:54:22" 695 | }, 696 | { 697 | "name": "phpspec/prophecy", 698 | "version": "v1.6.2", 699 | "source": { 700 | "type": "git", 701 | "url": "https://github.com/phpspec/prophecy.git", 702 | "reference": "6c52c2722f8460122f96f86346600e1077ce22cb" 703 | }, 704 | "dist": { 705 | "type": "zip", 706 | "url": "https://api.github.com/repos/phpspec/prophecy/zipball/6c52c2722f8460122f96f86346600e1077ce22cb", 707 | "reference": "6c52c2722f8460122f96f86346600e1077ce22cb", 708 | "shasum": "" 709 | }, 710 | "require": { 711 | "doctrine/instantiator": "^1.0.2", 712 | "php": "^5.3|^7.0", 713 | "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", 714 | "sebastian/comparator": "^1.1", 715 | "sebastian/recursion-context": "^1.0|^2.0" 716 | }, 717 | "require-dev": { 718 | "phpspec/phpspec": "^2.0", 719 | "phpunit/phpunit": "^4.8 || ^5.6.5" 720 | }, 721 | "type": "library", 722 | "extra": { 723 | "branch-alias": { 724 | "dev-master": "1.6.x-dev" 725 | } 726 | }, 727 | "autoload": { 728 | "psr-0": { 729 | "Prophecy\\": "src/" 730 | } 731 | }, 732 | "notification-url": "https://packagist.org/downloads/", 733 | "license": [ 734 | "MIT" 735 | ], 736 | "authors": [ 737 | { 738 | "name": "Konstantin Kudryashov", 739 | "email": "ever.zet@gmail.com", 740 | "homepage": "http://everzet.com" 741 | }, 742 | { 743 | "name": "Marcello Duarte", 744 | "email": "marcello.duarte@gmail.com" 745 | } 746 | ], 747 | "description": "Highly opinionated mocking framework for PHP 5.3+", 748 | "homepage": "https://github.com/phpspec/prophecy", 749 | "keywords": [ 750 | "Double", 751 | "Dummy", 752 | "fake", 753 | "mock", 754 | "spy", 755 | "stub" 756 | ], 757 | "time": "2016-11-21 14:58:47" 758 | }, 759 | { 760 | "name": "phpunit/php-code-coverage", 761 | "version": "4.0.3", 762 | "source": { 763 | "type": "git", 764 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 765 | "reference": "903fd6318d0a90b4770a009ff73e4a4e9c437929" 766 | }, 767 | "dist": { 768 | "type": "zip", 769 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/903fd6318d0a90b4770a009ff73e4a4e9c437929", 770 | "reference": "903fd6318d0a90b4770a009ff73e4a4e9c437929", 771 | "shasum": "" 772 | }, 773 | "require": { 774 | "php": "^5.6 || ^7.0", 775 | "phpunit/php-file-iterator": "~1.3", 776 | "phpunit/php-text-template": "~1.2", 777 | "phpunit/php-token-stream": "^1.4.2", 778 | "sebastian/code-unit-reverse-lookup": "~1.0", 779 | "sebastian/environment": "^1.3.2 || ^2.0", 780 | "sebastian/version": "~1.0|~2.0" 781 | }, 782 | "require-dev": { 783 | "ext-xdebug": ">=2.1.4", 784 | "phpunit/phpunit": "^5.4" 785 | }, 786 | "suggest": { 787 | "ext-dom": "*", 788 | "ext-xdebug": ">=2.4.0", 789 | "ext-xmlwriter": "*" 790 | }, 791 | "type": "library", 792 | "extra": { 793 | "branch-alias": { 794 | "dev-master": "4.0.x-dev" 795 | } 796 | }, 797 | "autoload": { 798 | "classmap": [ 799 | "src/" 800 | ] 801 | }, 802 | "notification-url": "https://packagist.org/downloads/", 803 | "license": [ 804 | "BSD-3-Clause" 805 | ], 806 | "authors": [ 807 | { 808 | "name": "Sebastian Bergmann", 809 | "email": "sb@sebastian-bergmann.de", 810 | "role": "lead" 811 | } 812 | ], 813 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 814 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 815 | "keywords": [ 816 | "coverage", 817 | "testing", 818 | "xunit" 819 | ], 820 | "time": "2016-11-28 16:00:31" 821 | }, 822 | { 823 | "name": "phpunit/php-file-iterator", 824 | "version": "1.4.2", 825 | "source": { 826 | "type": "git", 827 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 828 | "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5" 829 | }, 830 | "dist": { 831 | "type": "zip", 832 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5", 833 | "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5", 834 | "shasum": "" 835 | }, 836 | "require": { 837 | "php": ">=5.3.3" 838 | }, 839 | "type": "library", 840 | "extra": { 841 | "branch-alias": { 842 | "dev-master": "1.4.x-dev" 843 | } 844 | }, 845 | "autoload": { 846 | "classmap": [ 847 | "src/" 848 | ] 849 | }, 850 | "notification-url": "https://packagist.org/downloads/", 851 | "license": [ 852 | "BSD-3-Clause" 853 | ], 854 | "authors": [ 855 | { 856 | "name": "Sebastian Bergmann", 857 | "email": "sb@sebastian-bergmann.de", 858 | "role": "lead" 859 | } 860 | ], 861 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 862 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 863 | "keywords": [ 864 | "filesystem", 865 | "iterator" 866 | ], 867 | "time": "2016-10-03 07:40:28" 868 | }, 869 | { 870 | "name": "phpunit/php-text-template", 871 | "version": "1.2.1", 872 | "source": { 873 | "type": "git", 874 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 875 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" 876 | }, 877 | "dist": { 878 | "type": "zip", 879 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 880 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 881 | "shasum": "" 882 | }, 883 | "require": { 884 | "php": ">=5.3.3" 885 | }, 886 | "type": "library", 887 | "autoload": { 888 | "classmap": [ 889 | "src/" 890 | ] 891 | }, 892 | "notification-url": "https://packagist.org/downloads/", 893 | "license": [ 894 | "BSD-3-Clause" 895 | ], 896 | "authors": [ 897 | { 898 | "name": "Sebastian Bergmann", 899 | "email": "sebastian@phpunit.de", 900 | "role": "lead" 901 | } 902 | ], 903 | "description": "Simple template engine.", 904 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 905 | "keywords": [ 906 | "template" 907 | ], 908 | "time": "2015-06-21 13:50:34" 909 | }, 910 | { 911 | "name": "phpunit/php-timer", 912 | "version": "1.0.8", 913 | "source": { 914 | "type": "git", 915 | "url": "https://github.com/sebastianbergmann/php-timer.git", 916 | "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260" 917 | }, 918 | "dist": { 919 | "type": "zip", 920 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260", 921 | "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260", 922 | "shasum": "" 923 | }, 924 | "require": { 925 | "php": ">=5.3.3" 926 | }, 927 | "require-dev": { 928 | "phpunit/phpunit": "~4|~5" 929 | }, 930 | "type": "library", 931 | "autoload": { 932 | "classmap": [ 933 | "src/" 934 | ] 935 | }, 936 | "notification-url": "https://packagist.org/downloads/", 937 | "license": [ 938 | "BSD-3-Clause" 939 | ], 940 | "authors": [ 941 | { 942 | "name": "Sebastian Bergmann", 943 | "email": "sb@sebastian-bergmann.de", 944 | "role": "lead" 945 | } 946 | ], 947 | "description": "Utility class for timing", 948 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 949 | "keywords": [ 950 | "timer" 951 | ], 952 | "time": "2016-05-12 18:03:57" 953 | }, 954 | { 955 | "name": "phpunit/php-token-stream", 956 | "version": "1.4.9", 957 | "source": { 958 | "type": "git", 959 | "url": "https://github.com/sebastianbergmann/php-token-stream.git", 960 | "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b" 961 | }, 962 | "dist": { 963 | "type": "zip", 964 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3b402f65a4cc90abf6e1104e388b896ce209631b", 965 | "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b", 966 | "shasum": "" 967 | }, 968 | "require": { 969 | "ext-tokenizer": "*", 970 | "php": ">=5.3.3" 971 | }, 972 | "require-dev": { 973 | "phpunit/phpunit": "~4.2" 974 | }, 975 | "type": "library", 976 | "extra": { 977 | "branch-alias": { 978 | "dev-master": "1.4-dev" 979 | } 980 | }, 981 | "autoload": { 982 | "classmap": [ 983 | "src/" 984 | ] 985 | }, 986 | "notification-url": "https://packagist.org/downloads/", 987 | "license": [ 988 | "BSD-3-Clause" 989 | ], 990 | "authors": [ 991 | { 992 | "name": "Sebastian Bergmann", 993 | "email": "sebastian@phpunit.de" 994 | } 995 | ], 996 | "description": "Wrapper around PHP's tokenizer extension.", 997 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/", 998 | "keywords": [ 999 | "tokenizer" 1000 | ], 1001 | "time": "2016-11-15 14:06:22" 1002 | }, 1003 | { 1004 | "name": "phpunit/phpunit", 1005 | "version": "5.7.0", 1006 | "source": { 1007 | "type": "git", 1008 | "url": "https://github.com/sebastianbergmann/phpunit.git", 1009 | "reference": "00d72b8dbd2bb7d6f02a820e6db5cb70df6ac55c" 1010 | }, 1011 | "dist": { 1012 | "type": "zip", 1013 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/00d72b8dbd2bb7d6f02a820e6db5cb70df6ac55c", 1014 | "reference": "00d72b8dbd2bb7d6f02a820e6db5cb70df6ac55c", 1015 | "shasum": "" 1016 | }, 1017 | "require": { 1018 | "ext-dom": "*", 1019 | "ext-json": "*", 1020 | "ext-libxml": "*", 1021 | "ext-mbstring": "*", 1022 | "ext-xml": "*", 1023 | "myclabs/deep-copy": "~1.3", 1024 | "php": "^5.6 || ^7.0", 1025 | "phpspec/prophecy": "^1.3.1", 1026 | "phpunit/php-code-coverage": "^4.0.3", 1027 | "phpunit/php-file-iterator": "~1.4", 1028 | "phpunit/php-text-template": "~1.2", 1029 | "phpunit/php-timer": "^1.0.6", 1030 | "phpunit/phpunit-mock-objects": "^3.2", 1031 | "sebastian/comparator": "~1.2.2", 1032 | "sebastian/diff": "~1.2", 1033 | "sebastian/environment": "^1.3.4 || ^2.0", 1034 | "sebastian/exporter": "~2.0", 1035 | "sebastian/global-state": "~1.0", 1036 | "sebastian/object-enumerator": "~2.0", 1037 | "sebastian/resource-operations": "~1.0", 1038 | "sebastian/version": "~1.0|~2.0", 1039 | "symfony/yaml": "~2.1|~3.0" 1040 | }, 1041 | "conflict": { 1042 | "phpdocumentor/reflection-docblock": "3.0.2" 1043 | }, 1044 | "require-dev": { 1045 | "ext-pdo": "*" 1046 | }, 1047 | "suggest": { 1048 | "ext-xdebug": "*", 1049 | "phpunit/php-invoker": "~1.1" 1050 | }, 1051 | "bin": [ 1052 | "phpunit" 1053 | ], 1054 | "type": "library", 1055 | "extra": { 1056 | "branch-alias": { 1057 | "dev-master": "5.7.x-dev" 1058 | } 1059 | }, 1060 | "autoload": { 1061 | "classmap": [ 1062 | "src/" 1063 | ] 1064 | }, 1065 | "notification-url": "https://packagist.org/downloads/", 1066 | "license": [ 1067 | "BSD-3-Clause" 1068 | ], 1069 | "authors": [ 1070 | { 1071 | "name": "Sebastian Bergmann", 1072 | "email": "sebastian@phpunit.de", 1073 | "role": "lead" 1074 | } 1075 | ], 1076 | "description": "The PHP Unit Testing framework.", 1077 | "homepage": "https://phpunit.de/", 1078 | "keywords": [ 1079 | "phpunit", 1080 | "testing", 1081 | "xunit" 1082 | ], 1083 | "time": "2016-12-01 17:04:00" 1084 | }, 1085 | { 1086 | "name": "phpunit/phpunit-mock-objects", 1087 | "version": "3.4.2", 1088 | "source": { 1089 | "type": "git", 1090 | "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", 1091 | "reference": "90a08f5deed5f7ac35463c161f2e8fa0e5652faf" 1092 | }, 1093 | "dist": { 1094 | "type": "zip", 1095 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/90a08f5deed5f7ac35463c161f2e8fa0e5652faf", 1096 | "reference": "90a08f5deed5f7ac35463c161f2e8fa0e5652faf", 1097 | "shasum": "" 1098 | }, 1099 | "require": { 1100 | "doctrine/instantiator": "^1.0.2", 1101 | "php": "^5.6 || ^7.0", 1102 | "phpunit/php-text-template": "^1.2", 1103 | "sebastian/exporter": "^1.2 || ^2.0" 1104 | }, 1105 | "conflict": { 1106 | "phpunit/phpunit": "<5.4.0" 1107 | }, 1108 | "require-dev": { 1109 | "phpunit/phpunit": "^5.4" 1110 | }, 1111 | "suggest": { 1112 | "ext-soap": "*" 1113 | }, 1114 | "type": "library", 1115 | "extra": { 1116 | "branch-alias": { 1117 | "dev-master": "3.2.x-dev" 1118 | } 1119 | }, 1120 | "autoload": { 1121 | "classmap": [ 1122 | "src/" 1123 | ] 1124 | }, 1125 | "notification-url": "https://packagist.org/downloads/", 1126 | "license": [ 1127 | "BSD-3-Clause" 1128 | ], 1129 | "authors": [ 1130 | { 1131 | "name": "Sebastian Bergmann", 1132 | "email": "sb@sebastian-bergmann.de", 1133 | "role": "lead" 1134 | } 1135 | ], 1136 | "description": "Mock Object library for PHPUnit", 1137 | "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", 1138 | "keywords": [ 1139 | "mock", 1140 | "xunit" 1141 | ], 1142 | "time": "2016-11-27 07:52:03" 1143 | }, 1144 | { 1145 | "name": "psr/log", 1146 | "version": "1.0.2", 1147 | "source": { 1148 | "type": "git", 1149 | "url": "https://github.com/php-fig/log.git", 1150 | "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" 1151 | }, 1152 | "dist": { 1153 | "type": "zip", 1154 | "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", 1155 | "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", 1156 | "shasum": "" 1157 | }, 1158 | "require": { 1159 | "php": ">=5.3.0" 1160 | }, 1161 | "type": "library", 1162 | "extra": { 1163 | "branch-alias": { 1164 | "dev-master": "1.0.x-dev" 1165 | } 1166 | }, 1167 | "autoload": { 1168 | "psr-4": { 1169 | "Psr\\Log\\": "Psr/Log/" 1170 | } 1171 | }, 1172 | "notification-url": "https://packagist.org/downloads/", 1173 | "license": [ 1174 | "MIT" 1175 | ], 1176 | "authors": [ 1177 | { 1178 | "name": "PHP-FIG", 1179 | "homepage": "http://www.php-fig.org/" 1180 | } 1181 | ], 1182 | "description": "Common interface for logging libraries", 1183 | "homepage": "https://github.com/php-fig/log", 1184 | "keywords": [ 1185 | "log", 1186 | "psr", 1187 | "psr-3" 1188 | ], 1189 | "time": "2016-10-10 12:19:37" 1190 | }, 1191 | { 1192 | "name": "satooshi/php-coveralls", 1193 | "version": "v1.0.1", 1194 | "source": { 1195 | "type": "git", 1196 | "url": "https://github.com/satooshi/php-coveralls.git", 1197 | "reference": "da51d304fe8622bf9a6da39a8446e7afd432115c" 1198 | }, 1199 | "dist": { 1200 | "type": "zip", 1201 | "url": "https://api.github.com/repos/satooshi/php-coveralls/zipball/da51d304fe8622bf9a6da39a8446e7afd432115c", 1202 | "reference": "da51d304fe8622bf9a6da39a8446e7afd432115c", 1203 | "shasum": "" 1204 | }, 1205 | "require": { 1206 | "ext-json": "*", 1207 | "ext-simplexml": "*", 1208 | "guzzle/guzzle": "^2.8|^3.0", 1209 | "php": ">=5.3.3", 1210 | "psr/log": "^1.0", 1211 | "symfony/config": "^2.1|^3.0", 1212 | "symfony/console": "^2.1|^3.0", 1213 | "symfony/stopwatch": "^2.0|^3.0", 1214 | "symfony/yaml": "^2.0|^3.0" 1215 | }, 1216 | "suggest": { 1217 | "symfony/http-kernel": "Allows Symfony integration" 1218 | }, 1219 | "bin": [ 1220 | "bin/coveralls" 1221 | ], 1222 | "type": "library", 1223 | "autoload": { 1224 | "psr-4": { 1225 | "Satooshi\\": "src/Satooshi/" 1226 | } 1227 | }, 1228 | "notification-url": "https://packagist.org/downloads/", 1229 | "license": [ 1230 | "MIT" 1231 | ], 1232 | "authors": [ 1233 | { 1234 | "name": "Kitamura Satoshi", 1235 | "email": "with.no.parachute@gmail.com", 1236 | "homepage": "https://www.facebook.com/satooshi.jp" 1237 | } 1238 | ], 1239 | "description": "PHP client library for Coveralls API", 1240 | "homepage": "https://github.com/satooshi/php-coveralls", 1241 | "keywords": [ 1242 | "ci", 1243 | "coverage", 1244 | "github", 1245 | "test" 1246 | ], 1247 | "time": "2016-01-20 17:35:46" 1248 | }, 1249 | { 1250 | "name": "sebastian/code-unit-reverse-lookup", 1251 | "version": "1.0.0", 1252 | "source": { 1253 | "type": "git", 1254 | "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", 1255 | "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe" 1256 | }, 1257 | "dist": { 1258 | "type": "zip", 1259 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/c36f5e7cfce482fde5bf8d10d41a53591e0198fe", 1260 | "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe", 1261 | "shasum": "" 1262 | }, 1263 | "require": { 1264 | "php": ">=5.6" 1265 | }, 1266 | "require-dev": { 1267 | "phpunit/phpunit": "~5" 1268 | }, 1269 | "type": "library", 1270 | "extra": { 1271 | "branch-alias": { 1272 | "dev-master": "1.0.x-dev" 1273 | } 1274 | }, 1275 | "autoload": { 1276 | "classmap": [ 1277 | "src/" 1278 | ] 1279 | }, 1280 | "notification-url": "https://packagist.org/downloads/", 1281 | "license": [ 1282 | "BSD-3-Clause" 1283 | ], 1284 | "authors": [ 1285 | { 1286 | "name": "Sebastian Bergmann", 1287 | "email": "sebastian@phpunit.de" 1288 | } 1289 | ], 1290 | "description": "Looks up which function or method a line of code belongs to", 1291 | "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", 1292 | "time": "2016-02-13 06:45:14" 1293 | }, 1294 | { 1295 | "name": "sebastian/comparator", 1296 | "version": "1.2.2", 1297 | "source": { 1298 | "type": "git", 1299 | "url": "https://github.com/sebastianbergmann/comparator.git", 1300 | "reference": "6a1ed12e8b2409076ab22e3897126211ff8b1f7f" 1301 | }, 1302 | "dist": { 1303 | "type": "zip", 1304 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/6a1ed12e8b2409076ab22e3897126211ff8b1f7f", 1305 | "reference": "6a1ed12e8b2409076ab22e3897126211ff8b1f7f", 1306 | "shasum": "" 1307 | }, 1308 | "require": { 1309 | "php": ">=5.3.3", 1310 | "sebastian/diff": "~1.2", 1311 | "sebastian/exporter": "~1.2 || ~2.0" 1312 | }, 1313 | "require-dev": { 1314 | "phpunit/phpunit": "~4.4" 1315 | }, 1316 | "type": "library", 1317 | "extra": { 1318 | "branch-alias": { 1319 | "dev-master": "1.2.x-dev" 1320 | } 1321 | }, 1322 | "autoload": { 1323 | "classmap": [ 1324 | "src/" 1325 | ] 1326 | }, 1327 | "notification-url": "https://packagist.org/downloads/", 1328 | "license": [ 1329 | "BSD-3-Clause" 1330 | ], 1331 | "authors": [ 1332 | { 1333 | "name": "Jeff Welch", 1334 | "email": "whatthejeff@gmail.com" 1335 | }, 1336 | { 1337 | "name": "Volker Dusch", 1338 | "email": "github@wallbash.com" 1339 | }, 1340 | { 1341 | "name": "Bernhard Schussek", 1342 | "email": "bschussek@2bepublished.at" 1343 | }, 1344 | { 1345 | "name": "Sebastian Bergmann", 1346 | "email": "sebastian@phpunit.de" 1347 | } 1348 | ], 1349 | "description": "Provides the functionality to compare PHP values for equality", 1350 | "homepage": "http://www.github.com/sebastianbergmann/comparator", 1351 | "keywords": [ 1352 | "comparator", 1353 | "compare", 1354 | "equality" 1355 | ], 1356 | "time": "2016-11-19 09:18:40" 1357 | }, 1358 | { 1359 | "name": "sebastian/diff", 1360 | "version": "1.4.1", 1361 | "source": { 1362 | "type": "git", 1363 | "url": "https://github.com/sebastianbergmann/diff.git", 1364 | "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" 1365 | }, 1366 | "dist": { 1367 | "type": "zip", 1368 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", 1369 | "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", 1370 | "shasum": "" 1371 | }, 1372 | "require": { 1373 | "php": ">=5.3.3" 1374 | }, 1375 | "require-dev": { 1376 | "phpunit/phpunit": "~4.8" 1377 | }, 1378 | "type": "library", 1379 | "extra": { 1380 | "branch-alias": { 1381 | "dev-master": "1.4-dev" 1382 | } 1383 | }, 1384 | "autoload": { 1385 | "classmap": [ 1386 | "src/" 1387 | ] 1388 | }, 1389 | "notification-url": "https://packagist.org/downloads/", 1390 | "license": [ 1391 | "BSD-3-Clause" 1392 | ], 1393 | "authors": [ 1394 | { 1395 | "name": "Kore Nordmann", 1396 | "email": "mail@kore-nordmann.de" 1397 | }, 1398 | { 1399 | "name": "Sebastian Bergmann", 1400 | "email": "sebastian@phpunit.de" 1401 | } 1402 | ], 1403 | "description": "Diff implementation", 1404 | "homepage": "https://github.com/sebastianbergmann/diff", 1405 | "keywords": [ 1406 | "diff" 1407 | ], 1408 | "time": "2015-12-08 07:14:41" 1409 | }, 1410 | { 1411 | "name": "sebastian/environment", 1412 | "version": "2.0.0", 1413 | "source": { 1414 | "type": "git", 1415 | "url": "https://github.com/sebastianbergmann/environment.git", 1416 | "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac" 1417 | }, 1418 | "dist": { 1419 | "type": "zip", 1420 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5795ffe5dc5b02460c3e34222fee8cbe245d8fac", 1421 | "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac", 1422 | "shasum": "" 1423 | }, 1424 | "require": { 1425 | "php": "^5.6 || ^7.0" 1426 | }, 1427 | "require-dev": { 1428 | "phpunit/phpunit": "^5.0" 1429 | }, 1430 | "type": "library", 1431 | "extra": { 1432 | "branch-alias": { 1433 | "dev-master": "2.0.x-dev" 1434 | } 1435 | }, 1436 | "autoload": { 1437 | "classmap": [ 1438 | "src/" 1439 | ] 1440 | }, 1441 | "notification-url": "https://packagist.org/downloads/", 1442 | "license": [ 1443 | "BSD-3-Clause" 1444 | ], 1445 | "authors": [ 1446 | { 1447 | "name": "Sebastian Bergmann", 1448 | "email": "sebastian@phpunit.de" 1449 | } 1450 | ], 1451 | "description": "Provides functionality to handle HHVM/PHP environments", 1452 | "homepage": "http://www.github.com/sebastianbergmann/environment", 1453 | "keywords": [ 1454 | "Xdebug", 1455 | "environment", 1456 | "hhvm" 1457 | ], 1458 | "time": "2016-11-26 07:53:53" 1459 | }, 1460 | { 1461 | "name": "sebastian/exporter", 1462 | "version": "2.0.0", 1463 | "source": { 1464 | "type": "git", 1465 | "url": "https://github.com/sebastianbergmann/exporter.git", 1466 | "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4" 1467 | }, 1468 | "dist": { 1469 | "type": "zip", 1470 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", 1471 | "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", 1472 | "shasum": "" 1473 | }, 1474 | "require": { 1475 | "php": ">=5.3.3", 1476 | "sebastian/recursion-context": "~2.0" 1477 | }, 1478 | "require-dev": { 1479 | "ext-mbstring": "*", 1480 | "phpunit/phpunit": "~4.4" 1481 | }, 1482 | "type": "library", 1483 | "extra": { 1484 | "branch-alias": { 1485 | "dev-master": "2.0.x-dev" 1486 | } 1487 | }, 1488 | "autoload": { 1489 | "classmap": [ 1490 | "src/" 1491 | ] 1492 | }, 1493 | "notification-url": "https://packagist.org/downloads/", 1494 | "license": [ 1495 | "BSD-3-Clause" 1496 | ], 1497 | "authors": [ 1498 | { 1499 | "name": "Jeff Welch", 1500 | "email": "whatthejeff@gmail.com" 1501 | }, 1502 | { 1503 | "name": "Volker Dusch", 1504 | "email": "github@wallbash.com" 1505 | }, 1506 | { 1507 | "name": "Bernhard Schussek", 1508 | "email": "bschussek@2bepublished.at" 1509 | }, 1510 | { 1511 | "name": "Sebastian Bergmann", 1512 | "email": "sebastian@phpunit.de" 1513 | }, 1514 | { 1515 | "name": "Adam Harvey", 1516 | "email": "aharvey@php.net" 1517 | } 1518 | ], 1519 | "description": "Provides the functionality to export PHP variables for visualization", 1520 | "homepage": "http://www.github.com/sebastianbergmann/exporter", 1521 | "keywords": [ 1522 | "export", 1523 | "exporter" 1524 | ], 1525 | "time": "2016-11-19 08:54:04" 1526 | }, 1527 | { 1528 | "name": "sebastian/global-state", 1529 | "version": "1.1.1", 1530 | "source": { 1531 | "type": "git", 1532 | "url": "https://github.com/sebastianbergmann/global-state.git", 1533 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" 1534 | }, 1535 | "dist": { 1536 | "type": "zip", 1537 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", 1538 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", 1539 | "shasum": "" 1540 | }, 1541 | "require": { 1542 | "php": ">=5.3.3" 1543 | }, 1544 | "require-dev": { 1545 | "phpunit/phpunit": "~4.2" 1546 | }, 1547 | "suggest": { 1548 | "ext-uopz": "*" 1549 | }, 1550 | "type": "library", 1551 | "extra": { 1552 | "branch-alias": { 1553 | "dev-master": "1.0-dev" 1554 | } 1555 | }, 1556 | "autoload": { 1557 | "classmap": [ 1558 | "src/" 1559 | ] 1560 | }, 1561 | "notification-url": "https://packagist.org/downloads/", 1562 | "license": [ 1563 | "BSD-3-Clause" 1564 | ], 1565 | "authors": [ 1566 | { 1567 | "name": "Sebastian Bergmann", 1568 | "email": "sebastian@phpunit.de" 1569 | } 1570 | ], 1571 | "description": "Snapshotting of global state", 1572 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 1573 | "keywords": [ 1574 | "global state" 1575 | ], 1576 | "time": "2015-10-12 03:26:01" 1577 | }, 1578 | { 1579 | "name": "sebastian/object-enumerator", 1580 | "version": "2.0.0", 1581 | "source": { 1582 | "type": "git", 1583 | "url": "https://github.com/sebastianbergmann/object-enumerator.git", 1584 | "reference": "96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35" 1585 | }, 1586 | "dist": { 1587 | "type": "zip", 1588 | "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35", 1589 | "reference": "96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35", 1590 | "shasum": "" 1591 | }, 1592 | "require": { 1593 | "php": ">=5.6", 1594 | "sebastian/recursion-context": "~2.0" 1595 | }, 1596 | "require-dev": { 1597 | "phpunit/phpunit": "~5" 1598 | }, 1599 | "type": "library", 1600 | "extra": { 1601 | "branch-alias": { 1602 | "dev-master": "2.0.x-dev" 1603 | } 1604 | }, 1605 | "autoload": { 1606 | "classmap": [ 1607 | "src/" 1608 | ] 1609 | }, 1610 | "notification-url": "https://packagist.org/downloads/", 1611 | "license": [ 1612 | "BSD-3-Clause" 1613 | ], 1614 | "authors": [ 1615 | { 1616 | "name": "Sebastian Bergmann", 1617 | "email": "sebastian@phpunit.de" 1618 | } 1619 | ], 1620 | "description": "Traverses array structures and object graphs to enumerate all referenced objects", 1621 | "homepage": "https://github.com/sebastianbergmann/object-enumerator/", 1622 | "time": "2016-11-19 07:35:10" 1623 | }, 1624 | { 1625 | "name": "sebastian/recursion-context", 1626 | "version": "2.0.0", 1627 | "source": { 1628 | "type": "git", 1629 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 1630 | "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a" 1631 | }, 1632 | "dist": { 1633 | "type": "zip", 1634 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/2c3ba150cbec723aa057506e73a8d33bdb286c9a", 1635 | "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a", 1636 | "shasum": "" 1637 | }, 1638 | "require": { 1639 | "php": ">=5.3.3" 1640 | }, 1641 | "require-dev": { 1642 | "phpunit/phpunit": "~4.4" 1643 | }, 1644 | "type": "library", 1645 | "extra": { 1646 | "branch-alias": { 1647 | "dev-master": "2.0.x-dev" 1648 | } 1649 | }, 1650 | "autoload": { 1651 | "classmap": [ 1652 | "src/" 1653 | ] 1654 | }, 1655 | "notification-url": "https://packagist.org/downloads/", 1656 | "license": [ 1657 | "BSD-3-Clause" 1658 | ], 1659 | "authors": [ 1660 | { 1661 | "name": "Jeff Welch", 1662 | "email": "whatthejeff@gmail.com" 1663 | }, 1664 | { 1665 | "name": "Sebastian Bergmann", 1666 | "email": "sebastian@phpunit.de" 1667 | }, 1668 | { 1669 | "name": "Adam Harvey", 1670 | "email": "aharvey@php.net" 1671 | } 1672 | ], 1673 | "description": "Provides functionality to recursively process PHP variables", 1674 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context", 1675 | "time": "2016-11-19 07:33:16" 1676 | }, 1677 | { 1678 | "name": "sebastian/resource-operations", 1679 | "version": "1.0.0", 1680 | "source": { 1681 | "type": "git", 1682 | "url": "https://github.com/sebastianbergmann/resource-operations.git", 1683 | "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" 1684 | }, 1685 | "dist": { 1686 | "type": "zip", 1687 | "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", 1688 | "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", 1689 | "shasum": "" 1690 | }, 1691 | "require": { 1692 | "php": ">=5.6.0" 1693 | }, 1694 | "type": "library", 1695 | "extra": { 1696 | "branch-alias": { 1697 | "dev-master": "1.0.x-dev" 1698 | } 1699 | }, 1700 | "autoload": { 1701 | "classmap": [ 1702 | "src/" 1703 | ] 1704 | }, 1705 | "notification-url": "https://packagist.org/downloads/", 1706 | "license": [ 1707 | "BSD-3-Clause" 1708 | ], 1709 | "authors": [ 1710 | { 1711 | "name": "Sebastian Bergmann", 1712 | "email": "sebastian@phpunit.de" 1713 | } 1714 | ], 1715 | "description": "Provides a list of PHP built-in functions that operate on resources", 1716 | "homepage": "https://www.github.com/sebastianbergmann/resource-operations", 1717 | "time": "2015-07-28 20:34:47" 1718 | }, 1719 | { 1720 | "name": "sebastian/version", 1721 | "version": "2.0.1", 1722 | "source": { 1723 | "type": "git", 1724 | "url": "https://github.com/sebastianbergmann/version.git", 1725 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" 1726 | }, 1727 | "dist": { 1728 | "type": "zip", 1729 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", 1730 | "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", 1731 | "shasum": "" 1732 | }, 1733 | "require": { 1734 | "php": ">=5.6" 1735 | }, 1736 | "type": "library", 1737 | "extra": { 1738 | "branch-alias": { 1739 | "dev-master": "2.0.x-dev" 1740 | } 1741 | }, 1742 | "autoload": { 1743 | "classmap": [ 1744 | "src/" 1745 | ] 1746 | }, 1747 | "notification-url": "https://packagist.org/downloads/", 1748 | "license": [ 1749 | "BSD-3-Clause" 1750 | ], 1751 | "authors": [ 1752 | { 1753 | "name": "Sebastian Bergmann", 1754 | "email": "sebastian@phpunit.de", 1755 | "role": "lead" 1756 | } 1757 | ], 1758 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 1759 | "homepage": "https://github.com/sebastianbergmann/version", 1760 | "time": "2016-10-03 07:35:21" 1761 | }, 1762 | { 1763 | "name": "symfony/config", 1764 | "version": "v3.2.0", 1765 | "source": { 1766 | "type": "git", 1767 | "url": "https://github.com/symfony/config.git", 1768 | "reference": "4a68f8953180bf77ea65f585020f4db0b18600b4" 1769 | }, 1770 | "dist": { 1771 | "type": "zip", 1772 | "url": "https://api.github.com/repos/symfony/config/zipball/4a68f8953180bf77ea65f585020f4db0b18600b4", 1773 | "reference": "4a68f8953180bf77ea65f585020f4db0b18600b4", 1774 | "shasum": "" 1775 | }, 1776 | "require": { 1777 | "php": ">=5.5.9", 1778 | "symfony/filesystem": "~2.8|~3.0" 1779 | }, 1780 | "require-dev": { 1781 | "symfony/yaml": "~3.0" 1782 | }, 1783 | "suggest": { 1784 | "symfony/yaml": "To use the yaml reference dumper" 1785 | }, 1786 | "type": "library", 1787 | "extra": { 1788 | "branch-alias": { 1789 | "dev-master": "3.2-dev" 1790 | } 1791 | }, 1792 | "autoload": { 1793 | "psr-4": { 1794 | "Symfony\\Component\\Config\\": "" 1795 | }, 1796 | "exclude-from-classmap": [ 1797 | "/Tests/" 1798 | ] 1799 | }, 1800 | "notification-url": "https://packagist.org/downloads/", 1801 | "license": [ 1802 | "MIT" 1803 | ], 1804 | "authors": [ 1805 | { 1806 | "name": "Fabien Potencier", 1807 | "email": "fabien@symfony.com" 1808 | }, 1809 | { 1810 | "name": "Symfony Community", 1811 | "homepage": "https://symfony.com/contributors" 1812 | } 1813 | ], 1814 | "description": "Symfony Config Component", 1815 | "homepage": "https://symfony.com", 1816 | "time": "2016-11-29 11:12:32" 1817 | }, 1818 | { 1819 | "name": "symfony/console", 1820 | "version": "v3.2.0", 1821 | "source": { 1822 | "type": "git", 1823 | "url": "https://github.com/symfony/console.git", 1824 | "reference": "09d0fd33560e3573185a2ea17614e37ba38716c5" 1825 | }, 1826 | "dist": { 1827 | "type": "zip", 1828 | "url": "https://api.github.com/repos/symfony/console/zipball/09d0fd33560e3573185a2ea17614e37ba38716c5", 1829 | "reference": "09d0fd33560e3573185a2ea17614e37ba38716c5", 1830 | "shasum": "" 1831 | }, 1832 | "require": { 1833 | "php": ">=5.5.9", 1834 | "symfony/debug": "~2.8|~3.0", 1835 | "symfony/polyfill-mbstring": "~1.0" 1836 | }, 1837 | "require-dev": { 1838 | "psr/log": "~1.0", 1839 | "symfony/event-dispatcher": "~2.8|~3.0", 1840 | "symfony/filesystem": "~2.8|~3.0", 1841 | "symfony/process": "~2.8|~3.0" 1842 | }, 1843 | "suggest": { 1844 | "psr/log": "For using the console logger", 1845 | "symfony/event-dispatcher": "", 1846 | "symfony/filesystem": "", 1847 | "symfony/process": "" 1848 | }, 1849 | "type": "library", 1850 | "extra": { 1851 | "branch-alias": { 1852 | "dev-master": "3.2-dev" 1853 | } 1854 | }, 1855 | "autoload": { 1856 | "psr-4": { 1857 | "Symfony\\Component\\Console\\": "" 1858 | }, 1859 | "exclude-from-classmap": [ 1860 | "/Tests/" 1861 | ] 1862 | }, 1863 | "notification-url": "https://packagist.org/downloads/", 1864 | "license": [ 1865 | "MIT" 1866 | ], 1867 | "authors": [ 1868 | { 1869 | "name": "Fabien Potencier", 1870 | "email": "fabien@symfony.com" 1871 | }, 1872 | { 1873 | "name": "Symfony Community", 1874 | "homepage": "https://symfony.com/contributors" 1875 | } 1876 | ], 1877 | "description": "Symfony Console Component", 1878 | "homepage": "https://symfony.com", 1879 | "time": "2016-11-16 22:18:16" 1880 | }, 1881 | { 1882 | "name": "symfony/debug", 1883 | "version": "v3.2.0", 1884 | "source": { 1885 | "type": "git", 1886 | "url": "https://github.com/symfony/debug.git", 1887 | "reference": "9f923e68d524a3095c5a2ae5fc7220c7cbc12231" 1888 | }, 1889 | "dist": { 1890 | "type": "zip", 1891 | "url": "https://api.github.com/repos/symfony/debug/zipball/9f923e68d524a3095c5a2ae5fc7220c7cbc12231", 1892 | "reference": "9f923e68d524a3095c5a2ae5fc7220c7cbc12231", 1893 | "shasum": "" 1894 | }, 1895 | "require": { 1896 | "php": ">=5.5.9", 1897 | "psr/log": "~1.0" 1898 | }, 1899 | "conflict": { 1900 | "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" 1901 | }, 1902 | "require-dev": { 1903 | "symfony/class-loader": "~2.8|~3.0", 1904 | "symfony/http-kernel": "~2.8|~3.0" 1905 | }, 1906 | "type": "library", 1907 | "extra": { 1908 | "branch-alias": { 1909 | "dev-master": "3.2-dev" 1910 | } 1911 | }, 1912 | "autoload": { 1913 | "psr-4": { 1914 | "Symfony\\Component\\Debug\\": "" 1915 | }, 1916 | "exclude-from-classmap": [ 1917 | "/Tests/" 1918 | ] 1919 | }, 1920 | "notification-url": "https://packagist.org/downloads/", 1921 | "license": [ 1922 | "MIT" 1923 | ], 1924 | "authors": [ 1925 | { 1926 | "name": "Fabien Potencier", 1927 | "email": "fabien@symfony.com" 1928 | }, 1929 | { 1930 | "name": "Symfony Community", 1931 | "homepage": "https://symfony.com/contributors" 1932 | } 1933 | ], 1934 | "description": "Symfony Debug Component", 1935 | "homepage": "https://symfony.com", 1936 | "time": "2016-11-16 22:18:16" 1937 | }, 1938 | { 1939 | "name": "symfony/event-dispatcher", 1940 | "version": "v2.8.14", 1941 | "source": { 1942 | "type": "git", 1943 | "url": "https://github.com/symfony/event-dispatcher.git", 1944 | "reference": "25c576abd4e0f212e678fe8b2bd9a9a98c7ea934" 1945 | }, 1946 | "dist": { 1947 | "type": "zip", 1948 | "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/25c576abd4e0f212e678fe8b2bd9a9a98c7ea934", 1949 | "reference": "25c576abd4e0f212e678fe8b2bd9a9a98c7ea934", 1950 | "shasum": "" 1951 | }, 1952 | "require": { 1953 | "php": ">=5.3.9" 1954 | }, 1955 | "require-dev": { 1956 | "psr/log": "~1.0", 1957 | "symfony/config": "~2.0,>=2.0.5|~3.0.0", 1958 | "symfony/dependency-injection": "~2.6|~3.0.0", 1959 | "symfony/expression-language": "~2.6|~3.0.0", 1960 | "symfony/stopwatch": "~2.3|~3.0.0" 1961 | }, 1962 | "suggest": { 1963 | "symfony/dependency-injection": "", 1964 | "symfony/http-kernel": "" 1965 | }, 1966 | "type": "library", 1967 | "extra": { 1968 | "branch-alias": { 1969 | "dev-master": "2.8-dev" 1970 | } 1971 | }, 1972 | "autoload": { 1973 | "psr-4": { 1974 | "Symfony\\Component\\EventDispatcher\\": "" 1975 | }, 1976 | "exclude-from-classmap": [ 1977 | "/Tests/" 1978 | ] 1979 | }, 1980 | "notification-url": "https://packagist.org/downloads/", 1981 | "license": [ 1982 | "MIT" 1983 | ], 1984 | "authors": [ 1985 | { 1986 | "name": "Fabien Potencier", 1987 | "email": "fabien@symfony.com" 1988 | }, 1989 | { 1990 | "name": "Symfony Community", 1991 | "homepage": "https://symfony.com/contributors" 1992 | } 1993 | ], 1994 | "description": "Symfony EventDispatcher Component", 1995 | "homepage": "https://symfony.com", 1996 | "time": "2016-10-13 01:43:15" 1997 | }, 1998 | { 1999 | "name": "symfony/filesystem", 2000 | "version": "v3.2.0", 2001 | "source": { 2002 | "type": "git", 2003 | "url": "https://github.com/symfony/filesystem.git", 2004 | "reference": "8d4cf7561a5b17e5eb7a02b80d0b8f014a3796d4" 2005 | }, 2006 | "dist": { 2007 | "type": "zip", 2008 | "url": "https://api.github.com/repos/symfony/filesystem/zipball/8d4cf7561a5b17e5eb7a02b80d0b8f014a3796d4", 2009 | "reference": "8d4cf7561a5b17e5eb7a02b80d0b8f014a3796d4", 2010 | "shasum": "" 2011 | }, 2012 | "require": { 2013 | "php": ">=5.5.9" 2014 | }, 2015 | "type": "library", 2016 | "extra": { 2017 | "branch-alias": { 2018 | "dev-master": "3.2-dev" 2019 | } 2020 | }, 2021 | "autoload": { 2022 | "psr-4": { 2023 | "Symfony\\Component\\Filesystem\\": "" 2024 | }, 2025 | "exclude-from-classmap": [ 2026 | "/Tests/" 2027 | ] 2028 | }, 2029 | "notification-url": "https://packagist.org/downloads/", 2030 | "license": [ 2031 | "MIT" 2032 | ], 2033 | "authors": [ 2034 | { 2035 | "name": "Fabien Potencier", 2036 | "email": "fabien@symfony.com" 2037 | }, 2038 | { 2039 | "name": "Symfony Community", 2040 | "homepage": "https://symfony.com/contributors" 2041 | } 2042 | ], 2043 | "description": "Symfony Filesystem Component", 2044 | "homepage": "https://symfony.com", 2045 | "time": "2016-11-24 00:46:43" 2046 | }, 2047 | { 2048 | "name": "symfony/polyfill-mbstring", 2049 | "version": "v1.3.0", 2050 | "source": { 2051 | "type": "git", 2052 | "url": "https://github.com/symfony/polyfill-mbstring.git", 2053 | "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4" 2054 | }, 2055 | "dist": { 2056 | "type": "zip", 2057 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/e79d363049d1c2128f133a2667e4f4190904f7f4", 2058 | "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4", 2059 | "shasum": "" 2060 | }, 2061 | "require": { 2062 | "php": ">=5.3.3" 2063 | }, 2064 | "suggest": { 2065 | "ext-mbstring": "For best performance" 2066 | }, 2067 | "type": "library", 2068 | "extra": { 2069 | "branch-alias": { 2070 | "dev-master": "1.3-dev" 2071 | } 2072 | }, 2073 | "autoload": { 2074 | "psr-4": { 2075 | "Symfony\\Polyfill\\Mbstring\\": "" 2076 | }, 2077 | "files": [ 2078 | "bootstrap.php" 2079 | ] 2080 | }, 2081 | "notification-url": "https://packagist.org/downloads/", 2082 | "license": [ 2083 | "MIT" 2084 | ], 2085 | "authors": [ 2086 | { 2087 | "name": "Nicolas Grekas", 2088 | "email": "p@tchwork.com" 2089 | }, 2090 | { 2091 | "name": "Symfony Community", 2092 | "homepage": "https://symfony.com/contributors" 2093 | } 2094 | ], 2095 | "description": "Symfony polyfill for the Mbstring extension", 2096 | "homepage": "https://symfony.com", 2097 | "keywords": [ 2098 | "compatibility", 2099 | "mbstring", 2100 | "polyfill", 2101 | "portable", 2102 | "shim" 2103 | ], 2104 | "time": "2016-11-14 01:06:16" 2105 | }, 2106 | { 2107 | "name": "symfony/stopwatch", 2108 | "version": "v3.2.0", 2109 | "source": { 2110 | "type": "git", 2111 | "url": "https://github.com/symfony/stopwatch.git", 2112 | "reference": "5b139e1c4290e6c7640ba80d9c9b5e49ef22b841" 2113 | }, 2114 | "dist": { 2115 | "type": "zip", 2116 | "url": "https://api.github.com/repos/symfony/stopwatch/zipball/5b139e1c4290e6c7640ba80d9c9b5e49ef22b841", 2117 | "reference": "5b139e1c4290e6c7640ba80d9c9b5e49ef22b841", 2118 | "shasum": "" 2119 | }, 2120 | "require": { 2121 | "php": ">=5.5.9" 2122 | }, 2123 | "type": "library", 2124 | "extra": { 2125 | "branch-alias": { 2126 | "dev-master": "3.2-dev" 2127 | } 2128 | }, 2129 | "autoload": { 2130 | "psr-4": { 2131 | "Symfony\\Component\\Stopwatch\\": "" 2132 | }, 2133 | "exclude-from-classmap": [ 2134 | "/Tests/" 2135 | ] 2136 | }, 2137 | "notification-url": "https://packagist.org/downloads/", 2138 | "license": [ 2139 | "MIT" 2140 | ], 2141 | "authors": [ 2142 | { 2143 | "name": "Fabien Potencier", 2144 | "email": "fabien@symfony.com" 2145 | }, 2146 | { 2147 | "name": "Symfony Community", 2148 | "homepage": "https://symfony.com/contributors" 2149 | } 2150 | ], 2151 | "description": "Symfony Stopwatch Component", 2152 | "homepage": "https://symfony.com", 2153 | "time": "2016-06-29 05:43:10" 2154 | }, 2155 | { 2156 | "name": "symfony/yaml", 2157 | "version": "v3.2.0", 2158 | "source": { 2159 | "type": "git", 2160 | "url": "https://github.com/symfony/yaml.git", 2161 | "reference": "f2300ba8fbb002c028710b92e1906e7457410693" 2162 | }, 2163 | "dist": { 2164 | "type": "zip", 2165 | "url": "https://api.github.com/repos/symfony/yaml/zipball/f2300ba8fbb002c028710b92e1906e7457410693", 2166 | "reference": "f2300ba8fbb002c028710b92e1906e7457410693", 2167 | "shasum": "" 2168 | }, 2169 | "require": { 2170 | "php": ">=5.5.9" 2171 | }, 2172 | "require-dev": { 2173 | "symfony/console": "~2.8|~3.0" 2174 | }, 2175 | "suggest": { 2176 | "symfony/console": "For validating YAML files using the lint command" 2177 | }, 2178 | "type": "library", 2179 | "extra": { 2180 | "branch-alias": { 2181 | "dev-master": "3.2-dev" 2182 | } 2183 | }, 2184 | "autoload": { 2185 | "psr-4": { 2186 | "Symfony\\Component\\Yaml\\": "" 2187 | }, 2188 | "exclude-from-classmap": [ 2189 | "/Tests/" 2190 | ] 2191 | }, 2192 | "notification-url": "https://packagist.org/downloads/", 2193 | "license": [ 2194 | "MIT" 2195 | ], 2196 | "authors": [ 2197 | { 2198 | "name": "Fabien Potencier", 2199 | "email": "fabien@symfony.com" 2200 | }, 2201 | { 2202 | "name": "Symfony Community", 2203 | "homepage": "https://symfony.com/contributors" 2204 | } 2205 | ], 2206 | "description": "Symfony Yaml Component", 2207 | "homepage": "https://symfony.com", 2208 | "time": "2016-11-18 21:17:59" 2209 | }, 2210 | { 2211 | "name": "webmozart/assert", 2212 | "version": "1.2.0", 2213 | "source": { 2214 | "type": "git", 2215 | "url": "https://github.com/webmozart/assert.git", 2216 | "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f" 2217 | }, 2218 | "dist": { 2219 | "type": "zip", 2220 | "url": "https://api.github.com/repos/webmozart/assert/zipball/2db61e59ff05fe5126d152bd0655c9ea113e550f", 2221 | "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f", 2222 | "shasum": "" 2223 | }, 2224 | "require": { 2225 | "php": "^5.3.3 || ^7.0" 2226 | }, 2227 | "require-dev": { 2228 | "phpunit/phpunit": "^4.6", 2229 | "sebastian/version": "^1.0.1" 2230 | }, 2231 | "type": "library", 2232 | "extra": { 2233 | "branch-alias": { 2234 | "dev-master": "1.3-dev" 2235 | } 2236 | }, 2237 | "autoload": { 2238 | "psr-4": { 2239 | "Webmozart\\Assert\\": "src/" 2240 | } 2241 | }, 2242 | "notification-url": "https://packagist.org/downloads/", 2243 | "license": [ 2244 | "MIT" 2245 | ], 2246 | "authors": [ 2247 | { 2248 | "name": "Bernhard Schussek", 2249 | "email": "bschussek@gmail.com" 2250 | } 2251 | ], 2252 | "description": "Assertions to validate method input/output with nice error messages.", 2253 | "keywords": [ 2254 | "assert", 2255 | "check", 2256 | "validate" 2257 | ], 2258 | "time": "2016-11-23 20:04:58" 2259 | } 2260 | ], 2261 | "aliases": [], 2262 | "minimum-stability": "stable", 2263 | "stability-flags": [], 2264 | "prefer-stable": false, 2265 | "prefer-lowest": false, 2266 | "platform": { 2267 | "php": ">=5.6" 2268 | }, 2269 | "platform-dev": [] 2270 | } 2271 | -------------------------------------------------------------------------------- /examples/autoload.php: -------------------------------------------------------------------------------- 1 | getIterator($commandName); 15 | foreach ($iterator as $item) { 16 | print_r($item); 17 | } 18 | -------------------------------------------------------------------------------- /examples/single_page.php: -------------------------------------------------------------------------------- 1 | getCommand($commandName); 15 | $items = $client->execute($command); 16 | print_r($items); 17 | -------------------------------------------------------------------------------- /examples/single_page_with_id.php: -------------------------------------------------------------------------------- 1 | getCommand($commandName, ['id' => $id]); 15 | $items = $client->execute($command); 16 | print_r($items); 17 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | tests 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | src/ 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/Usabilla/API/Client/UsabillaClient.php: -------------------------------------------------------------------------------- 1 | getEmitter()->attach(new SignatureSubscriber(new Signature(), $accessKey, $secretKey)); 44 | 45 | $description = new UsabillaDescription(); 46 | 47 | parent::__construct($client, $description, $config); 48 | } 49 | 50 | /** 51 | * Iterates through a given command. 52 | * 53 | * @param string $commandName 54 | * 55 | * @return \Generator 56 | */ 57 | public function getIterator($commandName) 58 | { 59 | $hasMore = true; 60 | $arguments = []; 61 | while ($hasMore) { 62 | $result = $this->execute($this->getCommand($commandName, $arguments)); 63 | foreach ($result['items'] as $item) { 64 | yield $item; 65 | } 66 | $hasMore = $result['hasMore']; 67 | $arguments['since'] = $result['lastTimestamp']; 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /src/Usabilla/API/Description/UsabillaDescription.php: -------------------------------------------------------------------------------- 1 | 'https://data.usabilla.com', 34 | 'apiVersion' => '1.2', 35 | 36 | // All the operations that can be performed at the Usabilla API. 37 | 'operations' => [ 38 | 39 | // Usabilla for Apps. 40 | 'GetApps' => [ 41 | 'httpMethod' => 'GET', 42 | 'uri' => '/live/apps', 43 | 'responseModel' => 'AppItems', 44 | ], 45 | 46 | 'GetAppFeedbackItems' => [ 47 | 'httpMethod' => 'GET', 48 | 'uri' => '/live/apps/{id}/feedback', 49 | 'responseModel' => 'AppFeedbackItems', 50 | 'parameters' => [ 51 | 'id' => [ '$ref' => 'NonMandatoryIdParam' ], 52 | 'limit' => [ '$ref' => 'LimitParam' ], 53 | 'since' => [ '$ref' => 'SinceParam' ], 54 | ], 55 | ], 56 | 57 | 'GetAppCampaigns' => [ 58 | 'httpMethod' => 'GET', 59 | 'uri' => '/live/apps/campaign', 60 | 'responseModel' => 'AppCampaignItems', 61 | ], 62 | 63 | 'GetAppCampaignResults' => [ 64 | 'httpMethod' => 'GET', 65 | 'uri' => '/live/apps/campaign/{id}/results', 66 | 'responseModel' => 'AppCampaignResults', 67 | 'parameters' => [ 68 | 'id' => [ '$ref' => 'MandatoryIdParam' ], 69 | 'limit' => [ '$ref' => 'LimitParam' ], 70 | 'since' => [ '$ref' => 'SinceParam' ], 71 | ], 72 | ], 73 | 74 | // Usabilla for Email. 75 | 'GetEmailButtons' => [ 76 | 'httpMethod' => 'GET', 77 | 'uri' => '/live/email/button', 78 | 'responseModel' => 'EmailButtonItems', 79 | ], 80 | 81 | 'GetEmailFeedbackItems' => [ 82 | 'httpMethod' => 'GET', 83 | 'uri' => '/live/email/button/{id}/feedback', 84 | 'responseModel' => 'EmailFeedbackItems', 85 | 'parameters' => [ 86 | 'id' => [ '$ref' => 'NonMandatoryIdParam' ], 87 | 'limit' => [ '$ref' => 'LimitParam' ], 88 | 'since' => [ '$ref' => 'SinceParam' ], 89 | ], 90 | ], 91 | 92 | // Usabilla for Websites. 93 | 'GetInpageWidgets' => [ 94 | 'httpMethod' => 'GET', 95 | 'uri' => '/live/websites/inpage', 96 | 'responseModel' => 'InpageWidgetItems', 97 | 'parameters' => [ 98 | 'limit' => [ '$ref' => 'LimitParam' ], 99 | 'since' => [ '$ref' => 'SinceParam' ], 100 | ], 101 | ], 102 | 103 | 'GetInpageWidgetFeedbackItems' => [ 104 | 'httpMethod' => 'GET', 105 | 'uri' => '/live/websites/inpage/{id}/feedback', 106 | 'responseModel' => 'InpageWidgetFeedbackItems', 107 | 'parameters' => [ 108 | 'id' => [ '$ref' => 'MandatoryIdParam' ], 109 | 'limit' => [ '$ref' => 'LimitParam' ], 110 | 'since' => [ '$ref' => 'SinceParam' ], 111 | ], 112 | ], 113 | 114 | 'GetWebsiteCampaigns' => [ 115 | 'httpMethod' => 'GET', 116 | 'uri' => '/live/websites/campaign', 117 | 'responseModel' => 'WebsiteCampaignItems', 118 | 'parameters' => [ 119 | 'limit' => [ '$ref' => 'LimitParam' ], 120 | 'since' => [ '$ref' => 'SinceParam' ], 121 | ], 122 | ], 123 | 124 | 'GetWebsiteCampaignResults' => [ 125 | 'httpMethod' => 'GET', 126 | 'uri' => '/live/websites/campaign/{id}/results', 127 | 'responseModel' => 'WebsiteCampaignResultItems', 128 | 'parameters' => [ 129 | 'id' => [ '$ref' => 'MandatoryIdParam' ], 130 | 'limit' => [ '$ref' => 'LimitParam' ], 131 | 'since' => [ '$ref' => 'SinceParam' ], 132 | ], 133 | ], 134 | 135 | 'GetWebsiteCampaignStats' => [ 136 | 'httpMethod' => 'GET', 137 | 'uri' => '/live/websites/campaign/{id}/stats', 138 | 'responseModel' => 'WebsiteCampaignStatsItems', 139 | 'parameters' => [ 140 | 'id' => [ '$ref' => 'MandatoryIdParam' ], 141 | 'limit' => [ '$ref' => 'LimitParam' ], 142 | 'since' => [ '$ref' => 'SinceParam' ], 143 | ], 144 | ], 145 | 146 | 'GetWebsiteButtons' => [ 147 | 'httpMethod' => 'GET', 148 | 'uri' => '/live/websites/button', 149 | 'responseModel' => 'WebsiteButtonItems', 150 | ], 151 | 152 | 'GetWebsiteFeedbackItems' => [ 153 | 'httpMethod' => 'GET', 154 | 'uri' => '/live/websites/button/{id}/feedback', 155 | 'responseModel' => 'WebsiteFeedbackItems', 156 | 'parameters' => [ 157 | 'id' => [ '$ref' => 'NonMandatoryIdParam' ], 158 | 'limit' => [ '$ref' => 'LimitParam' ], 159 | 'since' => [ '$ref' => 'SinceParam' ], 160 | ], 161 | ], 162 | ], 163 | 164 | 'models' => [ 165 | 166 | // The main models that can be fetched from the Usabilla API. 167 | 'AppItems' => [ '$ref' => 'DefaultRequest' ], 168 | 'AppFeedbackItems' => [ '$ref' => 'DefaultRequest' ], 169 | 'AppCampaignItems' => [ '$ref' => 'DefaultRequest' ], 170 | 'AppCampaignResults' => [ '$ref' => 'DefaultRequest' ], 171 | 'WebsiteFeedbackItems' => [ '$ref' => 'DefaultRequest' ], 172 | 'EmailFeedbackItems' => [ '$ref' => 'DefaultRequest' ], 173 | 'WebsiteButtonItems' => [ '$ref' => 'DefaultRequest' ], 174 | 'EmailButtonItems' => [ '$ref' => 'DefaultRequest' ], 175 | 'InpageWidgetItems' => [ '$ref' => 'DefaultRequest' ], 176 | 'InpageWidgetFeedbackItems' => [ '$ref' => 'DefaultRequest' ], 177 | 'WebsiteCampaignItems' => [ '$ref' => 'DefaultRequest' ], 178 | 'WebsiteCampaignStatsItems' => [ '$ref' => 'DefaultRequest' ], 179 | 'WebsiteCampaignResultItems' => [ '$ref' => 'DefaultRequest' ], 180 | 181 | // Request types 182 | 'DefaultRequest' => [ 183 | 'type' => 'object', 184 | 'properties' => [ 185 | 'count' => [ '$ref' => 'CountAttribute' ], 186 | 'hasMore' => [ '$ref' => 'HasMoreAttribute' ], 187 | 'items' => [ 188 | 'location' => 'json', 189 | 'type' => 'array', 190 | 'items' => [ 191 | 'type' => 'object', 192 | ], 193 | ], 194 | 'lastTimestamp' => [ '$ref' => 'LastTimestampAttribute' ], 195 | ], 196 | 'errorResponses' => [ 197 | [ '$ref' => '403Error' ] 198 | ], 199 | ], 200 | 201 | // Other models that are fetched from the Usabilla API. 202 | 'CountAttribute' => ['type' => 'integer', 'location' => 'json'], 203 | 'HasMoreAttribute' => ['type' => 'boolean', 'location' => 'json'], 204 | 'LastTimestampAttribute' => ['type' => 'integer', 'location' => 'json'], 205 | 206 | // Parameter models. 207 | 'LimitParam' => [ 'type' => 'integer', 'location' => 'query' ], 208 | 'MandatoryIdParam' => [ 'type' => 'string', 'location' => 'uri' ], 209 | 'NonMandatoryIdParam' => [ 'type' => 'string', 'location' => 'uri', 'default' => '*' ], 210 | 'SinceParam' => [ 'type' => 'integer', 'location' => 'query' ], 211 | 212 | // Error responses 213 | '403Error' => [ 214 | 'code' => '403', 215 | 'phrase' => 'authorisation failed', 216 | 'class' => 'ClientErrorResponseException' 217 | ] 218 | 219 | ] 220 | 221 | ]); 222 | } 223 | 224 | /** 225 | * @return Operation[] 226 | */ 227 | public function getOperations() 228 | { 229 | return parent::getOperations(); 230 | } 231 | } 232 | -------------------------------------------------------------------------------- /src/Usabilla/API/EventSubscriber/SignatureSubscriber.php: -------------------------------------------------------------------------------- 1 | signature = $signature; 48 | $this->accessKey = $accessKey; 49 | $this->secretKey = $secretKey; 50 | } 51 | 52 | /** 53 | * {@inheritdoc} 54 | */ 55 | public function getEvents() 56 | { 57 | return [ 58 | 'before' => ['onBefore', -255], 59 | ]; 60 | } 61 | 62 | /** 63 | * Signs requests before they are sent 64 | * 65 | * @param BeforeEvent $event Event emitted 66 | */ 67 | public function onBefore(BeforeEvent $event) 68 | { 69 | $this->signature->signRequest($event->getRequest(), $this->accessKey, $this->secretKey); 70 | } 71 | } -------------------------------------------------------------------------------- /src/Usabilla/API/Signature/Signature.php: -------------------------------------------------------------------------------- 1 | getTimestamp(); 40 | $longDate = gmdate(self::ISO8601, $timestamp); 41 | $request->addHeader('Date', gmdate(self::RFC1123, $timestamp)); 42 | 43 | $shortDate = substr($longDate, 0, 8); 44 | $credentialScope = $this->createScope($shortDate); 45 | $signingContext = $this->createSigningContext($request, $this->getPayload($request)); 46 | $signingContext['string_to_sign'] = $this->createStringToSign($longDate, $credentialScope, $signingContext['canonical_request']); 47 | 48 | // Calculate the signing key using a series of derived keys 49 | $signature = hash_hmac('sha256', $signingContext['string_to_sign'], $this->getSigningKey($shortDate, $secretKey)); 50 | 51 | $request->addHeader( 52 | 'Authorization', sprintf( 53 | 'USBL1-HMAC-SHA256 Credential=%s/%s, SignedHeaders=%s, Signature=%s', 54 | $accessKey, 55 | $credentialScope, 56 | $signingContext['signed_headers'], 57 | $signature 58 | ) 59 | ); 60 | 61 | return $request; 62 | } 63 | 64 | /** 65 | * Get the payload part of a signature from a request. 66 | * 67 | * @param RequestInterface $request 68 | * 69 | * @return string 70 | */ 71 | private function getPayload(RequestInterface $request) 72 | { 73 | if ($request->hasHeader('x-usbl-content-sha256')) { 74 | return (string)$request->getHeader('x-usbl-content-sha256'); 75 | } 76 | 77 | return self::DEFAULT_PAYLOAD; 78 | } 79 | 80 | /** 81 | * @param string $shortDate 82 | * 83 | * @return string 84 | */ 85 | private function createScope($shortDate) 86 | { 87 | return sprintf('%s/usbl1_request', $shortDate); 88 | } 89 | 90 | /** 91 | * Create the canonical representation of a request 92 | * 93 | * @param RequestInterface $request Request to canonicalize 94 | * @param string $payload Request payload 95 | * 96 | * @return array Returns an array of context information including: 97 | * - canonical_request 98 | * - signed_headers 99 | */ 100 | private function createSigningContext(RequestInterface $request, $payload) 101 | { 102 | $canonHeaders = []; 103 | foreach ($request->getHeaders() as $key => $values) { 104 | $key = strtolower($key); 105 | if (count($values) == 1) { 106 | $values = $values[0]; 107 | } else { 108 | sort($values); 109 | $values = implode(',', $values); 110 | } 111 | $canonHeaders[$key] = $key . ':' . preg_replace('/\s+/', ' ', $values); 112 | } 113 | 114 | ksort($canonHeaders); 115 | $signedHeadersString = implode(';', array_keys($canonHeaders)); 116 | 117 | $canon = sprintf( 118 | "%s\n%s\n%s\n%s\n\n%s\n%s", 119 | $request->getMethod(), 120 | $this->createCanonicalizedPath($request), 121 | $this->getCanonicalizedQueryString($request), 122 | implode("\n", $canonHeaders), 123 | $signedHeadersString, 124 | $payload 125 | ); 126 | 127 | return [ 128 | 'canonical_request' => $canon, 129 | 'signed_headers' => $signedHeadersString 130 | ]; 131 | } 132 | 133 | /** 134 | * @param RequestInterface $request 135 | * 136 | * @return string 137 | */ 138 | private function createCanonicalizedPath(RequestInterface $request) 139 | { 140 | return $request->getPath(); 141 | } 142 | 143 | /** 144 | * Get the canonicalized query string for a request 145 | * 146 | * @param RequestInterface $request 147 | * 148 | * @return string 149 | */ 150 | private function getCanonicalizedQueryString(RequestInterface $request) 151 | { 152 | $queryParamsKeys = $request->getQuery()->getKeys(); 153 | 154 | $signatureKey = array_search('X-Usbl-Signature', $queryParamsKeys); 155 | if (false !== $signatureKey) { 156 | unset($queryParamsKeys[$signatureKey]); 157 | } 158 | if (empty($queryParamsKeys)) { 159 | return ''; 160 | } 161 | 162 | ksort($queryParamsKeys); 163 | 164 | $qs = ''; 165 | foreach ($queryParamsKeys as $key) { 166 | $values = $request->getQuery()->get($key); 167 | if (is_array($values)) { 168 | sort($values); 169 | } elseif ($values === 0) { 170 | $values = ['0']; 171 | } elseif (!$values) { 172 | $values = ['']; 173 | } 174 | foreach ((array)$values as $value) { 175 | $qs .= rawurlencode($key) . '=' . rawurlencode($value) . '&'; 176 | } 177 | } 178 | 179 | return substr($qs, 0, -1); 180 | } 181 | 182 | /** 183 | * @param string $longDate 184 | * @param string $credentialScope 185 | * @param string $creq 186 | * 187 | * @return string 188 | */ 189 | private function createStringToSign($longDate, $credentialScope, $creq) 190 | { 191 | return sprintf("USBL1-HMAC-SHA256\n%s\n%s\n%s", $longDate, $credentialScope, hash('sha256', $creq)); 192 | } 193 | 194 | /** 195 | * Get a hash for a specific key and value. If the hash was previously 196 | * cached, return it 197 | * 198 | * @param string $shortDate Short date 199 | * @param string $secretKey Secret Access Key 200 | * 201 | * @return string 202 | */ 203 | private function getSigningKey($shortDate, $secretKey) 204 | { 205 | return hash_hmac('sha256', 'usbl1_request', hash_hmac('sha256', $shortDate, 'USBL1' . $secretKey, true), true); 206 | } 207 | } -------------------------------------------------------------------------------- /tests/Usabilla/Tests/API/Client/UsabillaClientTest.php: -------------------------------------------------------------------------------- 1 | client = $this 31 | ->getMockBuilder(UsabillaClient::class) 32 | ->setConstructorArgs([ DEFAULT_KEY, DEFAULT_SECRET, ['validate' => false, 'process' => false] ]) 33 | ->getMock(); 34 | } 35 | 36 | public function testGetIterator() 37 | { 38 | $this 39 | ->client 40 | ->expects($this->any()) 41 | ->method('execute') 42 | ->will( 43 | $this->returnValue([ 44 | 'hasMore' => false, 45 | 'items' => [1, 2, 3], 46 | 'lastTimestamp' => 0 47 | ]) 48 | ); 49 | 50 | $apps = $this->client->getIterator('GetApps'); 51 | $this->assertNull($apps); 52 | } 53 | } 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /tests/Usabilla/Tests/API/Description/UsabillaDescriptionTest.php: -------------------------------------------------------------------------------- 1 | description = new UsabillaDescription(); 30 | } 31 | 32 | public function testGetOperations() 33 | { 34 | $operations = $this->description->getOperations(); 35 | $this->assertEquals(13, count($operations)); 36 | } 37 | } -------------------------------------------------------------------------------- /tests/Usabilla/Tests/API/EventSubscriber/SignatureSubscriberTest.php: -------------------------------------------------------------------------------- 1 | subscriber = new SignatureSubscriber(new Signature(), DEFAULT_KEY, DEFAULT_SECRET); 35 | } 36 | 37 | public function testGetEvents() 38 | { 39 | return [ 40 | 'before' => ['onBefore', -255], 41 | ]; 42 | } 43 | 44 | public function testOnBefore() 45 | { 46 | $event = new BeforeEvent(new Transaction(new Client(), new Request('GET', 'https://data.usabilla.com'))); 47 | $this->subscriber->onBefore($event); 48 | 49 | $this->assertEquals(['Host', 'Date', 'Authorization'], array_keys($event->getRequest()->getHeaders())); 50 | } 51 | } -------------------------------------------------------------------------------- /tests/Usabilla/Tests/API/Signature/SignatureTest.php: -------------------------------------------------------------------------------- 1 | signature = new Signature(); 39 | } 40 | 41 | public function testSignsRequests() 42 | { 43 | $request = $this->createRequest(); 44 | 45 | $contentHash = hash('sha256', 'foobar'); 46 | $request->setHeader('x-usbl-content-sha256', $contentHash); 47 | 48 | $this->signature->signRequest($request, DEFAULT_KEY, DEFAULT_SECRET); 49 | } 50 | 51 | public function testRequestDefaultPayload() 52 | { 53 | $request = $this->createRequest(); 54 | 55 | $this->signature->signRequest($request, DEFAULT_KEY, DEFAULT_SECRET); 56 | } 57 | 58 | public function queryStringProvider() 59 | { 60 | return [ 61 | [[ 'Foo' => '', 'a' => 0, ], 'Foo=&a=0'], 62 | [[ 'Foo' => '', 'a' => '', ], 'Foo=&a='], 63 | [[ ], ''], 64 | [[ 'X-Usbl-Signature' => 'foo'], ''], 65 | [[ 'Foo' => '123', 'Bar' => '456' ], 'Foo=123&Bar=456'], 66 | [[ 'Foo' => ['b', 'a'], 'a' => 'bc' ], 'Foo=a&Foo=b&a=bc'], 67 | [[ 'Foo' => '', 'a' => 'b' ], 'Foo=&a=b'], 68 | ]; 69 | } 70 | 71 | /** 72 | * @dataProvider queryStringProvider 73 | */ 74 | public function testCreatesCanonicalizedQueryString($headers, $string) 75 | { 76 | // Make the method publicly callable 77 | $method = new \ReflectionMethod('Usabilla\Api\Signature\Signature', 'getCanonicalizedQueryString'); 78 | $method->setAccessible(true); 79 | // Create a request and replace the headers with the test headers 80 | $request = new Request('GET', 'http://www.example.com'); 81 | $request->getQuery()->replace($headers); 82 | $signature = $this->getMockBuilder('Usabilla\Api\Signature\Signature') 83 | ->getMockForAbstractClass(); 84 | $this->assertEquals($string, $method->invoke($signature, $request)); 85 | } 86 | 87 | public function testSignsRequestsWithContentHashCorrectly() 88 | { 89 | $request = $this->createRequest(); 90 | $contentHash = hash('sha256', 'foobar'); 91 | $request->setHeader('x-usbl-content-sha256', $contentHash); 92 | $this->signature->signRequest($request, DEFAULT_KEY, DEFAULT_SECRET); 93 | $context = $request->getQuery()->get('usbl.signature'); 94 | $this->assertNull($context); 95 | } 96 | 97 | private function createRequest() 98 | { 99 | return new Request('GET', 'https://data.usabilla.com', [ 100 | 'x-usbl-date' => 'Mon, 09 Sep 2011 23:36:00 GMT', 101 | 'Host' => 'foo.com' 102 | ]); 103 | } 104 | } --------------------------------------------------------------------------------