├── .gitignore ├── LICENSE ├── README.md ├── composer.json ├── composer.lock ├── config └── analytics.php ├── database └── migrations │ └── 2015_07_27_000000_create_analytcs_visits_table.php ├── gulpfile.js ├── package.json ├── resources ├── assets │ └── analytics.js ├── lang │ ├── en │ │ └── messages.php │ └── pt-BR │ │ └── messages.php └── views │ └── file.blade.php ├── screenshot.png └── src ├── Http ├── Controllers │ └── AnalyticsController.php └── routes.php ├── Models └── Visit.php ├── Providers └── AnalyticsServiceProvider.php ├── Services ├── GetByHours.php ├── GetParams.php └── Visits │ ├── CreateVisit.php │ └── GetVisitByPeriod.php └── Support └── helpers.php /.gitignore: -------------------------------------------------------------------------------- 1 | composer.phar 2 | composer.lock 3 | vendor/ 4 | .idea 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 baconfy 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 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Laravel Analytcs 2 | 3 | 4 | ## How to install 5 | 6 | ```shell 7 | composer require baconfy/laravel-analytics 8 | ``` 9 | 10 | config/app.php 11 | 12 | ```php 13 | ... 14 | 'providers' => [ 15 | Rdehnhardt\Analytics\Providers\AnalyticsServiceProvider::class, 16 | ], 17 | ... 18 | ``` 19 | 20 | ## Execute 21 | 22 | ```shell 23 | php artisan migrate 24 | 25 | php artisan vendor:publish 26 | ``` 27 | 28 | ## In html pages 29 | 30 | ```html 31 | 43 | ``` 44 | 45 | ## Route 46 | 47 | ``` 48 | /analytics/visits/Y-m-d/Y-m-d 49 | 50 | Ex: 51 | 52 | /analytics/visits/2015-07-27/2015-07-27 53 | 54 | show 55 | 56 | Hora,Visitas,Únicas 57 | 00:00,1,1 58 | 01:00,2,1 59 | 02:00,3,1 60 | 03:00,4,1 61 | 04:00,5,1 62 | 05:00,7,1 63 | 06:00,1,1 64 | 07:00,4,1 65 | 08:00,6,1 66 | 09:00,2,1 67 | 10:00,3,1 68 | 11:00,3,1 69 | 12:00,3,1 70 | 13:00,15,1 71 | 14:00,15,1 72 | ``` 73 | 74 | ## Using HighCharts 75 | 76 | ```html 77 |
78 | 79 | 93 | ``` 94 | 95 | ![alt text](https://raw.githubusercontent.com/rdehnhardt/laravel-analytics/master/screenshot.png "ScreenShot") 96 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rdehnhardt/laravel-analytics", 3 | "type": "library", 4 | "license": "MIT", 5 | "description": "Analytcs for Laravel", 6 | "authors": [ 7 | { 8 | "name": "Renato Dehnhardt", 9 | "email": "renatotkd@gmail.com" 10 | } 11 | ], 12 | "require": { 13 | "php": ">=5.5.0", 14 | "nesbot/carbon": "~1.0", 15 | "illuminate/support": "~5.2|~6.0" 16 | }, 17 | "require-dev": { 18 | "phpunit/phpunit": "~4.0", 19 | "phpspec/phpspec": "~2.1" 20 | }, 21 | "autoload": { 22 | "files": [ 23 | "src/Support/helpers.php" 24 | ], 25 | "psr-4": { 26 | "Rdehnhardt\\Analytics\\": "src/" 27 | } 28 | }, 29 | "minimum-stability": "stable" 30 | } 31 | -------------------------------------------------------------------------------- /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": "c94e1b5321d676ed65f36b7096fbb79b", 8 | "packages": [ 9 | { 10 | "name": "nesbot/carbon", 11 | "version": "1.20.0", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/briannesbitt/Carbon.git", 15 | "reference": "bfd3eaba109c9a2405c92174c8e17f20c2b9caf3" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/bfd3eaba109c9a2405c92174c8e17f20c2b9caf3", 20 | "reference": "bfd3eaba109c9a2405c92174c8e17f20c2b9caf3", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "php": ">=5.3.0", 25 | "symfony/translation": "~2.6|~3.0" 26 | }, 27 | "require-dev": { 28 | "phpunit/phpunit": "~4.0" 29 | }, 30 | "type": "library", 31 | "autoload": { 32 | "psr-0": { 33 | "Carbon": "src" 34 | } 35 | }, 36 | "notification-url": "https://packagist.org/downloads/", 37 | "license": [ 38 | "MIT" 39 | ], 40 | "authors": [ 41 | { 42 | "name": "Brian Nesbitt", 43 | "email": "brian@nesbot.com", 44 | "homepage": "http://nesbot.com" 45 | } 46 | ], 47 | "description": "A simple API extension for DateTime.", 48 | "homepage": "http://carbon.nesbot.com", 49 | "keywords": [ 50 | "date", 51 | "datetime", 52 | "time" 53 | ], 54 | "time": "2015-06-25 04:19:39" 55 | }, 56 | { 57 | "name": "symfony/translation", 58 | "version": "dev-master", 59 | "source": { 60 | "type": "git", 61 | "url": "https://github.com/symfony/Translation.git", 62 | "reference": "d049b8bb7085f2d8b413be00336acba3ceceadd4" 63 | }, 64 | "dist": { 65 | "type": "zip", 66 | "url": "https://api.github.com/repos/symfony/Translation/zipball/d049b8bb7085f2d8b413be00336acba3ceceadd4", 67 | "reference": "d049b8bb7085f2d8b413be00336acba3ceceadd4", 68 | "shasum": "" 69 | }, 70 | "require": { 71 | "php": ">=5.5.9" 72 | }, 73 | "conflict": { 74 | "symfony/config": "<2.8" 75 | }, 76 | "require-dev": { 77 | "psr/log": "~1.0", 78 | "symfony/config": "~2.8|~3.0", 79 | "symfony/intl": "~2.8|~3.0", 80 | "symfony/phpunit-bridge": "~2.8|~3.0", 81 | "symfony/yaml": "~2.8|~3.0" 82 | }, 83 | "suggest": { 84 | "psr/log": "To use logging capability in translator", 85 | "symfony/config": "", 86 | "symfony/yaml": "" 87 | }, 88 | "type": "library", 89 | "extra": { 90 | "branch-alias": { 91 | "dev-master": "3.0-dev" 92 | } 93 | }, 94 | "autoload": { 95 | "psr-4": { 96 | "Symfony\\Component\\Translation\\": "" 97 | } 98 | }, 99 | "notification-url": "https://packagist.org/downloads/", 100 | "license": [ 101 | "MIT" 102 | ], 103 | "authors": [ 104 | { 105 | "name": "Fabien Potencier", 106 | "email": "fabien@symfony.com" 107 | }, 108 | { 109 | "name": "Symfony Community", 110 | "homepage": "https://symfony.com/contributors" 111 | } 112 | ], 113 | "description": "Symfony Translation Component", 114 | "homepage": "https://symfony.com", 115 | "time": "2015-07-10 04:29:01" 116 | } 117 | ], 118 | "packages-dev": [ 119 | { 120 | "name": "doctrine/instantiator", 121 | "version": "dev-master", 122 | "source": { 123 | "type": "git", 124 | "url": "https://github.com/doctrine/instantiator.git", 125 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" 126 | }, 127 | "dist": { 128 | "type": "zip", 129 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", 130 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", 131 | "shasum": "" 132 | }, 133 | "require": { 134 | "php": ">=5.3,<8.0-DEV" 135 | }, 136 | "require-dev": { 137 | "athletic/athletic": "~0.1.8", 138 | "ext-pdo": "*", 139 | "ext-phar": "*", 140 | "phpunit/phpunit": "~4.0", 141 | "squizlabs/php_codesniffer": "~2.0" 142 | }, 143 | "type": "library", 144 | "extra": { 145 | "branch-alias": { 146 | "dev-master": "1.0.x-dev" 147 | } 148 | }, 149 | "autoload": { 150 | "psr-4": { 151 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" 152 | } 153 | }, 154 | "notification-url": "https://packagist.org/downloads/", 155 | "license": [ 156 | "MIT" 157 | ], 158 | "authors": [ 159 | { 160 | "name": "Marco Pivetta", 161 | "email": "ocramius@gmail.com", 162 | "homepage": "http://ocramius.github.com/" 163 | } 164 | ], 165 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 166 | "homepage": "https://github.com/doctrine/instantiator", 167 | "keywords": [ 168 | "constructor", 169 | "instantiate" 170 | ], 171 | "time": "2015-06-14 21:17:01" 172 | }, 173 | { 174 | "name": "phpdocumentor/reflection-docblock", 175 | "version": "2.0.4", 176 | "source": { 177 | "type": "git", 178 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", 179 | "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8" 180 | }, 181 | "dist": { 182 | "type": "zip", 183 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8", 184 | "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8", 185 | "shasum": "" 186 | }, 187 | "require": { 188 | "php": ">=5.3.3" 189 | }, 190 | "require-dev": { 191 | "phpunit/phpunit": "~4.0" 192 | }, 193 | "suggest": { 194 | "dflydev/markdown": "~1.0", 195 | "erusev/parsedown": "~1.0" 196 | }, 197 | "type": "library", 198 | "extra": { 199 | "branch-alias": { 200 | "dev-master": "2.0.x-dev" 201 | } 202 | }, 203 | "autoload": { 204 | "psr-0": { 205 | "phpDocumentor": [ 206 | "src/" 207 | ] 208 | } 209 | }, 210 | "notification-url": "https://packagist.org/downloads/", 211 | "license": [ 212 | "MIT" 213 | ], 214 | "authors": [ 215 | { 216 | "name": "Mike van Riel", 217 | "email": "mike.vanriel@naenius.com" 218 | } 219 | ], 220 | "time": "2015-02-03 12:10:50" 221 | }, 222 | { 223 | "name": "phpspec/php-diff", 224 | "version": "v1.0.2", 225 | "source": { 226 | "type": "git", 227 | "url": "https://github.com/phpspec/php-diff.git", 228 | "reference": "30e103d19519fe678ae64a60d77884ef3d71b28a" 229 | }, 230 | "dist": { 231 | "type": "zip", 232 | "url": "https://api.github.com/repos/phpspec/php-diff/zipball/30e103d19519fe678ae64a60d77884ef3d71b28a", 233 | "reference": "30e103d19519fe678ae64a60d77884ef3d71b28a", 234 | "shasum": "" 235 | }, 236 | "type": "library", 237 | "autoload": { 238 | "psr-0": { 239 | "Diff": "lib/" 240 | } 241 | }, 242 | "notification-url": "https://packagist.org/downloads/", 243 | "license": [ 244 | "BSD-3-Clause" 245 | ], 246 | "authors": [ 247 | { 248 | "name": "Chris Boulton", 249 | "homepage": "http://github.com/chrisboulton", 250 | "role": "Original developer" 251 | } 252 | ], 253 | "description": "A comprehensive library for generating differences between two hashable objects (strings or arrays).", 254 | "time": "2013-11-01 13:02:21" 255 | }, 256 | { 257 | "name": "phpspec/phpspec", 258 | "version": "2.3.0-beta", 259 | "source": { 260 | "type": "git", 261 | "url": "https://github.com/phpspec/phpspec.git", 262 | "reference": "5858b8b111023248ff8e9fc50e914c54118cd3ff" 263 | }, 264 | "dist": { 265 | "type": "zip", 266 | "url": "https://api.github.com/repos/phpspec/phpspec/zipball/5858b8b111023248ff8e9fc50e914c54118cd3ff", 267 | "reference": "5858b8b111023248ff8e9fc50e914c54118cd3ff", 268 | "shasum": "" 269 | }, 270 | "require": { 271 | "doctrine/instantiator": "^1.0.1", 272 | "php": ">=5.3.3", 273 | "phpspec/php-diff": "~1.0.0", 274 | "phpspec/prophecy": "~1.4", 275 | "sebastian/exporter": "~1.0", 276 | "symfony/console": "~2.3", 277 | "symfony/event-dispatcher": "~2.1", 278 | "symfony/finder": "~2.1", 279 | "symfony/process": "~2.1", 280 | "symfony/yaml": "~2.1" 281 | }, 282 | "require-dev": { 283 | "behat/behat": "^3.0.11", 284 | "bossa/phpspec2-expect": "~1.0", 285 | "phpunit/phpunit": "~4.4", 286 | "symfony/filesystem": "~2.1", 287 | "symfony/process": "~2.1" 288 | }, 289 | "suggest": { 290 | "phpspec/nyan-formatters": "~1.0 – Adds Nyan formatters" 291 | }, 292 | "bin": [ 293 | "bin/phpspec" 294 | ], 295 | "type": "library", 296 | "extra": { 297 | "branch-alias": { 298 | "dev-master": "2.2.x-dev" 299 | } 300 | }, 301 | "autoload": { 302 | "psr-0": { 303 | "PhpSpec": "src/" 304 | } 305 | }, 306 | "notification-url": "https://packagist.org/downloads/", 307 | "license": [ 308 | "MIT" 309 | ], 310 | "authors": [ 311 | { 312 | "name": "Konstantin Kudryashov", 313 | "email": "ever.zet@gmail.com", 314 | "homepage": "http://everzet.com" 315 | }, 316 | { 317 | "name": "Marcello Duarte", 318 | "homepage": "http://marcelloduarte.net/" 319 | } 320 | ], 321 | "description": "Specification-oriented BDD framework for PHP 5.3+", 322 | "homepage": "http://phpspec.net/", 323 | "keywords": [ 324 | "BDD", 325 | "SpecBDD", 326 | "TDD", 327 | "spec", 328 | "specification", 329 | "testing", 330 | "tests" 331 | ], 332 | "time": "2015-07-04 10:12:31" 333 | }, 334 | { 335 | "name": "phpspec/prophecy", 336 | "version": "dev-master", 337 | "source": { 338 | "type": "git", 339 | "url": "https://github.com/phpspec/prophecy.git", 340 | "reference": "5700f75b23b0dd3495c0f495fe33a5e6717ee160" 341 | }, 342 | "dist": { 343 | "type": "zip", 344 | "url": "https://api.github.com/repos/phpspec/prophecy/zipball/5700f75b23b0dd3495c0f495fe33a5e6717ee160", 345 | "reference": "5700f75b23b0dd3495c0f495fe33a5e6717ee160", 346 | "shasum": "" 347 | }, 348 | "require": { 349 | "doctrine/instantiator": "^1.0.2", 350 | "phpdocumentor/reflection-docblock": "~2.0", 351 | "sebastian/comparator": "~1.1" 352 | }, 353 | "require-dev": { 354 | "phpspec/phpspec": "~2.0" 355 | }, 356 | "type": "library", 357 | "extra": { 358 | "branch-alias": { 359 | "dev-master": "1.4.x-dev" 360 | } 361 | }, 362 | "autoload": { 363 | "psr-0": { 364 | "Prophecy\\": "src/" 365 | } 366 | }, 367 | "notification-url": "https://packagist.org/downloads/", 368 | "license": [ 369 | "MIT" 370 | ], 371 | "authors": [ 372 | { 373 | "name": "Konstantin Kudryashov", 374 | "email": "ever.zet@gmail.com", 375 | "homepage": "http://everzet.com" 376 | }, 377 | { 378 | "name": "Marcello Duarte", 379 | "email": "marcello.duarte@gmail.com" 380 | } 381 | ], 382 | "description": "Highly opinionated mocking framework for PHP 5.3+", 383 | "homepage": "https://github.com/phpspec/prophecy", 384 | "keywords": [ 385 | "Double", 386 | "Dummy", 387 | "fake", 388 | "mock", 389 | "spy", 390 | "stub" 391 | ], 392 | "time": "2015-06-30 10:26:46" 393 | }, 394 | { 395 | "name": "phpunit/php-code-coverage", 396 | "version": "dev-master", 397 | "source": { 398 | "type": "git", 399 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 400 | "reference": "df29d420311aa94ed1eb26560b573710f3603b2d" 401 | }, 402 | "dist": { 403 | "type": "zip", 404 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/df29d420311aa94ed1eb26560b573710f3603b2d", 405 | "reference": "df29d420311aa94ed1eb26560b573710f3603b2d", 406 | "shasum": "" 407 | }, 408 | "require": { 409 | "php": ">=5.3.3", 410 | "phpunit/php-file-iterator": "~1.3", 411 | "phpunit/php-text-template": "~1.2", 412 | "phpunit/php-token-stream": "~1.3", 413 | "sebastian/environment": "~1.3", 414 | "sebastian/version": "~1.0" 415 | }, 416 | "require-dev": { 417 | "ext-xdebug": ">=2.1.4", 418 | "phpunit/phpunit": "~4" 419 | }, 420 | "suggest": { 421 | "ext-dom": "*", 422 | "ext-xdebug": ">=2.2.1", 423 | "ext-xmlwriter": "*" 424 | }, 425 | "type": "library", 426 | "extra": { 427 | "branch-alias": { 428 | "dev-master": "2.2.x-dev" 429 | } 430 | }, 431 | "autoload": { 432 | "classmap": [ 433 | "src/" 434 | ] 435 | }, 436 | "notification-url": "https://packagist.org/downloads/", 437 | "license": [ 438 | "BSD-3-Clause" 439 | ], 440 | "authors": [ 441 | { 442 | "name": "Sebastian Bergmann", 443 | "email": "sb@sebastian-bergmann.de", 444 | "role": "lead" 445 | } 446 | ], 447 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 448 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 449 | "keywords": [ 450 | "coverage", 451 | "testing", 452 | "xunit" 453 | ], 454 | "time": "2015-07-27 14:08:10" 455 | }, 456 | { 457 | "name": "phpunit/php-file-iterator", 458 | "version": "dev-master", 459 | "source": { 460 | "type": "git", 461 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 462 | "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0" 463 | }, 464 | "dist": { 465 | "type": "zip", 466 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0", 467 | "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0", 468 | "shasum": "" 469 | }, 470 | "require": { 471 | "php": ">=5.3.3" 472 | }, 473 | "type": "library", 474 | "extra": { 475 | "branch-alias": { 476 | "dev-master": "1.4.x-dev" 477 | } 478 | }, 479 | "autoload": { 480 | "classmap": [ 481 | "src/" 482 | ] 483 | }, 484 | "notification-url": "https://packagist.org/downloads/", 485 | "license": [ 486 | "BSD-3-Clause" 487 | ], 488 | "authors": [ 489 | { 490 | "name": "Sebastian Bergmann", 491 | "email": "sb@sebastian-bergmann.de", 492 | "role": "lead" 493 | } 494 | ], 495 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 496 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 497 | "keywords": [ 498 | "filesystem", 499 | "iterator" 500 | ], 501 | "time": "2015-06-21 13:08:43" 502 | }, 503 | { 504 | "name": "phpunit/php-text-template", 505 | "version": "1.2.1", 506 | "source": { 507 | "type": "git", 508 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 509 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" 510 | }, 511 | "dist": { 512 | "type": "zip", 513 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 514 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 515 | "shasum": "" 516 | }, 517 | "require": { 518 | "php": ">=5.3.3" 519 | }, 520 | "type": "library", 521 | "autoload": { 522 | "classmap": [ 523 | "src/" 524 | ] 525 | }, 526 | "notification-url": "https://packagist.org/downloads/", 527 | "license": [ 528 | "BSD-3-Clause" 529 | ], 530 | "authors": [ 531 | { 532 | "name": "Sebastian Bergmann", 533 | "email": "sebastian@phpunit.de", 534 | "role": "lead" 535 | } 536 | ], 537 | "description": "Simple template engine.", 538 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 539 | "keywords": [ 540 | "template" 541 | ], 542 | "time": "2015-06-21 13:50:34" 543 | }, 544 | { 545 | "name": "phpunit/php-timer", 546 | "version": "dev-master", 547 | "source": { 548 | "type": "git", 549 | "url": "https://github.com/sebastianbergmann/php-timer.git", 550 | "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b" 551 | }, 552 | "dist": { 553 | "type": "zip", 554 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3e82f4e9fc92665fafd9157568e4dcb01d014e5b", 555 | "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b", 556 | "shasum": "" 557 | }, 558 | "require": { 559 | "php": ">=5.3.3" 560 | }, 561 | "type": "library", 562 | "autoload": { 563 | "classmap": [ 564 | "src/" 565 | ] 566 | }, 567 | "notification-url": "https://packagist.org/downloads/", 568 | "license": [ 569 | "BSD-3-Clause" 570 | ], 571 | "authors": [ 572 | { 573 | "name": "Sebastian Bergmann", 574 | "email": "sb@sebastian-bergmann.de", 575 | "role": "lead" 576 | } 577 | ], 578 | "description": "Utility class for timing", 579 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 580 | "keywords": [ 581 | "timer" 582 | ], 583 | "time": "2015-06-21 08:01:12" 584 | }, 585 | { 586 | "name": "phpunit/php-token-stream", 587 | "version": "dev-master", 588 | "source": { 589 | "type": "git", 590 | "url": "https://github.com/sebastianbergmann/php-token-stream.git", 591 | "reference": "7a9b0969488c3c54fd62b4d504b3ec758fd005d9" 592 | }, 593 | "dist": { 594 | "type": "zip", 595 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/7a9b0969488c3c54fd62b4d504b3ec758fd005d9", 596 | "reference": "7a9b0969488c3c54fd62b4d504b3ec758fd005d9", 597 | "shasum": "" 598 | }, 599 | "require": { 600 | "ext-tokenizer": "*", 601 | "php": ">=5.3.3" 602 | }, 603 | "require-dev": { 604 | "phpunit/phpunit": "~4.2" 605 | }, 606 | "type": "library", 607 | "extra": { 608 | "branch-alias": { 609 | "dev-master": "1.4-dev" 610 | } 611 | }, 612 | "autoload": { 613 | "classmap": [ 614 | "src/" 615 | ] 616 | }, 617 | "notification-url": "https://packagist.org/downloads/", 618 | "license": [ 619 | "BSD-3-Clause" 620 | ], 621 | "authors": [ 622 | { 623 | "name": "Sebastian Bergmann", 624 | "email": "sebastian@phpunit.de" 625 | } 626 | ], 627 | "description": "Wrapper around PHP's tokenizer extension.", 628 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/", 629 | "keywords": [ 630 | "tokenizer" 631 | ], 632 | "time": "2015-06-19 03:43:16" 633 | }, 634 | { 635 | "name": "phpunit/phpunit", 636 | "version": "4.8.x-dev", 637 | "source": { 638 | "type": "git", 639 | "url": "https://github.com/sebastianbergmann/phpunit.git", 640 | "reference": "21b64e299bc68a9fed8f5107794acee6f0b657fb" 641 | }, 642 | "dist": { 643 | "type": "zip", 644 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/21b64e299bc68a9fed8f5107794acee6f0b657fb", 645 | "reference": "21b64e299bc68a9fed8f5107794acee6f0b657fb", 646 | "shasum": "" 647 | }, 648 | "require": { 649 | "ext-dom": "*", 650 | "ext-json": "*", 651 | "ext-pcre": "*", 652 | "ext-reflection": "*", 653 | "ext-spl": "*", 654 | "php": ">=5.3.3", 655 | "phpspec/prophecy": "~1.3,>=1.3.1", 656 | "phpunit/php-code-coverage": "~2.1", 657 | "phpunit/php-file-iterator": "~1.4", 658 | "phpunit/php-text-template": "~1.2", 659 | "phpunit/php-timer": ">=1.0.6", 660 | "phpunit/phpunit-mock-objects": "~2.3", 661 | "sebastian/comparator": "~1.1", 662 | "sebastian/diff": "~1.2", 663 | "sebastian/environment": "~1.3", 664 | "sebastian/exporter": "~1.2", 665 | "sebastian/global-state": "~1.0", 666 | "sebastian/version": "~1.0", 667 | "symfony/yaml": "~2.1|~3.0" 668 | }, 669 | "suggest": { 670 | "phpunit/php-invoker": "~1.1" 671 | }, 672 | "bin": [ 673 | "phpunit" 674 | ], 675 | "type": "library", 676 | "extra": { 677 | "branch-alias": { 678 | "dev-master": "4.8.x-dev" 679 | } 680 | }, 681 | "autoload": { 682 | "classmap": [ 683 | "src/" 684 | ] 685 | }, 686 | "notification-url": "https://packagist.org/downloads/", 687 | "license": [ 688 | "BSD-3-Clause" 689 | ], 690 | "authors": [ 691 | { 692 | "name": "Sebastian Bergmann", 693 | "email": "sebastian@phpunit.de", 694 | "role": "lead" 695 | } 696 | ], 697 | "description": "The PHP Unit Testing framework.", 698 | "homepage": "https://phpunit.de/", 699 | "keywords": [ 700 | "phpunit", 701 | "testing", 702 | "xunit" 703 | ], 704 | "time": "2015-07-26 12:57:56" 705 | }, 706 | { 707 | "name": "phpunit/phpunit-mock-objects", 708 | "version": "2.3.x-dev", 709 | "source": { 710 | "type": "git", 711 | "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", 712 | "reference": "18dfbcb81d05e2296c0bcddd4db96cade75e6f42" 713 | }, 714 | "dist": { 715 | "type": "zip", 716 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/18dfbcb81d05e2296c0bcddd4db96cade75e6f42", 717 | "reference": "18dfbcb81d05e2296c0bcddd4db96cade75e6f42", 718 | "shasum": "" 719 | }, 720 | "require": { 721 | "doctrine/instantiator": "~1.0,>=1.0.2", 722 | "php": ">=5.3.3", 723 | "phpunit/php-text-template": "~1.2", 724 | "sebastian/exporter": "~1.2" 725 | }, 726 | "require-dev": { 727 | "phpunit/phpunit": "~4.4" 728 | }, 729 | "suggest": { 730 | "ext-soap": "*" 731 | }, 732 | "type": "library", 733 | "extra": { 734 | "branch-alias": { 735 | "dev-master": "2.3.x-dev" 736 | } 737 | }, 738 | "autoload": { 739 | "classmap": [ 740 | "src/" 741 | ] 742 | }, 743 | "notification-url": "https://packagist.org/downloads/", 744 | "license": [ 745 | "BSD-3-Clause" 746 | ], 747 | "authors": [ 748 | { 749 | "name": "Sebastian Bergmann", 750 | "email": "sb@sebastian-bergmann.de", 751 | "role": "lead" 752 | } 753 | ], 754 | "description": "Mock Object library for PHPUnit", 755 | "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", 756 | "keywords": [ 757 | "mock", 758 | "xunit" 759 | ], 760 | "time": "2015-07-10 06:54:24" 761 | }, 762 | { 763 | "name": "sebastian/comparator", 764 | "version": "dev-master", 765 | "source": { 766 | "type": "git", 767 | "url": "https://github.com/sebastianbergmann/comparator.git", 768 | "reference": "937efb279bd37a375bcadf584dec0726f84dbf22" 769 | }, 770 | "dist": { 771 | "type": "zip", 772 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22", 773 | "reference": "937efb279bd37a375bcadf584dec0726f84dbf22", 774 | "shasum": "" 775 | }, 776 | "require": { 777 | "php": ">=5.3.3", 778 | "sebastian/diff": "~1.2", 779 | "sebastian/exporter": "~1.2" 780 | }, 781 | "require-dev": { 782 | "phpunit/phpunit": "~4.4" 783 | }, 784 | "type": "library", 785 | "extra": { 786 | "branch-alias": { 787 | "dev-master": "1.2.x-dev" 788 | } 789 | }, 790 | "autoload": { 791 | "classmap": [ 792 | "src/" 793 | ] 794 | }, 795 | "notification-url": "https://packagist.org/downloads/", 796 | "license": [ 797 | "BSD-3-Clause" 798 | ], 799 | "authors": [ 800 | { 801 | "name": "Jeff Welch", 802 | "email": "whatthejeff@gmail.com" 803 | }, 804 | { 805 | "name": "Volker Dusch", 806 | "email": "github@wallbash.com" 807 | }, 808 | { 809 | "name": "Bernhard Schussek", 810 | "email": "bschussek@2bepublished.at" 811 | }, 812 | { 813 | "name": "Sebastian Bergmann", 814 | "email": "sebastian@phpunit.de" 815 | } 816 | ], 817 | "description": "Provides the functionality to compare PHP values for equality", 818 | "homepage": "http://www.github.com/sebastianbergmann/comparator", 819 | "keywords": [ 820 | "comparator", 821 | "compare", 822 | "equality" 823 | ], 824 | "time": "2015-07-26 15:48:44" 825 | }, 826 | { 827 | "name": "sebastian/diff", 828 | "version": "dev-master", 829 | "source": { 830 | "type": "git", 831 | "url": "https://github.com/sebastianbergmann/diff.git", 832 | "reference": "6899b3e33bfbd386d88b5eea5f65f563e8793051" 833 | }, 834 | "dist": { 835 | "type": "zip", 836 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/6899b3e33bfbd386d88b5eea5f65f563e8793051", 837 | "reference": "6899b3e33bfbd386d88b5eea5f65f563e8793051", 838 | "shasum": "" 839 | }, 840 | "require": { 841 | "php": ">=5.3.3" 842 | }, 843 | "require-dev": { 844 | "phpunit/phpunit": "~4.2" 845 | }, 846 | "type": "library", 847 | "extra": { 848 | "branch-alias": { 849 | "dev-master": "1.3-dev" 850 | } 851 | }, 852 | "autoload": { 853 | "classmap": [ 854 | "src/" 855 | ] 856 | }, 857 | "notification-url": "https://packagist.org/downloads/", 858 | "license": [ 859 | "BSD-3-Clause" 860 | ], 861 | "authors": [ 862 | { 863 | "name": "Kore Nordmann", 864 | "email": "mail@kore-nordmann.de" 865 | }, 866 | { 867 | "name": "Sebastian Bergmann", 868 | "email": "sebastian@phpunit.de" 869 | } 870 | ], 871 | "description": "Diff implementation", 872 | "homepage": "http://www.github.com/sebastianbergmann/diff", 873 | "keywords": [ 874 | "diff" 875 | ], 876 | "time": "2015-06-22 14:15:55" 877 | }, 878 | { 879 | "name": "sebastian/environment", 880 | "version": "dev-master", 881 | "source": { 882 | "type": "git", 883 | "url": "https://github.com/sebastianbergmann/environment.git", 884 | "reference": "70c3ba9398826b0d0117c2e9f1922c3bc47644ce" 885 | }, 886 | "dist": { 887 | "type": "zip", 888 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/70c3ba9398826b0d0117c2e9f1922c3bc47644ce", 889 | "reference": "70c3ba9398826b0d0117c2e9f1922c3bc47644ce", 890 | "shasum": "" 891 | }, 892 | "require": { 893 | "php": ">=5.3.3" 894 | }, 895 | "require-dev": { 896 | "phpunit/phpunit": "~4.4" 897 | }, 898 | "type": "library", 899 | "extra": { 900 | "branch-alias": { 901 | "dev-master": "1.3.x-dev" 902 | } 903 | }, 904 | "autoload": { 905 | "classmap": [ 906 | "src/" 907 | ] 908 | }, 909 | "notification-url": "https://packagist.org/downloads/", 910 | "license": [ 911 | "BSD-3-Clause" 912 | ], 913 | "authors": [ 914 | { 915 | "name": "Sebastian Bergmann", 916 | "email": "sebastian@phpunit.de" 917 | } 918 | ], 919 | "description": "Provides functionality to handle HHVM/PHP environments", 920 | "homepage": "http://www.github.com/sebastianbergmann/environment", 921 | "keywords": [ 922 | "Xdebug", 923 | "environment", 924 | "hhvm" 925 | ], 926 | "time": "2015-07-26 09:06:39" 927 | }, 928 | { 929 | "name": "sebastian/exporter", 930 | "version": "dev-master", 931 | "source": { 932 | "type": "git", 933 | "url": "https://github.com/sebastianbergmann/exporter.git", 934 | "reference": "7ae5513327cb536431847bcc0c10edba2701064e" 935 | }, 936 | "dist": { 937 | "type": "zip", 938 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/7ae5513327cb536431847bcc0c10edba2701064e", 939 | "reference": "7ae5513327cb536431847bcc0c10edba2701064e", 940 | "shasum": "" 941 | }, 942 | "require": { 943 | "php": ">=5.3.3", 944 | "sebastian/recursion-context": "~1.0" 945 | }, 946 | "require-dev": { 947 | "phpunit/phpunit": "~4.4" 948 | }, 949 | "type": "library", 950 | "extra": { 951 | "branch-alias": { 952 | "dev-master": "1.2.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": "Volker Dusch", 971 | "email": "github@wallbash.com" 972 | }, 973 | { 974 | "name": "Bernhard Schussek", 975 | "email": "bschussek@2bepublished.at" 976 | }, 977 | { 978 | "name": "Sebastian Bergmann", 979 | "email": "sebastian@phpunit.de" 980 | }, 981 | { 982 | "name": "Adam Harvey", 983 | "email": "aharvey@php.net" 984 | } 985 | ], 986 | "description": "Provides the functionality to export PHP variables for visualization", 987 | "homepage": "http://www.github.com/sebastianbergmann/exporter", 988 | "keywords": [ 989 | "export", 990 | "exporter" 991 | ], 992 | "time": "2015-06-21 07:55:53" 993 | }, 994 | { 995 | "name": "sebastian/global-state", 996 | "version": "dev-master", 997 | "source": { 998 | "type": "git", 999 | "url": "https://github.com/sebastianbergmann/global-state.git", 1000 | "reference": "23af31f402993cfd94e99cbc4b782e9a78eb0e97" 1001 | }, 1002 | "dist": { 1003 | "type": "zip", 1004 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/23af31f402993cfd94e99cbc4b782e9a78eb0e97", 1005 | "reference": "23af31f402993cfd94e99cbc4b782e9a78eb0e97", 1006 | "shasum": "" 1007 | }, 1008 | "require": { 1009 | "php": ">=5.3.3" 1010 | }, 1011 | "require-dev": { 1012 | "phpunit/phpunit": "~4.2" 1013 | }, 1014 | "suggest": { 1015 | "ext-uopz": "*" 1016 | }, 1017 | "type": "library", 1018 | "extra": { 1019 | "branch-alias": { 1020 | "dev-master": "1.0-dev" 1021 | } 1022 | }, 1023 | "autoload": { 1024 | "classmap": [ 1025 | "src/" 1026 | ] 1027 | }, 1028 | "notification-url": "https://packagist.org/downloads/", 1029 | "license": [ 1030 | "BSD-3-Clause" 1031 | ], 1032 | "authors": [ 1033 | { 1034 | "name": "Sebastian Bergmann", 1035 | "email": "sebastian@phpunit.de" 1036 | } 1037 | ], 1038 | "description": "Snapshotting of global state", 1039 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 1040 | "keywords": [ 1041 | "global state" 1042 | ], 1043 | "time": "2015-06-21 15:11:22" 1044 | }, 1045 | { 1046 | "name": "sebastian/recursion-context", 1047 | "version": "dev-master", 1048 | "source": { 1049 | "type": "git", 1050 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 1051 | "reference": "994d4a811bafe801fb06dccbee797863ba2792ba" 1052 | }, 1053 | "dist": { 1054 | "type": "zip", 1055 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/994d4a811bafe801fb06dccbee797863ba2792ba", 1056 | "reference": "994d4a811bafe801fb06dccbee797863ba2792ba", 1057 | "shasum": "" 1058 | }, 1059 | "require": { 1060 | "php": ">=5.3.3" 1061 | }, 1062 | "require-dev": { 1063 | "phpunit/phpunit": "~4.4" 1064 | }, 1065 | "type": "library", 1066 | "extra": { 1067 | "branch-alias": { 1068 | "dev-master": "1.0.x-dev" 1069 | } 1070 | }, 1071 | "autoload": { 1072 | "classmap": [ 1073 | "src/" 1074 | ] 1075 | }, 1076 | "notification-url": "https://packagist.org/downloads/", 1077 | "license": [ 1078 | "BSD-3-Clause" 1079 | ], 1080 | "authors": [ 1081 | { 1082 | "name": "Jeff Welch", 1083 | "email": "whatthejeff@gmail.com" 1084 | }, 1085 | { 1086 | "name": "Sebastian Bergmann", 1087 | "email": "sebastian@phpunit.de" 1088 | }, 1089 | { 1090 | "name": "Adam Harvey", 1091 | "email": "aharvey@php.net" 1092 | } 1093 | ], 1094 | "description": "Provides functionality to recursively process PHP variables", 1095 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context", 1096 | "time": "2015-06-21 08:04:50" 1097 | }, 1098 | { 1099 | "name": "sebastian/version", 1100 | "version": "1.0.6", 1101 | "source": { 1102 | "type": "git", 1103 | "url": "https://github.com/sebastianbergmann/version.git", 1104 | "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" 1105 | }, 1106 | "dist": { 1107 | "type": "zip", 1108 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", 1109 | "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", 1110 | "shasum": "" 1111 | }, 1112 | "type": "library", 1113 | "autoload": { 1114 | "classmap": [ 1115 | "src/" 1116 | ] 1117 | }, 1118 | "notification-url": "https://packagist.org/downloads/", 1119 | "license": [ 1120 | "BSD-3-Clause" 1121 | ], 1122 | "authors": [ 1123 | { 1124 | "name": "Sebastian Bergmann", 1125 | "email": "sebastian@phpunit.de", 1126 | "role": "lead" 1127 | } 1128 | ], 1129 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 1130 | "homepage": "https://github.com/sebastianbergmann/version", 1131 | "time": "2015-06-21 13:59:46" 1132 | }, 1133 | { 1134 | "name": "symfony/console", 1135 | "version": "2.8.x-dev", 1136 | "source": { 1137 | "type": "git", 1138 | "url": "https://github.com/symfony/Console.git", 1139 | "reference": "575782770a015042d2fe34f1388d5073bde784bd" 1140 | }, 1141 | "dist": { 1142 | "type": "zip", 1143 | "url": "https://api.github.com/repos/symfony/Console/zipball/575782770a015042d2fe34f1388d5073bde784bd", 1144 | "reference": "575782770a015042d2fe34f1388d5073bde784bd", 1145 | "shasum": "" 1146 | }, 1147 | "require": { 1148 | "php": ">=5.3.9" 1149 | }, 1150 | "require-dev": { 1151 | "psr/log": "~1.0", 1152 | "symfony/event-dispatcher": "~2.1|~3.0.0", 1153 | "symfony/phpunit-bridge": "~2.7|~3.0.0", 1154 | "symfony/process": "~2.1|~3.0.0" 1155 | }, 1156 | "suggest": { 1157 | "psr/log": "For using the console logger", 1158 | "symfony/event-dispatcher": "", 1159 | "symfony/process": "" 1160 | }, 1161 | "type": "library", 1162 | "extra": { 1163 | "branch-alias": { 1164 | "dev-master": "2.8-dev" 1165 | } 1166 | }, 1167 | "autoload": { 1168 | "psr-4": { 1169 | "Symfony\\Component\\Console\\": "" 1170 | } 1171 | }, 1172 | "notification-url": "https://packagist.org/downloads/", 1173 | "license": [ 1174 | "MIT" 1175 | ], 1176 | "authors": [ 1177 | { 1178 | "name": "Fabien Potencier", 1179 | "email": "fabien@symfony.com" 1180 | }, 1181 | { 1182 | "name": "Symfony Community", 1183 | "homepage": "https://symfony.com/contributors" 1184 | } 1185 | ], 1186 | "description": "Symfony Console Component", 1187 | "homepage": "https://symfony.com", 1188 | "time": "2015-07-26 09:09:29" 1189 | }, 1190 | { 1191 | "name": "symfony/event-dispatcher", 1192 | "version": "2.8.x-dev", 1193 | "source": { 1194 | "type": "git", 1195 | "url": "https://github.com/symfony/EventDispatcher.git", 1196 | "reference": "d7246885b7fe4cb5a2786bda34362d2f0e40b730" 1197 | }, 1198 | "dist": { 1199 | "type": "zip", 1200 | "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/d7246885b7fe4cb5a2786bda34362d2f0e40b730", 1201 | "reference": "d7246885b7fe4cb5a2786bda34362d2f0e40b730", 1202 | "shasum": "" 1203 | }, 1204 | "require": { 1205 | "php": ">=5.3.9" 1206 | }, 1207 | "require-dev": { 1208 | "psr/log": "~1.0", 1209 | "symfony/config": "~2.0,>=2.0.5|~3.0.0", 1210 | "symfony/dependency-injection": "~2.6|~3.0.0", 1211 | "symfony/expression-language": "~2.6|~3.0.0", 1212 | "symfony/phpunit-bridge": "~2.7|~3.0.0", 1213 | "symfony/stopwatch": "~2.3|~3.0.0" 1214 | }, 1215 | "suggest": { 1216 | "symfony/dependency-injection": "", 1217 | "symfony/http-kernel": "" 1218 | }, 1219 | "type": "library", 1220 | "extra": { 1221 | "branch-alias": { 1222 | "dev-master": "2.8-dev" 1223 | } 1224 | }, 1225 | "autoload": { 1226 | "psr-4": { 1227 | "Symfony\\Component\\EventDispatcher\\": "" 1228 | } 1229 | }, 1230 | "notification-url": "https://packagist.org/downloads/", 1231 | "license": [ 1232 | "MIT" 1233 | ], 1234 | "authors": [ 1235 | { 1236 | "name": "Fabien Potencier", 1237 | "email": "fabien@symfony.com" 1238 | }, 1239 | { 1240 | "name": "Symfony Community", 1241 | "homepage": "https://symfony.com/contributors" 1242 | } 1243 | ], 1244 | "description": "Symfony EventDispatcher Component", 1245 | "homepage": "https://symfony.com", 1246 | "time": "2015-06-24 15:32:32" 1247 | }, 1248 | { 1249 | "name": "symfony/finder", 1250 | "version": "2.8.x-dev", 1251 | "source": { 1252 | "type": "git", 1253 | "url": "https://github.com/symfony/Finder.git", 1254 | "reference": "8712d5e8c4ad65e6b936ed9b6a581e5e6a87fddf" 1255 | }, 1256 | "dist": { 1257 | "type": "zip", 1258 | "url": "https://api.github.com/repos/symfony/Finder/zipball/8712d5e8c4ad65e6b936ed9b6a581e5e6a87fddf", 1259 | "reference": "8712d5e8c4ad65e6b936ed9b6a581e5e6a87fddf", 1260 | "shasum": "" 1261 | }, 1262 | "require": { 1263 | "php": ">=5.3.9" 1264 | }, 1265 | "require-dev": { 1266 | "symfony/phpunit-bridge": "~2.7|~3.0.0" 1267 | }, 1268 | "type": "library", 1269 | "extra": { 1270 | "branch-alias": { 1271 | "dev-master": "2.8-dev" 1272 | } 1273 | }, 1274 | "autoload": { 1275 | "psr-4": { 1276 | "Symfony\\Component\\Finder\\": "" 1277 | } 1278 | }, 1279 | "notification-url": "https://packagist.org/downloads/", 1280 | "license": [ 1281 | "MIT" 1282 | ], 1283 | "authors": [ 1284 | { 1285 | "name": "Fabien Potencier", 1286 | "email": "fabien@symfony.com" 1287 | }, 1288 | { 1289 | "name": "Symfony Community", 1290 | "homepage": "https://symfony.com/contributors" 1291 | } 1292 | ], 1293 | "description": "Symfony Finder Component", 1294 | "homepage": "https://symfony.com", 1295 | "time": "2015-07-09 16:11:14" 1296 | }, 1297 | { 1298 | "name": "symfony/process", 1299 | "version": "2.8.x-dev", 1300 | "source": { 1301 | "type": "git", 1302 | "url": "https://github.com/symfony/Process.git", 1303 | "reference": "25d74c90d79e66905013714d8d188e4ccb5ff466" 1304 | }, 1305 | "dist": { 1306 | "type": "zip", 1307 | "url": "https://api.github.com/repos/symfony/Process/zipball/25d74c90d79e66905013714d8d188e4ccb5ff466", 1308 | "reference": "25d74c90d79e66905013714d8d188e4ccb5ff466", 1309 | "shasum": "" 1310 | }, 1311 | "require": { 1312 | "php": ">=5.3.9" 1313 | }, 1314 | "require-dev": { 1315 | "symfony/phpunit-bridge": "~2.7|~3.0.0" 1316 | }, 1317 | "type": "library", 1318 | "extra": { 1319 | "branch-alias": { 1320 | "dev-master": "2.8-dev" 1321 | } 1322 | }, 1323 | "autoload": { 1324 | "psr-4": { 1325 | "Symfony\\Component\\Process\\": "" 1326 | } 1327 | }, 1328 | "notification-url": "https://packagist.org/downloads/", 1329 | "license": [ 1330 | "MIT" 1331 | ], 1332 | "authors": [ 1333 | { 1334 | "name": "Fabien Potencier", 1335 | "email": "fabien@symfony.com" 1336 | }, 1337 | { 1338 | "name": "Symfony Community", 1339 | "homepage": "https://symfony.com/contributors" 1340 | } 1341 | ], 1342 | "description": "Symfony Process Component", 1343 | "homepage": "https://symfony.com", 1344 | "time": "2015-07-01 14:16:54" 1345 | }, 1346 | { 1347 | "name": "symfony/yaml", 1348 | "version": "2.8.x-dev", 1349 | "source": { 1350 | "type": "git", 1351 | "url": "https://github.com/symfony/Yaml.git", 1352 | "reference": "b7bf092bc2b3af532ef916805e214febec89ae4b" 1353 | }, 1354 | "dist": { 1355 | "type": "zip", 1356 | "url": "https://api.github.com/repos/symfony/Yaml/zipball/b7bf092bc2b3af532ef916805e214febec89ae4b", 1357 | "reference": "b7bf092bc2b3af532ef916805e214febec89ae4b", 1358 | "shasum": "" 1359 | }, 1360 | "require": { 1361 | "php": ">=5.3.9" 1362 | }, 1363 | "require-dev": { 1364 | "symfony/phpunit-bridge": "~2.7|~3.0.0" 1365 | }, 1366 | "type": "library", 1367 | "extra": { 1368 | "branch-alias": { 1369 | "dev-master": "2.8-dev" 1370 | } 1371 | }, 1372 | "autoload": { 1373 | "psr-4": { 1374 | "Symfony\\Component\\Yaml\\": "" 1375 | } 1376 | }, 1377 | "notification-url": "https://packagist.org/downloads/", 1378 | "license": [ 1379 | "MIT" 1380 | ], 1381 | "authors": [ 1382 | { 1383 | "name": "Fabien Potencier", 1384 | "email": "fabien@symfony.com" 1385 | }, 1386 | { 1387 | "name": "Symfony Community", 1388 | "homepage": "https://symfony.com/contributors" 1389 | } 1390 | ], 1391 | "description": "Symfony Yaml Component", 1392 | "homepage": "https://symfony.com", 1393 | "time": "2015-07-26 09:09:29" 1394 | } 1395 | ], 1396 | "aliases": [], 1397 | "minimum-stability": "dev", 1398 | "stability-flags": [], 1399 | "prefer-stable": false, 1400 | "prefer-lowest": false, 1401 | "platform": { 1402 | "php": ">=5.5.0" 1403 | }, 1404 | "platform-dev": [] 1405 | } 1406 | -------------------------------------------------------------------------------- /config/analytics.php: -------------------------------------------------------------------------------- 1 | 'analytics_visits', 5 | 'model' => \Rdehnhardt\Analytics\Models\Visit::class, 6 | 'default_routes' => true, 7 | 'controller_middleware' => [ 8 | #'auth' => ['only' => ['visitsByPeriod']], 9 | ], 10 | ]; -------------------------------------------------------------------------------- /database/migrations/2015_07_27_000000_create_analytcs_visits_table.php: -------------------------------------------------------------------------------- 1 | table = config('analytics.visits_table', 'analytics_visits'); 13 | } 14 | 15 | /** 16 | * Run the migrations. 17 | * 18 | * @return void 19 | */ 20 | public function up() 21 | { 22 | Schema::create($this->table, function (Blueprint $table) { 23 | $table->increments('id'); 24 | 25 | $table->string('uuid')->index(); 26 | $table->string('ip'); 27 | $table->string('location'); 28 | $table->string('referrer'); 29 | 30 | $table->timestamps(); 31 | }); 32 | } 33 | 34 | /** 35 | * Reverse the migrations. 36 | * 37 | * @return void 38 | */ 39 | public function down() 40 | { 41 | Schema::drop($this->table); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var elixir = require('laravel-elixir'); 2 | 3 | elixir(function (mix) { 4 | 5 | mix.scripts(["resources/assets/analytics,js"], 'resources/assets/analytics.min.js', './'); 6 | 7 | }); 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "dependencies": { 4 | "laravel-elixir": "^3.0.0" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /resources/assets/analytics.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | var analytcs = { 3 | 4 | endPoint: '/analytics/visit', 5 | session: null, 6 | user: null, 7 | app: null, 8 | 9 | init: function (app) { 10 | this.session = this.getSessionStorageKey('session'); 11 | this.user = this.getLocalStorageKey('uuid'); 12 | 13 | if (!this.user) { 14 | this.user = this.makeUniqueId(); 15 | this.setLocalStorageKey('uuid', this.user); 16 | } 17 | 18 | if (!this.session) { 19 | this.session = this.makeSessionId(); 20 | this.setSessionStorageKey('session', this.session); 21 | } 22 | 23 | this.app = app; 24 | this.ping(); 25 | }, 26 | 27 | setLocalStorageKey: function (key, value) { 28 | localStorage.setItem(key, value); 29 | }, 30 | 31 | getLocalStorageKey: function (key) { 32 | for (var i = 0; i < localStorage.length; i++) { 33 | if (localStorage.key(i) == key) { 34 | return localStorage.getItem(localStorage.key(i)); 35 | } 36 | } 37 | 38 | return false; 39 | }, 40 | 41 | setSessionStorageKey: function (key, value) { 42 | sessionStorage.setItem(key, value); 43 | }, 44 | 45 | getSessionStorageKey: function (key) { 46 | for (var i = 0; i < sessionStorage.length; i++) { 47 | if (sessionStorage.key(i) == key) { 48 | return sessionStorage.getItem(sessionStorage.key(i)); 49 | } 50 | } 51 | 52 | return false; 53 | }, 54 | 55 | makeUniqueId: function () { 56 | var rnd = Math.floor((Math.random() * 100000) + 1); 57 | var d = new Date(); 58 | 59 | return d.getDay() + '_' + d.getMonth() + '_' + d.getYear() + '_' + rnd + '_' + d.getSeconds() + '_' + d.getMilliseconds() + '_' + d.getMinutes() + '_' + d.getHours(); 60 | }, 61 | 62 | makeSessionId: function () { 63 | var d = new Date().getTime(); 64 | var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { 65 | var r = (d + Math.random() * 16) % 16 | 0; 66 | d = Math.floor(d / 16); 67 | 68 | return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16); 69 | }); 70 | 71 | return uuid; 72 | }, 73 | 74 | getParams: function () { 75 | var output = []; 76 | 77 | if (this.app.length) { 78 | for (var i = 0; i < this.app.length; i++) { 79 | output.push(this.app[i][0] + '=' + this.app[i][1]); 80 | } 81 | } 82 | 83 | return output.join('&'); 84 | }, 85 | 86 | getRequest: function () { 87 | var xmlhttp; 88 | 89 | if (window.XMLHttpRequest) { 90 | xmlhttp = new XMLHttpRequest(); 91 | } else { 92 | xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); 93 | } 94 | 95 | return xmlhttp; 96 | }, 97 | 98 | ping: function () { 99 | this.app.push(['referrer', document.referrer]); 100 | this.app.push(['location', location.href]); 101 | this.app.push(['uuid', this.user]); 102 | 103 | var Request = this.getRequest(); 104 | Request.open("GET", this.endPoint + '?q=' + JSON.stringify(this.app), true); 105 | Request.send(); 106 | } 107 | 108 | } 109 | 110 | analytcs.init(_bc); 111 | })(); -------------------------------------------------------------------------------- /resources/lang/en/messages.php: -------------------------------------------------------------------------------- 1 | 'day', 5 | 'month' => 'month', 6 | 'year' => 'year', 7 | 'hour' => 'hour', 8 | 'unique' => 'unique', 9 | 'visits' => 'visits', 10 | ]; -------------------------------------------------------------------------------- /resources/lang/pt-BR/messages.php: -------------------------------------------------------------------------------- 1 | 'dia', 5 | 'month' => 'mẽs', 6 | 'year' => 'ano', 7 | 'hour' => 'hora', 8 | 'unique' => 'únicos', 9 | 'visits' => 'visitas', 10 | ]; -------------------------------------------------------------------------------- /resources/views/file.blade.php: -------------------------------------------------------------------------------- 1 | (function () { 2 | var analytcs = { 3 | 4 | endPoint: '/analytics/visit', 5 | session: null, 6 | user: null, 7 | app: null, 8 | 9 | init: function (app) { 10 | this.session = this.getSessionStorageKey('session'); 11 | this.user = this.getLocalStorageKey('uuid'); 12 | 13 | if (!this.user) { 14 | this.user = this.makeUniqueId(); 15 | this.setLocalStorageKey('uuid', this.user); 16 | } 17 | 18 | if (!this.session) { 19 | this.session = this.makeSessionId(); 20 | this.setSessionStorageKey('session', this.session); 21 | } 22 | 23 | this.app = app; 24 | this.ping(); 25 | }, 26 | 27 | setLocalStorageKey: function (key, value) { 28 | localStorage.setItem(key, value); 29 | }, 30 | 31 | getLocalStorageKey: function (key) { 32 | for (var i = 0; i < localStorage.length; i++) { 33 | if (localStorage.key(i) == key) { 34 | return localStorage.getItem(localStorage.key(i)); 35 | } 36 | } 37 | 38 | return false; 39 | }, 40 | 41 | setSessionStorageKey: function (key, value) { 42 | sessionStorage.setItem(key, value); 43 | }, 44 | 45 | getSessionStorageKey: function (key) { 46 | for (var i = 0; i < sessionStorage.length; i++) { 47 | if (sessionStorage.key(i) == key) { 48 | return sessionStorage.getItem(sessionStorage.key(i)); 49 | } 50 | } 51 | 52 | return false; 53 | }, 54 | 55 | makeUniqueId: function () { 56 | var rnd = Math.floor((Math.random() * 100000) + 1); 57 | var d = new Date(); 58 | 59 | return d.getDay() + '_' + d.getMonth() + '_' + d.getYear() + '_' + rnd + '_' + d.getSeconds() + '_' + d.getMilliseconds() + '_' + d.getMinutes() + '_' + d.getHours(); 60 | }, 61 | 62 | makeSessionId: function () { 63 | var d = new Date().getTime(); 64 | var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { 65 | var r = (d + Math.random() * 16) % 16 | 0; 66 | d = Math.floor(d / 16); 67 | 68 | return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16); 69 | }); 70 | 71 | return uuid; 72 | }, 73 | 74 | getParams: function () { 75 | var output = []; 76 | 77 | if (this.app.length) { 78 | for (var i = 0; i < this.app.length; i++) { 79 | output.push(this.app[i][0] + '=' + this.app[i][1]); 80 | } 81 | } 82 | 83 | return output.join('&'); 84 | }, 85 | 86 | getRequest: function () { 87 | var xmlhttp; 88 | 89 | if (window.XMLHttpRequest) { 90 | xmlhttp = new XMLHttpRequest(); 91 | } else { 92 | xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); 93 | } 94 | 95 | return xmlhttp; 96 | }, 97 | 98 | ping: function () { 99 | this.app.push(['referrer', document.referrer]); 100 | this.app.push(['location', location.href]); 101 | this.app.push(['uuid', this.user]); 102 | 103 | var Request = this.getRequest(); 104 | Request.open("GET", this.endPoint + '?q=' + JSON.stringify(this.app), true); 105 | Request.send(); 106 | } 107 | 108 | } 109 | 110 | analytcs.init(_bc); 111 | })(); -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rdehnhardt/laravel-analytics/8b17fc172d6230fd32047534e92b856e7546d3eb/screenshot.png -------------------------------------------------------------------------------- /src/Http/Controllers/AnalyticsController.php: -------------------------------------------------------------------------------- 1 | $options) { 18 | $this->middleware($middleware, $options); 19 | } 20 | } 21 | 22 | /** 23 | * @param CreateVisit $createVisit 24 | * @param GetParams $getParams 25 | * 26 | * @return void 27 | */ 28 | public function visit(CreateVisit $createVisit, GetParams $getParams) 29 | { 30 | $params = $getParams->build(request('q')); 31 | 32 | $uuid = array_get($params, 'uuid'); 33 | $location = array_get($params, 'location'); 34 | $referrer = array_get($params, 'referrer'); 35 | 36 | $createVisit->fire($uuid, $_SERVER['REMOTE_ADDR'], $location, $referrer); 37 | } 38 | 39 | /** 40 | * @param string $startDate 41 | * @param string $endDate 42 | * @param GetVisitByPeriod $getVisitByPeriod 43 | * 44 | * @return mixed 45 | */ 46 | public function visitsByPeriod($startDate, $endDate, GetVisitByPeriod $getVisitByPeriod) 47 | { 48 | $startDate = Carbon::createFromFormat('Y-m-d', $startDate); 49 | $endDate = Carbon::createFromFormat('Y-m-d', $endDate); 50 | 51 | return $getVisitByPeriod->fire($startDate, $endDate); 52 | } 53 | 54 | /** 55 | * @return mixed 56 | */ 57 | public function getFile() 58 | { 59 | return view('analytics::file'); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/Http/routes.php: -------------------------------------------------------------------------------- 1 | 'Rdehnhardt\Analytics\Http\Controllers'], function () { 4 | Route::get('analytics.js', ['as' => 'analytcs', 'uses' => 'AnalyticsController@getFile']); 5 | Route::get('analytics/visit', ['as' => 'visits.store', 'uses' => 'AnalyticsController@visit']); 6 | Route::get('analytics/visits/{start}/{end}', ['as' => 'visits', 'uses' => 'AnalyticsController@visitsByPeriod']); 7 | }); 8 | -------------------------------------------------------------------------------- /src/Models/Visit.php: -------------------------------------------------------------------------------- 1 | table)) { 17 | return $this->table; 18 | } 19 | 20 | return config('analytics.visits_table', 'analytics_visits'); 21 | } 22 | } -------------------------------------------------------------------------------- /src/Providers/AnalyticsServiceProvider.php: -------------------------------------------------------------------------------- 1 | publishes([__DIR__ . '/../../database/migrations/' => database_path('migrations')], 'migrations'); 17 | $this->publishes([__DIR__ . '/../../config/analytics.php' => config_path('analytics.php')], 'config'); 18 | 19 | $this->loadTranslationsFrom(__DIR__ . '/../../resources/lang', 'analytics'); 20 | $this->loadViewsFrom(__DIR__ . '/../../resources/views', 'analytics'); 21 | 22 | $this->mergeConfigFrom( 23 | __DIR__ . '/../../config/analytics.php', 'analytics' 24 | ); 25 | 26 | if (!$this->app->routesAreCached() && config('analytics.default_routes', true)) { 27 | require __DIR__ . '/../Http/routes.php'; 28 | } 29 | } 30 | 31 | /** 32 | * Register any application services. 33 | * 34 | * @return void 35 | */ 36 | public function register() 37 | { 38 | // 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Services/GetByHours.php: -------------------------------------------------------------------------------- 1 | diffInHours($endDate); 18 | 19 | if ($hours <= 24) { 20 | return '%H:00'; 21 | } 22 | 23 | if ($hours > 24 && $hours <= 744) { 24 | return '%d'; 25 | } 26 | 27 | if ($hours > 744 && $hours <= 8766) { 28 | return '%m/%Y'; 29 | } 30 | 31 | if ($hours > 8766) { 32 | return '%Y'; 33 | } 34 | } 35 | 36 | /** 37 | * @param Carbon $startDate 38 | * @param Carbon $endDate 39 | * @return mixed 40 | */ 41 | public static function title(Carbon $startDate, Carbon $endDate) 42 | { 43 | $hours = $startDate->diffInHours($endDate); 44 | 45 | if ($hours <= 24) { 46 | return trans('analytics::messages.hour'); 47 | } 48 | 49 | if ($hours > 24 && $hours <= 720) { 50 | return trans('analytics::messages.day'); 51 | } 52 | 53 | if ($hours > 720 && $hours <= 8766) { 54 | return trans('analytics::messages.month'); 55 | } 56 | 57 | if ($hours > 8766) { 58 | return trans('analytics::messages.year'); 59 | } 60 | } 61 | 62 | } -------------------------------------------------------------------------------- /src/Services/GetParams.php: -------------------------------------------------------------------------------- 1 | factoryVisit($uuid, $ip, $location, $referrer, $extra); 22 | 23 | $visit->save(); 24 | } 25 | 26 | /** 27 | * @param string $uuid 28 | * @param string $ip 29 | * @param string $location 30 | * @param string $referrer 31 | * @param array $extra 32 | * 33 | * @return Visit 34 | */ 35 | protected function factoryVisit($uuid, $ip, $location, $referrer, array $extra = []) 36 | { 37 | $data = array_merge([ 38 | 'uuid' => $uuid, 39 | 'location' => $location, 40 | 'ip' => $ip, 41 | 'referrer' => $referrer, 42 | ], $extra); 43 | 44 | $visit = app()->make(config('analytics.model', Visit::class)); 45 | 46 | $visit->fill($data); 47 | 48 | return $visit; 49 | } 50 | } -------------------------------------------------------------------------------- /src/Services/Visits/GetVisitByPeriod.php: -------------------------------------------------------------------------------- 1 | start = $startDate; 26 | $this->end = $endDate; 27 | 28 | return $this->getData(); 29 | } 30 | 31 | /** 32 | * @return array 33 | */ 34 | public function getLabels() 35 | { 36 | $output = []; 37 | 38 | if ($this->data) { 39 | foreach ($this->data as $row) { 40 | $output[] = $row->key; 41 | } 42 | } 43 | 44 | return $output; 45 | } 46 | 47 | /** 48 | * @return array 49 | */ 50 | public function getTotal() 51 | { 52 | $output = []; 53 | 54 | if ($this->data) { 55 | foreach ($this->data as $row) { 56 | $output[] = $row->total; 57 | } 58 | } 59 | 60 | return $output; 61 | } 62 | 63 | public function getUniques() 64 | { 65 | $output = []; 66 | 67 | if ($this->data) { 68 | foreach ($this->data as $row) { 69 | $output[] = $row->uniques; 70 | } 71 | } 72 | 73 | return $output; 74 | } 75 | 76 | /** 77 | * @return mixed 78 | */ 79 | private function getData() 80 | { 81 | $key = GetByHours::key($this->start, $this->end); 82 | 83 | $Select = DB::table($this->getTable())->select( 84 | DB::raw("date_format(created_at, '$key') as `key`"), 85 | DB::raw("count(uuid) as total"), 86 | DB::raw("count(distinct uuid) as uniques") 87 | ); 88 | 89 | $Select->where('created_at', '>=', "{$this->start} 00:00:00"); 90 | $Select->where('created_at', '<=', "{$this->end} 23:59:59"); 91 | $Select->groupBy('key'); 92 | 93 | $this->data = $Select->get(); 94 | 95 | return $this->data; 96 | } 97 | 98 | /** 99 | * @return string 100 | */ 101 | protected function getTable() 102 | { 103 | return config('analytics.visits_table', 'analytics_visits'); 104 | } 105 | } -------------------------------------------------------------------------------- /src/Support/helpers.php: -------------------------------------------------------------------------------- 1 | make(\Rdehnhardt\Analytics\Services\Visits\GetVisitByPeriod::class); 14 | 15 | return $Visits->fire(Carbon::createFromFormat('Y-m-d', $startDate), Carbon::createFromFormat('Y-m-d', $endDate)); 16 | } 17 | } 18 | 19 | if (!function_exists('graph_values')) { 20 | /** 21 | * @param $records 22 | * @param $key 23 | * @param bool|false $withComma 24 | * @return bool|string 25 | */ 26 | function graph_values($records, $key, $withComma = false) 27 | { 28 | $tmp = []; 29 | 30 | if (count($records)) { 31 | foreach ($records as $record) { 32 | if ($withComma) { 33 | $tmp[] = "'" . $record->{$key} . "'"; 34 | } else { 35 | $tmp[] = $record->{$key}; 36 | } 37 | 38 | } 39 | 40 | return implode(',', $tmp); 41 | } 42 | 43 | return false; 44 | } 45 | } 46 | --------------------------------------------------------------------------------