├── .gitignore ├── README.md ├── composer.json ├── composer.lock ├── examples └── extend │ ├── Test │ ├── Http │ │ └── Controllers │ │ │ └── TestController.php │ ├── TestPlugin.php │ ├── routes.php │ └── views │ │ └── test.blade.php │ └── TestExtension │ ├── Plugins │ └── Test │ │ └── Http │ │ └── Controllers │ │ └── TestController.php │ └── TestExtensionPlugin.php └── src ├── ClassLoader.php ├── Plugin.php ├── PluginExtender.php ├── PluginManager.php └── PluginServiceProvider.php /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | /.idea/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # laravel-plugins 2 | Plugin system for Laravel 5.x and Lumen 5.x. 3 | Plugins can overwrite and extend each other. 4 | 5 | ## Usage 6 | For Lumen add to bootstrap/app.php: 7 | `$app->register(\Oneso\LaravelPlugins\PluginServiceProvider::class);` 8 | 9 | For Laravel add to 'providers' array in config/app.php: 10 | `\Oneso\LaravelPlugins\PluginServiceProvider::class,` 11 | 12 | ## Create a plugin 13 | 14 | ### Structure 15 | Plugins must be in app/Plugins. Example plugin structure: 16 | - Test 17 | - Http 18 | - Controllers 19 | - TestController.php 20 | - views 21 | - test.blade.php 22 | - migrations 23 | - 2018_06_15_000000_create_test_table.php 24 | - routes.php 25 | - TestPlugin.php 26 | 27 | The TestPlugin class must extend the Oneso\LaravelPlugins\Plugin class, containing a unique $name property and a boot() method. 28 | 29 | ### Views 30 | In the boot() method of your plugin call `$this->enableViews()`. 31 | Optional you can pass a relative path to the views directory, default to `views`. 32 | Views automatically have a namespace (`"plugin:{name}"`), the name is defined by the the main plugin class in a camel case format, with `Plugin` stripped from the end. For the example above it would be `plugin:test`. 33 | To render a view you can either write the namespace yourself or use the helper method `view()` in the plugin class. For example `view('plugin:test::some.view.name');` 34 | 35 | ### Routes 36 | In the boot() method of your plugin call `$this->enableRoutes()`. 37 | Optional you can pass a relative path to the routes file, default to `routes.php`. 38 | You automatically have access to the `$app` variable. 39 | Routes are automatically grouped to your plugin namespace, so you only have to type the controller name without the namespace. 40 | 41 | ### Controllers 42 | Controllers must be in PluginDirectory->Http->Controllers. 43 | 44 | ### Migrations 45 | In the boot() method of your plugin call `$this->enableMigrations()`. 46 | Optional you can pass a relative path to the migrations directory, default to `migrations`. 47 | Keep in mind that migrations must follow the `yyyy_mm_dd_tttt_.php` naming convention, for example `2014_10_12_000000_create_users_table.php` would be a valid migration. 48 | 49 | ### How to extend another plugin 50 | see examples/extend 51 | 52 | ## ToDo 53 | - Move plugin directory and project namespace to publishable config file 54 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "oneso/laravel-plugins", 3 | "description": "A Laravel and Lumen plugin system", 4 | "license": "MIT", 5 | "authors": [ 6 | { 7 | "name": "Marcel Görtz", 8 | "email": "goertz.marcel@gmail.com" 9 | } 10 | ], 11 | "minimum-stability": "stable", 12 | "require": { 13 | "php": ">=5.5.9" 14 | }, 15 | "autoload": { 16 | "psr-4": { 17 | "Oneso\\LaravelPlugins\\": "src/" 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /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": "b6780106ebf781f45e3616e01a897915", 8 | "content-hash": "37567455ed350aa56f3b50a90aa269b6", 9 | "packages": [ 10 | { 11 | "name": "doctrine/inflector", 12 | "version": "v1.1.0", 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/auth", 79 | "version": "v5.2.21", 80 | "source": { 81 | "type": "git", 82 | "url": "https://github.com/illuminate/auth.git", 83 | "reference": "e2e9a37b225f0598f7e7ff78d402c3d2cb81a604" 84 | }, 85 | "dist": { 86 | "type": "zip", 87 | "url": "https://api.github.com/repos/illuminate/auth/zipball/e2e9a37b225f0598f7e7ff78d402c3d2cb81a604", 88 | "reference": "e2e9a37b225f0598f7e7ff78d402c3d2cb81a604", 89 | "shasum": "" 90 | }, 91 | "require": { 92 | "illuminate/contracts": "5.2.*", 93 | "illuminate/http": "5.2.*", 94 | "illuminate/support": "5.2.*", 95 | "nesbot/carbon": "~1.20", 96 | "php": ">=5.5.9" 97 | }, 98 | "suggest": { 99 | "illuminate/console": "Required to use the auth:clear-resets command (5.2.*).", 100 | "illuminate/session": "Required to use the session based guard (5.2.*)" 101 | }, 102 | "type": "library", 103 | "extra": { 104 | "branch-alias": { 105 | "dev-master": "5.2-dev" 106 | } 107 | }, 108 | "autoload": { 109 | "psr-4": { 110 | "Illuminate\\Auth\\": "" 111 | } 112 | }, 113 | "notification-url": "https://packagist.org/downloads/", 114 | "license": [ 115 | "MIT" 116 | ], 117 | "authors": [ 118 | { 119 | "name": "Taylor Otwell", 120 | "email": "taylorotwell@gmail.com" 121 | } 122 | ], 123 | "description": "The Illuminate Auth package.", 124 | "homepage": "http://laravel.com", 125 | "time": "2016-02-22 13:55:56" 126 | }, 127 | { 128 | "name": "illuminate/broadcasting", 129 | "version": "v5.2.21", 130 | "source": { 131 | "type": "git", 132 | "url": "https://github.com/illuminate/broadcasting.git", 133 | "reference": "9247b5ec092472d5e49d7d550b7683bbd6d9587e" 134 | }, 135 | "dist": { 136 | "type": "zip", 137 | "url": "https://api.github.com/repos/illuminate/broadcasting/zipball/9247b5ec092472d5e49d7d550b7683bbd6d9587e", 138 | "reference": "9247b5ec092472d5e49d7d550b7683bbd6d9587e", 139 | "shasum": "" 140 | }, 141 | "require": { 142 | "illuminate/contracts": "5.2.*", 143 | "illuminate/support": "5.2.*", 144 | "php": ">=5.5.9" 145 | }, 146 | "suggest": { 147 | "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (~2.0)." 148 | }, 149 | "type": "library", 150 | "extra": { 151 | "branch-alias": { 152 | "dev-master": "5.2-dev" 153 | } 154 | }, 155 | "autoload": { 156 | "psr-4": { 157 | "Illuminate\\Broadcasting\\": "" 158 | } 159 | }, 160 | "notification-url": "https://packagist.org/downloads/", 161 | "license": [ 162 | "MIT" 163 | ], 164 | "authors": [ 165 | { 166 | "name": "Taylor Otwell", 167 | "email": "taylorotwell@gmail.com" 168 | } 169 | ], 170 | "description": "The Illuminate Broadcasting package.", 171 | "homepage": "http://laravel.com", 172 | "time": "2015-12-24 14:23:14" 173 | }, 174 | { 175 | "name": "illuminate/bus", 176 | "version": "v5.2.21", 177 | "source": { 178 | "type": "git", 179 | "url": "https://github.com/illuminate/bus.git", 180 | "reference": "93e30593dafe249f83f08effc5340aace8551f98" 181 | }, 182 | "dist": { 183 | "type": "zip", 184 | "url": "https://api.github.com/repos/illuminate/bus/zipball/93e30593dafe249f83f08effc5340aace8551f98", 185 | "reference": "93e30593dafe249f83f08effc5340aace8551f98", 186 | "shasum": "" 187 | }, 188 | "require": { 189 | "illuminate/contracts": "5.2.*", 190 | "illuminate/pipeline": "5.2.*", 191 | "illuminate/support": "5.2.*", 192 | "php": ">=5.5.9" 193 | }, 194 | "type": "library", 195 | "extra": { 196 | "branch-alias": { 197 | "dev-master": "5.2-dev" 198 | } 199 | }, 200 | "autoload": { 201 | "psr-4": { 202 | "Illuminate\\Bus\\": "" 203 | } 204 | }, 205 | "notification-url": "https://packagist.org/downloads/", 206 | "license": [ 207 | "MIT" 208 | ], 209 | "authors": [ 210 | { 211 | "name": "Taylor Otwell", 212 | "email": "taylorotwell@gmail.com" 213 | } 214 | ], 215 | "description": "The Illuminate Bus package.", 216 | "homepage": "http://laravel.com", 217 | "time": "2015-12-05 22:11:33" 218 | }, 219 | { 220 | "name": "illuminate/cache", 221 | "version": "v5.2.21", 222 | "source": { 223 | "type": "git", 224 | "url": "https://github.com/illuminate/cache.git", 225 | "reference": "ce878db215d9c0f763af396cf608d08710574424" 226 | }, 227 | "dist": { 228 | "type": "zip", 229 | "url": "https://api.github.com/repos/illuminate/cache/zipball/ce878db215d9c0f763af396cf608d08710574424", 230 | "reference": "ce878db215d9c0f763af396cf608d08710574424", 231 | "shasum": "" 232 | }, 233 | "require": { 234 | "illuminate/contracts": "5.2.*", 235 | "illuminate/support": "5.2.*", 236 | "nesbot/carbon": "~1.20", 237 | "php": ">=5.5.9" 238 | }, 239 | "suggest": { 240 | "illuminate/database": "Required to use the database cache driver (5.2.*).", 241 | "illuminate/filesystem": "Required to use the file cache driver (5.2.*).", 242 | "illuminate/redis": "Required to use the redis cache driver (5.2.*)." 243 | }, 244 | "type": "library", 245 | "extra": { 246 | "branch-alias": { 247 | "dev-master": "5.2-dev" 248 | } 249 | }, 250 | "autoload": { 251 | "psr-4": { 252 | "Illuminate\\Cache\\": "" 253 | } 254 | }, 255 | "notification-url": "https://packagist.org/downloads/", 256 | "license": [ 257 | "MIT" 258 | ], 259 | "authors": [ 260 | { 261 | "name": "Taylor Otwell", 262 | "email": "taylorotwell@gmail.com" 263 | } 264 | ], 265 | "description": "The Illuminate Cache package.", 266 | "homepage": "http://laravel.com", 267 | "time": "2016-02-05 14:57:25" 268 | }, 269 | { 270 | "name": "illuminate/config", 271 | "version": "v5.2.21", 272 | "source": { 273 | "type": "git", 274 | "url": "https://github.com/illuminate/config.git", 275 | "reference": "c7a54f3d4cc28b24799433b8f8656ccca42ff3f1" 276 | }, 277 | "dist": { 278 | "type": "zip", 279 | "url": "https://api.github.com/repos/illuminate/config/zipball/c7a54f3d4cc28b24799433b8f8656ccca42ff3f1", 280 | "reference": "c7a54f3d4cc28b24799433b8f8656ccca42ff3f1", 281 | "shasum": "" 282 | }, 283 | "require": { 284 | "illuminate/contracts": "5.2.*", 285 | "illuminate/filesystem": "5.2.*", 286 | "illuminate/support": "5.2.*", 287 | "php": ">=5.5.9" 288 | }, 289 | "type": "library", 290 | "extra": { 291 | "branch-alias": { 292 | "dev-master": "5.2-dev" 293 | } 294 | }, 295 | "autoload": { 296 | "psr-4": { 297 | "Illuminate\\Config\\": "" 298 | } 299 | }, 300 | "notification-url": "https://packagist.org/downloads/", 301 | "license": [ 302 | "MIT" 303 | ], 304 | "authors": [ 305 | { 306 | "name": "Taylor Otwell", 307 | "email": "taylorotwell@gmail.com" 308 | } 309 | ], 310 | "description": "The Illuminate Config package.", 311 | "homepage": "http://laravel.com", 312 | "time": "2015-06-22 20:36:58" 313 | }, 314 | { 315 | "name": "illuminate/console", 316 | "version": "v5.2.21", 317 | "source": { 318 | "type": "git", 319 | "url": "https://github.com/illuminate/console.git", 320 | "reference": "a58e77d91c949eed906d3b8c67e0f0ad9246ee96" 321 | }, 322 | "dist": { 323 | "type": "zip", 324 | "url": "https://api.github.com/repos/illuminate/console/zipball/a58e77d91c949eed906d3b8c67e0f0ad9246ee96", 325 | "reference": "a58e77d91c949eed906d3b8c67e0f0ad9246ee96", 326 | "shasum": "" 327 | }, 328 | "require": { 329 | "illuminate/contracts": "5.2.*", 330 | "illuminate/support": "5.2.*", 331 | "nesbot/carbon": "~1.20", 332 | "php": ">=5.5.9", 333 | "symfony/console": "2.8.*|3.0.*" 334 | }, 335 | "suggest": { 336 | "guzzlehttp/guzzle": "Required to use the ping methods on schedules (~5.3|~6.0).", 337 | "mtdowling/cron-expression": "Required to use scheduling component (~1.0).", 338 | "symfony/process": "Required to use scheduling component (2.8.*|3.0.*)." 339 | }, 340 | "type": "library", 341 | "extra": { 342 | "branch-alias": { 343 | "dev-master": "5.2-dev" 344 | } 345 | }, 346 | "autoload": { 347 | "psr-4": { 348 | "Illuminate\\Console\\": "" 349 | } 350 | }, 351 | "notification-url": "https://packagist.org/downloads/", 352 | "license": [ 353 | "MIT" 354 | ], 355 | "authors": [ 356 | { 357 | "name": "Taylor Otwell", 358 | "email": "taylorotwell@gmail.com" 359 | } 360 | ], 361 | "description": "The Illuminate Console package.", 362 | "homepage": "http://laravel.com", 363 | "time": "2016-02-22 14:14:58" 364 | }, 365 | { 366 | "name": "illuminate/container", 367 | "version": "v5.2.21", 368 | "source": { 369 | "type": "git", 370 | "url": "https://github.com/illuminate/container.git", 371 | "reference": "ba7a8b3c24535ab102ebe9738a0003846c372b95" 372 | }, 373 | "dist": { 374 | "type": "zip", 375 | "url": "https://api.github.com/repos/illuminate/container/zipball/ba7a8b3c24535ab102ebe9738a0003846c372b95", 376 | "reference": "ba7a8b3c24535ab102ebe9738a0003846c372b95", 377 | "shasum": "" 378 | }, 379 | "require": { 380 | "illuminate/contracts": "5.2.*", 381 | "php": ">=5.5.9" 382 | }, 383 | "type": "library", 384 | "extra": { 385 | "branch-alias": { 386 | "dev-master": "5.2-dev" 387 | } 388 | }, 389 | "autoload": { 390 | "psr-4": { 391 | "Illuminate\\Container\\": "" 392 | } 393 | }, 394 | "notification-url": "https://packagist.org/downloads/", 395 | "license": [ 396 | "MIT" 397 | ], 398 | "authors": [ 399 | { 400 | "name": "Taylor Otwell", 401 | "email": "taylorotwell@gmail.com" 402 | } 403 | ], 404 | "description": "The Illuminate Container package.", 405 | "homepage": "http://laravel.com", 406 | "time": "2016-02-22 06:42:06" 407 | }, 408 | { 409 | "name": "illuminate/contracts", 410 | "version": "v5.2.21", 411 | "source": { 412 | "type": "git", 413 | "url": "https://github.com/illuminate/contracts.git", 414 | "reference": "eea3cf7ce90651e067a914d16383b019da45fcb5" 415 | }, 416 | "dist": { 417 | "type": "zip", 418 | "url": "https://api.github.com/repos/illuminate/contracts/zipball/eea3cf7ce90651e067a914d16383b019da45fcb5", 419 | "reference": "eea3cf7ce90651e067a914d16383b019da45fcb5", 420 | "shasum": "" 421 | }, 422 | "require": { 423 | "php": ">=5.5.9" 424 | }, 425 | "type": "library", 426 | "extra": { 427 | "branch-alias": { 428 | "dev-master": "5.2-dev" 429 | } 430 | }, 431 | "autoload": { 432 | "psr-4": { 433 | "Illuminate\\Contracts\\": "" 434 | } 435 | }, 436 | "notification-url": "https://packagist.org/downloads/", 437 | "license": [ 438 | "MIT" 439 | ], 440 | "authors": [ 441 | { 442 | "name": "Taylor Otwell", 443 | "email": "taylorotwell@gmail.com" 444 | } 445 | ], 446 | "description": "The Illuminate Contracts package.", 447 | "homepage": "http://laravel.com", 448 | "time": "2016-02-22 09:18:57" 449 | }, 450 | { 451 | "name": "illuminate/database", 452 | "version": "v5.2.21", 453 | "source": { 454 | "type": "git", 455 | "url": "https://github.com/illuminate/database.git", 456 | "reference": "8b0068c326652332fd364399f4d8cce894953172" 457 | }, 458 | "dist": { 459 | "type": "zip", 460 | "url": "https://api.github.com/repos/illuminate/database/zipball/8b0068c326652332fd364399f4d8cce894953172", 461 | "reference": "8b0068c326652332fd364399f4d8cce894953172", 462 | "shasum": "" 463 | }, 464 | "require": { 465 | "illuminate/container": "5.2.*", 466 | "illuminate/contracts": "5.2.*", 467 | "illuminate/support": "5.2.*", 468 | "nesbot/carbon": "~1.20", 469 | "php": ">=5.5.9" 470 | }, 471 | "suggest": { 472 | "doctrine/dbal": "Required to rename columns and drop SQLite columns (~2.4).", 473 | "fzaninotto/faker": "Required to use the eloquent factory builder (~1.4).", 474 | "illuminate/console": "Required to use the database commands (5.2.*).", 475 | "illuminate/events": "Required to use the observers with Eloquent (5.2.*).", 476 | "illuminate/filesystem": "Required to use the migrations (5.2.*).", 477 | "illuminate/pagination": "Required to paginate the result set (5.2.*)." 478 | }, 479 | "type": "library", 480 | "extra": { 481 | "branch-alias": { 482 | "dev-master": "5.2-dev" 483 | } 484 | }, 485 | "autoload": { 486 | "psr-4": { 487 | "Illuminate\\Database\\": "" 488 | } 489 | }, 490 | "notification-url": "https://packagist.org/downloads/", 491 | "license": [ 492 | "MIT" 493 | ], 494 | "authors": [ 495 | { 496 | "name": "Taylor Otwell", 497 | "email": "taylorotwell@gmail.com" 498 | } 499 | ], 500 | "description": "The Illuminate Database package.", 501 | "homepage": "http://laravel.com", 502 | "keywords": [ 503 | "database", 504 | "laravel", 505 | "orm", 506 | "sql" 507 | ], 508 | "time": "2016-02-24 15:02:47" 509 | }, 510 | { 511 | "name": "illuminate/encryption", 512 | "version": "v5.2.21", 513 | "source": { 514 | "type": "git", 515 | "url": "https://github.com/illuminate/encryption.git", 516 | "reference": "85010b0cd33a77d0e8825822f0c448debd8f9100" 517 | }, 518 | "dist": { 519 | "type": "zip", 520 | "url": "https://api.github.com/repos/illuminate/encryption/zipball/85010b0cd33a77d0e8825822f0c448debd8f9100", 521 | "reference": "85010b0cd33a77d0e8825822f0c448debd8f9100", 522 | "shasum": "" 523 | }, 524 | "require": { 525 | "ext-mbstring": "*", 526 | "ext-openssl": "*", 527 | "illuminate/contracts": "5.2.*", 528 | "illuminate/support": "5.2.*", 529 | "php": ">=5.5.9" 530 | }, 531 | "suggest": { 532 | "paragonie/random_compat": "Provides a compatible interface like PHP7's random_bytes() in PHP 5 projects (~1.1)." 533 | }, 534 | "type": "library", 535 | "extra": { 536 | "branch-alias": { 537 | "dev-master": "5.2-dev" 538 | } 539 | }, 540 | "autoload": { 541 | "psr-4": { 542 | "Illuminate\\Encryption\\": "" 543 | } 544 | }, 545 | "notification-url": "https://packagist.org/downloads/", 546 | "license": [ 547 | "MIT" 548 | ], 549 | "authors": [ 550 | { 551 | "name": "Taylor Otwell", 552 | "email": "taylorotwell@gmail.com" 553 | } 554 | ], 555 | "description": "The Illuminate Encryption package.", 556 | "homepage": "http://laravel.com", 557 | "time": "2016-01-13 09:25:36" 558 | }, 559 | { 560 | "name": "illuminate/events", 561 | "version": "v5.2.21", 562 | "source": { 563 | "type": "git", 564 | "url": "https://github.com/illuminate/events.git", 565 | "reference": "aeebcd54a61ce3bddddcb0273b532256201cd9d1" 566 | }, 567 | "dist": { 568 | "type": "zip", 569 | "url": "https://api.github.com/repos/illuminate/events/zipball/aeebcd54a61ce3bddddcb0273b532256201cd9d1", 570 | "reference": "aeebcd54a61ce3bddddcb0273b532256201cd9d1", 571 | "shasum": "" 572 | }, 573 | "require": { 574 | "illuminate/container": "5.2.*", 575 | "illuminate/contracts": "5.2.*", 576 | "illuminate/support": "5.2.*", 577 | "php": ">=5.5.9" 578 | }, 579 | "type": "library", 580 | "extra": { 581 | "branch-alias": { 582 | "dev-master": "5.2-dev" 583 | } 584 | }, 585 | "autoload": { 586 | "psr-4": { 587 | "Illuminate\\Events\\": "" 588 | } 589 | }, 590 | "notification-url": "https://packagist.org/downloads/", 591 | "license": [ 592 | "MIT" 593 | ], 594 | "authors": [ 595 | { 596 | "name": "Taylor Otwell", 597 | "email": "taylorotwell@gmail.com" 598 | } 599 | ], 600 | "description": "The Illuminate Events package.", 601 | "homepage": "http://laravel.com", 602 | "time": "2016-01-01 01:00:19" 603 | }, 604 | { 605 | "name": "illuminate/filesystem", 606 | "version": "v5.2.21", 607 | "source": { 608 | "type": "git", 609 | "url": "https://github.com/illuminate/filesystem.git", 610 | "reference": "ec2df9bb97fbc08776ed1df399a323440e6db563" 611 | }, 612 | "dist": { 613 | "type": "zip", 614 | "url": "https://api.github.com/repos/illuminate/filesystem/zipball/ec2df9bb97fbc08776ed1df399a323440e6db563", 615 | "reference": "ec2df9bb97fbc08776ed1df399a323440e6db563", 616 | "shasum": "" 617 | }, 618 | "require": { 619 | "illuminate/contracts": "5.2.*", 620 | "illuminate/support": "5.2.*", 621 | "php": ">=5.5.9", 622 | "symfony/finder": "2.8.*|3.0.*" 623 | }, 624 | "suggest": { 625 | "league/flysystem": "Required to use the Flysystem local and FTP drivers (~1.0).", 626 | "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (~1.0).", 627 | "league/flysystem-rackspace": "Required to use the Flysystem Rackspace driver (~1.0)." 628 | }, 629 | "type": "library", 630 | "extra": { 631 | "branch-alias": { 632 | "dev-master": "5.2-dev" 633 | } 634 | }, 635 | "autoload": { 636 | "psr-4": { 637 | "Illuminate\\Filesystem\\": "" 638 | } 639 | }, 640 | "notification-url": "https://packagist.org/downloads/", 641 | "license": [ 642 | "MIT" 643 | ], 644 | "authors": [ 645 | { 646 | "name": "Taylor Otwell", 647 | "email": "taylorotwell@gmail.com" 648 | } 649 | ], 650 | "description": "The Illuminate Filesystem package.", 651 | "homepage": "http://laravel.com", 652 | "time": "2016-02-24 03:13:07" 653 | }, 654 | { 655 | "name": "illuminate/hashing", 656 | "version": "v5.2.21", 657 | "source": { 658 | "type": "git", 659 | "url": "https://github.com/illuminate/hashing.git", 660 | "reference": "cc65dab4006faafe9e795aa457224a6741bd43b4" 661 | }, 662 | "dist": { 663 | "type": "zip", 664 | "url": "https://api.github.com/repos/illuminate/hashing/zipball/cc65dab4006faafe9e795aa457224a6741bd43b4", 665 | "reference": "cc65dab4006faafe9e795aa457224a6741bd43b4", 666 | "shasum": "" 667 | }, 668 | "require": { 669 | "illuminate/contracts": "5.2.*", 670 | "illuminate/support": "5.2.*", 671 | "php": ">=5.5.9" 672 | }, 673 | "type": "library", 674 | "extra": { 675 | "branch-alias": { 676 | "dev-master": "5.2-dev" 677 | } 678 | }, 679 | "autoload": { 680 | "psr-4": { 681 | "Illuminate\\Hashing\\": "" 682 | } 683 | }, 684 | "notification-url": "https://packagist.org/downloads/", 685 | "license": [ 686 | "MIT" 687 | ], 688 | "authors": [ 689 | { 690 | "name": "Taylor Otwell", 691 | "email": "taylorotwell@gmail.com" 692 | } 693 | ], 694 | "description": "The Illuminate Hashing package.", 695 | "homepage": "http://laravel.com", 696 | "time": "2015-11-30 19:26:21" 697 | }, 698 | { 699 | "name": "illuminate/http", 700 | "version": "v5.2.21", 701 | "source": { 702 | "type": "git", 703 | "url": "https://github.com/illuminate/http.git", 704 | "reference": "03f340393526bcdb0f04f19fcdcdbe800b9c3106" 705 | }, 706 | "dist": { 707 | "type": "zip", 708 | "url": "https://api.github.com/repos/illuminate/http/zipball/03f340393526bcdb0f04f19fcdcdbe800b9c3106", 709 | "reference": "03f340393526bcdb0f04f19fcdcdbe800b9c3106", 710 | "shasum": "" 711 | }, 712 | "require": { 713 | "illuminate/session": "5.2.*", 714 | "illuminate/support": "5.2.*", 715 | "php": ">=5.5.9", 716 | "symfony/http-foundation": "2.8.*|3.0.*", 717 | "symfony/http-kernel": "2.8.*|3.0.*" 718 | }, 719 | "type": "library", 720 | "extra": { 721 | "branch-alias": { 722 | "dev-master": "5.2-dev" 723 | } 724 | }, 725 | "autoload": { 726 | "psr-4": { 727 | "Illuminate\\Http\\": "" 728 | } 729 | }, 730 | "notification-url": "https://packagist.org/downloads/", 731 | "license": [ 732 | "MIT" 733 | ], 734 | "authors": [ 735 | { 736 | "name": "Taylor Otwell", 737 | "email": "taylorotwell@gmail.com" 738 | } 739 | ], 740 | "description": "The Illuminate Http package.", 741 | "homepage": "http://laravel.com", 742 | "time": "2016-02-18 16:31:31" 743 | }, 744 | { 745 | "name": "illuminate/pagination", 746 | "version": "v5.2.21", 747 | "source": { 748 | "type": "git", 749 | "url": "https://github.com/illuminate/pagination.git", 750 | "reference": "dcaeed59eb190b03c5498b7fc16e9ea47ce1c0d7" 751 | }, 752 | "dist": { 753 | "type": "zip", 754 | "url": "https://api.github.com/repos/illuminate/pagination/zipball/dcaeed59eb190b03c5498b7fc16e9ea47ce1c0d7", 755 | "reference": "dcaeed59eb190b03c5498b7fc16e9ea47ce1c0d7", 756 | "shasum": "" 757 | }, 758 | "require": { 759 | "illuminate/contracts": "5.2.*", 760 | "illuminate/support": "5.2.*", 761 | "php": ">=5.5.9" 762 | }, 763 | "type": "library", 764 | "extra": { 765 | "branch-alias": { 766 | "dev-master": "5.2-dev" 767 | } 768 | }, 769 | "autoload": { 770 | "psr-4": { 771 | "Illuminate\\Pagination\\": "" 772 | } 773 | }, 774 | "notification-url": "https://packagist.org/downloads/", 775 | "license": [ 776 | "MIT" 777 | ], 778 | "authors": [ 779 | { 780 | "name": "Taylor Otwell", 781 | "email": "taylorotwell@gmail.com" 782 | } 783 | ], 784 | "description": "The Illuminate Pagination package.", 785 | "homepage": "http://laravel.com", 786 | "time": "2016-02-18 16:19:20" 787 | }, 788 | { 789 | "name": "illuminate/pipeline", 790 | "version": "v5.2.21", 791 | "source": { 792 | "type": "git", 793 | "url": "https://github.com/illuminate/pipeline.git", 794 | "reference": "57a5690e2e3047e21d8d8669d2ce1e64fe268fe0" 795 | }, 796 | "dist": { 797 | "type": "zip", 798 | "url": "https://api.github.com/repos/illuminate/pipeline/zipball/57a5690e2e3047e21d8d8669d2ce1e64fe268fe0", 799 | "reference": "57a5690e2e3047e21d8d8669d2ce1e64fe268fe0", 800 | "shasum": "" 801 | }, 802 | "require": { 803 | "illuminate/contracts": "5.2.*", 804 | "illuminate/support": "5.2.*", 805 | "php": ">=5.5.9" 806 | }, 807 | "type": "library", 808 | "extra": { 809 | "branch-alias": { 810 | "dev-master": "5.2-dev" 811 | } 812 | }, 813 | "autoload": { 814 | "psr-4": { 815 | "Illuminate\\Pipeline\\": "" 816 | } 817 | }, 818 | "notification-url": "https://packagist.org/downloads/", 819 | "license": [ 820 | "MIT" 821 | ], 822 | "authors": [ 823 | { 824 | "name": "Taylor Otwell", 825 | "email": "taylorotwell@gmail.com" 826 | } 827 | ], 828 | "description": "The Illuminate Pipeline package.", 829 | "homepage": "http://laravel.com", 830 | "time": "2016-02-08 20:07:06" 831 | }, 832 | { 833 | "name": "illuminate/queue", 834 | "version": "v5.2.21", 835 | "source": { 836 | "type": "git", 837 | "url": "https://github.com/illuminate/queue.git", 838 | "reference": "29f25aadd6b94aac3084b062e7d9445355ad850d" 839 | }, 840 | "dist": { 841 | "type": "zip", 842 | "url": "https://api.github.com/repos/illuminate/queue/zipball/29f25aadd6b94aac3084b062e7d9445355ad850d", 843 | "reference": "29f25aadd6b94aac3084b062e7d9445355ad850d", 844 | "shasum": "" 845 | }, 846 | "require": { 847 | "illuminate/console": "5.2.*", 848 | "illuminate/container": "5.2.*", 849 | "illuminate/contracts": "5.2.*", 850 | "illuminate/support": "5.2.*", 851 | "nesbot/carbon": "~1.20", 852 | "php": ">=5.5.9", 853 | "symfony/process": "2.8.*|3.0.*" 854 | }, 855 | "suggest": { 856 | "aws/aws-sdk-php": "Required to use the SQS queue driver (~3.0).", 857 | "illuminate/redis": "Required to use the Redis queue driver (5.2.*).", 858 | "pda/pheanstalk": "Required to use the Beanstalk queue driver (~3.0)." 859 | }, 860 | "type": "library", 861 | "extra": { 862 | "branch-alias": { 863 | "dev-master": "5.2-dev" 864 | } 865 | }, 866 | "autoload": { 867 | "psr-4": { 868 | "Illuminate\\Queue\\": "" 869 | }, 870 | "classmap": [ 871 | "IlluminateQueueClosure.php" 872 | ] 873 | }, 874 | "notification-url": "https://packagist.org/downloads/", 875 | "license": [ 876 | "MIT" 877 | ], 878 | "authors": [ 879 | { 880 | "name": "Taylor Otwell", 881 | "email": "taylorotwell@gmail.com" 882 | } 883 | ], 884 | "description": "The Illuminate Queue package.", 885 | "homepage": "http://laravel.com", 886 | "time": "2016-02-23 13:58:22" 887 | }, 888 | { 889 | "name": "illuminate/session", 890 | "version": "v5.2.21", 891 | "source": { 892 | "type": "git", 893 | "url": "https://github.com/illuminate/session.git", 894 | "reference": "42144cbf4aea94cca95a489f07f256a4416c11a2" 895 | }, 896 | "dist": { 897 | "type": "zip", 898 | "url": "https://api.github.com/repos/illuminate/session/zipball/42144cbf4aea94cca95a489f07f256a4416c11a2", 899 | "reference": "42144cbf4aea94cca95a489f07f256a4416c11a2", 900 | "shasum": "" 901 | }, 902 | "require": { 903 | "illuminate/contracts": "5.2.*", 904 | "illuminate/support": "5.2.*", 905 | "nesbot/carbon": "~1.20", 906 | "php": ">=5.5.9", 907 | "symfony/finder": "2.8.*|3.0.*", 908 | "symfony/http-foundation": "2.8.*|3.0.*" 909 | }, 910 | "suggest": { 911 | "illuminate/console": "Required to use the session:table command (5.2.*)." 912 | }, 913 | "type": "library", 914 | "extra": { 915 | "branch-alias": { 916 | "dev-master": "5.2-dev" 917 | } 918 | }, 919 | "autoload": { 920 | "psr-4": { 921 | "Illuminate\\Session\\": "" 922 | } 923 | }, 924 | "notification-url": "https://packagist.org/downloads/", 925 | "license": [ 926 | "MIT" 927 | ], 928 | "authors": [ 929 | { 930 | "name": "Taylor Otwell", 931 | "email": "taylorotwell@gmail.com" 932 | } 933 | ], 934 | "description": "The Illuminate Session package.", 935 | "homepage": "http://laravel.com", 936 | "time": "2016-02-09 23:34:56" 937 | }, 938 | { 939 | "name": "illuminate/support", 940 | "version": "v5.2.21", 941 | "source": { 942 | "type": "git", 943 | "url": "https://github.com/illuminate/support.git", 944 | "reference": "6749fab3f3d38d8b15427536a8e7bbdc57497c9e" 945 | }, 946 | "dist": { 947 | "type": "zip", 948 | "url": "https://api.github.com/repos/illuminate/support/zipball/6749fab3f3d38d8b15427536a8e7bbdc57497c9e", 949 | "reference": "6749fab3f3d38d8b15427536a8e7bbdc57497c9e", 950 | "shasum": "" 951 | }, 952 | "require": { 953 | "doctrine/inflector": "~1.0", 954 | "ext-mbstring": "*", 955 | "illuminate/contracts": "5.2.*", 956 | "php": ">=5.5.9" 957 | }, 958 | "suggest": { 959 | "illuminate/filesystem": "Required to use the composer class (5.2.*).", 960 | "jeremeamia/superclosure": "Required to be able to serialize closures (~2.2).", 961 | "paragonie/random_compat": "Provides a compatible interface like PHP7's random_bytes() in PHP 5 projects (~1.1).", 962 | "symfony/polyfill-php56": "Required to use the hash_equals function on PHP 5.5 (~1.0).", 963 | "symfony/process": "Required to use the composer class (2.8.*|3.0.*).", 964 | "symfony/var-dumper": "Improves the dd function (2.8.*|3.0.*)." 965 | }, 966 | "type": "library", 967 | "extra": { 968 | "branch-alias": { 969 | "dev-master": "5.2-dev" 970 | } 971 | }, 972 | "autoload": { 973 | "psr-4": { 974 | "Illuminate\\Support\\": "" 975 | }, 976 | "files": [ 977 | "helpers.php" 978 | ] 979 | }, 980 | "notification-url": "https://packagist.org/downloads/", 981 | "license": [ 982 | "MIT" 983 | ], 984 | "authors": [ 985 | { 986 | "name": "Taylor Otwell", 987 | "email": "taylorotwell@gmail.com" 988 | } 989 | ], 990 | "description": "The Illuminate Support package.", 991 | "homepage": "http://laravel.com", 992 | "time": "2016-02-22 20:29:02" 993 | }, 994 | { 995 | "name": "illuminate/translation", 996 | "version": "v5.2.21", 997 | "source": { 998 | "type": "git", 999 | "url": "https://github.com/illuminate/translation.git", 1000 | "reference": "76107317f20fa34251460122804f54d4ea4ef335" 1001 | }, 1002 | "dist": { 1003 | "type": "zip", 1004 | "url": "https://api.github.com/repos/illuminate/translation/zipball/76107317f20fa34251460122804f54d4ea4ef335", 1005 | "reference": "76107317f20fa34251460122804f54d4ea4ef335", 1006 | "shasum": "" 1007 | }, 1008 | "require": { 1009 | "illuminate/filesystem": "5.2.*", 1010 | "illuminate/support": "5.2.*", 1011 | "php": ">=5.5.9", 1012 | "symfony/translation": "2.8.*|3.0.*" 1013 | }, 1014 | "type": "library", 1015 | "extra": { 1016 | "branch-alias": { 1017 | "dev-master": "5.2-dev" 1018 | } 1019 | }, 1020 | "autoload": { 1021 | "psr-4": { 1022 | "Illuminate\\Translation\\": "" 1023 | } 1024 | }, 1025 | "notification-url": "https://packagist.org/downloads/", 1026 | "license": [ 1027 | "MIT" 1028 | ], 1029 | "authors": [ 1030 | { 1031 | "name": "Taylor Otwell", 1032 | "email": "taylorotwell@gmail.com" 1033 | } 1034 | ], 1035 | "description": "The Illuminate Translation package.", 1036 | "homepage": "http://laravel.com", 1037 | "time": "2016-02-11 06:50:30" 1038 | }, 1039 | { 1040 | "name": "illuminate/validation", 1041 | "version": "v5.2.21", 1042 | "source": { 1043 | "type": "git", 1044 | "url": "https://github.com/illuminate/validation.git", 1045 | "reference": "5ad5c176656d7166beb8902f30b074f65d001481" 1046 | }, 1047 | "dist": { 1048 | "type": "zip", 1049 | "url": "https://api.github.com/repos/illuminate/validation/zipball/5ad5c176656d7166beb8902f30b074f65d001481", 1050 | "reference": "5ad5c176656d7166beb8902f30b074f65d001481", 1051 | "shasum": "" 1052 | }, 1053 | "require": { 1054 | "illuminate/container": "5.2.*", 1055 | "illuminate/contracts": "5.2.*", 1056 | "illuminate/support": "5.2.*", 1057 | "php": ">=5.5.9", 1058 | "symfony/http-foundation": "2.8.*|3.0.*", 1059 | "symfony/translation": "2.8.*|3.0.*" 1060 | }, 1061 | "suggest": { 1062 | "illuminate/database": "Required to use the database presence verifier (5.2.*)." 1063 | }, 1064 | "type": "library", 1065 | "extra": { 1066 | "branch-alias": { 1067 | "dev-master": "5.2-dev" 1068 | } 1069 | }, 1070 | "autoload": { 1071 | "psr-4": { 1072 | "Illuminate\\Validation\\": "" 1073 | } 1074 | }, 1075 | "notification-url": "https://packagist.org/downloads/", 1076 | "license": [ 1077 | "MIT" 1078 | ], 1079 | "authors": [ 1080 | { 1081 | "name": "Taylor Otwell", 1082 | "email": "taylorotwell@gmail.com" 1083 | } 1084 | ], 1085 | "description": "The Illuminate Validation package.", 1086 | "homepage": "http://laravel.com", 1087 | "time": "2016-02-19 17:39:11" 1088 | }, 1089 | { 1090 | "name": "illuminate/view", 1091 | "version": "v5.2.21", 1092 | "source": { 1093 | "type": "git", 1094 | "url": "https://github.com/illuminate/view.git", 1095 | "reference": "ba8f02a40e8e66fa4b913df42a57f058ed7faf7d" 1096 | }, 1097 | "dist": { 1098 | "type": "zip", 1099 | "url": "https://api.github.com/repos/illuminate/view/zipball/ba8f02a40e8e66fa4b913df42a57f058ed7faf7d", 1100 | "reference": "ba8f02a40e8e66fa4b913df42a57f058ed7faf7d", 1101 | "shasum": "" 1102 | }, 1103 | "require": { 1104 | "illuminate/container": "5.2.*", 1105 | "illuminate/contracts": "5.2.*", 1106 | "illuminate/events": "5.2.*", 1107 | "illuminate/filesystem": "5.2.*", 1108 | "illuminate/support": "5.2.*", 1109 | "php": ">=5.5.9" 1110 | }, 1111 | "type": "library", 1112 | "extra": { 1113 | "branch-alias": { 1114 | "dev-master": "5.2-dev" 1115 | } 1116 | }, 1117 | "autoload": { 1118 | "psr-4": { 1119 | "Illuminate\\View\\": "" 1120 | } 1121 | }, 1122 | "notification-url": "https://packagist.org/downloads/", 1123 | "license": [ 1124 | "MIT" 1125 | ], 1126 | "authors": [ 1127 | { 1128 | "name": "Taylor Otwell", 1129 | "email": "taylorotwell@gmail.com" 1130 | } 1131 | ], 1132 | "description": "The Illuminate View package.", 1133 | "homepage": "http://laravel.com", 1134 | "time": "2016-02-02 16:45:07" 1135 | }, 1136 | { 1137 | "name": "laravel/lumen-framework", 1138 | "version": "v5.2.5", 1139 | "source": { 1140 | "type": "git", 1141 | "url": "https://github.com/laravel/lumen-framework.git", 1142 | "reference": "01bafdbef52c5ecc072b668da70808d55a4bbf41" 1143 | }, 1144 | "dist": { 1145 | "type": "zip", 1146 | "url": "https://api.github.com/repos/laravel/lumen-framework/zipball/01bafdbef52c5ecc072b668da70808d55a4bbf41", 1147 | "reference": "01bafdbef52c5ecc072b668da70808d55a4bbf41", 1148 | "shasum": "" 1149 | }, 1150 | "require": { 1151 | "illuminate/auth": "5.2.*", 1152 | "illuminate/broadcasting": "5.2.*", 1153 | "illuminate/bus": "5.2.*", 1154 | "illuminate/cache": "5.2.*", 1155 | "illuminate/config": "5.2.*", 1156 | "illuminate/container": "5.2.*", 1157 | "illuminate/contracts": "5.2.*", 1158 | "illuminate/database": "5.2.*", 1159 | "illuminate/encryption": "5.2.*", 1160 | "illuminate/events": "5.2.*", 1161 | "illuminate/filesystem": "5.2.*", 1162 | "illuminate/hashing": "5.2.*", 1163 | "illuminate/http": "5.2.*", 1164 | "illuminate/pagination": "5.2.*", 1165 | "illuminate/pipeline": "5.2.*", 1166 | "illuminate/queue": "5.2.*", 1167 | "illuminate/support": "5.2.*", 1168 | "illuminate/translation": "5.2.*", 1169 | "illuminate/validation": "~5.2.7", 1170 | "illuminate/view": "5.2.*", 1171 | "monolog/monolog": "~1.11", 1172 | "mtdowling/cron-expression": "~1.0", 1173 | "nikic/fast-route": "0.7.*", 1174 | "paragonie/random_compat": "~1.1", 1175 | "php": ">=5.5.9", 1176 | "symfony/http-foundation": "2.8.*|3.0.*", 1177 | "symfony/http-kernel": "2.8.*|3.0.*", 1178 | "symfony/polyfill-php56": "~1.0" 1179 | }, 1180 | "require-dev": { 1181 | "mockery/mockery": "~0.9", 1182 | "phpunit/phpunit": "~4.0" 1183 | }, 1184 | "suggest": { 1185 | "vlucas/phpdotenv": "Required to use .env files (~2.2)." 1186 | }, 1187 | "type": "library", 1188 | "extra": { 1189 | "branch-alias": { 1190 | "dev-master": "5.2-dev" 1191 | } 1192 | }, 1193 | "autoload": { 1194 | "psr-4": { 1195 | "Laravel\\Lumen\\": "src/" 1196 | }, 1197 | "files": [ 1198 | "src/helpers.php" 1199 | ] 1200 | }, 1201 | "notification-url": "https://packagist.org/downloads/", 1202 | "license": [ 1203 | "MIT" 1204 | ], 1205 | "authors": [ 1206 | { 1207 | "name": "Taylor Otwell", 1208 | "email": "taylorotwell@gmail.com" 1209 | } 1210 | ], 1211 | "description": "The Laravel Lumen Framework.", 1212 | "homepage": "http://laravel.com", 1213 | "keywords": [ 1214 | "framework", 1215 | "laravel", 1216 | "lumen" 1217 | ], 1218 | "time": "2016-02-12 15:02:34" 1219 | }, 1220 | { 1221 | "name": "monolog/monolog", 1222 | "version": "1.18.0", 1223 | "source": { 1224 | "type": "git", 1225 | "url": "https://github.com/Seldaek/monolog.git", 1226 | "reference": "e19b764b5c855580e8ffa7e615f72c10fd2f99cc" 1227 | }, 1228 | "dist": { 1229 | "type": "zip", 1230 | "url": "https://api.github.com/repos/Seldaek/monolog/zipball/e19b764b5c855580e8ffa7e615f72c10fd2f99cc", 1231 | "reference": "e19b764b5c855580e8ffa7e615f72c10fd2f99cc", 1232 | "shasum": "" 1233 | }, 1234 | "require": { 1235 | "php": ">=5.3.0", 1236 | "psr/log": "~1.0" 1237 | }, 1238 | "provide": { 1239 | "psr/log-implementation": "1.0.0" 1240 | }, 1241 | "require-dev": { 1242 | "aws/aws-sdk-php": "^2.4.9", 1243 | "doctrine/couchdb": "~1.0@dev", 1244 | "graylog2/gelf-php": "~1.0", 1245 | "jakub-onderka/php-parallel-lint": "0.9", 1246 | "php-console/php-console": "^3.1.3", 1247 | "phpunit/phpunit": "~4.5", 1248 | "phpunit/phpunit-mock-objects": "2.3.0", 1249 | "raven/raven": "^0.13", 1250 | "ruflin/elastica": ">=0.90 <3.0", 1251 | "swiftmailer/swiftmailer": "~5.3", 1252 | "videlalvaro/php-amqplib": "~2.4" 1253 | }, 1254 | "suggest": { 1255 | "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", 1256 | "doctrine/couchdb": "Allow sending log messages to a CouchDB server", 1257 | "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", 1258 | "ext-mongo": "Allow sending log messages to a MongoDB server", 1259 | "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", 1260 | "mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver", 1261 | "php-console/php-console": "Allow sending log messages to Google Chrome", 1262 | "raven/raven": "Allow sending log messages to a Sentry server", 1263 | "rollbar/rollbar": "Allow sending log messages to Rollbar", 1264 | "ruflin/elastica": "Allow sending log messages to an Elastic Search server", 1265 | "videlalvaro/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib" 1266 | }, 1267 | "type": "library", 1268 | "extra": { 1269 | "branch-alias": { 1270 | "dev-master": "2.0.x-dev" 1271 | } 1272 | }, 1273 | "autoload": { 1274 | "psr-4": { 1275 | "Monolog\\": "src/Monolog" 1276 | } 1277 | }, 1278 | "notification-url": "https://packagist.org/downloads/", 1279 | "license": [ 1280 | "MIT" 1281 | ], 1282 | "authors": [ 1283 | { 1284 | "name": "Jordi Boggiano", 1285 | "email": "j.boggiano@seld.be", 1286 | "homepage": "http://seld.be" 1287 | } 1288 | ], 1289 | "description": "Sends your logs to files, sockets, inboxes, databases and various web services", 1290 | "homepage": "http://github.com/Seldaek/monolog", 1291 | "keywords": [ 1292 | "log", 1293 | "logging", 1294 | "psr-3" 1295 | ], 1296 | "time": "2016-03-01 18:00:40" 1297 | }, 1298 | { 1299 | "name": "mtdowling/cron-expression", 1300 | "version": "v1.1.0", 1301 | "source": { 1302 | "type": "git", 1303 | "url": "https://github.com/mtdowling/cron-expression.git", 1304 | "reference": "c9ee7886f5a12902b225a1a12f36bb45f9ab89e5" 1305 | }, 1306 | "dist": { 1307 | "type": "zip", 1308 | "url": "https://api.github.com/repos/mtdowling/cron-expression/zipball/c9ee7886f5a12902b225a1a12f36bb45f9ab89e5", 1309 | "reference": "c9ee7886f5a12902b225a1a12f36bb45f9ab89e5", 1310 | "shasum": "" 1311 | }, 1312 | "require": { 1313 | "php": ">=5.3.2" 1314 | }, 1315 | "require-dev": { 1316 | "phpunit/phpunit": "~4.0|~5.0" 1317 | }, 1318 | "type": "library", 1319 | "autoload": { 1320 | "psr-0": { 1321 | "Cron": "src/" 1322 | } 1323 | }, 1324 | "notification-url": "https://packagist.org/downloads/", 1325 | "license": [ 1326 | "MIT" 1327 | ], 1328 | "authors": [ 1329 | { 1330 | "name": "Michael Dowling", 1331 | "email": "mtdowling@gmail.com", 1332 | "homepage": "https://github.com/mtdowling" 1333 | } 1334 | ], 1335 | "description": "CRON for PHP: Calculate the next or previous run date and determine if a CRON expression is due", 1336 | "keywords": [ 1337 | "cron", 1338 | "schedule" 1339 | ], 1340 | "time": "2016-01-26 21:23:30" 1341 | }, 1342 | { 1343 | "name": "nesbot/carbon", 1344 | "version": "1.21.0", 1345 | "source": { 1346 | "type": "git", 1347 | "url": "https://github.com/briannesbitt/Carbon.git", 1348 | "reference": "7b08ec6f75791e130012f206e3f7b0e76e18e3d7" 1349 | }, 1350 | "dist": { 1351 | "type": "zip", 1352 | "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/7b08ec6f75791e130012f206e3f7b0e76e18e3d7", 1353 | "reference": "7b08ec6f75791e130012f206e3f7b0e76e18e3d7", 1354 | "shasum": "" 1355 | }, 1356 | "require": { 1357 | "php": ">=5.3.0", 1358 | "symfony/translation": "~2.6|~3.0" 1359 | }, 1360 | "require-dev": { 1361 | "phpunit/phpunit": "~4.0|~5.0" 1362 | }, 1363 | "type": "library", 1364 | "autoload": { 1365 | "psr-4": { 1366 | "Carbon\\": "src/Carbon/" 1367 | } 1368 | }, 1369 | "notification-url": "https://packagist.org/downloads/", 1370 | "license": [ 1371 | "MIT" 1372 | ], 1373 | "authors": [ 1374 | { 1375 | "name": "Brian Nesbitt", 1376 | "email": "brian@nesbot.com", 1377 | "homepage": "http://nesbot.com" 1378 | } 1379 | ], 1380 | "description": "A simple API extension for DateTime.", 1381 | "homepage": "http://carbon.nesbot.com", 1382 | "keywords": [ 1383 | "date", 1384 | "datetime", 1385 | "time" 1386 | ], 1387 | "time": "2015-11-04 20:07:17" 1388 | }, 1389 | { 1390 | "name": "nikic/fast-route", 1391 | "version": "v0.7.0", 1392 | "source": { 1393 | "type": "git", 1394 | "url": "https://github.com/nikic/FastRoute.git", 1395 | "reference": "8164b4a0d8afde4eae5f1bfc39084972ba23ad36" 1396 | }, 1397 | "dist": { 1398 | "type": "zip", 1399 | "url": "https://api.github.com/repos/nikic/FastRoute/zipball/8164b4a0d8afde4eae5f1bfc39084972ba23ad36", 1400 | "reference": "8164b4a0d8afde4eae5f1bfc39084972ba23ad36", 1401 | "shasum": "" 1402 | }, 1403 | "require": { 1404 | "php": ">=5.4.0" 1405 | }, 1406 | "type": "library", 1407 | "autoload": { 1408 | "psr-4": { 1409 | "FastRoute\\": "src/" 1410 | }, 1411 | "files": [ 1412 | "src/functions.php" 1413 | ] 1414 | }, 1415 | "notification-url": "https://packagist.org/downloads/", 1416 | "license": [ 1417 | "BSD-3-Clause" 1418 | ], 1419 | "authors": [ 1420 | { 1421 | "name": "Nikita Popov", 1422 | "email": "nikic@php.net" 1423 | } 1424 | ], 1425 | "description": "Fast request router for PHP", 1426 | "keywords": [ 1427 | "router", 1428 | "routing" 1429 | ], 1430 | "time": "2015-12-20 19:50:12" 1431 | }, 1432 | { 1433 | "name": "paragonie/random_compat", 1434 | "version": "v1.2.1", 1435 | "source": { 1436 | "type": "git", 1437 | "url": "https://github.com/paragonie/random_compat.git", 1438 | "reference": "f078eba3bcf140fd69b5fcc3ea5ac809abf729dc" 1439 | }, 1440 | "dist": { 1441 | "type": "zip", 1442 | "url": "https://api.github.com/repos/paragonie/random_compat/zipball/f078eba3bcf140fd69b5fcc3ea5ac809abf729dc", 1443 | "reference": "f078eba3bcf140fd69b5fcc3ea5ac809abf729dc", 1444 | "shasum": "" 1445 | }, 1446 | "require": { 1447 | "php": ">=5.2.0" 1448 | }, 1449 | "require-dev": { 1450 | "phpunit/phpunit": "4.*|5.*" 1451 | }, 1452 | "suggest": { 1453 | "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." 1454 | }, 1455 | "type": "library", 1456 | "autoload": { 1457 | "files": [ 1458 | "lib/random.php" 1459 | ] 1460 | }, 1461 | "notification-url": "https://packagist.org/downloads/", 1462 | "license": [ 1463 | "MIT" 1464 | ], 1465 | "authors": [ 1466 | { 1467 | "name": "Paragon Initiative Enterprises", 1468 | "email": "security@paragonie.com", 1469 | "homepage": "https://paragonie.com" 1470 | } 1471 | ], 1472 | "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", 1473 | "keywords": [ 1474 | "csprng", 1475 | "pseudorandom", 1476 | "random" 1477 | ], 1478 | "time": "2016-02-29 17:25:04" 1479 | }, 1480 | { 1481 | "name": "psr/log", 1482 | "version": "1.0.0", 1483 | "source": { 1484 | "type": "git", 1485 | "url": "https://github.com/php-fig/log.git", 1486 | "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b" 1487 | }, 1488 | "dist": { 1489 | "type": "zip", 1490 | "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b", 1491 | "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b", 1492 | "shasum": "" 1493 | }, 1494 | "type": "library", 1495 | "autoload": { 1496 | "psr-0": { 1497 | "Psr\\Log\\": "" 1498 | } 1499 | }, 1500 | "notification-url": "https://packagist.org/downloads/", 1501 | "license": [ 1502 | "MIT" 1503 | ], 1504 | "authors": [ 1505 | { 1506 | "name": "PHP-FIG", 1507 | "homepage": "http://www.php-fig.org/" 1508 | } 1509 | ], 1510 | "description": "Common interface for logging libraries", 1511 | "keywords": [ 1512 | "log", 1513 | "psr", 1514 | "psr-3" 1515 | ], 1516 | "time": "2012-12-21 11:40:51" 1517 | }, 1518 | { 1519 | "name": "symfony/console", 1520 | "version": "v3.0.3", 1521 | "source": { 1522 | "type": "git", 1523 | "url": "https://github.com/symfony/console.git", 1524 | "reference": "2ed5e2706ce92313d120b8fe50d1063bcfd12e04" 1525 | }, 1526 | "dist": { 1527 | "type": "zip", 1528 | "url": "https://api.github.com/repos/symfony/console/zipball/2ed5e2706ce92313d120b8fe50d1063bcfd12e04", 1529 | "reference": "2ed5e2706ce92313d120b8fe50d1063bcfd12e04", 1530 | "shasum": "" 1531 | }, 1532 | "require": { 1533 | "php": ">=5.5.9", 1534 | "symfony/polyfill-mbstring": "~1.0" 1535 | }, 1536 | "require-dev": { 1537 | "psr/log": "~1.0", 1538 | "symfony/event-dispatcher": "~2.8|~3.0", 1539 | "symfony/process": "~2.8|~3.0" 1540 | }, 1541 | "suggest": { 1542 | "psr/log": "For using the console logger", 1543 | "symfony/event-dispatcher": "", 1544 | "symfony/process": "" 1545 | }, 1546 | "type": "library", 1547 | "extra": { 1548 | "branch-alias": { 1549 | "dev-master": "3.0-dev" 1550 | } 1551 | }, 1552 | "autoload": { 1553 | "psr-4": { 1554 | "Symfony\\Component\\Console\\": "" 1555 | }, 1556 | "exclude-from-classmap": [ 1557 | "/Tests/" 1558 | ] 1559 | }, 1560 | "notification-url": "https://packagist.org/downloads/", 1561 | "license": [ 1562 | "MIT" 1563 | ], 1564 | "authors": [ 1565 | { 1566 | "name": "Fabien Potencier", 1567 | "email": "fabien@symfony.com" 1568 | }, 1569 | { 1570 | "name": "Symfony Community", 1571 | "homepage": "https://symfony.com/contributors" 1572 | } 1573 | ], 1574 | "description": "Symfony Console Component", 1575 | "homepage": "https://symfony.com", 1576 | "time": "2016-02-28 16:24:34" 1577 | }, 1578 | { 1579 | "name": "symfony/debug", 1580 | "version": "v3.0.3", 1581 | "source": { 1582 | "type": "git", 1583 | "url": "https://github.com/symfony/debug.git", 1584 | "reference": "29606049ced1ec715475f88d1bbe587252a3476e" 1585 | }, 1586 | "dist": { 1587 | "type": "zip", 1588 | "url": "https://api.github.com/repos/symfony/debug/zipball/29606049ced1ec715475f88d1bbe587252a3476e", 1589 | "reference": "29606049ced1ec715475f88d1bbe587252a3476e", 1590 | "shasum": "" 1591 | }, 1592 | "require": { 1593 | "php": ">=5.5.9", 1594 | "psr/log": "~1.0" 1595 | }, 1596 | "conflict": { 1597 | "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" 1598 | }, 1599 | "require-dev": { 1600 | "symfony/class-loader": "~2.8|~3.0", 1601 | "symfony/http-kernel": "~2.8|~3.0" 1602 | }, 1603 | "type": "library", 1604 | "extra": { 1605 | "branch-alias": { 1606 | "dev-master": "3.0-dev" 1607 | } 1608 | }, 1609 | "autoload": { 1610 | "psr-4": { 1611 | "Symfony\\Component\\Debug\\": "" 1612 | }, 1613 | "exclude-from-classmap": [ 1614 | "/Tests/" 1615 | ] 1616 | }, 1617 | "notification-url": "https://packagist.org/downloads/", 1618 | "license": [ 1619 | "MIT" 1620 | ], 1621 | "authors": [ 1622 | { 1623 | "name": "Fabien Potencier", 1624 | "email": "fabien@symfony.com" 1625 | }, 1626 | { 1627 | "name": "Symfony Community", 1628 | "homepage": "https://symfony.com/contributors" 1629 | } 1630 | ], 1631 | "description": "Symfony Debug Component", 1632 | "homepage": "https://symfony.com", 1633 | "time": "2016-01-27 05:14:46" 1634 | }, 1635 | { 1636 | "name": "symfony/event-dispatcher", 1637 | "version": "v3.0.3", 1638 | "source": { 1639 | "type": "git", 1640 | "url": "https://github.com/symfony/event-dispatcher.git", 1641 | "reference": "4dd5df31a28c0f82b41cb1e1599b74b5dcdbdafa" 1642 | }, 1643 | "dist": { 1644 | "type": "zip", 1645 | "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/4dd5df31a28c0f82b41cb1e1599b74b5dcdbdafa", 1646 | "reference": "4dd5df31a28c0f82b41cb1e1599b74b5dcdbdafa", 1647 | "shasum": "" 1648 | }, 1649 | "require": { 1650 | "php": ">=5.5.9" 1651 | }, 1652 | "require-dev": { 1653 | "psr/log": "~1.0", 1654 | "symfony/config": "~2.8|~3.0", 1655 | "symfony/dependency-injection": "~2.8|~3.0", 1656 | "symfony/expression-language": "~2.8|~3.0", 1657 | "symfony/stopwatch": "~2.8|~3.0" 1658 | }, 1659 | "suggest": { 1660 | "symfony/dependency-injection": "", 1661 | "symfony/http-kernel": "" 1662 | }, 1663 | "type": "library", 1664 | "extra": { 1665 | "branch-alias": { 1666 | "dev-master": "3.0-dev" 1667 | } 1668 | }, 1669 | "autoload": { 1670 | "psr-4": { 1671 | "Symfony\\Component\\EventDispatcher\\": "" 1672 | }, 1673 | "exclude-from-classmap": [ 1674 | "/Tests/" 1675 | ] 1676 | }, 1677 | "notification-url": "https://packagist.org/downloads/", 1678 | "license": [ 1679 | "MIT" 1680 | ], 1681 | "authors": [ 1682 | { 1683 | "name": "Fabien Potencier", 1684 | "email": "fabien@symfony.com" 1685 | }, 1686 | { 1687 | "name": "Symfony Community", 1688 | "homepage": "https://symfony.com/contributors" 1689 | } 1690 | ], 1691 | "description": "Symfony EventDispatcher Component", 1692 | "homepage": "https://symfony.com", 1693 | "time": "2016-01-27 05:14:46" 1694 | }, 1695 | { 1696 | "name": "symfony/finder", 1697 | "version": "v3.0.3", 1698 | "source": { 1699 | "type": "git", 1700 | "url": "https://github.com/symfony/finder.git", 1701 | "reference": "623bda0abd9aa29e529c8e9c08b3b84171914723" 1702 | }, 1703 | "dist": { 1704 | "type": "zip", 1705 | "url": "https://api.github.com/repos/symfony/finder/zipball/623bda0abd9aa29e529c8e9c08b3b84171914723", 1706 | "reference": "623bda0abd9aa29e529c8e9c08b3b84171914723", 1707 | "shasum": "" 1708 | }, 1709 | "require": { 1710 | "php": ">=5.5.9" 1711 | }, 1712 | "type": "library", 1713 | "extra": { 1714 | "branch-alias": { 1715 | "dev-master": "3.0-dev" 1716 | } 1717 | }, 1718 | "autoload": { 1719 | "psr-4": { 1720 | "Symfony\\Component\\Finder\\": "" 1721 | }, 1722 | "exclude-from-classmap": [ 1723 | "/Tests/" 1724 | ] 1725 | }, 1726 | "notification-url": "https://packagist.org/downloads/", 1727 | "license": [ 1728 | "MIT" 1729 | ], 1730 | "authors": [ 1731 | { 1732 | "name": "Fabien Potencier", 1733 | "email": "fabien@symfony.com" 1734 | }, 1735 | { 1736 | "name": "Symfony Community", 1737 | "homepage": "https://symfony.com/contributors" 1738 | } 1739 | ], 1740 | "description": "Symfony Finder Component", 1741 | "homepage": "https://symfony.com", 1742 | "time": "2016-01-27 05:14:46" 1743 | }, 1744 | { 1745 | "name": "symfony/http-foundation", 1746 | "version": "v3.0.3", 1747 | "source": { 1748 | "type": "git", 1749 | "url": "https://github.com/symfony/http-foundation.git", 1750 | "reference": "52065702c71743c05d415a8facfcad6d4257e8d7" 1751 | }, 1752 | "dist": { 1753 | "type": "zip", 1754 | "url": "https://api.github.com/repos/symfony/http-foundation/zipball/52065702c71743c05d415a8facfcad6d4257e8d7", 1755 | "reference": "52065702c71743c05d415a8facfcad6d4257e8d7", 1756 | "shasum": "" 1757 | }, 1758 | "require": { 1759 | "php": ">=5.5.9" 1760 | }, 1761 | "require-dev": { 1762 | "symfony/expression-language": "~2.8|~3.0" 1763 | }, 1764 | "type": "library", 1765 | "extra": { 1766 | "branch-alias": { 1767 | "dev-master": "3.0-dev" 1768 | } 1769 | }, 1770 | "autoload": { 1771 | "psr-4": { 1772 | "Symfony\\Component\\HttpFoundation\\": "" 1773 | }, 1774 | "exclude-from-classmap": [ 1775 | "/Tests/" 1776 | ] 1777 | }, 1778 | "notification-url": "https://packagist.org/downloads/", 1779 | "license": [ 1780 | "MIT" 1781 | ], 1782 | "authors": [ 1783 | { 1784 | "name": "Fabien Potencier", 1785 | "email": "fabien@symfony.com" 1786 | }, 1787 | { 1788 | "name": "Symfony Community", 1789 | "homepage": "https://symfony.com/contributors" 1790 | } 1791 | ], 1792 | "description": "Symfony HttpFoundation Component", 1793 | "homepage": "https://symfony.com", 1794 | "time": "2016-02-28 16:24:34" 1795 | }, 1796 | { 1797 | "name": "symfony/http-kernel", 1798 | "version": "v3.0.3", 1799 | "source": { 1800 | "type": "git", 1801 | "url": "https://github.com/symfony/http-kernel.git", 1802 | "reference": "59c0a1972e9aad87b7a56bbe1ccee26b7535a0db" 1803 | }, 1804 | "dist": { 1805 | "type": "zip", 1806 | "url": "https://api.github.com/repos/symfony/http-kernel/zipball/59c0a1972e9aad87b7a56bbe1ccee26b7535a0db", 1807 | "reference": "59c0a1972e9aad87b7a56bbe1ccee26b7535a0db", 1808 | "shasum": "" 1809 | }, 1810 | "require": { 1811 | "php": ">=5.5.9", 1812 | "psr/log": "~1.0", 1813 | "symfony/debug": "~2.8|~3.0", 1814 | "symfony/event-dispatcher": "~2.8|~3.0", 1815 | "symfony/http-foundation": "~2.8|~3.0" 1816 | }, 1817 | "conflict": { 1818 | "symfony/config": "<2.8" 1819 | }, 1820 | "require-dev": { 1821 | "symfony/browser-kit": "~2.8|~3.0", 1822 | "symfony/class-loader": "~2.8|~3.0", 1823 | "symfony/config": "~2.8|~3.0", 1824 | "symfony/console": "~2.8|~3.0", 1825 | "symfony/css-selector": "~2.8|~3.0", 1826 | "symfony/dependency-injection": "~2.8|~3.0", 1827 | "symfony/dom-crawler": "~2.8|~3.0", 1828 | "symfony/expression-language": "~2.8|~3.0", 1829 | "symfony/finder": "~2.8|~3.0", 1830 | "symfony/process": "~2.8|~3.0", 1831 | "symfony/routing": "~2.8|~3.0", 1832 | "symfony/stopwatch": "~2.8|~3.0", 1833 | "symfony/templating": "~2.8|~3.0", 1834 | "symfony/translation": "~2.8|~3.0", 1835 | "symfony/var-dumper": "~2.8|~3.0" 1836 | }, 1837 | "suggest": { 1838 | "symfony/browser-kit": "", 1839 | "symfony/class-loader": "", 1840 | "symfony/config": "", 1841 | "symfony/console": "", 1842 | "symfony/dependency-injection": "", 1843 | "symfony/finder": "", 1844 | "symfony/var-dumper": "" 1845 | }, 1846 | "type": "library", 1847 | "extra": { 1848 | "branch-alias": { 1849 | "dev-master": "3.0-dev" 1850 | } 1851 | }, 1852 | "autoload": { 1853 | "psr-4": { 1854 | "Symfony\\Component\\HttpKernel\\": "" 1855 | }, 1856 | "exclude-from-classmap": [ 1857 | "/Tests/" 1858 | ] 1859 | }, 1860 | "notification-url": "https://packagist.org/downloads/", 1861 | "license": [ 1862 | "MIT" 1863 | ], 1864 | "authors": [ 1865 | { 1866 | "name": "Fabien Potencier", 1867 | "email": "fabien@symfony.com" 1868 | }, 1869 | { 1870 | "name": "Symfony Community", 1871 | "homepage": "https://symfony.com/contributors" 1872 | } 1873 | ], 1874 | "description": "Symfony HttpKernel Component", 1875 | "homepage": "https://symfony.com", 1876 | "time": "2016-02-28 21:33:13" 1877 | }, 1878 | { 1879 | "name": "symfony/polyfill-mbstring", 1880 | "version": "v1.1.0", 1881 | "source": { 1882 | "type": "git", 1883 | "url": "https://github.com/symfony/polyfill-mbstring.git", 1884 | "reference": "1289d16209491b584839022f29257ad859b8532d" 1885 | }, 1886 | "dist": { 1887 | "type": "zip", 1888 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/1289d16209491b584839022f29257ad859b8532d", 1889 | "reference": "1289d16209491b584839022f29257ad859b8532d", 1890 | "shasum": "" 1891 | }, 1892 | "require": { 1893 | "php": ">=5.3.3" 1894 | }, 1895 | "suggest": { 1896 | "ext-mbstring": "For best performance" 1897 | }, 1898 | "type": "library", 1899 | "extra": { 1900 | "branch-alias": { 1901 | "dev-master": "1.1-dev" 1902 | } 1903 | }, 1904 | "autoload": { 1905 | "psr-4": { 1906 | "Symfony\\Polyfill\\Mbstring\\": "" 1907 | }, 1908 | "files": [ 1909 | "bootstrap.php" 1910 | ] 1911 | }, 1912 | "notification-url": "https://packagist.org/downloads/", 1913 | "license": [ 1914 | "MIT" 1915 | ], 1916 | "authors": [ 1917 | { 1918 | "name": "Nicolas Grekas", 1919 | "email": "p@tchwork.com" 1920 | }, 1921 | { 1922 | "name": "Symfony Community", 1923 | "homepage": "https://symfony.com/contributors" 1924 | } 1925 | ], 1926 | "description": "Symfony polyfill for the Mbstring extension", 1927 | "homepage": "https://symfony.com", 1928 | "keywords": [ 1929 | "compatibility", 1930 | "mbstring", 1931 | "polyfill", 1932 | "portable", 1933 | "shim" 1934 | ], 1935 | "time": "2016-01-20 09:13:37" 1936 | }, 1937 | { 1938 | "name": "symfony/polyfill-php56", 1939 | "version": "v1.1.0", 1940 | "source": { 1941 | "type": "git", 1942 | "url": "https://github.com/symfony/polyfill-php56.git", 1943 | "reference": "4d891fff050101a53a4caabb03277284942d1ad9" 1944 | }, 1945 | "dist": { 1946 | "type": "zip", 1947 | "url": "https://api.github.com/repos/symfony/polyfill-php56/zipball/4d891fff050101a53a4caabb03277284942d1ad9", 1948 | "reference": "4d891fff050101a53a4caabb03277284942d1ad9", 1949 | "shasum": "" 1950 | }, 1951 | "require": { 1952 | "php": ">=5.3.3", 1953 | "symfony/polyfill-util": "~1.0" 1954 | }, 1955 | "type": "library", 1956 | "extra": { 1957 | "branch-alias": { 1958 | "dev-master": "1.1-dev" 1959 | } 1960 | }, 1961 | "autoload": { 1962 | "psr-4": { 1963 | "Symfony\\Polyfill\\Php56\\": "" 1964 | }, 1965 | "files": [ 1966 | "bootstrap.php" 1967 | ] 1968 | }, 1969 | "notification-url": "https://packagist.org/downloads/", 1970 | "license": [ 1971 | "MIT" 1972 | ], 1973 | "authors": [ 1974 | { 1975 | "name": "Nicolas Grekas", 1976 | "email": "p@tchwork.com" 1977 | }, 1978 | { 1979 | "name": "Symfony Community", 1980 | "homepage": "https://symfony.com/contributors" 1981 | } 1982 | ], 1983 | "description": "Symfony polyfill backporting some PHP 5.6+ features to lower PHP versions", 1984 | "homepage": "https://symfony.com", 1985 | "keywords": [ 1986 | "compatibility", 1987 | "polyfill", 1988 | "portable", 1989 | "shim" 1990 | ], 1991 | "time": "2016-01-20 09:13:37" 1992 | }, 1993 | { 1994 | "name": "symfony/polyfill-util", 1995 | "version": "v1.1.0", 1996 | "source": { 1997 | "type": "git", 1998 | "url": "https://github.com/symfony/polyfill-util.git", 1999 | "reference": "8de62801aa12bc4dfcf85eef5d21981ae7bb3cc4" 2000 | }, 2001 | "dist": { 2002 | "type": "zip", 2003 | "url": "https://api.github.com/repos/symfony/polyfill-util/zipball/8de62801aa12bc4dfcf85eef5d21981ae7bb3cc4", 2004 | "reference": "8de62801aa12bc4dfcf85eef5d21981ae7bb3cc4", 2005 | "shasum": "" 2006 | }, 2007 | "require": { 2008 | "php": ">=5.3.3" 2009 | }, 2010 | "type": "library", 2011 | "extra": { 2012 | "branch-alias": { 2013 | "dev-master": "1.1-dev" 2014 | } 2015 | }, 2016 | "autoload": { 2017 | "psr-4": { 2018 | "Symfony\\Polyfill\\Util\\": "" 2019 | } 2020 | }, 2021 | "notification-url": "https://packagist.org/downloads/", 2022 | "license": [ 2023 | "MIT" 2024 | ], 2025 | "authors": [ 2026 | { 2027 | "name": "Nicolas Grekas", 2028 | "email": "p@tchwork.com" 2029 | }, 2030 | { 2031 | "name": "Symfony Community", 2032 | "homepage": "https://symfony.com/contributors" 2033 | } 2034 | ], 2035 | "description": "Symfony utilities for portability of PHP codes", 2036 | "homepage": "https://symfony.com", 2037 | "keywords": [ 2038 | "compat", 2039 | "compatibility", 2040 | "polyfill", 2041 | "shim" 2042 | ], 2043 | "time": "2016-01-20 09:13:37" 2044 | }, 2045 | { 2046 | "name": "symfony/process", 2047 | "version": "v3.0.3", 2048 | "source": { 2049 | "type": "git", 2050 | "url": "https://github.com/symfony/process.git", 2051 | "reference": "dfecef47506179db2501430e732adbf3793099c8" 2052 | }, 2053 | "dist": { 2054 | "type": "zip", 2055 | "url": "https://api.github.com/repos/symfony/process/zipball/dfecef47506179db2501430e732adbf3793099c8", 2056 | "reference": "dfecef47506179db2501430e732adbf3793099c8", 2057 | "shasum": "" 2058 | }, 2059 | "require": { 2060 | "php": ">=5.5.9" 2061 | }, 2062 | "type": "library", 2063 | "extra": { 2064 | "branch-alias": { 2065 | "dev-master": "3.0-dev" 2066 | } 2067 | }, 2068 | "autoload": { 2069 | "psr-4": { 2070 | "Symfony\\Component\\Process\\": "" 2071 | }, 2072 | "exclude-from-classmap": [ 2073 | "/Tests/" 2074 | ] 2075 | }, 2076 | "notification-url": "https://packagist.org/downloads/", 2077 | "license": [ 2078 | "MIT" 2079 | ], 2080 | "authors": [ 2081 | { 2082 | "name": "Fabien Potencier", 2083 | "email": "fabien@symfony.com" 2084 | }, 2085 | { 2086 | "name": "Symfony Community", 2087 | "homepage": "https://symfony.com/contributors" 2088 | } 2089 | ], 2090 | "description": "Symfony Process Component", 2091 | "homepage": "https://symfony.com", 2092 | "time": "2016-02-02 13:44:19" 2093 | }, 2094 | { 2095 | "name": "symfony/translation", 2096 | "version": "v3.0.3", 2097 | "source": { 2098 | "type": "git", 2099 | "url": "https://github.com/symfony/translation.git", 2100 | "reference": "2de0b6f7ebe43cffd8a06996ebec6aab79ea9e91" 2101 | }, 2102 | "dist": { 2103 | "type": "zip", 2104 | "url": "https://api.github.com/repos/symfony/translation/zipball/2de0b6f7ebe43cffd8a06996ebec6aab79ea9e91", 2105 | "reference": "2de0b6f7ebe43cffd8a06996ebec6aab79ea9e91", 2106 | "shasum": "" 2107 | }, 2108 | "require": { 2109 | "php": ">=5.5.9", 2110 | "symfony/polyfill-mbstring": "~1.0" 2111 | }, 2112 | "conflict": { 2113 | "symfony/config": "<2.8" 2114 | }, 2115 | "require-dev": { 2116 | "psr/log": "~1.0", 2117 | "symfony/config": "~2.8|~3.0", 2118 | "symfony/intl": "~2.8|~3.0", 2119 | "symfony/yaml": "~2.8|~3.0" 2120 | }, 2121 | "suggest": { 2122 | "psr/log": "To use logging capability in translator", 2123 | "symfony/config": "", 2124 | "symfony/yaml": "" 2125 | }, 2126 | "type": "library", 2127 | "extra": { 2128 | "branch-alias": { 2129 | "dev-master": "3.0-dev" 2130 | } 2131 | }, 2132 | "autoload": { 2133 | "psr-4": { 2134 | "Symfony\\Component\\Translation\\": "" 2135 | }, 2136 | "exclude-from-classmap": [ 2137 | "/Tests/" 2138 | ] 2139 | }, 2140 | "notification-url": "https://packagist.org/downloads/", 2141 | "license": [ 2142 | "MIT" 2143 | ], 2144 | "authors": [ 2145 | { 2146 | "name": "Fabien Potencier", 2147 | "email": "fabien@symfony.com" 2148 | }, 2149 | { 2150 | "name": "Symfony Community", 2151 | "homepage": "https://symfony.com/contributors" 2152 | } 2153 | ], 2154 | "description": "Symfony Translation Component", 2155 | "homepage": "https://symfony.com", 2156 | "time": "2016-02-02 13:44:19" 2157 | } 2158 | ], 2159 | "packages-dev": [], 2160 | "aliases": [], 2161 | "minimum-stability": "stable", 2162 | "stability-flags": [], 2163 | "prefer-stable": false, 2164 | "prefer-lowest": false, 2165 | "platform": { 2166 | "php": ">=5.5.9" 2167 | }, 2168 | "platform-dev": [] 2169 | } 2170 | -------------------------------------------------------------------------------- /examples/extend/Test/Http/Controllers/TestController.php: -------------------------------------------------------------------------------- 1 | enableViews(); 14 | $this->enableRoutes(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /examples/extend/Test/routes.php: -------------------------------------------------------------------------------- 1 | pluginManager = $pluginManager; 19 | } 20 | 21 | /** 22 | * Loads the given class or interface. 23 | * 24 | * @param $class 25 | * @return bool|null 26 | */ 27 | public function loadClass($class) 28 | { 29 | if (isset($this->pluginManager->getClassMap()[$class])) { 30 | \Composer\Autoload\includeFile($this->pluginManager->getClassMap()[$class]); 31 | 32 | return true; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Plugin.php: -------------------------------------------------------------------------------- 1 | app = $app; 45 | 46 | $this->checkPluginName(); 47 | } 48 | 49 | abstract public function boot(); 50 | 51 | /** 52 | * Check for empty plugin name. 53 | * 54 | * @throws \InvalidArgumentException 55 | */ 56 | private function checkPluginName() 57 | { 58 | if (!$this->name) { 59 | throw new \InvalidArgumentException('Missing Plugin name.'); 60 | } 61 | } 62 | 63 | /** 64 | * Returns the view namespace in a camel case format based off 65 | * the plugins class name, with plugin stripped off the end. 66 | * 67 | * Eg: ArticlesPlugin will be accessible through 'plugin:articles::' 68 | * 69 | * @return string 70 | */ 71 | protected function getViewNamespace() 72 | { 73 | return 'plugin:' . Str::camel( 74 | mb_substr( 75 | get_called_class(), 76 | strrpos(get_called_class(), '\\') + 1, 77 | -6 78 | ) 79 | ); 80 | } 81 | 82 | /** 83 | * Add a view namespace for this plugin. 84 | * Eg: view("plugin:articles::{view_name}") 85 | * 86 | * @param string $path 87 | */ 88 | protected function enableViews($path = 'views') 89 | { 90 | $this->app['view']->addNamespace( 91 | $this->getViewNamespace(), 92 | $this->getPluginPath() . DIRECTORY_SEPARATOR . $path 93 | ); 94 | } 95 | 96 | /** 97 | * Enable routes for this plugin. 98 | * 99 | * @param string $path 100 | * @param array|string $middleware 101 | */ 102 | protected function enableRoutes($path = 'routes.php', $middleware = 'web') 103 | { 104 | $this->app->router->group( 105 | [ 106 | 'namespace' => $this->getPluginControllerNamespace(), 107 | 'middleware' => $middleware, 108 | ], 109 | function ($app) use ($path) { 110 | require $this->getPluginPath() . DIRECTORY_SEPARATOR . $path; 111 | } 112 | ); 113 | } 114 | 115 | /** 116 | * Register a database migration path for this plugin. 117 | * 118 | * @param array|string $paths 119 | * @return void 120 | */ 121 | protected function enableMigrations($paths = 'migrations') 122 | { 123 | $this->app->afterResolving('migrator', function ($migrator) use ($paths) { 124 | foreach ((array) $paths as $path) { 125 | $migrator->path($this->getPluginPath() . DIRECTORY_SEPARATOR . $path); 126 | } 127 | }); 128 | } 129 | 130 | /** 131 | * Add a translations namespace for this plugin. 132 | * Eg: __("plugin:articles::{trans_path}") 133 | * 134 | * @param string $path 135 | */ 136 | protected function enableTranslations($path = 'lang') 137 | { 138 | $this->app->afterResolving('translator', function ($translator) use ($path) { 139 | $translator->addNamespace( 140 | $this->getViewNamespace(), 141 | $this->getPluginPath() . DIRECTORY_SEPARATOR . $path 142 | ); 143 | }); 144 | } 145 | 146 | /** 147 | * @return string 148 | */ 149 | public function getPluginPath() 150 | { 151 | $reflector = $this->getReflector(); 152 | $fileName = $reflector->getFileName(); 153 | 154 | return dirname($fileName); 155 | } 156 | 157 | /** 158 | * @return string 159 | */ 160 | protected function getPluginControllerNamespace() 161 | { 162 | $reflector = $this->getReflector(); 163 | $baseDir = str_replace($reflector->getShortName(), '', $reflector->getName()); 164 | 165 | return $baseDir . 'Http\\Controllers'; 166 | } 167 | 168 | /** 169 | * @return \ReflectionClass 170 | */ 171 | private function getReflector() 172 | { 173 | if (is_null($this->reflector)) { 174 | $this->reflector = new \ReflectionClass($this); 175 | } 176 | 177 | return $this->reflector; 178 | } 179 | 180 | /** 181 | * Returns a plugin view 182 | * 183 | * @param $view 184 | * @return \Illuminate\View\View 185 | */ 186 | protected function view($view) 187 | { 188 | return view($this->getViewNamespace() . '::' . $view); 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /src/PluginExtender.php: -------------------------------------------------------------------------------- 1 | pluginManager = $pluginManager; 30 | $this->app = $app; 31 | $this->classMapCacheFile = storage_path('plugins/classmap.json'); 32 | } 33 | 34 | /** 35 | * Extends all plugins. 36 | */ 37 | public function extendAll() 38 | { 39 | if (!$this->load()) { 40 | foreach ($this->pluginManager->getPlugins() as $plugin) { 41 | $this->extend($plugin, false); 42 | } 43 | 44 | $this->writeCache(); 45 | } 46 | } 47 | 48 | /** 49 | * Search for plugin extensions. 50 | * 51 | * @param Plugin $plugin 52 | * @param bool $writeCache 53 | */ 54 | public function extend(Plugin $plugin, $writeCache = true) 55 | { 56 | foreach ($this->getAllPluginClasses($plugin) as $pluginClassPath) { 57 | $classNamespace = $this->getClassNamespaceFromFilename($pluginClassPath); 58 | 59 | // we cannot redeclare classes 60 | if ($this->classExists($classNamespace)) { 61 | continue; 62 | } 63 | 64 | $addMethods = []; 65 | $beforeReturnMethods = []; 66 | $contants = []; 67 | 68 | foreach ($this->getExtensionFilesForFile($pluginClassPath, $plugin) as $file) { 69 | \Composer\Autoload\includeFile($file); 70 | 71 | $extendingClassNamespace = $this->getClassNamespaceFromFilename($file); 72 | 73 | $fileContent = $this->app['files']->get($file); 74 | $reflector = new \ReflectionClass($extendingClassNamespace); 75 | 76 | $addMethods = array_merge( 77 | $addMethods, 78 | $this->collectMethodsOfType('add', $fileContent, $reflector) 79 | ); 80 | 81 | $beforeReturnMethods = array_merge( 82 | $beforeReturnMethods, 83 | $this->collectMethodsOfType('beforeReturn', $fileContent, $reflector) 84 | ); 85 | 86 | $contants = array_merge($contants, $this->collectConstants($reflector)); 87 | } 88 | 89 | if ($addMethods || $beforeReturnMethods || $contants) { 90 | $originalFileContent = $this->app['files']->get($pluginClassPath); 91 | $originalFileContentExploded = explode(PHP_EOL, $originalFileContent); 92 | 93 | $this->removeLastBracket($originalFileContentExploded); 94 | 95 | if ($addMethods) { 96 | $this->insertAddMethods($addMethods, $originalFileContentExploded); 97 | } 98 | 99 | if ($beforeReturnMethods) { 100 | $this->insertBeforeReturnMethods($beforeReturnMethods, $originalFileContentExploded); 101 | } 102 | 103 | if ($contants) { 104 | $this->insertConstants($contants, $originalFileContentExploded); 105 | } 106 | 107 | $originalFileContentExploded[] = '}'; 108 | 109 | $newFileContent = implode(PHP_EOL, $originalFileContentExploded); 110 | $storagePath = $this->getExtendedClassStoragePath($pluginClassPath); 111 | 112 | $this->app['files']->put($storagePath, $newFileContent); 113 | 114 | $this->pluginManager->addClassMapping($classNamespace, $storagePath); 115 | } 116 | } 117 | 118 | if ($writeCache) { 119 | $this->writeCache(); 120 | } 121 | } 122 | 123 | /** 124 | * @param array $target 125 | */ 126 | protected function removeLastBracket(array &$target) 127 | { 128 | if (false !== $index = $this->getIndexForFirstOccurence('}', array_reverse($target, true))) { 129 | unset($target[$index]); 130 | } 131 | } 132 | 133 | /** 134 | * @param $search 135 | * @param array $subject 136 | * @return bool|int 137 | */ 138 | protected function getIndexForFirstOccurence($search, array $subject) 139 | { 140 | foreach ($subject as $key => $value) { 141 | if (strpos($value, $search) !== false) { 142 | return $key; 143 | } 144 | } 145 | 146 | return false; 147 | } 148 | 149 | /** 150 | * @param array $methods 151 | * @param array $fileContentExploded 152 | */ 153 | protected function insertAddMethods(array $methods, array &$fileContentExploded) 154 | { 155 | $fileContentExploded = array_merge($fileContentExploded, [''], $methods); 156 | } 157 | 158 | /** 159 | * @param array $methods 160 | * @param array $fileContentExploded 161 | */ 162 | protected function insertBeforeReturnMethods(array $methods, array &$fileContentExploded) 163 | { 164 | foreach ($methods as $method) { 165 | $methodExploded = explode(PHP_EOL, $method); 166 | 167 | $innerStart = $this->getIndexForFirstOccurence('{', $methodExploded) + 1; 168 | $innerEnd = $this->getIndexForFirstOccurence('}', array_reverse($methodExploded, true)) - 1; 169 | 170 | $inner = array_slice($methodExploded, $innerStart, $innerEnd - $innerStart + 1); 171 | 172 | if (false == $methodName = $this->getMethodNameFromString($method)) { 173 | continue; 174 | } 175 | 176 | $originalMethodStartIndex = $this->getIndexForFirstOccurence($methodName, $fileContentExploded); 177 | $originalMethodReturnIndex = $this->getIndexForFirstOccurence( 178 | 'return', 179 | array_slice($fileContentExploded, $originalMethodStartIndex, null, true) 180 | ); 181 | 182 | $fileContentBeforeReturn = array_slice($fileContentExploded, 0, $originalMethodReturnIndex); 183 | $fileContentAfterReturn = array_slice($fileContentExploded, $originalMethodReturnIndex); 184 | $fileContentExploded = array_merge($fileContentBeforeReturn, $inner, [''], $fileContentAfterReturn); 185 | } 186 | } 187 | 188 | /** 189 | * @param $string 190 | * @return bool|string 191 | */ 192 | protected function getMethodNameFromString($string) 193 | { 194 | preg_match('/.*function\s+(.*)\(.*/i', $string, $methodName); 195 | 196 | return isset($methodName[1]) ? $methodName[1] : false; 197 | } 198 | 199 | /** 200 | * @param array $constants 201 | * @param array $fileContentExploded 202 | */ 203 | protected function insertConstants(array $constants, array &$fileContentExploded) 204 | { 205 | $lastConstantIndex = $this->getIndexForFirstOccurence('const', array_reverse($fileContentExploded, true)); 206 | 207 | if ($lastConstantIndex === false) { 208 | $lastConstantIndex = $this->getIndexForFirstOccurence('{', $fileContentExploded); 209 | } 210 | 211 | if ($lastConstantIndex !== false) { 212 | $before = array_slice($fileContentExploded, 0, $lastConstantIndex + 1); 213 | $after = array_slice($fileContentExploded, $lastConstantIndex + 1); 214 | 215 | $fileContentExploded = $before; 216 | 217 | foreach ($constants as $constantName => $constantValue) { 218 | if (is_bool($constantValue)) { 219 | $constantValue = $constantValue ? 'true' : 'false'; 220 | } elseif (is_array($constantValue)) { 221 | $constantValue = '[' . implode(',', $constantValue) . ']'; 222 | } 223 | 224 | $fileContentExploded[] = ' const ' . $constantName . ' = ' . $constantValue . ';'; 225 | } 226 | 227 | $fileContentExploded = array_merge($fileContentExploded, $after); 228 | } 229 | } 230 | 231 | /** 232 | * @param string $type 233 | * @param $fileContent 234 | * @param \ReflectionClass $reflector 235 | * @return array 236 | */ 237 | protected function collectMethodsOfType($type, $fileContent, \ReflectionClass $reflector) 238 | { 239 | $methods = []; 240 | 241 | $fileContentExploded = explode(PHP_EOL, $fileContent); 242 | 243 | foreach ($reflector->getMethods() as $reflectionMethod) { 244 | /** @var \ReflectionMethod $reflectionMethod */ 245 | 246 | $doc = $reflectionMethod->getDocComment(); 247 | 248 | if (strpos($doc, '@' . $type) !== false) { 249 | $methods[] = $this->getMethodString($reflectionMethod, $fileContentExploded); 250 | } 251 | } 252 | 253 | return $methods; 254 | } 255 | 256 | /** 257 | * @param \ReflectionClass $reflactor 258 | * @return array 259 | */ 260 | protected function collectConstants(\ReflectionClass $reflactor) 261 | { 262 | return $reflactor->getConstants(); 263 | } 264 | 265 | /** 266 | * @param \ReflectionMethod $method 267 | * @param array $splittedContent 268 | * @return string 269 | */ 270 | protected function getMethodString(\ReflectionMethod $method, array $splittedContent) 271 | { 272 | $methodString = ''; 273 | 274 | for ($i = $method->getStartLine(); $i <= $method->getEndLine(); $i++) { 275 | $methodString .= $splittedContent[$i - 1] . PHP_EOL; 276 | } 277 | 278 | return $methodString; 279 | } 280 | 281 | /** 282 | * @param Plugin $plugin 283 | * @return array 284 | */ 285 | protected function getAllPluginClasses(Plugin $plugin) 286 | { 287 | $files = []; 288 | 289 | foreach ($this->app['files']->allFiles($plugin->getPluginPath()) as $file) { 290 | /** @var SplFileInfo $file */ 291 | 292 | if (!$this->fileContainsClass($file->getContents())) { 293 | continue; 294 | } 295 | 296 | $files[] = $file->getPathname(); 297 | } 298 | 299 | return $files; 300 | } 301 | 302 | /** 303 | * @param $file 304 | * @param Plugin $plugin 305 | * @return array 306 | */ 307 | protected function getExtensionFilesForFile($file, Plugin $plugin) 308 | { 309 | $files = []; 310 | $classPath = str_replace($this->pluginManager->getPluginDirectory(), DIRECTORY_SEPARATOR . 'Plugins', $file); 311 | 312 | foreach ($this->pluginManager->getPlugins() as $otherPlugin) { 313 | /** @var Plugin $otherPlugin */ 314 | 315 | if ($plugin->name == $otherPlugin->name) { 316 | continue; 317 | } 318 | 319 | $extensionFilePath = $otherPlugin->getPluginPath() . $classPath; 320 | 321 | if (!$this->app['files']->exists($extensionFilePath)) { 322 | continue; 323 | } 324 | 325 | $files[] = $extensionFilePath; 326 | } 327 | 328 | return $files; 329 | } 330 | 331 | /** 332 | * @param $file 333 | * @return bool 334 | */ 335 | protected function fileContainsClass($file) 336 | { 337 | $tokens = token_get_all($file); 338 | 339 | foreach ($tokens as $idx => $token) { 340 | if (is_array($token)) { 341 | if (token_name($token[0]) == 'T_CLASS' && 342 | token_name($tokens[$idx-1][0]) != 'T_DOUBLE_COLON') { 343 | 344 | return true; 345 | } 346 | } 347 | } 348 | 349 | return false; 350 | } 351 | 352 | /** 353 | * @param $file 354 | * @return string 355 | */ 356 | protected function getClassNamespaceFromFilename($file) 357 | { 358 | $namespace = str_replace($this->pluginManager->getPluginDirectory(), 'App\\Plugins', $file); 359 | $namespace = str_replace('/', '\\', $namespace); 360 | $namespace = str_replace('.php', '', $namespace); 361 | 362 | return $namespace; 363 | } 364 | 365 | /** 366 | * @param $file 367 | * @return string 368 | */ 369 | protected function getExtendedClassStoragePath($file) 370 | { 371 | $classNamespace = $this->getClassNamespaceFromFilename($file); 372 | 373 | return storage_path( 374 | 'plugins' 375 | . DIRECTORY_SEPARATOR 376 | . str_replace('\\', '_', $classNamespace) 377 | . '.php' 378 | ); 379 | } 380 | 381 | /** 382 | * @param $class 383 | * @param bool $autoload 384 | * @return bool 385 | */ 386 | protected function classExists($class, $autoload = false) 387 | { 388 | return class_exists($class, $autoload); 389 | } 390 | 391 | /** 392 | * @return bool 393 | */ 394 | protected function load() 395 | { 396 | if (!env('PLUGIN_CACHE', true)) { 397 | return false; 398 | } 399 | 400 | try { 401 | $this->pluginManager->setClassMap(json_decode($this->app['files']->get($this->classMapCacheFile), true)); 402 | } catch (FileNotFoundException $e) { 403 | return false; 404 | } 405 | 406 | return true; 407 | } 408 | 409 | /** 410 | * @return int 411 | */ 412 | protected function writeCache() 413 | { 414 | return $this->app['files']->put($this->classMapCacheFile, json_encode($this->pluginManager->getClassMap())); 415 | } 416 | } 417 | -------------------------------------------------------------------------------- /src/PluginManager.php: -------------------------------------------------------------------------------- 1 | app = $app; 44 | $this->pluginDirectory = $app->path() . DIRECTORY_SEPARATOR . 'Plugins'; 45 | $this->pluginExtender = new PluginExtender($this, $app); 46 | 47 | $this->bootPlugins(); 48 | $this->pluginExtender->extendAll(); 49 | 50 | $this->registerClassLoader(); 51 | } 52 | 53 | /** 54 | * Registers plugin autoloader. 55 | */ 56 | private function registerClassLoader() 57 | { 58 | spl_autoload_register([new ClassLoader($this), 'loadClass'], true, true); 59 | } 60 | 61 | /** 62 | * @param $app 63 | * @return PluginManager 64 | */ 65 | public static function getInstance($app) 66 | { 67 | if (is_null(self::$instance)) { 68 | self::$instance = new self($app); 69 | } 70 | 71 | return self::$instance; 72 | } 73 | 74 | protected function bootPlugins() 75 | { 76 | foreach (Finder::create()->in($this->pluginDirectory)->directories()->depth(0) as $dir) { 77 | /** @var SplFileInfo $dir */ 78 | $directoryName = $dir->getBasename(); 79 | 80 | $pluginClass = $this->getPluginClassNameFromDirectory($directoryName); 81 | 82 | if (!class_exists($pluginClass)) { 83 | dd('Plugin ' . $directoryName . ' needs a ' . $directoryName . 'Plugin class.'); 84 | } 85 | 86 | try { 87 | $plugin = $this->app->makeWith($pluginClass, [$this->app]); 88 | } catch (\ReflectionException $e) { 89 | dd('Plugin ' . $directoryName . ' could not be booted: "' . $e->getMessage() . '"'); 90 | exit; 91 | } 92 | 93 | if (!($plugin instanceof Plugin)) { 94 | dd('Plugin ' . $directoryName . ' must extends the Plugin Base Class'); 95 | } 96 | 97 | $plugin->boot(); 98 | 99 | $this->plugins[$plugin->name] = $plugin; 100 | } 101 | } 102 | 103 | /** 104 | * @param $directory 105 | * @return string 106 | */ 107 | protected function getPluginClassNameFromDirectory($directory) 108 | { 109 | return "App\\Plugins\\${directory}\\${directory}Plugin"; 110 | } 111 | 112 | /** 113 | * @return array 114 | */ 115 | public function getClassMap() 116 | { 117 | return $this->classMap; 118 | } 119 | 120 | /** 121 | * @param array $classMap 122 | * @return $this 123 | */ 124 | public function setClassMap($classMap) 125 | { 126 | $this->classMap = $classMap; 127 | 128 | return $this; 129 | } 130 | 131 | /** 132 | * @param $classNamespace 133 | * @param $storagePath 134 | */ 135 | public function addClassMapping($classNamespace, $storagePath) 136 | { 137 | $this->classMap[$classNamespace] = $storagePath; 138 | } 139 | 140 | /** 141 | * @return array 142 | */ 143 | public function getPlugins() 144 | { 145 | return $this->plugins; 146 | } 147 | 148 | /** 149 | * @return string 150 | */ 151 | public function getPluginDirectory() 152 | { 153 | return $this->pluginDirectory; 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /src/PluginServiceProvider.php: -------------------------------------------------------------------------------- 1 | app); 14 | } 15 | 16 | /** 17 | * Register the service provider. 18 | * 19 | * @return void 20 | */ 21 | public function register() 22 | { 23 | $this->app->bind('laravel-plugins', function ($app) { 24 | return PluginManager::getInstance($app); 25 | }); 26 | } 27 | } 28 | --------------------------------------------------------------------------------