├── .gitignore ├── LICENSE.txt ├── composer.json ├── composer.lock ├── phpunit.xml ├── readme.md ├── src ├── BladeDirective.php ├── Cacheable.php ├── FlushViews.php ├── MatryoshkaServiceProvider.php └── RussianCaching.php └── tests ├── BladeDirectiveTest.php ├── CacheableTest.php ├── RussianCachingTest.php └── TestCase.php /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 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 13 | all 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "laracasts/matryoshka", 3 | "description": "Russian Doll Caching for Laravel.", 4 | "license": "MIT", 5 | "keywords": ["laravel", "cache"], 6 | "authors": [ 7 | { 8 | "name": "Jeffrey Way", 9 | "email": "jeffrey@laracasts.com" 10 | } 11 | ], 12 | "require": { 13 | "illuminate/support": "^5.1" 14 | }, 15 | "autoload": { 16 | "psr-4": { 17 | "Laracasts\\Matryoshka\\": "src/" 18 | } 19 | }, 20 | "autoload-dev": { 21 | "classmap": ["tests/TestCase.php"] 22 | }, 23 | "require-dev": { 24 | "phpunit/phpunit": "^5.2", 25 | "illuminate/database": "^5.1", 26 | "illuminate/cache": "^5.1" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /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": "efd92b5737757172ccff084b8b6a46ec", 8 | "content-hash": "e211626c88b349ffbb0606b7b30fb441", 9 | "packages": [ 10 | { 11 | "name": "doctrine/inflector", 12 | "version": "dev-master", 13 | "source": { 14 | "type": "git", 15 | "url": "https://github.com/doctrine/inflector.git", 16 | "reference": "90b2128806bfde671b6952ab8bea493942c1fdae" 17 | }, 18 | "dist": { 19 | "type": "zip", 20 | "url": "https://api.github.com/repos/doctrine/inflector/zipball/90b2128806bfde671b6952ab8bea493942c1fdae", 21 | "reference": "90b2128806bfde671b6952ab8bea493942c1fdae", 22 | "shasum": "" 23 | }, 24 | "require": { 25 | "php": ">=5.3.2" 26 | }, 27 | "require-dev": { 28 | "phpunit/phpunit": "4.*" 29 | }, 30 | "type": "library", 31 | "extra": { 32 | "branch-alias": { 33 | "dev-master": "1.1.x-dev" 34 | } 35 | }, 36 | "autoload": { 37 | "psr-0": { 38 | "Doctrine\\Common\\Inflector\\": "lib/" 39 | } 40 | }, 41 | "notification-url": "https://packagist.org/downloads/", 42 | "license": [ 43 | "MIT" 44 | ], 45 | "authors": [ 46 | { 47 | "name": "Roman Borschel", 48 | "email": "roman@code-factory.org" 49 | }, 50 | { 51 | "name": "Benjamin Eberlei", 52 | "email": "kontakt@beberlei.de" 53 | }, 54 | { 55 | "name": "Guilherme Blanco", 56 | "email": "guilhermeblanco@gmail.com" 57 | }, 58 | { 59 | "name": "Jonathan Wage", 60 | "email": "jonwage@gmail.com" 61 | }, 62 | { 63 | "name": "Johannes Schmitt", 64 | "email": "schmittjoh@gmail.com" 65 | } 66 | ], 67 | "description": "Common String Manipulations with regard to casing and singular/plural rules.", 68 | "homepage": "http://www.doctrine-project.org", 69 | "keywords": [ 70 | "inflection", 71 | "pluralize", 72 | "singularize", 73 | "string" 74 | ], 75 | "time": "2015-11-06 14:35:42" 76 | }, 77 | { 78 | "name": "illuminate/contracts", 79 | "version": "5.2.x-dev", 80 | "source": { 81 | "type": "git", 82 | "url": "https://github.com/illuminate/contracts.git", 83 | "reference": "255a9547a2fa7cb1dfb8fc3223f7114650848eaf" 84 | }, 85 | "dist": { 86 | "type": "zip", 87 | "url": "https://api.github.com/repos/illuminate/contracts/zipball/255a9547a2fa7cb1dfb8fc3223f7114650848eaf", 88 | "reference": "255a9547a2fa7cb1dfb8fc3223f7114650848eaf", 89 | "shasum": "" 90 | }, 91 | "require": { 92 | "php": ">=5.5.9" 93 | }, 94 | "type": "library", 95 | "extra": { 96 | "branch-alias": { 97 | "dev-master": "5.2-dev" 98 | } 99 | }, 100 | "autoload": { 101 | "psr-4": { 102 | "Illuminate\\Contracts\\": "" 103 | } 104 | }, 105 | "notification-url": "https://packagist.org/downloads/", 106 | "license": [ 107 | "MIT" 108 | ], 109 | "authors": [ 110 | { 111 | "name": "Taylor Otwell", 112 | "email": "taylorotwell@gmail.com" 113 | } 114 | ], 115 | "description": "The Illuminate Contracts package.", 116 | "homepage": "http://laravel.com", 117 | "time": "2016-01-07 19:57:38" 118 | }, 119 | { 120 | "name": "illuminate/support", 121 | "version": "5.2.x-dev", 122 | "source": { 123 | "type": "git", 124 | "url": "https://github.com/illuminate/support.git", 125 | "reference": "669166b56d0b2d831791b3b697de5fba2d7836a6" 126 | }, 127 | "dist": { 128 | "type": "zip", 129 | "url": "https://api.github.com/repos/illuminate/support/zipball/669166b56d0b2d831791b3b697de5fba2d7836a6", 130 | "reference": "669166b56d0b2d831791b3b697de5fba2d7836a6", 131 | "shasum": "" 132 | }, 133 | "require": { 134 | "doctrine/inflector": "~1.0", 135 | "ext-mbstring": "*", 136 | "illuminate/contracts": "5.2.*", 137 | "php": ">=5.5.9" 138 | }, 139 | "suggest": { 140 | "illuminate/filesystem": "Required to use the composer class (5.2.*).", 141 | "jeremeamia/superclosure": "Required to be able to serialize closures (~2.2).", 142 | "paragonie/random_compat": "Provides a compatible interface like PHP7's random_bytes() in PHP 5 projects (~1.1).", 143 | "symfony/polyfill-php56": "Required to use the hash_equals function on PHP 5.5 (~1.0).", 144 | "symfony/process": "Required to use the composer class (2.8.*|3.0.*).", 145 | "symfony/var-dumper": "Improves the dd function (2.8.*|3.0.*)." 146 | }, 147 | "type": "library", 148 | "extra": { 149 | "branch-alias": { 150 | "dev-master": "5.2-dev" 151 | } 152 | }, 153 | "autoload": { 154 | "psr-4": { 155 | "Illuminate\\Support\\": "" 156 | }, 157 | "files": [ 158 | "helpers.php" 159 | ] 160 | }, 161 | "notification-url": "https://packagist.org/downloads/", 162 | "license": [ 163 | "MIT" 164 | ], 165 | "authors": [ 166 | { 167 | "name": "Taylor Otwell", 168 | "email": "taylorotwell@gmail.com" 169 | } 170 | ], 171 | "description": "The Illuminate Support package.", 172 | "homepage": "http://laravel.com", 173 | "time": "2016-02-16 14:39:24" 174 | } 175 | ], 176 | "packages-dev": [ 177 | { 178 | "name": "doctrine/instantiator", 179 | "version": "dev-master", 180 | "source": { 181 | "type": "git", 182 | "url": "https://github.com/doctrine/instantiator.git", 183 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" 184 | }, 185 | "dist": { 186 | "type": "zip", 187 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", 188 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", 189 | "shasum": "" 190 | }, 191 | "require": { 192 | "php": ">=5.3,<8.0-DEV" 193 | }, 194 | "require-dev": { 195 | "athletic/athletic": "~0.1.8", 196 | "ext-pdo": "*", 197 | "ext-phar": "*", 198 | "phpunit/phpunit": "~4.0", 199 | "squizlabs/php_codesniffer": "~2.0" 200 | }, 201 | "type": "library", 202 | "extra": { 203 | "branch-alias": { 204 | "dev-master": "1.0.x-dev" 205 | } 206 | }, 207 | "autoload": { 208 | "psr-4": { 209 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" 210 | } 211 | }, 212 | "notification-url": "https://packagist.org/downloads/", 213 | "license": [ 214 | "MIT" 215 | ], 216 | "authors": [ 217 | { 218 | "name": "Marco Pivetta", 219 | "email": "ocramius@gmail.com", 220 | "homepage": "http://ocramius.github.com/" 221 | } 222 | ], 223 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 224 | "homepage": "https://github.com/doctrine/instantiator", 225 | "keywords": [ 226 | "constructor", 227 | "instantiate" 228 | ], 229 | "time": "2015-06-14 21:17:01" 230 | }, 231 | { 232 | "name": "illuminate/cache", 233 | "version": "5.2.x-dev", 234 | "source": { 235 | "type": "git", 236 | "url": "https://github.com/illuminate/cache.git", 237 | "reference": "a03bb30c61ff70051d2ab9180cf012fc28c7adaa" 238 | }, 239 | "dist": { 240 | "type": "zip", 241 | "url": "https://api.github.com/repos/illuminate/cache/zipball/a03bb30c61ff70051d2ab9180cf012fc28c7adaa", 242 | "reference": "a03bb30c61ff70051d2ab9180cf012fc28c7adaa", 243 | "shasum": "" 244 | }, 245 | "require": { 246 | "illuminate/contracts": "5.2.*", 247 | "illuminate/support": "5.2.*", 248 | "nesbot/carbon": "~1.20", 249 | "php": ">=5.5.9" 250 | }, 251 | "suggest": { 252 | "illuminate/database": "Required to use the database cache driver (5.2.*).", 253 | "illuminate/filesystem": "Required to use the file cache driver (5.2.*).", 254 | "illuminate/redis": "Required to use the redis cache driver (5.2.*)." 255 | }, 256 | "type": "library", 257 | "extra": { 258 | "branch-alias": { 259 | "dev-master": "5.2-dev" 260 | } 261 | }, 262 | "autoload": { 263 | "psr-4": { 264 | "Illuminate\\Cache\\": "" 265 | } 266 | }, 267 | "notification-url": "https://packagist.org/downloads/", 268 | "license": [ 269 | "MIT" 270 | ], 271 | "authors": [ 272 | { 273 | "name": "Taylor Otwell", 274 | "email": "taylorotwell@gmail.com" 275 | } 276 | ], 277 | "description": "The Illuminate Cache package.", 278 | "homepage": "http://laravel.com", 279 | "time": "2016-02-05 14:57:25" 280 | }, 281 | { 282 | "name": "illuminate/container", 283 | "version": "5.2.x-dev", 284 | "source": { 285 | "type": "git", 286 | "url": "https://github.com/illuminate/container.git", 287 | "reference": "88cd62ea45063ecc7a2c2319f3dfa601a9f8a47e" 288 | }, 289 | "dist": { 290 | "type": "zip", 291 | "url": "https://api.github.com/repos/illuminate/container/zipball/88cd62ea45063ecc7a2c2319f3dfa601a9f8a47e", 292 | "reference": "88cd62ea45063ecc7a2c2319f3dfa601a9f8a47e", 293 | "shasum": "" 294 | }, 295 | "require": { 296 | "illuminate/contracts": "5.2.*", 297 | "php": ">=5.5.9" 298 | }, 299 | "type": "library", 300 | "extra": { 301 | "branch-alias": { 302 | "dev-master": "5.2-dev" 303 | } 304 | }, 305 | "autoload": { 306 | "psr-4": { 307 | "Illuminate\\Container\\": "" 308 | } 309 | }, 310 | "notification-url": "https://packagist.org/downloads/", 311 | "license": [ 312 | "MIT" 313 | ], 314 | "authors": [ 315 | { 316 | "name": "Taylor Otwell", 317 | "email": "taylorotwell@gmail.com" 318 | } 319 | ], 320 | "description": "The Illuminate Container package.", 321 | "homepage": "http://laravel.com", 322 | "time": "2016-01-18 22:49:36" 323 | }, 324 | { 325 | "name": "illuminate/database", 326 | "version": "5.2.x-dev", 327 | "source": { 328 | "type": "git", 329 | "url": "https://github.com/illuminate/database.git", 330 | "reference": "c4b06f7ef8bf9a2748bf289b9988c3232eb961c4" 331 | }, 332 | "dist": { 333 | "type": "zip", 334 | "url": "https://api.github.com/repos/illuminate/database/zipball/c4b06f7ef8bf9a2748bf289b9988c3232eb961c4", 335 | "reference": "c4b06f7ef8bf9a2748bf289b9988c3232eb961c4", 336 | "shasum": "" 337 | }, 338 | "require": { 339 | "illuminate/container": "5.2.*", 340 | "illuminate/contracts": "5.2.*", 341 | "illuminate/support": "5.2.*", 342 | "nesbot/carbon": "~1.20", 343 | "php": ">=5.5.9" 344 | }, 345 | "suggest": { 346 | "doctrine/dbal": "Required to rename columns and drop SQLite columns (~2.4).", 347 | "fzaninotto/faker": "Required to use the eloquent factory builder (~1.4).", 348 | "illuminate/console": "Required to use the database commands (5.2.*).", 349 | "illuminate/events": "Required to use the observers with Eloquent (5.2.*).", 350 | "illuminate/filesystem": "Required to use the migrations (5.2.*).", 351 | "illuminate/pagination": "Required to paginate the result set (5.2.*)." 352 | }, 353 | "type": "library", 354 | "extra": { 355 | "branch-alias": { 356 | "dev-master": "5.2-dev" 357 | } 358 | }, 359 | "autoload": { 360 | "psr-4": { 361 | "Illuminate\\Database\\": "" 362 | } 363 | }, 364 | "notification-url": "https://packagist.org/downloads/", 365 | "license": [ 366 | "MIT" 367 | ], 368 | "authors": [ 369 | { 370 | "name": "Taylor Otwell", 371 | "email": "taylorotwell@gmail.com" 372 | } 373 | ], 374 | "description": "The Illuminate Database package.", 375 | "homepage": "http://laravel.com", 376 | "keywords": [ 377 | "database", 378 | "laravel", 379 | "orm", 380 | "sql" 381 | ], 382 | "time": "2016-02-17 17:31:14" 383 | }, 384 | { 385 | "name": "myclabs/deep-copy", 386 | "version": "1.5.0", 387 | "source": { 388 | "type": "git", 389 | "url": "https://github.com/myclabs/DeepCopy.git", 390 | "reference": "e3abefcd7f106677fd352cd7c187d6c969aa9ddc" 391 | }, 392 | "dist": { 393 | "type": "zip", 394 | "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/e3abefcd7f106677fd352cd7c187d6c969aa9ddc", 395 | "reference": "e3abefcd7f106677fd352cd7c187d6c969aa9ddc", 396 | "shasum": "" 397 | }, 398 | "require": { 399 | "php": ">=5.4.0" 400 | }, 401 | "require-dev": { 402 | "doctrine/collections": "1.*", 403 | "phpunit/phpunit": "~4.1" 404 | }, 405 | "type": "library", 406 | "autoload": { 407 | "psr-4": { 408 | "DeepCopy\\": "src/DeepCopy/" 409 | } 410 | }, 411 | "notification-url": "https://packagist.org/downloads/", 412 | "license": [ 413 | "MIT" 414 | ], 415 | "description": "Create deep copies (clones) of your objects", 416 | "homepage": "https://github.com/myclabs/DeepCopy", 417 | "keywords": [ 418 | "clone", 419 | "copy", 420 | "duplicate", 421 | "object", 422 | "object graph" 423 | ], 424 | "time": "2015-11-07 22:20:37" 425 | }, 426 | { 427 | "name": "nesbot/carbon", 428 | "version": "1.21.0", 429 | "source": { 430 | "type": "git", 431 | "url": "https://github.com/briannesbitt/Carbon.git", 432 | "reference": "7b08ec6f75791e130012f206e3f7b0e76e18e3d7" 433 | }, 434 | "dist": { 435 | "type": "zip", 436 | "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/7b08ec6f75791e130012f206e3f7b0e76e18e3d7", 437 | "reference": "7b08ec6f75791e130012f206e3f7b0e76e18e3d7", 438 | "shasum": "" 439 | }, 440 | "require": { 441 | "php": ">=5.3.0", 442 | "symfony/translation": "~2.6|~3.0" 443 | }, 444 | "require-dev": { 445 | "phpunit/phpunit": "~4.0|~5.0" 446 | }, 447 | "type": "library", 448 | "autoload": { 449 | "psr-4": { 450 | "Carbon\\": "src/Carbon/" 451 | } 452 | }, 453 | "notification-url": "https://packagist.org/downloads/", 454 | "license": [ 455 | "MIT" 456 | ], 457 | "authors": [ 458 | { 459 | "name": "Brian Nesbitt", 460 | "email": "brian@nesbot.com", 461 | "homepage": "http://nesbot.com" 462 | } 463 | ], 464 | "description": "A simple API extension for DateTime.", 465 | "homepage": "http://carbon.nesbot.com", 466 | "keywords": [ 467 | "date", 468 | "datetime", 469 | "time" 470 | ], 471 | "time": "2015-11-04 20:07:17" 472 | }, 473 | { 474 | "name": "phpdocumentor/reflection-docblock", 475 | "version": "2.0.4", 476 | "source": { 477 | "type": "git", 478 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", 479 | "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8" 480 | }, 481 | "dist": { 482 | "type": "zip", 483 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8", 484 | "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8", 485 | "shasum": "" 486 | }, 487 | "require": { 488 | "php": ">=5.3.3" 489 | }, 490 | "require-dev": { 491 | "phpunit/phpunit": "~4.0" 492 | }, 493 | "suggest": { 494 | "dflydev/markdown": "~1.0", 495 | "erusev/parsedown": "~1.0" 496 | }, 497 | "type": "library", 498 | "extra": { 499 | "branch-alias": { 500 | "dev-master": "2.0.x-dev" 501 | } 502 | }, 503 | "autoload": { 504 | "psr-0": { 505 | "phpDocumentor": [ 506 | "src/" 507 | ] 508 | } 509 | }, 510 | "notification-url": "https://packagist.org/downloads/", 511 | "license": [ 512 | "MIT" 513 | ], 514 | "authors": [ 515 | { 516 | "name": "Mike van Riel", 517 | "email": "mike.vanriel@naenius.com" 518 | } 519 | ], 520 | "time": "2015-02-03 12:10:50" 521 | }, 522 | { 523 | "name": "phpspec/prophecy", 524 | "version": "dev-master", 525 | "source": { 526 | "type": "git", 527 | "url": "https://github.com/phpspec/prophecy.git", 528 | "reference": "ce91d434b3dc443a3294c4535747765e84d11094" 529 | }, 530 | "dist": { 531 | "type": "zip", 532 | "url": "https://api.github.com/repos/phpspec/prophecy/zipball/ce91d434b3dc443a3294c4535747765e84d11094", 533 | "reference": "ce91d434b3dc443a3294c4535747765e84d11094", 534 | "shasum": "" 535 | }, 536 | "require": { 537 | "doctrine/instantiator": "^1.0.2", 538 | "php": "^5.3|^7.0", 539 | "phpdocumentor/reflection-docblock": "~2.0", 540 | "sebastian/comparator": "~1.1", 541 | "sebastian/recursion-context": "~1.0" 542 | }, 543 | "require-dev": { 544 | "phpspec/phpspec": "~2.0" 545 | }, 546 | "type": "library", 547 | "extra": { 548 | "branch-alias": { 549 | "dev-master": "1.6.x-dev" 550 | } 551 | }, 552 | "autoload": { 553 | "psr-0": { 554 | "Prophecy\\": "src/" 555 | } 556 | }, 557 | "notification-url": "https://packagist.org/downloads/", 558 | "license": [ 559 | "MIT" 560 | ], 561 | "authors": [ 562 | { 563 | "name": "Konstantin Kudryashov", 564 | "email": "ever.zet@gmail.com", 565 | "homepage": "http://everzet.com" 566 | }, 567 | { 568 | "name": "Marcello Duarte", 569 | "email": "marcello.duarte@gmail.com" 570 | } 571 | ], 572 | "description": "Highly opinionated mocking framework for PHP 5.3+", 573 | "homepage": "https://github.com/phpspec/prophecy", 574 | "keywords": [ 575 | "Double", 576 | "Dummy", 577 | "fake", 578 | "mock", 579 | "spy", 580 | "stub" 581 | ], 582 | "time": "2016-02-15 13:39:12" 583 | }, 584 | { 585 | "name": "phpunit/php-code-coverage", 586 | "version": "dev-master", 587 | "source": { 588 | "type": "git", 589 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 590 | "reference": "85f5db2d0a0da79ad6a256eb54148ba383059ad9" 591 | }, 592 | "dist": { 593 | "type": "zip", 594 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/85f5db2d0a0da79ad6a256eb54148ba383059ad9", 595 | "reference": "85f5db2d0a0da79ad6a256eb54148ba383059ad9", 596 | "shasum": "" 597 | }, 598 | "require": { 599 | "php": ">=5.6", 600 | "phpunit/php-file-iterator": "~1.3", 601 | "phpunit/php-text-template": "~1.2", 602 | "phpunit/php-token-stream": "~1.3", 603 | "sebastian/code-unit-reverse-lookup": "~1.0", 604 | "sebastian/environment": "^1.3.2", 605 | "sebastian/version": "~1.0|~2.0" 606 | }, 607 | "require-dev": { 608 | "ext-xdebug": ">=2.1.4", 609 | "phpunit/phpunit": "~5" 610 | }, 611 | "suggest": { 612 | "ext-dom": "*", 613 | "ext-xdebug": ">=2.2.1", 614 | "ext-xmlwriter": "*" 615 | }, 616 | "type": "library", 617 | "extra": { 618 | "branch-alias": { 619 | "dev-master": "3.2.x-dev" 620 | } 621 | }, 622 | "autoload": { 623 | "classmap": [ 624 | "src/" 625 | ] 626 | }, 627 | "notification-url": "https://packagist.org/downloads/", 628 | "license": [ 629 | "BSD-3-Clause" 630 | ], 631 | "authors": [ 632 | { 633 | "name": "Sebastian Bergmann", 634 | "email": "sb@sebastian-bergmann.de", 635 | "role": "lead" 636 | } 637 | ], 638 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 639 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 640 | "keywords": [ 641 | "coverage", 642 | "testing", 643 | "xunit" 644 | ], 645 | "time": "2016-02-13 06:47:56" 646 | }, 647 | { 648 | "name": "phpunit/php-file-iterator", 649 | "version": "dev-master", 650 | "source": { 651 | "type": "git", 652 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 653 | "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0" 654 | }, 655 | "dist": { 656 | "type": "zip", 657 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0", 658 | "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0", 659 | "shasum": "" 660 | }, 661 | "require": { 662 | "php": ">=5.3.3" 663 | }, 664 | "type": "library", 665 | "extra": { 666 | "branch-alias": { 667 | "dev-master": "1.4.x-dev" 668 | } 669 | }, 670 | "autoload": { 671 | "classmap": [ 672 | "src/" 673 | ] 674 | }, 675 | "notification-url": "https://packagist.org/downloads/", 676 | "license": [ 677 | "BSD-3-Clause" 678 | ], 679 | "authors": [ 680 | { 681 | "name": "Sebastian Bergmann", 682 | "email": "sb@sebastian-bergmann.de", 683 | "role": "lead" 684 | } 685 | ], 686 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 687 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 688 | "keywords": [ 689 | "filesystem", 690 | "iterator" 691 | ], 692 | "time": "2015-06-21 13:08:43" 693 | }, 694 | { 695 | "name": "phpunit/php-text-template", 696 | "version": "1.2.1", 697 | "source": { 698 | "type": "git", 699 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 700 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" 701 | }, 702 | "dist": { 703 | "type": "zip", 704 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 705 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", 706 | "shasum": "" 707 | }, 708 | "require": { 709 | "php": ">=5.3.3" 710 | }, 711 | "type": "library", 712 | "autoload": { 713 | "classmap": [ 714 | "src/" 715 | ] 716 | }, 717 | "notification-url": "https://packagist.org/downloads/", 718 | "license": [ 719 | "BSD-3-Clause" 720 | ], 721 | "authors": [ 722 | { 723 | "name": "Sebastian Bergmann", 724 | "email": "sebastian@phpunit.de", 725 | "role": "lead" 726 | } 727 | ], 728 | "description": "Simple template engine.", 729 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 730 | "keywords": [ 731 | "template" 732 | ], 733 | "time": "2015-06-21 13:50:34" 734 | }, 735 | { 736 | "name": "phpunit/php-timer", 737 | "version": "dev-master", 738 | "source": { 739 | "type": "git", 740 | "url": "https://github.com/sebastianbergmann/php-timer.git", 741 | "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b" 742 | }, 743 | "dist": { 744 | "type": "zip", 745 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3e82f4e9fc92665fafd9157568e4dcb01d014e5b", 746 | "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b", 747 | "shasum": "" 748 | }, 749 | "require": { 750 | "php": ">=5.3.3" 751 | }, 752 | "type": "library", 753 | "autoload": { 754 | "classmap": [ 755 | "src/" 756 | ] 757 | }, 758 | "notification-url": "https://packagist.org/downloads/", 759 | "license": [ 760 | "BSD-3-Clause" 761 | ], 762 | "authors": [ 763 | { 764 | "name": "Sebastian Bergmann", 765 | "email": "sb@sebastian-bergmann.de", 766 | "role": "lead" 767 | } 768 | ], 769 | "description": "Utility class for timing", 770 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 771 | "keywords": [ 772 | "timer" 773 | ], 774 | "time": "2015-06-21 08:01:12" 775 | }, 776 | { 777 | "name": "phpunit/php-token-stream", 778 | "version": "dev-master", 779 | "source": { 780 | "type": "git", 781 | "url": "https://github.com/sebastianbergmann/php-token-stream.git", 782 | "reference": "cab6c6fefee93d7b7c3a01292a0fe0884ea66644" 783 | }, 784 | "dist": { 785 | "type": "zip", 786 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/cab6c6fefee93d7b7c3a01292a0fe0884ea66644", 787 | "reference": "cab6c6fefee93d7b7c3a01292a0fe0884ea66644", 788 | "shasum": "" 789 | }, 790 | "require": { 791 | "ext-tokenizer": "*", 792 | "php": ">=5.3.3" 793 | }, 794 | "require-dev": { 795 | "phpunit/phpunit": "~4.2" 796 | }, 797 | "type": "library", 798 | "extra": { 799 | "branch-alias": { 800 | "dev-master": "1.4-dev" 801 | } 802 | }, 803 | "autoload": { 804 | "classmap": [ 805 | "src/" 806 | ] 807 | }, 808 | "notification-url": "https://packagist.org/downloads/", 809 | "license": [ 810 | "BSD-3-Clause" 811 | ], 812 | "authors": [ 813 | { 814 | "name": "Sebastian Bergmann", 815 | "email": "sebastian@phpunit.de" 816 | } 817 | ], 818 | "description": "Wrapper around PHP's tokenizer extension.", 819 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/", 820 | "keywords": [ 821 | "tokenizer" 822 | ], 823 | "time": "2015-09-23 14:46:55" 824 | }, 825 | { 826 | "name": "phpunit/phpunit", 827 | "version": "dev-master", 828 | "source": { 829 | "type": "git", 830 | "url": "https://github.com/sebastianbergmann/phpunit.git", 831 | "reference": "f81a1fa79c7fc93b8ab1ef60e48c19589a4c1f7e" 832 | }, 833 | "dist": { 834 | "type": "zip", 835 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f81a1fa79c7fc93b8ab1ef60e48c19589a4c1f7e", 836 | "reference": "f81a1fa79c7fc93b8ab1ef60e48c19589a4c1f7e", 837 | "shasum": "" 838 | }, 839 | "require": { 840 | "ext-dom": "*", 841 | "ext-json": "*", 842 | "ext-pcre": "*", 843 | "ext-reflection": "*", 844 | "ext-spl": "*", 845 | "myclabs/deep-copy": "~1.3", 846 | "php": ">=5.6", 847 | "phpspec/prophecy": "^1.3.1", 848 | "phpunit/php-code-coverage": "~3.2", 849 | "phpunit/php-file-iterator": "~1.4", 850 | "phpunit/php-text-template": "~1.2", 851 | "phpunit/php-timer": ">=1.0.6", 852 | "phpunit/phpunit-mock-objects": ">=3.0.5", 853 | "sebastian/comparator": "~1.1", 854 | "sebastian/diff": "~1.2", 855 | "sebastian/environment": "~1.3", 856 | "sebastian/exporter": "~1.2", 857 | "sebastian/global-state": "~1.0", 858 | "sebastian/object-enumerator": "~1.0", 859 | "sebastian/resource-operations": "~1.0", 860 | "sebastian/version": "~1.0|~2.0", 861 | "symfony/yaml": "~2.1|~3.0" 862 | }, 863 | "suggest": { 864 | "phpunit/php-invoker": "~1.1" 865 | }, 866 | "bin": [ 867 | "phpunit" 868 | ], 869 | "type": "library", 870 | "extra": { 871 | "branch-alias": { 872 | "dev-master": "5.4.x-dev" 873 | } 874 | }, 875 | "autoload": { 876 | "classmap": [ 877 | "src/" 878 | ] 879 | }, 880 | "notification-url": "https://packagist.org/downloads/", 881 | "license": [ 882 | "BSD-3-Clause" 883 | ], 884 | "authors": [ 885 | { 886 | "name": "Sebastian Bergmann", 887 | "email": "sebastian@phpunit.de", 888 | "role": "lead" 889 | } 890 | ], 891 | "description": "The PHP Unit Testing framework.", 892 | "homepage": "https://phpunit.de/", 893 | "keywords": [ 894 | "phpunit", 895 | "testing", 896 | "xunit" 897 | ], 898 | "time": "2016-02-16 17:47:19" 899 | }, 900 | { 901 | "name": "phpunit/phpunit-mock-objects", 902 | "version": "dev-master", 903 | "source": { 904 | "type": "git", 905 | "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", 906 | "reference": "c4dd0c9e7fcbf53c6aa48012902be692318c7566" 907 | }, 908 | "dist": { 909 | "type": "zip", 910 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/c4dd0c9e7fcbf53c6aa48012902be692318c7566", 911 | "reference": "c4dd0c9e7fcbf53c6aa48012902be692318c7566", 912 | "shasum": "" 913 | }, 914 | "require": { 915 | "doctrine/instantiator": "^1.0.2", 916 | "php": ">=5.6", 917 | "phpunit/php-text-template": "~1.2", 918 | "sebastian/exporter": "~1.2" 919 | }, 920 | "require-dev": { 921 | "phpunit/phpunit": "~5" 922 | }, 923 | "suggest": { 924 | "ext-soap": "*" 925 | }, 926 | "type": "library", 927 | "extra": { 928 | "branch-alias": { 929 | "dev-master": "3.1.x-dev" 930 | } 931 | }, 932 | "autoload": { 933 | "classmap": [ 934 | "src/" 935 | ] 936 | }, 937 | "notification-url": "https://packagist.org/downloads/", 938 | "license": [ 939 | "BSD-3-Clause" 940 | ], 941 | "authors": [ 942 | { 943 | "name": "Sebastian Bergmann", 944 | "email": "sb@sebastian-bergmann.de", 945 | "role": "lead" 946 | } 947 | ], 948 | "description": "Mock Object library for PHPUnit", 949 | "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", 950 | "keywords": [ 951 | "mock", 952 | "xunit" 953 | ], 954 | "time": "2015-12-08 08:54:19" 955 | }, 956 | { 957 | "name": "sebastian/code-unit-reverse-lookup", 958 | "version": "dev-master", 959 | "source": { 960 | "type": "git", 961 | "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", 962 | "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe" 963 | }, 964 | "dist": { 965 | "type": "zip", 966 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/c36f5e7cfce482fde5bf8d10d41a53591e0198fe", 967 | "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe", 968 | "shasum": "" 969 | }, 970 | "require": { 971 | "php": ">=5.6" 972 | }, 973 | "require-dev": { 974 | "phpunit/phpunit": "~5" 975 | }, 976 | "type": "library", 977 | "extra": { 978 | "branch-alias": { 979 | "dev-master": "1.0.x-dev" 980 | } 981 | }, 982 | "autoload": { 983 | "classmap": [ 984 | "src/" 985 | ] 986 | }, 987 | "notification-url": "https://packagist.org/downloads/", 988 | "license": [ 989 | "BSD-3-Clause" 990 | ], 991 | "authors": [ 992 | { 993 | "name": "Sebastian Bergmann", 994 | "email": "sebastian@phpunit.de" 995 | } 996 | ], 997 | "description": "Looks up which function or method a line of code belongs to", 998 | "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", 999 | "time": "2016-02-13 06:45:14" 1000 | }, 1001 | { 1002 | "name": "sebastian/comparator", 1003 | "version": "dev-master", 1004 | "source": { 1005 | "type": "git", 1006 | "url": "https://github.com/sebastianbergmann/comparator.git", 1007 | "reference": "937efb279bd37a375bcadf584dec0726f84dbf22" 1008 | }, 1009 | "dist": { 1010 | "type": "zip", 1011 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22", 1012 | "reference": "937efb279bd37a375bcadf584dec0726f84dbf22", 1013 | "shasum": "" 1014 | }, 1015 | "require": { 1016 | "php": ">=5.3.3", 1017 | "sebastian/diff": "~1.2", 1018 | "sebastian/exporter": "~1.2" 1019 | }, 1020 | "require-dev": { 1021 | "phpunit/phpunit": "~4.4" 1022 | }, 1023 | "type": "library", 1024 | "extra": { 1025 | "branch-alias": { 1026 | "dev-master": "1.2.x-dev" 1027 | } 1028 | }, 1029 | "autoload": { 1030 | "classmap": [ 1031 | "src/" 1032 | ] 1033 | }, 1034 | "notification-url": "https://packagist.org/downloads/", 1035 | "license": [ 1036 | "BSD-3-Clause" 1037 | ], 1038 | "authors": [ 1039 | { 1040 | "name": "Jeff Welch", 1041 | "email": "whatthejeff@gmail.com" 1042 | }, 1043 | { 1044 | "name": "Volker Dusch", 1045 | "email": "github@wallbash.com" 1046 | }, 1047 | { 1048 | "name": "Bernhard Schussek", 1049 | "email": "bschussek@2bepublished.at" 1050 | }, 1051 | { 1052 | "name": "Sebastian Bergmann", 1053 | "email": "sebastian@phpunit.de" 1054 | } 1055 | ], 1056 | "description": "Provides the functionality to compare PHP values for equality", 1057 | "homepage": "http://www.github.com/sebastianbergmann/comparator", 1058 | "keywords": [ 1059 | "comparator", 1060 | "compare", 1061 | "equality" 1062 | ], 1063 | "time": "2015-07-26 15:48:44" 1064 | }, 1065 | { 1066 | "name": "sebastian/diff", 1067 | "version": "dev-master", 1068 | "source": { 1069 | "type": "git", 1070 | "url": "https://github.com/sebastianbergmann/diff.git", 1071 | "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" 1072 | }, 1073 | "dist": { 1074 | "type": "zip", 1075 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", 1076 | "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", 1077 | "shasum": "" 1078 | }, 1079 | "require": { 1080 | "php": ">=5.3.3" 1081 | }, 1082 | "require-dev": { 1083 | "phpunit/phpunit": "~4.8" 1084 | }, 1085 | "type": "library", 1086 | "extra": { 1087 | "branch-alias": { 1088 | "dev-master": "1.4-dev" 1089 | } 1090 | }, 1091 | "autoload": { 1092 | "classmap": [ 1093 | "src/" 1094 | ] 1095 | }, 1096 | "notification-url": "https://packagist.org/downloads/", 1097 | "license": [ 1098 | "BSD-3-Clause" 1099 | ], 1100 | "authors": [ 1101 | { 1102 | "name": "Kore Nordmann", 1103 | "email": "mail@kore-nordmann.de" 1104 | }, 1105 | { 1106 | "name": "Sebastian Bergmann", 1107 | "email": "sebastian@phpunit.de" 1108 | } 1109 | ], 1110 | "description": "Diff implementation", 1111 | "homepage": "https://github.com/sebastianbergmann/diff", 1112 | "keywords": [ 1113 | "diff" 1114 | ], 1115 | "time": "2015-12-08 07:14:41" 1116 | }, 1117 | { 1118 | "name": "sebastian/environment", 1119 | "version": "dev-master", 1120 | "source": { 1121 | "type": "git", 1122 | "url": "https://github.com/sebastianbergmann/environment.git", 1123 | "reference": "6e7133793a8e5a5714a551a8324337374be209df" 1124 | }, 1125 | "dist": { 1126 | "type": "zip", 1127 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6e7133793a8e5a5714a551a8324337374be209df", 1128 | "reference": "6e7133793a8e5a5714a551a8324337374be209df", 1129 | "shasum": "" 1130 | }, 1131 | "require": { 1132 | "php": ">=5.3.3" 1133 | }, 1134 | "require-dev": { 1135 | "phpunit/phpunit": "~4.4" 1136 | }, 1137 | "type": "library", 1138 | "extra": { 1139 | "branch-alias": { 1140 | "dev-master": "1.3.x-dev" 1141 | } 1142 | }, 1143 | "autoload": { 1144 | "classmap": [ 1145 | "src/" 1146 | ] 1147 | }, 1148 | "notification-url": "https://packagist.org/downloads/", 1149 | "license": [ 1150 | "BSD-3-Clause" 1151 | ], 1152 | "authors": [ 1153 | { 1154 | "name": "Sebastian Bergmann", 1155 | "email": "sebastian@phpunit.de" 1156 | } 1157 | ], 1158 | "description": "Provides functionality to handle HHVM/PHP environments", 1159 | "homepage": "http://www.github.com/sebastianbergmann/environment", 1160 | "keywords": [ 1161 | "Xdebug", 1162 | "environment", 1163 | "hhvm" 1164 | ], 1165 | "time": "2015-12-02 08:37:27" 1166 | }, 1167 | { 1168 | "name": "sebastian/exporter", 1169 | "version": "dev-master", 1170 | "source": { 1171 | "type": "git", 1172 | "url": "https://github.com/sebastianbergmann/exporter.git", 1173 | "reference": "f88f8936517d54ae6d589166810877fb2015d0a2" 1174 | }, 1175 | "dist": { 1176 | "type": "zip", 1177 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/f88f8936517d54ae6d589166810877fb2015d0a2", 1178 | "reference": "f88f8936517d54ae6d589166810877fb2015d0a2", 1179 | "shasum": "" 1180 | }, 1181 | "require": { 1182 | "php": ">=5.3.3", 1183 | "sebastian/recursion-context": "~1.0" 1184 | }, 1185 | "require-dev": { 1186 | "ext-mbstring": "*", 1187 | "phpunit/phpunit": "~4.4" 1188 | }, 1189 | "type": "library", 1190 | "extra": { 1191 | "branch-alias": { 1192 | "dev-master": "1.3.x-dev" 1193 | } 1194 | }, 1195 | "autoload": { 1196 | "classmap": [ 1197 | "src/" 1198 | ] 1199 | }, 1200 | "notification-url": "https://packagist.org/downloads/", 1201 | "license": [ 1202 | "BSD-3-Clause" 1203 | ], 1204 | "authors": [ 1205 | { 1206 | "name": "Jeff Welch", 1207 | "email": "whatthejeff@gmail.com" 1208 | }, 1209 | { 1210 | "name": "Volker Dusch", 1211 | "email": "github@wallbash.com" 1212 | }, 1213 | { 1214 | "name": "Bernhard Schussek", 1215 | "email": "bschussek@2bepublished.at" 1216 | }, 1217 | { 1218 | "name": "Sebastian Bergmann", 1219 | "email": "sebastian@phpunit.de" 1220 | }, 1221 | { 1222 | "name": "Adam Harvey", 1223 | "email": "aharvey@php.net" 1224 | } 1225 | ], 1226 | "description": "Provides the functionality to export PHP variables for visualization", 1227 | "homepage": "http://www.github.com/sebastianbergmann/exporter", 1228 | "keywords": [ 1229 | "export", 1230 | "exporter" 1231 | ], 1232 | "time": "2015-08-09 04:23:41" 1233 | }, 1234 | { 1235 | "name": "sebastian/global-state", 1236 | "version": "1.1.1", 1237 | "source": { 1238 | "type": "git", 1239 | "url": "https://github.com/sebastianbergmann/global-state.git", 1240 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" 1241 | }, 1242 | "dist": { 1243 | "type": "zip", 1244 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", 1245 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", 1246 | "shasum": "" 1247 | }, 1248 | "require": { 1249 | "php": ">=5.3.3" 1250 | }, 1251 | "require-dev": { 1252 | "phpunit/phpunit": "~4.2" 1253 | }, 1254 | "suggest": { 1255 | "ext-uopz": "*" 1256 | }, 1257 | "type": "library", 1258 | "extra": { 1259 | "branch-alias": { 1260 | "dev-master": "1.0-dev" 1261 | } 1262 | }, 1263 | "autoload": { 1264 | "classmap": [ 1265 | "src/" 1266 | ] 1267 | }, 1268 | "notification-url": "https://packagist.org/downloads/", 1269 | "license": [ 1270 | "BSD-3-Clause" 1271 | ], 1272 | "authors": [ 1273 | { 1274 | "name": "Sebastian Bergmann", 1275 | "email": "sebastian@phpunit.de" 1276 | } 1277 | ], 1278 | "description": "Snapshotting of global state", 1279 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 1280 | "keywords": [ 1281 | "global state" 1282 | ], 1283 | "time": "2015-10-12 03:26:01" 1284 | }, 1285 | { 1286 | "name": "sebastian/object-enumerator", 1287 | "version": "dev-master", 1288 | "source": { 1289 | "type": "git", 1290 | "url": "https://github.com/sebastianbergmann/object-enumerator.git", 1291 | "reference": "d4ca2fb70344987502567bc50081c03e6192fb26" 1292 | }, 1293 | "dist": { 1294 | "type": "zip", 1295 | "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/d4ca2fb70344987502567bc50081c03e6192fb26", 1296 | "reference": "d4ca2fb70344987502567bc50081c03e6192fb26", 1297 | "shasum": "" 1298 | }, 1299 | "require": { 1300 | "php": ">=5.6", 1301 | "sebastian/recursion-context": "~1.0" 1302 | }, 1303 | "require-dev": { 1304 | "phpunit/phpunit": "~5" 1305 | }, 1306 | "type": "library", 1307 | "extra": { 1308 | "branch-alias": { 1309 | "dev-master": "1.0.x-dev" 1310 | } 1311 | }, 1312 | "autoload": { 1313 | "classmap": [ 1314 | "src/" 1315 | ] 1316 | }, 1317 | "notification-url": "https://packagist.org/downloads/", 1318 | "license": [ 1319 | "BSD-3-Clause" 1320 | ], 1321 | "authors": [ 1322 | { 1323 | "name": "Sebastian Bergmann", 1324 | "email": "sebastian@phpunit.de" 1325 | } 1326 | ], 1327 | "description": "Traverses array structures and object graphs to enumerate all referenced objects", 1328 | "homepage": "https://github.com/sebastianbergmann/object-enumerator/", 1329 | "time": "2016-01-28 13:25:10" 1330 | }, 1331 | { 1332 | "name": "sebastian/recursion-context", 1333 | "version": "dev-master", 1334 | "source": { 1335 | "type": "git", 1336 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 1337 | "reference": "7ff5b1b3dcc55b8ab8ae61ef99d4730940856ee7" 1338 | }, 1339 | "dist": { 1340 | "type": "zip", 1341 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/7ff5b1b3dcc55b8ab8ae61ef99d4730940856ee7", 1342 | "reference": "7ff5b1b3dcc55b8ab8ae61ef99d4730940856ee7", 1343 | "shasum": "" 1344 | }, 1345 | "require": { 1346 | "php": ">=5.3.3" 1347 | }, 1348 | "require-dev": { 1349 | "phpunit/phpunit": "~4.4" 1350 | }, 1351 | "type": "library", 1352 | "extra": { 1353 | "branch-alias": { 1354 | "dev-master": "1.0.x-dev" 1355 | } 1356 | }, 1357 | "autoload": { 1358 | "classmap": [ 1359 | "src/" 1360 | ] 1361 | }, 1362 | "notification-url": "https://packagist.org/downloads/", 1363 | "license": [ 1364 | "BSD-3-Clause" 1365 | ], 1366 | "authors": [ 1367 | { 1368 | "name": "Jeff Welch", 1369 | "email": "whatthejeff@gmail.com" 1370 | }, 1371 | { 1372 | "name": "Sebastian Bergmann", 1373 | "email": "sebastian@phpunit.de" 1374 | }, 1375 | { 1376 | "name": "Adam Harvey", 1377 | "email": "aharvey@php.net" 1378 | } 1379 | ], 1380 | "description": "Provides functionality to recursively process PHP variables", 1381 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context", 1382 | "time": "2016-01-28 05:39:29" 1383 | }, 1384 | { 1385 | "name": "sebastian/resource-operations", 1386 | "version": "dev-master", 1387 | "source": { 1388 | "type": "git", 1389 | "url": "https://github.com/sebastianbergmann/resource-operations.git", 1390 | "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" 1391 | }, 1392 | "dist": { 1393 | "type": "zip", 1394 | "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", 1395 | "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", 1396 | "shasum": "" 1397 | }, 1398 | "require": { 1399 | "php": ">=5.6.0" 1400 | }, 1401 | "type": "library", 1402 | "extra": { 1403 | "branch-alias": { 1404 | "dev-master": "1.0.x-dev" 1405 | } 1406 | }, 1407 | "autoload": { 1408 | "classmap": [ 1409 | "src/" 1410 | ] 1411 | }, 1412 | "notification-url": "https://packagist.org/downloads/", 1413 | "license": [ 1414 | "BSD-3-Clause" 1415 | ], 1416 | "authors": [ 1417 | { 1418 | "name": "Sebastian Bergmann", 1419 | "email": "sebastian@phpunit.de" 1420 | } 1421 | ], 1422 | "description": "Provides a list of PHP built-in functions that operate on resources", 1423 | "homepage": "https://www.github.com/sebastianbergmann/resource-operations", 1424 | "time": "2015-07-28 20:34:47" 1425 | }, 1426 | { 1427 | "name": "sebastian/version", 1428 | "version": "dev-master", 1429 | "source": { 1430 | "type": "git", 1431 | "url": "https://github.com/sebastianbergmann/version.git", 1432 | "reference": "c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5" 1433 | }, 1434 | "dist": { 1435 | "type": "zip", 1436 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5", 1437 | "reference": "c829badbd8fdf16a0bad8aa7fa7971c029f1b9c5", 1438 | "shasum": "" 1439 | }, 1440 | "require": { 1441 | "php": ">=5.6" 1442 | }, 1443 | "type": "library", 1444 | "extra": { 1445 | "branch-alias": { 1446 | "dev-master": "2.0.x-dev" 1447 | } 1448 | }, 1449 | "autoload": { 1450 | "classmap": [ 1451 | "src/" 1452 | ] 1453 | }, 1454 | "notification-url": "https://packagist.org/downloads/", 1455 | "license": [ 1456 | "BSD-3-Clause" 1457 | ], 1458 | "authors": [ 1459 | { 1460 | "name": "Sebastian Bergmann", 1461 | "email": "sebastian@phpunit.de", 1462 | "role": "lead" 1463 | } 1464 | ], 1465 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 1466 | "homepage": "https://github.com/sebastianbergmann/version", 1467 | "time": "2016-02-04 12:56:52" 1468 | }, 1469 | { 1470 | "name": "symfony/polyfill-mbstring", 1471 | "version": "dev-master", 1472 | "source": { 1473 | "type": "git", 1474 | "url": "https://github.com/symfony/polyfill-mbstring.git", 1475 | "reference": "1289d16209491b584839022f29257ad859b8532d" 1476 | }, 1477 | "dist": { 1478 | "type": "zip", 1479 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/1289d16209491b584839022f29257ad859b8532d", 1480 | "reference": "1289d16209491b584839022f29257ad859b8532d", 1481 | "shasum": "" 1482 | }, 1483 | "require": { 1484 | "php": ">=5.3.3" 1485 | }, 1486 | "suggest": { 1487 | "ext-mbstring": "For best performance" 1488 | }, 1489 | "type": "library", 1490 | "extra": { 1491 | "branch-alias": { 1492 | "dev-master": "1.1-dev" 1493 | } 1494 | }, 1495 | "autoload": { 1496 | "psr-4": { 1497 | "Symfony\\Polyfill\\Mbstring\\": "" 1498 | }, 1499 | "files": [ 1500 | "bootstrap.php" 1501 | ] 1502 | }, 1503 | "notification-url": "https://packagist.org/downloads/", 1504 | "license": [ 1505 | "MIT" 1506 | ], 1507 | "authors": [ 1508 | { 1509 | "name": "Nicolas Grekas", 1510 | "email": "p@tchwork.com" 1511 | }, 1512 | { 1513 | "name": "Symfony Community", 1514 | "homepage": "https://symfony.com/contributors" 1515 | } 1516 | ], 1517 | "description": "Symfony polyfill for the Mbstring extension", 1518 | "homepage": "https://symfony.com", 1519 | "keywords": [ 1520 | "compatibility", 1521 | "mbstring", 1522 | "polyfill", 1523 | "portable", 1524 | "shim" 1525 | ], 1526 | "time": "2016-01-20 09:13:37" 1527 | }, 1528 | { 1529 | "name": "symfony/translation", 1530 | "version": "dev-master", 1531 | "source": { 1532 | "type": "git", 1533 | "url": "https://github.com/symfony/translation.git", 1534 | "reference": "74893d6cb2536d7ec0152a0cff48859e6c80aceb" 1535 | }, 1536 | "dist": { 1537 | "type": "zip", 1538 | "url": "https://api.github.com/repos/symfony/translation/zipball/74893d6cb2536d7ec0152a0cff48859e6c80aceb", 1539 | "reference": "74893d6cb2536d7ec0152a0cff48859e6c80aceb", 1540 | "shasum": "" 1541 | }, 1542 | "require": { 1543 | "php": ">=5.5.9", 1544 | "symfony/polyfill-mbstring": "~1.0" 1545 | }, 1546 | "conflict": { 1547 | "symfony/config": "<2.8" 1548 | }, 1549 | "require-dev": { 1550 | "psr/log": "~1.0", 1551 | "symfony/config": "~2.8|~3.0", 1552 | "symfony/intl": "~2.8|~3.0", 1553 | "symfony/yaml": "~2.8|~3.0" 1554 | }, 1555 | "suggest": { 1556 | "psr/log": "To use logging capability in translator", 1557 | "symfony/config": "", 1558 | "symfony/yaml": "" 1559 | }, 1560 | "type": "library", 1561 | "extra": { 1562 | "branch-alias": { 1563 | "dev-master": "3.1-dev" 1564 | } 1565 | }, 1566 | "autoload": { 1567 | "psr-4": { 1568 | "Symfony\\Component\\Translation\\": "" 1569 | }, 1570 | "exclude-from-classmap": [ 1571 | "/Tests/" 1572 | ] 1573 | }, 1574 | "notification-url": "https://packagist.org/downloads/", 1575 | "license": [ 1576 | "MIT" 1577 | ], 1578 | "authors": [ 1579 | { 1580 | "name": "Fabien Potencier", 1581 | "email": "fabien@symfony.com" 1582 | }, 1583 | { 1584 | "name": "Symfony Community", 1585 | "homepage": "https://symfony.com/contributors" 1586 | } 1587 | ], 1588 | "description": "Symfony Translation Component", 1589 | "homepage": "https://symfony.com", 1590 | "time": "2016-02-04 12:57:09" 1591 | }, 1592 | { 1593 | "name": "symfony/yaml", 1594 | "version": "dev-master", 1595 | "source": { 1596 | "type": "git", 1597 | "url": "https://github.com/symfony/yaml.git", 1598 | "reference": "91dbeb63c08bf4daf74b007d1a0cdc940d6c7efb" 1599 | }, 1600 | "dist": { 1601 | "type": "zip", 1602 | "url": "https://api.github.com/repos/symfony/yaml/zipball/91dbeb63c08bf4daf74b007d1a0cdc940d6c7efb", 1603 | "reference": "91dbeb63c08bf4daf74b007d1a0cdc940d6c7efb", 1604 | "shasum": "" 1605 | }, 1606 | "require": { 1607 | "php": ">=5.5.9" 1608 | }, 1609 | "type": "library", 1610 | "extra": { 1611 | "branch-alias": { 1612 | "dev-master": "3.1-dev" 1613 | } 1614 | }, 1615 | "autoload": { 1616 | "psr-4": { 1617 | "Symfony\\Component\\Yaml\\": "" 1618 | }, 1619 | "exclude-from-classmap": [ 1620 | "/Tests/" 1621 | ] 1622 | }, 1623 | "notification-url": "https://packagist.org/downloads/", 1624 | "license": [ 1625 | "MIT" 1626 | ], 1627 | "authors": [ 1628 | { 1629 | "name": "Fabien Potencier", 1630 | "email": "fabien@symfony.com" 1631 | }, 1632 | { 1633 | "name": "Symfony Community", 1634 | "homepage": "https://symfony.com/contributors" 1635 | } 1636 | ], 1637 | "description": "Symfony Yaml Component", 1638 | "homepage": "https://symfony.com", 1639 | "time": "2016-02-16 08:48:00" 1640 | } 1641 | ], 1642 | "aliases": [], 1643 | "minimum-stability": "dev", 1644 | "stability-flags": [], 1645 | "prefer-stable": false, 1646 | "prefer-lowest": false, 1647 | "platform": [], 1648 | "platform-dev": [] 1649 | } 1650 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | ./tests/ 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Matryoshka 2 | 3 | Matryoshka is a package for Laravel that provides Russian-Doll caching for your view logic. 4 | 5 | > Want to learn how this exact package was made from scratch? [See Laracasts.com](https://laracasts.com/series/russian-doll-caching-in-laravel). 6 | 7 | ## Installation 8 | 9 | ### Step 1: Composer 10 | 11 | From the command line, run: 12 | 13 | ``` 14 | composer require laracasts/matryoshka 15 | ``` 16 | 17 | ### Step 2: Service Provider 18 | 19 | For your Laravel app, open `config/app.php` and, within the `providers` array, append: 20 | 21 | ``` 22 | Laracasts\Matryoshka\MatryoshkaServiceProvider::class 23 | ``` 24 | 25 | This will bootstrap the package into Laravel. 26 | 27 | ### Step 3: Cache Driver 28 | 29 | For this package to function properly, you must use a Laravel cache driver that supports tagging (like `Cache::tags('foo')`). Drivers such as Memcached and Redis support this feature. 30 | 31 | Check your `.env` file, and ensure that your `CACHE_DRIVER` choice accomodates this requirement: 32 | 33 | ``` 34 | CACHE_DRIVER=memcached 35 | ``` 36 | 37 | > Have a look at [Laravel's cache configuration documentation](https://laravel.com/docs/5.2/cache#configuration), if you need any help. 38 | 39 | ## Usage 40 | 41 | ### The Basics 42 | 43 | With the package now installed, you may use the provided `@cache` Blade directive anywhere in your views, like so: 44 | 45 | ```html 46 | @cache('my-cache-key') 47 |
48 |

Hello World

49 |
50 | @endcache 51 | ``` 52 | 53 | By surrounding this block of HTML with the `@cache` and `@endcache` directives, we're asking the package to cache the given HTML. Now this example is trivial, however, you can imagine a more complex view that includes various nested caches, as well as lazy-loaded relationship calls that trigger additional database queries. After the initial page load that caches the HTML fragment, each subsequent refresh will instead pull from the cache. As such, those additional database queries will never be executed. 54 | 55 | Please keep in mind that, in production, this will cache the HTML fragment "forever." For local development, on the other hand, we'll automatically flush the relevant cache for you each time you refresh the page. That way, you may update your views and templates however you wish, without needing to worry about clearing the cache manually. 56 | 57 | Now because your production server will cache the fragments forever, you'll want to add a step to your deployment process that clears the relevant cache. 58 | 59 | ```php 60 | Cache::tags('views')->flush(); 61 | ``` 62 | 63 | ### Caching Models 64 | 65 | While you're free to hard-code any string for the cache key, the true power of Russian-Doll caching comes into play when we use a timestamp-based approach. 66 | 67 | Consider the following fragment: 68 | 69 | ```html 70 | @cache($post) 71 |
72 |

{{ $post->title }}>

73 |

Written By: {{ $post->author->username }}

74 | 75 |
{{ $post->body }}
76 |
77 | @endcache 78 | ``` 79 | 80 | In this example, we're passing the `$post` object, itself, to the `@cache` directive - rather than a string. The package will then look for a `getCacheKey()` method on the model. We've already done that work for you; just have your Eloquent model use the `Laracasts\Matryoshka\Cacheable` trait, like so: 81 | 82 | ```php 83 | use Laracasts\Matryoshka\Cacheable; 84 | 85 | class Post extends Eloquent 86 | { 87 | use Cacheable; 88 | } 89 | ``` 90 | 91 | Alternatively, you may use this trait on a parent class that each of your Eloquent models extend. 92 | 93 | That should do it! Now, the cache key for this fragment will include the object's `id` and `updated_at` timestamp: `App\Post/1-13241235123`. 94 | 95 | > The key is that, because we factor the `updated_at` timestamp into the cache key, whenever you update the given post, the cache key will change. This will then, in effect, bust the cache! 96 | 97 | #### Touching 98 | 99 | In order for this technique to work properly, it's vital that we have some mechanism to alert parent relationships (and subsequently bust parent caches) each time a model is updated. Here's a basic workflow: 100 | 101 | 1. Model is updated in the database. 102 | 2. Its `updated_at` timestamp is refreshed, triggering a new cache key for the instance. 103 | 3. The model "touches" (or pings) its parent. 104 | 4. The parent's `updated_at` timestamp, too, is updated, which busts its associated cache. 105 | 5. Only the affected fragments re-render. All other cached items remain untouched. 106 | 107 | Luckily, Laravel offers this "touch" functionality out of the box. Consider a `Note` object that needs to alert its parent `Card` relationship each time an update occurs. 108 | 109 | ```php 110 | belongsTo(Card::class); 126 | } 127 | } 128 | ``` 129 | 130 | Notice the `$touches = ['card']` portion. This instructs Laravel to ping the `card` relationship's timestamps each time the note is updated. 131 | 132 | Now, everything is in place. You might render your view, like so: 133 | 134 | **resources/views/cards/_card.blade.php** 135 | 136 | ```html 137 | @cache($card) 138 |
139 |

{{ $card->title }}

140 | 141 | 146 |
147 | @endcache 148 | ``` 149 | 150 | **resources/views/cards/_note.blade.php** 151 | 152 | ```html 153 | @cache($note) 154 |
  • {{ $note->body }}
  • 155 | @endcache 156 | ``` 157 | 158 | Notice the Russian-Doll style cascading for our caches; that's the key. If any note is updated, its individual cache will clear - along with its parent - but any siblings will remain untouched. 159 | 160 | ### Caching Collections 161 | 162 | You won't always want to cache model instances; you may wish to cache a Laravel collection as well! No problem. 163 | 164 | ```html 165 | @cache($posts) 166 | @foreach ($posts as $post) 167 | @include ('post') 168 | @endforeach 169 | @endcache 170 | ``` 171 | 172 | Now, as long as the `$posts` collection contents does not change, that `@foreach` section will never run. Instead, as always, we'll pull from the cache. 173 | 174 | Behind the scenes, this package will detect that you've passed a Laravel collection to the `cache` directive, and will subsequently generate a unique cache key for the collection. 175 | 176 | ## FAQ 177 | 178 | **1. Is there any way to override the cache key for a model instance?** 179 | 180 | Yes. Let's say you have: 181 | 182 | ```html 183 | @cache($post) 184 |
    view here
    185 | @endcache 186 | ``` 187 | 188 | Behind the scenes, we'll look for a `getCacheKey` method on the model. Now, as mentioned above, you can use the `Laracasts\Matryoshka\Cacheable` trait to instantly import this functionality. Alternatively, you may pass a second argument to the `@cache` directive, like this: 189 | 190 | ```html 191 | @cache($post, 'my-custom-key') 192 |
    view here
    193 | @endcache 194 | ``` 195 | 196 | This instructs the package to use `my-custom-key` for the cache instead. This can be useful for pagination and other related tasks. 197 | 198 | **2. Where can I learn more about this approach to caching?** 199 | 200 | Give these two articles a read: 201 | 202 | - https://signalvnoise.com/posts/3112-how-basecamp-next-got-to-be-so-damn-fast-without-using-much-client-side-ui 203 | - https://signalvnoise.com/posts/3113-how-key-based-cache-expiration-works 204 | 205 | And, if you enjoy Laracasts, [watch the creation of this package from scratch here.](https://laracasts.com/series/russian-doll-caching-in-laravel) 206 | -------------------------------------------------------------------------------- /src/BladeDirective.php: -------------------------------------------------------------------------------- 1 | cache = $cache; 31 | } 32 | 33 | /** 34 | * Handle the @cache setup. 35 | * 36 | * @param mixed $model 37 | * @param string|null $key 38 | */ 39 | public function setUp($model, $key = null) 40 | { 41 | ob_start(); 42 | 43 | $this->keys[] = $key = $this->normalizeKey($model, $key); 44 | 45 | return $this->cache->has($key); 46 | } 47 | 48 | /** 49 | * Handle the @endcache teardown. 50 | */ 51 | public function tearDown() 52 | { 53 | return $this->cache->put( 54 | array_pop($this->keys), ob_get_clean() 55 | ); 56 | } 57 | 58 | /** 59 | * Normalize the cache key. 60 | * 61 | * @param mixed $item 62 | * @param string|null $key 63 | */ 64 | protected function normalizeKey($item, $key = null) 65 | { 66 | // If the user wants to provide their own cache 67 | // key, we'll opt for that. 68 | if (is_string($item) || is_string($key)) { 69 | return is_string($item) ? $item : $key; 70 | } 71 | 72 | // Otherwise we'll try to use the item to calculate 73 | // the cache key, itself. 74 | if (is_object($item) && method_exists($item, 'getCacheKey')) { 75 | return $item->getCacheKey(); 76 | } 77 | 78 | // If we're dealing with a collection, we'll 79 | // use a hashed version of its contents. 80 | if ($item instanceof \Illuminate\Support\Collection) { 81 | return md5($item); 82 | } 83 | 84 | throw new Exception('Could not determine an appropriate cache key.'); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/Cacheable.php: -------------------------------------------------------------------------------- 1 | getKey(), 15 | $this->updated_at->timestamp 16 | ); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/FlushViews.php: -------------------------------------------------------------------------------- 1 | flush(); 18 | 19 | return $next($request); 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /src/MatryoshkaServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->isLocal()) { 19 | $kernel->pushMiddleware('Laracasts\Matryoshka\FlushViews'); 20 | } 21 | 22 | Blade::directive('cache', function ($expression) { 23 | $version = explode('.', $this->app::VERSION); 24 | // Starting with laravel 5.3 the parens are not included in the expression string. 25 | if ($version[1] > 2) { 26 | return "setUp({$expression})) : ?>"; 27 | } 28 | return "setUp{$expression}) : ?>"; 29 | }); 30 | 31 | Blade::directive('endcache', function () { 32 | return "tearDown() ?>"; 33 | }); 34 | } 35 | 36 | /** 37 | * Register any application services. 38 | */ 39 | public function register() 40 | { 41 | $this->app->singleton(BladeDirective::class); 42 | } 43 | } 44 | 45 | -------------------------------------------------------------------------------- /src/RussianCaching.php: -------------------------------------------------------------------------------- 1 | cache = $cache; 24 | } 25 | 26 | /** 27 | * Put to the cache. 28 | * 29 | * @param mixed $key 30 | * @param string $fragment 31 | */ 32 | public function put($key, $fragment) 33 | { 34 | $key = $this->normalizeCacheKey($key); 35 | 36 | return $this->cache 37 | ->tags('views') 38 | ->rememberForever($key, function () use ($fragment) { 39 | return $fragment; 40 | }); 41 | } 42 | 43 | /** 44 | * Check if the given key exists in the cache. 45 | * 46 | * @param mixed $key 47 | */ 48 | public function has($key) 49 | { 50 | $key = $this->normalizeCacheKey($key); 51 | 52 | return $this->cache 53 | ->tags('views') 54 | ->has($key); 55 | } 56 | 57 | /** 58 | * Normalize the cache key. 59 | * 60 | * @param mixed $key 61 | */ 62 | protected function normalizeCacheKey($key) 63 | { 64 | if (is_object($key) && method_exists($key, 'getCacheKey')) { 65 | return $key->getCacheKey(); 66 | } 67 | 68 | return $key; 69 | } 70 | } 71 | 72 | -------------------------------------------------------------------------------- /tests/BladeDirectiveTest.php: -------------------------------------------------------------------------------- 1 | createNewCacheDirective(); 14 | 15 | $isCached = $directive->setUp($post = $this->makePost()); 16 | 17 | $this->assertFalse($isCached); 18 | 19 | echo '
    fragment
    '; 20 | 21 | $cachedFragment = $directive->tearDown(); 22 | 23 | $this->assertEquals('
    fragment
    ', $cachedFragment); 24 | $this->assertTrue($this->doll->has($post)); 25 | } 26 | 27 | /** @test */ 28 | function it_can_use_a_string_as_the_cache_key() 29 | { 30 | $doll = $this->prophesize(RussianCaching::class); 31 | $directive = new BladeDirective($doll->reveal()); 32 | 33 | $doll->has('foo')->shouldBeCalled(); 34 | $directive->setUp('foo'); 35 | 36 | ob_end_clean(); // Since we're not doing teardown. 37 | } 38 | 39 | /** @test */ 40 | function it_can_use_a_collection_as_the_cache_key() 41 | { 42 | $doll = $this->prophesize(RussianCaching::class); 43 | $directive = new BladeDirective($doll->reveal()); 44 | 45 | $collection = collect(['one', 'two']); 46 | $doll->has(md5($collection))->shouldBeCalled(); 47 | $directive->setUp($collection); 48 | 49 | ob_end_clean(); // Since we're not doing teardown. 50 | } 51 | 52 | /** @test */ 53 | function it_can_use_the_model_to_determine_the_cache_key() 54 | { 55 | $doll = $this->prophesize(RussianCaching::class); 56 | $directive = new BladeDirective($doll->reveal()); 57 | 58 | $post = $this->makePost(); 59 | $doll->has('Post/1-' . $post->updated_at->timestamp)->shouldBeCalled(); 60 | $directive->setUp($post); 61 | 62 | ob_end_clean(); // Since we're not doing teardown. 63 | } 64 | 65 | /** @test */ 66 | function it_can_use_a_string_to_override_the_models_cache_key() 67 | { 68 | $doll = $this->prophesize(RussianCaching::class); 69 | $directive = new BladeDirective($doll->reveal()); 70 | 71 | $doll->has('override-key')->shouldBeCalled(); 72 | $directive->setUp($this->makePost(), 'override-key'); 73 | 74 | ob_end_clean(); // Since we're not doing teardown. 75 | } 76 | 77 | 78 | /** 79 | * @test 80 | * @expectedException Exception 81 | * */ 82 | function it_throws_an_exception_if_it_cannot_determine_the_cache_key() 83 | { 84 | $directive = $this->createNewCacheDirective(); 85 | 86 | $directive->setUp(new UnCacheablePost); 87 | } 88 | 89 | protected function createNewCacheDirective() 90 | { 91 | $cache = new \Illuminate\Cache\Repository( 92 | new \Illuminate\Cache\ArrayStore 93 | ); 94 | 95 | $this->doll = new RussianCaching($cache); 96 | 97 | return new BladeDirective($this->doll); 98 | } 99 | } 100 | 101 | class UnCacheablePost extends \Illuminate\Database\Eloquent\Model {} 102 | -------------------------------------------------------------------------------- /tests/CacheableTest.php: -------------------------------------------------------------------------------- 1 | makePost(); 9 | 10 | $this->assertEquals( 11 | 'Post/1-'.$model->updated_at->timestamp, 12 | $model->getCacheKey() 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/RussianCachingTest.php: -------------------------------------------------------------------------------- 1 | makePost(); 11 | 12 | $cache = new \Illuminate\Cache\Repository( 13 | new \Illuminate\Cache\ArrayStore 14 | ); 15 | 16 | $cache = new RussianCaching($cache); 17 | 18 | $cache->put($post, '
    view fragment
    '); 19 | 20 | $this->assertTrue($cache->has($post->getCacheKey())); 21 | $this->assertTrue($cache->has($post)); 22 | } 23 | 24 | } 25 | 26 | -------------------------------------------------------------------------------- /tests/TestCase.php: -------------------------------------------------------------------------------- 1 | setUpDatabase(); 10 | $this->migrateTables(); 11 | } 12 | 13 | protected function setUpDatabase() 14 | { 15 | $database = new DB; 16 | 17 | $database->addConnection(['driver' => 'sqlite', 'database' => ':memory:']); 18 | $database->bootEloquent(); 19 | $database->setAsGlobal(); 20 | } 21 | 22 | protected function migrateTables() 23 | { 24 | DB::schema()->create('posts', function ($table) { 25 | $table->increments('id'); 26 | $table->string('title'); 27 | $table->timestamps(); 28 | }); 29 | } 30 | 31 | protected function makePost() 32 | { 33 | $post = new Post; 34 | $post->title = 'Some title'; 35 | $post->save(); 36 | 37 | return $post; 38 | } 39 | } 40 | 41 | class Post extends \Illuminate\Database\Eloquent\Model 42 | { 43 | use Laracasts\Matryoshka\Cacheable; 44 | } 45 | --------------------------------------------------------------------------------