WP Staging – DB & File Duplicator & Migration - Version 2.7.8

Version Description

  • New: Add special admin notice if plugin is not tested with latest WordPress version
  • New: Compatible up to WordPress 5.5.2
  • New: Allow deleting of orphaned staging site entries if staging site was deleted manually before

  • Fix: Activation hook is not fired after first time installation and wpstg optimizer and cron tasks are not set up

  • Fix: Staging site does not work if database password contains dollar sign in password

  • Fix: Prevent fatal error when the plugin is activated, but there is no permission to create folder wp-content/uploads/wp-staging or wp-content/uploads/wp-staging/logs.

  • Dev: Add new DI container implementation

  • Dev: Add composer 2

Download this release

Release Info

Developer ReneHermi
Plugin Icon 128x128 WP Staging – DB & File Duplicator & Migration
Version 2.7.8
Comparing to
See all releases

Code changes from version 2.7.7 to 2.7.8

Files changed (72) hide show
  1. Backend/Administrator.php +2 -2
  2. Backend/Modules/Jobs/CloningProcess.php +50 -11
  3. Backend/Modules/Jobs/Database.php +1 -1
  4. Backend/Modules/Jobs/Delete.php +42 -25
  5. Backend/Notices/Notices.php +66 -42
  6. Backend/views/_main/header.php +2 -2
  7. Backend/views/clone/ajax/delete-confirmation.php +19 -15
  8. Backend/views/clone/ajax/mail-setting.php +1 -1
  9. Backend/views/clone/multi-site/index.php +1 -1
  10. Backend/views/clone/staging-site/index.php +2 -2
  11. Backend/views/notices/cache-directory-permission-problem.php +9 -3
  12. Backend/views/notices/logs-directory-permission-problem.php +9 -3
  13. Backend/views/notices/no-license-key.php +1 -1
  14. Backend/views/notices/rating.php +1 -1
  15. Backend/views/notices/transient.php +2 -2
  16. Backend/views/notices/uploads-cache-directory-permission-problem.php +0 -10
  17. Backend/views/notices/wp-version-compatible-message.php +1 -1
  18. Backend/views/welcome/welcome.php +3 -3
  19. Core/Utils/Cache.php +7 -1
  20. Core/Utils/Logger.php +7 -1
  21. Core/Utils/functions.php +5 -5
  22. Framework/CloningProcess/Data/UpdateWpConfigConstants.php +13 -4
  23. Requirements/WpstgFreeRequirements.php +125 -104
  24. _init.php +8 -45
  25. constants.php +35 -11
  26. install.php +14 -20
  27. readme.txt +25 -35
  28. vendor/composer/autoload_classmap.php +7 -0
  29. vendor/composer/autoload_namespaces.php +2 -0
  30. vendor/composer/autoload_static.php +25 -0
  31. vendor/composer/installed.json +109 -11
  32. vendor/lucatume/di52/.github/workflows/test-php-52.yml +17 -0
  33. vendor/lucatume/di52/.github/workflows/test.yml +33 -0
  34. vendor/lucatume/di52/.gitignore +11 -0
  35. vendor/lucatume/di52/.phpstorm.meta.php +9 -0
  36. vendor/lucatume/di52/CHANGELOG.md +232 -0
  37. vendor/lucatume/di52/README.md +688 -0
  38. vendor/lucatume/di52/_build/check_exports.sh +35 -0
  39. vendor/lucatume/di52/_build/composer-hash.sh +15 -0
  40. vendor/lucatume/di52/_build/containers/php-52/Dockerfile +3 -0
  41. vendor/lucatume/di52/_build/dir_hash.sh +16 -0
  42. vendor/lucatume/di52/_build/release.php +230 -0
  43. vendor/lucatume/di52/autoload.php +27 -0
  44. vendor/lucatume/di52/composer-5-3-plus.json +36 -0
  45. vendor/lucatume/di52/composer.json +53 -0
  46. vendor/lucatume/di52/composer.lock +535 -0
  47. vendor/lucatume/di52/makefile +38 -0
  48. vendor/lucatume/di52/phpunit.xml +17 -0
  49. vendor/lucatume/di52/src/tad/DI52/Container.php +906 -0
  50. vendor/lucatume/di52/src/tad/DI52/ContainerInterface.php +181 -0
  51. vendor/lucatume/di52/src/tad/DI52/ProtectedValue.php +27 -0
  52. vendor/lucatume/di52/src/tad/DI52/ServiceProvider.php +58 -0
  53. vendor/lucatume/di52/src/tad/DI52/ServiceProviderInterface.php +28 -0
  54. vendor/lucatume/di52/src/tad/DI52/closuresSupport.php +68 -0
  55. vendor/lucatume/di52/tests/52-compat/Container52CompatTest.php +1448 -0
  56. vendor/lucatume/di52/tests/52-compat/autoloadTest.php +32 -0
  57. vendor/lucatume/di52/tests/53-above/Container53CompatTest.php +811 -0
  58. vendor/lucatume/di52/tests/bootstrap.php +7 -0
  59. vendor/lucatume/di52/tests/data/namespaced-test-classes.php +170 -0
  60. vendor/lucatume/di52/tests/data/test-classes.php +435 -0
  61. vendor/lucatume/di52/tests/data/test-providers.php +80 -0
  62. vendor/lucatume/di52/todo.txt +1 -0
  63. vendor/symfony/polyfill-ctype/bootstrap.php +11 -11
  64. vendor/symfony/polyfill-ctype/composer.json +1 -1
  65. vendor/xrstf/composer-php52/.gitignore +1 -0
  66. vendor/xrstf/composer-php52/LICENSE +19 -0
  67. vendor/xrstf/composer-php52/README.md +37 -0
  68. vendor/xrstf/composer-php52/composer.json +26 -0
  69. vendor/xrstf/composer-php52/lib/xrstf/Composer52/AutoloadGenerator.php +346 -0
  70. vendor/xrstf/composer-php52/lib/xrstf/Composer52/ClassLoader.php +271 -0
  71. vendor/xrstf/composer-php52/lib/xrstf/Composer52/Generator.php +39 -0
  72. wp-staging.php +23 -8
Backend/Administrator.php CHANGED
@@ -712,12 +712,12 @@ class Administrator extends InjectionAware
712
  */
713
  public function ajaxDeleteConfirmation()
714
  {
715
- if ( ! $this->isAuthenticated()) {
716
  return false;
717
  }
718
 
719
  $delete = new Delete();
720
- $delete->setData();
721
 
722
  $clone = $delete->getClone();
723
 
712
  */
713
  public function ajaxDeleteConfirmation()
714
  {
715
+ if (!$this->isAuthenticated()) {
716
  return false;
717
  }
718
 
719
  $delete = new Delete();
720
+ $isDatabaseConnected = $delete->setData();
721
 
722
  $clone = $delete->getClone();
723
 
Backend/Modules/Jobs/CloningProcess.php CHANGED
@@ -22,23 +22,62 @@ abstract class CloningProcess extends JobExecutable
22
  protected function initializeDbObjects()
23
  {
24
  $this->productionDb = WPStaging::getInstance()->get("wpdb");
 
25
  if ($this->isExternal()) {
26
- $this->stagingDb = new \wpdb($this->options->databaseUser, $this->options->databasePassword, $this->options->databaseDatabase, $this->options->databaseServer);
27
- // Can not connect to mysql
28
- if (!empty($this->stagingDb->error->errors['db_connect_fail']['0'])) {
29
- $this->returnException("Can not connect to external database {$this->options->databaseDatabase}");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  return false;
31
  }
32
- // Can not connect to database
33
- $this->stagingDb->select($this->options->databaseDatabase);
34
- if (!$this->stagingDb->ready) {
35
- $error = isset($db->error->errors['db_select_fail']) ? $db->error->errors['db_select_fail'] : "Error: Can't select {database} Either it does not exist or you don't have privileges to access it.";
36
- $this->returnException($error);
 
 
 
 
 
 
 
 
 
 
 
 
37
  exit;
38
  }
39
- } else {
40
- $this->stagingDb = WPStaging::getInstance()->get("wpdb");
 
 
41
  }
 
42
  }
43
 
44
  protected function isExternal()
22
  protected function initializeDbObjects()
23
  {
24
  $this->productionDb = WPStaging::getInstance()->get("wpdb");
25
+
26
  if ($this->isExternal()) {
27
+ $this->setExternalDatabase();
28
+ } else {
29
+ $this->setLocalDatabase();
30
+ }
31
+ }
32
+
33
+ protected function setLocalDatabase()
34
+ {
35
+ $this->stagingDb = WPStaging::getInstance()->get("wpdb");
36
+ }
37
+
38
+ /**
39
+ * @return bool
40
+ */
41
+ protected function setExternalDatabase()
42
+ {
43
+ $this->stagingDb = new \wpdb($this->options->databaseUser, $this->options->databasePassword, $this->options->databaseDatabase, $this->options->databaseServer);
44
+
45
+ // Check if there were any error when connecting
46
+ if (
47
+ property_exists($this->stagingDb, 'error') &&
48
+ $this->stagingDb->error instanceof \WP_Error
49
+ ) {
50
+ /** @var \WP_Error $wp_error */
51
+ $wp_error = $this->stagingDb->error;
52
+ if ($wp_error->get_error_code() === 'db_connect_fail') {
53
+ $this->returnException(sprintf('Can not connect to external database %s. Reason: %s', $this->options->databaseDatabase, $wp_error->get_error_message()));
54
  return false;
55
  }
56
+ }
57
+
58
+ $this->stagingDb->select($this->options->databaseDatabase);
59
+ if (!$this->stagingDb->ready) {
60
+ if (
61
+ property_exists($this->stagingDb, 'error') &&
62
+ $this->stagingDb->error instanceof \WP_Error
63
+ ) {
64
+ /** @var \WP_Error $wp_error */
65
+ $wp_error = $this->stagingDb->error;
66
+ if ($wp_error->get_error_code() === 'db_select_fail') {
67
+ $this->returnException($wp_error->get_error_message());
68
+ exit;
69
+ }
70
+
71
+ // Generic error
72
+ $this->returnException(sprintf('Error: Can\'t select database %s. Either it does not exist or you don\'t have privileges to access it.', $this->options->databaseDatabase));
73
  exit;
74
  }
75
+
76
+ // Generic error
77
+ $this->returnException(sprintf('Error: Can\'t select database %s. Either it does not exist or you don\'t have privileges to access it.', $this->options->databaseDatabase));
78
+ exit;
79
  }
80
+ return true;
81
  }
82
 
83
  protected function isExternal()
Backend/Modules/Jobs/Database.php CHANGED
@@ -150,7 +150,7 @@ class Database extends CloningProcess
150
  if (defined('WPSTGPRO_VERSION')) {
151
  return false;
152
  }
153
- $this->returnException(__("This staging site is located in another database and needs to be edited with <a href='https://wp-staging.com' target='_blank'>WP Staging Pro</a>", "wp-staging"));
154
  return true;
155
  }
156
 
150
  if (defined('WPSTGPRO_VERSION')) {
151
  return false;
152
  }
153
+ $this->returnException(__("This staging site is located in another database and needs to be edited with <a href='https://wp-staging.com' target='_blank'>WP STAGING Pro</a>", "wp-staging"));
154
  return true;
155
  }
156
 
Backend/Modules/Jobs/Delete.php CHANGED
@@ -3,7 +3,6 @@
3
  namespace WPStaging\Backend\Modules\Jobs;
4
 
5
  use WPStaging\Backend\Modules\Jobs\Exceptions\CloneNotFoundException;
6
- use WPStaging\Utils\Directories;
7
  use WPStaging\Utils\Logger;
8
  use WPStaging\WPStaging;
9
 
@@ -14,13 +13,13 @@ use WPStaging\WPStaging;
14
  class Delete extends Job {
15
 
16
  /**
17
- * @var false
18
  */
19
  private $clone = false;
20
 
21
  /**
22
  * The path to delete
23
- * @var type
24
  */
25
  private $deleteDir = '';
26
 
@@ -61,22 +60,30 @@ class Delete extends Job {
61
  /**
62
  * Sets Clone and Table Records
63
  * @param null|array $clone
 
64
  */
65
- public function setData( $clone = null ) {
66
- if( !is_array( $clone ) ) {
 
67
  $this->getCloneRecords();
68
  } else {
69
- $this->clone = ( object ) $clone;
70
  $this->forceDeleteDirectories = true;
71
  }
72
 
73
- if( $this->isExternalDatabase() ) {
74
- $this->wpdb = $this->getStagingDb();
75
- } else {
76
- $this->wpdb = WPStaging::getInstance()->get( "wpdb" );
77
  }
78
-
 
 
 
 
 
79
  $this->getTableRecords();
 
80
  }
81
 
82
  /**
@@ -88,7 +95,7 @@ class Delete extends Job {
88
 
89
  /**
90
  * Date database name
91
- * @return type
92
  */
93
  public function getDbName() {
94
  return $this->wpdb->dbname;
@@ -117,19 +124,17 @@ class Delete extends Job {
117
  private function getCloneRecords( $name = null ) {
118
  if( null === $name && !isset( $_POST["clone"] ) ) {
119
  $this->log( "Clone name is not set", Logger::TYPE_FATAL );
120
- //throw new CloneNotFoundException();
121
  $this->returnException( "Clone name is not set" );
122
  }
123
 
124
  if( null === $name ) {
125
- $name = $_POST["clone"];
126
  }
127
 
128
  $clones = get_option( "wpstg_existing_clones_beta", array() );
129
 
130
  if( empty( $clones ) || !isset( $clones[$name] ) ) {
131
  $this->log( "Couldn't find clone name {$name} or no existing clone", Logger::TYPE_FATAL );
132
- //throw new CloneNotFoundException();
133
  $this->returnException( "Couldn't find clone name {$name} or no existing clone" );
134
  }
135
 
@@ -327,9 +332,9 @@ class Delete extends Job {
327
  if( !$this->isExternalDatabase() && $this->startsWith( $table, $this->wpdb->prefix ) ) {
328
  $this->log( "Fatal Error: Trying to delete table {$table} of main WP installation!", Logger::TYPE_CRITICAL );
329
  return false;
330
- } else {
331
- $this->wpdb->query( "DROP TABLE {$table}" );
332
  }
 
 
333
  }
334
 
335
  // Move on to the next
@@ -349,9 +354,9 @@ class Delete extends Job {
349
  }
350
 
351
  /**
 
352
  * Delete complete directory including all files and subfolders
353
- *
354
- * @throws InvalidArgumentException
355
  */
356
  public function deleteDirectory() {
357
  if( $this->isFatalError() ) {
@@ -379,7 +384,6 @@ class Delete extends Job {
379
 
380
  // Check if threshold is reached
381
  if( $this->isOverThreshold() ) {
382
- //$this->returnException('Maximum PHP execution time exceeded. Run again and repeat the deletion process until it is sucessfully finished.');
383
  return;
384
  }
385
 
@@ -389,7 +393,6 @@ class Delete extends Job {
389
  foreach ( $ri as $file ) {
390
  $this->deleteFile( $file );
391
  if( $this->isOverThreshold() ) {
392
- //$this->returnException('Maximum PHP execution time exceeded. Run again and repeat the deletion process until it is sucessfully finished.');
393
  return;
394
  }
395
  }
@@ -458,10 +461,7 @@ class Delete extends Job {
458
  */
459
  public function isFatalError() {
460
  $homePath = rtrim( get_home_path(), "/" );
461
- if( rtrim( $this->deleteDir, "/" ) == $homePath ) {
462
- return true;
463
- }
464
- return false;
465
  }
466
 
467
  /**
@@ -495,4 +495,21 @@ class Delete extends Job {
495
  wp_die( json_encode( $response ) );
496
  }
497
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
498
  }
3
  namespace WPStaging\Backend\Modules\Jobs;
4
 
5
  use WPStaging\Backend\Modules\Jobs\Exceptions\CloneNotFoundException;
 
6
  use WPStaging\Utils\Logger;
7
  use WPStaging\WPStaging;
8
 
13
  class Delete extends Job {
14
 
15
  /**
16
+ * @var \stdClass
17
  */
18
  private $clone = false;
19
 
20
  /**
21
  * The path to delete
22
+ * @var string
23
  */
24
  private $deleteDir = '';
25
 
60
  /**
61
  * Sets Clone and Table Records
62
  * @param null|array $clone
63
+ * @return bool
64
  */
65
+ public function setData($clone = null)
66
+ {
67
+ if(!is_array($clone)) {
68
  $this->getCloneRecords();
69
  } else {
70
+ $this->clone = (object) $clone;
71
  $this->forceDeleteDirectories = true;
72
  }
73
 
74
+ if(!$this->isExternalDatabase()) {
75
+ $this->wpdb = WPStaging::getInstance()->get("wpdb");
76
+ $this->getTableRecords();
77
+ return true;
78
  }
79
+
80
+ if ($this->isExternalDatabaseError()) {
81
+ return false;
82
+ }
83
+
84
+ $this->wpdb = $this->getStagingDb();
85
  $this->getTableRecords();
86
+ return true;
87
  }
88
 
89
  /**
95
 
96
  /**
97
  * Date database name
98
+ * @return string
99
  */
100
  public function getDbName() {
101
  return $this->wpdb->dbname;
124
  private function getCloneRecords( $name = null ) {
125
  if( null === $name && !isset( $_POST["clone"] ) ) {
126
  $this->log( "Clone name is not set", Logger::TYPE_FATAL );
 
127
  $this->returnException( "Clone name is not set" );
128
  }
129
 
130
  if( null === $name ) {
131
+ $name = (string)$_POST["clone"];
132
  }
133
 
134
  $clones = get_option( "wpstg_existing_clones_beta", array() );
135
 
136
  if( empty( $clones ) || !isset( $clones[$name] ) ) {
137
  $this->log( "Couldn't find clone name {$name} or no existing clone", Logger::TYPE_FATAL );
 
138
  $this->returnException( "Couldn't find clone name {$name} or no existing clone" );
139
  }
140
 
332
  if( !$this->isExternalDatabase() && $this->startsWith( $table, $this->wpdb->prefix ) ) {
333
  $this->log( "Fatal Error: Trying to delete table {$table} of main WP installation!", Logger::TYPE_CRITICAL );
334
  return false;
 
 
335
  }
336
+
337
+ $this->wpdb->query( "DROP TABLE {$table}" );
338
  }
339
 
340
  // Move on to the next
354
  }
355
 
356
  /**
357
+ *
358
  * Delete complete directory including all files and subfolders
359
+ * @throws \Exception
 
360
  */
361
  public function deleteDirectory() {
362
  if( $this->isFatalError() ) {
384
 
385
  // Check if threshold is reached
386
  if( $this->isOverThreshold() ) {
 
387
  return;
388
  }
389
 
393
  foreach ( $ri as $file ) {
394
  $this->deleteFile( $file );
395
  if( $this->isOverThreshold() ) {
 
396
  return;
397
  }
398
  }
461
  */
462
  public function isFatalError() {
463
  $homePath = rtrim( get_home_path(), "/" );
464
+ return rtrim($this->deleteDir, "/") == $homePath;
 
 
 
465
  }
466
 
467
  /**
495
  wp_die( json_encode( $response ) );
496
  }
497
 
498
+ /**
499
+ * Check if there is error in external database connection
500
+ * can happen if the external database does not exist or stored credentials are wrong
501
+ * @return bool
502
+ *
503
+ * @todo replace it logic with DbInfo once collation check PR is merged.
504
+ */
505
+ private function isExternalDatabaseError()
506
+ {
507
+ $db = new \mysqli($this->clone->databaseServer, $this->clone->databaseUser, $this->clone->databasePassword, $this->clone->databaseDatabase);
508
+ if ($db->connect_error) {
509
+ return true;
510
+ }
511
+
512
+ return false;
513
+ }
514
+
515
  }
Backend/Notices/Notices.php CHANGED
@@ -7,18 +7,21 @@ namespace WPStaging\Backend\Notices;
7
  */
8
 
9
  // No Direct Access
10
- if( !defined( "WPINC" ) ) {
11
  die;
12
  }
13
 
14
  use WPStaging\Backend\Pro\Notices\Notices as ProNotices;
 
 
 
15
 
16
  /**
17
  * Class Notices
18
  * @package WPStaging\Backend\Notices
19
  */
20
- class Notices {
21
-
22
  /**
23
  * @var string
24
  */
@@ -29,67 +32,81 @@ class Notices {
29
  */
30
  private $url;
31
 
32
- public function __construct( $path, $url ) {
 
33
  $this->path = $path;
34
- $this->url = $url;
35
  }
36
 
37
  /**
38
  * Check whether the page is admin page or not
39
  * @return bool
40
  */
41
- public function isAdminPage() {
 
42
  $currentPage = (isset( $_GET["page"] )) ? $_GET["page"] : null;
43
 
44
  $availablePages = array(
45
  "wpstg-settings", "wpstg-addons", "wpstg-tools", "wpstg-clone", "wpstg_clone"
46
  );
47
 
48
- if( !is_admin() || !in_array( $currentPage, $availablePages, true ) ) {
49
  return false;
50
  }
51
 
52
  return true;
53
  }
54
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  /**
56
  * Check if notice should be shown after certain days of installation
57
  * @param int $days default 10
58
  * @return bool
59
  */
60
- private function canShow( $option, $days = 10 ) {
61
-
62
  // Do not show notice
63
- if( empty( $option ) ) {
64
  return false;
65
  }
66
 
67
- $dbOption = get_option( $option );
68
 
69
  // Do not show notice
70
- if ("no" === $dbOption){
71
  return false;
72
  }
73
 
74
- $now = new \DateTime( "now" );
75
 
76
  // Check if user clicked on "rate later" button and if there is a valid 'later' date
77
- if( wpstg_is_valid_date( $dbOption ) ) {
78
  // Do not show before this date
79
- $show = new \DateTime( $dbOption );
80
- if ($now < $show){
81
  return false;
82
  }
83
  }
84
 
85
 
86
  // Show X days after installation
87
- $installDate = new \DateTime( get_option( "wpstg_installDate" ) );
88
 
89
  // get number of days between installation date and today
90
- $difference = $now->diff( $installDate )->days;
91
 
92
- if( $days <= $difference ) {
93
  return true;
94
  }
95
 
@@ -100,8 +117,9 @@ class Notices {
100
  * Get current page
101
  * @return string | post, page
102
  */
103
- private function getCurrentScreen() {
104
- if( function_exists( 'get_current_screen' ) ) {
 
105
  return \get_current_screen()->post_type;
106
  }
107
  }
@@ -115,47 +133,52 @@ class Notices {
115
  $viewsNoticesPath = "{$this->path}views/notices/";
116
 
117
  // Show "rate the plugin". Free version only
118
- if (!defined('WPSTGPRO_VERSION')) {
119
- if ($this->canShow("wpstg_rating", 7) && $this->getCurrentScreen() !== 'page' && $this->getCurrentScreen() !== 'post') {
120
  require_once "{$viewsNoticesPath}rating.php";
121
  }
122
 
123
  }
124
 
125
  // Show all pro version notices
126
- if (defined('WPSTGPRO_VERSION')) {
127
  $proNotices = new ProNotices($this);
128
  $proNotices->getNotices();
129
  }
130
 
131
  // Display notices below in wp staging admin pages only
132
- if( !current_user_can( "update_plugins" ) || !$this->isAdminPage() ) {
133
  return;
134
  }
135
 
136
- // Cache directory in uploads is not writable
137
- $varsDirectory = \WPStaging\WPStaging::getContentDir();
138
- if( !is_writable( $varsDirectory ) ) {
139
- require_once "{$viewsNoticesPath}/uploads-cache-directory-permission-problem.php";
 
 
 
 
 
 
 
 
 
 
140
  }
141
 
142
  // Staging directory is not writable
143
- if( !is_writeable( ABSPATH ) ) {
144
  require_once "{$viewsNoticesPath}/staging-directory-permission-problem.php";
145
  }
146
 
147
- // Version Control
148
- if( version_compare( WPSTG_COMPATIBLE, get_bloginfo( "version" ), "<" ) ) {
149
  require_once "{$viewsNoticesPath}wp-version-compatible-message.php";
150
  }
151
 
152
- // Beta
153
- /*if( false === get_option( "wpstg_beta" ) || "no" !== get_option( "wpstg_beta" ) ) {
154
- require_once "{$viewsNoticesPath}beta.php";
155
- }*/
156
-
157
  // Different scheme in home and siteurl
158
- if( $this->isDifferentScheme() ) {
159
  require_once "{$viewsNoticesPath}wrong-scheme.php";
160
  }
161
  }
@@ -164,11 +187,12 @@ class Notices {
164
  * Check if the url scheme of siteurl and home is identical
165
  * @return boolean
166
  */
167
- private function isDifferentScheme() {
168
- $siteurlScheme = parse_url( get_option( 'siteurl' ), PHP_URL_SCHEME );
169
- $homeScheme = parse_url( get_option( 'home' ), PHP_URL_SCHEME );
 
170
 
171
- if( $siteurlScheme === $homeScheme ) {
172
  return false;
173
  }
174
  return true;
7
  */
8
 
9
  // No Direct Access
10
+ if (!defined("WPINC")) {
11
  die;
12
  }
13
 
14
  use WPStaging\Backend\Pro\Notices\Notices as ProNotices;
15
+ use WPStaging\Utils\Cache;
16
+ use WPStaging\Utils\Logger;
17
+ use WPStaging\WPStaging;
18
 
19
  /**
20
  * Class Notices
21
  * @package WPStaging\Backend\Notices
22
  */
23
+ class Notices
24
+ {
25
  /**
26
  * @var string
27
  */
32
  */
33
  private $url;
34
 
35
+ public function __construct($path, $url)
36
+ {
37
  $this->path = $path;
38
+ $this->url = $url;
39
  }
40
 
41
  /**
42
  * Check whether the page is admin page or not
43
  * @return bool
44
  */
45
+ public function isAdminPage()
46
+ {
47
  $currentPage = (isset( $_GET["page"] )) ? $_GET["page"] : null;
48
 
49
  $availablePages = array(
50
  "wpstg-settings", "wpstg-addons", "wpstg-tools", "wpstg-clone", "wpstg_clone"
51
  );
52
 
53
+ if(!is_admin() || !in_array( $currentPage, $availablePages, true)) {
54
  return false;
55
  }
56
 
57
  return true;
58
  }
59
 
60
+ /**
61
+ * check whether the plugin is pro version
62
+ *
63
+ * @todo Implement this in a separate class related to plugin. Then replace it with dependency injection. Add filters
64
+ *
65
+ * @return boolean
66
+ */
67
+ protected function isPro()
68
+ {
69
+ return defined('WPSTGPRO_VERSION');
70
+ }
71
+
72
  /**
73
  * Check if notice should be shown after certain days of installation
74
  * @param int $days default 10
75
  * @return bool
76
  */
77
+ private function canShow($option, $days = 10)
78
+ {
79
  // Do not show notice
80
+ if (empty($option)) {
81
  return false;
82
  }
83
 
84
+ $dbOption = get_option($option);
85
 
86
  // Do not show notice
87
+ if ("no" === $dbOption) {
88
  return false;
89
  }
90
 
91
+ $now = new \DateTime("now");
92
 
93
  // Check if user clicked on "rate later" button and if there is a valid 'later' date
94
+ if (wpstg_is_valid_date($dbOption)) {
95
  // Do not show before this date
96
+ $show = new \DateTime($dbOption);
97
+ if ($now < $show) {
98
  return false;
99
  }
100
  }
101
 
102
 
103
  // Show X days after installation
104
+ $installDate = new \DateTime(get_option("wpstg_installDate"));
105
 
106
  // get number of days between installation date and today
107
+ $difference = $now->diff($installDate)->days;
108
 
109
+ if ($days <= $difference) {
110
  return true;
111
  }
112
 
117
  * Get current page
118
  * @return string | post, page
119
  */
120
+ private function getCurrentScreen()
121
+ {
122
+ if (function_exists('get_current_screen')) {
123
  return \get_current_screen()->post_type;
124
  }
125
  }
133
  $viewsNoticesPath = "{$this->path}views/notices/";
134
 
135
  // Show "rate the plugin". Free version only
136
+ if (!$this->isPro()) {
137
+ if ($this->canShow("wpstg_rating", 7) && $this->getCurrentScreen() !== 'page' && $this->getCurrentScreen() !== 'post') {
138
  require_once "{$viewsNoticesPath}rating.php";
139
  }
140
 
141
  }
142
 
143
  // Show all pro version notices
144
+ if ($this->isPro()) {
145
  $proNotices = new ProNotices($this);
146
  $proNotices->getNotices();
147
  }
148
 
149
  // Display notices below in wp staging admin pages only
150
+ if (!current_user_can("update_plugins") || !$this->isAdminPage()) {
151
  return;
152
  }
153
 
154
+ // Cache directory is not writable
155
+ /** @var Cache $cache */
156
+ $cache = WPStaging::getInstance()->get("cache");
157
+ $cacheDir = $cache->getCacheDir();
158
+ if (!is_dir($cacheDir) || !is_writable($cacheDir)) {
159
+ require_once "{$viewsNoticesPath}/cache-directory-permission-problem.php";
160
+ }
161
+
162
+ // Logger directory is not writable
163
+ /** @var Logger $logger */
164
+ $logger = WPStaging::getInstance()->get("logger");
165
+ $logsDir = $logger->getLogDir();
166
+ if (!is_dir($logsDir) || !is_writable($logsDir)) {
167
+ require_once "{$viewsNoticesPath}/logs-directory-permission-problem.php";
168
  }
169
 
170
  // Staging directory is not writable
171
+ if (!is_writeable(ABSPATH)) {
172
  require_once "{$viewsNoticesPath}/staging-directory-permission-problem.php";
173
  }
174
 
175
+ // Version Control for Free
176
+ if(!$this->isPro() && version_compare(WPStaging::getInstance()->get('WPSTG_COMPATIBLE'), get_bloginfo("version"), "<")) {
177
  require_once "{$viewsNoticesPath}wp-version-compatible-message.php";
178
  }
179
 
 
 
 
 
 
180
  // Different scheme in home and siteurl
181
+ if ($this->isDifferentScheme()) {
182
  require_once "{$viewsNoticesPath}wrong-scheme.php";
183
  }
184
  }
187
  * Check if the url scheme of siteurl and home is identical
188
  * @return boolean
189
  */
190
+ private function isDifferentScheme()
191
+ {
192
+ $siteurlScheme = parse_url(get_option('siteurl'), PHP_URL_SCHEME);
193
+ $homeScheme = parse_url(get_option('home'), PHP_URL_SCHEME);
194
 
195
+ if ($siteurlScheme === $homeScheme) {
196
  return false;
197
  }
198
  return true;
Backend/views/_main/header.php CHANGED
@@ -49,8 +49,8 @@
49
  ?>
50
 
51
  <div id="wpstg-update-notify" style="display:<?php echo $display; ?>">
52
- <strong><?php echo sprintf( __( 'WP Staging Pro %s is available!', 'wp-staging' ), $version ); ?></strong> <br/>
53
- <?php echo sprintf( __( 'Important: Please update WP Staging Pro before pushing the staging site to production site. <a href="%s" target="_blank">What\'s New? ', 'wp-staging' ), 'https://wp-staging.com/wp-staging-pro-changelog' ); ?></a>
54
  </div>
55
 
56
  </div>
49
  ?>
50
 
51
  <div id="wpstg-update-notify" style="display:<?php echo $display; ?>">
52
+ <strong><?php echo sprintf( __( 'WP STAGING Pro %s is available!', 'wp-staging' ), $version ); ?></strong> <br/>
53
+ <?php echo sprintf( __( 'Important: Please update WP STAGING Pro before pushing the staging site to production site. <a href="%s" target="_blank">What\'s New? ', 'wp-staging' ), 'https://wp-staging.com/wp-staging-pro-changelog' ); ?></a>
54
  </div>
55
 
56
  </div>
Backend/views/clone/ajax/delete-confirmation.php CHANGED
@@ -1,9 +1,10 @@
1
- <div class="wpstg-notice-alert wpstg-failed">
2
- <h4 style="margin:0">
 
3
  <?php
4
- _e("Note: The selected tables below will be deleted. <br/>Verify that before you delete them.", "wp-staging")
5
  ?>
6
- </h4>
7
 
8
  <p>
9
  <?php _e('Clone Name:', 'wp-staging'); ?>
@@ -22,20 +23,22 @@
22
  ?>
23
  </span>
24
  </p>
 
 
25
 
26
- <p>
27
- <?php
28
- _e(
29
- 'Usually the preselected data can be deleted without any risk '.
30
- 'but in case something is going wrong you better verify it.',
31
- 'wp-staging'
32
- );
33
- ?>
34
- </p>
35
  </div>
 
36
 
37
  <div class="wpstg-tabs-wrapper">
38
 
 
39
  <a href="#" class="wpstg-tab-header active" data-id="#wpstg-scanning-db">
40
  <span class="wpstg-tab-triangle">&#9658;</span>
41
  <?php echo __("Database tables to remove", "wp-staging")?>
@@ -48,7 +51,7 @@
48
  </h4>
49
  <div style="margin-bottom:6px;margin-top:6px;">
50
  <a href="#" class="wpstg-button-unselect">
51
- Unselect All
52
  </a>
53
  </div>
54
 
@@ -65,10 +68,11 @@
65
  <?php endforeach ?>
66
  <div style="margin-bottom:6px;margin-top:6px;">
67
  <a href="#" class="wpstg-button-unselect">
68
- Unselect All
69
  </a>
70
  </div>
71
  </div>
 
72
  <!-- /Database -->
73
 
74
  <a href="#" class="wpstg-tab-header" data-id="#wpstg-scanning-files">
1
+ <?php if ($isDatabaseConnected) { ?>
2
+ <div class="wpstg-notice-alert">
3
+ <h3 style="margin:0;padding-bottom:5px;">
4
  <?php
5
+ _e("This staging site will be deleted:", "wp-staging")
6
  ?>
7
+ </h3>
8
 
9
  <p>
10
  <?php _e('Clone Name:', 'wp-staging'); ?>
23
  ?>
24
  </span>
25
  </p>
26
+ </div>
27
+ <?php } ?>
28
 
29
+ <?php if (!$isDatabaseConnected) { ?>
30
+ <div class="wpstg-notice-alert wpstg-failed">
31
+ <h4 class="wpstg-mb-0"><?php _e('Error: Can not connect to external database: ', 'wp-staging'); echo $clone->databaseDatabase; ?></h4>
32
+ <ul class="wpstg-mb-0">
33
+ <li><?php _e('This can happen if the password of the external database has been changed or if the database was deleted', 'wp-staging') ?></li>
34
+ <li><?php _e('You can still delete this staging site but deleting this site will not delete any table or database. You will have to delete them manually if they exist.', 'wp-staging') ?></li>
35
+ </ul>
 
 
36
  </div>
37
+ <?php } ?>
38
 
39
  <div class="wpstg-tabs-wrapper">
40
 
41
+ <?php if ($isDatabaseConnected) { ?>
42
  <a href="#" class="wpstg-tab-header active" data-id="#wpstg-scanning-db">
43
  <span class="wpstg-tab-triangle">&#9658;</span>
44
  <?php echo __("Database tables to remove", "wp-staging")?>
51
  </h4>
52
  <div style="margin-bottom:6px;margin-top:6px;">
53
  <a href="#" class="wpstg-button-unselect">
54
+ <?php _e("Unselect All", "wp-staging") ?>
55
  </a>
56
  </div>
57
 
68
  <?php endforeach ?>
69
  <div style="margin-bottom:6px;margin-top:6px;">
70
  <a href="#" class="wpstg-button-unselect">
71
+ <?php _e("Unselect All", "wp-staging") ?>
72
  </a>
73
  </div>
74
  </div>
75
+ <?php } ?>
76
  <!-- /Database -->
77
 
78
  <a href="#" class="wpstg-tab-header" data-id="#wpstg-scanning-files">
Backend/views/clone/ajax/mail-setting.php CHANGED
@@ -11,5 +11,5 @@
11
  </div>
12
  <p style="font-weight:bold;background-color:#e6e6e6;padding:15px;border-top: 1px solid white;margin-top: 20px;"><?php _e('That\'s a Pro Feature', 'wp-staging'); ?>
13
  <br>
14
- <a href="https://wp-staging.com/?utm_source=wp-admin&utm_medium=wp-admin&utm_campaign=db-external&utm_term=db-external" target="_blank" class="quads-button green wpstg-button" style="border-radius:3px;font-size: 14px;border: 1px solid white;"><?php _e("Get WP Staging Pro", "wp-staging"); ?></a>
15
  </p>
11
  </div>
12
  <p style="font-weight:bold;background-color:#e6e6e6;padding:15px;border-top: 1px solid white;margin-top: 20px;"><?php _e('That\'s a Pro Feature', 'wp-staging'); ?>
13
  <br>
14
+ <a href="https://wp-staging.com/?utm_source=wp-admin&utm_medium=wp-admin&utm_campaign=db-external&utm_term=db-external" target="_blank" class="quads-button green wpstg-button" style="border-radius:3px;font-size: 14px;border: 1px solid white;"><?php _e("Get WP STAGING Pro", "wp-staging"); ?></a>
15
  </p>
Backend/views/clone/multi-site/index.php CHANGED
@@ -1,3 +1,3 @@
1
  <span class="wpstg-notice-alert" style="margin-top:20px;">
2
- <?php echo sprintf(__('WordPress Multisite is not supported! Upgrade to <a href="%s" target="_blank">WP Staging Pro</a>', 'wp-staging'), 'https://wp-staging.com/')?>
3
  </span>
1
  <span class="wpstg-notice-alert" style="margin-top:20px;">
2
+ <?php echo sprintf(__('WordPress Multisite is not supported! Upgrade to <a href="%s" target="_blank">WP STAGING Pro</a>', 'wp-staging'), 'https://wp-staging.com/')?>
3
  </span>
Backend/views/clone/staging-site/index.php CHANGED
@@ -1,7 +1,7 @@
1
  <span class="wpstg-notice-alert" style="margin-top:20px;">
2
- <?php echo __("This staging site can be pushed and modified with WP Staging Pro plugin installed on your production site! Open WP Staging Pro on your production site and start the pushing process from there!", "wp-staging")?>
3
  <br/>
4
- <?php echo sprintf(__("<a href='%s' target='_new'>Open WP Staging Pro on Live Site</a>"), wpstg_get_production_hostname() . '/wp-admin/admin.php?page=wpstg_clone'); ?>
5
  <br/>
6
  <br/>
7
  <?php echo sprintf(__("If you like to clone this staging site check out <a href='%s' target='_new'>this article</a>."), 'https://wp-staging.com/docs/cloning-a-staging-site-testing-push-method/'); ?>
1
  <span class="wpstg-notice-alert" style="margin-top:20px;">
2
+ <?php echo __("This staging site can be pushed and modified with WP STAGING Pro plugin installed on your production site! Open WP Staging Pro on your production site and start the pushing process from there!", "wp-staging")?>
3
  <br/>
4
+ <?php echo sprintf(__("<a href='%s' target='_new'>Open WP STAGING Pro on Live Site</a>"), wpstg_get_production_hostname() . '/wp-admin/admin.php?page=wpstg_clone'); ?>
5
  <br/>
6
  <br/>
7
  <?php echo sprintf(__("If you like to clone this staging site check out <a href='%s' target='_new'>this article</a>."), 'https://wp-staging.com/docs/cloning-a-staging-site-testing-push-method/'); ?>
Backend/views/notices/cache-directory-permission-problem.php CHANGED
@@ -1,7 +1,13 @@
 
 
 
 
 
 
1
  <div class="wpstg-error">
2
  <p>
3
- <strong>WP Staging Folder Permission error: </strong> <?php echo "{$varsDirectory}cache"?> is not write and/or readable.
4
  <br>
5
- Check if the folder <strong><?php echo "{$varsDirectory}cache"?></strong> exists! Folder permissions should be chmod 755 or higher.
6
  </p>
7
- </div>
1
+ <?php
2
+ /**
3
+ * @var string $cacheDir
4
+ * @see \WPStaging\Backend\Notices\Notices::messages
5
+ */
6
+ ?>
7
  <div class="wpstg-error">
8
  <p>
9
+ <strong>WP Staging Folder Permission error: </strong> <?php echo $cacheDir; ?> is not write and/or readable.
10
  <br>
11
+ Check if the folder <strong><?php echo $cacheDir; ?></strong> exists! Folder permissions should be chmod 755 or higher.
12
  </p>
13
+ </div>
Backend/views/notices/logs-directory-permission-problem.php CHANGED
@@ -1,7 +1,13 @@
 
 
 
 
 
 
1
  <div class="wpstg-error">
2
  <p>
3
- <strong>WP Staging Folder Permission error: </strong> <?php echo "{$varsDirectory}logs"?> is not write and/or readable.
4
  <br>
5
- Check if the folder <strong><?php echo "{$varsDirectory}logs"?></strong> exists! Folder permissions should be chmod 755 or higher.
6
  </p>
7
- </div>
1
+ <?php
2
+ /**
3
+ * @var string $logsDir
4
+ * @see \WPStaging\Backend\Notices\Notices::messages
5
+ */
6
+ ?>
7
  <div class="wpstg-error">
8
  <p>
9
+ <strong>WP Staging Folder Permission error: </strong> <?php echo $logsDir; ?> is not write and/or readable.
10
  <br>
11
+ Check if the folder <strong><?php echo $logsDir; ?></strong> exists! Folder permissions should be chmod 755 or higher.
12
  </p>
13
+ </div>
Backend/views/notices/no-license-key.php CHANGED
@@ -2,7 +2,7 @@
2
  <p>
3
  <?php
4
  echo sprintf( __(
5
- 'You have no license key entered. WP Staging Pro needs a valid license key to be activated. You can purchase the license from here:' .
6
  '<br/> <a href="%1$s" target="_blank">%1$s</a>', 'wp-staging'), 'https://wp-staging.com'
7
  );
8
  ?>
2
  <p>
3
  <?php
4
  echo sprintf( __(
5
+ 'You have no license key entered. WP STAGING Pro needs a valid license key to be activated. You can purchase the license from here:' .
6
  '<br/> <a href="%1$s" target="_blank">%1$s</a>', 'wp-staging'), 'https://wp-staging.com'
7
  );
8
  ?>
Backend/views/notices/rating.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
  /**
3
  * @var $this \WPStaging\Backend\Notices\Notices
4
- * @see \WPStaging\Backend\Notices\Notices::messages
5
  */
6
  ?>
7
  <div class="wpstg_fivestar" style="display:none;box-shadow: 0 1px 1px 0 rgba(0,0,0,.1); border-left:none; background-color:#59a7f7; color:white; padding: 10px; margin: 10px; margin-left: 0px;">
1
  <?php
2
  /**
3
  * @var $this \WPStaging\Backend\Notices\Notices
4
+ * @see \WPStaging\Backend\Notices\Notices::showNotices
5
  */
6
  ?>
7
  <div class="wpstg_fivestar" style="display:none;box-shadow: 0 1px 1px 0 rgba(0,0,0,.1); border-left:none; background-color:#59a7f7; color:white; padding: 10px; margin: 10px; margin-left: 0px;">
Backend/views/notices/transient.php CHANGED
@@ -3,8 +3,8 @@
3
  <?php
4
  echo esc_html(
5
  ('1' === $deactivatedNoticeID) ?
6
- __("WP Staging and WP Staging Pro cannot both be active. We've automatically deactivated WP Staging.", "wp-staging"):
7
- __("WP Staging and WP Staging Pro cannot both be active. We've automatically deactivated WP Staging Pro.", "wp-staging")
8
  )
9
  ?>
10
  </p>
3
  <?php
4
  echo esc_html(
5
  ('1' === $deactivatedNoticeID) ?
6
+ __("WP Staging and WP STAGING Pro cannot both be active. We've automatically deactivated WP STAGING.", "wp-staging"):
7
+ __("WP Staging and WP STAGING Pro cannot both be active. We've automatically deactivated WP STAGING Pro.", "wp-staging")
8
  )
9
  ?>
10
  </p>
Backend/views/notices/uploads-cache-directory-permission-problem.php DELETED
@@ -1,10 +0,0 @@
1
- <div class="wpstg-error">
2
- <p>
3
- <strong>WP Staging Folder Permission error: </strong>
4
- <?php echo \WPStaging\WPStaging::getContentDir()?>
5
- is not write and/or readable.
6
- <br>
7
- Check if the folder <strong><?php echo \WPStaging\WPStaging::getContentDir()?></strong> exists!
8
- Folder permissions should be chmod 755 or 777.
9
- </p>
10
- </div>
 
 
 
 
 
 
 
 
 
 
Backend/views/notices/wp-version-compatible-message.php CHANGED
@@ -2,7 +2,7 @@
2
  <p>
3
  <?php
4
  echo sprintf( __(
5
- 'Your version of WP Staging has not been tested with WordPress %2$s.' .
6
  '<br/><br/>WP STAGING has an enterprise-level quality control that performs a compatibility audit on every new WordPress release.' .
7
  '<br/>We prioritize testing the Pro version of the plugin first, which receives the compatibility audit earlier than the Free version. If you are in a rush, upgrade to Pro today to get the latest version of WPSTAGING.' .
8
  '<p><a href="%1$s" target="_blank"><strong>Get the latest version Now</strong></a>.', 'wp-staging'), 'https://wp-staging.com', get_bloginfo( 'version' )
2
  <p>
3
  <?php
4
  echo sprintf( __(
5
+ 'Your version of WP STAGING has not been tested with WordPress %2$s.' .
6
  '<br/><br/>WP STAGING has an enterprise-level quality control that performs a compatibility audit on every new WordPress release.' .
7
  '<br/>We prioritize testing the Pro version of the plugin first, which receives the compatibility audit earlier than the Free version. If you are in a rush, upgrade to Pro today to get the latest version of WPSTAGING.' .
8
  '<p><a href="%1$s" target="_blank"><strong>Get the latest version Now</strong></a>.', 'wp-staging'), 'https://wp-staging.com', get_bloginfo( 'version' )
Backend/views/welcome/welcome.php CHANGED
@@ -1,15 +1,15 @@
1
  <div class="" id="wpstg-welcome">
2
  <div style="border: 2px solid white;padding: 20px;margin-bottom:20px;">
3
  <h2 class="wpstg-h2">
4
- <span class="wpstg-heading-pro"><?php _e( 'WP Staging Pro', 'wp-staging' ); ?></span><?php _e( ' - Copy Themes & Plugins from Staging to Live Site', 'wp-staging' ); ?>
5
  </h2>
6
  <li><strong>Cloning</strong> - <?php _e( 'Create a clone of your website with a simple click', 'wp-staging' ); ?></li>
7
  <li><strong>Push Changes</strong> - <?php _e( 'Copy plugin and theme files from staging to live site', 'wp-staging' ); ?></li>
8
  <li><strong>Authentication</strong> - <?php _e( 'Staging Site is available to authenticated users only', 'wp-staging' ); ?></li>
9
  <li><strong>High Performance</strong> - <?php _e( 'Cloning process is fast and does not slow down website loading', 'wp-staging' ); ?></li>
10
  <li><strong>Secure</strong> - <?php _e( 'WP Staging is coded well for protection of your data', 'wp-staging' ); ?></li>
11
- <li><strong>Multisites</strong> - <?php _e( 'WP Staging Pro allows to clone and push Multisites, (main site & sub sites)', 'wp-staging' ); ?></li>
12
- <a href="http://wp-staging.com/?utm_source=wpstg&utm_medium=addon_page&utm_term=click-wpstaging-pro&utm_campaign=wpstaging" target="_blank" class="wpstg-button green">Buy WP Staging Pro</a>
13
  <a href="<?php echo admin_url(); ?>admin.php?page=wpstg_clone" target="_self" style="margin-left:30px;">Skip - Start Cloning</a>
14
  <div class="wpstg-footer"> <?php _e( 'Comes with our 30-day money back guarantee * You need to give us chance to resolve your issue first.', 'wp-staging' ); ?></div>
15
  </div>
1
  <div class="" id="wpstg-welcome">
2
  <div style="border: 2px solid white;padding: 20px;margin-bottom:20px;">
3
  <h2 class="wpstg-h2">
4
+ <span class="wpstg-heading-pro"><?php _e( 'WP STAGING Pro', 'wp-staging' ); ?></span><?php _e( ' - Copy Themes & Plugins from Staging to Live Site', 'wp-staging' ); ?>
5
  </h2>
6
  <li><strong>Cloning</strong> - <?php _e( 'Create a clone of your website with a simple click', 'wp-staging' ); ?></li>
7
  <li><strong>Push Changes</strong> - <?php _e( 'Copy plugin and theme files from staging to live site', 'wp-staging' ); ?></li>
8
  <li><strong>Authentication</strong> - <?php _e( 'Staging Site is available to authenticated users only', 'wp-staging' ); ?></li>
9
  <li><strong>High Performance</strong> - <?php _e( 'Cloning process is fast and does not slow down website loading', 'wp-staging' ); ?></li>
10
  <li><strong>Secure</strong> - <?php _e( 'WP Staging is coded well for protection of your data', 'wp-staging' ); ?></li>
11
+ <li><strong>Multisites</strong> - <?php _e( 'WP STAGING Pro allows to clone and push Multisites, (main site & sub sites)', 'wp-staging' ); ?></li>
12
+ <a href="http://wp-staging.com/?utm_source=wpstg&utm_medium=addon_page&utm_term=click-wpstaging-pro&utm_campaign=wpstaging" target="_blank" class="wpstg-button green">Buy WP STAGING Pro</a>
13
  <a href="<?php echo admin_url(); ?>admin.php?page=wpstg_clone" target="_self" style="margin-left:30px;">Skip - Start Cloning</a>
14
  <div class="wpstg-footer"> <?php _e( 'Comes with our 30-day money back guarantee * You need to give us chance to resolve your issue first.', 'wp-staging' ); ?></div>
15
  </div>
Core/Utils/Cache.php CHANGED
@@ -71,7 +71,13 @@ class Cache {
71
 
72
  // If cache directory doesn't exists, create it
73
  if( !is_dir( $this->cacheDir ) && !@mkdir( $this->cacheDir, 0775, true ) ) {
74
- throw new \Exception( "Failed to create cache directory " . $this->cacheDir . '! Make sure folder permission is 755 and owner is correct. Should be www-data or similar.' );
 
 
 
 
 
 
75
  }
76
  }
77
 
71
 
72
  // If cache directory doesn't exists, create it
73
  if( !is_dir( $this->cacheDir ) && !@mkdir( $this->cacheDir, 0775, true ) ) {
74
+ /**
75
+ * There's no need to throw this exception, which causes a fatal,
76
+ * as a warning is already displayed on:
77
+ *
78
+ * @see \WPStaging\Backend\Notices\Notices::messages
79
+ */
80
+ //throw new \Exception( "Failed to create cache directory " . $this->cacheDir . '! Make sure folder permission is 755 and owner is correct. Should be www-data or similar.' );
81
  }
82
  }
83
 
Core/Utils/Logger.php CHANGED
@@ -86,7 +86,13 @@ class Logger implements LoggerInterface
86
  // If cache directory doesn't exists, create it
87
  if (!is_dir($this->logDir) && !@mkdir($this->logDir, 0755, true))
88
  {
89
- throw new \Exception("Failed to create log directory!");
 
 
 
 
 
 
90
  }
91
  }
92
 
86
  // If cache directory doesn't exists, create it
87
  if (!is_dir($this->logDir) && !@mkdir($this->logDir, 0755, true))
88
  {
89
+ /**
90
+ * There's no need to throw this exception, which causes a fatal,
91
+ * as a warning is already displayed on:
92
+ *
93
+ * @see \WPStaging\Backend\Notices\Notices::messages
94
+ */
95
+ // throw new \Exception("Failed to create log directory!");
96
  }
97
  }
98
 
Core/Utils/functions.php CHANGED
@@ -126,9 +126,9 @@ function wpstg_replace_first_match($needle, $replace, $haystack)
126
 
127
  /**
128
  * Search & Replace last occurence of string in haystack
129
- * @param type $haystack
130
- * @param type $needle
131
- * @return type
132
  */
133
  function wpstg_replace_last_match($needle, $replace, $haystack)
134
  {
@@ -142,8 +142,8 @@ function wpstg_replace_last_match($needle, $replace, $haystack)
142
 
143
  /**
144
  * Check if string is valid date
145
- * @param type $date
146
- * @param type $format
147
  * @return bool
148
  */
149
  function wpstg_is_valid_date($date, $format = 'Y-m-d')
126
 
127
  /**
128
  * Search & Replace last occurence of string in haystack
129
+ * @param string $haystack
130
+ * @param string $needle
131
+ * @return string
132
  */
133
  function wpstg_replace_last_match($needle, $replace, $haystack)
134
  {
142
 
143
  /**
144
  * Check if string is valid date
145
+ * @param string $date
146
+ * @param string $format
147
  * @return bool
148
  */
149
  function wpstg_is_valid_date($date, $format = 'Y-m-d')
Framework/CloningProcess/Data/UpdateWpConfigConstants.php CHANGED
@@ -20,8 +20,6 @@ class UpdateWpConfigConstants extends FileCloningService
20
  "UPLOADS" => sprintf("'%s'", $this->escapeSingleQuotes($this->dto->getUploadFolder())),
21
  "WP_PLUGIN_DIR" => '__DIR__ . "/wp-content/plugins"',
22
  "WP_LANG_DIR" => '__DIR__ . "/wp-content/languages"',
23
- // Below disabled. It can lead to deleting plugins after login to admin dashboard
24
- //"WP_TEMP_DIR" => '__DIR__ . "/wp-content/temp"',
25
  "WP_HOME" => sprintf("'%s'", $this->escapeSingleQuotes($this->dto->getStagingSiteUrl())),
26
  "WP_SITEURL" => sprintf("'%s'", $this->escapeSingleQuotes($this->dto->getStagingSiteUrl())),
27
  "WP_CACHE" => 'false',
@@ -98,11 +96,15 @@ class UpdateWpConfigConstants extends FileCloningService
98
 
99
  $replace = sprintf("define('%s', %s);", $constant, $newDefinition);
100
 
101
- $content = preg_replace([$pattern], $replace, $content);
 
 
 
102
 
103
  if ($content === null) {
104
  throw new \RuntimeException("Failed to change " . $constant);
105
  }
 
106
  $this->log("Updated: " . $constant);
107
  return $content;
108
  }
@@ -118,14 +120,21 @@ class UpdateWpConfigConstants extends FileCloningService
118
  {
119
  preg_match($this->abspathRegex, $content, $matches);
120
  if (!empty($matches[0])) {
 
121
  $replace = "define('" . $constant . "', " . $newDefinition . "); \n" .
122
  "if ( ! defined( 'ABSPATH' ) )";
123
- if (null === ($content = preg_replace(array($this->abspathRegex), $replace, $content))) {
 
 
 
 
124
  throw new \RuntimeException("Failed to change " . $constant);
125
  }
 
126
  } else {
127
  throw new \RuntimeException("Can not add " . $constant . " constant to wp-config.php. Can not find free position to add it.");
128
  }
 
129
  $this->log("Added:" . $constant);
130
  return $content;
131
  }
20
  "UPLOADS" => sprintf("'%s'", $this->escapeSingleQuotes($this->dto->getUploadFolder())),
21
  "WP_PLUGIN_DIR" => '__DIR__ . "/wp-content/plugins"',
22
  "WP_LANG_DIR" => '__DIR__ . "/wp-content/languages"',
 
 
23
  "WP_HOME" => sprintf("'%s'", $this->escapeSingleQuotes($this->dto->getStagingSiteUrl())),
24
  "WP_SITEURL" => sprintf("'%s'", $this->escapeSingleQuotes($this->dto->getStagingSiteUrl())),
25
  "WP_CACHE" => 'false',
96
 
97
  $replace = sprintf("define('%s', %s);", $constant, $newDefinition);
98
 
99
+ // escaping dollar sign in the value
100
+ $replacementEscapedCharacter = addcslashes($replace, '\\$');
101
+
102
+ $content = preg_replace([$pattern], $replacementEscapedCharacter, $content);
103
 
104
  if ($content === null) {
105
  throw new \RuntimeException("Failed to change " . $constant);
106
  }
107
+
108
  $this->log("Updated: " . $constant);
109
  return $content;
110
  }
120
  {
121
  preg_match($this->abspathRegex, $content, $matches);
122
  if (!empty($matches[0])) {
123
+
124
  $replace = "define('" . $constant . "', " . $newDefinition . "); \n" .
125
  "if ( ! defined( 'ABSPATH' ) )";
126
+
127
+ // escaping dollar sign in the value
128
+ $replaceEscaped = addcslashes($replace, '\\$');
129
+
130
+ if (null === ($content = preg_replace(array($this->abspathRegex), $replaceEscaped, $content))) {
131
  throw new \RuntimeException("Failed to change " . $constant);
132
  }
133
+
134
  } else {
135
  throw new \RuntimeException("Can not add " . $constant . " constant to wp-config.php. Can not find free position to add it.");
136
  }
137
+
138
  $this->log("Added:" . $constant);
139
  return $content;
140
  }
Requirements/WpstgFreeRequirements.php CHANGED
@@ -5,6 +5,12 @@ if (!class_exists('WpstgFreeRequirements')) {
5
 
6
  class WpstgFreeRequirements extends WpstgRequirements
7
  {
 
 
 
 
 
 
8
  public function checkRequirements()
9
  {
10
  $this->proVersionMustNotBeEnabled();
@@ -12,7 +18,7 @@ if (!class_exists('WpstgFreeRequirements')) {
12
  }
13
 
14
  /**
15
- * Prevent conflicts when WPSTAGING Pro is active.
16
  */
17
  private function proVersionMustNotBeEnabled()
18
  {
@@ -21,118 +27,24 @@ if (!class_exists('WpstgFreeRequirements')) {
21
  return;
22
  }
23
 
24
- $proPlugin = plugin_basename(WPSTG_PRO_LOADED);
25
- $freePlugin = plugin_basename($this->pluginFile);
26
 
27
  require_once ABSPATH . 'wp-admin/includes/plugin.php';
28
 
29
- if (!is_multisite()) {
30
- /*
31
- * Pro active
32
- * Free active
33
- *
34
- * Result: Deactivate Free
35
- */
36
- if (is_plugin_active($proPlugin)) {
37
- if (current_user_can('deactivate_plugin', $freePlugin)) {
38
- unset($_GET['activate']);
39
- deactivate_plugins($freePlugin);
40
-
41
- $this->notificationMessage = __('WP STAGING Pro is activated, therefore WP STAGING Basic was automatically disabled.', 'wp-staging');
42
- add_action('admin_notices', [$this, '_displayWarning']);
43
-
44
- throw new RuntimeException(sprintf("WP STAGING Pro is activated, therefore WP STAGING Basic was automatically disabled. Pro version that was active: %s, Basic version that was disabled: %s", $proPlugin, $freePlugin));
45
- } else {
46
- $this->notificationMessage = __('Another instance of WP STAGING was activated, therefore other instances of the WP STAGING plugin were prevented from loading. Please ask the site administrator to leave only one instance of WP STAGING active.', 'wp-staging');
47
- add_action('admin_notices', [$this, '_displayWarning']);
48
-
49
- throw new RuntimeException(sprintf('Another instance of WP STAGING was activated, therefore other instances of the WP STAGING plugin were prevented from loading. Plugin that was loaded: %s, Plugin that was prevented from loading: %s', $freePlugin, $proPlugin));
50
- }
51
- }
52
- } else {
53
- if (!is_network_admin()) {
54
- /*
55
- * Pro active site-level
56
- * Free active site-level
57
- * Free deactivated network-level
58
- *
59
- * Result: Deactivate Free site-level
60
- */
61
- if (
62
- is_plugin_active($proPlugin) &&
63
- is_plugin_active($freePlugin) &&
64
- !is_plugin_active_for_network($freePlugin)
65
- ) {
66
- if (current_user_can('deactivate_plugin', $freePlugin)) {
67
- unset($_GET['activate']);
68
- deactivate_plugins($freePlugin);
69
-
70
- $this->notificationMessage = __('WP STAGING Pro is activated, therefore WP STAGING Basic was automatically disabled.', 'wp-staging');
71
- add_action('admin_notices', [$this, '_displayWarning']);
72
-
73
- throw new RuntimeException(sprintf("WP STAGING Pro is activated, therefore WP STAGING Basic was automatically disabled. Pro version that was active: %s, Basic version that was disabled: %s", $proPlugin, $freePlugin));
74
- } else {
75
- $this->notificationMessage = __('Another instance of WP STAGING was activated, therefore other instances of the WP STAGING plugin were prevented from loading. Please ask the site administrator to leave only one instance of WP STAGING active.', 'wp-staging');
76
- add_action('admin_notices', [$this, '_displayWarning']);
77
-
78
- throw new RuntimeException(sprintf('Another instance of WP STAGING was activated, therefore other instances of the WP STAGING plugin were prevented from loading. Plugin that was loaded: %s, Plugin that was prevented from loading: %s', $freePlugin, $proPlugin));
79
- }
80
- }
81
-
82
- /*
83
- * Pro active site-level
84
- * Free active network-level
85
- *
86
- * Result: Deactivate Pro site-level
87
- */
88
- if (
89
- is_plugin_active($proPlugin) &&
90
- is_plugin_active_for_network($freePlugin)
91
- ) {
92
- if (current_user_can('deactivate_plugin', $proPlugin)) {
93
- unset($_GET['activate']);
94
- deactivate_plugins($proPlugin);
95
-
96
- $this->notificationMessage = __('WP STAGING Basic is activated network-wide, therefore WP STAGING Pro was automatically disabled. Please disable WP STAGING Basic network-wide to enable WP STAGING Pro.', 'wp-staging');
97
- add_action('admin_notices', [$this, '_displayWarning']);
98
-
99
- throw new RuntimeException(sprintf("WP STAGING Basic is activated networkwide, therefore WP STAGING Pro was automatically disabled. Basic version that was activate networkwide: %s, Pro version that was disabled: %s", $freePlugin, $proPlugin));
100
- } else {
101
- $this->notificationMessage = __('Another instance of WP STAGING was activated, therefore other instances of the WP STAGING plugin were prevented from loading. Please ask the site administrator to leave only one instance of WP STAGING active.', 'wp-staging');
102
- add_action('admin_notices', [$this, '_displayWarning']);
103
-
104
- throw new RuntimeException(sprintf('Another instance of WP STAGING was activated, therefore other instances of the WP STAGING plugin were prevented from loading. Plugin that was loaded: %s, Plugin that was prevented from loading: %s', $freePlugin, $proPlugin));
105
- }
106
- }
107
  } else {
108
- /*
109
- * Pro active network-level
110
- * Free active network-level
111
- *
112
- * Result: Deactivate Free network-level
113
- */
114
- if (is_plugin_active_for_network($proPlugin)) {
115
- if (current_user_can('manage_network_plugins')) {
116
- unset($_GET['activate']);
117
- deactivate_plugins($freePlugin, null, true);
118
-
119
- $this->notificationMessage = __('WP STAGING Pro is activated network-wide, therefore WP STAGING Basic was disabled network-wide.', 'wp-staging');
120
- add_action('network_admin_notices', [$this, '_displayWarning']);
121
-
122
- throw new RuntimeException(sprintf("WP STAGING Pro is activated networkwide, therefore WP STAGING Basic networkwide was automatically disabled. Pro version that was activate networkwide: %s, Basic version that was disabled networkwide: %s", $proPlugin, $freePlugin));
123
- } else {
124
- $this->notificationMessage = __('Another instance of WP STAGING was activated, therefore other instances of the WP STAGING plugin were prevented from loading. Please ask the site administrator to leave only one instance of WP STAGING active.', 'wp-staging');
125
- add_action('admin_notices', [$this, '_displayWarning']);
126
-
127
- throw new RuntimeException(sprintf('Another instance of WP STAGING was activated, therefore other instances of the WP STAGING plugin were prevented from loading. Plugin that was loaded: %s, Plugin that was prevented from loading: %s', $freePlugin, $proPlugin));
128
- }
129
- }
130
  }
 
 
131
  }
132
  }
133
 
134
  /**
135
- * Catch-all to prevent conflicts when another instance of WPSTAGING is active.
136
  */
137
  private function anotherInstanceOfWpstagingMustNotBeEnabled()
138
  {
@@ -155,5 +67,114 @@ if (!class_exists('WpstgFreeRequirements')) {
155
  throw new RuntimeException(sprintf("Another instance of WP STAGING is activated, therefore other instances of WP STAGING were automatically prevented from running to avoid errors. Please leave only one instance of the WP STAGING plugin active. Plugin that was prevented from loading: %s", $this->pluginFile));
156
  }
157
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158
  }
159
  }
5
 
6
  class WpstgFreeRequirements extends WpstgRequirements
7
  {
8
+ /** @var string */
9
+ private $proPlugin;
10
+
11
+ /** @var string */
12
+ private $freePlugin;
13
+
14
  public function checkRequirements()
15
  {
16
  $this->proVersionMustNotBeEnabled();
18
  }
19
 
20
  /**
21
+ * Prevent conflicts when WP STAGING Pro is active.
22
  */
23
  private function proVersionMustNotBeEnabled()
24
  {
27
  return;
28
  }
29
 
30
+ $this->proPlugin = plugin_basename(WPSTG_PRO_LOADED);
31
+ $this->freePlugin = plugin_basename($this->pluginFile);
32
 
33
  require_once ABSPATH . 'wp-admin/includes/plugin.php';
34
 
35
+ if (is_multisite()) {
36
+ if (is_network_admin()) {
37
+ $this->deactivateFreePluginOnMultisiteNetworkLevel();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  } else {
39
+ $this->deactivateFreeOrProPluginOnMultisite();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  }
41
+ } else {
42
+ $this->deactivateFreePluginIfProIsActiveOnSingleSite();
43
  }
44
  }
45
 
46
  /**
47
+ * Catch-all to prevent conflicts when another instance of WP STAGING is active.
48
  */
49
  private function anotherInstanceOfWpstagingMustNotBeEnabled()
50
  {
67
  throw new RuntimeException(sprintf("Another instance of WP STAGING is activated, therefore other instances of WP STAGING were automatically prevented from running to avoid errors. Please leave only one instance of the WP STAGING plugin active. Plugin that was prevented from loading: %s", $this->pluginFile));
68
  }
69
  }
70
+
71
+ /**
72
+ * Pro active
73
+ * Free active
74
+ *
75
+ * Result: Deactivate Free
76
+ */
77
+ private function deactivateFreePluginIfProIsActiveOnSingleSite()
78
+ {
79
+ if (is_plugin_active($this->proPlugin)) {
80
+ if (current_user_can('deactivate_plugin', $this->freePlugin)) {
81
+ unset($_GET['activate']);
82
+ deactivate_plugins($this->freePlugin);
83
+
84
+ $this->notificationMessage = __('WP STAGING Pro is activated, therefore WP STAGING Basic was automatically disabled.', 'wp-staging');
85
+ add_action('admin_notices', [$this, '_displayWarning']);
86
+
87
+ throw new RuntimeException(sprintf("WP STAGING Pro is activated, therefore WP STAGING Basic was automatically disabled. Pro version that was active: %s, Basic version that was disabled: %s", $this->proPlugin, $this->freePlugin));
88
+ }
89
+
90
+ $this->notificationMessage = __('Another instance of WP STAGING was activated, therefore other instances of the WP STAGING plugin were prevented from loading. Please ask the site administrator to leave only one instance of WP STAGING active.', 'wp-staging');
91
+ add_action('admin_notices', [$this, '_displayWarning']);
92
+
93
+ throw new RuntimeException(sprintf('Another instance of WP STAGING was activated, therefore other instances of the WP STAGING plugin were prevented from loading. Plugin that was loaded: %s, Plugin that was prevented from loading: %s', $this->freePlugin, $this->proPlugin));
94
+ }
95
+ }
96
+
97
+ private function deactivateFreeOrProPluginOnMultisite()
98
+ {
99
+ /*
100
+ * Pro active site-level
101
+ * Free active site-level
102
+ * Free deactivated network-level
103
+ *
104
+ * Result: Deactivate Free site-level
105
+ */
106
+ if (
107
+ is_plugin_active($this->proPlugin) &&
108
+ is_plugin_active($this->freePlugin) &&
109
+ !is_plugin_active_for_network($this->freePlugin)
110
+ ) {
111
+ if (current_user_can('deactivate_plugin', $this->freePlugin)) {
112
+ unset($_GET['activate']);
113
+ deactivate_plugins($this->freePlugin);
114
+
115
+ $this->notificationMessage = __('WP STAGING Pro is activated, therefore WP STAGING Basic was automatically disabled.', 'wp-staging');
116
+ add_action('admin_notices', [$this, '_displayWarning']);
117
+
118
+ throw new RuntimeException(sprintf("WP STAGING Pro is activated, therefore WP STAGING Basic was automatically disabled. Pro version that was active: %s, Basic version that was disabled: %s", $this->proPlugin, $this->freePlugin));
119
+ }
120
+
121
+ $this->notificationMessage = __('Another instance of WP STAGING was activated, therefore other instances of the WP STAGING plugin were prevented from loading. Please ask the site administrator to leave only one instance of WP STAGING active.', 'wp-staging');
122
+ add_action('admin_notices', [$this, '_displayWarning']);
123
+
124
+ throw new RuntimeException(sprintf('Another instance of WP STAGING was activated, therefore other instances of the WP STAGING plugin were prevented from loading. Plugin that was loaded: %s, Plugin that was prevented from loading: %s', $this->freePlugin, $this->proPlugin));
125
+ }
126
+
127
+ /*
128
+ * Pro active site-level
129
+ * Free active network-level
130
+ *
131
+ * Result: Deactivate Pro site-level
132
+ */
133
+ if (
134
+ is_plugin_active($this->proPlugin) &&
135
+ is_plugin_active_for_network($this->freePlugin)
136
+ ) {
137
+ if (current_user_can('deactivate_plugin', $this->proPlugin)) {
138
+ unset($_GET['activate']);
139
+ deactivate_plugins($this->proPlugin);
140
+
141
+ $this->notificationMessage = __('WP STAGING Basic is activated network-wide, therefore WP STAGING Pro was automatically disabled. Please disable WP STAGING Basic network-wide to enable WP STAGING Pro.', 'wp-staging');
142
+ add_action('admin_notices', [$this, '_displayWarning']);
143
+
144
+ throw new RuntimeException(sprintf("WP STAGING Basic is activated networkwide, therefore WP STAGING Pro was automatically disabled. Basic version that was activate networkwide: %s, Pro version that was disabled: %s", $this->freePlugin, $this->proPlugin));
145
+ }
146
+
147
+ $this->notificationMessage = __('Another instance of WP STAGING was activated, therefore other instances of the WP STAGING plugin were prevented from loading. Please ask the site administrator to leave only one instance of WP STAGING active.', 'wp-staging');
148
+ add_action('admin_notices', [$this, '_displayWarning']);
149
+
150
+ throw new RuntimeException(sprintf('Another instance of WP STAGING was activated, therefore other instances of the WP STAGING plugin were prevented from loading. Plugin that was loaded: %s, Plugin that was prevented from loading: %s', $this->freePlugin, $this->proPlugin));
151
+ }
152
+ }
153
+
154
+ /*
155
+ * Pro active network-level
156
+ * Free active network-level
157
+ *
158
+ * Result: Deactivate Free network-level
159
+ */
160
+ private function deactivateFreePluginOnMultisiteNetworkLevel()
161
+ {
162
+ if (is_plugin_active_for_network($this->proPlugin)) {
163
+ if (current_user_can('manage_network_plugins')) {
164
+ unset($_GET['activate']);
165
+ deactivate_plugins($this->freePlugin, null, true);
166
+
167
+ $this->notificationMessage = __('WP STAGING Pro is activated network-wide, therefore WP STAGING Basic was disabled network-wide.', 'wp-staging');
168
+ add_action('network_admin_notices', [$this, '_displayWarning']);
169
+
170
+ throw new RuntimeException(sprintf("WP STAGING Pro is activated networkwide, therefore WP STAGING Basic networkwide was automatically disabled. Pro version that was activate networkwide: %s, Basic version that was disabled networkwide: %s", $this->proPlugin, $this->freePlugin));
171
+ }
172
+
173
+ $this->notificationMessage = __('Another instance of WP STAGING was activated, therefore other instances of the WP STAGING plugin were prevented from loading. Please ask the site administrator to leave only one instance of WP STAGING active.', 'wp-staging');
174
+ add_action('admin_notices', [$this, '_displayWarning']);
175
+
176
+ throw new RuntimeException(sprintf('Another instance of WP STAGING was activated, therefore other instances of the WP STAGING plugin were prevented from loading. Plugin that was loaded: %s, Plugin that was prevented from loading: %s', $this->freePlugin, $this->proPlugin));
177
+ }
178
+ }
179
  }
180
  }
_init.php CHANGED
@@ -2,40 +2,6 @@
2
 
3
  use WPStaging\WPStaging;
4
 
5
- // Compatible maximum WordPress Version
6
- if (!defined('WPSTG_COMPATIBLE')) {
7
- define('WPSTG_COMPATIBLE', '5.5.1');
8
- }
9
-
10
- // Compatible minimum WordPress version
11
- if (!defined('WPSTG_MIN_WP_VERSION')) {
12
- define('WPSTG_MIN_WP_VERSION', '4.0');
13
- }
14
-
15
- // Compatible up to PHP Version
16
- if (!defined('WPSTG_PHP_COMPATIBLE')) {
17
- define('WPSTG_PHP_COMPATIBLE', '5.5');
18
- }
19
-
20
- // Expected version number of the must-use plugin 'optimizer'. Used for automatic updates of the mu-plugin
21
- if (!defined('WPSTG_OPTIMIZER_MUVERSION')) {
22
- define('WPSTG_OPTIMIZER_MUVERSION', 1.3);
23
- }
24
-
25
- // URL of the base folder
26
- if (!defined('WPSTG_PLUGIN_URL')) {
27
- define('WPSTG_PLUGIN_URL', plugin_dir_url(WPSTG_PLUGIN_FILE));
28
- }
29
-
30
- /**
31
- * Load Basic/Pro related constants and due to that the rest of the basic or pro version
32
- */
33
- if (file_exists(plugin_dir_path(__FILE__) . 'Pro/constants.php')) {
34
- require_once plugin_dir_path(__FILE__) . 'Pro/constants.php';
35
- } else {
36
- require_once plugin_dir_path(__FILE__) . 'constants.php';
37
- }
38
-
39
  /**
40
  * Do not show update notifications for WP STAGING Pro on the staging site
41
  * @param object
@@ -69,8 +35,8 @@ if (!class_exists('Wpstg_Requirements_Check')) {
69
 
70
  $pluginRequirements = new Wpstg_Requirements_Check(array(
71
  'title' => 'WP STAGING',
72
- 'php' => WPSTG_PHP_COMPATIBLE,
73
- 'wp' => WPSTG_MIN_WP_VERSION,
74
  'file' => __FILE__,
75
  ));
76
 
@@ -81,11 +47,15 @@ if ($pluginRequirements->passes()) {
81
  // Load composer autoloader
82
  require_once __DIR__ . '/vendor/autoload.php';
83
 
 
 
84
  $wpStaging = WPStaging::getInstance();
85
 
86
- /**
87
- * Load important WP globals into WPStaging class to make them available via dependancy injection
 
88
  */
 
89
 
90
  // Wordpress DB Object
91
  global $wpdb;
@@ -93,11 +63,4 @@ if ($pluginRequirements->passes()) {
93
  if ($wpdb instanceof \wpdb) {
94
  $wpStaging->set("wpdb", $wpdb);
95
  }
96
-
97
- /**
98
- * Installation Hooks
99
- */
100
- if (!class_exists('WPStaging\Install')) {
101
- require_once WPSTG_PLUGIN_DIR . "install.php";
102
- }
103
  }
2
 
3
  use WPStaging\WPStaging;
4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  /**
6
  * Do not show update notifications for WP STAGING Pro on the staging site
7
  * @param object
35
 
36
  $pluginRequirements = new Wpstg_Requirements_Check(array(
37
  'title' => 'WP STAGING',
38
+ 'php' => '5.5',
39
+ 'wp' => '4.0',
40
  'file' => __FILE__,
41
  ));
42
 
47
  // Load composer autoloader
48
  require_once __DIR__ . '/vendor/autoload.php';
49
 
50
+ require_once __DIR__ . '/constants.php';
51
+
52
  $wpStaging = WPStaging::getInstance();
53
 
54
+ /*
55
+ * Set the WPSTG_COMPATIBLE constant in the container,
56
+ * so that we can change it for testing purposes.
57
  */
58
+ $wpStaging->set('WPSTG_COMPATIBLE', WPSTG_COMPATIBLE);
59
 
60
  // Wordpress DB Object
61
  global $wpdb;
63
  if ($wpdb instanceof \wpdb) {
64
  $wpStaging->set("wpdb", $wpdb);
65
  }
 
 
 
 
 
 
 
66
  }
constants.php CHANGED
@@ -1,18 +1,42 @@
1
  <?php
2
 
 
 
 
 
3
 
4
- namespace WPStaging;
5
-
6
- // WP STAGING version number
7
- if (!defined('WPSTG_VERSION')) {
8
- define('WPSTG_VERSION', '2.7.7');
9
  }
10
 
11
- // Compatible up to WordPress Version
12
- if (!defined('WPSTG_COMPATIBLE')) {
13
- define('WPSTG_COMPATIBLE', '5.5.1');
14
  }
15
 
16
- if (!defined('WPSTG_PLUGIN_SLUG')) {
17
- define('WPSTG_PLUGIN_SLUG', 'wp-staging');
18
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <?php
2
 
3
+ // Absolute path to plugin dir /var/www/.../plugins/wp-staging(-pro)
4
+ if (!defined('WPSTG_PLUGIN_DIR')) {
5
+ define('WPSTG_PLUGIN_DIR', plugin_dir_path(WPSTG_PLUGIN_FILE));
6
+ }
7
 
8
+ // URL of the base folder
9
+ if (!defined('WPSTG_PLUGIN_URL')) {
10
+ define('WPSTG_PLUGIN_URL', plugin_dir_url(WPSTG_PLUGIN_FILE));
 
 
11
  }
12
 
13
+ // Expected version number of the must-use plugin 'optimizer'. Used for automatic updates of the mu-plugin
14
+ if (!defined('WPSTG_OPTIMIZER_MUVERSION')) {
15
+ define('WPSTG_OPTIMIZER_MUVERSION', 1.3);
16
  }
17
 
18
+ if (file_exists(__DIR__ . '/wp-staging-pro.php')) {
19
+ /** WPSTAGING Pro Constants */
20
+
21
+ // WP STAGING version number
22
+ if (!defined('WPSTGPRO_VERSION')) {
23
+ define('WPSTGPRO_VERSION', '3.1.3');
24
+ }
25
+
26
+ // Compatible up to WordPress Version
27
+ if (!defined('WPSTG_COMPATIBLE')) {
28
+ define('WPSTG_COMPATIBLE', '5.5.3');
29
+ }
30
+ } else {
31
+ /** WPSTAGING Free Constants */
32
+
33
+ // WP STAGING version number
34
+ if (!defined('WPSTG_VERSION')) {
35
+ define('WPSTG_VERSION', '2.7.8');
36
+ }
37
+
38
+ // Compatible up to WordPress Version
39
+ if (!defined('WPSTG_COMPATIBLE')) {
40
+ define('WPSTG_COMPATIBLE', '5.5.2');
41
+ }
42
+ }
install.php CHANGED
@@ -7,35 +7,31 @@ use WPStaging\Utils\IISWebConfig;
7
  use WPStaging\Utils\Htaccess;
8
  use WPStaging\Utils\Filesystem;
9
 
10
- // Exit if accessed directly
11
- if (!defined('ABSPATH'))
12
- exit;
13
-
14
- // TODO; remove previous auto-loader, use composer based instead!
15
- require_once __DIR__ . '/vendor/autoload.php';
16
-
17
  /**
18
  * Install Class
19
  *
20
  */
21
  class Install
22
  {
 
23
 
24
- public function __construct()
25
  {
26
- $file = __DIR__ . DIRECTORY_SEPARATOR . WPSTG_PLUGIN_SLUG . '.php';
27
- register_activation_hook($file, array($this, 'activation'));
28
  }
29
 
30
- public static function activation()
31
  {
32
- $install = new Install();
33
-
34
- $install->initCron();
35
- $install->installOptimizer();
36
- $install->createHtaccess();
37
- $install->createIndex();
38
- $install->createWebConfig();
 
 
 
39
  }
40
 
41
  private function initCron()
@@ -83,5 +79,3 @@ class Install
83
  $webconfig->create(trailingslashit(\WPStaging\WPStaging::getContentDir()) . 'logs/web.config');
84
  }
85
  }
86
-
87
- new Install();
7
  use WPStaging\Utils\Htaccess;
8
  use WPStaging\Utils\Filesystem;
9
 
 
 
 
 
 
 
 
10
  /**
11
  * Install Class
12
  *
13
  */
14
  class Install
15
  {
16
+ private $bootstrap;
17
 
18
+ public function __construct(\WpstgBootstrapInterface $bootstrap)
19
  {
20
+ $this->bootstrap = $bootstrap;
 
21
  }
22
 
23
+ public function activation()
24
  {
25
+ $this->bootstrap->checkRequirements();
26
+ $this->bootstrap->bootstrap();
27
+
28
+ if ($this->bootstrap->passedRequirements()) {
29
+ $this->initCron();
30
+ $this->installOptimizer();
31
+ $this->createHtaccess();
32
+ $this->createIndex();
33
+ $this->createWebConfig();
34
+ }
35
  }
36
 
37
  private function initCron()
79
  $webconfig->create(trailingslashit(\WPStaging\WPStaging::getContentDir()) . 'logs/web.config');
80
  }
81
  }
 
 
readme.txt CHANGED
@@ -9,7 +9,7 @@ License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
  Tags: backup, staging, duplication, clone, migration
10
  Requires at least: 3.6+
11
  Tested up to: 5.5
12
- Stable tag: 2.7.7
13
  Requires PHP: 5.5
14
 
15
  A duplicator plugin - clone/move, duplicate & migrate websites to staging, backup and development sites that only authorized users can access.
@@ -157,8 +157,20 @@ https://wp-staging.com
157
 
158
  == Changelog ==
159
 
 
 
 
 
 
 
 
 
 
 
 
 
160
  = 2.7.7 =
161
- * Fix: Fatal error on activation if PHP version < 7.x version on some circumstances
162
 
163
  = 2.7.6 =
164
  * New: Compatible up to WordPress 5.5.1
@@ -176,7 +188,6 @@ https://wp-staging.com
176
  * Fix: Wrong german translations
177
  * Fix: Cloning fails if there is no underscore in table prefix
178
 
179
-
180
  = 2.7.5 =
181
  * New: Compatible up to WordPress 5.4.2
182
  * Fix: Remove beta notice
@@ -252,7 +263,6 @@ SKIP VERSION
252
  * Fix: use an alternative method for file_put_contents as it is not supported on all systems due to file permission issues
253
  * Fix: Redundant and duplicated update comments in wp-config.php in staging site
254
 
255
-
256
  = 2.6.2 =
257
  * Fix: Do not show warning "Preparing Data Step3: Failed to update rewrite_rules in wpstg0_options"
258
  * Fix: Change error "Table wpstgtmp_options does not exist" to warning
@@ -260,7 +270,6 @@ SKIP VERSION
260
  * New: Setup server environment variables per process and not globally (e.g. set_time_limit)
261
  * New: Add support for custom uploads folder if user customized UPLOADS constant or upload_path in DB
262
 
263
-
264
  = 2.6.1 =
265
  * New: Improve styling of login form. Thanks to Andy Kennan (Screaming Frog)
266
  * New: Add 'password lost' button to login form
@@ -269,8 +278,6 @@ SKIP VERSION
269
  * Fix: PDO instances can not be serialized or unserialized
270
  * Fix: Can not update staging site db table if there are constraints in it
271
 
272
-
273
-
274
  = 2.6.0 =
275
  * New: Compatible up to WordPress 5.2.2
276
  * New: Performance improvement for directory iterator using less server ressources
@@ -278,34 +285,17 @@ SKIP VERSION
278
  * Fix: Error conditions in class Data does not compare type strict (== vs. ==) resulting in interruption of clone process
279
  * Fix: Excluded folders under wp-content level are not take into account on microsoft IIS servers
280
 
281
- = 2.5.9 =
282
- * New: Update for WP 5.2.1
283
- * New: Better corporate identity and more friendly UI colors for staging sites listings and button
284
- * New: Better warning notices before updating process is executed
285
- * New: Add tooltips for explaining navigation buttons
286
- * New: Check if UPLOAD constant is defined and use this value for uploads folder destination
287
- * New: Show notice if user tries to clone a staging website.
288
- * Fix: Staging sites listing entries appeared on the cloned website.
289
- * Fix: Do not search & replace through "__PHP_Incomplete_Class_Name" definitions
290
- * Fix: Prevent wordfence firewall rule interrupting the clone deletion method
291
- * Fix: Excluded wp staging directory from deleting process is ignored and will be deleted either way
292
- * Fix: Strip whitespaces in cloning site internal names
293
-
294
- Complete changelog: [https://wp-staging.com/wp-staging-changelog](https://wp-staging.com/wp-staging-changelog)
295
 
296
  == Upgrade Notice ==
297
- * New: Compatible up to WordPress 5.5.1
298
- * New: Add WP_ENVIRONMENT_TYPE constant for staging site
299
- * New: Better and wider test coverage
300
- * New: Implementing of automated CI tests
301
- * New: Huge code base refactor for cleaner code
302
- * New: Updated authentication mechanism for ajax requests
303
- * New: Show welcome video message
304
- * New: Show message asking for admin credentials on login form
305
- * New: Move WP STAGING menu down below the menu Plugins
306
- * New: Selected tables are highlighted with a blue background color
307
- * Fix: Show access denied message if a non but existing user tries to access the staging site
308
- * Fix: Remove wp_logout() in staging site login form to prevent multiple login log entries with plugin WP Activity Log
309
- * Fix: Wrong german translations
310
- * Fix: Cloning fails if there is no underscore in table prefix
311
 
9
  Tags: backup, staging, duplication, clone, migration
10
  Requires at least: 3.6+
11
  Tested up to: 5.5
12
+ Stable tag: 2.7.8
13
  Requires PHP: 5.5
14
 
15
  A duplicator plugin - clone/move, duplicate & migrate websites to staging, backup and development sites that only authorized users can access.
157
 
158
  == Changelog ==
159
 
160
+ = 2.7.8 =
161
+ * New: Add special admin notice if plugin is not tested with latest WordPress version
162
+ * New: Compatible up to WordPress 5.5.2
163
+ * New: Allow deleting of orphaned staging site entries if staging site was deleted manually before
164
+
165
+ * Fix: Activation hook is not fired after first time installation and wpstg optimizer and cron tasks are not set up
166
+ * Fix: Staging site does not work if database password contains dollar sign in password
167
+ * Fix: Prevent fatal error when the plugin is activated, but there is no permission to create folder wp-content/uploads/wp-staging or wp-content/uploads/wp-staging/logs.
168
+
169
+ * Dev: Add new DI container implementation
170
+ * Dev: Add composer 2
171
+
172
  = 2.7.7 =
173
+ * Fix: Fatal error on activation in pro version (Syntax error)
174
 
175
  = 2.7.6 =
176
  * New: Compatible up to WordPress 5.5.1
188
  * Fix: Wrong german translations
189
  * Fix: Cloning fails if there is no underscore in table prefix
190
 
 
191
  = 2.7.5 =
192
  * New: Compatible up to WordPress 5.4.2
193
  * Fix: Remove beta notice
263
  * Fix: use an alternative method for file_put_contents as it is not supported on all systems due to file permission issues
264
  * Fix: Redundant and duplicated update comments in wp-config.php in staging site
265
 
 
266
  = 2.6.2 =
267
  * Fix: Do not show warning "Preparing Data Step3: Failed to update rewrite_rules in wpstg0_options"
268
  * Fix: Change error "Table wpstgtmp_options does not exist" to warning
270
  * New: Setup server environment variables per process and not globally (e.g. set_time_limit)
271
  * New: Add support for custom uploads folder if user customized UPLOADS constant or upload_path in DB
272
 
 
273
  = 2.6.1 =
274
  * New: Improve styling of login form. Thanks to Andy Kennan (Screaming Frog)
275
  * New: Add 'password lost' button to login form
278
  * Fix: PDO instances can not be serialized or unserialized
279
  * Fix: Can not update staging site db table if there are constraints in it
280
 
 
 
281
  = 2.6.0 =
282
  * New: Compatible up to WordPress 5.2.2
283
  * New: Performance improvement for directory iterator using less server ressources
285
  * Fix: Error conditions in class Data does not compare type strict (== vs. ==) resulting in interruption of clone process
286
  * Fix: Excluded folders under wp-content level are not take into account on microsoft IIS servers
287
 
288
+ Full changelog: [https://wp-staging.com/wp-staging-changelog](https://wp-staging.com/wp-staging-changelog)
 
 
 
 
 
 
 
 
 
 
 
 
 
289
 
290
  == Upgrade Notice ==
291
+ * New: Add special admin notice if plugin is not tested with latest WordPress version
292
+ * New: Compatible up to WordPress 5.5.2
293
+ * New: Allow deleting of orphaned staging site entries if staging site was deleted manually before
294
+
295
+ * Fix: Activation hook is not fired after first time installation and wpstg optimizer and cron tasks are not set up
296
+ * Fix: Staging site does not work if database password contains dollar sign in password
297
+ * Fix: Prevent fatal error when the plugin is activated, but there is no permission to create folder wp-content/uploads/wp-staging or wp-content/uploads/wp-staging/logs.
298
+
299
+ * Dev: Add new DI container implementation
300
+ * Dev: Add composer 2
 
 
 
 
301
 
vendor/composer/autoload_classmap.php CHANGED
@@ -282,4 +282,11 @@ return array(
282
  'WPStaging\\Utils\\Strings' => $baseDir . '/Core/Utils/Strings.php',
283
  'WPStaging\\WPStaging' => $baseDir . '/Core/WPStaging.php',
284
  'WPStaging\\thirdParty\\thirdPartyCompatibility' => $baseDir . '/Core/thirdParty/thirdPartyCompatibility.php',
 
 
 
 
 
 
 
285
  );
282
  'WPStaging\\Utils\\Strings' => $baseDir . '/Core/Utils/Strings.php',
283
  'WPStaging\\WPStaging' => $baseDir . '/Core/WPStaging.php',
284
  'WPStaging\\thirdParty\\thirdPartyCompatibility' => $baseDir . '/Core/thirdParty/thirdPartyCompatibility.php',
285
+ 'tad_DI52_Container' => $vendorDir . '/lucatume/di52/src/tad/DI52/Container.php',
286
+ 'tad_DI52_ContainerInterface' => $vendorDir . '/lucatume/di52/src/tad/DI52/ContainerInterface.php',
287
+ 'tad_DI52_ProtectedValue' => $vendorDir . '/lucatume/di52/src/tad/DI52/ProtectedValue.php',
288
+ 'tad_DI52_ServiceProvider' => $vendorDir . '/lucatume/di52/src/tad/DI52/ServiceProvider.php',
289
+ 'tad_DI52_ServiceProviderInterface' => $vendorDir . '/lucatume/di52/src/tad/DI52/ServiceProviderInterface.php',
290
+ 'xrstf\\Composer52\\AutoloadGenerator' => $vendorDir . '/xrstf/composer-php52/lib/xrstf/Composer52/AutoloadGenerator.php',
291
+ 'xrstf\\Composer52\\Generator' => $vendorDir . '/xrstf/composer-php52/lib/xrstf/Composer52/Generator.php',
292
  );
vendor/composer/autoload_namespaces.php CHANGED
@@ -6,4 +6,6 @@ $vendorDir = dirname(dirname(__FILE__));
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
 
 
9
  );
6
  $baseDir = dirname($vendorDir);
7
 
8
  return array(
9
+ 'xrstf\\Composer52' => array($vendorDir . '/xrstf/composer-php52/lib'),
10
+ 'tad_DI52_' => array($vendorDir . '/lucatume/di52/src'),
11
  );
vendor/composer/autoload_static.php CHANGED
@@ -50,6 +50,23 @@ class ComposerStaticInitwpstgfree
50
  ),
51
  );
52
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  public static $classMap = array (
54
  'Psr\\Log\\AbstractLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/AbstractLogger.php',
55
  'Psr\\Log\\InvalidArgumentException' => __DIR__ . '/..' . '/psr/log/Psr/Log/InvalidArgumentException.php',
@@ -327,6 +344,13 @@ class ComposerStaticInitwpstgfree
327
  'WPStaging\\Utils\\Strings' => __DIR__ . '/../..' . '/Core/Utils/Strings.php',
328
  'WPStaging\\WPStaging' => __DIR__ . '/../..' . '/Core/WPStaging.php',
329
  'WPStaging\\thirdParty\\thirdPartyCompatibility' => __DIR__ . '/../..' . '/Core/thirdParty/thirdPartyCompatibility.php',
 
 
 
 
 
 
 
330
  );
331
 
332
  public static function getInitializer(ClassLoader $loader)
@@ -334,6 +358,7 @@ class ComposerStaticInitwpstgfree
334
  return \Closure::bind(function () use ($loader) {
335
  $loader->prefixLengthsPsr4 = ComposerStaticInitwpstgfree::$prefixLengthsPsr4;
336
  $loader->prefixDirsPsr4 = ComposerStaticInitwpstgfree::$prefixDirsPsr4;
 
337
  $loader->classMap = ComposerStaticInitwpstgfree::$classMap;
338
 
339
  }, null, ClassLoader::class);
50
  ),
51
  );
52
 
53
+ public static $prefixesPsr0 = array (
54
+ 'x' =>
55
+ array (
56
+ 'xrstf\\Composer52' =>
57
+ array (
58
+ 0 => __DIR__ . '/..' . '/xrstf/composer-php52/lib',
59
+ ),
60
+ ),
61
+ 't' =>
62
+ array (
63
+ 'tad_DI52_' =>
64
+ array (
65
+ 0 => __DIR__ . '/..' . '/lucatume/di52/src',
66
+ ),
67
+ ),
68
+ );
69
+
70
  public static $classMap = array (
71
  'Psr\\Log\\AbstractLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/AbstractLogger.php',
72
  'Psr\\Log\\InvalidArgumentException' => __DIR__ . '/..' . '/psr/log/Psr/Log/InvalidArgumentException.php',
344
  'WPStaging\\Utils\\Strings' => __DIR__ . '/../..' . '/Core/Utils/Strings.php',
345
  'WPStaging\\WPStaging' => __DIR__ . '/../..' . '/Core/WPStaging.php',
346
  'WPStaging\\thirdParty\\thirdPartyCompatibility' => __DIR__ . '/../..' . '/Core/thirdParty/thirdPartyCompatibility.php',
347
+ 'tad_DI52_Container' => __DIR__ . '/..' . '/lucatume/di52/src/tad/DI52/Container.php',
348
+ 'tad_DI52_ContainerInterface' => __DIR__ . '/..' . '/lucatume/di52/src/tad/DI52/ContainerInterface.php',
349
+ 'tad_DI52_ProtectedValue' => __DIR__ . '/..' . '/lucatume/di52/src/tad/DI52/ProtectedValue.php',
350
+ 'tad_DI52_ServiceProvider' => __DIR__ . '/..' . '/lucatume/di52/src/tad/DI52/ServiceProvider.php',
351
+ 'tad_DI52_ServiceProviderInterface' => __DIR__ . '/..' . '/lucatume/di52/src/tad/DI52/ServiceProviderInterface.php',
352
+ 'xrstf\\Composer52\\AutoloadGenerator' => __DIR__ . '/..' . '/xrstf/composer-php52/lib/xrstf/Composer52/AutoloadGenerator.php',
353
+ 'xrstf\\Composer52\\Generator' => __DIR__ . '/..' . '/xrstf/composer-php52/lib/xrstf/Composer52/Generator.php',
354
  );
355
 
356
  public static function getInitializer(ClassLoader $loader)
358
  return \Closure::bind(function () use ($loader) {
359
  $loader->prefixLengthsPsr4 = ComposerStaticInitwpstgfree::$prefixLengthsPsr4;
360
  $loader->prefixDirsPsr4 = ComposerStaticInitwpstgfree::$prefixDirsPsr4;
361
+ $loader->prefixesPsr0 = ComposerStaticInitwpstgfree::$prefixesPsr0;
362
  $loader->classMap = ComposerStaticInitwpstgfree::$classMap;
363
 
364
  }, null, ClassLoader::class);
vendor/composer/installed.json CHANGED
@@ -1,4 +1,53 @@
1
  [
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  {
3
  "name": "psr/log",
4
  "version": "1.1.3",
@@ -46,7 +95,10 @@
46
  "log",
47
  "psr",
48
  "psr-3"
49
- ]
 
 
 
50
  },
51
  {
52
  "name": "symfony/filesystem",
@@ -98,7 +150,10 @@
98
  }
99
  ],
100
  "description": "Symfony Filesystem Component",
101
- "homepage": "https://symfony.com"
 
 
 
102
  },
103
  {
104
  "name": "symfony/finder",
@@ -149,21 +204,24 @@
149
  }
150
  ],
151
  "description": "Symfony Finder Component",
152
- "homepage": "https://symfony.com"
 
 
 
153
  },
154
  {
155
  "name": "symfony/polyfill-ctype",
156
- "version": "v1.18.1",
157
- "version_normalized": "1.18.1.0",
158
  "source": {
159
  "type": "git",
160
  "url": "https://github.com/symfony/polyfill-ctype.git",
161
- "reference": "1c302646f6efc070cd46856e600e5e0684d6b454"
162
  },
163
  "dist": {
164
  "type": "zip",
165
- "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/1c302646f6efc070cd46856e600e5e0684d6b454",
166
- "reference": "1c302646f6efc070cd46856e600e5e0684d6b454",
167
  "shasum": ""
168
  },
169
  "require": {
@@ -172,11 +230,11 @@
172
  "suggest": {
173
  "ext-ctype": "For best performance"
174
  },
175
- "time": "2020-07-14T12:35:20+00:00",
176
  "type": "library",
177
  "extra": {
178
  "branch-alias": {
179
- "dev-master": "1.18-dev"
180
  },
181
  "thanks": {
182
  "name": "symfony/polyfill",
@@ -213,6 +271,46 @@
213
  "ctype",
214
  "polyfill",
215
  "portable"
216
- ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
217
  }
218
  ]
1
  [
2
+ {
3
+ "name": "lucatume/di52",
4
+ "version": "2.1.2",
5
+ "version_normalized": "2.1.2.0",
6
+ "source": {
7
+ "type": "git",
8
+ "url": "https://github.com/lucatume/di52.git",
9
+ "reference": "d0f9afbc609a1fed67a9396db5e99badf2e4f23a"
10
+ },
11
+ "dist": {
12
+ "type": "zip",
13
+ "url": "https://api.github.com/repos/lucatume/di52/zipball/d0f9afbc609a1fed67a9396db5e99badf2e4f23a",
14
+ "reference": "d0f9afbc609a1fed67a9396db5e99badf2e4f23a",
15
+ "shasum": ""
16
+ },
17
+ "require": {
18
+ "php": ">=5.2",
19
+ "xrstf/composer-php52": "1.*"
20
+ },
21
+ "require-dev": {
22
+ "phpunit/phpunit-mock-objects-php52": "dev-1.1.0-php52",
23
+ "phpunit/phpunit-php52": "dev-3.6.12-php52"
24
+ },
25
+ "time": "2020-10-27T15:26:20+00:00",
26
+ "type": "library",
27
+ "installation-source": "dist",
28
+ "autoload": {
29
+ "psr-0": {
30
+ "tad_DI52_": [
31
+ "src/"
32
+ ]
33
+ }
34
+ },
35
+ "notification-url": "https://packagist.org/downloads/",
36
+ "license": [
37
+ "GPL-3.0"
38
+ ],
39
+ "authors": [
40
+ {
41
+ "name": "Luca Tumedei",
42
+ "email": "luca@theaveragedev.com"
43
+ }
44
+ ],
45
+ "description": "A PHP 5.2 compatible dependency injection container.",
46
+ "support": {
47
+ "issues": "https://github.com/lucatume/di52/issues",
48
+ "source": "https://github.com/lucatume/di52/tree/2.1.2"
49
+ }
50
+ },
51
  {
52
  "name": "psr/log",
53
  "version": "1.1.3",
95
  "log",
96
  "psr",
97
  "psr-3"
98
+ ],
99
+ "support": {
100
+ "source": "https://github.com/php-fig/log/tree/1.1.3"
101
+ }
102
  },
103
  {
104
  "name": "symfony/filesystem",
150
  }
151
  ],
152
  "description": "Symfony Filesystem Component",
153
+ "homepage": "https://symfony.com",
154
+ "support": {
155
+ "source": "https://github.com/symfony/filesystem/tree/v2.8.52"
156
+ }
157
  },
158
  {
159
  "name": "symfony/finder",
204
  }
205
  ],
206
  "description": "Symfony Finder Component",
207
+ "homepage": "https://symfony.com",
208
+ "support": {
209
+ "source": "https://github.com/symfony/finder/tree/v2.8.50"
210
+ }
211
  },
212
  {
213
  "name": "symfony/polyfill-ctype",
214
+ "version": "v1.19.0",
215
+ "version_normalized": "1.19.0.0",
216
  "source": {
217
  "type": "git",
218
  "url": "https://github.com/symfony/polyfill-ctype.git",
219
+ "reference": "aed596913b70fae57be53d86faa2e9ef85a2297b"
220
  },
221
  "dist": {
222
  "type": "zip",
223
+ "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/aed596913b70fae57be53d86faa2e9ef85a2297b",
224
+ "reference": "aed596913b70fae57be53d86faa2e9ef85a2297b",
225
  "shasum": ""
226
  },
227
  "require": {
230
  "suggest": {
231
  "ext-ctype": "For best performance"
232
  },
233
+ "time": "2020-10-23T09:01:57+00:00",
234
  "type": "library",
235
  "extra": {
236
  "branch-alias": {
237
+ "dev-main": "1.19-dev"
238
  },
239
  "thanks": {
240
  "name": "symfony/polyfill",
271
  "ctype",
272
  "polyfill",
273
  "portable"
274
+ ],
275
+ "support": {
276
+ "source": "https://github.com/symfony/polyfill-ctype/tree/v1.19.0"
277
+ }
278
+ },
279
+ {
280
+ "name": "xrstf/composer-php52",
281
+ "version": "v1.0.20",
282
+ "version_normalized": "1.0.20.0",
283
+ "source": {
284
+ "type": "git",
285
+ "url": "https://github.com/composer-php52/composer-php52.git",
286
+ "reference": "bd41459d5e27df8d33057842b32377c39e97a5a8"
287
+ },
288
+ "dist": {
289
+ "type": "zip",
290
+ "url": "https://api.github.com/repos/composer-php52/composer-php52/zipball/bd41459d5e27df8d33057842b32377c39e97a5a8",
291
+ "reference": "bd41459d5e27df8d33057842b32377c39e97a5a8",
292
+ "shasum": ""
293
+ },
294
+ "time": "2016-04-16T21:52:24+00:00",
295
+ "type": "library",
296
+ "extra": {
297
+ "branch-alias": {
298
+ "dev-default": "1.x-dev"
299
+ }
300
+ },
301
+ "installation-source": "dist",
302
+ "autoload": {
303
+ "psr-0": {
304
+ "xrstf\\Composer52": "lib/"
305
+ }
306
+ },
307
+ "notification-url": "https://packagist.org/downloads/",
308
+ "license": [
309
+ "MIT"
310
+ ],
311
+ "support": {
312
+ "issues": "https://github.com/composer-php52/composer-php52/issues",
313
+ "source": "https://github.com/composer-php52/composer-php52"
314
+ }
315
  }
316
  ]
vendor/lucatume/di52/.github/workflows/test-php-52.yml ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: PHP 5.2
2
+ on: push
3
+ jobs:
4
+ test:
5
+ name: PHPUnit tests
6
+ runs-on: ubuntu-latest
7
+ steps:
8
+ - name: Checkout code
9
+ uses: actions/checkout@v2
10
+ - name: Install Composer dependencies
11
+ run: composer install
12
+ - name: Pull tommylau/php-5.2
13
+ run: docker pull tommylau/php-5.2
14
+ - name: Build custom PHP 5.2 image
15
+ run: docker build ./_build/containers/php-52 --tag di52/php-52:latest
16
+ - name: Run PHPUnit tests
17
+ run: docker run --rm -v ${GITHUB_WORKSPACE}:/project di52/php-52
vendor/lucatume/di52/.github/workflows/test.yml ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: PHP 5.2+
2
+ on: push
3
+ jobs:
4
+ test:
5
+ name: PHPUnit tests
6
+ runs-on: ubuntu-latest
7
+ strategy:
8
+ matrix:
9
+ php: ["5.3","5.4","5.5","5.6","7.0","7.1","7.2","7.3","7.4"]
10
+ steps:
11
+ - name: Checkout code
12
+ uses: actions/checkout@v2
13
+ - name: Setup PHP
14
+ uses: shivammathur/setup-php@v2
15
+ with:
16
+ php-version: ${{matrix.php}}
17
+ - name: Swap composer.json file
18
+ run: rm composer.json; mv composer-5-3-plus.json composer.json
19
+ - name: Get Composer cache directory
20
+ id: composercache
21
+ run: echo "::set-output name=dir::$(composer config cache-files-dir)"
22
+ - name: Cache Composer dependencies
23
+ uses: actions/cache@v2
24
+ with:
25
+ path: ${{ steps.composercache.outputs.dir }}
26
+ key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
27
+ restore-keys: ${{ runner.os }}-composer-
28
+ - name: Install dependencies
29
+ run: composer update
30
+ - name: Swap the autoload file
31
+ run: rm -f vendor/autoload_52.php; cp vendor/autoload.php vendor/autoload_52.php
32
+ - name: Run PHPUnit tests
33
+ run: vendor/bin/phpunit-php52
vendor/lucatume/di52/.gitignore ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ .idea
2
+ # Created by .ignore support plugin (hsz.mobi)
3
+ ### Composer template
4
+ vendor/
5
+
6
+ # Commit your application's lock file http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file
7
+ # You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file
8
+ # composer.lock
9
+
10
+ tests/coverage
11
+
vendor/lucatume/di52/.phpstorm.meta.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace PHPSTORM_META {
4
+ $STATIC_METHOD_TYPES = [
5
+ \tad_DI52_Container::make( '' ) => [
6
+ "" == "@",
7
+ ],
8
+ ];
9
+ }
vendor/lucatume/di52/CHANGELOG.md ADDED
@@ -0,0 +1,232 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Change Log
2
+ All notable changes to this project will be documented in this file.
3
+ This project adheres to [Semantic Versioning](http://semver.org/).
4
+
5
+ ## [unreleased] Unreleased
6
+
7
+ ## [2.1.2] 2020-10-27;
8
+
9
+ ### Fixed
10
+ - PHP 5.3 and 7.4 incompatibility issues
11
+ ### Changed
12
+ - moved the builds to GitHub Actions
13
+
14
+ ## [2.1.1] 2020-10-23;
15
+
16
+ ### Added
17
+ - new build tools to the repository
18
+ ### Changed
19
+ - refactor `Container::callback` code to re-use callbacks when available (thanks @sc0ttkclark)
20
+ ### Fixed
21
+ - fix an issue where the Closure produced by the `callback` method would build the object for static method calls
22
+
23
+ ## [2.1.0] - 2020-07-14
24
+ ### Added
25
+ - support for one parameter singletong binding of concrete, instantiatable, classes, thanks @Luc45
26
+
27
+ ## [2.0.12] - 2019-10-14
28
+ ### Added
29
+ - add PHPStorm make method auto-completion (thanks @Luc45)
30
+
31
+ ## [2.0.11] - 2019-09-26
32
+ ### Changed
33
+ - improve exception throwing to show original exceptions when the building of a bound class, interface or slug fails
34
+
35
+ ## [2.0.10] - 2018-10-29
36
+ ### Fixed
37
+ - an issue with array variable handling
38
+ - made error message more clear for non-string offsets
39
+
40
+ ## [2.0.9] - 2017-09-26
41
+ ### Fixed
42
+ - issue with `setVar` method where, in some instances, variable values could not be overridden
43
+
44
+ ## [2.0.8] - 2017-07-18
45
+ ### Fixed
46
+ - check for file existence in autoload script (thanks @truongwp)
47
+
48
+ ## [2.0.7] - 2017-06-15
49
+ ### Fixed
50
+ - issue where non registered classes object dependencies would be built just the first time (issue #2)
51
+
52
+ ## [2.0.6] - 2017-05-09
53
+ ### Fixed
54
+ - fix handling of unbound interface arguments
55
+
56
+ ## [2.0.5] - 2017-02-22
57
+ ### Changed
58
+ - change internal method visibility to improve compatibility with monkey patching libraries
59
+
60
+ ## [2.0.4] - 2017-02-22
61
+ ### Fixed
62
+ - allow unbound classes with `__construct` method requirements to be used in `instance` callbacks
63
+
64
+ ## [2.0.3] - 2017-02-07
65
+ ### Fixed
66
+ - support for use of `callback` to feed `instance` and viceversa
67
+
68
+ ## [2.0.2] - 2017-02-02
69
+ ### Fixed
70
+ - support for built objects in `instance` and `callback` methods
71
+
72
+ ## [2.0.1] - 2017-01-23
73
+ ### Fixed
74
+ - an issue where re-binding implementations could lead to built objects still using previous bindings
75
+
76
+ #### Changed
77
+ - removed some dead code left over from previous iterations
78
+
79
+ ## [2.0.0] - 2017-01-21
80
+ ### Added
81
+ - `instance` and `callback` methods
82
+
83
+ ### Changed
84
+ - refactored the code completely
85
+ - the README file to update it to the new code
86
+
87
+ ### Removed
88
+ - support for array based construction instructions (see `instance` methods)
89
+
90
+ ## [1.4.5] - 2017-01-19
91
+ ### Fixed
92
+ - an issue where singleton resolution would result in circular reference on some Windows versions (thanks @bordoni)
93
+
94
+ ## [1.4.4] - 2017-01-09
95
+ ### Added
96
+ - support for binding replacement
97
+
98
+ ## [1.4.3] - 2016-10-18
99
+ ### Changed
100
+ - snake_case method names are now set to camelCase
101
+
102
+ ### Fixed
103
+ - an inheritance issue on PHP 5.2
104
+ - non PHP 5.2 compatible tests
105
+
106
+ ### Added
107
+ - Travis CI support and build
108
+
109
+ ## [1.4.2] - 2016-10-14
110
+ ### Fixed
111
+ - nested dependency resolution issue with interfaces and default values
112
+
113
+ ## [1.4.1b] - 2016-10-14
114
+ ### Fixed
115
+ - pass the `afterBuildMethods` argument along...
116
+
117
+ ## [1.4.1] - 2016-10-14
118
+ ### Fixed
119
+ - updated `tad_di512_Container` `bind` and `singleton` methods signatures
120
+
121
+ ## [1.4.0] - 2016-10-14
122
+ ### Added
123
+ - more informative exception message when trying to resolve unbound slug or non existing class
124
+ - support for after build methods
125
+
126
+ ### Fixed
127
+ - another nested dependency resolving issue
128
+
129
+ ## [1.3.2] - 2016-07-28
130
+ ### Fixed
131
+ - nested dependency resolving issue
132
+
133
+ ## [1.3.1] - 2016-04-19
134
+ ### Added
135
+ - more informative exception message when default primitive value is missing
136
+
137
+ ## [1.3.0] - 2016-04-19
138
+ ### Added
139
+ - support for the custom bindings
140
+ - support for same class singleton binding
141
+
142
+ ### Changed
143
+ - performance optimization
144
+
145
+ ## [1.2.6] - 2016-04-11
146
+ ### Changed
147
+ - internal workings to improve performance (using [@TomBZombie benchmarks](https://github.com/TomBZombie/php-dependency-injection-benchmarks)
148
+
149
+ ## [1.2.5] - 2016-03-06
150
+ ### Added
151
+ - support for decorator pattern in PHP 5.2 compatible syntax
152
+ - code highlighting for code examples in doc (thanks @omarreiss)
153
+
154
+ ## [1.2.4] - 2016-03-05
155
+ ### Added
156
+ - tests for uncovered code
157
+
158
+ ## [1.2.3] - 2016-03-04
159
+ ### Fixed
160
+ - singleton resolution for same implementations
161
+
162
+ ## [1.2.2] - 2016-02-13
163
+ - doc updates
164
+
165
+ ## [1.2.1] - 2016-02-13
166
+ ### Added
167
+ - `hasTag($tag)` method to the container
168
+ - `isBound($classOrInterface)` method to the container
169
+ - support for deferred service providers
170
+
171
+ ## [1.2.1] - 2016-01-23
172
+ ### Added
173
+ - tagging support
174
+ - service providers support
175
+
176
+ ## [1.2.0] - 2016-01-22
177
+ ### Added
178
+ - the binding and automatic resolution API ([code inspiration](https://www.ltconsulting.co.uk/automatic-dependency-injection-with-phps-reflection-api/))
179
+
180
+ ## [1.1.2] - 2016-01-19
181
+ ### Fixed
182
+ - resolution for objects in arrays
183
+
184
+ ## [1.1.1] - 2016-01-19
185
+ ### Added
186
+ - support for the `%varName%` variable notation.
187
+
188
+ ## [1.1.0] - 2016-01-18
189
+ ### Added
190
+ - array resolution support for the Array Access API.
191
+ - the changelog.
192
+
193
+ [1.0.2]: https://github.com/lucatume/di52/compare/1.0.1...1.0.2
194
+ [1.0.3]: https://github.com/lucatume/di52/compare/1.0.2...1.0.3
195
+ [1.1.0]: https://github.com/lucatume/di52/compare/1.0.3...1.1.0
196
+ [1.1.1]: https://github.com/lucatume/di52/compare/1.0.3...1.1.2
197
+ [1.1.2]: https://github.com/lucatume/di52/compare/1.0.3...1.1.2
198
+ [1.2.0]: https://github.com/lucatume/di52/compare/1.1.2...1.2.0
199
+ [1.2.0]: https://github.com/lucatume/di52/compare/1.1.2...1.2.0
200
+ [1.2.1]: https://github.com/lucatume/di52/compare/1.2.0...1.2.1
201
+ [1.2.2]: https://github.com/lucatume/di52/compare/1.2.1...1.2.2
202
+ [1.2.3]: https://github.com/lucatume/di52/compare/1.2.2...1.2.3
203
+ [1.2.4]: https://github.com/lucatume/di52/compare/1.2.3...1.2.4
204
+ [1.2.5]: https://github.com/lucatume/di52/compare/1.2.4...1.2.5
205
+ [1.2.6]: https://github.com/lucatume/di52/compare/1.2.5...1.2.6
206
+ [1.3.0]: https://github.com/lucatume/di52/compare/1.2.6...1.3.0
207
+ [1.3.1]: https://github.com/lucatume/di52/compare/1.3.0...1.3.1
208
+ [1.3.2]: https://github.com/lucatume/di52/compare/1.3.1...1.3.2
209
+ [1.4.0]: https://github.com/lucatume/di52/compare/1.3.1...1.4.0
210
+ [1.4.1]: https://github.com/lucatume/di52/compare/1.4.0...1.4.1
211
+ [1.4.1b]: https://github.com/lucatume/di52/compare/1.4.1...1.4.1b
212
+ [1.4.2]: https://github.com/lucatume/di52/compare/1.4.1b...1.4.2
213
+ [1.4.3]: https://github.com/lucatume/di52/compare/1.4.2...1.4.3
214
+ [1.4.4]: https://github.com/lucatume/di52/compare/1.4.3...1.4.4
215
+ [1.4.5]: https://github.com/lucatume/di52/compare/1.4.4...1.4.5
216
+ [2.0.0]: https://github.com/lucatume/di52/compare/1.4.5...2.0.0
217
+ [2.0.1]: https://github.com/lucatume/di52/compare/2.0.0...2.0.1
218
+ [2.0.2]: https://github.com/lucatume/di52/compare/2.0.1...2.0.2
219
+ [2.0.3]: https://github.com/lucatume/di52/compare/2.0.2...2.0.3
220
+ [2.0.4]: https://github.com/lucatume/di52/compare/2.0.3...2.0.4
221
+ [2.0.5]: https://github.com/lucatume/di52/compare/2.0.4...2.0.5
222
+ [2.0.6]: https://github.com/lucatume/di52/compare/2.0.5...2.0.6
223
+ [2.0.7]: https://github.com/lucatume/di52/compare/2.0.6...2.0.7
224
+ [2.0.8]: https://github.com/lucatume/di52/compare/2.0.7...2.0.8
225
+ [2.0.9]: https://github.com/lucatume/di52/compare/2.0.8...2.0.9
226
+ [2.0.10]: https://github.com/lucatume/di52/compare/2.0.9...2.0.10
227
+ [2.0.11]: https://github.com/lucatume/di52/compare/2.0.10...2.0.11
228
+ [2.0.12]: https://github.com/lucatume/di52/compare/2.0.11...2.0.12
229
+ [2.1.0]: https://github.com/lucatume/di52/compare/2.0.12...2.1.0
230
+ [2.1.1]: https://github.com/lucatume/di52/compare/2.1.0...2.1.1
231
+ [2.1.2]: https://github.com/lucatume/di52/compare/2.1.1...2.1.2
232
+ [Unreleased]: https://github.com/lucatume/di52/compare/2.1.2...HEAD
vendor/lucatume/di52/README.md ADDED
@@ -0,0 +1,688 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ A PHP 5.2 compatible dependency injection container heavily inspired by [Laravel IOC](https://laravel.com/docs/5.0/container "Service Container - Laravel - The PHP Framework For Web Artisans") and [Pimple](http://pimple.sensiolabs.org/ "Pimple - A simple PHP Dependency Injection Container") that works even better on newer version of PHP.
2
+
3
+ [![Build Status](https://travis-ci.org/lucatume/di52.svg?branch=master)](https://travis-ci.org/lucatume/di52)
4
+
5
+ ## Installation
6
+ Use [Composer](https://getcomposer.org/) to require the library:
7
+
8
+ ```bash
9
+ composer require lucatume/di52
10
+ ```
11
+
12
+ Include the [Composer](https://getcomposer.org/) autoload file in your project entry point and create a new instance of the container to start using it:
13
+
14
+ ```php
15
+ require_once 'vendor/autoload.php'
16
+
17
+ $container = new tad_DI52_Container();
18
+ ```
19
+
20
+ If that's not an option then clone or download the package and require the `di52/autoload.php` file in your code:
21
+
22
+ ```php
23
+ require_once 'path/to/di52/autoload.php'
24
+
25
+ $container = new tad_DI52_Container();
26
+ ```
27
+
28
+ Where `path/to/di52/autoload.php` is the absolute path to the `autoload.php` file found in di52 root folder.
29
+
30
+ ### PHP 5.2 Installation
31
+ While the container will work on newer versions of php it was born to support PHP 5.2 out of the box; if the application requires it I suggest [requiring the `xrstf/composer-php52` package](https://packagist.org/packages/xrstf/composer-php52 "xrstf/composer-php52 - Packagist") to handle autoloading on PHP 5.2 compatible code.
32
+
33
+ ## PHP 5.2 examples, PHP 7 ready code
34
+ While the examples in the code are, for the most part, PHP 5.2 compatible di52 will work even better with newer versions of PHP.
35
+
36
+ ## Code example
37
+ ```php
38
+ // ClassOne.php
39
+ class ClassOne implements InterfaceOne {}
40
+
41
+ // MysqlConnection.php
42
+ class MysqlConnection implements DbConnectionInterface {}
43
+
44
+ // ClassThree.php
45
+ class ClassThree {
46
+ public function __construct(InterfaceOne $one, DbConnectionInterface $db){
47
+ // ...
48
+ }
49
+ }
50
+
51
+ // in the application bootstrap file
52
+ $container = new tad_DI52_Container();
53
+
54
+ $container->bind('InterfaceOne', 'ClassOne');
55
+ $container->singleton('DbConnectionInterface', 'MysqlConnection');
56
+
57
+ $three = $container->make('ClassThree');
58
+ ```
59
+
60
+ ## Quick and dirty introduction to dependency injection and DI containers
61
+
62
+ ### What is dependency injection?
63
+
64
+ A [Dependency Injection (DI) Container](https://en.wikipedia.org/wiki/Dependency_injection "Dependency injection - Wikipedia") is a tool meant to make dependency injection possible and easy to manage.
65
+ Dependencies are specified by a class constructor method via [**type-hinting**](http://php.net/manual/en/language.oop5.typehinting.php "PHP: Type Hinting - Manual"):
66
+
67
+ ```php
68
+ class A {
69
+ private $b;
70
+ private $c;
71
+
72
+ public function __construct(B $b, C $c){
73
+ $this->b = $b;
74
+ $this->c = $c;
75
+ }
76
+ }
77
+ ```
78
+
79
+ Any instance of class `A` **depends** on implementations of the `B` and `C` classes.
80
+ The "injection" happens when class `A` dependencies are passed to it, "injected" in its constructor method, in place of being created inside the class itself.
81
+
82
+
83
+ ```php
84
+ $a = new A(new B(), new C());
85
+ ```
86
+
87
+ The flexibility of type hinting allows injecting into `A` not just instances of `B` and `C` but instances of any class extending the two:
88
+
89
+ ```php
90
+ class ExtendedB extends B {}
91
+
92
+ class ExtendedC extends C {}
93
+
94
+ $a = new a(new ExtendedB(), new ExtendedC());
95
+ ```
96
+
97
+ PHP allows type hinting not just **concrete implementations** (classes) but **interfaces** too:
98
+
99
+ ```php
100
+ class A {
101
+ private $b;
102
+ private $c;
103
+
104
+ public function __construct(BInterface $b, CInterface $c){
105
+ $this->b = $b;
106
+ $this->c = $c;
107
+ }
108
+ }
109
+ ```
110
+
111
+ This extends the possibilities of dependency injection even further and avoids strict coupling of the code:
112
+
113
+ ```php
114
+ class B implements BInterface {}
115
+
116
+ class C implements CInterface {}
117
+
118
+ $a = new a(new B(), new C());
119
+ ```
120
+
121
+ ### What is a DI container?
122
+ The `B` and `C` classes are concrete (as in "you can instance them") implementations of interfaces and while the interfaces might never change the implementations might and should change in the lifecycle of code: that's the [Dependency Inversion principle](https://en.wikipedia.org/wiki/Dependency_inversion_principle) or "depend upon abstraction, non concretions".
123
+ If the implementation of `BInterface` changes from `B` to `BetterB` then I'd have to update all the code where I'm building instances of `A` to use `BetterB` in place of `B`:
124
+
125
+ ```php
126
+
127
+ // before
128
+ $a = new A(new B(), new C());
129
+
130
+ //after
131
+ $a = new A(new BetterB(), new C());
132
+ ```
133
+
134
+ On smaller code-bases this might prove to be a quick solution but, as the code grows, it will become less and less an applicable solution.
135
+ Adding classes to the mix proves the point when dependencies start to stack:
136
+
137
+ ```php
138
+ class D implements DInterface{
139
+ public function __construct(AInterface $a, CInterface $c){}
140
+ }
141
+
142
+ class E {
143
+ public function __construct(DInterface $d){}
144
+ }
145
+
146
+ $a = new A (new BetterB(), new C());
147
+ $d = new D($a, $c);
148
+ $e = new E($d);
149
+ ```
150
+
151
+ Another issue with this approach is that classes have to be built immediately to be injected, see `$a` and `$d` above to feed `$e`, with the immediate cost of "eager" instantiation, if `$e` is never used than the effort put into building it, in terms of time and resources spent by PHP to build `$a`, `$b`, `$c`, `$d` and finally `$e`, are wasted.
152
+ A **dependency injection container** is an object that, provided construction templates of objects, will take care of building only objects that are really needed taking care of **resolving** nested dependencies.
153
+
154
+ >Need an instance of `E`? I will build instances of `B` and `C` to build an instance of `A` to build an instance of `D` to finally build and return an instance of `E`.
155
+
156
+ ### Construction templates
157
+ The container will need to be told, just once, how objects should be built.
158
+ For the container it's easy to understand that a class type-hinting an instance of the concrete class `A` will require a new instance of `A` but loosely coupled code leveraging the use of a DI container will probably type-hint an `interface` in place of concrete `class`es.
159
+ Telling the container what concrete `class` to instance when a certain `interface` is requested by an object `__construct` method is called "binding and implementation to an interface".
160
+ While dependency injection can be made in other methods too beyond the `__construct` one that's what di52 supports at the moment; if you want to read more the web is full of good reference material, [this article by Fabien Potencier](http://fabien.potencier.org/what-is-dependency-injection.html) is a very good start.
161
+
162
+ ## The power of make
163
+ At its base the container is a dependency resolution and injection machine: given a class to its `make` method it will read the class type-hinted dependencies, build them and inject them in the class.
164
+
165
+ ```php
166
+ // file ClassThree.php
167
+ class ClassThree {
168
+ private $one;
169
+ private $two;
170
+
171
+ public function __construct(ClassOne $one, ClassTwo $two){
172
+ $this->one = $one;
173
+ $this->two = $two;
174
+ }
175
+ }
176
+
177
+ // application bootstrap file
178
+ $container = new tad_DI52_Container();
179
+
180
+ $three = $container->make('ClassThree');
181
+ ```
182
+
183
+ Keep that in mind while reading the following paragraphs.
184
+
185
+ ## Storing variables
186
+ In its most basic use case the container can store variables:
187
+
188
+ ```php
189
+ $container = new tad_DI52_Container();
190
+
191
+ $container->setVar('foo', 23);
192
+
193
+ $foo = $container->getVar('foo');
194
+ ```
195
+
196
+ Since di52 will treat any callable object as a factory (see below) callables have to be protected using the container `protect` method:
197
+
198
+ ```php
199
+ $container = new tad_DI52_Container();
200
+
201
+ $container->setVar('foo.factory', $container->protect(function($val){
202
+ return $val + 23;
203
+ }));
204
+
205
+ $foo = $container->getVar('foo');
206
+ ```
207
+
208
+ ## Binding implementations
209
+ Once an instance of di52 is available telling it what should be built and when is quite easy; di52 proposes the same API exposed by [Laravel Service container](https://laravel.com/docs/5.3/container "Service Container - Laravel - The PHP Framework For Web ...") and while the inner workings are different the good idea (Laravel's) is reused.
210
+ Reusing the example above:
211
+
212
+ ```php
213
+ $container = new tad_DI52_Container();
214
+
215
+ // binding
216
+ $container->bind('AInterface', 'A');
217
+ $container->bind('BInterface', 'BetterB');
218
+ $container->bind('CInterface', 'C');
219
+ $container->bind('DInterface', 'D');
220
+
221
+ // constructing
222
+ $e = $container->make('E');
223
+ ```
224
+
225
+ The `make` method will build the `E` object resolving its requirements to the bound implementations when requested.
226
+ When using the `bind` method a new instance of the bound implementations will be returned on each request; this might not be the wanted behaviour especially for object costly to build (like a database driver that needs to connect): in that case the `singleton` method should be used:
227
+
228
+ ```php
229
+ $container = new tad_DI52_Container();
230
+
231
+ $container->singleton('DBDriverInterface', 'MYSqlDriver');
232
+ $container->singleton('RepositoryInterface', 'MYSQLRepository');
233
+
234
+ $container->make('RepositoryInterface');
235
+ ```
236
+
237
+ Binding an implementation to an interface using the `singleton` methods tells the container the implementations should be built just the first time: any later call for that same interface should return the same instance.
238
+ Implementations can be redefined in any moment simple calling the `bind` or `singleton` methods again specifying a different implementation.
239
+
240
+ ## Binding objects
241
+ The container allows binding (using the `bind` or the `singleton` method) more than just implementations in the form of class names to take into account various scenarios where objects might be pre-existing in previous code or built in an other way; when binding an object that same object will be returned each time making the use of `bind` and `singleton` equivalent:
242
+
243
+ ```php
244
+ $container = new tad_DI52_Container();
245
+
246
+ // a globally stored instance of the database handling class
247
+ global $db;
248
+
249
+ $container->bind('DBInterface', $db);
250
+
251
+ // binding an object that's built using a factory
252
+ $container->bind('RepositoryInterface', RepositoryFactory::make('post'));
253
+
254
+ if($condition) {
255
+ $handler = new HandlerOne();
256
+ } else {
257
+ $handler = new HandlerTwo();
258
+ }
259
+
260
+ // binding an object that's built in some other way
261
+ $container->bind('HandlerInterface', $handler);
262
+ ```
263
+
264
+ ## Binding closures on PHP 5.3+
265
+ All of the cases above suffers from an "eager instantiation" that's far from being ideal; if that's the case and the code runs on PHP 5.3+ then closures can be bound as factories using `bind` and as singletons using `singleton`:
266
+
267
+ ```php
268
+ $container = new tad_DI52_Container();
269
+
270
+ // binding an object that's built using a factory using a closure
271
+ $container->bind('RepositoryInterface', function(){
272
+ return RepositoryFactory::make('post');
273
+ });
274
+
275
+ // binding an object that's built in some other way
276
+ $container->singleton('HandlerInterface', function(){
277
+ if($condition) {
278
+ $handler = new HandlerOne();
279
+ } else {
280
+ $handler = new HandlerTwo();
281
+ }
282
+ });
283
+ ```
284
+
285
+ Closures will receive the container itself as an argument and will be able to leverage its resolution power:
286
+
287
+ ```php
288
+ $container = new tad_DI52_Container();
289
+
290
+ $container->make('DBDriverInterface', 'MYSQLDriver');
291
+
292
+ $container->bind('DBInterface', function(tad_DI52_Container $container){
293
+ $dbDriver = $container->make('DBDriverInterface');
294
+
295
+ return new DBConnection($dbDriver);
296
+ });
297
+ ```
298
+
299
+ ## Binding implementations to classes
300
+ Binding implementations to interfaces works when the object constructor methods type hint interfaces but that might not always be the case; the container will handle that case allowing implementations to be bound to classes supporting both the `bind` and the `singleton` methods:
301
+
302
+ ```php
303
+ // file LegacyClass.php
304
+ class LegacyClass {
305
+ public function __construct(ClassOne $one, ClassTwo $two){}
306
+ }
307
+
308
+ // app bootstrap file
309
+ $container = new tad_DI52_Container();
310
+
311
+ $container->bind('ClassOne', 'ModernClassOne');
312
+ $container->bind('ClassTwo', 'ModernClassTwo');
313
+
314
+ // the container will inject instances of the `ModernClassOne` and `ModernClassTwo` classes
315
+ $container->make('LegacyClass');
316
+ ```
317
+
318
+ ### Registering concrete instantiable classes as singleton
319
+ The container knows how to `make` instances of a concrete, instantiatable class, and there might be situations where
320
+ the requirement is to have `make` return the same singleton instance of a class on each call.
321
+
322
+ In those situations the binding syntax can be shortened to one parameter in place of two:
323
+
324
+ ```php
325
+ // I want the `ClassOne` instance returned by the container to be the same every time.
326
+
327
+ // app bootstrap file
328
+ $container = new tad_DI52_Container();
329
+
330
+ // This is the short syntax to instruct the container to bind `ClassOne` as a singleton.
331
+ // This is the short form of this: $container->singleton(ClassOne::class, ClassOne::class);
332
+ $container->singleton(ClassOne::class);
333
+
334
+ assert($container->make(ClassOne::class) === $container->make(ClassOne::class));
335
+ ```
336
+
337
+ ## Binding implementations to slugs
338
+ The container was heavily inspired by [Pimple](http://pimple.sensiolabs.org/ "Pimple - A simple PHP Dependency Injection Container") and offers some features of the PHP 5.3+ DI container as well:
339
+
340
+ ```php
341
+ $container = new tad_DI52_Container();
342
+
343
+ $container['db.driver'] = 'MYSQLDriver';
344
+
345
+ // storing a closure as a singleton constructor
346
+ $container['db.connection'] = function($container){
347
+ $dbDriver = $container->make('db.driver');
348
+
349
+ return new DBConnection($dbDriver);
350
+ };
351
+
352
+ $dbConnection = $container['db.connection'];
353
+
354
+ // storing a closure as a var
355
+ $container['uniqid'] = $container->protect(function(){
356
+ return uniqid('id', true);
357
+ });
358
+
359
+ // storing vars
360
+ $container['db.name'] = 'appDb';
361
+ $container['db.user'] = 'root';
362
+ $container['db.pass'] = '';
363
+ $container['db.host'] = 'localhost';
364
+
365
+ // getting vars
366
+ $dbName = $container['db.name'];
367
+ $dbUser = $container['db.user'];
368
+ $dbPass = $container['db.pass'];
369
+ $dbHost = $container['db.host'];
370
+ ```
371
+
372
+ There is no replacement for the `factory` method offered by Pimple: the `bind` method should be used instead.
373
+
374
+ ## Contextual binding
375
+ Borrowing an excellent idea from Laravel's container the possibility of contextual binding exists (supporting all the binding possibilities above).
376
+ Contextual binding solves the problem of different objects requiring different implementations of the same interface (or class, see above):
377
+
378
+ ```php
379
+ $container = new tad_DI52_Container();
380
+
381
+ // by default any object requiring an implementation of the `CacheInterface`
382
+ // should be given the same instance of `Array Cache`
383
+ $container->singleton('CacheInterface', 'ArrayCache');
384
+
385
+ $container->bind('DbCache', function($container){
386
+ $cache = $container->make('CacheInterface');
387
+ $dbCache = new DbCache($cache);
388
+ $dbCache->prime();
389
+ $dbCache->dump();
390
+
391
+ return $dbCache;
392
+ });
393
+
394
+ // but when an implementation of the `CacheInterface` is requested by `TransactionManager`
395
+ // give it an instance of `DbCache` instead
396
+ $container->when('TransactionManager')
397
+ ->needs('CacheInterface')
398
+ ->give('DbCache');
399
+ ```
400
+
401
+ ## After-build methods
402
+ When working on PHP 5.2 compatible code closures will not be available and while that does impose limits di52 tries to "limit the damage".
403
+ The last code example could be rewritten in PHP 5.2 compatible code leveraging the container support for after-build methods: methods that will be called **with no arguments** on the built objects after it has been built:
404
+
405
+ ```php
406
+ $container = new tad_DI52_Container();
407
+
408
+ $container->singleton('CacheInterface', 'ArrayCache');
409
+
410
+ $container->singleton('DbCache', 'DbCache', array('prime', 'dump'));
411
+
412
+ $container->when('TransactionManager')
413
+ ->needs('CacheInterface')
414
+ ->give('DbCache');
415
+ ```
416
+
417
+ After-build methods can be specified as the third argument of the `bind` an `singleton` methods.
418
+ If the implementation is bound using `singleton` then the after-build methods will be called only the first time when the object is built.
419
+
420
+ ## Binding decorator chains
421
+ The [Decorator pattern](https://en.wikipedia.org/wiki/Decorator_pattern "Decorator pattern - Wikipedia") allows extending the functionalities of an implementation without creating an extension and leveraging interfaces.
422
+ In very simple terms:
423
+
424
+ ```php
425
+
426
+ interface EndpointInterface {
427
+ public function get();
428
+ }
429
+
430
+ class BaseEndpoint implements EndpointInterface {
431
+ private $repository;
432
+
433
+ public function __construct(ReposistoryInterface $repository) {
434
+ $this->repository = $repository;
435
+ }
436
+
437
+ public function get() {
438
+ return $this->repository->getAll();
439
+ }
440
+ }
441
+
442
+ class CachingEndpoint implements EndpointInterface {
443
+ private $decorated;
444
+ private $cache;
445
+
446
+ public function __construct(EndpointInterface $decorated, CacheInterface $cache ) {
447
+ $this->decorated = $decorated;
448
+ $this->cache = $cache;
449
+ }
450
+
451
+ public function get() {
452
+ $data = $this->cache->get('data')
453
+
454
+ if(false === $data) {
455
+ $data = $this->decorated->get();
456
+ $this->cache->set('data', $data);
457
+ }
458
+
459
+ return $data;
460
+ }
461
+ }
462
+
463
+ class LoggingEndpoint implements EndpointInterface {
464
+ private $decorated;
465
+ private $logger;
466
+
467
+ public function __construct(EndpointInterface $decorated, LoggerInterface $logger ) {
468
+ $this->decorated = $decorated;
469
+ $this->logger = logger$;
470
+ }
471
+
472
+ public function get() {
473
+ $this->logger->logRequest('get');
474
+ $data = $this->decorated->get();
475
+
476
+ return $data;
477
+ }
478
+ }
479
+ ```
480
+
481
+ The container allows binding "chain of decorators" to an interface (or slug a la Pimple, or class) using the `bindDecorators` and `singletonDecorators`.
482
+ The two methods are the `bind` and `singleton` equivalents for decorators.
483
+ The two methods can be skipped on PHP 5.3+ code:
484
+
485
+ ```php
486
+ $container = new tad_DI52_Container();
487
+
488
+ $container->bind('RepositoryInterface', 'PostRepository');
489
+ $container->bind('CacheInterface', 'ArrayCache');
490
+ $container->bind('LoggerInterface', 'FileLogger');
491
+
492
+ $container->bind('PostEndpoint', function($container){
493
+ $base = $container->make('BaseEndpoint');
494
+ $caching = new CachingEndpoint($base, $container->make('CacheInterface'));
495
+ $logging = new LoggingEndpoint($caching, $container->make('LoggerInterface'));
496
+
497
+ return $logging;
498
+ });
499
+ ```
500
+
501
+ But becomes necessary on PHP 5.2 compatible code:
502
+
503
+ ```php
504
+ $container = new tad_DI52_Container();
505
+
506
+ $container->bind('CacheInterface', 'ArrayCache');
507
+ $container->bind('LoggerInterface', 'FileLogger');
508
+
509
+ // decorate right to left, last is built first!
510
+ $container->bindDecorators('EndpointInterface', array('LoggingEndpoint', 'CachingEndpoint', 'BaseEndpoint'));
511
+
512
+ $postEndpoint = $container->make('EndpointInterface');
513
+ ```
514
+
515
+ ## Tagging
516
+ Tagging allows grouping similar implementations for the purpose of referencing them by group.
517
+ Grouping implementations makes sense when, as an example, the same method has to be called on each implementation:
518
+
519
+ ```php
520
+ $container = new tad_DI52_Container();
521
+
522
+ $container->bind('UnsupportedEndpoint', function($container){
523
+ $template = '404';
524
+ $message = 'Nope';
525
+ $redirectAfter = 3;
526
+ $redirectTo = $container->make('HomeEndpoint');
527
+
528
+ return new UnsupportedEndpoint($template, $message, $redirectAfter, $redirectTo);
529
+ });
530
+
531
+ $container->tag(array('HomeEndpoint', 'PostEndpoint', 'UnsupportedEndpoint'), 'endpoints');
532
+
533
+ foreach($container->tagged('enpoints') as $endpoint) {
534
+ $endpoint->register();
535
+ }
536
+ ```
537
+
538
+ The `tag` method supports any possibility offered by the container in terms of binding of objects, closures, decorator chains and after-build methods.
539
+
540
+ ## The instance method
541
+ In the example above the `UnsupportedEndpoint` requires three primitive parameters and an endpoint to be built and the method used above relies on closures only available in PHP 5.3+.
542
+ To offer a degree of support the container offers the `instance` method that allows rewriting the code above to this:
543
+
544
+ ```php
545
+ $container = new tad_DI52_Container();
546
+
547
+ $container->bind('UnsupportedEndpoint', $container->instance('404', 'Nope', 3, 'HomeEndpoint'));
548
+
549
+ $container->tag(array('HomeEndpoint', 'PostEndpoint', 'UnsupportedEndpoint'), 'enpoints');
550
+
551
+ foreach($container->tagged('enpoints') as $endpoint) {
552
+ $endpoint->register();
553
+ }
554
+ ```
555
+
556
+ The instance methods does not offer the same amount of flexibility closures offer (and that's why closures were implemented) but mitigates the problem avoiding other work-arounds (singletons, factories or an eager instantiation) and granting a **lazy instantiation**.
557
+
558
+ ## The callback method
559
+ Some applications require callbacks (or some form of callable) to be returned in specific pieces of code.
560
+ This is especially the case with WordPress and its [event-based architecture](https://codex.wordpress.org/Plugin_API/Filter_Reference "Plugin API/Filter Reference « WordPress Codex").
561
+ Using the container does not removes that possibility:
562
+
563
+ ```php
564
+ $container = new tad_DI52_Container();
565
+
566
+ $container->bind('FilterInterface', 'ConcreteFilter');
567
+
568
+ add_filter('some_filter', array($container->make('FilterInterface'), 'filter'));
569
+ ```
570
+
571
+ This code suffers, but, from an eager instantiation problem: `ConcreteFilter` is built for the purpose of binding it but might never be used.
572
+ The problem is easy to solve on PHP 5.3+:
573
+
574
+
575
+ ```php
576
+ $container = new tad_DI52_Container();
577
+
578
+ $container->bind('FilterInterface', 'ConcreteFilter');
579
+
580
+ $filterFunction = function($dataToFilter) use($container){
581
+ $filter = $container->make('FilterInterface');
582
+
583
+ return $filter->filter($data);
584
+ };
585
+
586
+ add_filter('some_filter', $filterFunction);
587
+ ```
588
+
589
+ But this is not an option on PHP 5.2 compatible code.
590
+ In that case the container offers the `callback` method to return a callable function that will **lazily build** the object, call the method on it passing the call arguments and return its return value:
591
+
592
+ ```php
593
+ $container = new tad_DI52_Container();
594
+
595
+ $container->bind('FilterInterface', 'ConcreteFilter');
596
+
597
+ add_filter('some_filter', $container->callback('FilterInterface', 'filter'));
598
+ ```
599
+
600
+ ## Service providers
601
+ To avoid passing the container instance around (see [Service Locator pattern](https://en.wikipedia.org/wiki/Service_locator_pattern "Service locator pattern - Wikipedia")) or globalising it all the binding should happen in the same PHP file: this could lead, as the application grows, to a thousand lines monster.
602
+ To avoid that the container supports service providers: those are classes implmenting the `tad_DI52_ServiceProviderInterface` interface, or extend the ready to use `tad_DI52_ServiceProvider` class, that allow organizing the binding registrations into logical, self-contained and manageable units:
603
+
604
+ ```php
605
+ // file ProviderOne.php
606
+ class ProviderOne extends tad_DI52_ServiceProvider {
607
+ public function register() {
608
+ $this->container->bind('InterfaceOne', 'ClassOne');
609
+ $this->container->bind('InterfaceTwo', 'ClassTwo');
610
+ $this->container->singleton('InterfaceThree', 'ClassThree');
611
+ }
612
+ }
613
+
614
+ // application bootstrap file
615
+ $container = new tad_DI52_Container();
616
+
617
+ $container->register('ProviderOne');
618
+ ```
619
+
620
+ ### Booting service providers
621
+ The container implements a `boot` method that will, in turn, call the `boot` method on any service provider that overloads it.
622
+ Some applications might define constants and environment variables at "boot" time (e.g. WordPress `plugins_loaded` action) that might make an immediate registration futile.
623
+ In that case service providers can overload the `boot` method:
624
+
625
+
626
+ ```php
627
+ // file ProviderOne.php
628
+ class ProviderOne extends tad_DI52_ServiceProvider {
629
+ public function register() {
630
+ $this->container->bind('InterfaceOne', 'ClassOne');
631
+ $this->container->bind('InterfaceTwo', 'ClassTwo');
632
+ $this->container->singleton('InterfaceThree', 'ClassThree');
633
+ }
634
+
635
+ public function boot() {
636
+ if(defined('SOME_CONSTANT')) {
637
+ $this->container->bind('InterfaceFour', 'ClassFour');
638
+ } else {
639
+ $this->container->bind('InterfaceFour', 'AnotherClassFour');
640
+ }
641
+ }
642
+ }
643
+
644
+ // application bootstrap file
645
+ $container = new tad_DI52_Container();
646
+
647
+ $container->register('ProviderOne');
648
+ ```
649
+
650
+ ### Deferred service providers
651
+ Sometimes even just setting up the implementations might require such an up-front cost to make it undesireable unless it's needed.
652
+ This might happen with non autoloading code that will require a tangle of files to load (and side load) to grab a simple class instance.
653
+ To "defer" that cost service providers can overload the `deferred` property and the `provides` method:
654
+
655
+ ```php
656
+ // file ProviderOne.php
657
+ class ProviderOne extends tad_DI52_ServiceProvider {
658
+ public $deferred = true;
659
+
660
+ public function provides() {
661
+ return array('LegacyClassOne', 'LegacyInterfaceTwo');
662
+ }
663
+
664
+ public function register() {
665
+ include_once('legacy-file-one.php')
666
+ include_once('legacy-file-two.php')
667
+
668
+ $db = new Db();
669
+
670
+ $details = $db->getDetails();
671
+
672
+ $this->container->singleton('LegacyClassOne', new LegacyClassOne($details));
673
+ $this->container->bind('LegacyInterfaceTwo', new LegacyClassTwo($details));
674
+ }
675
+ }
676
+
677
+ // application bootstrap file
678
+ $container = new tad_DI52_Container();
679
+
680
+ // the provider `register` method will not be called immediately...
681
+ $container->register('ProviderOne');
682
+
683
+ // ...it will be called here as it provides the binding of `LegacyClassOne`
684
+ $legacyOne = $container->make('LegacyClassOne');
685
+
686
+ // will not be called again here, done already
687
+ $legacyTwo = $container->make('LegacyInterfaceTwo');
688
+ ```
vendor/lucatume/di52/_build/check_exports.sh ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+
3
+ PWD=${1:-$(pwd)}
4
+
5
+ ignored_files=$(git status --ignored --porcelain \
6
+ | grep -E '^!!' \
7
+ | awk -F' ' '{ print $2 }' \
8
+ | sed -E 's#\/$$##g'); \
9
+
10
+ echo -e "\033[1mIgnored files (local and global .gitignore file)\033[0m"; \
11
+ echo -e "\033[1m================================================\033[0m"; \
12
+ echo "${ignored_files}"; \
13
+
14
+ excluded_files=$(echo "${ignored_files}" | tr '\n' ',' | sed -e 's/,[^,]*$//g'); \
15
+ ignore_pattern="(\.$|$(echo "${excluded_files}" | sed -e 's/,/|/g' ))"; \
16
+ vcs_files=$(ls -a -1 "${PWD}" | grep -Ev "${ignore_pattern}" | sort); \
17
+
18
+ echo ""; \
19
+ echo -e "\033[1mVCS files (these will be pushed to the repository)\033[0m"; \
20
+ echo -e "\033[1m==================================================\033[0m"; \
21
+ echo "${vcs_files}"; \
22
+
23
+ export_ignored_files=$(grep -E '\s+export-ignore' ${PWD}/.gitattributes | awk -F' ' '{ print $1 }' | sort); \
24
+
25
+ echo ""; \
26
+ echo -e "\033[1mExport ignored files (export-ignore)\033[0m"; \
27
+ echo -e "\033[1m====================================\033[0m"; \
28
+ echo "${export_ignored_files}"; \
29
+
30
+ exported_vcs_files=$(comm -23 <(echo "${vcs_files}") <(echo "${export_ignored_files}")); \
31
+
32
+ echo ""; \
33
+ echo -e "\033[1mThe following files will be exported\033[0m"; \
34
+ echo -e "\033[1m====================================\033[0m"; \
35
+ echo "${exported_vcs_files}"
vendor/lucatume/di52/_build/composer-hash.sh ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env sh
2
+
3
+ # Replaces the `extra._hash` string in the composer.json file.
4
+
5
+ SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
6
+ COMPOSER_FILE="${SCRIPT_DIR}/../composer.json"
7
+
8
+ test -f "${COMPOSER_FILE}" || {
9
+ echo "composer.json file (${COMPOSER_FILE}) does not exist."
10
+ exit 1
11
+ }
12
+
13
+ ORIGINAL_HASH=$(cat "${COMPOSER_FILE}" | grep -e '"_hash"' | cut -d':' -f2 | cut -d'"' -f2)
14
+ NEW_HASH=$(date | md5sum | cut -d' ' -f1)
15
+ sed -i'.bak' -e "s/${ORIGINAL_HASH}/${NEW_HASH}/g" "${COMPOSER_FILE}"
vendor/lucatume/di52/_build/containers/php-52/Dockerfile ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ FROM tommylau/php-5.2
2
+ WORKDIR /project
3
+ CMD ["/project/vendor/bin/phpunit-php52"]
vendor/lucatume/di52/_build/dir_hash.sh ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+
3
+ if [ "$#" -lt 1 ]; then
4
+ echo -e "\033[1mReturns a directory hash.\033[0m"
5
+ echo ""
6
+ echo -e "\033[32mUsage:\033[0m"
7
+ echo " dir_hash.sh <dir>"
8
+ echo ""
9
+ echo -e "\033[32mExamples:\033[0m"
10
+ echo ""
11
+ echo " Return the hash of the src directory"
12
+ echo -e " \033[36mdir_hash.sh src \033[0m"
13
+ exit 0
14
+ fi
15
+
16
+ echo "$(find "$1" -type f -print0 | sort -z | xargs -0 sha1sum | sha1sum | cut -d' ' -f1)"
vendor/lucatume/di52/_build/release.php ADDED
@@ -0,0 +1,230 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env php
2
+ <?php
3
+ /**
4
+ * Release a major, minor or patch update w/ release notes from the CHANGELOG.md file.
5
+ *
6
+ * Usage:
7
+ *
8
+ * _build/release.php patch
9
+ * _build/release.php minor
10
+ * _build/release.php major
11
+ *
12
+ * Release w/o prompt confirmation:
13
+ *
14
+ * _build/release.php -q patch
15
+ * _build/release.php --no-interactive minor
16
+ *
17
+ * Release w/o checking for dirty or unpushed changes:
18
+ *
19
+ * _build/release.php --no-dirty-check minor
20
+ * _build/release.php --no-unpushed-check patch
21
+ *
22
+ * Run a dry-run test:
23
+ *
24
+ * _build/release.php --dry-run patch
25
+ *
26
+ * Update the changelog:
27
+ *
28
+ * _build/release.php --changelog-update patch
29
+ */
30
+
31
+ namespace lucatume\tools;
32
+
33
+ $root = dirname(__DIR__);
34
+
35
+ require_once $root . '/vendor/autoload.php';
36
+
37
+ $changelogFile = $root . '/CHANGELOG.md';
38
+
39
+ if ( ! file_exists( $changelogFile ) ) {
40
+ echo "\e[31mChangelog file (CHANGELOG.md, changelog.md) does not exist.\e[0m\n";
41
+ exit( 1 );
42
+ }
43
+
44
+ function args()
45
+ {
46
+ global $argv;
47
+
48
+ $options = getopt('q', ['not-interactive', 'no-diff-check', 'no-unpushed-check', 'dry-run', 'no-changelog-update'],
49
+ $optind);
50
+
51
+ $map = [
52
+ 'releaseType' => isset($argv[$optind]) ? $argv[$optind] : 'patch',
53
+ 'notInteractive' => isset($options['q']) || isset($options['not-interactive']),
54
+ 'noChangelogUpdate' => isset($options['no-changelog-update']),
55
+ 'checkDiff' => empty($options['no-diff-check']),
56
+ 'checkUnpushed' => empty($options['no-unpushed-check']),
57
+ 'dryRun' => isset($options['dry-run']),
58
+ ];
59
+
60
+ return static function ($key, $default = null) use ($map) {
61
+ return isset($map[$key]) ? $map[$key] : $default;
62
+ };
63
+ }
64
+
65
+ $args = args();
66
+
67
+ if (!in_array($args('releaseType'), ['major', 'minor', 'patch'], true)) {
68
+ echo "\e[31mThe release type has to be one of major, minor or patch.\e[0m\n";
69
+ exit(1);
70
+ }
71
+
72
+ $dryRun = $args('dryRun', false);
73
+
74
+ if (!$dryRun) {
75
+ $currentGitBranch = trim(shell_exec('git rev-parse --abbrev-ref HEAD'));
76
+ if ($currentGitBranch !== 'master') {
77
+ echo "\e[31mCan release only from master branch.\e[0m\n";
78
+ exit(1);
79
+ }
80
+ echo "Current git branch: \e[32m" . $currentGitBranch . "\e[0m\n";
81
+ }
82
+
83
+ /**
84
+ * Parses the changelog to get the latest notes and the latest, released, version.
85
+ *
86
+ * @param string $changelog The absolute path to the changelog file.
87
+ *
88
+ * @return array<string,mixed> The map of parsed values.
89
+ */
90
+ function changelog($changelog)
91
+ {
92
+ $notes = '';
93
+ $latestVersion = '';
94
+
95
+ $f = fopen($changelog, 'rb');
96
+ $read = false;
97
+ while ($line = fgets($f)) {
98
+ if (preg_match('/^## \\[unreleased]/', $line)) {
99
+ $read = true;
100
+ continue;
101
+ }
102
+
103
+ if (preg_match('/^## \\[(?<version>\\d+\\.\\d\.\\d+)]/', $line, $m)) {
104
+ $latestVersion = $m['version'];
105
+ break;
106
+ }
107
+
108
+ if ($read === true) {
109
+ $notes .= $line;
110
+ }
111
+ }
112
+
113
+ fclose($f);
114
+
115
+ return [ 'notes' => trim( $notes ), 'latestVersion' => $latestVersion ];
116
+ }
117
+
118
+ function updateChangelog($changelogFile, $version, callable $args, $date = null)
119
+ {
120
+ $date = $date === null ? date('Y-m-d') : $date;
121
+ $changelogVersionLine = sprintf("\n\n## [%s] %s;", $version, $date);
122
+ $changelogFileName = basename($changelogFile);
123
+ $currentContents = file_get_contents($changelogFile);
124
+ $entryLine = '## [unreleased] Unreleased';
125
+ if ( strpos( $currentContents, $entryLine ) === false ) {
126
+ $message = 'Unreleased entry line not found; does the changelog file contain an entry like "' . $entryLine . '"?';
127
+ echo "\e[31m{$message}\e[0m\n";
128
+ exit( 1 );
129
+ }
130
+ $changelogContents = str_replace($entryLine, $entryLine . $changelogVersionLine, $currentContents);
131
+ $changelogContents = preg_replace_callback(
132
+ '/^\\[unreleased]:\\s+(?<repo>.*)(?<previous_version>\\d\\.\\d\\.\\d)\\.{3}HEAD$/um',
133
+ static function (array $matches) use ($version) {
134
+ return sprintf('[%1$s]: %2$s%3$s...%1$s' . PHP_EOL . '[unreleased]: %2$s%1$s...HEAD'
135
+ , $version, $matches['repo'], $matches['previous_version']);
136
+ },
137
+ $changelogContents
138
+ );
139
+ echo "Changelog updates:\n\n---\n";
140
+ echo substr($changelogContents, 0, 1024);
141
+ echo "\n\n[...]\n\n";
142
+ echo substr($changelogContents, strlen($changelogContents) - 512);
143
+ echo "---\n\n";
144
+ if (!$args('dryRun', false)
145
+ && (
146
+ $args('notInteractive', false)
147
+ || confirm("Would you like to proceed?")
148
+ )
149
+ ) {
150
+ file_put_contents($changelogFile, $changelogContents);
151
+ passthru('git commit -m "doc(' . $changelogFileName . '.md) update to version ' . $version . '" -- ' . $changelogFile);
152
+ }
153
+ }
154
+
155
+ $changelog = changelog($changelogFile);
156
+
157
+ $releaseType = $args('releaseType', 'patch');
158
+ switch ($releaseType) {
159
+ case 'major':
160
+ $releaseVersion = preg_replace_callback('/(?<target>\\d+)\\.\\d\.\\d+/', static function ($m) {
161
+ return (++$m['target']) . '.0.0';
162
+ }, $changelog['latestVersion']);
163
+ break;
164
+ case 'minor':
165
+ $releaseVersion = preg_replace_callback('/(?<major>\\d+)\\.(?<target>\\d)\.\\d+/', static function ($m) {
166
+ return $m['major'] . '.' . (++$m['target']) . '.0';
167
+ }, $changelog['latestVersion']);
168
+ break;
169
+ case 'patch':
170
+ $releaseVersion = preg_replace_callback('/(?<major>\\d+)\\.(?<minor>\\d)\.(?<target>\\d+)/',
171
+ static function ($m) {
172
+ return $m['major'] . '.' . ($m['minor']) . '.' . (++$m['target']);
173
+ }, $changelog['latestVersion']);
174
+ break;
175
+ }
176
+
177
+ $releaseNotesHeader = "{$releaseVersion}\n\n";
178
+ $fullReleaseNotes = $releaseNotesHeader . $changelog['notes'];
179
+
180
+ echo "Latest release: \e[32m" . $changelog['latestVersion'] . "\e[0m\n";
181
+ echo "Release type: \e[32m" . $releaseType . "\e[0m\n";
182
+ echo "Next release: \e[32m" . $releaseVersion . "\e[0m\n";
183
+ echo "Release notes:\n\n---\n" . $fullReleaseNotes . "\n---\n";
184
+ echo "\n\n";
185
+
186
+ if (!$args('noChangelogUpdate', false)) {
187
+ updateChangelog($changelogFile, $releaseVersion, $args);
188
+ }
189
+
190
+ if ($args('checkDiff', true) && !$dryRun) {
191
+ $gitDirty = trim(shell_exec('git diff HEAD'));
192
+ if (!empty($gitDirty)) {
193
+ echo "\e[31mYou have uncommited work.\e[0m\n";
194
+ exit(1);
195
+ }
196
+ }
197
+
198
+ function confirm($question)
199
+ {
200
+ $question = "\n{$question} ";
201
+ return preg_match('/y/i', readline($question));
202
+ }
203
+
204
+ if ($args('checkUnpushed', true) && !$dryRun) {
205
+ $gitDiff = trim(shell_exec('git log origin/master..HEAD'));
206
+ if (!empty($gitDiff)) {
207
+ echo "\e[31mYou have unpushed changes.\e[0m\n";
208
+ if (confirm('Would you like to push them now?')) {
209
+ passthru('git push');
210
+ } else {
211
+ exit(1);
212
+ }
213
+ }
214
+ }
215
+
216
+ file_put_contents($root . '/.rel', $fullReleaseNotes);
217
+
218
+ $releaseCommand = 'hub release create -F .rel ' . $releaseVersion;
219
+
220
+ echo "Releasing with command: \e[32m" . $releaseCommand . "\e[0m\n\n";
221
+
222
+ if ($dryRun || $args('notInteractive', false) || confirm('Do you want to proceed?')) {
223
+ if (!$dryRun) {
224
+ passthru($releaseCommand);
225
+ }
226
+ } else {
227
+ echo "Canceling\n";
228
+ }
229
+
230
+ unlink($root . '/.rel');
vendor/lucatume/di52/autoload.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!function_exists('di52_findFile')) {
3
+ function di52_findFile($class)
4
+ {
5
+ if (0 !== strpos($class, 'tad_DI52_')) {
6
+ return false;
7
+ }
8
+
9
+ return dirname(__FILE__) . '/src/' . str_replace('_', DIRECTORY_SEPARATOR, $class) . '.php';
10
+ }
11
+ }
12
+
13
+ if (!function_exists('di52_autoload')) {
14
+ function di52_autoload($class)
15
+ {
16
+ $file = di52_findFile($class);
17
+ if ($file) {
18
+ include $file;
19
+
20
+ return true;
21
+ }
22
+
23
+ return false;
24
+ }
25
+ }
26
+
27
+ spl_autoload_register('di52_autoload');
vendor/lucatume/di52/composer-5-3-plus.json ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "lucatume/di52",
3
+ "description": "A PHP 5.2 compatible dependency injection container.",
4
+ "license": "GPL-3.0",
5
+ "authors": [
6
+ {
7
+ "name": "Luca Tumedei",
8
+ "email": "luca@theaveragedev.com"
9
+ }
10
+ ],
11
+ "autoload": {
12
+ "psr-0": {
13
+ "tad_DI52_": [
14
+ "src/"
15
+ ]
16
+ }
17
+ },
18
+ "minimum-stability": "dev",
19
+ "require": {
20
+ "php": ">=5.3"
21
+ },
22
+ "require-dev": {
23
+ "phpunit/phpunit-php52": "dev-3.6.12-php52",
24
+ "phpunit/phpunit-mock-objects-php52": "dev-1.1.0-php52"
25
+ },
26
+ "repositories": [
27
+ {
28
+ "type": "git",
29
+ "url": "https://github.com/garex/phpunit"
30
+ },
31
+ {
32
+ "type": "git",
33
+ "url": "https://github.com/garex/phpunit-mock-objects"
34
+ }
35
+ ]
36
+ }
vendor/lucatume/di52/composer.json ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "lucatume/di52",
3
+ "description": "A PHP 5.2 compatible dependency injection container.",
4
+ "license": "GPL-3.0",
5
+ "authors": [
6
+ {
7
+ "name": "Luca Tumedei",
8
+ "email": "luca@theaveragedev.com"
9
+ }
10
+ ],
11
+ "autoload": {
12
+ "psr-0": {
13
+ "tad_DI52_": [
14
+ "src/"
15
+ ]
16
+ }
17
+ },
18
+ "minimum-stability": "dev",
19
+ "config": {
20
+ "platform": {
21
+ "php": "5.2.17"
22
+ }
23
+ },
24
+ "require": {
25
+ "php": ">=5.2",
26
+ "xrstf/composer-php52": "1.*"
27
+ },
28
+ "require-dev": {
29
+ "phpunit/phpunit-php52": "dev-3.6.12-php52",
30
+ "phpunit/phpunit-mock-objects-php52": "dev-1.1.0-php52"
31
+ },
32
+ "repositories": [
33
+ {
34
+ "type": "git",
35
+ "url": "https://github.com/garex/phpunit"
36
+ },
37
+ {
38
+ "type": "git",
39
+ "url": "https://github.com/garex/phpunit-mock-objects"
40
+ }
41
+ ],
42
+ "scripts": {
43
+ "post-install-cmd": [
44
+ "xrstf\\Composer52\\Generator::onPostInstallCmd"
45
+ ],
46
+ "post-update-cmd": [
47
+ "xrstf\\Composer52\\Generator::onPostInstallCmd"
48
+ ],
49
+ "post-autoload-dump": [
50
+ "xrstf\\Composer52\\Generator::onPostInstallCmd"
51
+ ]
52
+ }
53
+ }
vendor/lucatume/di52/composer.lock ADDED
@@ -0,0 +1,535 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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#installing-dependencies",
5
+ "This file is @generated automatically"
6
+ ],
7
+ "content-hash": "21d2d1cfe07d9e4e835907431fc9c87e",
8
+ "packages": [
9
+ {
10
+ "name": "xrstf/composer-php52",
11
+ "version": "v1.0.20",
12
+ "source": {
13
+ "type": "git",
14
+ "url": "https://github.com/composer-php52/composer-php52.git",
15
+ "reference": "bd41459d5e27df8d33057842b32377c39e97a5a8"
16
+ },
17
+ "dist": {
18
+ "type": "zip",
19
+ "url": "https://api.github.com/repos/composer-php52/composer-php52/zipball/bd41459d5e27df8d33057842b32377c39e97a5a8",
20
+ "reference": "bd41459d5e27df8d33057842b32377c39e97a5a8",
21
+ "shasum": ""
22
+ },
23
+ "type": "library",
24
+ "extra": {
25
+ "branch-alias": {
26
+ "dev-default": "1.x-dev"
27
+ }
28
+ },
29
+ "autoload": {
30
+ "psr-0": {
31
+ "xrstf\\Composer52": "lib/"
32
+ }
33
+ },
34
+ "notification-url": "https://packagist.org/downloads/",
35
+ "license": [
36
+ "MIT"
37
+ ],
38
+ "time": "2016-04-16T21:52:24+00:00"
39
+ }
40
+ ],
41
+ "packages-dev": [
42
+ {
43
+ "name": "phpunit/php-code-coverage",
44
+ "version": "1.2.0",
45
+ "source": {
46
+ "type": "git",
47
+ "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
48
+ "reference": "21d0f05b8127057159eec4be79f8f8a92bc90957"
49
+ },
50
+ "dist": {
51
+ "type": "zip",
52
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/21d0f05b8127057159eec4be79f8f8a92bc90957",
53
+ "reference": "21d0f05b8127057159eec4be79f8f8a92bc90957",
54
+ "shasum": ""
55
+ },
56
+ "require": {
57
+ "php": ">=5.3.3",
58
+ "phpunit/php-file-iterator": ">=1.3.0@stable",
59
+ "phpunit/php-text-template": ">=1.1.1@stable",
60
+ "phpunit/php-token-stream": ">=1.1.3@stable"
61
+ },
62
+ "suggest": {
63
+ "ext-dom": "*",
64
+ "ext-reflection": "*",
65
+ "ext-spl": "*",
66
+ "ext-xdebug": ">=2.0.5"
67
+ },
68
+ "type": "library",
69
+ "autoload": {
70
+ "files": [
71
+ "PHP/CodeCoverage/Autoload.php"
72
+ ]
73
+ },
74
+ "notification-url": "https://packagist.org/downloads/",
75
+ "include-path": [
76
+ ""
77
+ ],
78
+ "license": [
79
+ "BSD-3-Clause"
80
+ ],
81
+ "authors": [
82
+ {
83
+ "name": "Sebastian Bergmann",
84
+ "email": "sb@sebastian-bergmann.de",
85
+ "role": "lead"
86
+ }
87
+ ],
88
+ "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
89
+ "homepage": "http://www.phpunit.de/",
90
+ "keywords": [
91
+ "coverage",
92
+ "testing",
93
+ "xunit"
94
+ ],
95
+ "time": "2012-09-19T00:00:00+00:00"
96
+ },
97
+ {
98
+ "name": "phpunit/php-file-iterator",
99
+ "version": "1.3.2",
100
+ "source": {
101
+ "type": "git",
102
+ "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
103
+ "reference": "46b0610951db3a918ee7842bc0d471e72c1d0d46"
104
+ },
105
+ "dist": {
106
+ "type": "zip",
107
+ "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/46b0610951db3a918ee7842bc0d471e72c1d0d46",
108
+ "reference": "46b0610951db3a918ee7842bc0d471e72c1d0d46",
109
+ "shasum": ""
110
+ },
111
+ "require": {
112
+ "php": ">=5.2.7"
113
+ },
114
+ "type": "library",
115
+ "autoload": {
116
+ "files": [
117
+ "File/Iterator/Autoload.php"
118
+ ]
119
+ },
120
+ "notification-url": "https://packagist.org/downloads/",
121
+ "include-path": [
122
+ ""
123
+ ],
124
+ "license": [
125
+ "BSD-3-Clause"
126
+ ],
127
+ "authors": [
128
+ {
129
+ "name": "Sebastian Bergmann",
130
+ "email": "sb@sebastian-bergmann.de",
131
+ "role": "lead"
132
+ }
133
+ ],
134
+ "description": "FilterIterator implementation that filters files based on a list of suffixes.",
135
+ "homepage": "http://www.phpunit.de/",
136
+ "keywords": [
137
+ "filesystem",
138
+ "iterator"
139
+ ],
140
+ "time": "2012-09-22T00:00:00+00:00"
141
+ },
142
+ {
143
+ "name": "phpunit/php-text-template",
144
+ "version": "1.1.2",
145
+ "source": {
146
+ "type": "git",
147
+ "url": "https://github.com/sebastianbergmann/php-text-template.git",
148
+ "reference": "1da672430d58dcbb21139a018febe038d8500fd8"
149
+ },
150
+ "dist": {
151
+ "type": "zip",
152
+ "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/1da672430d58dcbb21139a018febe038d8500fd8",
153
+ "reference": "1da672430d58dcbb21139a018febe038d8500fd8",
154
+ "shasum": ""
155
+ },
156
+ "require": {
157
+ "php": ">=5.2.7"
158
+ },
159
+ "type": "library",
160
+ "autoload": {
161
+ "files": [
162
+ "Text/Template/Autoload.php"
163
+ ]
164
+ },
165
+ "notification-url": "https://packagist.org/downloads/",
166
+ "include-path": [
167
+ ""
168
+ ],
169
+ "license": [
170
+ "BSD-3-Clause"
171
+ ],
172
+ "authors": [
173
+ {
174
+ "name": "Sebastian Bergmann",
175
+ "email": "sb@sebastian-bergmann.de",
176
+ "role": "lead"
177
+ }
178
+ ],
179
+ "description": "Simple template engine.",
180
+ "homepage": "http://www.phpunit.de/",
181
+ "keywords": [
182
+ "template"
183
+ ],
184
+ "time": "2012-09-23T00:00:00+00:00"
185
+ },
186
+ {
187
+ "name": "phpunit/php-timer",
188
+ "version": "1.0.3",
189
+ "source": {
190
+ "type": "git",
191
+ "url": "https://github.com/sebastianbergmann/php-timer.git",
192
+ "reference": "5175e9bb35fc9cc430973ed83a3d62531c3c8698"
193
+ },
194
+ "dist": {
195
+ "type": "zip",
196
+ "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5175e9bb35fc9cc430973ed83a3d62531c3c8698",
197
+ "reference": "5175e9bb35fc9cc430973ed83a3d62531c3c8698",
198
+ "shasum": ""
199
+ },
200
+ "require": {
201
+ "php": ">=5.2.7"
202
+ },
203
+ "type": "library",
204
+ "autoload": {
205
+ "files": [
206
+ "PHP/Timer/Autoload.php"
207
+ ]
208
+ },
209
+ "notification-url": "https://packagist.org/downloads/",
210
+ "include-path": [
211
+ ""
212
+ ],
213
+ "license": [
214
+ "BSD-3-Clause"
215
+ ],
216
+ "authors": [
217
+ {
218
+ "name": "Sebastian Bergmann",
219
+ "email": "sb@sebastian-bergmann.de",
220
+ "role": "lead"
221
+ }
222
+ ],
223
+ "description": "Utility class for timing",
224
+ "homepage": "http://www.phpunit.de/",
225
+ "keywords": [
226
+ "timer"
227
+ ],
228
+ "time": "2012-09-23T00:00:00+00:00"
229
+ },
230
+ {
231
+ "name": "phpunit/php-token-stream",
232
+ "version": "1.1.4",
233
+ "source": {
234
+ "type": "git",
235
+ "url": "https://github.com/sebastianbergmann/php-token-stream.git",
236
+ "reference": "dd11f1b0c071dc46fe711a7dd331db1b2179b9be"
237
+ },
238
+ "dist": {
239
+ "type": "zip",
240
+ "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/dd11f1b0c071dc46fe711a7dd331db1b2179b9be",
241
+ "reference": "dd11f1b0c071dc46fe711a7dd331db1b2179b9be",
242
+ "shasum": ""
243
+ },
244
+ "require": {
245
+ "ext-tokenizer": "*",
246
+ "php": ">=5.2.7"
247
+ },
248
+ "type": "library",
249
+ "autoload": {
250
+ "files": [
251
+ "PHP/Token/Stream/Autoload.php"
252
+ ]
253
+ },
254
+ "notification-url": "https://packagist.org/downloads/",
255
+ "include-path": [
256
+ ""
257
+ ],
258
+ "license": [
259
+ "BSD-3-Clause"
260
+ ],
261
+ "authors": [
262
+ {
263
+ "name": "Sebastian Bergmann",
264
+ "email": "sb@sebastian-bergmann.de",
265
+ "role": "lead"
266
+ }
267
+ ],
268
+ "description": "Wrapper around PHP's tokenizer extension.",
269
+ "homepage": "http://www.phpunit.de/",
270
+ "keywords": [
271
+ "tokenizer"
272
+ ],
273
+ "time": "2012-09-23T00:00:00+00:00"
274
+ },
275
+ {
276
+ "name": "phpunit/phpunit-mock-objects-php52",
277
+ "version": "dev-1.1.0-php52",
278
+ "source": {
279
+ "type": "git",
280
+ "url": "https://github.com/garex/phpunit-mock-objects",
281
+ "reference": "625622b0678d53aa47c6dc7e232e0171e2623d75"
282
+ },
283
+ "require": {
284
+ "ext-reflection": "*",
285
+ "ext-spl": "*",
286
+ "php": ">=5.2.6",
287
+ "phpunit/php-text-template": ">=1.1.1@stable"
288
+ },
289
+ "type": "library",
290
+ "autoload": {
291
+ "classmap": [
292
+ "PHPUnit/"
293
+ ]
294
+ },
295
+ "include-path": [
296
+ ""
297
+ ],
298
+ "time": "2014-10-02T18:21:59+00:00"
299
+ },
300
+ {
301
+ "name": "phpunit/phpunit-php52",
302
+ "version": "dev-3.6.12-php52",
303
+ "source": {
304
+ "type": "git",
305
+ "url": "https://github.com/garex/phpunit",
306
+ "reference": "96cd6cf307d82a4458f0c0bf8fb695d21b1a6072"
307
+ },
308
+ "require": {
309
+ "ext-dom": "*",
310
+ "ext-pcre": "*",
311
+ "ext-reflection": "*",
312
+ "ext-spl": "*",
313
+ "php": ">=5.2.7",
314
+ "phpunit/php-code-coverage": "=1.2.0",
315
+ "phpunit/php-file-iterator": "=1.3.2",
316
+ "phpunit/php-text-template": "=1.1.2",
317
+ "phpunit/php-timer": "=1.0.3",
318
+ "phpunit/php-token-stream": "=1.1.4",
319
+ "symfony/yaml": ">=2.1.0@stable",
320
+ "xrstf/composer-php52": "1.*"
321
+ },
322
+ "bin": [
323
+ "composer/bin/phpunit-php52"
324
+ ],
325
+ "type": "library",
326
+ "autoload": {
327
+ "files": [
328
+ "PHPUnit/Autoload.php"
329
+ ]
330
+ },
331
+ "include-path": [
332
+ "",
333
+ "../../symfony/yaml/"
334
+ ],
335
+ "scripts": {
336
+ "post-install-cmd": [
337
+ "xrstf\\Composer52\\Generator::onPostInstallCmd"
338
+ ],
339
+ "post-update-cmd": [
340
+ "xrstf\\Composer52\\Generator::onPostInstallCmd"
341
+ ],
342
+ "post-autoload-dump": [
343
+ "xrstf\\Composer52\\Generator::onPostInstallCmd"
344
+ ]
345
+ },
346
+ "time": "2019-06-23T16:06:23+00:00"
347
+ },
348
+ {
349
+ "name": "symfony/deprecation-contracts",
350
+ "version": "dev-main",
351
+ "source": {
352
+ "type": "git",
353
+ "url": "https://github.com/symfony/deprecation-contracts.git",
354
+ "reference": "be5a36670fd7ccb6f6e03d9c9bd7345e2a9a8515"
355
+ },
356
+ "dist": {
357
+ "type": "zip",
358
+ "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/be5a36670fd7ccb6f6e03d9c9bd7345e2a9a8515",
359
+ "reference": "be5a36670fd7ccb6f6e03d9c9bd7345e2a9a8515",
360
+ "shasum": ""
361
+ },
362
+ "require": {
363
+ "php": ">=7.1"
364
+ },
365
+ "type": "library",
366
+ "extra": {
367
+ "branch-version": "2.3",
368
+ "branch-alias": {
369
+ "dev-main": "2.3-dev"
370
+ },
371
+ "thanks": {
372
+ "name": "symfony/contracts",
373
+ "url": "https://github.com/symfony/contracts"
374
+ }
375
+ },
376
+ "autoload": {
377
+ "files": [
378
+ "function.php"
379
+ ]
380
+ },
381
+ "notification-url": "https://packagist.org/downloads/",
382
+ "license": [
383
+ "MIT"
384
+ ],
385
+ "authors": [
386
+ {
387
+ "name": "Nicolas Grekas",
388
+ "email": "p@tchwork.com"
389
+ },
390
+ {
391
+ "name": "Symfony Community",
392
+ "homepage": "https://symfony.com/contributors"
393
+ }
394
+ ],
395
+ "description": "A generic function and convention to trigger deprecation notices",
396
+ "homepage": "https://symfony.com",
397
+ "time": "2020-10-14T17:08:19+00:00"
398
+ },
399
+ {
400
+ "name": "symfony/polyfill-ctype",
401
+ "version": "dev-main",
402
+ "source": {
403
+ "type": "git",
404
+ "url": "https://github.com/symfony/polyfill-ctype.git",
405
+ "reference": "325e20642232b66e3f140a76f795b58b50a08787"
406
+ },
407
+ "dist": {
408
+ "type": "zip",
409
+ "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/325e20642232b66e3f140a76f795b58b50a08787",
410
+ "reference": "325e20642232b66e3f140a76f795b58b50a08787",
411
+ "shasum": ""
412
+ },
413
+ "require": {
414
+ "php": ">=5.3.3"
415
+ },
416
+ "suggest": {
417
+ "ext-ctype": "For best performance"
418
+ },
419
+ "type": "library",
420
+ "extra": {
421
+ "branch-alias": {
422
+ "dev-main": "1.19-dev"
423
+ },
424
+ "thanks": {
425
+ "name": "symfony/polyfill",
426
+ "url": "https://github.com/symfony/polyfill"
427
+ }
428
+ },
429
+ "autoload": {
430
+ "psr-4": {
431
+ "Symfony\\Polyfill\\Ctype\\": ""
432
+ },
433
+ "files": [
434
+ "bootstrap.php"
435
+ ]
436
+ },
437
+ "notification-url": "https://packagist.org/downloads/",
438
+ "license": [
439
+ "MIT"
440
+ ],
441
+ "authors": [
442
+ {
443
+ "name": "Gert de Pagter",
444
+ "email": "BackEndTea@gmail.com"
445
+ },
446
+ {
447
+ "name": "Symfony Community",
448
+ "homepage": "https://symfony.com/contributors"
449
+ }
450
+ ],
451
+ "description": "Symfony polyfill for ctype functions",
452
+ "homepage": "https://symfony.com",
453
+ "keywords": [
454
+ "compatibility",
455
+ "ctype",
456
+ "polyfill",
457
+ "portable"
458
+ ],
459
+ "time": "2020-10-21T09:57:48+00:00"
460
+ },
461
+ {
462
+ "name": "symfony/yaml",
463
+ "version": "5.x-dev",
464
+ "source": {
465
+ "type": "git",
466
+ "url": "https://github.com/symfony/yaml.git",
467
+ "reference": "28ab1c87ffd653dc77e84581fed890c65dcafc19"
468
+ },
469
+ "dist": {
470
+ "type": "zip",
471
+ "url": "https://api.github.com/repos/symfony/yaml/zipball/28ab1c87ffd653dc77e84581fed890c65dcafc19",
472
+ "reference": "28ab1c87ffd653dc77e84581fed890c65dcafc19",
473
+ "shasum": ""
474
+ },
475
+ "require": {
476
+ "php": ">=7.2.5",
477
+ "symfony/deprecation-contracts": "^2.1",
478
+ "symfony/polyfill-ctype": "~1.8"
479
+ },
480
+ "conflict": {
481
+ "symfony/console": "<4.4"
482
+ },
483
+ "require-dev": {
484
+ "symfony/console": "^4.4|^5.0"
485
+ },
486
+ "suggest": {
487
+ "symfony/console": "For validating YAML files using the lint command"
488
+ },
489
+ "bin": [
490
+ "Resources/bin/yaml-lint"
491
+ ],
492
+ "type": "library",
493
+ "extra": {
494
+ "branch-version": "5.2"
495
+ },
496
+ "autoload": {
497
+ "psr-4": {
498
+ "Symfony\\Component\\Yaml\\": ""
499
+ },
500
+ "exclude-from-classmap": [
501
+ "/Tests/"
502
+ ]
503
+ },
504
+ "notification-url": "https://packagist.org/downloads/",
505
+ "license": [
506
+ "MIT"
507
+ ],
508
+ "authors": [
509
+ {
510
+ "name": "Fabien Potencier",
511
+ "email": "fabien@symfony.com"
512
+ },
513
+ {
514
+ "name": "Symfony Community",
515
+ "homepage": "https://symfony.com/contributors"
516
+ }
517
+ ],
518
+ "description": "Symfony Yaml Component",
519
+ "homepage": "https://symfony.com",
520
+ "time": "2020-10-14T17:08:19+00:00"
521
+ }
522
+ ],
523
+ "aliases": [],
524
+ "minimum-stability": "dev",
525
+ "stability-flags": {
526
+ "phpunit/phpunit-php52": 20,
527
+ "phpunit/phpunit-mock-objects-php52": 20
528
+ },
529
+ "prefer-stable": false,
530
+ "prefer-lowest": false,
531
+ "platform": {
532
+ "php": ">=5.2"
533
+ },
534
+ "platform-dev": []
535
+ }
vendor/lucatume/di52/makefile ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ php52 = /Applications/Mamp/bin/php/php5.2.17/bin/php
2
+ benchmarksFolder = /Users/Luca/Repos/php-dependency-injection-benchmarks
3
+
4
+ test:
5
+ docker run --rm \
6
+ -v "${CURDIR}:/project" \
7
+ --entrypoint /project/vendor/bin/phpunit-php52 \
8
+ tommylau/php-5.2 \
9
+ --bootstrap /project/tests/bootstrap.php \
10
+ /project/tests/52-compat
11
+ vendor/bin/phpunit-php52 -v
12
+
13
+ benchmark:
14
+ cd $(benchmarksFolder); \
15
+ php test1-5_runner.php; \
16
+ ls -p -t ./results/test1-5_results-*.html | head -1 | xargs open;
17
+
18
+ benchmark6:
19
+ cd $(benchmarksFolder); \
20
+ php test6_runner.php; \
21
+ ls -p -t ./results/test6_results-*.html | head -1 | xargs open;
22
+
23
+ cover:
24
+ vendor/bin/phpunit-php52 --coverage-html ./tests/coverage tests
25
+ open ./tests/coverage/index.html
26
+
27
+ lint_52:
28
+ docker run --rm -v "${CURDIR}:/project" --entrypoint php tommylau/php-5.2 -l /project/src/tad/DI52/Container.php
29
+ docker run --rm -v "${CURDIR}:/project" --entrypoint php tommylau/php-5.2 -l /project/src/tad/DI52/ContainerInterface.php
30
+ docker run --rm -v "${CURDIR}:/project" --entrypoint php tommylau/php-5.2 -l /project/src/tad/DI52/ProtectedValue.php
31
+ docker run --rm -v "${CURDIR}:/project" --entrypoint php tommylau/php-5.2 -l /project/src/tad/DI52/ServiceProviderInterface.php
32
+
33
+ lint_53:
34
+ docker run --rm -v "${CURDIR}:/project" cespi/php-5.3 php -l /project/src/tad/DI52/closuresSupport.php
35
+ docker run --rm -v "${CURDIR}:/project" cespi/php-5.3 php -l /project/src/tad/DI52/Container.php
36
+ docker run --rm -v "${CURDIR}:/project" cespi/php-5.3 php -l /project/src/tad/DI52/ContainerInterface.php
37
+ docker run --rm -v "${CURDIR}:/project" cespi/php-5.3 php -l /project/src/tad/DI52/ProtectedValue.php
38
+ docker run --rm -v "${CURDIR}:/project" cespi/php-5.3 php -l /project/src/tad/DI52/ServiceProviderInterface.php
vendor/lucatume/di52/phpunit.xml ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <phpunit bootstrap='tests/bootstrap.php'
2
+ colors='true'>
3
+ <testsuites>
4
+ <testsuite name='All'>
5
+ <directory suffix="Test.php">tests/52-compat</directory>
6
+ <directory suffix="Test.php" phpVersion="5.3.0" phpVersionOperator=">=">tests/53-above</directory>
7
+ </testsuite>
8
+ </testsuites>
9
+ <filter>
10
+ <blacklist>
11
+ <directory suffix=".php">vendor</directory>
12
+ </blacklist>
13
+ <whitelist addUncoveredFilesFromWhitelist="true">
14
+ <directory suffix=".php">src</directory>
15
+ </whitelist>
16
+ </filter>
17
+ </phpunit>
vendor/lucatume/di52/src/tad/DI52/Container.php ADDED
@@ -0,0 +1,906 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class tad_DI52_Container implements ArrayAccess {
4
+
5
+ /**
6
+ * @var boolean
7
+ */
8
+ protected $useClosures;
9
+
10
+ /**
11
+ * @var array
12
+ */
13
+ protected $callbacks = array();
14
+
15
+ /**
16
+ * @var array
17
+ */
18
+ protected $protected = array();
19
+
20
+ /**
21
+ * @var array
22
+ */
23
+ protected $strings = array();
24
+
25
+ /**
26
+ * @var array
27
+ */
28
+ protected $objects = array();
29
+
30
+ /**
31
+ * @var array
32
+ */
33
+ protected $callables = array();
34
+
35
+ /**
36
+ * @var array
37
+ */
38
+ protected $singletons = array();
39
+
40
+ /**
41
+ * @var array
42
+ */
43
+ protected $deferred = array();
44
+
45
+ /**
46
+ * @var array
47
+ */
48
+ protected $chains = array();
49
+
50
+ /**
51
+ * @var array
52
+ */
53
+ protected $reflections = array();
54
+
55
+ /**
56
+ * @var array
57
+ */
58
+ protected $afterbuild = array();
59
+
60
+ /**
61
+ * @var string
62
+ */
63
+ protected $resolving = '';
64
+
65
+ /**
66
+ * @var array
67
+ */
68
+ protected $tags = array();
69
+
70
+ /**
71
+ * @var array
72
+ */
73
+ protected $bootable = array();
74
+
75
+ /**
76
+ * @var array
77
+ */
78
+ protected $contexts = array();
79
+
80
+ /**
81
+ * @var string
82
+ */
83
+ protected $bindingFor;
84
+
85
+ /**
86
+ * @var string
87
+ */
88
+ protected $neededImplementation;
89
+
90
+ /**
91
+ * @var string
92
+ */
93
+ protected $id;
94
+
95
+ /**
96
+ * @var array
97
+ */
98
+ protected $bindings = array();
99
+
100
+ /**
101
+ * @var array
102
+ */
103
+ protected $instanceCallbacks = array();
104
+
105
+ /**
106
+ * @var array
107
+ */
108
+ public $__instanceCallbackArgs = array();
109
+
110
+ /**
111
+ * @var array
112
+ */
113
+ protected $dependants = array();
114
+
115
+ /**
116
+ * tad_DI52_Container constructor.
117
+ */
118
+ public function __construct() {
119
+ $this->id = uniqid(rand(1, 9999));
120
+ $GLOBALS['__container_' . $this->id] = $this;
121
+ }
122
+
123
+ /**
124
+ * Sets a variable on the container.
125
+ *
126
+ * Variables will be evaluated before storing, to protect a variable from the process, e.g. storing a closure, use
127
+ * the `protect` method:
128
+ *
129
+ * $container->setVar('foo', $container->protect($f));
130
+ *
131
+ * @see tad_DI52_Container::protect()
132
+ *
133
+ * @param string $key The alias the container will use to reference the variable.
134
+ * @param mixed $value The variable value.
135
+ */
136
+ public function setVar($key, $value) {
137
+ $this->offsetSet($key, $value);
138
+ }
139
+
140
+ /**
141
+ * Sets a variable on the container using the ArrayAccess API.
142
+ *
143
+ * When using the container as an array bindings will be bound as singletons; the two functions below are
144
+ * equivalent:
145
+ *
146
+ * $container->singleton('foo','ClassOne');
147
+ * $container['foo'] = 'ClassOne';
148
+ *
149
+ * Variables will be evaluated before storing, to protect a variable from the process, e.g. storing a closure, use
150
+ * the `protect` method:
151
+ *
152
+ * $container['foo'] = $container->protect($f));
153
+ *
154
+ * @see tad_DI52_Container::protect()
155
+ * @see tad_DI52_Container::singleton()
156
+ *
157
+ * @param string $key The alias the container will use to reference the variable.
158
+ * @param mixed $value The variable value.
159
+ *
160
+ * @return void
161
+ * @since 5.0.0
162
+ */
163
+ public function offsetSet($offset, $value) {
164
+ if ($value instanceof tad_DI52_ProtectedValue) {
165
+ $this->protected[$offset] = true;
166
+ $value = $value->getValue();
167
+ }
168
+
169
+ $this->offsetUnset($offset);
170
+
171
+ $this->singletons[$offset] = $offset;
172
+
173
+ if (isset($this->protected[$offset])) {
174
+ $this->strings[$offset] = $value;
175
+ return;
176
+ }
177
+
178
+ if (is_callable($value)) {
179
+ $this->callables[$offset] = $value;
180
+ return;
181
+ }
182
+
183
+ if (is_object($value)) {
184
+ $this->objects[$offset] = $value;
185
+ return;
186
+ }
187
+
188
+ $this->strings[$offset] = $value;
189
+ }
190
+
191
+ /**
192
+ * Returns a variable stored in the container.
193
+ *
194
+ * If the variable is a binding then the binding will be resolved before returning it.
195
+ *
196
+ * @see tad_DI52_Container::make
197
+ *
198
+ * @param string $key The alias of the variable or binding to fetch.
199
+ *
200
+ * @return mixed The variable value or the resolved binding.
201
+ */
202
+ public function getVar($key) {
203
+ try {
204
+ return $this->offsetGet($key);
205
+ } catch (RuntimeException $e) {
206
+ return null;
207
+ }
208
+ }
209
+
210
+ /**
211
+ * Retrieves a variable or a binding from the database.
212
+ *
213
+ * If the offset is bound to an implementation then it will be resolved before returning it.
214
+ * * @param string $offset
215
+ *
216
+ * @return mixed
217
+ */
218
+ public function offsetGet($offset) {
219
+ if (is_object($offset)) {
220
+ return is_callable($offset) ? call_user_func($offset, $this) : $offset;
221
+ }
222
+
223
+ if (isset($this->objects[$offset])) {
224
+ return $this->objects[$offset];
225
+ }
226
+
227
+ if (isset($this->strings[$offset])) {
228
+ if (isset($this->protected[$offset])) {
229
+ return $this->strings[$offset];
230
+ }
231
+ if (is_string($this->strings[$offset]) && class_exists($this->strings[$offset])) {
232
+ $instance = $this->make($this->strings[$offset]);
233
+ $this->objects[$offset] = $instance;
234
+ return $instance;
235
+ }
236
+ return $this->strings[$offset];
237
+ }
238
+
239
+ if (isset($this->callables[$offset])) {
240
+ return call_user_func($this->callables[$offset], $this);
241
+ }
242
+
243
+ if (is_string($offset) && class_exists($offset)) {
244
+ return $this->resolve($offset);
245
+ }
246
+
247
+ throw new RuntimeException("Nothing is bound to the key '{$offset}'");
248
+ }
249
+
250
+ /**
251
+ * Returns an instance of the class or object bound to an interface, class or string slug if any, else it will try
252
+ * to automagically resolve the object to a usable instance.
253
+ *
254
+ * If the implementation has been bound as singleton using the `singleton` method
255
+ * or the ArrayAccess API then the implementation will be resolved just on the first request.
256
+ *
257
+ * @param string $classOrInterface A fully qualified class or interface name.
258
+ *
259
+ * @return mixed
260
+ */
261
+ public function make($classOrInterface) {
262
+ if (is_object($classOrInterface)) {
263
+ return $classOrInterface;
264
+ }
265
+
266
+ if (!isset($this->bindings[$classOrInterface])) {
267
+ try {
268
+ return $this->build($classOrInterface, true);
269
+ } catch (Exception $e) {
270
+ // continue... we tried an early resolution
271
+ }
272
+ }
273
+
274
+ if (isset($this->objects[$classOrInterface])) {
275
+ return $this->objects[$classOrInterface];
276
+ }
277
+
278
+ if (isset($this->callables[$classOrInterface])) {
279
+ $resolved = call_user_func($this->callables[$classOrInterface], $this);
280
+ } else {
281
+ $resolved = $this->resolve($classOrInterface);
282
+ }
283
+
284
+ if (isset($this->singletons[$classOrInterface])) {
285
+ $this->objects[$classOrInterface] = $resolved;
286
+ }
287
+
288
+ return $resolved;
289
+ }
290
+
291
+ /**
292
+ * Returns an instance of the class or object bound to an interface, class or string slug if any, else it will try
293
+ * to automagically resolve the object to a usable instance.
294
+ *
295
+ * Differently from the `make` method singleton implementations will be be ignored.
296
+ *
297
+ * @param string $classOrInterface
298
+ *
299
+ * @return array|mixed
300
+ */
301
+ protected function resolve($classOrInterface) {
302
+ $original = $this->resolving;
303
+ $this->resolving = $classOrInterface;
304
+
305
+ try {
306
+ if (isset($this->deferred[$classOrInterface])) {
307
+ /** @var tad_DI52_ServiceProviderInterface $provider */
308
+ $provider = $this->deferred[$classOrInterface];
309
+ $provider->register();
310
+ }
311
+
312
+ if (!isset($this->strings[$classOrInterface])) {
313
+ try {
314
+ $instance = $this->build($classOrInterface);
315
+ } catch (Exception $e) {
316
+ if ( $e instanceof ReflectionException ) {
317
+ throw $e;
318
+ }
319
+
320
+ throw new RuntimeException("'{$classOrInterface}' is not a bound alias or an existing class.");
321
+ }
322
+ } else {
323
+ if (isset($this->chains[$classOrInterface])) {
324
+ $instance = $this->buildFromChain($classOrInterface);
325
+ } else {
326
+ $instance = $this->build($this->strings[$classOrInterface]);
327
+ }
328
+ }
329
+
330
+ if (isset($this->afterbuild[$classOrInterface])) {
331
+ foreach ($this->afterbuild[$classOrInterface] as $method) {
332
+ call_user_func(array($instance, $method));
333
+ }
334
+ }
335
+
336
+ $this->resolving = $original;
337
+
338
+ return $instance;
339
+ } catch (Exception $e) {
340
+ preg_match('/Error while making/', $e->getMessage(), $matches);
341
+ if (count($matches)) {
342
+ // @codeCoverageIgnoreStart
343
+ $divider = "\n\t => ";
344
+ $prefix = ' ';
345
+ // @codeCoverageIgnoreEnd
346
+ } else {
347
+ $divider = ':';
348
+ $prefix = 'Error while making ';
349
+ }
350
+ $message = "{$prefix} '{$classOrInterface}'{$divider} " . $e->getMessage();
351
+
352
+ throw new RuntimeException($message);
353
+ }
354
+ }
355
+
356
+ /**
357
+ * @param $implementation
358
+ * @param bool $resolving
359
+ *
360
+ * @return mixed
361
+ */
362
+ protected function build($implementation, $resolving = false) {
363
+ $this->resolving = $resolving ? $implementation : $this->resolving;
364
+ if (!isset($this->reflections[$implementation])) {
365
+ $this->reflections[$implementation] = new ReflectionClass($implementation);
366
+ }
367
+
368
+ /** @var ReflectionClass $classReflection */
369
+ $classReflection = $this->reflections[$implementation];
370
+ $constructor = $classReflection->getConstructor();
371
+ $parameters = empty($constructor) ? array() : $constructor->getParameters();
372
+ $builtParams = array_map(array($this, '_getParameter'), $parameters);
373
+
374
+ $instance = !empty($builtParams) ?
375
+ $this->reflections[$implementation]->newInstanceArgs($builtParams)
376
+ : new $implementation;
377
+
378
+ return $instance;
379
+ }
380
+
381
+ /**
382
+ * @param string $classOrInterface
383
+ *
384
+ * @return mixed
385
+ */
386
+ protected function buildFromChain($classOrInterface) {
387
+ $chainElements = $this->chains[$classOrInterface];
388
+ unset($this->chains[$classOrInterface]);
389
+
390
+ $instance = null;
391
+ foreach (array_reverse($chainElements) as $element) {
392
+ $instance = $this->resolve($element);
393
+ $this->objects[$classOrInterface] = $instance;
394
+ }
395
+
396
+ $this->chains[$classOrInterface] = $chainElements;
397
+ unset($this->objects[$classOrInterface]);
398
+
399
+ return $instance;
400
+ }
401
+
402
+ /**
403
+ * Tags an array of implementations bindings for later retrieval.
404
+ *
405
+ * The implementations can also reference interfaces, classes or string slugs.
406
+ * Example:
407
+ *
408
+ * $container->tag(['Posts', 'Users', 'Comments'], 'endpoints');
409
+ *
410
+ * @see tad_DI52_Container::tagged()
411
+ *
412
+ * @param array $implementationsArray
413
+ * @param string $tag
414
+ */
415
+ public function tag(array $implementationsArray, $tag) {
416
+ $this->tags[$tag] = $implementationsArray;
417
+ }
418
+
419
+ /**
420
+ * Retrieves an array of bound implementations resolving them.
421
+ *
422
+ * The array of implementations should be bound using the `tag` method:
423
+ *
424
+ * $container->tag(['Posts', 'Users', 'Comments'], 'endpoints');
425
+ * foreach($container->tagged('endpoints') as $endpoint){
426
+ * $endpoint->register();
427
+ * }
428
+ *
429
+ * @see tad_DI52_Container::tag()
430
+ *
431
+ * @param string $tag
432
+ *
433
+ * @return array An array of resolved bound implementations.
434
+ */
435
+ public function tagged($tag) {
436
+ if ($this->hasTag($tag)) {
437
+ return array_map(array($this, 'offsetGet'), $this->tags[$tag]);
438
+ }
439
+
440
+ throw new RuntimeException("Nothing has been tagged {$tag}.");
441
+ }
442
+
443
+ /**
444
+ * Checks whether a tag group exists in the container.
445
+ *
446
+ * @see tad_DI52_Container::tag()
447
+ *
448
+ * @param string $tag
449
+ *
450
+ * @return bool
451
+ */
452
+ public function hasTag($tag) {
453
+ return isset($this->tags[$tag]);
454
+ }
455
+
456
+ /**
457
+ * Registers a service provider implementation.
458
+ *
459
+ * The `register` method will be called immediately on the service provider.
460
+ *
461
+ * If the provider overloads the `isDeferred` method returning a truthy value then the `register` method will be
462
+ * called only if one of the implementations provided by the provider is requested. The container defines which
463
+ * implementations is offering overloading the `provides` method; the method should return an array of provided
464
+ * implementations.
465
+ *
466
+ * If a provider overloads the `boot` method that method will be called when the `boot` method is called on the
467
+ * container itself.
468
+ *
469
+ * @see tad_DI52_ServiceProviderInterface::register()
470
+ * @see tad_DI52_ServiceProviderInterface::isDeferred()
471
+ * @see tad_DI52_ServiceProviderInterface::provides()
472
+ * @see tad_DI52_ServiceProviderInterface::boot()
473
+ *
474
+ * @param string $serviceProviderClass
475
+ */
476
+ public function register($serviceProviderClass) {
477
+ /** @var tad_DI52_ServiceProviderInterface $provider */
478
+ $provider = new $serviceProviderClass($this);
479
+ if (!$provider->isDeferred()) {
480
+ $provider->register();
481
+ } else {
482
+ $provided = $provider->provides();
483
+
484
+ $count = count($provided);
485
+ if ($count === 0) {
486
+ throw new RuntimeException("Service provider '{$serviceProviderClass}' is marked as deferred but is not providing any implementation.");
487
+ }
488
+
489
+ $this->bindings = array_merge($this->bindings, array_combine($provided, $provided));
490
+ $this->deferred = array_merge($this->deferred,
491
+ array_combine($provided, array_fill(0, $count, $provider)));
492
+ }
493
+ $ref = new ReflectionMethod($provider, 'boot');
494
+ $requiresBoot = ($ref->getDeclaringClass()->getName() === get_class($provider));
495
+ if ($requiresBoot) {
496
+ $this->bootable[] = $provider;
497
+ }
498
+ }
499
+
500
+ /**
501
+ * Boots up the application calling the `boot` method of each registered service provider.
502
+ *
503
+ * If there are bootable providers (providers overloading the `boot` method) then the `boot` method will be
504
+ * called on each bootable provider.
505
+ *
506
+ * @see tad_DI52_ServiceProviderInterface::boot()
507
+ */
508
+ public function boot() {
509
+ if (!empty($this->bootable)) {
510
+ foreach ($this->bootable as $provider) {
511
+ /** @var tad_DI52_ServiceProviderInterface $provider */
512
+ $provider->boot();
513
+ }
514
+ }
515
+ }
516
+
517
+ /**
518
+ * Checks whether an interface, class or string slug has been bound in the container.
519
+ *
520
+ * @param string $classOrInterface
521
+ *
522
+ * @return bool
523
+ */
524
+ public function isBound($classOrInterface) {
525
+ return $this->offsetExists($classOrInterface);
526
+ }
527
+
528
+ /**
529
+ * Whether a offset exists
530
+ *
531
+ * @see isBound
532
+ *
533
+ * @link http://php.net/manual/en/arrayaccess.offsetexists.php
534
+ *
535
+ * @param mixed $offset <p>
536
+ * An offset to check for.
537
+ * </p>
538
+ *
539
+ * @return boolean true on success or false on failure.
540
+ * </p>
541
+ * <p>
542
+ * The return value will be casted to boolean if non-boolean was returned.
543
+ * @since 5.0.0
544
+ */
545
+ public function offsetExists($offset) {
546
+ return isset($this->bindings[$offset]);
547
+ }
548
+
549
+ /**
550
+ * Binds a class, interface or string slug to a chain of implementations decorating a base
551
+ * object; the chain will be lazily resolved only on the first call.
552
+ *
553
+ * The base decorated object must be the last element of the array.
554
+ *
555
+ * @param string $classOrInterface The class, interface or slug the decorator chain should be bound to.
556
+ * @param array $decorators An array of implementations that decorate an object.
557
+ * @param array $afterBuildMethods An array of methods that should be called on the instance after it has been
558
+ * built; the methods should not require any argument.
559
+ */
560
+ public function singletonDecorators($classOrInterface, $decorators, array $afterBuildMethods = null) {
561
+ $this->bindDecorators($classOrInterface, $decorators, $afterBuildMethods);
562
+ $this->singletons[$classOrInterface] = $classOrInterface;
563
+ }
564
+
565
+ /**
566
+ * Binds a class, interface or string slug to to a chain of implementations decorating a
567
+ * base object.
568
+ *
569
+ * The base decorated object must be the last element of the array.
570
+ *
571
+ * @param string $classOrInterface The class, interface or slug the decorator chain should be bound to.
572
+ * @param array $decorators An array of implementations that decorate an object.
573
+ * @param array $afterBuildMethods An array of methods that should be called on the instance after it has been
574
+ * built; the methods should not require any argument.
575
+ */
576
+ public function bindDecorators($classOrInterface, array $decorators, array $afterBuildMethods = null) {
577
+ $this->bindings[$classOrInterface] = $classOrInterface;
578
+ $this->strings[$classOrInterface] = $decorators;
579
+ $this->chains[$classOrInterface] = $decorators;
580
+
581
+ if (!empty($afterBuildMethods)) {
582
+ $base = end($decorators);
583
+ $this->afterbuild[$base] = $afterBuildMethods;
584
+ }
585
+ }
586
+
587
+ /**
588
+ * Offset to unset
589
+ *
590
+ * @link http://php.net/manual/en/arrayaccess.offsetunset.php
591
+ *
592
+ * @param mixed $offset <p>
593
+ * The offset to unset.
594
+ * </p>
595
+ *
596
+ * @return void
597
+ * @since 5.0.0
598
+ */
599
+ public function offsetUnset($offset) {
600
+ unset(
601
+ $this->strings[$offset],
602
+ $this->singletons[$offset],
603
+ $this->objects[$offset],
604
+ $this->bindings[$offset],
605
+ $this->afterbuild[$offset],
606
+ $this->callables[$offset],
607
+ $this->contexts[$offset],
608
+ $this->tags[$offset],
609
+ $this->chains[$offset]
610
+ );
611
+ }
612
+
613
+ /**
614
+ * Starts the `when->needs->give` chain for a contextual binding.
615
+ *
616
+ * @param string $class The fully qualified name of the requesting class.
617
+ *
618
+ * Example:
619
+ *
620
+ * // any class requesting an implementation of `LoggerInterface` will receive this implementation...
621
+ * $container->singleton('LoggerInterface', 'FilesystemLogger');
622
+ * // but if the requesting class is `Worker` return another implementation
623
+ * $container->when('Worker')
624
+ * ->needs('LoggerInterface)
625
+ * ->give('RemoteLogger);
626
+ *
627
+ * @return tad_DI52_Container
628
+ */
629
+ public function when($class) {
630
+ $this->bindingFor = $class;
631
+
632
+ return $this;
633
+ }
634
+
635
+ /**
636
+ * Second step of the `when->needs->give` chain for a contextual binding.
637
+ *
638
+ * Example:
639
+ *
640
+ * // any class requesting an implementation of `LoggerInterface` will receive this implementation...
641
+ * $container->singleton('LoggerInterface', 'FilesystemLogger');
642
+ * // but if the requesting class is `Worker` return another implementation
643
+ * $container->when('Worker')
644
+ * ->needs('LoggerInterface)
645
+ * ->give('RemoteLogger);
646
+ *
647
+ * @param string $classOrInterface The class or interface needed by the class.
648
+ *
649
+ * @return tad_DI52_Container
650
+ */
651
+ public function needs($classOrInterface) {
652
+ $this->neededImplementation = $classOrInterface;
653
+ return $this;
654
+ }
655
+
656
+ /**
657
+ * Third step of the `when->needs->give` chain for a contextual binding.
658
+ *
659
+ * Example:
660
+ *
661
+ * // any class requesting an implementation of `LoggerInterface` will receive this implementation...
662
+ * $container->singleton('LoggerInterface', 'FilesystemLogger');
663
+ * // but if the requesting class is `Worker` return another implementation
664
+ * $container->when('Worker')
665
+ * ->needs('LoggerInterface)
666
+ * ->give('RemoteLogger);
667
+ *
668
+ * @param mixed $implementation The implementation specified
669
+ */
670
+ public function give($implementation) {
671
+ $this->bindings[$this->bindingFor] = $this->bindingFor;
672
+
673
+ $this->contexts[$this->neededImplementation] =
674
+ !empty($this->contexts[$this->neededImplementation]) ?
675
+ $this->contexts[$this->neededImplementation] : array();
676
+ $this->contexts[$this->neededImplementation][$this->bindingFor] = $implementation;
677
+ }
678
+
679
+ /**
680
+ * Protects a value from being resolved by the container.
681
+ *
682
+ * Example usage `$container['var'] = $container->protect(function(){return 'bar';});`
683
+ *
684
+ * @param mixed $value
685
+ */
686
+ public function protect($value) {
687
+ return new tad_DI52_ProtectedValue($value);
688
+ }
689
+
690
+ /**
691
+ * Binds an interface, a class or a string slug to an implementation.
692
+ *
693
+ * Existing implementations are replaced.
694
+ *
695
+ * @param string $classOrInterface A class or interface fully qualified name or a string slug.
696
+ * @param mixed $implementation The implementation that should be bound to the alias(es); can be a class name,
697
+ * an object or a closure.
698
+ * @param array $afterBuildMethods An array of methods that should be called on the built implementation after
699
+ * resolving it.
700
+ *
701
+ * @throws ReflectionException When binding a class that does not exist without defining an implementation.
702
+ * @throws InvalidArgumentException When binding a class that cannot be instantiated without defining an implementation.
703
+ */
704
+ public function bind($classOrInterface, $implementation = null, array $afterBuildMethods = null) {
705
+ if (is_null($implementation)) {
706
+ $reflection = new ReflectionClass($classOrInterface);
707
+ if (!$reflection->isInstantiable()) {
708
+ throw new InvalidArgumentException( sprintf('To bind a class in the Container without defining an implementation, the class must be instantiable. %s is not instantiable.', $classOrInterface) );
709
+ }
710
+ $implementation = $classOrInterface;
711
+ }
712
+
713
+ $this->offsetUnset($classOrInterface);
714
+
715
+ $this->bindings[$classOrInterface] = $classOrInterface;
716
+
717
+ if (is_callable($implementation)) {
718
+ $this->callables[$classOrInterface] = $implementation;
719
+ return;
720
+ }
721
+
722
+ if (is_object($implementation)) {
723
+ $this->objects[$classOrInterface] = $implementation;
724
+ return;
725
+ }
726
+
727
+ $this->strings[$classOrInterface] = $implementation;
728
+
729
+ if (!empty($afterBuildMethods)) {
730
+ $this->afterbuild[$classOrInterface] = $afterBuildMethods;
731
+ }
732
+ }
733
+
734
+ /**
735
+ * Binds an interface a class or a string slug to an implementation and will always return the same instance.
736
+ *
737
+ * @param string $classOrInterface A class or interface fully qualified name or a string slug.
738
+ * @param mixed $implementation The implementation that should be bound to the alias(es); can be a class name,
739
+ * an object or a closure.
740
+ * @param array $afterBuildMethods An array of methods that should be called on the built implementation after
741
+ * resolving it.
742
+ */
743
+ public function singleton($classOrInterface, $implementation = null, array $afterBuildMethods = null) {
744
+ $this->bind($classOrInterface, $implementation, $afterBuildMethods);
745
+
746
+ $this->singletons[$classOrInterface] = $classOrInterface;
747
+ }
748
+
749
+ /**
750
+ * Returns a lambda function suitable to use as a callback; when called the function will build the implementation
751
+ * bound to `$classOrInterface` and return the value of a call to `$method` method with the call arguments.
752
+ *
753
+ * @param string|object $classOrInterface A class or interface fully qualified name or a string slug.
754
+ * @param string $method The method that should be called on the resolved implementation with the
755
+ * specified array arguments.
756
+ *
757
+ * @return mixed The called method return value.
758
+ */
759
+ public function callback($classOrInterface, $method) {
760
+ $this->initClosuresSupport();
761
+
762
+ if (!is_string($method)) {
763
+ throw new RuntimeException('Callback method must be a string');
764
+ }
765
+
766
+ $classOrInterfaceName = is_object($classOrInterface) ? spl_object_hash($classOrInterface) : $classOrInterface;
767
+ $cacheKey = $classOrInterfaceName . '::' . $method;
768
+
769
+ if ( isset( $this->callbacks[ $cacheKey ] ) ) {
770
+ // Only return the existing callback if $classOrInterface was not an object (so it remains unique).
771
+ return $this->callbacks[ $cacheKey ];
772
+ }
773
+
774
+ if ($this->useClosures) {
775
+ $f = di52_callbackClosure($this, $classOrInterface, $method);
776
+ } else {
777
+ $classOrInterfaceName = is_object($classOrInterface) ? get_class($classOrInterface) : $classOrInterface;
778
+ // @codeCoverageIgnoreStart
779
+ if (is_object($classOrInterface) || is_callable($classOrInterface)) {
780
+ $objectId = uniqid(rand(1, 9999) . md5($classOrInterfaceName));
781
+ $this->bind($objectId, $classOrInterface);
782
+ $body = '$a = func_get_args();
783
+ global $__container_' . $this->id . ';
784
+ $c = $__container_' . $this->id . ';
785
+ $i = $c->make(\'' . $objectId . '\');
786
+ return call_user_func_array(array($i, \'' . $method . '\'),$a);';
787
+ } else {
788
+ $body = '$a = func_get_args();
789
+ global $__container_' . $this->id . ';
790
+ $c = $__container_' . $this->id . ';
791
+ $i = $c->make(\'' . $classOrInterfaceName . '\');
792
+ return call_user_func_array(array($i, \'' . $method . '\'),$a);';
793
+ }
794
+ $f = create_function('', $body);
795
+ // @codeCoverageIgnoreEnd
796
+ }
797
+
798
+ $this->callbacks[ $cacheKey ] = $f;
799
+
800
+ return $f;
801
+ }
802
+
803
+ public function _getParameter(ReflectionParameter $parameter) {
804
+ $class = $parameter->getClass();
805
+
806
+ if (null === $class) {
807
+ if (!$parameter->isDefaultValueAvailable()) {
808
+ throw new ReflectionException("parameter '{$parameter->name}' of '{$this->resolving}::__construct' does not have a default value.");
809
+ }
810
+ return $parameter->getDefaultValue();
811
+ }
812
+
813
+ $parameterClass = $parameter->getClass()->getName();
814
+
815
+ if (!$this->isBound($parameterClass) && !$parameter->getClass()->isInstantiable()) {
816
+ if (!$parameter->isDefaultValueAvailable()) {
817
+ throw new ReflectionException("parameter '{$parameter->name}' of '{$this->resolving}::__construct' does not have a default value.");
818
+ }
819
+ return $parameter->getDefaultValue();
820
+ }
821
+
822
+ if (!isset($this->dependants[$parameterClass])) {
823
+ $this->dependants[$parameterClass] = array($this->resolving);
824
+ } else {
825
+ $this->dependants[$parameterClass][] = $this->resolving;
826
+ }
827
+
828
+ return isset($this->contexts[$parameterClass][$this->resolving]) ?
829
+ $this->offsetGet($this->contexts[$parameterClass][$this->resolving])
830
+ : $this->offsetGet($parameterClass);
831
+ }
832
+
833
+ /**
834
+ * Returns a callable object that will build an instance of the specified class using the
835
+ * specified arguments when called.
836
+ *
837
+ * The callable will be a closure on PHP 5.3+ or a lambda function on PHP 5.2.
838
+ *
839
+ * @param string $classOrInterface The fully qualified name of a class or an interface.
840
+ * @param array $args An array of arguments that should be used to build the instancee;
841
+ * note that any argument will be resolved using the container itself and bindings
842
+ * will apply.
843
+ *
844
+ * @return callable A callable function that will return an instance of the specified class when
845
+ * called.
846
+ */
847
+ public function instance($classOrInterface, array $args = array()) {
848
+ $this->initClosuresSupport();
849
+
850
+ $classOrInterfaceName = is_object($classOrInterface) ? get_class($classOrInterface) : $classOrInterface;
851
+
852
+ $instanceId = md5($classOrInterfaceName . '::' . serialize($args));
853
+ if (!isset($this->instanceCallbacks[$instanceId])) {
854
+ $this->__instanceCallbackArgs[$instanceId] = $args;
855
+
856
+ if ($this->useClosures) {
857
+ $f = di52_instanceClosure($this, $classOrInterface, $args);
858
+ } else {
859
+ // @codeCoverageIgnoreStart
860
+ if (is_object($classOrInterface) || is_callable($classOrInterface)) {
861
+ $objectId = uniqid(rand(1, 9999) . md5($classOrInterfaceName));
862
+ $this->bind($objectId, $classOrInterface);
863
+ $body = "global \$__container_{$this->id};
864
+ \$c = \$__container_{$this->id};
865
+ return \$c->make('{$objectId}'); ";
866
+ } else {
867
+ $body = "global \$__container_{$this->id};
868
+ \$c = \$__container_{$this->id};
869
+ \$r = new ReflectionClass('{$classOrInterface}');
870
+ \$vars = \$c->__instanceCallbackArgs['{$instanceId}'];
871
+ \$constructor = \$r->getConstructor();
872
+ if (null === \$constructor || empty(\$vars)) {
873
+ return \$c->make('{$classOrInterface}');
874
+ }
875
+ \$args = array();
876
+ foreach (\$vars as \$var) {
877
+ try {
878
+ \$args[] = \$c->make(\$var);
879
+ } catch (RuntimeException \$e) {
880
+ \$args[] = \$var;
881
+ }
882
+ }
883
+ return \$r->newInstanceArgs(\$args);";
884
+ }
885
+ $f = create_function('', $body);
886
+ // @codeCoverageIgnoreEnd
887
+ }
888
+
889
+ $this->instanceCallbacks[$instanceId] = $f;
890
+ }
891
+
892
+ return $this->instanceCallbacks[$instanceId];
893
+ }
894
+
895
+ /**
896
+ * Initializes the closure support on PHP 5.3+.
897
+ */
898
+ protected function initClosuresSupport() {
899
+ if (null === $this->useClosures) {
900
+ $this->useClosures = version_compare(PHP_VERSION, '5.3.0', '>=');
901
+ if ($this->useClosures) {
902
+ require_once dirname(__FILE__) . '/closuresSupport.php';
903
+ }
904
+ }
905
+ }
906
+ }
vendor/lucatume/di52/src/tad/DI52/ContainerInterface.php ADDED
@@ -0,0 +1,181 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Interface tad_DI52_ContainerInterface
5
+ *
6
+ * The API supported by the container.
7
+ */
8
+ interface tad_DI52_ContainerInterface
9
+ {
10
+ /**
11
+ * @param string $key
12
+ * @param mixed $value
13
+ */
14
+ public function setVar($key, $value);
15
+
16
+ /**
17
+ * @param string $key
18
+ *
19
+ * @return mixed
20
+ */
21
+ public function getVar($key);
22
+
23
+ /**
24
+ * Binds an interface or class to an implementation.
25
+ *
26
+ * @param string $classOrInterface An alias or an array of implementation aliases
27
+ * @param mixed $implementation
28
+ * @param array $afterBuildMethods
29
+ */
30
+ public function bind($classOrInterface, $implementation, array $afterBuildMethods = null);
31
+
32
+ /**
33
+ * Binds an interface or class to an implementation replacing an existing implementation.
34
+ *
35
+ * @param string $classOrInterface
36
+ * @param string $implementation
37
+ * @param array $afterBuildMethods
38
+ */
39
+ public function replaceBind($classOrInterface, $implementation, array $afterBuildMethods = null);
40
+
41
+ /**
42
+ * Returns an instance of the class or object bound to an interface.
43
+ *
44
+ * @param string $classOrInterface A fully qualified class or interface name.
45
+ * @return mixed
46
+ */
47
+ public function make($classOrInterface);
48
+
49
+ /**
50
+ * Binds an interface or class to an implementation and will always return the same instance.
51
+ *
52
+ * @param string $classOrInterface
53
+ * @param string $implementation
54
+ * @param array $afterBuildMethods
55
+ */
56
+ public function singleton($classOrInterface, $implementation, array $afterBuildMethods = null);
57
+
58
+ /**
59
+ * Binds an interface or class to an implementation and will always return the same instance replacing an
60
+ * existing singleton binding.
61
+ *
62
+ * @param string $classOrInterface
63
+ * @param string $implementation
64
+ * @param array $afterBuildMethods
65
+ */
66
+ public function replaceSingleton($classOrInterface, $implementation, array $afterBuildMethods = null);
67
+
68
+ /**
69
+ * Tags an array of implementation bindings.
70
+ *
71
+ * @param array $implementationsArray
72
+ * @param string $tag
73
+ */
74
+ public function tag(array $implementationsArray, $tag);
75
+
76
+ /**
77
+ * Retrieves an array of bound implementations resolving them.
78
+ *
79
+ * @param string $tag
80
+ * @return array An array of resolved bound implementations.
81
+ */
82
+ public function tagged($tag);
83
+
84
+ /**
85
+ * Registers a service provider implementation.
86
+ *
87
+ * @param string $serviceProviderClass
88
+ */
89
+ public function register($serviceProviderClass);
90
+
91
+ /**
92
+ * Boots up the application calling the `boot` method of each registered service provider.
93
+ */
94
+ public function boot();
95
+
96
+ /**
97
+ * Checks whether if an interface or class has been bound to a concrete implementation.
98
+ *
99
+ * @param string $classOrInterface
100
+ * @return bool
101
+ */
102
+ public function isBound($classOrInterface);
103
+
104
+ /**
105
+ * Checks whether a tag group exists in the container.
106
+ *
107
+ * @param string $tag
108
+ * @return bool
109
+ */
110
+ public function hasTag($tag);
111
+
112
+ /**
113
+ * Binds a chain of decorators to a class or interface.
114
+ *
115
+ * @param $classOrInterface
116
+ * @param array $decorators
117
+ */
118
+ public function bindDecorators($classOrInterface, array $decorators);
119
+
120
+ /**
121
+ * Binds a chain of decorators to a class or interface to be returned as a singleton.
122
+ *
123
+ * @param $classOrInterface
124
+ * @param array $decorators
125
+ */
126
+ public function singletonDecorators($classOrInterface, $decorators);
127
+
128
+ /**
129
+ * Starts the `when->needs->give` chain for a contextual binding.
130
+ *
131
+ * @param string $class The fully qualified name of the requesting class.
132
+ *
133
+ * Example:
134
+ *
135
+ * // any class requesting an implementation of `LoggerInterface` will receive this implementation...
136
+ * $container->singleton('LoggerInterface', 'FilesystemLogger');
137
+ * // but if the requesting class is `Worker` return another implementation
138
+ * $container->when('Worker')
139
+ * ->needs('LoggerInterface)
140
+ * ->give('RemoteLogger);
141
+ *
142
+ * @return tad_DI52_ContainerInterface
143
+ */
144
+ public function when($class);
145
+
146
+ /**
147
+ * Second step the `when->needs->give` chain for a contextual binding.
148
+ *
149
+ * @param string $classOrInterface The fully qualified name of the requested class.
150
+ *
151
+ * Example:
152
+ *
153
+ * // any class requesting an implementation of `LoggerInterface` will receive this implementation...
154
+ * $container->singleton('LoggerInterface', 'FilesystemLogger');
155
+ * // but if the requesting class is `Worker` return another implementation
156
+ * $container->when('Worker')
157
+ * ->needs('LoggerInterface)
158
+ * ->give('RemoteLogger);
159
+ *
160
+ * @return tad_DI52_ContainerInterface
161
+ */
162
+ public function needs($classOrInterface);
163
+
164
+ /**
165
+ * Last step the `when->needs->give` chain for a contextual binding.
166
+ *
167
+ * @param mixed $implementation An implementation of the requested class.
168
+ *
169
+ * Example:
170
+ *
171
+ * // any class requesting an implementation of `LoggerInterface` will receive this implementation...
172
+ * $container->singleton('LoggerInterface', 'FilesystemLogger');
173
+ * // but if the requesting class is `Worker` return another implementation
174
+ * $container->when('Worker')
175
+ * ->needs('LoggerInterface)
176
+ * ->give('RemoteLogger);
177
+ *
178
+ * @return tad_DI52_ContainerInterface
179
+ */
180
+ public function give($implementation);
181
+ }
vendor/lucatume/di52/src/tad/DI52/ProtectedValue.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class tad_DI52_ProtectedValue
4
+ {
5
+
6
+ /**
7
+ * @var mixed
8
+ */
9
+ protected $value;
10
+
11
+ /**
12
+ * tad_DI52_ProtectedValue constructor.
13
+ * @param mixed $value
14
+ */
15
+ public function __construct($value)
16
+ {
17
+ $this->value = $value;
18
+ }
19
+
20
+ /**
21
+ * @return mixed
22
+ */
23
+ public function getValue()
24
+ {
25
+ return $this->value;
26
+ }
27
+ }
vendor/lucatume/di52/src/tad/DI52/ServiceProvider.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class tad_DI52_ServiceProvider
5
+ * @codeCoverageIgnore
6
+ */
7
+ abstract class tad_DI52_ServiceProvider implements tad_DI52_ServiceProviderInterface
8
+ {
9
+ /**
10
+ * Whether the service provider will be a deferred one or not.
11
+ *
12
+ * @var bool
13
+ */
14
+ protected $deferred = false;
15
+
16
+ /**
17
+ * @var tad_DI52_Container
18
+ */
19
+ protected $container;
20
+
21
+
22
+ /**
23
+ * tad_DI52_ServiceProvider constructor.
24
+ * @param tad_DI52_Container $container
25
+ */
26
+ public function __construct(tad_DI52_Container $container)
27
+ {
28
+ $this->container = $container;
29
+ }
30
+
31
+ /**
32
+ * Whether the service provider will be a deferred one or not.
33
+ *
34
+ * @return bool
35
+ */
36
+ public function isDeferred()
37
+ {
38
+ return $this->deferred;
39
+ }
40
+
41
+ /**
42
+ * Returns an array of the class or interfaces bound and provided by the service provider.
43
+ *
44
+ * @return array
45
+ */
46
+ public function provides()
47
+ {
48
+ return array();
49
+ }
50
+
51
+ /**
52
+ * Binds and sets up implementations at boot time.
53
+ */
54
+ public function boot()
55
+ {
56
+ // no-op
57
+ }
58
+ }
vendor/lucatume/di52/src/tad/DI52/ServiceProviderInterface.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ interface tad_DI52_ServiceProviderInterface
4
+ {
5
+ /**
6
+ * Binds and sets up implementations.
7
+ */
8
+ public function register();
9
+
10
+ /**
11
+ * Binds and sets up implementations at boot time.
12
+ */
13
+ public function boot();
14
+
15
+ /**
16
+ * Returns an array of implementations provided by the service provider.
17
+ *
18
+ * @return array
19
+ */
20
+ public function provides();
21
+
22
+ /**
23
+ * Whether the service provider will be a deferred one or not.
24
+ *
25
+ * @return bool
26
+ */
27
+ public function isDeferred();
28
+ }
vendor/lucatume/di52/src/tad/DI52/closuresSupport.php ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Builds and returns a closure to be used to lazily make objects on PHP 5.3+, call a method on them and return the
4
+ * method value.
5
+ *
6
+ * @param tad_DI52_Container $container
7
+ * @param string|object $classOrInterface
8
+ * @param string $method
9
+ *
10
+ * @return Closure
11
+ */
12
+ function di52_callbackClosure(tad_DI52_Container $container, $classOrInterface, $method) {
13
+ if ( is_object( $classOrInterface ) ) {
14
+ $objectId = uniqid( spl_object_hash( $classOrInterface ), true );
15
+ $container->bind( $objectId, $classOrInterface );
16
+ } else {
17
+ $objectId = $classOrInterface;
18
+ }
19
+
20
+ $isStatic = false;
21
+ try {
22
+ $reflectionMethod = new ReflectionMethod($classOrInterface, $method);
23
+ $isStatic = $reflectionMethod->isStatic();
24
+ } catch ( ReflectionException $e ) {
25
+ // no-op
26
+ }
27
+
28
+ return function () use ( $isStatic, $container, $objectId, $method ) {
29
+ return $isStatic ?
30
+ call_user_func_array( array( $objectId, $method ), func_get_args() )
31
+ : call_user_func_array( array( $container->make( $objectId ), $method ), func_get_args() );
32
+ };
33
+ }
34
+
35
+ /**
36
+ * Builds and returns a closure to be used to lazily make objects on PHP 5.3+ and return them.
37
+ *
38
+ * @param tad_DI52_Container $container
39
+ * @param string $classOrInterface
40
+ * @param array $vars
41
+ *
42
+ * @return Closure
43
+ */
44
+ function di52_instanceClosure(tad_DI52_Container $container, $classOrInterface, array $vars = array()) {
45
+ return function () use ($container, $classOrInterface, $vars) {
46
+ if (is_object($classOrInterface)) {
47
+ if (is_callable($classOrInterface)) {
48
+ return call_user_func_array($classOrInterface, $vars);
49
+ }
50
+ return $classOrInterface;
51
+ }
52
+
53
+ $r = new ReflectionClass($classOrInterface);
54
+ $constructor = $r->getConstructor();
55
+ if (null === $constructor || empty($vars)) {
56
+ return $container->make($classOrInterface);
57
+ }
58
+ $args = array();
59
+ foreach ($vars as $var) {
60
+ try {
61
+ $args[] = $container->make($var);
62
+ } catch (RuntimeException $e) {
63
+ $args[] = $var;
64
+ }
65
+ }
66
+ return $r->newInstanceArgs($args);
67
+ };
68
+ }
vendor/lucatume/di52/tests/52-compat/Container52CompatTest.php ADDED
@@ -0,0 +1,1448 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class TestObject {
4
+ protected $num;
5
+
6
+ public function __construct( $num = 123 ) {
7
+ $this->num = $num;
8
+ }
9
+
10
+ public function getNum() {
11
+ return $this->num;
12
+ }
13
+
14
+ public static function staticOne() {
15
+ return 'static one';
16
+ }
17
+
18
+ public static function staticTwo() {
19
+ return 'static two';
20
+ }
21
+
22
+ public static function staticThree( $param1 ) {
23
+ return 'static two';
24
+ }
25
+ }
26
+
27
+ interface TestInterface{
28
+ public static function apiMethodOne( $param1 = 23 );
29
+
30
+ public function apiMethodTwo( $param1 );
31
+ }
32
+
33
+ class Container52CompatTest extends PHPUnit_Framework_TestCase {
34
+
35
+ public function boundVariables() {
36
+ return array(
37
+ array('bar'),
38
+ array(23),
39
+ array((object)array('prop' => 'value')),
40
+ array(''),
41
+ );
42
+ }
43
+
44
+ protected function setUp() {
45
+ ClassEight::reset();
46
+ }
47
+
48
+ /**
49
+ * @test
50
+ * it should allow setting a var on the container
51
+ * @dataProvider boundVariables
52
+ */
53
+ public function it_should_allow_setting_a_var_on_the_container($value) {
54
+ $container = new tad_DI52_Container();
55
+
56
+ $container->setVar('foo', $value);
57
+
58
+ $this->assertEquals($value, $container->getVar('foo'));
59
+ }
60
+
61
+ /**
62
+ * @test
63
+ * it should allow setting a var on the container with ArrayAccess API
64
+ * @dataProvider boundVariables
65
+ */
66
+ public function it_should_allow_setting_a_var_on_the_container_with_array_access_api($value) {
67
+ $container = new tad_DI52_Container();
68
+
69
+ $container['foo'] = $value;
70
+
71
+ $this->assertEquals($value, $container['foo']);
72
+ }
73
+
74
+ /**
75
+ * @test
76
+ * it should return null when trying to get non existing var
77
+ */
78
+ public function it_should_return_null_when_trying_to_get_non_existing_var() {
79
+ $container = new tad_DI52_Container();
80
+
81
+ $this->assertNull($container->getVar('foo'));
82
+ }
83
+
84
+ /**
85
+ * @test
86
+ * it should return throw when using ArrayAccess API to get non set var
87
+ */
88
+ public function it_should_return_throw_when_using_array_access_api_to_get_non_set_var() {
89
+ $container = new tad_DI52_Container();
90
+
91
+ $this->setExpectedException('RuntimeException');
92
+
93
+ $this->assertNull($container['foo']);
94
+ }
95
+
96
+ /**
97
+ * @test
98
+ * it should allow binding an implementation with no constructor to an interface
99
+ */
100
+ public function it_should_allow_binding_an_implementation_with_no_constructor_to_an_interface() {
101
+ $container = new tad_DI52_Container();
102
+
103
+ $container->bind('One', 'ClassOne');
104
+
105
+ $this->assertInstanceOf('ClassOne', $container->make('One'));
106
+ }
107
+
108
+ /**
109
+ * @test
110
+ * it should return a different instance of a bound interface implementation on each build
111
+ */
112
+ public function it_should_return_a_different_instance_of_a_bound_interface_implementation_on_each_build() {
113
+ $container = new tad_DI52_Container();
114
+
115
+ $container->bind('One', 'ClassOne');
116
+
117
+ $this->assertNotSame($container->make('One'), $container->make('One'));
118
+ }
119
+
120
+ /**
121
+ * @test
122
+ * it should allow binding an implementation with constructor to an interface
123
+ */
124
+ public function it_should_allow_binding_an_implementation_with_constructor_to_an_interface() {
125
+ $container = new tad_DI52_Container();
126
+
127
+ $container->bind('One', 'ClassOneOne');
128
+
129
+ $this->assertInstanceOf('ClassOneOne', $container->make('One'));
130
+ }
131
+
132
+ /**
133
+ * @test
134
+ * it should allow binding an implementation with constructor arguments
135
+ */
136
+ public function it_should_allow_binding_an_implementation_with_constructor_arguments() {
137
+ $container = new tad_DI52_Container();
138
+
139
+ $container->bind('One', 'ClassOneTwo');
140
+
141
+ $this->assertInstanceOf('ClassOneTwo', $container->make('One'));
142
+ }
143
+
144
+ /**
145
+ * @test
146
+ * it should allow binding an implementation to a string slug
147
+ */
148
+ public function it_should_allow_binding_an_implementation_to_a_string_slug() {
149
+ $container = new tad_DI52_Container();
150
+
151
+ $container->bind('foo', 'ClassOneTwo');
152
+
153
+ $this->assertInstanceOf('ClassOneTwo', $container->make('foo'));
154
+ }
155
+
156
+ /**
157
+ * @test
158
+ * it should allow binding an implementation to a class
159
+ */
160
+ public function it_should_allow_binding_an_implementation_to_a_class() {
161
+ $container = new tad_DI52_Container();
162
+
163
+ $container->bind('ClassOne', 'ClassOneOne');
164
+
165
+ $this->assertInstanceOf('ClassOneOne', $container->make('ClassOne'));
166
+ }
167
+
168
+ /**
169
+ * @test
170
+ * it should resolve unbound class with no constructor
171
+ */
172
+ public function it_should_resolve_unbound_class_with_no_constructor() {
173
+ $container = new tad_DI52_Container();
174
+
175
+ $this->assertInstanceOf('ClassOne', $container->make('ClassOne'));
176
+ }
177
+
178
+ /**
179
+ * @test
180
+ * it should resolve an unbound class with a defaulted scalar dependency
181
+ */
182
+ public function it_should_resolve_an_unbound_class_with_a_defaulted_scalar_dependency() {
183
+ $container = new tad_DI52_Container();
184
+
185
+ $this->assertInstanceOf('ClassOneTwo', $container->make('ClassOneTwo'));
186
+ }
187
+
188
+ /**
189
+ * @test
190
+ * it should throw if trying to resolve class with unbound interface dependency
191
+ */
192
+ public function it_should_throw_if_trying_to_resolve_class_with_unbound_interface_dependency() {
193
+ $this->setExpectedException('RuntimeException');
194
+
195
+ $container = new tad_DI52_Container();
196
+
197
+ $container->make('ClassTwo');
198
+ }
199
+
200
+ /**
201
+ * @test
202
+ * it should resolve an unbound class with an interface dependency
203
+ */
204
+ public function it_should_resolve_an_unbound_class_with_an_interface_dependency() {
205
+ $container = new tad_DI52_Container();
206
+
207
+ $container->bind('One', 'ClassOne');
208
+
209
+ $this->assertInstanceOf('ClassTwo', $container->make('ClassTwo'));
210
+ }
211
+
212
+ /**
213
+ * @test
214
+ * it should resolve an unbound class with a class dependency
215
+ */
216
+ public function it_should_resolve_an_unbound_class_with_a_class_dependency() {
217
+ $container = new tad_DI52_Container();
218
+
219
+ $this->assertInstanceOf('ClassTwoOne', $container->make('ClassTwoOne'));
220
+ }
221
+
222
+ /**
223
+ * @test
224
+ * it should resolve an unbound class with plus one interface dependencies
225
+ */
226
+ public function it_should_resolve_an_unbound_class_with_plus_one_interface_dependencies() {
227
+ $container = new tad_DI52_Container();
228
+
229
+ $container->bind('One', 'ClassOne');
230
+ $container->bind('Two', 'ClassTwo');
231
+
232
+ $this->assertInstanceOf('ClassThree', $container->make('ClassThree'));
233
+ }
234
+
235
+ /**
236
+ * @test
237
+ * it should resolve an unbound class with plus one class dependencies
238
+ */
239
+ public function it_should_resolve_an_unbound_class_with_plus_one_class_dependencies() {
240
+ $container = new tad_DI52_Container();
241
+
242
+ $container->bind('One', 'ClassOne');
243
+
244
+ $this->assertInstanceOf('ClassThreeOne', $container->make('ClassThreeone'));
245
+ }
246
+
247
+ /**
248
+ * @test
249
+ * it should resolve an unbound class with plus one interface and class dependencies
250
+ */
251
+ public function it_should_resolve_an_unbound_class_with_plus_one_interface_and_class_dependencies() {
252
+ $container = new tad_DI52_Container();
253
+
254
+ $this->assertInstanceOf('ClassThreeTwo', $container->make('ClassThreeTwo'));
255
+ }
256
+
257
+ /**
258
+ * @test
259
+ * it should throw if trying to resolve class with non type-hinted dependency without default
260
+ */
261
+ public function it_should_throw_if_trying_to_resolve_class_with_non_type_hinted_dependency_without_default() {
262
+ $container = new tad_DI52_Container();
263
+
264
+ $this->setExpectedException('RuntimeException');
265
+
266
+ $container->make('ClassFour');
267
+ }
268
+
269
+ /**
270
+ * @test
271
+ * it should allow binding a class to an interface as a singleton
272
+ */
273
+ public function it_should_allow_binding_a_class_to_an_interface_as_a_singleton() {
274
+ $container = new tad_DI52_Container();
275
+
276
+ $container->singleton('One', 'ClassOne');
277
+
278
+ $this->assertInstanceOf('ClassOne', $container->make('One'));
279
+ $this->assertSame($container->make('One'), $container->make('One'));
280
+ }
281
+
282
+ /**
283
+ * @test
284
+ * it should allow binding a class to a class as a singleton
285
+ */
286
+ public function it_should_allow_binding_a_class_to_a_class_as_a_singleton() {
287
+ $container = new tad_DI52_Container();
288
+
289
+ $container->singleton('ClassOne', 'ClassOneOne');
290
+
291
+ $this->assertInstanceOf('ClassOneOne', $container->make('ClassOne'));
292
+ $this->assertSame($container->make('ClassOne'), $container->make('ClassOne'));
293
+ }
294
+
295
+ /**
296
+ * @test
297
+ * it should allow binding a class to a string slug as a singleton
298
+ */
299
+ public function it_should_allow_binding_a_class_to_a_string_slug_as_a_singleton() {
300
+ $container = new tad_DI52_Container();
301
+
302
+ $container->singleton('one.foo', 'ClassOne');
303
+
304
+ $this->assertInstanceOf('ClassOne', $container->make('one.foo'));
305
+ $this->assertSame($container->make('one.foo'), $container->make('one.foo'));
306
+ }
307
+
308
+ public function implementationKeysAndValues() {
309
+ return array(
310
+ array('One', 'ClassOne'),
311
+ array('ClassOne', 'ClassOneOne'),
312
+ );
313
+ }
314
+
315
+ /**
316
+ * @test
317
+ * it should bind an implementation as singleton when using ArrayAccess API
318
+ * @dataProvider implementationKeysAndValues
319
+ */
320
+ public function it_should_bind_an_implementation_as_singleton_when_using_array_access_api($key, $value) {
321
+ $container = new tad_DI52_Container();
322
+
323
+ $container[$key] = $value;
324
+
325
+ $this->assertInstanceOf($value, $container[$key]);
326
+ $this->assertSame($container[$key], $container[$key]);
327
+ }
328
+
329
+ /**
330
+ * @test
331
+ * it should allow binding a decorator chain to an interface
332
+ */
333
+ public function it_should_allow_binding_a_decorator_chain_to_an_interface() {
334
+ $container = new tad_DI52_Container();
335
+
336
+ $container->bindDecorators('Four', array('FourDecoratorOne', 'FourDecoratorTwo', 'FourDecoratorThree', 'FourBase'));
337
+
338
+ $this->assertInstanceOf('Four', $container->make('Four'));
339
+ $this->assertNotSame($container->make('Four'), $container->make('Four'));
340
+ }
341
+
342
+ /**
343
+ * @test
344
+ * it should allow specifying after build methods to call on a decorator chain base
345
+ */
346
+ public function it_should_allow_specifying_after_build_methods_to_call_on_a_decorator_chain_base() {
347
+ $container = new tad_DI52_Container();
348
+
349
+ $container->bindDecorators('Four', array('FourDecoratorOne', 'FourDecoratorTwo', 'FourDecoratorThree', 'FourBase'),
350
+ array('methodOne', 'methodTwo'));
351
+
352
+ $this->assertInstanceOf('Four', $container->make('Four'));
353
+ $this->assertNotSame($container->make('Four'), $container->make('Four'));
354
+
355
+ global $one, $two;
356
+
357
+ $this->assertEquals('FourBase', $one);
358
+ $this->assertEquals('FourBase', $two);
359
+ }
360
+
361
+ /**
362
+ * @test
363
+ * it should allow binding a chain as a singleton to an interface
364
+ */
365
+ public function it_should_allow_binding_a_chain_as_a_singleton_to_an_interface() {
366
+ $container = new tad_DI52_Container();
367
+
368
+ $container->singletonDecorators('Four',
369
+ array('FourDecoratorOne', 'FourDecoratorTwo', 'FourDecoratorThree', 'FourBase'));
370
+
371
+ $this->assertInstanceOf('Four', $container->make('Four'));
372
+ $this->assertSame($container->make('Four'), $container->make('Four'));
373
+ }
374
+
375
+ /**
376
+ * @test
377
+ * it should allow binding a complex chain to an interface
378
+ */
379
+ public function it_should_allow_binding_a_complex_chain_to_an_interface() {
380
+ $container = new tad_DI52_Container();
381
+
382
+ $container->bind('Four', 'FourTwo');
383
+ $container->bind('One', 'ClassOne');
384
+ $container->bind('Two', 'ClassTwo');
385
+
386
+ $container->bindDecorators('Five', array('FiveDecoratorOne', 'FiveDecoratorTwo', 'FiveDecoratorThree', 'FiveBase'));
387
+
388
+ $this->assertInstanceOf('Five', $container->make('Five'));
389
+ $this->assertNotSame($container->make('Five'), $container->make('Five'));
390
+ }
391
+
392
+ /**
393
+ * @test
394
+ * it should allow binding a complex chain as a singleton to an interface
395
+ */
396
+ public function it_should_allow_binding_a_complex_chain_as_a_singleton_to_an_interface() {
397
+ $container = new tad_DI52_Container();
398
+
399
+ $container->bind('Four', 'FourTwo');
400
+ $container->bind('One', 'ClassOne');
401
+ $container->bind('Two', 'ClassTwo');
402
+
403
+ $container->singletonDecorators('Five',
404
+ array('FiveDecoratorOne', 'FiveDecoratorTwo', 'FiveDecoratorThree', 'FiveBase'));
405
+
406
+ $this->assertInstanceOf('Five', $container->make('Five'));
407
+ $this->assertSame($container->make('Five'), $container->make('Five'));
408
+ }
409
+
410
+ /**
411
+ * @test
412
+ * it should allow tagging and resolving tagged classes
413
+ */
414
+ public function it_should_allow_tagging_and_resolving_tagged_classes() {
415
+ $container = new tad_DI52_Container();
416
+
417
+ $container->tag(array('ClassOne', 'ClassOneOne', 'ClassOneTwo'), 'foo');
418
+ $made = $container->tagged('foo');
419
+
420
+ $this->assertInstanceOf('ClassOne', $made[0]);
421
+ $this->assertInstanceOf('ClassOneOne', $made[1]);
422
+ $this->assertInstanceOf('ClassOneTwo', $made[2]);
423
+ }
424
+
425
+ /**
426
+ * @test
427
+ * it should throw if trying to resolve non existing tag
428
+ */
429
+ public function it_should_throw_if_trying_to_resolve_non_existing_tag() {
430
+ $container = new tad_DI52_Container();
431
+
432
+ $this->setExpectedException('RuntimeException');
433
+
434
+ $container->tagged('foo');
435
+ }
436
+
437
+ /**
438
+ * @test
439
+ * it should allow tagging mixed values
440
+ */
441
+ public function it_should_allow_tagging_mixed_values() {
442
+ $container = new tad_DI52_Container();
443
+
444
+ $container->tag(array('ClassOne', new ClassOneOne(), 'ClassOneTwo'), 'foo');
445
+ $made = $container->tagged('foo');
446
+
447
+ $this->assertInstanceOf('ClassOne', $made[0]);
448
+ $this->assertInstanceOf('ClassOneOne', $made[1]);
449
+ $this->assertInstanceOf('ClassOneTwo', $made[2]);
450
+ }
451
+
452
+ /**
453
+ * @test
454
+ * it should call register method on on deferred service providers when registering
455
+ */
456
+ public function it_should_call_register_method_on_on_deferred_service_providers_when_registering() {
457
+ $container = new tad_DI52_Container();
458
+
459
+ $container->register('ProviderOne');
460
+
461
+ $this->assertTrue($container->isBound('foo'));
462
+ }
463
+
464
+ /**
465
+ * @test
466
+ * it should not call register method on deferred provider on registration
467
+ */
468
+ public function it_should_not_call_register_method_on_deferred_provider_on_registration() {
469
+ DeferredProviderTwo::reset();
470
+
471
+ $container = new tad_DI52_Container();
472
+
473
+ $container->register('DeferredProviderTwo');
474
+
475
+ $this->assertEmpty(DeferredProviderTwo::wasRegistered());
476
+ }
477
+
478
+ /**
479
+ * @test
480
+ * it should throw if deferred provider is not providing anything
481
+ */
482
+ public function it_should_throw_if_deferred_provider_is_not_providing_anything() {
483
+ $container = new tad_DI52_Container();
484
+
485
+ $this->setExpectedException('RuntimeException');
486
+
487
+ $container->register('DeferredProviderOne');
488
+ }
489
+
490
+ /**
491
+ * @test
492
+ * it should register deferred provider when trying to resolve provided class
493
+ */
494
+ public function it_should_register_deferred_provider_when_trying_to_resolve_provided_class() {
495
+ DeferredProviderTwo::reset();
496
+
497
+ $container = new tad_DI52_Container();
498
+
499
+ $container->register('DeferredProviderTwo');
500
+
501
+ $this->assertFalse(DeferredProviderTwo::wasRegistered());
502
+
503
+ $container->make('One');
504
+
505
+ $this->assertTrue(DeferredProviderTwo::wasRegistered());
506
+ }
507
+
508
+ /**
509
+ * @test
510
+ * it should call boot method on providers when booting the container
511
+ */
512
+ public function it_should_call_boot_method_on_providers_when_booting_the_container() {
513
+ $container = new tad_DI52_Container();
514
+
515
+ $container->register('ProviderThree');
516
+
517
+ $this->assertFalse($container->isBound('One'));
518
+
519
+ $container->boot();
520
+
521
+ $this->assertTrue($container->isBound('One'));
522
+ }
523
+
524
+ /**
525
+ * @test
526
+ * it should call after build methods on implementations
527
+ */
528
+ public function it_should_call_after_build_methods_on_implementations() {
529
+ $container = new tad_DI52_Container();
530
+
531
+ $container->bind('One', 'ClassOneThree', array('methodOne', 'methodTwo'));
532
+
533
+ $one = $container->make('One');
534
+ $this->assertTrue($one->oneCalled);
535
+ $this->assertTrue($one->twoCalled);
536
+ }
537
+
538
+ /**
539
+ * @test
540
+ * it should bind an object implementation as a singleton even when using bind
541
+ */
542
+ public function it_should_bind_an_object_implementation_as_a_singleton_even_when_using_bind() {
543
+ $container = new tad_DI52_Container();
544
+
545
+ $object = new stdClass();
546
+
547
+ $container->bind('foo', $object);
548
+
549
+ $this->assertInstanceOf('stdClass', $container->make('foo'));
550
+ $this->assertSame($container->make('foo'), $container->make('foo'));
551
+ }
552
+
553
+ /**
554
+ * @test
555
+ * it should allow binding an object to an interface as a singleton and resolving it using bind
556
+ */
557
+ public function it_should_allow_binding_an_object_to_an_interface_as_a_singleton_and_resolving_it_using_bind() {
558
+ $container = new tad_DI52_Container();
559
+
560
+ $object = new ClassOne();
561
+
562
+ $container->bind('One', $object);
563
+
564
+ $this->assertInstanceOf('ClassOne', $container->make('One'));
565
+ $this->assertInstanceOf('ClassOne', $container['One']);
566
+ $this->assertSame($container->make('One'), $container['One']);
567
+ }
568
+
569
+ /**
570
+ * @test
571
+ * it should allow binding an object to an interface as a singleton and resolving it
572
+ */
573
+ public function it_should_allow_binding_an_object_to_an_interface_as_a_singleton_and_resolving_it() {
574
+ $container = new tad_DI52_Container();
575
+
576
+ $object = new ClassOne();
577
+
578
+ $container->singleton('One', $object);
579
+
580
+ $this->assertInstanceOf('ClassOne', $container->make('One'));
581
+ $this->assertInstanceOf('ClassOne', $container['One']);
582
+ $this->assertSame($container->make('One'), $container['One']);
583
+ }
584
+
585
+ /**
586
+ * @test
587
+ * it should support contextual binding of interfaces
588
+ */
589
+ public function it_should_support_contextual_binding_of_interfaces() {
590
+ $container = new tad_DI52_Container();
591
+
592
+ $container->bind('One', 'ClassOne');
593
+
594
+ $container->when('ClassSix')
595
+ ->needs('One')
596
+ ->give('ClassOneOne');
597
+
598
+ $container->when('ClassSeven')
599
+ ->needs('One')
600
+ ->give('ClassOneTwo');
601
+
602
+ $this->assertInstanceOf('ClassOne', $container->make('One'));
603
+ $this->assertInstanceOf('ClassOneOne', $container->make('ClassSix')->getOne());
604
+ $this->assertInstanceOf('ClassOneTwo', $container->make('ClassSeven')->getOne());
605
+ }
606
+
607
+ /**
608
+ * @test
609
+ * it should support contextual binding of classes
610
+ */
611
+ public function it_should_support_contextual_binding_of_classes() {
612
+ $container = new tad_DI52_Container();
613
+
614
+ $container->when('ClassSixOne')
615
+ ->needs('ClassOne')
616
+ ->give('ExtendingClassOneOne');
617
+
618
+ $container->when('ClassSevenOne')
619
+ ->needs('ClassOne')
620
+ ->give('ExtendingClassOneTwo');
621
+
622
+ $this->assertInstanceOf('ClassOne', $container->make('ClassOne'));
623
+ $this->assertInstanceOf('ExtendingClassOneOne', $container->make('ClassSixOne')->getOne());
624
+ $this->assertInstanceOf('ExtendingClassOneTwo', $container->make('ClassSevenOne')->getOne());
625
+ }
626
+
627
+ /**
628
+ * @test
629
+ * it should throw when trying to make non existing class
630
+ */
631
+ public function it_should_throw_when_trying_to_make_non_existing_class() {
632
+ $container = new tad_DI52_Container();
633
+
634
+ $this->setExpectedException('RuntimeException');
635
+
636
+ $container->make('SomeNonExistingClass');
637
+ }
638
+
639
+ /**
640
+ * @test
641
+ * it should replace a binding when re-binding
642
+ */
643
+ public function it_should_replace_a_binding_when_re_binding() {
644
+ $container = new tad_DI52_Container();
645
+
646
+ $container->bind('One', 'ClassOne');
647
+
648
+ $this->assertInstanceOf('ClassOne', $container->make('One'));
649
+
650
+ $container->bind('One', 'ClassOneOne');
651
+
652
+ $this->assertInstanceOf('ClassOneOne', $container->make('One'));
653
+ }
654
+
655
+ /**
656
+ * @test
657
+ * it should replace a singleton bind when re-binding a singleton binding
658
+ */
659
+ public function it_should_replace_a_singleton_bind_when_re_binding_a_singleton_binding() {
660
+ $container = new tad_DI52_Container();
661
+
662
+ $container->singleton('One', 'ClassOne');
663
+
664
+ $this->assertInstanceOf('ClassOne', $container->make('One'));
665
+
666
+ $container->bind('One', 'ClassOneOne');
667
+
668
+ $this->assertInstanceOf('ClassOneOne', $container->make('One'));
669
+ $this->assertNotSame($container->make('One'), $container->make('One'));
670
+ }
671
+
672
+ /**
673
+ * @test
674
+ * it should replace bind with singleton if re-binding as singleton
675
+ */
676
+ public function it_should_replace_bind_with_singleton_if_re_binding_as_singleton() {
677
+ $container = new tad_DI52_Container();
678
+
679
+ $container->singleton('One', 'ClassOne');
680
+
681
+ $this->assertInstanceOf('ClassOne', $container->make('One'));
682
+ $this->assertSame($container->make('One'), $container->make('One'));
683
+
684
+ $container->singleton('One', 'ClassOneOne');
685
+
686
+ $this->assertInstanceOf('ClassOneOne', $container->make('One'));
687
+ $this->assertSame($container->make('One'), $container->make('One'));
688
+ }
689
+
690
+ /**
691
+ * @test
692
+ * it should replace singleton with simple bind if re-binding as non singleton
693
+ */
694
+ public function it_should_replace_singleton_with_simple_bind_if_re_binding_as_non_singleton() {
695
+ $container = new tad_DI52_Container();
696
+
697
+ $container->singleton('One', 'ClassOne');
698
+
699
+ $this->assertInstanceOf('ClassOne', $container->make('One'));
700
+ $this->assertSame($container->make('One'), $container->make('One'));
701
+
702
+ $container->bind('One', 'ClassOneOne');
703
+
704
+ $this->assertInstanceOf('ClassOneOne', $container->make('One'));
705
+ $this->assertNotSame($container->make('One'), $container->make('One'));
706
+ }
707
+
708
+ /**
709
+ * @test
710
+ * it should allow tagging non concrete implementations
711
+ */
712
+ public function it_should_allow_tagging_non_concrete_implementations() {
713
+ $container = new tad_DI52_Container();
714
+
715
+ $container->bind('foo', 'ClassOne');
716
+ $container->bind('One', 'ClassOne');
717
+
718
+ $container->tag(array('foo', 'One'), 'bar');
719
+
720
+ $resolved = $container->tagged('bar');
721
+
722
+ $this->assertCount(2, $resolved);
723
+ $this->assertInstanceOf('ClassOne', $resolved[0]);
724
+ $this->assertInstanceOf('ClassOne', $resolved[1]);
725
+ $this->assertNotSame($resolved[0], $resolved[1]);
726
+ }
727
+
728
+ /**
729
+ * @test
730
+ * it should allow lazy building an interface binding
731
+ */
732
+ public function it_should_allow_lazy_building_an_interface_binding() {
733
+ $container = new tad_DI52_Container();
734
+
735
+ $container->bind('Eight', 'ClassEight');
736
+ $f = $container->callback('Eight', 'methodOne');
737
+
738
+ $f();
739
+
740
+ $this->assertEquals(array('methodOne'), ClassEight::$called);
741
+ $this->assertNotSame($container->make('Eight'), $container->make('Eight'));
742
+ }
743
+
744
+ /**
745
+ * @test
746
+ * it should allow lazy building an class binding
747
+ */
748
+ public function it_should_allow_lazy_building_an_class_binding() {
749
+ $container = new tad_DI52_Container();
750
+
751
+ $container->bind('ClassEight', 'ClassEightExtension');
752
+ $f = $container->callback('ClassEight', 'methodOne');
753
+
754
+ $f();
755
+
756
+ $this->assertEquals(array('methodOne'), ClassEightExtension::$called);
757
+ $this->assertNotSame($container->make('ClassEight'), $container->make('ClassEight'));
758
+ }
759
+
760
+ /**
761
+ * @test
762
+ * it should allow lazy building an slug binding
763
+ */
764
+ public function it_should_allow_lazy_building_an_slug_binding() {
765
+ $container = new tad_DI52_Container();
766
+
767
+ $container->bind('foo', 'ClassEight');
768
+ $f = $container->callback('foo', 'methodOne');
769
+
770
+ $f();
771
+
772
+ $this->assertEquals(array('methodOne'), ClassEight::$called);
773
+ $this->assertNotSame($container->make('foo'), $container->make('foo'));
774
+ }
775
+
776
+ /**
777
+ * @test
778
+ * it should allow lazy binding a singleton interface binding
779
+ */
780
+ public function it_should_allow_lazy_binding_a_singleton_interface_binding() {
781
+ $container = new tad_DI52_Container();
782
+
783
+ $container->singleton('Eight', 'ClassEight');
784
+ $f = $container->callback('Eight', 'methodOne');
785
+
786
+ $f();
787
+
788
+ $this->assertSame($container->make('Eight'), $container->make('Eight'));
789
+ $this->assertEquals(array('methodOne'), ClassEight::$called);
790
+ }
791
+
792
+ /**
793
+ * @test
794
+ * it should allow lazy binding a singleton class binding
795
+ */
796
+ public function it_should_allow_lazy_binding_a_singleton_class_binding() {
797
+ $container = new tad_DI52_Container();
798
+
799
+ $container->singleton('ClassEight', 'ClassEightExtension');
800
+ $f = $container->callback('ClassEight', 'methodOne');
801
+
802
+ $f();
803
+
804
+ $this->assertSame($container->make('ClassEight'), $container->make('ClassEight'));
805
+ $this->assertEquals(array('methodOne'), ClassEight::$called);
806
+ }
807
+
808
+ /**
809
+ * @test
810
+ * it should allow lazy binding a singleton slug binding
811
+ */
812
+ public function it_should_allow_lazy_binding_a_singleton_slug_binding() {
813
+ $container = new tad_DI52_Container();
814
+
815
+ $container->singleton('foo', 'ClassEight');
816
+ $f = $container->callback('foo', 'methodOne');
817
+
818
+ $f();
819
+
820
+ $this->assertSame($container->make('foo'), $container->make('foo'));
821
+ $this->assertEquals(array('methodOne'), ClassEight::$called);
822
+ }
823
+
824
+ /**
825
+ * @test
826
+ * it should pass the calling arguments to the lazy made instance
827
+ */
828
+ public function it_should_pass_the_calling_arguments_to_the_lazy_made_instance() {
829
+ $container = new tad_DI52_Container();
830
+
831
+ $container->bind('foo', 'ClassEight');
832
+ $f = $container->callback('foo', 'methodFour');
833
+
834
+ $f('foo', 23);
835
+ $this->assertEquals(array('foo', 23), ClassEight::$calledWith);
836
+ }
837
+
838
+ /**
839
+ * @test
840
+ * it should allow lazy making a decorator binding
841
+ */
842
+ public function it_should_allow_lazy_making_a_decorator_binding() {
843
+ $container = new tad_DI52_Container();
844
+
845
+ $container->bindDecorators('Four', array('FourDecoratorOne', 'FourDecoratorTwo', 'FourDecoratorThree', 'FourBase'));
846
+
847
+ $f = $container->callback('Four', 'methodOne');
848
+ $this->assertEquals(26, $f(3));
849
+ }
850
+
851
+ /**
852
+ * @test
853
+ * it should allow lazy making a decorator singleton binding
854
+ */
855
+ public function it_should_allow_lazy_making_a_decorator_singleton_binding() {
856
+ $container = new tad_DI52_Container();
857
+
858
+ $container->singletonDecorators('Four',
859
+ array('FourDecoratorOne', 'FourDecoratorTwo', 'FourDecoratorThree', 'FourBase'));
860
+
861
+ $f = $container->callback('Four', 'methodOne');
862
+ $this->assertEquals(26, $f(3));
863
+ $this->assertSame($container->make('Four'), $container->make('Four'));
864
+ }
865
+
866
+ /**
867
+ * @test
868
+ * it should allow lazy making an unbound class
869
+ */
870
+ public function it_should_allow_lazy_making_an_unbound_class() {
871
+ $container = new tad_DI52_Container();
872
+
873
+ $f = $container->callback('FourBase', 'methodThree');
874
+
875
+ $this->assertEquals(26, $f(3));
876
+ }
877
+
878
+ /**
879
+ * @test
880
+ * it should throw if trying to lazy make a non string method
881
+ */
882
+ public function it_should_throw_if_trying_to_lazy_make_a_non_string_method() {
883
+ $container = new tad_DI52_Container();
884
+
885
+ $this->setExpectedException('RuntimeException');
886
+
887
+ $container->callback('foo', 23);
888
+ }
889
+
890
+ /**
891
+ * @test
892
+ * it should apply contextual binding to unbound classes
893
+ */
894
+ public function it_should_apply_contextual_binding_to_unbound_classes() {
895
+ $container = new tad_DI52_Container();
896
+
897
+ $container->bind('One', 'ClassOne');
898
+ $container->bind('Two', 'ClassTwo');
899
+ $container->when('ClassTwoOne')->needs('ClassOne')->give('ExtendingClassOneOne');
900
+
901
+ $resolved = $container->make('ClassTwoOne');
902
+ $this->assertInstanceOf('ExtendingClassOneOne', $resolved->getOne());
903
+ }
904
+
905
+ /**
906
+ * @test
907
+ * it should allow lazy making contextually bound interfaces
908
+ */
909
+ public function it_should_allow_lazy_making_contextually_bound_interfaces() {
910
+ $container = new tad_DI52_Container();
911
+
912
+ $container->bind('One', 'ClassOne');
913
+ $container->bind('Two', 'ClassTwo');
914
+ $container->when('ClassTwoOne')->needs('ClassOne')->give('ExtendingClassOneOne');
915
+
916
+ $f = $container->callback('ClassTwoOne', 'getOne');
917
+
918
+ $this->assertInstanceOf('ExtendingClassOneOne', $f());
919
+ }
920
+
921
+ /**
922
+ * @test
923
+ * it should return same instance when lazy making contextually bound singleton
924
+ */
925
+ public function it_should_return_same_instance_when_lazy_making_contextually_bound_singleton() {
926
+ $container = new tad_DI52_Container();
927
+
928
+ $container->bind('One', 'ClassOne');
929
+ $container->bind('Two', 'ClassTwo');
930
+ $container->singleton('two.one', 'ClassTwoOne');
931
+ $container->when('two.one')->needs('ClassOne')->give('ExtendingClassOneOne');
932
+
933
+ $f = $container->callback('two.one', 'getOne');
934
+
935
+ $this->assertInstanceOf('ExtendingClassOneOne', $f());
936
+ $this->assertSame($f(), $f());
937
+ }
938
+
939
+ /**
940
+ * @test
941
+ * it should not build lazy made object immediately
942
+ */
943
+ public function it_should_not_build_lazy_made_object_immediately() {
944
+ $container = new tad_DI52_Container();
945
+
946
+ ClassNine::reset();
947
+ $f = $container->callback('ClassNine', 'methodOne');
948
+
949
+ global $nine;
950
+ $this->assertEmpty($nine);
951
+
952
+ $f();
953
+
954
+ $this->assertEquals('called', $nine);
955
+ }
956
+
957
+ /**
958
+ * @test
959
+ * it should mark a deferred implementation as bound before registering the service provider
960
+ */
961
+ public function it_should_mark_a_deferred_implementation_as_bound_before_registering_the_service_provider() {
962
+ DeferredProviderTwo::reset();
963
+
964
+ $container = new tad_DI52_Container();
965
+
966
+ $container->register('DeferredProviderTwo');
967
+
968
+ $this->assertTrue($container->isBound('One'));
969
+ }
970
+
971
+ /**
972
+ * @test
973
+ * it should allow getting a callback to build an object
974
+ */
975
+ public function it_should_allow_getting_a_callback_to_build_an_object() {
976
+ ClassTen::reset();
977
+
978
+ $container = new tad_DI52_Container();
979
+
980
+ $f = $container->instance('ClassTen', array('foo', 'baz', 'bar'));
981
+
982
+ $this->assertEquals(0, ClassTen::$builtTimes);
983
+
984
+ $instance1 = $f();
985
+
986
+ $this->assertEquals(1, ClassTen::$builtTimes);
987
+ $this->assertEquals('foo', $instance1->getVarOne());
988
+ $this->assertEquals('baz', $instance1->getVarTwo());
989
+ $this->assertEquals('bar', $instance1->getVarThree());
990
+
991
+ $instance2 = $f();
992
+
993
+ $this->assertEquals(2, ClassTen::$builtTimes);
994
+ $this->assertEquals('foo', $instance2->getVarOne());
995
+ $this->assertEquals('baz', $instance2->getVarTwo());
996
+ $this->assertEquals('bar', $instance2->getVarThree());
997
+
998
+ $instance3 = $f();
999
+
1000
+ $this->assertEquals(3, ClassTen::$builtTimes);
1001
+ $this->assertEquals('foo', $instance3->getVarOne());
1002
+ $this->assertEquals('baz', $instance3->getVarTwo());
1003
+ $this->assertEquals('bar', $instance3->getVarThree());
1004
+ }
1005
+
1006
+ /**
1007
+ * @test
1008
+ * it should allow getting a callback to build an object with scalar and object dependencies
1009
+ */
1010
+ public function it_should_allow_getting_a_callback_to_build_an_object_with_scalar_and_object_dependencies() {
1011
+ ClassEleven::reset();
1012
+
1013
+ $container = new tad_DI52_Container();
1014
+
1015
+ $container->bind('One', 'ClassOneTwo');
1016
+ $container->bind('Two', 'ClassTwo');
1017
+
1018
+ $f = $container->instance('ClassEleven', array('ClassOne', 'Two', 'bar'));
1019
+
1020
+ $this->assertEquals(0, ClassEleven::$builtTimes);
1021
+
1022
+ $instance1 = $f();
1023
+
1024
+ $this->assertEquals(1, ClassEleven::$builtTimes);
1025
+ $this->assertInstanceOf('ClassOne', $instance1->getVarOne());
1026
+ $this->assertInstanceOf('ClassTwo', $instance1->getVarTwo());
1027
+ $this->assertInstanceOf('ClassOneTwo', $instance1->getVarTwo()->getOne());
1028
+ $this->assertEquals('bar', $instance1->getVarThree());
1029
+
1030
+ $instance2 = $f();
1031
+
1032
+ $this->assertEquals(2, ClassEleven::$builtTimes);
1033
+ $this->assertInstanceOf('ClassOne', $instance2->getVarOne());
1034
+ $this->assertInstanceOf('ClassTwo', $instance2->getVarTwo());
1035
+ $this->assertInstanceOf('ClassOneTwo', $instance2->getVarTwo()->getOne());
1036
+ $this->assertEquals('bar', $instance2->getVarThree());
1037
+
1038
+ $instance3 = $f();
1039
+
1040
+ $this->assertEquals(3, ClassEleven::$builtTimes);
1041
+ $this->assertInstanceOf('ClassOne', $instance3->getVarOne());
1042
+ $this->assertInstanceOf('ClassTwo', $instance3->getVarTwo());
1043
+ $this->assertInstanceOf('ClassOneTwo', $instance3->getVarTwo()->getOne());
1044
+ $this->assertEquals('bar', $instance3->getVarThree());
1045
+ }
1046
+
1047
+ /**
1048
+ * @test
1049
+ * it should instance using bound implementations
1050
+ */
1051
+ public function it_should_instance_using_bound_implementations() {
1052
+ ClassTwelve::reset();
1053
+
1054
+ $container = new tad_DI52_Container();
1055
+
1056
+ $container->bind('One', 'ClassOne');
1057
+
1058
+ $f = $container->instance('ClassTwelve', array('One'));
1059
+
1060
+ $instance1 = $f();
1061
+
1062
+ $this->assertEquals(1, ClassTwelve::$builtTimes);
1063
+ $this->assertInstanceOf('ClassOne', $instance1->getVarOne());
1064
+ }
1065
+
1066
+ /**
1067
+ * @test
1068
+ * it should allow overriding bound implementations in instance method
1069
+ */
1070
+ public function it_should_allow_overriding_bound_implementations_in_instance_method() {
1071
+ ClassTwelve::reset();
1072
+
1073
+ $container = new tad_DI52_Container();
1074
+
1075
+ $container->bind('One', 'ClassOne');
1076
+
1077
+ $f = $container->instance('ClassTwelve', array('ClassOneOne'));
1078
+
1079
+ $instance1 = $f();
1080
+
1081
+ $this->assertEquals(1, ClassTwelve::$builtTimes);
1082
+ $this->assertInstanceOf('ClassOneOne', $instance1->getVarOne());
1083
+ }
1084
+
1085
+ /**
1086
+ * @test
1087
+ * it should allow referring bound slugs in instance method
1088
+ */
1089
+ public function it_should_allow_referring_bound_slugs_in_instance_method() {
1090
+ ClassTwelve::reset();
1091
+
1092
+ $container = new tad_DI52_Container();
1093
+
1094
+ $container->bind('foo', 'ClassOne');
1095
+
1096
+ $f = $container->instance('ClassTwelve', array('foo'));
1097
+
1098
+ $instance1 = $f();
1099
+
1100
+ $this->assertEquals(1, ClassTwelve::$builtTimes);
1101
+ $this->assertInstanceOf('ClassOne', $instance1->getVarOne());
1102
+ }
1103
+
1104
+ /**
1105
+ * @test
1106
+ * it should use bound singletons as singletons in instance methods
1107
+ */
1108
+ public function it_should_use_bound_singletons_as_singletons_in_instance_methods() {
1109
+ ClassTwelve::reset();
1110
+
1111
+ $container = new tad_DI52_Container();
1112
+
1113
+ $container->singleton('One', 'ClassOne');
1114
+
1115
+ $f = $container->instance('ClassTwelve', array('One'));
1116
+
1117
+ $this->assertInstanceOf('ClassOne', $f()->getVarOne());
1118
+ $this->assertSame($f()->getVarOne(), $f()->getVarOne());
1119
+ }
1120
+
1121
+ /**
1122
+ * @test
1123
+ * it should resolve bound objects in instance method
1124
+ */
1125
+ public function it_should_resolve_bound_objects_in_instance_method() {
1126
+ ClassTwelve::reset();
1127
+
1128
+ $container = new tad_DI52_Container();
1129
+
1130
+ $one = new ClassOne;
1131
+ $container->singleton('One', $one);
1132
+
1133
+ $f = $container->instance('ClassTwelve', array('One'));
1134
+
1135
+ $this->assertInstanceOf('ClassOne', $f()->getVarOne());
1136
+ $this->assertSame($one, $f()->getVarOne());
1137
+ }
1138
+
1139
+ /**
1140
+ * @test
1141
+ * it should allow binding an instance in the container
1142
+ */
1143
+ public function it_should_allow_binding_an_instance_in_the_container() {
1144
+ $container = new tad_DI52_Container();
1145
+
1146
+ $container->bind('One', $container->instance('ClassOneTwo', array('sudo-foo')));
1147
+
1148
+ $this->assertInstanceOf('ClassOneTwo', $container->make('One'));
1149
+ $this->assertEquals('sudo-foo', $container->make('One')->getFoo());
1150
+ $this->assertNotSame($container->make('One'), $container->make('One'));
1151
+ }
1152
+
1153
+ /**
1154
+ * @test
1155
+ * it should allow binding an instance as a singleton in the container
1156
+ */
1157
+ public function it_should_allow_binding_an_instance_as_a_singleton_in_the_container() {
1158
+ $container = new tad_DI52_Container();
1159
+
1160
+ $container->singleton('One', $container->instance('ClassOneTwo', array('sudo-foo')));
1161
+
1162
+ $this->assertInstanceOf('ClassOneTwo', $container->make('One'));
1163
+ $this->assertEquals('sudo-foo', $container->make('One')->getFoo());
1164
+ $this->assertSame($container->make('One'), $container->make('One'));
1165
+ }
1166
+
1167
+ /**
1168
+ * @test
1169
+ * it should build the instance with the container if not specifying arguments
1170
+ */
1171
+ public function it_should_build_the_instance_with_the_container_if_not_specifying_arguments() {
1172
+ $container = new tad_DI52_Container();
1173
+
1174
+ $container->bind('One', 'ClassOneTwo');
1175
+ $f = $container->instance('One');
1176
+
1177
+ $this->assertInstanceOf('ClassOneTwo', $f());
1178
+ $this->assertEquals('bar', $f()->getFoo());
1179
+ $this->assertNotSame($f(), $f());
1180
+ }
1181
+
1182
+ /**
1183
+ * @test
1184
+ * it should use container binding settings when instancing
1185
+ */
1186
+ public function it_should_use_container_binding_settings_when_instancing() {
1187
+ $container = new tad_DI52_Container();
1188
+
1189
+ $container->singleton('One', 'ClassOneTwo');
1190
+ $f = $container->instance('One');
1191
+
1192
+ $this->assertInstanceOf('ClassOneTwo', $f());
1193
+ $this->assertEquals('bar', $f()->getFoo());
1194
+ $this->assertSame($f(), $f());
1195
+ }
1196
+
1197
+ /**
1198
+ * @test
1199
+ * it should fetch correct objects when re-binding
1200
+ */
1201
+ public function it_should_fetch_correct_objects_when_re_binding() {
1202
+ $container = new tad_DI52_Container();
1203
+
1204
+ $container->bind('One', 'ClassOneOne');
1205
+
1206
+ $firstInstance = $container->make('ClassTwo');
1207
+
1208
+ $this->assertInstanceOf('ClassOneOne', $firstInstance->getOne());
1209
+
1210
+ $container->bind('One', 'ClassOne');
1211
+
1212
+ $secondInstance = $container->make('ClassTwo');
1213
+
1214
+ $this->assertInstanceOf('ClassOne', $secondInstance->getOne());
1215
+ }
1216
+
1217
+ /**
1218
+ * @test
1219
+ * it should allow re-binding objects
1220
+ */
1221
+ public function it_should_allow_re_binding_objects() {
1222
+ $container = new tad_DI52_Container();
1223
+
1224
+ $container->bind('One', new ClassOneOne());
1225
+
1226
+ $firstInstance = $container->make('ClassTwo');
1227
+
1228
+ $this->assertInstanceOf('ClassOneOne', $firstInstance->getOne());
1229
+
1230
+ $container->bind('One', new ClassOne());
1231
+
1232
+ $secondInstance = $container->make('ClassTwo');
1233
+
1234
+ $this->assertInstanceOf('ClassOne', $secondInstance->getOne());
1235
+ }
1236
+
1237
+ /**
1238
+ * @test
1239
+ * it should allow for built objects to passed to instance
1240
+ */
1241
+ public function it_should_allow_for_built_objects_to_passed_to_instance() {
1242
+ $container = new tad_DI52_Container();
1243
+
1244
+ $obj = new ClassFour('foo');
1245
+ $instance = $container->instance($obj);
1246
+
1247
+ $this->assertInstanceOf('ClassFour', $instance());
1248
+ }
1249
+
1250
+ /**
1251
+ * @test
1252
+ * it should allow for built objects to be passed in callback
1253
+ */
1254
+ public function it_should_allow_for_built_objects_to_be_passed_in_callback() {
1255
+ $container = new tad_DI52_Container();
1256
+
1257
+ $obj = new ClassFour('foo');
1258
+ $callback = $container->callback($obj, 'methodTwo');
1259
+
1260
+ $this->assertEquals(23, $callback());
1261
+ }
1262
+
1263
+ /**
1264
+ * @test
1265
+ * it should allow for callback to be fed to instance
1266
+ */
1267
+ public function it_should_allow_for_callback_to_be_fed_to_instance() {
1268
+ $container = new tad_DI52_Container();
1269
+
1270
+ $callback = $container->callback('Factory', 'build');
1271
+
1272
+ $instance = $container->instance($callback);
1273
+
1274
+ $this->assertInstanceOf('ClassOne', $instance());
1275
+ }
1276
+
1277
+ /**
1278
+ * @test
1279
+ * it should allow for instance to be fed to callback
1280
+ */
1281
+ public function it_should_allow_for_instance_to_be_fed_to_callback() {
1282
+ $container = new tad_DI52_Container();
1283
+
1284
+ $instance = $container->instance('Factory');
1285
+
1286
+ $callback = $container->callback($instance, 'build');
1287
+
1288
+ $this->assertInstanceOf('ClassOne', $callback());
1289
+ }
1290
+
1291
+ /**
1292
+ * @test
1293
+ * it should allow registering instance callbacks on class names
1294
+ */
1295
+ public function it_should_allow_registering_instance_callbacks_on_class_names() {
1296
+ $container = new tad_DI52_Container();
1297
+
1298
+ $instance = $container->instance('ClassThirteen');
1299
+
1300
+ $this->assertInstanceOf('ClassThirteen', $instance());
1301
+ }
1302
+
1303
+ /**
1304
+ * @test
1305
+ * it should allow registering instance callbacks on classes with constructor arguments
1306
+ */
1307
+ public function it_should_allow_registering_instance_callbacks_on_classes_with_constructor_arguments() {
1308
+ $container = new tad_DI52_Container();
1309
+ $container->bind('One', 'ClassOne');
1310
+
1311
+ $instance = $container->instance('ClassFifteen');
1312
+
1313
+ $this->assertInstanceOf('ClassFifteen', $instance());
1314
+ }
1315
+
1316
+ /**
1317
+ * @test
1318
+ * it should allow registering callback callbacks on class names
1319
+ */
1320
+ public function it_should_allow_registering_callback_callbacks_on_class_names() {
1321
+ $container = new tad_DI52_Container();
1322
+
1323
+ $callback = $container->callback('ClassThirteen', 'doSomething');
1324
+
1325
+ $this->assertEquals('IDidSomething', $callback());
1326
+ }
1327
+
1328
+ /**
1329
+ * @test
1330
+ * it should allow registering callback callbacks on classes with constructor arguments
1331
+ */
1332
+ public function it_should_allow_registering_callback_callbacks_on_classes_with_constructor_arguments() {
1333
+ $container = new tad_DI52_Container();
1334
+ $container->bind('One', 'ClassOne');
1335
+
1336
+ $callback = $container->callback('ClassFifteen', 'doSomething');
1337
+
1338
+ $this->assertEquals('IDidSomething', $callback());
1339
+ }
1340
+
1341
+ /**
1342
+ * It should return an interface argument default value if available and the interface is not bound
1343
+ *
1344
+ * @test
1345
+ */
1346
+ public function it_should_return_an_interface_argument_default_value_if_available_and_the_interface_is_not_bound() {
1347
+ $reflectionMethod = new ReflectionMethod('TestInterface','apiMethodOne');
1348
+ $params = $reflectionMethod->getParameters();
1349
+ $reflectionParameter = reset($params);
1350
+
1351
+ $container = new tad_DI52_Container();
1352
+ $value = $container->_getParameter($reflectionParameter);
1353
+
1354
+ $this->assertEquals(23, $value);
1355
+ }
1356
+
1357
+ /**
1358
+ * It should throw an exception when trying to resolve unbound interface parameter with no default value
1359
+ *
1360
+ * @test
1361
+ */
1362
+ public function it_should_throw_an_exception_when_trying_to_resolve_unbound_interface_parameter_with_no_default_value() {
1363
+ $reflectionMethod = new ReflectionMethod('TestInterface','apiMethodTwo');
1364
+ $params = $reflectionMethod->getParameters();
1365
+ $reflectionParameter = reset($params);
1366
+
1367
+ $this->setExpectedException('ReflectionException');
1368
+
1369
+ $container = new tad_DI52_Container();
1370
+ $container->_getParameter($reflectionParameter);
1371
+ }
1372
+
1373
+ /**
1374
+ * It should build not registered class dependencies anew each time
1375
+ *
1376
+ * @test
1377
+ */
1378
+ public function it_should_build_not_registered_class_dependencies_anew_each_time() {
1379
+ $container = new tad_DI52_Container();
1380
+
1381
+ $d1 = $container->make('Depending');
1382
+ $d2 = $container->make('Depending');
1383
+
1384
+ $this->assertNotSame($d1,$d2);
1385
+ $this->assertNotSame($d1->getDependency(),$d2->getDependency());
1386
+ }
1387
+
1388
+ /**
1389
+ * It should return different callbacks for different input objects
1390
+ *
1391
+ * @test
1392
+ */
1393
+ public function should_return_different_callbacks_for_different_input_objects() {
1394
+ $o1 = new TestObject(23);
1395
+ $o2 = new TestObject(89);
1396
+
1397
+ $container = new tad_DI52_Container();
1398
+
1399
+ $o1Callback = $container->callback($o1,'getNum');
1400
+ $o2Callback = $container->callback($o2,'getNum');
1401
+
1402
+ $this->assertNotSame($o1Callback,$o2Callback);
1403
+ $this->assertEquals(23,$o1Callback());
1404
+ $this->assertEquals(89,$o2Callback());
1405
+ }
1406
+
1407
+ /**
1408
+ * It should return same callback when created for same object instance
1409
+ *
1410
+ * @test
1411
+ */
1412
+ public function should_return_same_callback_when_created_for_same_object_instance() {
1413
+ $this->markTestSkipped('Not a feature yet.');
1414
+
1415
+ $o1 = new TestObject(23);
1416
+
1417
+ $container = new tad_DI52_Container();
1418
+
1419
+ $callback1 = $container->callback($o1,'getNum');
1420
+ $callback2 = $container->callback($o1,'getNum');
1421
+
1422
+ $this->assertSame($callback1,$callback2);
1423
+ $this->assertEquals(23,$callback1());
1424
+ $this->assertEquals(89,$callback2());
1425
+ }
1426
+
1427
+ /**
1428
+ * It should return the same callback when building for same class and static method
1429
+ *
1430
+ * @test
1431
+ */
1432
+ public function should_return_the_same_callback_when_building_for_same_class_and_static_method() {
1433
+ $container = new tad_DI52_Container();
1434
+
1435
+ $callback1 = $container->callback('TestObject','staticOne');
1436
+ $callback2 = $container->callback('TestObject','staticOne');
1437
+ $callback3 = $container->callback('TestObject','staticTwo');
1438
+ $callback4 = $container->callback('TestObject','staticTwo');
1439
+
1440
+ $this->assertSame($callback1,$callback2);
1441
+ $this->assertSame($callback3,$callback4);
1442
+ $this->assertNotSame($callback1,$callback3);
1443
+ $this->assertEquals('static one',$callback1());
1444
+ $this->assertEquals('static one',$callback2());
1445
+ $this->assertEquals('static two',$callback3());
1446
+ $this->assertEquals('static two',$callback4());
1447
+ }
1448
+ }
vendor/lucatume/di52/tests/52-compat/autoloadTest.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class autoloadTest extends PHPUnit_Framework_TestCase
5
+ {
6
+
7
+ public function projectClasses()
8
+ {
9
+ $classes = glob(dirname(dirname(dirname(__FILE__))) . '/src/tad/DI52/*.php');
10
+ $data = array();
11
+ foreach ($classes as $class) {
12
+ $name = 'tad_DI52_' . basename($class, '.php');
13
+ if ($name === 'closuresSupport') {
14
+ continue;
15
+ }
16
+ $data[] = array($name, $class);
17
+ }
18
+
19
+ return $data;
20
+ }
21
+
22
+ /**
23
+ * Autoload classes
24
+ *
25
+ * @dataProvider projectClasses
26
+ */
27
+ public function test_autoload_classes($className, $classPath)
28
+ {
29
+ include_once dirname(dirname(dirname(__FILE__))) . '/autoload.php';
30
+ $this->assertEquals($classPath, di52_findFile($className));
31
+ }
32
+ }
vendor/lucatume/di52/tests/53-above/Container53CompatTest.php ADDED
@@ -0,0 +1,811 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Container53CompatTest extends \PHPUnit_Framework_TestCase
4
+ {
5
+ /**
6
+ * @test
7
+ * it should allow setting a closure var on the container
8
+ */
9
+ public function it_should_allow_setting_a_closure_var_on_the_container()
10
+ {
11
+ $container = new tad_DI52_Container();
12
+
13
+ $closure = function ($value) {
14
+ return $value + 1;
15
+ };
16
+
17
+ $container->setVar('foo', $container->protect($closure));
18
+
19
+ $this->assertEquals($closure, $container->getVar('foo'));
20
+ }
21
+
22
+ /**
23
+ * @test
24
+ * it should allow setting a closure as a variable using the ArrayAccess API
25
+ */
26
+ public function it_should_allow_setting_a_closure_as_a_variable_using_the_array_access_api()
27
+ {
28
+ $container = new tad_DI52_Container();
29
+
30
+ $closure = function ($value) {
31
+ return $value + 1;
32
+ };
33
+
34
+ $container['foo'] = $container->protect($closure);
35
+
36
+ $this->assertEquals($closure, $container['foo']);
37
+ }
38
+
39
+ /**
40
+ * @test
41
+ * it should allow binding a closure as implementation of an interface
42
+ */
43
+ public function it_should_allow_binding_a_closure_as_implementation_of_an_interface()
44
+ {
45
+ $container = new tad_DI52_Container();
46
+
47
+ $container->bind(
48
+ 'One', function () {
49
+ return new ClassOne();
50
+ }
51
+ );
52
+
53
+ $this->assertInstanceOf('ClassOne', $container->make('One'));
54
+ }
55
+
56
+ /**
57
+ * @test
58
+ * it should pass the container as parameter to the closure implementation
59
+ */
60
+ public function it_should_pass_the_container_as_parameter_to_the_closure_implementation()
61
+ {
62
+ $container = new tad_DI52_Container();
63
+
64
+ $passedContainer = null;
65
+
66
+ $container->bind(
67
+ 'One', function ($container) use (&$passedContainer) {
68
+ $passedContainer = $container;
69
+ return new ClassOne();
70
+ }
71
+ );
72
+
73
+ $container->make('One');
74
+
75
+ $this->assertSame($container, $passedContainer);
76
+ }
77
+
78
+ /**
79
+ * @test
80
+ * it should allow binding a closure to a string slug
81
+ */
82
+ public function it_should_allow_binding_a_closure_to_a_string_slug()
83
+ {
84
+ $container = new tad_DI52_Container();
85
+
86
+ $container->bind(
87
+ 'foo.bar', function () {
88
+ return 23;
89
+ }
90
+ );
91
+
92
+ $this->assertEquals(23, $container->make('foo.bar'));
93
+ }
94
+
95
+ /**
96
+ * @test
97
+ * it should allow binding a closure to an interface as a singletong
98
+ */
99
+ public function it_should_allow_binding_a_closure_to_an_interface_as_a_singletong()
100
+ {
101
+ $container = new tad_DI52_Container();
102
+
103
+ $container->singleton(
104
+ 'One', function () {
105
+ return new ClassOne();
106
+ }
107
+ );
108
+
109
+ $this->assertInstanceOf('ClassOne', $container->make('One'));
110
+ $this->assertSame($container->make('One'), $container->make('One'));
111
+ }
112
+
113
+ /**
114
+ * @test
115
+ * it should allow binding a closure to a string slug as a singleton
116
+ */
117
+ public function it_should_allow_binding_a_closure_to_a_string_slug_as_a_singleton()
118
+ {
119
+ $container = new tad_DI52_Container();
120
+
121
+ $container->singleton(
122
+ 'foo.one', function () {
123
+ return new ClassOne();
124
+ }
125
+ );
126
+
127
+ $this->assertInstanceOf('ClassOne', $container->make('foo.one'));
128
+ $this->assertSame($container->make('foo.one'), $container->make('foo.one'));
129
+ }
130
+
131
+ public function namespacedKeysAndValues()
132
+ {
133
+ return array(
134
+ array('Acme\One', 'Acme\ClassOne'),
135
+ array('\Acme\One', '\Acme\ClassOne'),
136
+ array('Acme\One', '\Acme\ClassOne'),
137
+ array('\Acme\One', 'Acme\ClassOne'),
138
+ array('foo.one', '\Acme\ClassOne'),
139
+ array('foo.one', 'Acme\ClassOne'),
140
+ );
141
+ }
142
+
143
+ /**
144
+ * @test
145
+ * it should allow binding fully namespaced interfaces and classes with or without leading slash
146
+ * @dataProvider namespacedKeysAndValues
147
+ */
148
+ public function it_should_allow_binding_fully_namespaced_interfaces_and_classes_with_or_without_leading_slash(
149
+ $key,
150
+ $value
151
+ ) {
152
+ $container = new tad_DI52_Container();
153
+
154
+ $container->bind($key, $value);
155
+
156
+ $this->assertInstanceOf('\\' . ltrim($value, '\\'), $container->make($key));
157
+ }
158
+
159
+ /**
160
+ * @test
161
+ * it should allow tagging mixed values
162
+ */
163
+ public function it_should_allow_tagging_mixed_values()
164
+ {
165
+ $container = new tad_DI52_Container();
166
+
167
+ $container->tag(
168
+ array(
169
+ 'ClassOne',
170
+ new ClassOneOne(),
171
+ function ($container) {
172
+ return $container->make('ClassOneTwo');
173
+ }
174
+ ), 'foo'
175
+ );
176
+ $made = $container->tagged('foo');
177
+
178
+ $this->assertInstanceOf('ClassOne', $made[0]);
179
+ $this->assertInstanceOf('ClassOneOne', $made[1]);
180
+ $this->assertInstanceOf('ClassOneTwo', $made[2]);
181
+ }
182
+
183
+ /**
184
+ * @test
185
+ * it should allow contextual binding of closures
186
+ */
187
+ public function it_should_allow_contextual_binding_of_closures()
188
+ {
189
+ $container = new tad_DI52_Container();
190
+
191
+ $container->when('ClassSixOne')
192
+ ->needs('ClassOne')
193
+ ->give(
194
+ function ($container) {
195
+ return $container->make('ExtendingClassOneOne');
196
+ }
197
+ );
198
+
199
+ $container->when('ClassSevenOne')
200
+ ->needs('ClassOne')
201
+ ->give(
202
+ function ($container) {
203
+ return $container->make('ExtendingClassOneTwo');
204
+ }
205
+ );
206
+
207
+ $this->assertInstanceOf('ClassOne', $container->make('ClassOne'));
208
+ $this->assertInstanceOf('ExtendingClassOneOne', $container->make('ClassSixOne')->getOne());
209
+ $this->assertInstanceOf('ExtendingClassOneTwo', $container->make('ClassSevenOne')->getOne());
210
+ }
211
+
212
+ /**
213
+ * @test
214
+ * it should call a closure when bound to an offset in ArrayAccess API
215
+ */
216
+ public function it_should_call_a_closure_when_bound_to_an_offset_in_array_access_api()
217
+ {
218
+ $container = new tad_DI52_Container();
219
+
220
+ $container['foo'] = function () {
221
+ return 'bar';
222
+ };
223
+
224
+ $this->assertEquals('bar', $container['foo']);
225
+ }
226
+
227
+ /**
228
+ * @test
229
+ * it should replace a binding when re-binding
230
+ */
231
+ public function it_should_replace_a_binding_when_re_binding()
232
+ {
233
+ $container = new tad_DI52_Container();
234
+
235
+ $container->bind(
236
+ 'One', function ($container) {
237
+ return $container->make('ClassOne');
238
+ }
239
+ );
240
+
241
+ $this->assertInstanceOf('ClassOne', $container->make('One'));
242
+
243
+ $container->bind(
244
+ 'One', function ($container) {
245
+ return $container->make('ClassOneOne');
246
+ }
247
+ );
248
+
249
+ $this->assertInstanceOf('ClassOneOne', $container->make('One'));
250
+ }
251
+
252
+ /**
253
+ * @test
254
+ * it should replace a singleton bind when re-binding a singleton binding
255
+ */
256
+ public function it_should_replace_a_singleton_bind_when_re_binding_a_singleton_binding()
257
+ {
258
+ $container = new tad_DI52_Container();
259
+
260
+ $container->singleton(
261
+ 'One', function ($container) {
262
+ return $container->make('ClassOne');
263
+ }
264
+ );
265
+
266
+ $this->assertInstanceOf('ClassOne', $container->make('One'));
267
+
268
+ $container->bind(
269
+ 'One', function ($container) {
270
+ return $container->make('ClassOneOne');
271
+ }
272
+ );
273
+
274
+ $this->assertInstanceOf('ClassOneOne', $container->make('One'));
275
+ $this->assertNotSame($container->make('One'), $container->make('One'));
276
+ }
277
+
278
+ /**
279
+ * @test
280
+ * it should replace bind with singleton if re-binding as singleton
281
+ */
282
+ public function it_should_replace_bind_with_singleton_if_re_binding_as_singleton()
283
+ {
284
+ $container = new tad_DI52_Container();
285
+
286
+ $container->singleton(
287
+ 'One', function ($container) {
288
+ return $container->make('ClassOne');
289
+ }
290
+ );
291
+
292
+ $this->assertInstanceOf('ClassOne', $container->make('One'));
293
+ $this->assertSame($container->make('One'), $container->make('One'));
294
+
295
+ $container->singleton(
296
+ 'One', function ($container) {
297
+ return $container->make('ClassOneOne');
298
+ }
299
+ );
300
+
301
+ $this->assertInstanceOf('ClassOneOne', $container->make('One'));
302
+ $this->assertSame($container->make('One'), $container->make('One'));
303
+ }
304
+
305
+ /**
306
+ * @test
307
+ * it should replace singleton with simple bind if re-binding as non singleton
308
+ */
309
+ public function it_should_replace_singleton_with_simple_bind_if_re_binding_as_non_singleton()
310
+ {
311
+ $container = new tad_DI52_Container();
312
+
313
+ $container->singleton(
314
+ 'One', function ($container) {
315
+ return $container->make('ClassOne');
316
+ }
317
+ );
318
+
319
+ $this->assertInstanceOf('ClassOne', $container->make('One'));
320
+ $this->assertSame($container->make('One'), $container->make('One'));
321
+
322
+ $container->bind(
323
+ 'One', function ($container) {
324
+ return $container->make('ClassOneOne');
325
+ }
326
+ );
327
+
328
+ $this->assertInstanceOf('ClassOneOne', $container->make('One'));
329
+ $this->assertNotSame($container->make('One'), $container->make('One'));
330
+ }
331
+
332
+ /**
333
+ * @test
334
+ * it should allow to lazy make a closure
335
+ */
336
+ public function it_should_allow_to_lazy_make_a_closure()
337
+ {
338
+ $container = new tad_DI52_Container();
339
+
340
+ $container->bind(
341
+ 'foo', function ($container) {
342
+ return $container->make('FourBase');
343
+ }
344
+ );
345
+
346
+ $f = $container->callback('foo', 'methodThree');
347
+
348
+ $this->assertEquals(28, $f(5));
349
+ }
350
+
351
+ /**
352
+ * @test
353
+ * it should resolve bound closures in instance method
354
+ */
355
+ public function it_should_resolve_bound_closures_in_instance_method()
356
+ {
357
+ ClassTwelve::reset();
358
+
359
+ $container = new tad_DI52_Container();
360
+
361
+ $one = function ($container) {
362
+ return $container->make('ClassOne');
363
+ };
364
+
365
+ $container->bind('One', $one);
366
+
367
+ $f = $container->instance('ClassTwelve', array('One'));
368
+
369
+ $this->assertInstanceOf('ClassOne', $f()->getVarOne());
370
+ }
371
+
372
+ /**
373
+ * @test
374
+ * it should resolve singleton closures in instance method
375
+ */
376
+ public function it_should_resolve_singleton_closures_in_instance_method()
377
+ {
378
+ ClassTwelve::reset();
379
+
380
+ $container = new tad_DI52_Container();
381
+
382
+ $one = function ($container) {
383
+ return $container->make('ClassOne');
384
+ };
385
+
386
+ $container->singleton('One', $one);
387
+
388
+ $f = $container->instance('ClassTwelve', array('One'));
389
+
390
+ $this->assertInstanceOf('ClassOne', $f()->getVarOne());
391
+ $this->assertSame($f()->getVarOne(), $f()->getVarOne());
392
+ }
393
+
394
+ /**
395
+ * @test
396
+ * it should resolve slug bound closures in instance method
397
+ */
398
+ public function it_should_resolve_slug_bound_closures_in_instance_method()
399
+ {
400
+ ClassTwelve::reset();
401
+
402
+ $container = new tad_DI52_Container();
403
+
404
+ $one = function ($container) {
405
+ return $container->make('ClassOne');
406
+ };
407
+
408
+ $container->bind('foo', $one);
409
+
410
+ $f = $container->instance('ClassTwelve', array('foo'));
411
+
412
+ $this->assertInstanceOf('ClassOne', $f()->getVarOne());
413
+ $this->assertNotSame($f()->getVarOne(), $f()->getVarOne());
414
+ }
415
+
416
+ /**
417
+ * @test
418
+ * it should resolve singleton slug bound closures in instance method
419
+ */
420
+ public function it_should_resolve_singleton_slug_bound_closures_in_instance_method()
421
+ {
422
+ ClassTwelve::reset();
423
+
424
+ $container = new tad_DI52_Container();
425
+
426
+ $one = function ($container) {
427
+ return $container->make('ClassOne');
428
+ };
429
+
430
+ $container->singleton('foo', $one);
431
+
432
+ $f = $container->instance('ClassTwelve', array('foo'));
433
+
434
+ $this->assertInstanceOf('ClassOne', $f()->getVarOne());
435
+ $this->assertSame($f()->getVarOne(), $f()->getVarOne());
436
+ }
437
+
438
+ /**
439
+ * @test
440
+ * it should allow binding and getting an object built as a closure
441
+ */
442
+ public function it_should_allow_binding_and_getting_an_object_built_as_a_closure()
443
+ {
444
+ $container = new tad_DI52_Container();
445
+
446
+ $container->bind(
447
+ 'One', function ($container) {
448
+ return $container->make('ClassOne');
449
+ }
450
+ );
451
+
452
+ $this->assertInstanceOf('ClassOne', $container['One']);
453
+ $this->assertNotSame($container['One'], $container['One']);
454
+ }
455
+
456
+ /**
457
+ * @test
458
+ * it should allow getting a callback to build an object
459
+ */
460
+ public function it_should_allow_getting_a_callback_to_build_an_object()
461
+ {
462
+ Acme\ClassTen::reset();
463
+
464
+ $container = new tad_DI52_Container();
465
+
466
+ $f = $container->instance('Acme\ClassTen', array('foo', 'baz', 'bar'));
467
+
468
+ $this->assertEquals(0, Acme\ClassTen::$builtTimes);
469
+
470
+ $instance1 = $f();
471
+
472
+ $this->assertEquals(1, Acme\ClassTen::$builtTimes);
473
+ $this->assertEquals('foo', $instance1->getVarOne());
474
+ $this->assertEquals('baz', $instance1->getVarTwo());
475
+ $this->assertEquals('bar', $instance1->getVarThree());
476
+
477
+ $instance2 = $f();
478
+
479
+ $this->assertEquals(2, Acme\ClassTen::$builtTimes);
480
+ $this->assertEquals('foo', $instance2->getVarOne());
481
+ $this->assertEquals('baz', $instance2->getVarTwo());
482
+ $this->assertEquals('bar', $instance2->getVarThree());
483
+
484
+ $instance3 = $f();
485
+
486
+ $this->assertEquals(3, Acme\ClassTen::$builtTimes);
487
+ $this->assertEquals('foo', $instance3->getVarOne());
488
+ $this->assertEquals('baz', $instance3->getVarTwo());
489
+ $this->assertEquals('bar', $instance3->getVarThree());
490
+ }
491
+
492
+ /**
493
+ * @test
494
+ * it should allow getting a callback to build an object with scalar and object dependencies
495
+ */
496
+ public function it_should_allow_getting_a_callback_to_build_an_object_with_scalar_and_object_dependencies()
497
+ {
498
+ Acme\ClassEleven::reset();
499
+
500
+ $container = new tad_DI52_Container();
501
+
502
+ $container->bind('Acme\One', 'Acme\ClassOne');
503
+ $container->bind('Acme\Two', 'Acme\ClassTwo');
504
+
505
+ $f = $container->instance('Acme\ClassEleven', array('Acme\ClassOne', 'Acme\Two', 'bar'));
506
+
507
+ $this->assertEquals(0, Acme\ClassEleven::$builtTimes);
508
+
509
+ $instance1 = $f();
510
+
511
+ $this->assertEquals(1, Acme\ClassEleven::$builtTimes);
512
+ $this->assertInstanceOf('Acme\ClassOne', $instance1->getVarOne());
513
+ $this->assertInstanceOf('Acme\ClassTwo', $instance1->getVarTwo());
514
+ $this->assertInstanceOf('Acme\ClassOne', $instance1->getVarTwo()->getOne());
515
+ $this->assertEquals('bar', $instance1->getVarThree());
516
+
517
+ $instance2 = $f();
518
+
519
+ $this->assertEquals(2, Acme\ClassEleven::$builtTimes);
520
+ $this->assertInstanceOf('Acme\ClassOne', $instance2->getVarOne());
521
+ $this->assertInstanceOf('Acme\ClassTwo', $instance2->getVarTwo());
522
+ $this->assertInstanceOf('Acme\ClassOne', $instance2->getVarTwo()->getOne());
523
+ $this->assertEquals('bar', $instance2->getVarThree());
524
+
525
+ $instance3 = $f();
526
+
527
+ $this->assertEquals(3, Acme\ClassEleven::$builtTimes);
528
+ $this->assertInstanceOf('Acme\ClassOne', $instance3->getVarOne());
529
+ $this->assertInstanceOf('Acme\ClassTwo', $instance3->getVarTwo());
530
+ $this->assertInstanceOf('Acme\ClassOne', $instance3->getVarTwo()->getOne());
531
+ $this->assertEquals('bar', $instance3->getVarThree());
532
+ }
533
+
534
+ /**
535
+ * @test
536
+ * it should instance using bound implementations
537
+ */
538
+ public function it_should_instance_using_bound_implementations()
539
+ {
540
+ Acme\ClassTwelve::reset();
541
+
542
+ $container = new tad_DI52_Container();
543
+
544
+ $container->bind('Acme\One', 'Acme\ClassOne');
545
+ $container->bind('Acme\ClassOne', 'Acme\ClassOne');
546
+
547
+ $f = $container->instance('Acme\ClassTwelve', array('Acme\ClassOne'));
548
+
549
+ $instance1 = $f();
550
+
551
+ $this->assertEquals(1, Acme\ClassTwelve::$builtTimes);
552
+ $this->assertInstanceOf('Acme\ClassOne', $instance1->getVarOne());
553
+ }
554
+
555
+ /**
556
+ * @test
557
+ * it should allow overriding bound implementations in instance method
558
+ */
559
+ public function it_should_allow_overriding_bound_implementations_in_instance_method()
560
+ {
561
+ Acme\ClassTwelve::reset();
562
+
563
+ $container = new tad_DI52_Container();
564
+
565
+ $container->bind('Acme\ClassOne', 'Acme\ClassOne');
566
+
567
+ $f = $container->instance('Acme\ClassTwelve', array('Acme\ClassOneOne'));
568
+
569
+ $instance1 = $f();
570
+
571
+ $this->assertEquals(1, Acme\ClassTwelve::$builtTimes);
572
+ $this->assertInstanceOf('Acme\ClassOneOne', $instance1->getVarOne());
573
+ }
574
+
575
+ /**
576
+ * @test
577
+ * it should allow referring bound slugs in instance method
578
+ */
579
+ public function it_should_allow_referring_bound_slugs_in_instance_method()
580
+ {
581
+ Acme\ClassTwelve::reset();
582
+
583
+ $container = new tad_DI52_Container();
584
+
585
+ $container->bind('foo', 'Acme\ClassOne');
586
+
587
+ $f = $container->instance('Acme\ClassTwelve', array('foo'));
588
+
589
+ $instance1 = $f();
590
+
591
+ $this->assertEquals(1, Acme\ClassTwelve::$builtTimes);
592
+ $this->assertInstanceOf('Acme\ClassOne', $instance1->getVarOne());
593
+ }
594
+
595
+ /**
596
+ * @test
597
+ * it should use bound singletons as singletons in instance methods
598
+ */
599
+ public function it_should_use_bound_singletons_as_singletons_in_instance_methods()
600
+ {
601
+ Acme\ClassTwelve::reset();
602
+
603
+ $container = new tad_DI52_Container();
604
+
605
+ $container->singleton('Acme\ClassOne', 'Acme\ClassOne');
606
+
607
+ $f = $container->instance('Acme\ClassTwelve', array('Acme\ClassOne'));
608
+
609
+ $this->assertInstanceOf('Acme\ClassOne', $f()->getVarOne());
610
+ $this->assertSame($f()->getVarOne(), $f()->getVarOne());
611
+ }
612
+
613
+ /**
614
+ * @test
615
+ * it should resolve bound objects in instance method
616
+ */
617
+ public function it_should_resolve_bound_objects_in_instance_method()
618
+ {
619
+ Acme\ClassTwelve::reset();
620
+
621
+ $container = new tad_DI52_Container();
622
+
623
+ $one = new Acme\ClassOne;
624
+ $container->singleton('Acme\ClassOne', $one);
625
+
626
+ $f = $container->instance('Acme\ClassTwelve', array('Acme\ClassOne'));
627
+
628
+ $this->assertInstanceOf('Acme\ClassOne', $f()->getVarOne());
629
+ $this->assertSame($one, $f()->getVarOne());
630
+ }
631
+
632
+ /**
633
+ * @test
634
+ * it should allow binding an instance in the container
635
+ */
636
+ public function it_should_allow_binding_an_instance_in_the_container()
637
+ {
638
+ $container = new tad_DI52_Container();
639
+
640
+ $container->bind('Acme\ClassOne', $container->instance('Acme\ClassOneTwo', array('sudo-foo')));
641
+
642
+ $this->assertInstanceOf('Acme\ClassOneTwo', $container->make('Acme\ClassOne'));
643
+ $this->assertEquals('sudo-foo', $container->make('Acme\ClassOne')->getFoo());
644
+ $this->assertNotSame($container->make('Acme\ClassOne'), $container->make('Acme\ClassOne'));
645
+ }
646
+
647
+ /**
648
+ * @test
649
+ * it should allow binding an instance as a singleton in the container
650
+ */
651
+ public function it_should_allow_binding_an_instance_as_a_singleton_in_the_container()
652
+ {
653
+ $container = new tad_DI52_Container();
654
+
655
+ $container->singleton('Acme\ClassOne', $container->instance('Acme\ClassOneTwo', array('sudo-foo')));
656
+
657
+ $this->assertInstanceOf('Acme\ClassOneTwo', $container->make('Acme\ClassOne'));
658
+ $this->assertEquals('sudo-foo', $container->make('Acme\ClassOne')->getFoo());
659
+ $this->assertSame($container->make('Acme\ClassOne'), $container->make('Acme\ClassOne'));
660
+ }
661
+
662
+ /**
663
+ * @test
664
+ * it should build the instance with the container if not specifying arguments
665
+ */
666
+ public function it_should_build_the_instance_with_the_container_if_not_specifying_arguments()
667
+ {
668
+ $container = new tad_DI52_Container();
669
+
670
+ $container->bind('Acme\ClassOne', 'Acme\ClassOneTwo');
671
+ $f = $container->instance('Acme\ClassOne');
672
+
673
+ $this->assertInstanceOf('Acme\ClassOneTwo', $f());
674
+ $this->assertEquals('bar', $f()->getFoo());
675
+ $this->assertNotSame($f(), $f());
676
+ }
677
+
678
+ /**
679
+ * @test
680
+ * it should use container binding settings when instancing
681
+ */
682
+ public function it_should_use_container_binding_settings_when_instancing()
683
+ {
684
+ $container = new tad_DI52_Container();
685
+
686
+ $container->singleton('Acme\ClassOne', 'Acme\ClassOneTwo');
687
+ $f = $container->instance('Acme\ClassOne');
688
+
689
+ $this->assertInstanceOf('Acme\ClassOneTwo', $f());
690
+ $this->assertEquals('bar', $f()->getFoo());
691
+ $this->assertSame($f(), $f());
692
+ }
693
+
694
+ /**
695
+ * @test
696
+ * it should allow re-binding closuress
697
+ */
698
+ public function it_should_allow_re_binding_closuress()
699
+ {
700
+ $container = new tad_DI52_Container();
701
+
702
+ $container->bind('One', function () {
703
+ return new ClassOneOne();
704
+ });
705
+
706
+ $firstInstance = $container->make('ClassTwo');
707
+
708
+ $this->assertInstanceOf('ClassOneOne', $firstInstance->getOne());
709
+
710
+ $container->bind('One', function () {
711
+ return new ClassOne();
712
+ });
713
+
714
+ $secondInstance = $container->make('ClassTwo');
715
+
716
+ $this->assertInstanceOf('ClassOne', $secondInstance->getOne());
717
+ }
718
+ /**
719
+ * @test
720
+ * it should allow for callback to be fed to instance
721
+ */
722
+ public function it_should_allow_for_callback_to_be_fed_to_instance() {
723
+ $container = new tad_DI52_Container();
724
+
725
+ $callback = $container->callback('Acme\Factory', 'build');
726
+
727
+ $instance = $container->instance($callback);
728
+
729
+ $this->assertInstanceOf('Acme\ClassOne', $instance());
730
+ }
731
+
732
+ /**
733
+ * @test
734
+ * it should allow for instance to be fed to callback
735
+ */
736
+ public function it_should_allow_for_instance_to_be_fed_to_callback() {
737
+ $container = new tad_DI52_Container();
738
+
739
+ $instance = $container->instance('Acme\Factory');
740
+
741
+ $callback = $container->callback($instance, 'build');
742
+
743
+ $this->assertInstanceOf('Acme\ClassOne', $callback());
744
+ }
745
+
746
+ /**
747
+ * @test
748
+ * it should allow to bind with one parameter
749
+ */
750
+ public function it_should_allow_to_bind_with_one_parameter() {
751
+ $container = new tad_DI52_Container();
752
+
753
+ $container->bind('ClassFourteen');
754
+
755
+ $instance = $container->make('ClassFourteen');
756
+
757
+ $this->assertInstanceOf('ClassFourteen', $instance);
758
+ }
759
+
760
+ /**
761
+ * @test
762
+ * it should allow to bind singleton with one parameter
763
+ */
764
+ public function it_should_allow_to_bind_singleton_with_one_parameter() {
765
+ $container = new tad_DI52_Container();
766
+
767
+ $container->singleton('ClassFourteen');
768
+
769
+ $instance1 = $container->make('ClassFourteen');
770
+ $instance2 = $container->make('ClassFourteen');
771
+
772
+ $this->assertInstanceOf('ClassFourteen', $instance1);
773
+ $this->assertEquals($instance1, $instance2);
774
+ }
775
+
776
+ /** @test */
777
+ public function it_should_throw_if_binding_string_with_one_parameter() {
778
+ $this->setExpectedException('ReflectionException');
779
+
780
+ $container = new tad_DI52_Container();
781
+
782
+ $container->bind('not-a-class');
783
+ }
784
+
785
+ /** @test */
786
+ public function it_should_throw_if_binding_interface_with_one_parameter() {
787
+ $this->setExpectedException('InvalidArgumentException');
788
+
789
+ $container = new tad_DI52_Container();
790
+
791
+ $container->bind('One');
792
+ }
793
+
794
+ /** @test */
795
+ public function it_should_throw_if_binding_abstract_with_one_parameter() {
796
+ $this->setExpectedException('InvalidArgumentException');
797
+
798
+ $container = new tad_DI52_Container();
799
+
800
+ $container->bind('AbstractClass');
801
+ }
802
+
803
+ /** @test */
804
+ public function it_should_throw_if_binding_private_constructor_with_one_parameter() {
805
+ $this->setExpectedException('InvalidArgumentException');
806
+
807
+ $container = new tad_DI52_Container();
808
+
809
+ $container->bind('PrivateConstructor');
810
+ }
811
+ }
vendor/lucatume/di52/tests/bootstrap.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+ require_once dirname(dirname(__FILE__)) . '/vendor/autoload_52.php';
3
+ require_once dirname(__FILE__) . '/data/test-classes.php';
4
+ if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
5
+ require_once dirname(__FILE__) . '/data/namespaced-test-classes.php';
6
+ }
7
+ require_once dirname(__FILE__) . '/data/test-providers.php';
vendor/lucatume/di52/tests/data/namespaced-test-classes.php ADDED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Acme;
4
+
5
+ interface One
6
+ {
7
+
8
+ }
9
+
10
+ interface Two
11
+ {
12
+
13
+ }
14
+
15
+ class ClassOne implements One
16
+ {
17
+
18
+ }
19
+
20
+ class ClassOneOne implements One
21
+ {
22
+ public function __construct()
23
+ {
24
+
25
+ }
26
+ }
27
+
28
+ class ClassOneTwo implements One
29
+ {
30
+ /**
31
+ * @var string
32
+ */
33
+ private $foo;
34
+
35
+ public function __construct($foo = 'bar')
36
+ {
37
+
38
+ $this->foo = $foo;
39
+ }
40
+
41
+ /**
42
+ * @return string
43
+ */
44
+ public function getFoo()
45
+ {
46
+ return $this->foo;
47
+ }
48
+ }
49
+
50
+ class ClassTwo implements Two
51
+ {
52
+ /**
53
+ * @var One
54
+ */
55
+ private $one;
56
+
57
+ public function __construct(One $one)
58
+ {
59
+
60
+ $this->one = $one;
61
+ }
62
+
63
+ /**
64
+ * @return One
65
+ */
66
+ public function getOne()
67
+ {
68
+ return $this->one;
69
+ }
70
+ }
71
+
72
+ class ClassTen
73
+ {
74
+ public static $builtTimes = 0;
75
+ private $varOne;
76
+ private $varTwo;
77
+ private $varThree;
78
+
79
+ public static function reset()
80
+ {
81
+ self::$builtTimes = 0;
82
+ }
83
+
84
+ public function __construct($varOne, $varTwo, $varThree)
85
+ {
86
+ self::$builtTimes++;
87
+ $this->varOne = $varOne;
88
+ $this->varTwo = $varTwo;
89
+ $this->varThree = $varThree;
90
+ }
91
+
92
+ public function getVarOne()
93
+ {
94
+ return $this->varOne;
95
+ }
96
+
97
+ public function getVarTwo()
98
+ {
99
+ return $this->varTwo;
100
+ }
101
+
102
+ public function getVarThree()
103
+ {
104
+ return $this->varThree;
105
+ }
106
+ }
107
+
108
+ class ClassEleven
109
+ {
110
+ public static $builtTimes = 0;
111
+ private $varOne;
112
+ private $varTwo;
113
+ private $varThree;
114
+
115
+ public static function reset()
116
+ {
117
+ self::$builtTimes = 0;
118
+ }
119
+
120
+ public function __construct(One $varOne, ClassTwo $varTwo, $varThree)
121
+ {
122
+ self::$builtTimes++;
123
+ $this->varOne = $varOne;
124
+ $this->varTwo = $varTwo;
125
+ $this->varThree = $varThree;
126
+ }
127
+
128
+ public function getVarOne()
129
+ {
130
+ return $this->varOne;
131
+ }
132
+
133
+ public function getVarTwo()
134
+ {
135
+ return $this->varTwo;
136
+ }
137
+
138
+ public function getVarThree()
139
+ {
140
+ return $this->varThree;
141
+ }
142
+ }
143
+
144
+ class ClassTwelve
145
+ {
146
+ public static $builtTimes = 0;
147
+ private $varOne;
148
+
149
+ public static function reset()
150
+ {
151
+ self::$builtTimes = 0;
152
+ }
153
+
154
+ public function __construct(One $varOne)
155
+ {
156
+ self::$builtTimes++;
157
+ $this->varOne = $varOne;
158
+ }
159
+
160
+ public function getVarOne()
161
+ {
162
+ return $this->varOne;
163
+ }
164
+ }
165
+
166
+ class Factory {
167
+ public function build() {
168
+ return new ClassOne();
169
+ }
170
+ }
vendor/lucatume/di52/tests/data/test-classes.php ADDED
@@ -0,0 +1,435 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ interface One {
4
+
5
+ }
6
+
7
+ interface Two {
8
+
9
+ }
10
+
11
+ interface Four {
12
+
13
+ }
14
+
15
+ interface Five {
16
+
17
+ }
18
+
19
+ class ClassOne implements One {
20
+
21
+ }
22
+
23
+ class ExtendingClassOneOne extends ClassOne {
24
+
25
+ }
26
+
27
+ class ExtendingClassOneTwo extends ClassOne {
28
+
29
+ }
30
+
31
+ class ClassOneOne implements One {
32
+ public function __construct() {
33
+
34
+ }
35
+ }
36
+
37
+ class ClassOneTwo implements One {
38
+ /**
39
+ * @var string
40
+ */
41
+ private $foo;
42
+
43
+ public function __construct($foo = 'bar') {
44
+
45
+ $this->foo = $foo;
46
+ }
47
+
48
+ /**
49
+ * @return string
50
+ */
51
+ public function getFoo() {
52
+ return $this->foo;
53
+ }
54
+ }
55
+
56
+ class ClassOneThree {
57
+ public $oneCalled;
58
+ public $twoCalled;
59
+
60
+ public function methodOne() {
61
+ $this->oneCalled = true;
62
+ }
63
+
64
+ public function methodTwo() {
65
+ $this->twoCalled = true;
66
+ }
67
+ }
68
+
69
+ class ClassTwo implements Two {
70
+ /**
71
+ * @var One
72
+ */
73
+ private $one;
74
+
75
+ public function __construct(One $one) {
76
+
77
+ $this->one = $one;
78
+ }
79
+
80
+ /**
81
+ * @return One
82
+ */
83
+ public function getOne() {
84
+ return $this->one;
85
+ }
86
+ }
87
+
88
+ class ClassTwoOne implements Two {
89
+ private $one;
90
+
91
+ public function __construct(ClassOne $one) {
92
+
93
+ $this->one = $one;
94
+ }
95
+
96
+ public function getOne() {
97
+ return $this->one;
98
+ }
99
+ }
100
+
101
+ class ClassTwoTwo implements Two {
102
+ public function __construct(One $one) {
103
+
104
+ }
105
+ }
106
+
107
+ class ClassThree {
108
+ public function __construct(One $one, Two $two, $three = 3) {
109
+
110
+ }
111
+ }
112
+
113
+ class ClassThreeOne {
114
+ public function __construct(One $one, ClassTwo $two, $three = 3) {
115
+
116
+ }
117
+ }
118
+
119
+ class ClassThreeTwo {
120
+ public function __construct(ClassOne $one, ClassOneOne $two, $three = 3) {
121
+
122
+ }
123
+ }
124
+
125
+ class ClassFour {
126
+ public function __construct($some) {
127
+
128
+ }
129
+
130
+ public function methodOne($n) {
131
+ return $n + 23;
132
+ }
133
+
134
+ public function methodTwo() {
135
+ return 23;
136
+ }
137
+ }
138
+
139
+ class FourBase implements Four {
140
+ public function __construct() {
141
+
142
+ }
143
+
144
+ public function methodOne() {
145
+ global $one;
146
+ $one = __CLASS__;
147
+ }
148
+
149
+ public function methodTwo() {
150
+ global $two;
151
+ $two = __CLASS__;
152
+ }
153
+
154
+ public function methodThree($n) {
155
+ return $n + 23;
156
+ }
157
+ }
158
+
159
+ class FourTwo implements Four {
160
+
161
+ }
162
+
163
+ class FourDecoratorOne implements Four {
164
+ public function __construct(Four $decorated) {
165
+
166
+ }
167
+
168
+ public function methodOne($n) {
169
+ return $n + 23;
170
+ }
171
+ }
172
+
173
+ class FourDecoratorTwo implements Four {
174
+ public function __construct(Four $decorated) {
175
+
176
+ }
177
+ }
178
+
179
+ class FourDecoratorThree implements Four {
180
+ public function __construct(Four $decorated) {
181
+
182
+ }
183
+ }
184
+
185
+ class FiveBase implements Five {
186
+ public function __construct($foo = 10) {
187
+ }
188
+ }
189
+
190
+ class FiveDecoratorOne implements Five {
191
+ public function __construct(Five $five, Four $four) {
192
+
193
+ }
194
+ }
195
+
196
+ class FiveDecoratorTwo implements Five {
197
+ public function __construct(Five $five, One $one) {
198
+
199
+ }
200
+ }
201
+
202
+ class FiveDecoratorThree implements Five {
203
+ public function __construct(Five $five, Two $two) {
204
+
205
+ }
206
+ }
207
+
208
+ class FiveTwo implements Five {
209
+
210
+ }
211
+
212
+
213
+ class ClassSix {
214
+ private $one;
215
+
216
+ public function __construct(One $one) {
217
+ $this->one = $one;
218
+ }
219
+
220
+ public function getOne() {
221
+ return $this->one;
222
+ }
223
+ }
224
+
225
+ class ClassSeven {
226
+ private $one;
227
+
228
+ public function __construct(One $one) {
229
+
230
+ $this->one = $one;
231
+ }
232
+
233
+ public function getOne() {
234
+ return $this->one;
235
+ }
236
+ }
237
+
238
+ class ClassSixOne {
239
+ private $one;
240
+
241
+ public function __construct(ClassOne $one) {
242
+ $this->one = $one;
243
+ }
244
+
245
+ public function getOne() {
246
+ return $this->one;
247
+ }
248
+ }
249
+
250
+ class ClassSevenOne {
251
+ private $one;
252
+
253
+ public function __construct(ClassOne $one) {
254
+
255
+ $this->one = $one;
256
+ }
257
+
258
+ public function getOne() {
259
+ return $this->one;
260
+ }
261
+ }
262
+
263
+ interface Eight {
264
+ public function methodOne();
265
+
266
+ public function methodTwo();
267
+
268
+ public function methodThree();
269
+ }
270
+
271
+ class ClassEight implements Eight {
272
+ public static $called = array();
273
+ public static $calledWith = array();
274
+
275
+ public static function reset() {
276
+ self::$called = array();
277
+ self::$calledWith = array();
278
+ }
279
+
280
+ public function methodOne() {
281
+ self::$called[] = 'methodOne';
282
+ }
283
+
284
+ public function methodTwo() {
285
+ self::$called[] = 'methodTwo';
286
+ }
287
+
288
+ public function methodThree() {
289
+ self::$called[] = 'methodThree';
290
+ }
291
+
292
+ public function methodFour() {
293
+ self::$calledWith = func_get_args();
294
+ }
295
+ }
296
+
297
+ class ClassEightExtension extends ClassEight {
298
+ }
299
+
300
+ class ClassNine {
301
+ public function __construct() {
302
+
303
+ }
304
+
305
+ public static function reset() {
306
+ unset($GLOBALS['nine']);
307
+ }
308
+
309
+ public function methodOne() {
310
+ $GLOBALS['nine'] = 'called';
311
+ }
312
+ }
313
+
314
+ class ClassTen {
315
+ public static $builtTimes = 0;
316
+ private $varOne;
317
+ private $varTwo;
318
+ private $varThree;
319
+
320
+ public static function reset() {
321
+ self::$builtTimes = 0;
322
+ }
323
+
324
+ public function __construct($varOne, $varTwo, $varThree) {
325
+ self::$builtTimes++;
326
+ $this->varOne = $varOne;
327
+ $this->varTwo = $varTwo;
328
+ $this->varThree = $varThree;
329
+ }
330
+
331
+ public function getVarOne() {
332
+ return $this->varOne;
333
+ }
334
+
335
+ public function getVarTwo() {
336
+ return $this->varTwo;
337
+ }
338
+
339
+ public function getVarThree() {
340
+ return $this->varThree;
341
+ }
342
+ }
343
+
344
+ class ClassEleven {
345
+ public static $builtTimes = 0;
346
+ private $varOne;
347
+ private $varTwo;
348
+ private $varThree;
349
+
350
+ public static function reset() {
351
+ self::$builtTimes = 0;
352
+ }
353
+
354
+ public function __construct(One $varOne, ClassTwo $varTwo, $varThree) {
355
+ self::$builtTimes++;
356
+ $this->varOne = $varOne;
357
+ $this->varTwo = $varTwo;
358
+ $this->varThree = $varThree;
359
+ }
360
+
361
+ public function getVarOne() {
362
+ return $this->varOne;
363
+ }
364
+
365
+ public function getVarTwo() {
366
+ return $this->varTwo;
367
+ }
368
+
369
+ public function getVarThree() {
370
+ return $this->varThree;
371
+ }
372
+ }
373
+
374
+ class ClassTwelve {
375
+ public static $builtTimes = 0;
376
+ private $varOne;
377
+
378
+ public static function reset() {
379
+ self::$builtTimes = 0;
380
+ }
381
+
382
+ public function __construct(One $varOne) {
383
+ self::$builtTimes++;
384
+ $this->varOne = $varOne;
385
+ }
386
+
387
+ public function getVarOne() {
388
+ return $this->varOne;
389
+ }
390
+ }
391
+
392
+ class Factory {
393
+ public function build() {
394
+ return new ClassOne();
395
+ }
396
+ }
397
+
398
+ class ClassThirteen {
399
+ public function doSomething() {
400
+ return 'IDidSomething';
401
+ }
402
+ }
403
+
404
+ class ClassFourteen {
405
+ }
406
+
407
+ class ClassFifteen {
408
+ public function __construct(One $one, ClassFourteen $fourteen) {
409
+
410
+ }
411
+
412
+ public function doSomething() {
413
+ return 'IDidSomething';
414
+ }
415
+ }
416
+
417
+ class Dependency {}
418
+
419
+ class Depending {
420
+ private $dependency;
421
+
422
+ public function __construct( Dependency $dependency ) {
423
+ $this->dependency = $dependency;
424
+ }
425
+
426
+ public function getDependency() {
427
+ return $this->dependency;
428
+ }
429
+ }
430
+
431
+ abstract class AbstractClass {};
432
+
433
+ class PrivateConstructor {
434
+ private function __construct() {}
435
+ }
vendor/lucatume/di52/tests/data/test-providers.php ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class ProviderOne extends tad_DI52_ServiceProvider
4
+ {
5
+ /**
6
+ * Binds and sets up implementations.
7
+ */
8
+ public function register()
9
+ {
10
+ $this->container->bind('foo', 23);
11
+ }
12
+ }
13
+
14
+ class DeferredProviderOne extends tad_DI52_ServiceProvider
15
+ {
16
+
17
+ protected $deferred = true;
18
+
19
+ /**
20
+ * Binds and sets up implementations.
21
+ */
22
+ public function register()
23
+ {
24
+ $this->container->bind('foo', 23);
25
+ }
26
+
27
+ }
28
+
29
+ class DeferredProviderTwo extends tad_DI52_ServiceProvider
30
+ {
31
+
32
+ protected static $wasRegistered = false;
33
+ protected $deferred = true;
34
+
35
+ public static function wasRegistered()
36
+ {
37
+ return self::$wasRegistered;
38
+ }
39
+
40
+ public static function reset()
41
+ {
42
+ self::$wasRegistered = false;
43
+ }
44
+
45
+ public function provides()
46
+ {
47
+ return array('One');
48
+ }
49
+
50
+
51
+ /**
52
+ * Binds and sets up implementations.
53
+ */
54
+ public function register()
55
+ {
56
+ $this->container->bind('One', 'ClassOne');
57
+ self::$wasRegistered = true;
58
+ }
59
+
60
+ }
61
+
62
+ class ProviderThree extends tad_DI52_ServiceProvider
63
+ {
64
+
65
+ /**
66
+ * Binds and sets up implementations.
67
+ */
68
+ public function boot()
69
+ {
70
+ $this->container->bind('One', 'ClassOne');
71
+ }
72
+
73
+ /**
74
+ * Binds and sets up implementations.
75
+ */
76
+ public function register()
77
+ {
78
+ // no-op
79
+ }
80
+ }
vendor/lucatume/di52/todo.txt ADDED
@@ -0,0 +1 @@
 
1
+ - hasTag() to check for tagging
vendor/symfony/polyfill-ctype/bootstrap.php CHANGED
@@ -12,35 +12,35 @@
12
  use Symfony\Polyfill\Ctype as p;
13
 
14
  if (!function_exists('ctype_alnum')) {
15
- function ctype_alnum($text) { return p\Ctype::ctype_alnum($text); }
16
  }
17
  if (!function_exists('ctype_alpha')) {
18
- function ctype_alpha($text) { return p\Ctype::ctype_alpha($text); }
19
  }
20
  if (!function_exists('ctype_cntrl')) {
21
- function ctype_cntrl($text) { return p\Ctype::ctype_cntrl($text); }
22
  }
23
  if (!function_exists('ctype_digit')) {
24
- function ctype_digit($text) { return p\Ctype::ctype_digit($text); }
25
  }
26
  if (!function_exists('ctype_graph')) {
27
- function ctype_graph($text) { return p\Ctype::ctype_graph($text); }
28
  }
29
  if (!function_exists('ctype_lower')) {
30
- function ctype_lower($text) { return p\Ctype::ctype_lower($text); }
31
  }
32
  if (!function_exists('ctype_print')) {
33
- function ctype_print($text) { return p\Ctype::ctype_print($text); }
34
  }
35
  if (!function_exists('ctype_punct')) {
36
- function ctype_punct($text) { return p\Ctype::ctype_punct($text); }
37
  }
38
  if (!function_exists('ctype_space')) {
39
- function ctype_space($text) { return p\Ctype::ctype_space($text); }
40
  }
41
  if (!function_exists('ctype_upper')) {
42
- function ctype_upper($text) { return p\Ctype::ctype_upper($text); }
43
  }
44
  if (!function_exists('ctype_xdigit')) {
45
- function ctype_xdigit($text) { return p\Ctype::ctype_xdigit($text); }
46
  }
12
  use Symfony\Polyfill\Ctype as p;
13
 
14
  if (!function_exists('ctype_alnum')) {
15
+ function ctype_alnum($input) { return p\Ctype::ctype_alnum($input); }
16
  }
17
  if (!function_exists('ctype_alpha')) {
18
+ function ctype_alpha($input) { return p\Ctype::ctype_alpha($input); }
19
  }
20
  if (!function_exists('ctype_cntrl')) {
21
+ function ctype_cntrl($input) { return p\Ctype::ctype_cntrl($input); }
22
  }
23
  if (!function_exists('ctype_digit')) {
24
+ function ctype_digit($input) { return p\Ctype::ctype_digit($input); }
25
  }
26
  if (!function_exists('ctype_graph')) {
27
+ function ctype_graph($input) { return p\Ctype::ctype_graph($input); }
28
  }
29
  if (!function_exists('ctype_lower')) {
30
+ function ctype_lower($input) { return p\Ctype::ctype_lower($input); }
31
  }
32
  if (!function_exists('ctype_print')) {
33
+ function ctype_print($input) { return p\Ctype::ctype_print($input); }
34
  }
35
  if (!function_exists('ctype_punct')) {
36
+ function ctype_punct($input) { return p\Ctype::ctype_punct($input); }
37
  }
38
  if (!function_exists('ctype_space')) {
39
+ function ctype_space($input) { return p\Ctype::ctype_space($input); }
40
  }
41
  if (!function_exists('ctype_upper')) {
42
+ function ctype_upper($input) { return p\Ctype::ctype_upper($input); }
43
  }
44
  if (!function_exists('ctype_xdigit')) {
45
+ function ctype_xdigit($input) { return p\Ctype::ctype_xdigit($input); }
46
  }
vendor/symfony/polyfill-ctype/composer.json CHANGED
@@ -28,7 +28,7 @@
28
  "minimum-stability": "dev",
29
  "extra": {
30
  "branch-alias": {
31
- "dev-master": "1.18-dev"
32
  },
33
  "thanks": {
34
  "name": "symfony/polyfill",
28
  "minimum-stability": "dev",
29
  "extra": {
30
  "branch-alias": {
31
+ "dev-main": "1.19-dev"
32
  },
33
  "thanks": {
34
  "name": "symfony/polyfill",
vendor/xrstf/composer-php52/.gitignore ADDED
@@ -0,0 +1 @@
 
1
+ /vendor/
vendor/xrstf/composer-php52/LICENSE ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) 2013 Christoph Mewes
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is furnished
8
+ to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
vendor/xrstf/composer-php52/README.md ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ PHP 5.2 Autoloading for Composer
2
+ ================================
3
+
4
+ This package provides an easy way to get a PHP 5.2 compatible autoloader out of Composer. The generated autoloader is fully compatible to the original and is written into separate files, each ending with `_52.php`.
5
+
6
+ Legacy
7
+ ------
8
+
9
+ Please do not use this, if you can avoid it. It's a horrible hack, often breaks and is extremely tied to Composer's interna. This package was originally developed in 2012, when PHP 5.2 was much more common on cheap webhosts.
10
+
11
+ In 2016, this package has been moved from Bitbucket to a Github organization, because the original developer could no longer reliably maintain it. This is the reason for this legacy package name ``xrstf/...``.
12
+
13
+ Usage
14
+ -----
15
+
16
+ In your project's `composer.json`, add the following lines:
17
+
18
+ ```json
19
+ {
20
+ "require": {
21
+ "xrstf/composer-php52": "1.*"
22
+ },
23
+ "scripts": {
24
+ "post-install-cmd": [
25
+ "xrstf\\Composer52\\Generator::onPostInstallCmd"
26
+ ],
27
+ "post-update-cmd": [
28
+ "xrstf\\Composer52\\Generator::onPostInstallCmd"
29
+ ],
30
+ "post-autoload-dump": [
31
+ "xrstf\\Composer52\\Generator::onPostInstallCmd"
32
+ ]
33
+ }
34
+ }
35
+ ```
36
+
37
+ After the next update/install, you will have a `vendor/autoload_52.php` file, that you can simply include and use in PHP 5.2 projects.
vendor/xrstf/composer-php52/composer.json ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "xrstf/composer-php52",
3
+ "license": "MIT",
4
+ "support": {
5
+ "source": "https://github.com/composer-php52/composer-php52",
6
+ "issues": "https://github.com/composer-php52/composer-php52/issues"
7
+ },
8
+ "autoload": {
9
+ "psr-0": {
10
+ "xrstf\\Composer52": "lib/"
11
+ }
12
+ },
13
+ "scripts": {
14
+ "post-install-cmd": [
15
+ "xrstf\\Composer52\\Generator::onPostInstallCmd"
16
+ ],
17
+ "post-update-cmd": [
18
+ "xrstf\\Composer52\\Generator::onPostInstallCmd"
19
+ ]
20
+ },
21
+ "extra": {
22
+ "branch-alias": {
23
+ "dev-default": "1.x-dev"
24
+ }
25
+ }
26
+ }
vendor/xrstf/composer-php52/lib/xrstf/Composer52/AutoloadGenerator.php ADDED
@@ -0,0 +1,346 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright (c) 2013, Christoph Mewes, http://www.xrstf.de
4
+ *
5
+ * This file is released under the terms of the MIT license. You can find the
6
+ * complete text in the attached LICENSE file or online at:
7
+ *
8
+ * http://www.opensource.org/licenses/mit-license.php
9
+ *
10
+ * --------------------------------------------------------------------------
11
+ *
12
+ * 99% of this is copied as-is from the original Composer source code and is
13
+ * released under MIT license as well. Copyright goes to:
14
+ *
15
+ * - Igor Wiedler <igor@wiedler.ch>
16
+ * - Jordi Boggiano <j.boggiano@seld.be>
17
+ */
18
+
19
+ namespace xrstf\Composer52;
20
+
21
+ use Composer\Autoload\AutoloadGenerator as BaseGenerator;
22
+ use Composer\Autoload\ClassMapGenerator;
23
+ use Composer\Config;
24
+ use Composer\Installer\InstallationManager;
25
+ use Composer\Package\AliasPackage;
26
+ use Composer\Package\PackageInterface;
27
+ use Composer\Repository\InstalledRepositoryInterface;
28
+ use Composer\Util\Filesystem;
29
+
30
+ class AutoloadGenerator extends BaseGenerator {
31
+
32
+ /**
33
+ * @var bool
34
+ */
35
+ private $classMapAuthoritative = false;
36
+
37
+ public function __construct() {
38
+ // do nothing (but keep this constructor so we can build an instance without the need for an event dispatcher)
39
+ }
40
+
41
+ /**
42
+ * Whether or not generated autoloader considers the class map
43
+ * authoritative.
44
+ *
45
+ * @param bool $classMapAuthoritative
46
+ */
47
+ public function setClassMapAuthoritative($classMapAuthoritative)
48
+ {
49
+ $this->classMapAuthoritative = (boolean) $classMapAuthoritative;
50
+ }
51
+
52
+ public function dump(Config $config, InstalledRepositoryInterface $localRepo, PackageInterface $mainPackage, InstallationManager $installationManager, $targetDir, $scanPsr0Packages = false, $suffix = '') {
53
+ if ($this->classMapAuthoritative) {
54
+ // Force scanPsr0Packages when classmap is authoritative
55
+ $scanPsr0Packages = true;
56
+ }
57
+
58
+ $filesystem = new Filesystem();
59
+ $filesystem->ensureDirectoryExists($config->get('vendor-dir'));
60
+
61
+ $cwd = getcwd();
62
+ $basePath = $filesystem->normalizePath($cwd);
63
+ $vendorPath = $filesystem->normalizePath(realpath($config->get('vendor-dir')));
64
+ $targetDir = $vendorPath.'/'.$targetDir;
65
+ $filesystem->ensureDirectoryExists($targetDir);
66
+
67
+ $useGlobalIncludePath = (bool) $config->get('use-include-path');
68
+ $prependAutoloader = $config->get('prepend-autoloader') === false ? 'false' : 'true';
69
+ $classMapAuthoritative = $config->get('classmap-authoritative');
70
+
71
+ $vendorPathCode = $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true);
72
+ $vendorPathToTargetDirCode = $filesystem->findShortestPathCode($vendorPath, realpath($targetDir), true);
73
+
74
+ $appBaseDirCode = $filesystem->findShortestPathCode($vendorPath, $basePath, true);
75
+ $appBaseDirCode = str_replace('__DIR__', '$vendorDir', $appBaseDirCode);
76
+
77
+ // add 5.2 compat
78
+ $vendorPathCode = str_replace('__DIR__', 'dirname(__FILE__)', $vendorPathCode);
79
+ $vendorPathToTargetDirCode = str_replace('__DIR__', 'dirname(__FILE__)', $vendorPathToTargetDirCode);
80
+
81
+ $packageMap = $this->buildPackageMap($installationManager, $mainPackage, $localRepo->getCanonicalPackages());
82
+ $autoloads = $this->parseAutoloads($packageMap, $mainPackage);
83
+
84
+ // add custom psr-0 autoloading if the root package has a target dir
85
+ $targetDirLoader = null;
86
+ $mainAutoload = $mainPackage->getAutoload();
87
+ if ($mainPackage->getTargetDir() && !empty($mainAutoload['psr-0'])) {
88
+ $levels = count(explode('/', $filesystem->normalizePath($mainPackage->getTargetDir())));
89
+ $prefixes = implode(', ', array_map(function ($prefix) {
90
+ return var_export($prefix, true);
91
+ }, array_keys($mainAutoload['psr-0'])));
92
+
93
+ $baseDirFromTargetDirCode = $filesystem->findShortestPathCode($targetDir, $basePath, true);
94
+
95
+ $targetDirLoader = <<<EOF
96
+
97
+ public static function autoload(\$class) {
98
+ \$dir = $baseDirFromTargetDirCode.'/';
99
+ \$prefixes = array($prefixes);
100
+
101
+ foreach (\$prefixes as \$prefix) {
102
+ if (0 !== strpos(\$class, \$prefix)) {
103
+ continue;
104
+ }
105
+
106
+ \$path = explode(DIRECTORY_SEPARATOR, self::getClassPath(\$class));
107
+ \$path = \$dir.implode('/', array_slice(\$path, $levels));
108
+
109
+ if (!\$path = self::resolveIncludePath(\$path)) {
110
+ return false;
111
+ }
112
+
113
+ require \$path;
114
+ return true;
115
+ }
116
+ }
117
+
118
+ EOF;
119
+ }
120
+
121
+ $filesCode = "";
122
+ $autoloads['files'] = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($autoloads['files']));
123
+ foreach ($autoloads['files'] as $functionFile) {
124
+ // don't include file if it is using PHP 5.3+ syntax
125
+ // https://bitbucket.org/xrstf/composer-php52/issue/4
126
+ if ($this->isPHP53($functionFile)) {
127
+ $filesCode .= '// require '.$this->getPathCode($filesystem, $basePath, $vendorPath, $functionFile)."; // disabled because of PHP 5.3 syntax\n";
128
+ }
129
+ else {
130
+ $filesCode .= ' require '.$this->getPathCode($filesystem, $basePath, $vendorPath, $functionFile).";\n";
131
+ }
132
+ }
133
+
134
+ if (!$suffix) {
135
+ $suffix = md5(uniqid('', true));
136
+ }
137
+
138
+ $includePathFile = $this->getIncludePathsFile($packageMap, $filesystem, $basePath, $vendorPath, $vendorPathCode, $appBaseDirCode);
139
+
140
+ file_put_contents($vendorPath.'/autoload_52.php', $this->getAutoloadFile($vendorPathToTargetDirCode, $suffix));
141
+ file_put_contents($targetDir.'/autoload_real_52.php', $this->getAutoloadRealFile(true, (bool) $includePathFile, $targetDirLoader, $filesCode, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader));
142
+
143
+ // use stream_copy_to_stream instead of copy
144
+ // to work around https://bugs.php.net/bug.php?id=64634
145
+ $sourceLoader = fopen(__DIR__.'/ClassLoader.php', 'r');
146
+ $targetLoader = fopen($targetDir.'/ClassLoader52.php', 'w+');
147
+ stream_copy_to_stream($sourceLoader, $targetLoader);
148
+ fclose($sourceLoader);
149
+ fclose($targetLoader);
150
+ unset($sourceLoader, $targetLoader);
151
+ }
152
+
153
+ protected function isPHP53($file) {
154
+ $tokens = token_get_all(file_get_contents($file));
155
+ $php53 = array(T_DIR, T_GOTO, T_NAMESPACE, T_NS_C, T_NS_SEPARATOR, T_USE);
156
+
157
+ // PHP 5.4+
158
+ if (defined('T_TRAIT')) {
159
+ $php53[] = T_TRAIT;
160
+ $php53[] = T_TRAIT_C;
161
+ $php53[] = T_TRAIT_C;
162
+ }
163
+
164
+ // PHP 5.5+
165
+ if (defined('T_FINALLY')) {
166
+ $php53[] = T_FINALLY;
167
+ $php53[] = T_YIELD;
168
+ }
169
+
170
+ foreach ($tokens as $token) {
171
+ if (is_array($token) && in_array($token[0], $php53)) {
172
+ return true;
173
+ }
174
+ }
175
+
176
+ return false;
177
+ }
178
+
179
+ protected function getIncludePathsFile(array $packageMap, Filesystem $filesystem, $basePath, $vendorPath, $vendorPathCode, $appBaseDirCode) {
180
+ $includePaths = array();
181
+
182
+ foreach ($packageMap as $item) {
183
+ list($package, $installPath) = $item;
184
+
185
+ if (null !== $package->getTargetDir() && strlen($package->getTargetDir()) > 0) {
186
+ $installPath = substr($installPath, 0, -strlen('/'.$package->getTargetDir()));
187
+ }
188
+
189
+ foreach ($package->getIncludePaths() as $includePath) {
190
+ $includePath = trim($includePath, '/');
191
+ $includePaths[] = empty($installPath) ? $includePath : $installPath.'/'.$includePath;
192
+ }
193
+ }
194
+
195
+ if (!$includePaths) {
196
+ return;
197
+ }
198
+
199
+ $includePathsFile = <<<EOF
200
+ <?php
201
+
202
+ // include_paths_52.php generated by xrstf/composer-php52
203
+
204
+ \$vendorDir = $vendorPathCode;
205
+ \$baseDir = $appBaseDirCode;
206
+
207
+ return array(
208
+
209
+ EOF;
210
+
211
+ foreach ($includePaths as $path) {
212
+ $includePathsFile .= "\t" . $this->getPathCode($filesystem, $basePath, $vendorPath, $path) . ",\n";
213
+ }
214
+
215
+ return $includePathsFile . ");\n";
216
+ }
217
+
218
+ protected function getAutoloadFile($vendorPathToTargetDirCode, $suffix) {
219
+ return <<<AUTOLOAD
220
+ <?php
221
+
222
+ // autoload_52.php generated by xrstf/composer-php52
223
+
224
+ require_once $vendorPathToTargetDirCode.'/autoload_real_52.php';
225
+
226
+ return ComposerAutoloaderInit$suffix::getLoader();
227
+
228
+ AUTOLOAD;
229
+ }
230
+
231
+ protected function getAutoloadRealFile($useClassMap, $useIncludePath, $targetDirLoader, $filesCode, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $staticPhpVersion = 70000) {
232
+ // TODO the class ComposerAutoloaderInit should be revert to a closure
233
+ // when APC has been fixed:
234
+ // - https://github.com/composer/composer/issues/959
235
+ // - https://bugs.php.net/bug.php?id=52144
236
+ // - https://bugs.php.net/bug.php?id=61576
237
+ // - https://bugs.php.net/bug.php?id=59298
238
+
239
+ if ($filesCode) {
240
+ $filesCode = "\n\n".rtrim($filesCode);
241
+ }
242
+
243
+ $file = <<<HEADER
244
+ <?php
245
+
246
+ // autoload_real_52.php generated by xrstf/composer-php52
247
+
248
+ class ComposerAutoloaderInit$suffix {
249
+ private static \$loader;
250
+
251
+ public static function loadClassLoader(\$class) {
252
+ if ('xrstf_Composer52_ClassLoader' === \$class) {
253
+ require dirname(__FILE__).'/ClassLoader52.php';
254
+ }
255
+ }
256
+
257
+ /**
258
+ * @return xrstf_Composer52_ClassLoader
259
+ */
260
+ public static function getLoader() {
261
+ if (null !== self::\$loader) {
262
+ return self::\$loader;
263
+ }
264
+
265
+ spl_autoload_register(array('ComposerAutoloaderInit$suffix', 'loadClassLoader'), true /*, true */);
266
+ self::\$loader = \$loader = new xrstf_Composer52_ClassLoader();
267
+ spl_autoload_unregister(array('ComposerAutoloaderInit$suffix', 'loadClassLoader'));
268
+
269
+ \$vendorDir = $vendorPathCode;
270
+ \$baseDir = $appBaseDirCode;
271
+ \$dir = dirname(__FILE__);
272
+
273
+
274
+ HEADER;
275
+
276
+ if ($useIncludePath) {
277
+ $file .= <<<'INCLUDE_PATH'
278
+ $includePaths = require $dir.'/include_paths.php';
279
+ array_push($includePaths, get_include_path());
280
+ set_include_path(implode(PATH_SEPARATOR, $includePaths));
281
+
282
+
283
+ INCLUDE_PATH;
284
+ }
285
+
286
+ $file .= <<<'PSR0'
287
+ $map = require $dir.'/autoload_namespaces.php';
288
+ foreach ($map as $namespace => $path) {
289
+ $loader->add($namespace, $path);
290
+ }
291
+
292
+
293
+ PSR0;
294
+
295
+ if ($useClassMap) {
296
+ $file .= <<<'CLASSMAP'
297
+ $classMap = require $dir.'/autoload_classmap.php';
298
+ if ($classMap) {
299
+ $loader->addClassMap($classMap);
300
+ }
301
+
302
+
303
+ CLASSMAP;
304
+ }
305
+
306
+ if ($this->classMapAuthoritative) {
307
+ $file .= <<<'CLASSMAPAUTHORITATIVE'
308
+ $loader->setClassMapAuthoritative(true);
309
+
310
+ CLASSMAPAUTHORITATIVE;
311
+ }
312
+
313
+ if ($useGlobalIncludePath) {
314
+ $file .= <<<'INCLUDEPATH'
315
+ $loader->setUseIncludePath(true);
316
+
317
+
318
+ INCLUDEPATH;
319
+ }
320
+
321
+ if ($targetDirLoader) {
322
+ $file .= <<<REGISTER_AUTOLOAD
323
+ spl_autoload_register(array('ComposerAutoloaderInit$suffix', 'autoload'), true);
324
+
325
+
326
+ REGISTER_AUTOLOAD;
327
+
328
+ }
329
+
330
+ $file .= <<<METHOD_FOOTER
331
+ \$loader->register($prependAutoloader);{$filesCode}
332
+
333
+ return \$loader;
334
+ }
335
+
336
+ METHOD_FOOTER;
337
+
338
+ $file .= $targetDirLoader;
339
+
340
+ return $file . <<<FOOTER
341
+ }
342
+
343
+ FOOTER;
344
+
345
+ }
346
+ }
vendor/xrstf/composer-php52/lib/xrstf/Composer52/ClassLoader.php ADDED
@@ -0,0 +1,271 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright (c) 2013, Christoph Mewes, http://www.xrstf.de
4
+ *
5
+ * This file is released under the terms of the MIT license. You can find the
6
+ * complete text in the attached LICENSE file or online at:
7
+ *
8
+ * http://www.opensource.org/licenses/mit-license.php
9
+ *
10
+ * --------------------------------------------------------------------------
11
+ *
12
+ * 99% of this is copied as-is from the original Composer source code and is
13
+ * released under MIT license as well. Copyright goes to:
14
+ *
15
+ * - Fabien Potencier <fabien@symfony.com>
16
+ * - Jordi Boggiano <j.boggiano@seld.be>
17
+ */
18
+
19
+ class xrstf_Composer52_ClassLoader {
20
+ private $prefixes = array();
21
+ private $fallbackDirs = array();
22
+ private $useIncludePath = false;
23
+ private $classMap = array();
24
+ private $classMapAuthoratative = false;
25
+ private $allowUnderscore = false;
26
+
27
+ /**
28
+ * @param boolean $flag true to allow class names with a leading underscore, false to disable
29
+ */
30
+ public function setAllowUnderscore($flag) {
31
+ $this->allowUnderscore = (boolean) $flag;
32
+ }
33
+
34
+ /**
35
+ * @return array
36
+ */
37
+ public function getPrefixes() {
38
+ return $this->prefixes;
39
+ }
40
+
41
+ /**
42
+ * Turns off searching the prefix and fallback directories for classes
43
+ * that have not been registered with the class map.
44
+ *
45
+ * @param bool $classMapAuthoratative
46
+ */
47
+ public function setClassMapAuthoritative($classMapAuthoratative) {
48
+ $this->classMapAuthoratative = $classMapAuthoratative;
49
+ }
50
+
51
+ /**
52
+ * Should class lookup fail if not found in the current class map?
53
+ *
54
+ * @return bool
55
+ */
56
+ public function getClassMapAuthoratative() {
57
+ return $this->classMapAuthoratative;
58
+ }
59
+
60
+ /**
61
+ * @return array
62
+ */
63
+ public function getFallbackDirs() {
64
+ return $this->fallbackDirs;
65
+ }
66
+
67
+ /**
68
+ * @return array
69
+ */
70
+ public function getClassMap() {
71
+ return $this->classMap;
72
+ }
73
+
74
+ /**
75
+ * @param array $classMap class to filename map
76
+ */
77
+ public function addClassMap(array $classMap) {
78
+ if ($this->classMap) {
79
+ $this->classMap = array_merge($this->classMap, $classMap);
80
+ }
81
+ else {
82
+ $this->classMap = $classMap;
83
+ }
84
+ }
85
+
86
+ /**
87
+ * Registers a set of classes, merging with any others previously set.
88
+ *
89
+ * @param string $prefix the classes prefix
90
+ * @param array|string $paths the location(s) of the classes
91
+ * @param bool $prepend prepend the location(s)
92
+ */
93
+ public function add($prefix, $paths, $prepend = false) {
94
+ if (!$prefix) {
95
+ if ($prepend) {
96
+ $this->fallbackDirs = array_merge(
97
+ (array) $paths,
98
+ $this->fallbackDirs
99
+ );
100
+ }
101
+ else {
102
+ $this->fallbackDirs = array_merge(
103
+ $this->fallbackDirs,
104
+ (array) $paths
105
+ );
106
+ }
107
+
108
+ return;
109
+ }
110
+
111
+ if (!isset($this->prefixes[$prefix])) {
112
+ $this->prefixes[$prefix] = (array) $paths;
113
+ return;
114
+ }
115
+
116
+ if ($prepend) {
117
+ $this->prefixes[$prefix] = array_merge(
118
+ (array) $paths,
119
+ $this->prefixes[$prefix]
120
+ );
121
+ }
122
+ else {
123
+ $this->prefixes[$prefix] = array_merge(
124
+ $this->prefixes[$prefix],
125
+ (array) $paths
126
+ );
127
+ }
128
+ }
129
+
130
+ /**
131
+ * Registers a set of classes, replacing any others previously set.
132
+ *
133
+ * @param string $prefix the classes prefix
134
+ * @param array|string $paths the location(s) of the classes
135
+ */
136
+ public function set($prefix, $paths) {
137
+ if (!$prefix) {
138
+ $this->fallbackDirs = (array) $paths;
139
+ return;
140
+ }
141
+
142
+ $this->prefixes[$prefix] = (array) $paths;
143
+ }
144
+
145
+ /**
146
+ * Turns on searching the include path for class files.
147
+ *
148
+ * @param bool $useIncludePath
149
+ */
150
+ public function setUseIncludePath($useIncludePath) {
151
+ $this->useIncludePath = $useIncludePath;
152
+ }
153
+
154
+ /**
155
+ * Can be used to check if the autoloader uses the include path to check
156
+ * for classes.
157
+ *
158
+ * @return bool
159
+ */
160
+ public function getUseIncludePath() {
161
+ return $this->useIncludePath;
162
+ }
163
+
164
+ /**
165
+ * Registers this instance as an autoloader.
166
+ */
167
+ public function register() {
168
+ spl_autoload_register(array($this, 'loadClass'), true);
169
+ }
170
+
171
+ /**
172
+ * Unregisters this instance as an autoloader.
173
+ */
174
+ public function unregister() {
175
+ spl_autoload_unregister(array($this, 'loadClass'));
176
+ }
177
+
178
+ /**
179
+ * Loads the given class or interface.
180
+ *
181
+ * @param string $class the name of the class
182
+ * @return bool|null true, if loaded
183
+ */
184
+ public function loadClass($class) {
185
+ if ($file = $this->findFile($class)) {
186
+ include $file;
187
+ return true;
188
+ }
189
+ }
190
+
191
+ /**
192
+ * Finds the path to the file where the class is defined.
193
+ *
194
+ * @param string $class the name of the class
195
+ * @return string|null the path, if found
196
+ */
197
+ public function findFile($class) {
198
+ if ('\\' === $class[0]) {
199
+ $class = substr($class, 1);
200
+ }
201
+
202
+ if (isset($this->classMap[$class])) {
203
+ return $this->classMap[$class];
204
+ }
205
+ elseif ($this->classMapAuthoratative) {
206
+ return false;
207
+ }
208
+
209
+ $classPath = $this->getClassPath($class);
210
+
211
+ foreach ($this->prefixes as $prefix => $dirs) {
212
+ if (0 === strpos($class, $prefix)) {
213
+ foreach ($dirs as $dir) {
214
+ if (file_exists($dir.DIRECTORY_SEPARATOR.$classPath)) {
215
+ return $dir.DIRECTORY_SEPARATOR.$classPath;
216
+ }
217
+ }
218
+ }
219
+ }
220
+
221
+ foreach ($this->fallbackDirs as $dir) {
222
+ if (file_exists($dir.DIRECTORY_SEPARATOR.$classPath)) {
223
+ return $dir.DIRECTORY_SEPARATOR.$classPath;
224
+ }
225
+ }
226
+
227
+ if ($this->useIncludePath && $file = self::resolveIncludePath($classPath)) {
228
+ return $file;
229
+ }
230
+
231
+ return $this->classMap[$class] = false;
232
+ }
233
+
234
+ private function getClassPath($class) {
235
+ if (false !== $pos = strrpos($class, '\\')) {
236
+ // namespaced class name
237
+ $classPath = str_replace('\\', DIRECTORY_SEPARATOR, substr($class, 0, $pos)).DIRECTORY_SEPARATOR;
238
+ $className = substr($class, $pos + 1);
239
+ }
240
+ else {
241
+ // PEAR-like class name
242
+ $classPath = null;
243
+ $className = $class;
244
+ }
245
+
246
+ $className = str_replace('_', DIRECTORY_SEPARATOR, $className);
247
+
248
+ // restore the prefix
249
+ if ($this->allowUnderscore && DIRECTORY_SEPARATOR === $className[0]) {
250
+ $className[0] = '_';
251
+ }
252
+
253
+ $classPath .= $className.'.php';
254
+
255
+ return $classPath;
256
+ }
257
+
258
+ public static function resolveIncludePath($classPath) {
259
+ $paths = explode(PATH_SEPARATOR, get_include_path());
260
+
261
+ foreach ($paths as $path) {
262
+ $path = rtrim($path, '/\\');
263
+
264
+ if ($file = file_exists($path.DIRECTORY_SEPARATOR.$file)) {
265
+ return $file;
266
+ }
267
+ }
268
+
269
+ return false;
270
+ }
271
+ }
vendor/xrstf/composer-php52/lib/xrstf/Composer52/Generator.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright (c) 2013, Christoph Mewes, http://www.xrstf.de
4
+ *
5
+ * This file is released under the terms of the MIT license. You can find the
6
+ * complete text in the attached LICENSE file or online at:
7
+ *
8
+ * http://www.opensource.org/licenses/mit-license.php
9
+ */
10
+
11
+ namespace xrstf\Composer52;
12
+
13
+ use Composer\Repository\CompositeRepository;
14
+ use Composer\Script\Event;
15
+
16
+ class Generator {
17
+ public static function onPostInstallCmd(Event $event) {
18
+ $composer = $event->getComposer();
19
+ $installationManager = $composer->getInstallationManager();
20
+ $repoManager = $composer->getRepositoryManager();
21
+ $localRepo = $repoManager->getLocalRepository();
22
+ $package = $composer->getPackage();
23
+ $config = $composer->getConfig();
24
+
25
+ // We can't gain access to the Command's input object, so we have to look
26
+ // for -o / --optimize-autoloader ourselves. Sadly, neither getopt() works
27
+ // (always returns an empty array), nor does Symfony's Console Input, as
28
+ // it expects a full definition of the current command line and we can't
29
+ // provide that.
30
+
31
+ $args = $_SERVER['argv'];
32
+ $optimize = in_array('-o', $args) || in_array('--optimize-autoloader', $args) || in_array('--optimize', $args);
33
+
34
+ $suffix = $config->get('autoloader-suffix');
35
+
36
+ $generator = new AutoloadGenerator();
37
+ $generator->dump($config, $localRepo, $package, $installationManager, 'composer', $optimize, $suffix);
38
+ }
39
+ }
wp-staging.php CHANGED
@@ -7,7 +7,7 @@
7
  * Author: WP-STAGING
8
  * Author URI: https://wp-staging.com
9
  * Contributors: ReneHermi
10
- * Version: 2.7.7
11
  * Text Domain: wp-staging
12
  * Domain Path: /languages/
13
  *
@@ -40,8 +40,16 @@ if (!defined('WPSTG_FREE_LOADED')) {
40
  // Standalone requirement-checking script
41
  require_once 'Requirements/WpstgFreeRequirements.php';
42
 
 
 
 
 
 
 
 
 
43
  if (!class_exists('WpstgFreeBootstrap')) {
44
- class WpstgFreeBootstrap
45
  {
46
  private $shouldBootstrap = true;
47
  private $requirements;
@@ -71,18 +79,17 @@ if (!class_exists('WpstgFreeBootstrap')) {
71
  return;
72
  }
73
 
74
- // Absolute path to plugin dir /var/www/.../plugins/wp-staging(-pro)
75
- if (!defined('WPSTG_PLUGIN_DIR')) {
76
- define('WPSTG_PLUGIN_DIR', plugin_dir_path(__FILE__));
77
- }
78
-
79
- // Absolute path and name to main plugin entry file /var/www/.../plugins/wp-staging(-pro)/wp-staging(-pro).php
80
  if (!defined('WPSTG_PLUGIN_FILE')) {
81
  define('WPSTG_PLUGIN_FILE', __FILE__);
82
  }
83
 
84
  require_once(__DIR__ . '/_init.php');
85
  }
 
 
 
 
 
86
  }
87
  }
88
 
@@ -90,3 +97,11 @@ $bootstrap = new WpstgFreeBootstrap(new WpstgFreeRequirements(__FILE__));
90
 
91
  add_action('plugins_loaded', [$bootstrap, 'checkRequirements'], 5);
92
  add_action('plugins_loaded', [$bootstrap, 'bootstrap'], 10);
 
 
 
 
 
 
 
 
7
  * Author: WP-STAGING
8
  * Author URI: https://wp-staging.com
9
  * Contributors: ReneHermi
10
+ * Version: 2.7.8
11
  * Text Domain: wp-staging
12
  * Domain Path: /languages/
13
  *
40
  // Standalone requirement-checking script
41
  require_once 'Requirements/WpstgFreeRequirements.php';
42
 
43
+ if (!interface_exists('WpstgBootstrapInterface')) {
44
+ interface WpstgBootstrapInterface {
45
+ public function checkRequirements();
46
+ public function bootstrap();
47
+ public function passedRequirements();
48
+ }
49
+ }
50
+
51
  if (!class_exists('WpstgFreeBootstrap')) {
52
+ class WpstgFreeBootstrap implements WpstgBootstrapInterface
53
  {
54
  private $shouldBootstrap = true;
55
  private $requirements;
79
  return;
80
  }
81
 
 
 
 
 
 
 
82
  if (!defined('WPSTG_PLUGIN_FILE')) {
83
  define('WPSTG_PLUGIN_FILE', __FILE__);
84
  }
85
 
86
  require_once(__DIR__ . '/_init.php');
87
  }
88
+
89
+ public function passedRequirements()
90
+ {
91
+ return $this->shouldBootstrap;
92
+ }
93
  }
94
  }
95
 
97
 
98
  add_action('plugins_loaded', [$bootstrap, 'checkRequirements'], 5);
99
  add_action('plugins_loaded', [$bootstrap, 'bootstrap'], 10);
100
+
101
+ /** Installation Hooks */
102
+ if (!class_exists('WPStaging\Install')) {
103
+ require_once __DIR__ . "/install.php";
104
+
105
+ $install = new \WPStaging\Install($bootstrap);
106
+ register_activation_hook(__FILE__, [$install, 'activation']);
107
+ }