Cookiebot | GDPR Compliant Cookie Consent and Notice - Version 3.10.0

Version Description

Download this release

Release Info

Developer aytac
Plugin Icon 128x128 Cookiebot | GDPR Compliant Cookie Consent and Notice
Version 3.10.0
Comparing to
See all releases

Code changes from version 3.9.0 to 3.10.0

Files changed (151) hide show
  1. addons/addons.json +7 -0
  2. addons/composer.json +37 -2
  3. addons/composer.lock +987 -11
  4. addons/config/settings-config.php +10 -10
  5. addons/controller/addons/add-to-any/add-to-any.php +47 -1
  6. addons/controller/addons/custom-facebook-feed-old/custom-facebook-feed-old.php +347 -0
  7. addons/controller/addons/custom-facebook-feed/custom-facebook-feed.php +33 -296
  8. addons/controller/addons/embed-autocorrect/embed-autocorrect.php +12 -11
  9. addons/controller/addons/enfold/enfold.php +326 -0
  10. addons/controller/addons/enhanced-ecommerce-for-woocommerce-store/enhanced-ecommerce-for-woocommerce-store.php +1 -1
  11. addons/controller/addons/gadwp/gadwp.php +19 -10
  12. addons/controller/addons/google-analytics-plus/google-analytics-plus.php +1 -1
  13. addons/controller/addons/google-analytics/google-analytics.php +1 -1
  14. addons/controller/addons/google-site-kit/google-site-kit.php +1 -1
  15. addons/controller/addons/jetpack/visitor-cookies.php +2 -2
  16. addons/controller/addons/jetpack/widget/facebook-widget.php +2 -2
  17. addons/controller/addons/jetpack/widget/goodreads-widget.php +1 -1
  18. addons/controller/addons/jetpack/widget/google-maps-widget.php +1 -1
  19. addons/controller/addons/jetpack/widget/googleplus-badge-widget.php +1 -1
  20. addons/controller/addons/jetpack/widget/internet-defense-league-widget.php +1 -1
  21. addons/controller/addons/jetpack/widget/twitter-timeline-widget.php +1 -1
  22. addons/controller/addons/litespeed-cache/litespeed-cache.php +1 -1
  23. addons/controller/addons/official-facebook-pixel/official-facebook-pixel.php +3 -1
  24. addons/controller/addons/optinmonster/optinmonster.php +1 -1
  25. addons/controller/addons/pixel-caffeine/pixel-caffeine.php +1 -1
  26. addons/controller/addons/simple-share-buttons-adder/simple-share-buttons-adder.php +1 -1
  27. addons/controller/addons/wp-rocket/wp-rocket.php +1 -1
  28. addons/controller/addons/wpforms/wpforms.php +2 -2
  29. addons/controller/plugin-controller.php +5 -5
  30. addons/cookiebot-addons-init.php +12 -7
  31. addons/inc/Dependencies/DI/Annotation/Inject.php +95 -0
  32. addons/inc/Dependencies/DI/Annotation/Injectable.php +74 -0
  33. addons/inc/Dependencies/DI/Container.php +340 -0
  34. addons/inc/Dependencies/DI/ContainerBuilder.php +258 -0
  35. addons/inc/Dependencies/DI/Debug.php +39 -0
  36. addons/inc/Dependencies/DI/Definition/AbstractFunctionCallDefinition.php +82 -0
  37. addons/inc/Dependencies/DI/Definition/AliasDefinition.php +66 -0
  38. addons/inc/Dependencies/DI/Definition/ArrayDefinition.php +66 -0
  39. addons/inc/Dependencies/DI/Definition/ArrayDefinitionExtension.php +61 -0
  40. addons/inc/Dependencies/DI/Definition/CacheableDefinition.php +19 -0
  41. addons/inc/Dependencies/DI/Definition/DecoratorDefinition.php +48 -0
  42. addons/inc/Dependencies/DI/Definition/Definition.php +32 -0
  43. addons/inc/Dependencies/DI/Definition/Dumper/AliasDefinitionDumper.php +48 -0
  44. addons/inc/Dependencies/DI/Definition/Dumper/ArrayDefinitionDumper.php +65 -0
  45. addons/inc/Dependencies/DI/Definition/Dumper/DecoratorDefinitionDumper.php +37 -0
  46. addons/inc/Dependencies/DI/Definition/Dumper/DefinitionDumper.php +30 -0
  47. addons/inc/Dependencies/DI/Definition/Dumper/DefinitionDumperDispatcher.php +68 -0
  48. addons/inc/Dependencies/DI/Definition/Dumper/EnvironmentVariableDefinitionDumper.php +63 -0
  49. addons/inc/Dependencies/DI/Definition/Dumper/FactoryDefinitionDumper.php +37 -0
  50. addons/inc/Dependencies/DI/Definition/Dumper/ObjectDefinitionDumper.php +156 -0
  51. addons/inc/Dependencies/DI/Definition/Dumper/StringDefinitionDumper.php +37 -0
  52. addons/inc/Dependencies/DI/Definition/Dumper/ValueDefinitionDumper.php +44 -0
  53. addons/inc/Dependencies/DI/Definition/EntryReference.php +52 -0
  54. addons/inc/Dependencies/DI/Definition/EnvironmentVariableDefinition.php +116 -0
  55. addons/inc/Dependencies/DI/Definition/Exception/AnnotationException.php +19 -0
  56. addons/inc/Dependencies/DI/Definition/Exception/DefinitionException.php +30 -0
  57. addons/inc/Dependencies/DI/Definition/FactoryDefinition.php +75 -0
  58. addons/inc/Dependencies/DI/Definition/HasSubDefinition.php +28 -0
  59. addons/inc/Dependencies/DI/Definition/Helper/ArrayDefinitionExtensionHelper.php +46 -0
  60. addons/inc/Dependencies/DI/Definition/Helper/DefinitionHelper.php +24 -0
  61. addons/inc/Dependencies/DI/Definition/Helper/EnvironmentVariableDefinitionHelper.php +64 -0
  62. addons/inc/Dependencies/DI/Definition/Helper/FactoryDefinitionHelper.php +72 -0
  63. addons/inc/Dependencies/DI/Definition/Helper/ObjectDefinitionHelper.php +273 -0
  64. addons/inc/Dependencies/DI/Definition/Helper/StringDefinitionHelper.php +39 -0
  65. addons/inc/Dependencies/DI/Definition/Helper/ValueDefinitionHelper.php +42 -0
  66. addons/inc/Dependencies/DI/Definition/InstanceDefinition.php +76 -0
  67. addons/inc/Dependencies/DI/Definition/ObjectDefinition.php +294 -0
  68. addons/inc/Dependencies/DI/Definition/ObjectDefinition/MethodInjection.php +54 -0
  69. addons/inc/Dependencies/DI/Definition/ObjectDefinition/PropertyInjection.php +56 -0
  70. addons/inc/Dependencies/DI/Definition/Resolver/AliasResolver.php +77 -0
  71. addons/inc/Dependencies/DI/Definition/Resolver/ArrayResolver.php +105 -0
  72. addons/inc/Dependencies/DI/Definition/Resolver/DecoratorResolver.php +107 -0
  73. addons/inc/Dependencies/DI/Definition/Resolver/DefinitionResolver.php +44 -0
  74. addons/inc/Dependencies/DI/Definition/Resolver/EnvironmentVariableResolver.php +94 -0
  75. addons/inc/Dependencies/DI/Definition/Resolver/FactoryResolver.php +85 -0
  76. addons/inc/Dependencies/DI/Definition/Resolver/InstanceInjector.php +67 -0
  77. addons/inc/Dependencies/DI/Definition/Resolver/ObjectCreator.php +266 -0
  78. addons/inc/Dependencies/DI/Definition/Resolver/ParameterResolver.php +138 -0
  79. addons/inc/Dependencies/DI/Definition/Resolver/ResolverDispatcher.php +141 -0
  80. addons/inc/Dependencies/DI/Definition/Resolver/StringResolver.php +95 -0
  81. addons/inc/Dependencies/DI/Definition/Resolver/ValueResolver.php +58 -0
  82. addons/inc/Dependencies/DI/Definition/Source/AnnotationReader.php +298 -0
  83. addons/inc/Dependencies/DI/Definition/Source/Autowiring.php +68 -0
  84. addons/inc/Dependencies/DI/Definition/Source/CachedDefinitionSource.php +104 -0
  85. addons/inc/Dependencies/DI/Definition/Source/DefinitionArray.php +142 -0
  86. addons/inc/Dependencies/DI/Definition/Source/DefinitionFile.php +74 -0
  87. addons/inc/Dependencies/DI/Definition/Source/DefinitionSource.php +31 -0
  88. addons/inc/Dependencies/DI/Definition/Source/MutableDefinitionSource.php +15 -0
  89. addons/inc/Dependencies/DI/Definition/Source/SourceChain.php +108 -0
  90. addons/inc/Dependencies/DI/Definition/StringDefinition.php +66 -0
  91. addons/inc/Dependencies/DI/Definition/ValueDefinition.php +67 -0
  92. addons/inc/Dependencies/DI/DependencyException.php +19 -0
  93. addons/inc/Dependencies/DI/FactoryInterface.php +34 -0
  94. addons/inc/Dependencies/DI/Invoker/DefinitionParameterResolver.php +45 -0
  95. addons/inc/Dependencies/DI/InvokerInterface.php +19 -0
  96. addons/inc/Dependencies/DI/NotFoundException.php +19 -0
  97. addons/inc/Dependencies/DI/Proxy/ProxyFactory.php +88 -0
  98. addons/inc/Dependencies/DI/Reflection/CallableReflectionFactory.php +51 -0
  99. addons/inc/Dependencies/DI/Scope.php +54 -0
  100. addons/inc/Dependencies/DI/functions.php +181 -0
  101. addons/inc/Dependencies/Interop/Container/ContainerInterface.php +15 -0
  102. addons/inc/Dependencies/Interop/Container/Exception/ContainerException.php +15 -0
  103. addons/inc/Dependencies/Interop/Container/Exception/NotFoundException.php +15 -0
  104. addons/inc/Dependencies/Invoker/CallableResolver.php +127 -0
  105. addons/inc/Dependencies/Invoker/Exception/InvocationException.php +12 -0
  106. addons/inc/Dependencies/Invoker/Exception/NotCallableException.php +35 -0
  107. addons/inc/Dependencies/Invoker/Exception/NotEnoughParametersException.php +12 -0
  108. addons/inc/Dependencies/Invoker/Invoker.php +122 -0
  109. addons/inc/Dependencies/Invoker/InvokerInterface.php +29 -0
  110. addons/inc/Dependencies/Invoker/ParameterResolver/AssociativeArrayResolver.php +39 -0
  111. addons/inc/Dependencies/Invoker/ParameterResolver/Container/ParameterNameContainerResolver.php +51 -0
  112. addons/inc/Dependencies/Invoker/ParameterResolver/Container/TypeHintContainerResolver.php +51 -0
  113. addons/inc/Dependencies/Invoker/ParameterResolver/DefaultValueResolver.php +40 -0
  114. addons/inc/Dependencies/Invoker/ParameterResolver/NumericArrayResolver.php +39 -0
  115. addons/inc/Dependencies/Invoker/ParameterResolver/ParameterResolver.php +33 -0
  116. addons/inc/Dependencies/Invoker/ParameterResolver/ResolverChain.php +69 -0
  117. addons/inc/Dependencies/Invoker/ParameterResolver/TypeHintResolver.php +39 -0
  118. addons/inc/Dependencies/Invoker/Reflection/CallableReflection.php +61 -0
  119. addons/inc/Dependencies/PhpDocReader/AnnotationException.php +10 -0
  120. addons/inc/Dependencies/PhpDocReader/PhpDocReader.php +307 -0
  121. addons/inc/Dependencies/PhpDocReader/PhpParser/TokenParser.php +182 -0
  122. addons/inc/Dependencies/PhpDocReader/PhpParser/UseStatementParser.php +64 -0
  123. addons/inc/Dependencies/Psr/Container/ContainerExceptionInterface.php +13 -0
  124. addons/inc/Dependencies/Psr/Container/ContainerInterface.php +37 -0
  125. addons/inc/Dependencies/Psr/Container/NotFoundExceptionInterface.php +13 -0
  126. addons/inc/classes/dependencies/.gitkeep +0 -0
  127. addons/lib/helper.php +47 -3
  128. addons/lib/settings-service-interface.php +6 -5
  129. addons/lib/settings-service.php +12 -8
  130. addons/lib/theme-settings-service.php +70 -0
  131. addons/tests/integration/addons/test-custom-facebook-feed-old.php +24 -0
  132. addons/tests/integration/addons/test-custom-facebook-feed.php +5 -6
  133. addons/tests/integration/addons/test-google-site-kit.php +1 -1
  134. addons/tests/integration/addons/test-official-facebook-pixel.php +1 -1
  135. addons/tests/integration/test-buffer-priorities.php +0 -9
  136. addons/vendor/autoload.php +7 -0
  137. addons/vendor/composer/ClassLoader.php +445 -0
  138. addons/vendor/composer/LICENSE +21 -0
  139. addons/vendor/composer/autoload_classmap.php +9 -0
  140. addons/vendor/composer/autoload_files.php +10 -0
  141. addons/vendor/composer/autoload_namespaces.php +9 -0
  142. addons/vendor/composer/autoload_psr4.php +10 -0
  143. addons/vendor/composer/autoload_real.php +73 -0
  144. addons/vendor/composer/autoload_static.php +35 -0
  145. addons/vendor/composer/installed.json +1224 -0
  146. addons/view/admin/settings/available-addon-callback.php +7 -20
  147. addons/view/admin/settings/jetpack-addon-callback.php +7 -7
  148. addons/view/admin/settings/setting-page.php +6 -6
  149. cookiebot.php +1389 -1261
  150. readme.txt +14 -2
  151. widgets/cookiebot-declaration-widget.php +4 -4
addons/addons.json CHANGED
@@ -23,6 +23,9 @@
23
  "Hubspot_Tracking_Code": {
24
  "class": "cookiebot_addons\\controller\\addons\\hubspot_tracking_code\\Hubspot_Tracking_Code"
25
  },
 
 
 
26
  "Custom_Facebook_Feed": {
27
  "class": "cookiebot_addons\\controller\\addons\\custom_facebook_feed\\Custom_Facebook_Feed"
28
  },
@@ -94,5 +97,9 @@
94
  },
95
  "Google_Site_Kit": {
96
  "class": "cookiebot_addons\\controller\\addons\\google_site_kit\\Google_Site_Kit"
 
 
 
 
97
  }
98
  }
23
  "Hubspot_Tracking_Code": {
24
  "class": "cookiebot_addons\\controller\\addons\\hubspot_tracking_code\\Hubspot_Tracking_Code"
25
  },
26
+ "Custom_Facebook_Feed_Old": {
27
+ "class": "cookiebot_addons\\controller\\addons\\custom_facebook_feed_old\\Custom_Facebook_Feed_Old"
28
+ },
29
  "Custom_Facebook_Feed": {
30
  "class": "cookiebot_addons\\controller\\addons\\custom_facebook_feed\\Custom_Facebook_Feed"
31
  },
97
  },
98
  "Google_Site_Kit": {
99
  "class": "cookiebot_addons\\controller\\addons\\google_site_kit\\Google_Site_Kit"
100
+ },
101
+ "Enfold": {
102
+ "class": "cookiebot_addons\\controller\\addons\\enfold\\Enfold",
103
+ "is_theme": true
104
  }
105
  }
addons/composer.json CHANGED
@@ -2,7 +2,42 @@
2
  "require": {
3
  "php-di/php-di": "5.0"
4
  },
5
- "config":{
6
- "prepend-autoloader": false
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  }
8
  }
2
  "require": {
3
  "php-di/php-di": "5.0"
4
  },
5
+ "require-dev": {
6
+ "coenjacobs/mozart": "^0.6.0-beta-3"
7
+ },
8
+ "extra": {
9
+ "mozart": {
10
+ "dep_namespace": "Cybot\\Dependencies\\",
11
+ "dep_directory": "/inc/Dependencies/",
12
+ "classmap_directory": "/inc/classes/dependencies/",
13
+ "classmap_prefix": "Cybot_",
14
+ "packages": [
15
+ "php-di/php-di"
16
+ ],
17
+ "delete_vendor_directories": true
18
+ }
19
+ },
20
+ "autoload": {
21
+ "classmap": [
22
+ "inc/classes"
23
+ ],
24
+ "psr-4": {
25
+ "Cybot\\": "inc/"
26
+ },
27
+ "files": [
28
+ "inc/Dependencies/DI/functions.php"
29
+ ]
30
+ },
31
+ "scripts": {
32
+ "post-install-cmd": [
33
+ "\"vendor/bin/mozart\" compose",
34
+ "rm -Rf vendor/symfony vendor/coenjacobs vendor/league",
35
+ "composer dump-autoload"
36
+ ],
37
+ "post-update-cmd": [
38
+ "\"vendor/bin/mozart\" compose",
39
+ "rm -Rf vendor/symfony vendor/coenjacobs vendor/league",
40
+ "composer dump-autoload"
41
+ ]
42
  }
43
  }
addons/composer.lock CHANGED
@@ -4,7 +4,7 @@
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": "201899dc63377043c49159a10773dd47",
8
  "packages": [
9
  {
10
  "name": "container-interop/container-interop",
@@ -35,6 +35,7 @@
35
  ],
36
  "description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
37
  "homepage": "https://github.com/container-interop/container-interop",
 
38
  "time": "2017-02-14T19:40:03+00:00"
39
  },
40
  {
@@ -136,23 +137,24 @@
136
  },
137
  {
138
  "name": "php-di/phpdoc-reader",
139
- "version": "2.1.1",
140
  "source": {
141
  "type": "git",
142
  "url": "https://github.com/PHP-DI/PhpDocReader.git",
143
- "reference": "15678f7451c020226807f520efb867ad26fbbfcf"
144
  },
145
  "dist": {
146
  "type": "zip",
147
- "url": "https://api.github.com/repos/PHP-DI/PhpDocReader/zipball/15678f7451c020226807f520efb867ad26fbbfcf",
148
- "reference": "15678f7451c020226807f520efb867ad26fbbfcf",
149
  "shasum": ""
150
  },
151
  "require": {
152
- "php": ">=5.4.0"
153
  },
154
  "require-dev": {
155
- "phpunit/phpunit": "~4.6"
 
156
  },
157
  "type": "library",
158
  "autoload": {
@@ -169,7 +171,7 @@
169
  "phpdoc",
170
  "reflection"
171
  ],
172
- "time": "2019-09-26T11:24:58+00:00"
173
  },
174
  {
175
  "name": "psr/container",
@@ -221,12 +223,986 @@
221
  "time": "2017-02-14T16:28:37+00:00"
222
  }
223
  ],
224
- "packages-dev": [],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
225
  "aliases": [],
226
  "minimum-stability": "stable",
227
- "stability-flags": [],
 
 
228
  "prefer-stable": false,
229
  "prefer-lowest": false,
230
  "platform": [],
231
- "platform-dev": []
 
232
  }
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": "da8cd89411908476f7e244c8b5404934",
8
  "packages": [
9
  {
10
  "name": "container-interop/container-interop",
35
  ],
36
  "description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
37
  "homepage": "https://github.com/container-interop/container-interop",
38
+ "abandoned": "psr/container",
39
  "time": "2017-02-14T19:40:03+00:00"
40
  },
41
  {
137
  },
138
  {
139
  "name": "php-di/phpdoc-reader",
140
+ "version": "2.2.1",
141
  "source": {
142
  "type": "git",
143
  "url": "https://github.com/PHP-DI/PhpDocReader.git",
144
+ "reference": "66daff34cbd2627740ffec9469ffbac9f8c8185c"
145
  },
146
  "dist": {
147
  "type": "zip",
148
+ "url": "https://api.github.com/repos/PHP-DI/PhpDocReader/zipball/66daff34cbd2627740ffec9469ffbac9f8c8185c",
149
+ "reference": "66daff34cbd2627740ffec9469ffbac9f8c8185c",
150
  "shasum": ""
151
  },
152
  "require": {
153
+ "php": ">=7.2.0"
154
  },
155
  "require-dev": {
156
+ "mnapoli/hard-mode": "~0.3.0",
157
+ "phpunit/phpunit": "^8.5|^9.0"
158
  },
159
  "type": "library",
160
  "autoload": {
171
  "phpdoc",
172
  "reflection"
173
  ],
174
+ "time": "2020-10-12T12:39:22+00:00"
175
  },
176
  {
177
  "name": "psr/container",
223
  "time": "2017-02-14T16:28:37+00:00"
224
  }
225
  ],
226
+ "packages-dev": [
227
+ {
228
+ "name": "coenjacobs/mozart",
229
+ "version": "0.6.0-beta-3",
230
+ "source": {
231
+ "type": "git",
232
+ "url": "https://github.com/coenjacobs/mozart.git",
233
+ "reference": "965d698d76639587b26c878b22f4373c32f3d9ee"
234
+ },
235
+ "dist": {
236
+ "type": "zip",
237
+ "url": "https://api.github.com/repos/coenjacobs/mozart/zipball/965d698d76639587b26c878b22f4373c32f3d9ee",
238
+ "reference": "965d698d76639587b26c878b22f4373c32f3d9ee",
239
+ "shasum": ""
240
+ },
241
+ "require": {
242
+ "league/flysystem": "^1.0",
243
+ "php": "^7.2",
244
+ "symfony/console": "^4|^5",
245
+ "symfony/finder": "^4|^5"
246
+ },
247
+ "require-dev": {
248
+ "phpunit/phpunit": "^8.5",
249
+ "squizlabs/php_codesniffer": "^3.5"
250
+ },
251
+ "bin": [
252
+ "bin/mozart"
253
+ ],
254
+ "type": "library",
255
+ "autoload": {
256
+ "psr-4": {
257
+ "CoenJacobs\\Mozart\\": "src/"
258
+ }
259
+ },
260
+ "notification-url": "https://packagist.org/downloads/",
261
+ "license": [
262
+ "MIT"
263
+ ],
264
+ "authors": [
265
+ {
266
+ "name": "Coen Jacobs",
267
+ "email": "coenjacobs@gmail.com"
268
+ }
269
+ ],
270
+ "description": "Composes all dependencies as a package inside a WordPress plugin",
271
+ "funding": [
272
+ {
273
+ "url": "https://github.com/coenjacobs",
274
+ "type": "github"
275
+ }
276
+ ],
277
+ "time": "2020-06-02T06:54:01+00:00"
278
+ },
279
+ {
280
+ "name": "league/flysystem",
281
+ "version": "1.1.3",
282
+ "source": {
283
+ "type": "git",
284
+ "url": "https://github.com/thephpleague/flysystem.git",
285
+ "reference": "9be3b16c877d477357c015cec057548cf9b2a14a"
286
+ },
287
+ "dist": {
288
+ "type": "zip",
289
+ "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/9be3b16c877d477357c015cec057548cf9b2a14a",
290
+ "reference": "9be3b16c877d477357c015cec057548cf9b2a14a",
291
+ "shasum": ""
292
+ },
293
+ "require": {
294
+ "ext-fileinfo": "*",
295
+ "league/mime-type-detection": "^1.3",
296
+ "php": "^7.2.5 || ^8.0"
297
+ },
298
+ "conflict": {
299
+ "league/flysystem-sftp": "<1.0.6"
300
+ },
301
+ "require-dev": {
302
+ "phpspec/prophecy": "^1.11.1",
303
+ "phpunit/phpunit": "^8.5.8"
304
+ },
305
+ "suggest": {
306
+ "ext-fileinfo": "Required for MimeType",
307
+ "ext-ftp": "Allows you to use FTP server storage",
308
+ "ext-openssl": "Allows you to use FTPS server storage",
309
+ "league/flysystem-aws-s3-v2": "Allows you to use S3 storage with AWS SDK v2",
310
+ "league/flysystem-aws-s3-v3": "Allows you to use S3 storage with AWS SDK v3",
311
+ "league/flysystem-azure": "Allows you to use Windows Azure Blob storage",
312
+ "league/flysystem-cached-adapter": "Flysystem adapter decorator for metadata caching",
313
+ "league/flysystem-eventable-filesystem": "Allows you to use EventableFilesystem",
314
+ "league/flysystem-rackspace": "Allows you to use Rackspace Cloud Files",
315
+ "league/flysystem-sftp": "Allows you to use SFTP server storage via phpseclib",
316
+ "league/flysystem-webdav": "Allows you to use WebDAV storage",
317
+ "league/flysystem-ziparchive": "Allows you to use ZipArchive adapter",
318
+ "spatie/flysystem-dropbox": "Allows you to use Dropbox storage",
319
+ "srmklive/flysystem-dropbox-v2": "Allows you to use Dropbox storage for PHP 5 applications"
320
+ },
321
+ "type": "library",
322
+ "extra": {
323
+ "branch-alias": {
324
+ "dev-master": "1.1-dev"
325
+ }
326
+ },
327
+ "autoload": {
328
+ "psr-4": {
329
+ "League\\Flysystem\\": "src/"
330
+ }
331
+ },
332
+ "notification-url": "https://packagist.org/downloads/",
333
+ "license": [
334
+ "MIT"
335
+ ],
336
+ "authors": [
337
+ {
338
+ "name": "Frank de Jonge",
339
+ "email": "info@frenky.net"
340
+ }
341
+ ],
342
+ "description": "Filesystem abstraction: Many filesystems, one API.",
343
+ "keywords": [
344
+ "Cloud Files",
345
+ "WebDAV",
346
+ "abstraction",
347
+ "aws",
348
+ "cloud",
349
+ "copy.com",
350
+ "dropbox",
351
+ "file systems",
352
+ "files",
353
+ "filesystem",
354
+ "filesystems",
355
+ "ftp",
356
+ "rackspace",
357
+ "remote",
358
+ "s3",
359
+ "sftp",
360
+ "storage"
361
+ ],
362
+ "funding": [
363
+ {
364
+ "url": "https://offset.earth/frankdejonge",
365
+ "type": "other"
366
+ }
367
+ ],
368
+ "time": "2020-08-23T07:39:11+00:00"
369
+ },
370
+ {
371
+ "name": "league/mime-type-detection",
372
+ "version": "1.5.1",
373
+ "source": {
374
+ "type": "git",
375
+ "url": "https://github.com/thephpleague/mime-type-detection.git",
376
+ "reference": "353f66d7555d8a90781f6f5e7091932f9a4250aa"
377
+ },
378
+ "dist": {
379
+ "type": "zip",
380
+ "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/353f66d7555d8a90781f6f5e7091932f9a4250aa",
381
+ "reference": "353f66d7555d8a90781f6f5e7091932f9a4250aa",
382
+ "shasum": ""
383
+ },
384
+ "require": {
385
+ "ext-fileinfo": "*",
386
+ "php": "^7.2 || ^8.0"
387
+ },
388
+ "require-dev": {
389
+ "phpstan/phpstan": "^0.12.36",
390
+ "phpunit/phpunit": "^8.5.8"
391
+ },
392
+ "type": "library",
393
+ "autoload": {
394
+ "psr-4": {
395
+ "League\\MimeTypeDetection\\": "src"
396
+ }
397
+ },
398
+ "notification-url": "https://packagist.org/downloads/",
399
+ "license": [
400
+ "MIT"
401
+ ],
402
+ "authors": [
403
+ {
404
+ "name": "Frank de Jonge",
405
+ "email": "info@frankdejonge.nl"
406
+ }
407
+ ],
408
+ "description": "Mime-type detection for Flysystem",
409
+ "funding": [
410
+ {
411
+ "url": "https://github.com/frankdejonge",
412
+ "type": "github"
413
+ },
414
+ {
415
+ "url": "https://tidelift.com/funding/github/packagist/league/flysystem",
416
+ "type": "tidelift"
417
+ }
418
+ ],
419
+ "time": "2020-10-18T11:50:25+00:00"
420
+ },
421
+ {
422
+ "name": "symfony/console",
423
+ "version": "v5.2.1",
424
+ "source": {
425
+ "type": "git",
426
+ "url": "https://github.com/symfony/console.git",
427
+ "reference": "47c02526c532fb381374dab26df05e7313978976"
428
+ },
429
+ "dist": {
430
+ "type": "zip",
431
+ "url": "https://api.github.com/repos/symfony/console/zipball/47c02526c532fb381374dab26df05e7313978976",
432
+ "reference": "47c02526c532fb381374dab26df05e7313978976",
433
+ "shasum": ""
434
+ },
435
+ "require": {
436
+ "php": ">=7.2.5",
437
+ "symfony/polyfill-mbstring": "~1.0",
438
+ "symfony/polyfill-php73": "^1.8",
439
+ "symfony/polyfill-php80": "^1.15",
440
+ "symfony/service-contracts": "^1.1|^2",
441
+ "symfony/string": "^5.1"
442
+ },
443
+ "conflict": {
444
+ "symfony/dependency-injection": "<4.4",
445
+ "symfony/dotenv": "<5.1",
446
+ "symfony/event-dispatcher": "<4.4",
447
+ "symfony/lock": "<4.4",
448
+ "symfony/process": "<4.4"
449
+ },
450
+ "provide": {
451
+ "psr/log-implementation": "1.0"
452
+ },
453
+ "require-dev": {
454
+ "psr/log": "~1.0",
455
+ "symfony/config": "^4.4|^5.0",
456
+ "symfony/dependency-injection": "^4.4|^5.0",
457
+ "symfony/event-dispatcher": "^4.4|^5.0",
458
+ "symfony/lock": "^4.4|^5.0",
459
+ "symfony/process": "^4.4|^5.0",
460
+ "symfony/var-dumper": "^4.4|^5.0"
461
+ },
462
+ "suggest": {
463
+ "psr/log": "For using the console logger",
464
+ "symfony/event-dispatcher": "",
465
+ "symfony/lock": "",
466
+ "symfony/process": ""
467
+ },
468
+ "type": "library",
469
+ "autoload": {
470
+ "psr-4": {
471
+ "Symfony\\Component\\Console\\": ""
472
+ },
473
+ "exclude-from-classmap": [
474
+ "/Tests/"
475
+ ]
476
+ },
477
+ "notification-url": "https://packagist.org/downloads/",
478
+ "license": [
479
+ "MIT"
480
+ ],
481
+ "authors": [
482
+ {
483
+ "name": "Fabien Potencier",
484
+ "email": "fabien@symfony.com"
485
+ },
486
+ {
487
+ "name": "Symfony Community",
488
+ "homepage": "https://symfony.com/contributors"
489
+ }
490
+ ],
491
+ "description": "Symfony Console Component",
492
+ "homepage": "https://symfony.com",
493
+ "keywords": [
494
+ "cli",
495
+ "command line",
496
+ "console",
497
+ "terminal"
498
+ ],
499
+ "funding": [
500
+ {
501
+ "url": "https://symfony.com/sponsor",
502
+ "type": "custom"
503
+ },
504
+ {
505
+ "url": "https://github.com/fabpot",
506
+ "type": "github"
507
+ },
508
+ {
509
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
510
+ "type": "tidelift"
511
+ }
512
+ ],
513
+ "time": "2020-12-18T08:03:05+00:00"
514
+ },
515
+ {
516
+ "name": "symfony/finder",
517
+ "version": "v5.2.1",
518
+ "source": {
519
+ "type": "git",
520
+ "url": "https://github.com/symfony/finder.git",
521
+ "reference": "0b9231a5922fd7287ba5b411893c0ecd2733e5ba"
522
+ },
523
+ "dist": {
524
+ "type": "zip",
525
+ "url": "https://api.github.com/repos/symfony/finder/zipball/0b9231a5922fd7287ba5b411893c0ecd2733e5ba",
526
+ "reference": "0b9231a5922fd7287ba5b411893c0ecd2733e5ba",
527
+ "shasum": ""
528
+ },
529
+ "require": {
530
+ "php": ">=7.2.5"
531
+ },
532
+ "type": "library",
533
+ "autoload": {
534
+ "psr-4": {
535
+ "Symfony\\Component\\Finder\\": ""
536
+ },
537
+ "exclude-from-classmap": [
538
+ "/Tests/"
539
+ ]
540
+ },
541
+ "notification-url": "https://packagist.org/downloads/",
542
+ "license": [
543
+ "MIT"
544
+ ],
545
+ "authors": [
546
+ {
547
+ "name": "Fabien Potencier",
548
+ "email": "fabien@symfony.com"
549
+ },
550
+ {
551
+ "name": "Symfony Community",
552
+ "homepage": "https://symfony.com/contributors"
553
+ }
554
+ ],
555
+ "description": "Symfony Finder Component",
556
+ "homepage": "https://symfony.com",
557
+ "funding": [
558
+ {
559
+ "url": "https://symfony.com/sponsor",
560
+ "type": "custom"
561
+ },
562
+ {
563
+ "url": "https://github.com/fabpot",
564
+ "type": "github"
565
+ },
566
+ {
567
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
568
+ "type": "tidelift"
569
+ }
570
+ ],
571
+ "time": "2020-12-08T17:02:38+00:00"
572
+ },
573
+ {
574
+ "name": "symfony/polyfill-ctype",
575
+ "version": "v1.22.0",
576
+ "source": {
577
+ "type": "git",
578
+ "url": "https://github.com/symfony/polyfill-ctype.git",
579
+ "reference": "c6c942b1ac76c82448322025e084cadc56048b4e"
580
+ },
581
+ "dist": {
582
+ "type": "zip",
583
+ "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/c6c942b1ac76c82448322025e084cadc56048b4e",
584
+ "reference": "c6c942b1ac76c82448322025e084cadc56048b4e",
585
+ "shasum": ""
586
+ },
587
+ "require": {
588
+ "php": ">=7.1"
589
+ },
590
+ "suggest": {
591
+ "ext-ctype": "For best performance"
592
+ },
593
+ "type": "library",
594
+ "extra": {
595
+ "branch-alias": {
596
+ "dev-main": "1.22-dev"
597
+ },
598
+ "thanks": {
599
+ "name": "symfony/polyfill",
600
+ "url": "https://github.com/symfony/polyfill"
601
+ }
602
+ },
603
+ "autoload": {
604
+ "psr-4": {
605
+ "Symfony\\Polyfill\\Ctype\\": ""
606
+ },
607
+ "files": [
608
+ "bootstrap.php"
609
+ ]
610
+ },
611
+ "notification-url": "https://packagist.org/downloads/",
612
+ "license": [
613
+ "MIT"
614
+ ],
615
+ "authors": [
616
+ {
617
+ "name": "Gert de Pagter",
618
+ "email": "BackEndTea@gmail.com"
619
+ },
620
+ {
621
+ "name": "Symfony Community",
622
+ "homepage": "https://symfony.com/contributors"
623
+ }
624
+ ],
625
+ "description": "Symfony polyfill for ctype functions",
626
+ "homepage": "https://symfony.com",
627
+ "keywords": [
628
+ "compatibility",
629
+ "ctype",
630
+ "polyfill",
631
+ "portable"
632
+ ],
633
+ "funding": [
634
+ {
635
+ "url": "https://symfony.com/sponsor",
636
+ "type": "custom"
637
+ },
638
+ {
639
+ "url": "https://github.com/fabpot",
640
+ "type": "github"
641
+ },
642
+ {
643
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
644
+ "type": "tidelift"
645
+ }
646
+ ],
647
+ "time": "2021-01-07T16:49:33+00:00"
648
+ },
649
+ {
650
+ "name": "symfony/polyfill-intl-grapheme",
651
+ "version": "v1.22.0",
652
+ "source": {
653
+ "type": "git",
654
+ "url": "https://github.com/symfony/polyfill-intl-grapheme.git",
655
+ "reference": "267a9adeb8ecb8071040a740930e077cdfb987af"
656
+ },
657
+ "dist": {
658
+ "type": "zip",
659
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/267a9adeb8ecb8071040a740930e077cdfb987af",
660
+ "reference": "267a9adeb8ecb8071040a740930e077cdfb987af",
661
+ "shasum": ""
662
+ },
663
+ "require": {
664
+ "php": ">=7.1"
665
+ },
666
+ "suggest": {
667
+ "ext-intl": "For best performance"
668
+ },
669
+ "type": "library",
670
+ "extra": {
671
+ "branch-alias": {
672
+ "dev-main": "1.22-dev"
673
+ },
674
+ "thanks": {
675
+ "name": "symfony/polyfill",
676
+ "url": "https://github.com/symfony/polyfill"
677
+ }
678
+ },
679
+ "autoload": {
680
+ "psr-4": {
681
+ "Symfony\\Polyfill\\Intl\\Grapheme\\": ""
682
+ },
683
+ "files": [
684
+ "bootstrap.php"
685
+ ]
686
+ },
687
+ "notification-url": "https://packagist.org/downloads/",
688
+ "license": [
689
+ "MIT"
690
+ ],
691
+ "authors": [
692
+ {
693
+ "name": "Nicolas Grekas",
694
+ "email": "p@tchwork.com"
695
+ },
696
+ {
697
+ "name": "Symfony Community",
698
+ "homepage": "https://symfony.com/contributors"
699
+ }
700
+ ],
701
+ "description": "Symfony polyfill for intl's grapheme_* functions",
702
+ "homepage": "https://symfony.com",
703
+ "keywords": [
704
+ "compatibility",
705
+ "grapheme",
706
+ "intl",
707
+ "polyfill",
708
+ "portable",
709
+ "shim"
710
+ ],
711
+ "funding": [
712
+ {
713
+ "url": "https://symfony.com/sponsor",
714
+ "type": "custom"
715
+ },
716
+ {
717
+ "url": "https://github.com/fabpot",
718
+ "type": "github"
719
+ },
720
+ {
721
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
722
+ "type": "tidelift"
723
+ }
724
+ ],
725
+ "time": "2021-01-07T16:49:33+00:00"
726
+ },
727
+ {
728
+ "name": "symfony/polyfill-intl-normalizer",
729
+ "version": "v1.22.0",
730
+ "source": {
731
+ "type": "git",
732
+ "url": "https://github.com/symfony/polyfill-intl-normalizer.git",
733
+ "reference": "6e971c891537eb617a00bb07a43d182a6915faba"
734
+ },
735
+ "dist": {
736
+ "type": "zip",
737
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/6e971c891537eb617a00bb07a43d182a6915faba",
738
+ "reference": "6e971c891537eb617a00bb07a43d182a6915faba",
739
+ "shasum": ""
740
+ },
741
+ "require": {
742
+ "php": ">=7.1"
743
+ },
744
+ "suggest": {
745
+ "ext-intl": "For best performance"
746
+ },
747
+ "type": "library",
748
+ "extra": {
749
+ "branch-alias": {
750
+ "dev-main": "1.22-dev"
751
+ },
752
+ "thanks": {
753
+ "name": "symfony/polyfill",
754
+ "url": "https://github.com/symfony/polyfill"
755
+ }
756
+ },
757
+ "autoload": {
758
+ "psr-4": {
759
+ "Symfony\\Polyfill\\Intl\\Normalizer\\": ""
760
+ },
761
+ "files": [
762
+ "bootstrap.php"
763
+ ],
764
+ "classmap": [
765
+ "Resources/stubs"
766
+ ]
767
+ },
768
+ "notification-url": "https://packagist.org/downloads/",
769
+ "license": [
770
+ "MIT"
771
+ ],
772
+ "authors": [
773
+ {
774
+ "name": "Nicolas Grekas",
775
+ "email": "p@tchwork.com"
776
+ },
777
+ {
778
+ "name": "Symfony Community",
779
+ "homepage": "https://symfony.com/contributors"
780
+ }
781
+ ],
782
+ "description": "Symfony polyfill for intl's Normalizer class and related functions",
783
+ "homepage": "https://symfony.com",
784
+ "keywords": [
785
+ "compatibility",
786
+ "intl",
787
+ "normalizer",
788
+ "polyfill",
789
+ "portable",
790
+ "shim"
791
+ ],
792
+ "funding": [
793
+ {
794
+ "url": "https://symfony.com/sponsor",
795
+ "type": "custom"
796
+ },
797
+ {
798
+ "url": "https://github.com/fabpot",
799
+ "type": "github"
800
+ },
801
+ {
802
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
803
+ "type": "tidelift"
804
+ }
805
+ ],
806
+ "time": "2021-01-07T17:09:11+00:00"
807
+ },
808
+ {
809
+ "name": "symfony/polyfill-mbstring",
810
+ "version": "v1.22.0",
811
+ "source": {
812
+ "type": "git",
813
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
814
+ "reference": "f377a3dd1fde44d37b9831d68dc8dea3ffd28e13"
815
+ },
816
+ "dist": {
817
+ "type": "zip",
818
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/f377a3dd1fde44d37b9831d68dc8dea3ffd28e13",
819
+ "reference": "f377a3dd1fde44d37b9831d68dc8dea3ffd28e13",
820
+ "shasum": ""
821
+ },
822
+ "require": {
823
+ "php": ">=7.1"
824
+ },
825
+ "suggest": {
826
+ "ext-mbstring": "For best performance"
827
+ },
828
+ "type": "library",
829
+ "extra": {
830
+ "branch-alias": {
831
+ "dev-main": "1.22-dev"
832
+ },
833
+ "thanks": {
834
+ "name": "symfony/polyfill",
835
+ "url": "https://github.com/symfony/polyfill"
836
+ }
837
+ },
838
+ "autoload": {
839
+ "psr-4": {
840
+ "Symfony\\Polyfill\\Mbstring\\": ""
841
+ },
842
+ "files": [
843
+ "bootstrap.php"
844
+ ]
845
+ },
846
+ "notification-url": "https://packagist.org/downloads/",
847
+ "license": [
848
+ "MIT"
849
+ ],
850
+ "authors": [
851
+ {
852
+ "name": "Nicolas Grekas",
853
+ "email": "p@tchwork.com"
854
+ },
855
+ {
856
+ "name": "Symfony Community",
857
+ "homepage": "https://symfony.com/contributors"
858
+ }
859
+ ],
860
+ "description": "Symfony polyfill for the Mbstring extension",
861
+ "homepage": "https://symfony.com",
862
+ "keywords": [
863
+ "compatibility",
864
+ "mbstring",
865
+ "polyfill",
866
+ "portable",
867
+ "shim"
868
+ ],
869
+ "funding": [
870
+ {
871
+ "url": "https://symfony.com/sponsor",
872
+ "type": "custom"
873
+ },
874
+ {
875
+ "url": "https://github.com/fabpot",
876
+ "type": "github"
877
+ },
878
+ {
879
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
880
+ "type": "tidelift"
881
+ }
882
+ ],
883
+ "time": "2021-01-07T16:49:33+00:00"
884
+ },
885
+ {
886
+ "name": "symfony/polyfill-php73",
887
+ "version": "v1.22.0",
888
+ "source": {
889
+ "type": "git",
890
+ "url": "https://github.com/symfony/polyfill-php73.git",
891
+ "reference": "a678b42e92f86eca04b7fa4c0f6f19d097fb69e2"
892
+ },
893
+ "dist": {
894
+ "type": "zip",
895
+ "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/a678b42e92f86eca04b7fa4c0f6f19d097fb69e2",
896
+ "reference": "a678b42e92f86eca04b7fa4c0f6f19d097fb69e2",
897
+ "shasum": ""
898
+ },
899
+ "require": {
900
+ "php": ">=7.1"
901
+ },
902
+ "type": "library",
903
+ "extra": {
904
+ "branch-alias": {
905
+ "dev-main": "1.22-dev"
906
+ },
907
+ "thanks": {
908
+ "name": "symfony/polyfill",
909
+ "url": "https://github.com/symfony/polyfill"
910
+ }
911
+ },
912
+ "autoload": {
913
+ "psr-4": {
914
+ "Symfony\\Polyfill\\Php73\\": ""
915
+ },
916
+ "files": [
917
+ "bootstrap.php"
918
+ ],
919
+ "classmap": [
920
+ "Resources/stubs"
921
+ ]
922
+ },
923
+ "notification-url": "https://packagist.org/downloads/",
924
+ "license": [
925
+ "MIT"
926
+ ],
927
+ "authors": [
928
+ {
929
+ "name": "Nicolas Grekas",
930
+ "email": "p@tchwork.com"
931
+ },
932
+ {
933
+ "name": "Symfony Community",
934
+ "homepage": "https://symfony.com/contributors"
935
+ }
936
+ ],
937
+ "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions",
938
+ "homepage": "https://symfony.com",
939
+ "keywords": [
940
+ "compatibility",
941
+ "polyfill",
942
+ "portable",
943
+ "shim"
944
+ ],
945
+ "funding": [
946
+ {
947
+ "url": "https://symfony.com/sponsor",
948
+ "type": "custom"
949
+ },
950
+ {
951
+ "url": "https://github.com/fabpot",
952
+ "type": "github"
953
+ },
954
+ {
955
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
956
+ "type": "tidelift"
957
+ }
958
+ ],
959
+ "time": "2021-01-07T16:49:33+00:00"
960
+ },
961
+ {
962
+ "name": "symfony/polyfill-php80",
963
+ "version": "v1.22.0",
964
+ "source": {
965
+ "type": "git",
966
+ "url": "https://github.com/symfony/polyfill-php80.git",
967
+ "reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91"
968
+ },
969
+ "dist": {
970
+ "type": "zip",
971
+ "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/dc3063ba22c2a1fd2f45ed856374d79114998f91",
972
+ "reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91",
973
+ "shasum": ""
974
+ },
975
+ "require": {
976
+ "php": ">=7.1"
977
+ },
978
+ "type": "library",
979
+ "extra": {
980
+ "branch-alias": {
981
+ "dev-main": "1.22-dev"
982
+ },
983
+ "thanks": {
984
+ "name": "symfony/polyfill",
985
+ "url": "https://github.com/symfony/polyfill"
986
+ }
987
+ },
988
+ "autoload": {
989
+ "psr-4": {
990
+ "Symfony\\Polyfill\\Php80\\": ""
991
+ },
992
+ "files": [
993
+ "bootstrap.php"
994
+ ],
995
+ "classmap": [
996
+ "Resources/stubs"
997
+ ]
998
+ },
999
+ "notification-url": "https://packagist.org/downloads/",
1000
+ "license": [
1001
+ "MIT"
1002
+ ],
1003
+ "authors": [
1004
+ {
1005
+ "name": "Ion Bazan",
1006
+ "email": "ion.bazan@gmail.com"
1007
+ },
1008
+ {
1009
+ "name": "Nicolas Grekas",
1010
+ "email": "p@tchwork.com"
1011
+ },
1012
+ {
1013
+ "name": "Symfony Community",
1014
+ "homepage": "https://symfony.com/contributors"
1015
+ }
1016
+ ],
1017
+ "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
1018
+ "homepage": "https://symfony.com",
1019
+ "keywords": [
1020
+ "compatibility",
1021
+ "polyfill",
1022
+ "portable",
1023
+ "shim"
1024
+ ],
1025
+ "funding": [
1026
+ {
1027
+ "url": "https://symfony.com/sponsor",
1028
+ "type": "custom"
1029
+ },
1030
+ {
1031
+ "url": "https://github.com/fabpot",
1032
+ "type": "github"
1033
+ },
1034
+ {
1035
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
1036
+ "type": "tidelift"
1037
+ }
1038
+ ],
1039
+ "time": "2021-01-07T16:49:33+00:00"
1040
+ },
1041
+ {
1042
+ "name": "symfony/service-contracts",
1043
+ "version": "v2.2.0",
1044
+ "source": {
1045
+ "type": "git",
1046
+ "url": "https://github.com/symfony/service-contracts.git",
1047
+ "reference": "d15da7ba4957ffb8f1747218be9e1a121fd298a1"
1048
+ },
1049
+ "dist": {
1050
+ "type": "zip",
1051
+ "url": "https://api.github.com/repos/symfony/service-contracts/zipball/d15da7ba4957ffb8f1747218be9e1a121fd298a1",
1052
+ "reference": "d15da7ba4957ffb8f1747218be9e1a121fd298a1",
1053
+ "shasum": ""
1054
+ },
1055
+ "require": {
1056
+ "php": ">=7.2.5",
1057
+ "psr/container": "^1.0"
1058
+ },
1059
+ "suggest": {
1060
+ "symfony/service-implementation": ""
1061
+ },
1062
+ "type": "library",
1063
+ "extra": {
1064
+ "branch-alias": {
1065
+ "dev-master": "2.2-dev"
1066
+ },
1067
+ "thanks": {
1068
+ "name": "symfony/contracts",
1069
+ "url": "https://github.com/symfony/contracts"
1070
+ }
1071
+ },
1072
+ "autoload": {
1073
+ "psr-4": {
1074
+ "Symfony\\Contracts\\Service\\": ""
1075
+ }
1076
+ },
1077
+ "notification-url": "https://packagist.org/downloads/",
1078
+ "license": [
1079
+ "MIT"
1080
+ ],
1081
+ "authors": [
1082
+ {
1083
+ "name": "Nicolas Grekas",
1084
+ "email": "p@tchwork.com"
1085
+ },
1086
+ {
1087
+ "name": "Symfony Community",
1088
+ "homepage": "https://symfony.com/contributors"
1089
+ }
1090
+ ],
1091
+ "description": "Generic abstractions related to writing services",
1092
+ "homepage": "https://symfony.com",
1093
+ "keywords": [
1094
+ "abstractions",
1095
+ "contracts",
1096
+ "decoupling",
1097
+ "interfaces",
1098
+ "interoperability",
1099
+ "standards"
1100
+ ],
1101
+ "funding": [
1102
+ {
1103
+ "url": "https://symfony.com/sponsor",
1104
+ "type": "custom"
1105
+ },
1106
+ {
1107
+ "url": "https://github.com/fabpot",
1108
+ "type": "github"
1109
+ },
1110
+ {
1111
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
1112
+ "type": "tidelift"
1113
+ }
1114
+ ],
1115
+ "time": "2020-09-07T11:33:47+00:00"
1116
+ },
1117
+ {
1118
+ "name": "symfony/string",
1119
+ "version": "v5.2.1",
1120
+ "source": {
1121
+ "type": "git",
1122
+ "url": "https://github.com/symfony/string.git",
1123
+ "reference": "5bd67751d2e3f7d6f770c9154b8fbcb2aa05f7ed"
1124
+ },
1125
+ "dist": {
1126
+ "type": "zip",
1127
+ "url": "https://api.github.com/repos/symfony/string/zipball/5bd67751d2e3f7d6f770c9154b8fbcb2aa05f7ed",
1128
+ "reference": "5bd67751d2e3f7d6f770c9154b8fbcb2aa05f7ed",
1129
+ "shasum": ""
1130
+ },
1131
+ "require": {
1132
+ "php": ">=7.2.5",
1133
+ "symfony/polyfill-ctype": "~1.8",
1134
+ "symfony/polyfill-intl-grapheme": "~1.0",
1135
+ "symfony/polyfill-intl-normalizer": "~1.0",
1136
+ "symfony/polyfill-mbstring": "~1.0",
1137
+ "symfony/polyfill-php80": "~1.15"
1138
+ },
1139
+ "require-dev": {
1140
+ "symfony/error-handler": "^4.4|^5.0",
1141
+ "symfony/http-client": "^4.4|^5.0",
1142
+ "symfony/translation-contracts": "^1.1|^2",
1143
+ "symfony/var-exporter": "^4.4|^5.0"
1144
+ },
1145
+ "type": "library",
1146
+ "autoload": {
1147
+ "psr-4": {
1148
+ "Symfony\\Component\\String\\": ""
1149
+ },
1150
+ "files": [
1151
+ "Resources/functions.php"
1152
+ ],
1153
+ "exclude-from-classmap": [
1154
+ "/Tests/"
1155
+ ]
1156
+ },
1157
+ "notification-url": "https://packagist.org/downloads/",
1158
+ "license": [
1159
+ "MIT"
1160
+ ],
1161
+ "authors": [
1162
+ {
1163
+ "name": "Nicolas Grekas",
1164
+ "email": "p@tchwork.com"
1165
+ },
1166
+ {
1167
+ "name": "Symfony Community",
1168
+ "homepage": "https://symfony.com/contributors"
1169
+ }
1170
+ ],
1171
+ "description": "Symfony String component",
1172
+ "homepage": "https://symfony.com",
1173
+ "keywords": [
1174
+ "grapheme",
1175
+ "i18n",
1176
+ "string",
1177
+ "unicode",
1178
+ "utf-8",
1179
+ "utf8"
1180
+ ],
1181
+ "funding": [
1182
+ {
1183
+ "url": "https://symfony.com/sponsor",
1184
+ "type": "custom"
1185
+ },
1186
+ {
1187
+ "url": "https://github.com/fabpot",
1188
+ "type": "github"
1189
+ },
1190
+ {
1191
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
1192
+ "type": "tidelift"
1193
+ }
1194
+ ],
1195
+ "time": "2020-12-05T07:33:16+00:00"
1196
+ }
1197
+ ],
1198
  "aliases": [],
1199
  "minimum-stability": "stable",
1200
+ "stability-flags": {
1201
+ "coenjacobs/mozart": 10
1202
+ },
1203
  "prefer-stable": false,
1204
  "prefer-lowest": false,
1205
  "platform": [],
1206
+ "platform-dev": [],
1207
+ "plugin-api-version": "1.1.0"
1208
  }
addons/config/settings-config.php CHANGED
@@ -43,12 +43,12 @@ class Settings_Config {
43
  * @since 1.3.0
44
  */
45
  public function add_submenu() {
46
- /*add_submenu_page('cookiebot', 'Prior Consent', __( 'Prior Consent', 'cookiebot' ), 'manage_options', 'cookiebot_addons', array(
47
  $this,
48
  'setting_page'
49
  ) );*/
50
 
51
- add_submenu_page( 'cookiebot', __( 'Prior Consent', 'cookiebot' ), __( 'Prior Consent', 'cookiebot' ), 'manage_options', 'cookiebot-addons', array(
52
  $this,
53
  'setting_page'
54
  ) );
@@ -67,7 +67,7 @@ class Settings_Config {
67
 
68
  wp_enqueue_script( 'cookiebot_tiptip_js', plugins_url( 'js/jquery.tipTip.js', dirname( __FILE__ ) ), array( 'jquery' ), '1.8', true );
69
  wp_enqueue_script( 'cookiebot_addons_custom_js', plugins_url( 'js/settings.js', dirname( __FILE__ ) ), array( 'jquery' ), '1.8', true );
70
- wp_localize_script( 'cookiebot_addons_custom_js', 'php', array( 'remove_link' => ' <a href="" class="submitdelete deletion">' . __( 'Remove language', 'cookiebot-addons' ) . '</a>' ) );
71
  wp_enqueue_style( 'cookiebot_addons_custom_css', plugins_url( 'style/css/admin_styles.css', dirname( __FILE__ ) ) );
72
  }
73
 
@@ -223,7 +223,7 @@ class Settings_Config {
223
  * @since 1.3.0
224
  */
225
  public function header_jetpack_addon() {
226
- echo '<p>' . __( 'Jetpack settings.', 'cookiebot' ) . '</p>';
227
  }
228
 
229
  /**
@@ -245,11 +245,11 @@ class Settings_Config {
245
  public function header_available_addons() {
246
  ?>
247
  <p>
248
- <?php _e( 'Below is a list of addons for Cookiebot. Addons help you make installed plugins GDPR compliant.', 'cookiebot' ); ?>
249
  <br/>
250
- <?php _e( 'These addons are available because you have the corresponding plugins installed and activated.', 'cookiebot' ); ?>
251
  <br/>
252
- <?php _e( 'Deactivate an addon if you want to handle GDPR compliance yourself, or through another plugin.', 'cookiebot' ); ?>
253
  </p>
254
  <?php
255
  }
@@ -273,7 +273,7 @@ class Settings_Config {
273
  * @since 1.3.0
274
  */
275
  public function header_unavailable_addons() {
276
- echo '<p>' . __( 'The following addons are unavailable. This is because the corresponding plugin is not installed.', 'cookiebot' ) . '</p>';
277
  }
278
 
279
  /**
@@ -290,9 +290,9 @@ class Settings_Config {
290
  <div class="postbox cookiebot-addon">
291
  <i><?php
292
  if ( ! $addon->is_addon_installed() ) {
293
- _e( 'The plugin is not installed.', 'cookiebot' );
294
  } else if ( ! $addon->is_addon_activated() ) {
295
- _e( 'The plugin is not activated.', 'cookiebot' );
296
  }
297
  ?></i>
298
  </div>
43
  * @since 1.3.0
44
  */
45
  public function add_submenu() {
46
+ /*add_submenu_page('cookiebot', 'Prior Consent', esc_html__( 'Prior Consent', 'cookiebot' ), 'manage_options', 'cookiebot_addons', array(
47
  $this,
48
  'setting_page'
49
  ) );*/
50
 
51
+ add_submenu_page( 'cookiebot', esc_html__( 'Prior Consent', 'cookiebot' ), esc_html__( 'Prior Consent', 'cookiebot' ), 'manage_options', 'cookiebot-addons', array(
52
  $this,
53
  'setting_page'
54
  ) );
67
 
68
  wp_enqueue_script( 'cookiebot_tiptip_js', plugins_url( 'js/jquery.tipTip.js', dirname( __FILE__ ) ), array( 'jquery' ), '1.8', true );
69
  wp_enqueue_script( 'cookiebot_addons_custom_js', plugins_url( 'js/settings.js', dirname( __FILE__ ) ), array( 'jquery' ), '1.8', true );
70
+ wp_localize_script( 'cookiebot_addons_custom_js', 'php', array( 'remove_link' => ' <a href="" class="submitdelete deletion">' . esc_html__( 'Remove language', 'cookiebot-addons' ) . '</a>' ) );
71
  wp_enqueue_style( 'cookiebot_addons_custom_css', plugins_url( 'style/css/admin_styles.css', dirname( __FILE__ ) ) );
72
  }
73
 
223
  * @since 1.3.0
224
  */
225
  public function header_jetpack_addon() {
226
+ echo '<p>' . esc_html__( 'Jetpack settings.', 'cookiebot' ) . '</p>';
227
  }
228
 
229
  /**
245
  public function header_available_addons() {
246
  ?>
247
  <p>
248
+ <?php esc_html_e( 'Below is a list of addons for Cookiebot. Addons help you make installed plugins GDPR compliant.', 'cookiebot' ); ?>
249
  <br/>
250
+ <?php esc_html_e( 'These addons are available because you have the corresponding plugins installed and activated.', 'cookiebot' ); ?>
251
  <br/>
252
+ <?php esc_html_e( 'Deactivate an addon if you want to handle GDPR compliance yourself, or through another plugin.', 'cookiebot' ); ?>
253
  </p>
254
  <?php
255
  }
273
  * @since 1.3.0
274
  */
275
  public function header_unavailable_addons() {
276
+ echo '<p>' . esc_html__( 'The following addons are unavailable. This is because the corresponding plugin is not installed.', 'cookiebot' ) . '</p>';
277
  }
278
 
279
  /**
290
  <div class="postbox cookiebot-addon">
291
  <i><?php
292
  if ( ! $addon->is_addon_installed() ) {
293
+ esc_html_e( 'The plugin is not installed.', 'cookiebot' );
294
  } else if ( ! $addon->is_addon_activated() ) {
295
+ esc_html_e( 'The plugin is not activated.', 'cookiebot' );
296
  }
297
  ?></i>
298
  </div>
addons/controller/addons/add-to-any/add-to-any.php CHANGED
@@ -2,6 +2,9 @@
2
 
3
  namespace cookiebot_addons\controller\addons\add_to_any;
4
 
 
 
 
5
  use cookiebot_addons\controller\addons\Cookiebot_Addons_Interface;
6
  use cookiebot_addons\lib\Cookie_Consent_Interface;
7
  use cookiebot_addons\lib\Settings_Service_Interface;
@@ -87,6 +90,49 @@ class Add_To_Any implements Cookiebot_Addons_Interface {
87
  if ( has_action( 'wp_enqueue_scripts', 'A2A_SHARE_SAVE_enqueue_script' ) ) {
88
  $this->script_loader_tag->add_tag( 'addtoany', $this->get_cookie_types() );
89
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  }
91
 
92
  /**
@@ -248,7 +294,7 @@ class Add_To_Any implements Cookiebot_Addons_Interface {
248
  * @since 1.8.0
249
  */
250
  public function get_extra_information() {
251
- return '<p>' . __( 'Blocks embedded videos from Youtube, Twitter, Vimeo and Facebook.', 'cookiebot-addons' ) . '</p>';
252
  }
253
 
254
  /**
2
 
3
  namespace cookiebot_addons\controller\addons\add_to_any;
4
 
5
+ use DOMDocument;
6
+ use DOMXPath;
7
+ use DOMElement;
8
  use cookiebot_addons\controller\addons\Cookiebot_Addons_Interface;
9
  use cookiebot_addons\lib\Cookie_Consent_Interface;
10
  use cookiebot_addons\lib\Settings_Service_Interface;
90
  if ( has_action( 'wp_enqueue_scripts', 'A2A_SHARE_SAVE_enqueue_script' ) ) {
91
  $this->script_loader_tag->add_tag( 'addtoany', $this->get_cookie_types() );
92
  }
93
+
94
+ add_filter( 'the_content', array(
95
+ $this,
96
+ 'cookiebot_addon_add_to_any_content',
97
+ ), 1000 ); //Ensure it is executed as the last filter
98
+
99
+ add_filter( 'the_excerpt', array(
100
+ $this,
101
+ 'cookiebot_addon_add_to_any_content',
102
+ ), 1000 ); //Ensure it is executed as the last filter
103
+ }
104
+
105
+ /**
106
+ * Display a placeholder on elements with "addtoany_share_save_container" class name.
107
+ *
108
+ * @param string $content
109
+ *
110
+ * @return string
111
+ */
112
+ public function cookiebot_addon_add_to_any_content( $content ) {
113
+ if ( ! class_exists( 'DOMDocument' ) || ! class_exists( 'DOMXPath' ) || ! class_exists( 'DOMElement' ) ) {
114
+ return $content;
115
+ }
116
+
117
+ if ( $this->has_placeholder() && $this->is_placeholder_enabled() ) {
118
+ $dom = new DOMDocument();
119
+ $dom->loadHTML( $content );
120
+ $finder = new DOMXPath( $dom );
121
+ $nodes = $finder->query( "//*[contains(@class, 'addtoany_share_save_container')]" );
122
+
123
+ $placeholder = $this->get_placeholder();
124
+ $placeholder_element = $dom->createDocumentFragment();
125
+ $placeholder_element->appendXML( '<div class="' . cookiebot_addons_cookieconsent_optout( $this->get_cookie_types() ) . '">' . $placeholder . '</div>' );
126
+
127
+ foreach ( $nodes as $node ) {
128
+ /* @var DOMElement $node */
129
+ $node->appendChild( $placeholder_element );
130
+ }
131
+
132
+ $content = $dom->saveHTML();
133
+ }
134
+
135
+ return $content;
136
  }
137
 
138
  /**
294
  * @since 1.8.0
295
  */
296
  public function get_extra_information() {
297
+ return '<p>' . esc_html__( 'Blocks embedded videos from Youtube, Twitter, Vimeo and Facebook.', 'cookiebot-addons' ) . '</p>';
298
  }
299
 
300
  /**
addons/controller/addons/custom-facebook-feed-old/custom-facebook-feed-old.php ADDED
@@ -0,0 +1,347 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\controller\addons\custom_facebook_feed_old;
4
+
5
+ use cookiebot_addons\controller\addons\Cookiebot_Addons_Interface;
6
+ use cookiebot_addons\lib\buffer\Buffer_Output_Interface;
7
+ use cookiebot_addons\lib\script_loader_tag\Script_Loader_Tag_Interface;
8
+ use cookiebot_addons\lib\Cookie_Consent_Interface;
9
+ use cookiebot_addons\lib\Settings_Service_Interface;
10
+
11
+ class Custom_Facebook_Feed_Old implements Cookiebot_Addons_Interface {
12
+
13
+ /**
14
+ * @var Settings_Service_Interface
15
+ *
16
+ * @since 1.3.0
17
+ */
18
+ protected $settings;
19
+
20
+ /**
21
+ * @var Script_Loader_Tag_Interface
22
+ *
23
+ * @since 1.3.0
24
+ */
25
+ protected $script_loader_tag;
26
+
27
+ /**
28
+ * @var Cookie_Consent_Interface
29
+ *
30
+ * @since 1.3.0
31
+ */
32
+ public $cookie_consent;
33
+
34
+ /**
35
+ * @var Buffer_Output_Interface
36
+ *
37
+ * @since 1.3.0
38
+ */
39
+ protected $buffer_output;
40
+
41
+ /**
42
+ * Jetpack constructor.
43
+ *
44
+ * @param $settings Settings_Service_Interface
45
+ * @param $script_loader_tag Script_Loader_Tag_Interface
46
+ * @param $cookie_consent Cookie_Consent_Interface
47
+ * @param $buffer_output Buffer_Output_Interface
48
+ *
49
+ * @since 1.2.0
50
+ */
51
+ public function __construct( Settings_Service_Interface $settings, Script_Loader_Tag_Interface $script_loader_tag, Cookie_Consent_Interface $cookie_consent, Buffer_Output_Interface $buffer_output ) {
52
+ $this->settings = $settings;
53
+ $this->script_loader_tag = $script_loader_tag;
54
+ $this->cookie_consent = $cookie_consent;
55
+ $this->buffer_output = $buffer_output;
56
+ }
57
+
58
+ /**
59
+ * Loads addon configuration
60
+ *
61
+ * @since 1.3.0
62
+ */
63
+ public function load_configuration() {
64
+ /**
65
+ * We add the action after wp_loaded and replace the original GA Google
66
+ * Analytics action with our own adjusted version.
67
+ */
68
+ add_action( 'wp_loaded', array( $this, 'cookiebot_addon_custom_facebook_feed' ), 5 );
69
+ }
70
+
71
+ /**
72
+ * Manipulate the scripts if they are loaded.
73
+ *
74
+ * @since 1.1.0
75
+ */
76
+ public function cookiebot_addon_custom_facebook_feed() {
77
+
78
+ if ( has_action( 'wp_footer', 'cff_js' ) ) {
79
+ /**
80
+ * Consent not given - no cache
81
+ */
82
+ $this->buffer_output->add_tag( 'wp_footer', 10, array( 'cfflinkhashtags' => $this->get_cookie_types() ), false );
83
+ }
84
+
85
+ // External js, so manipulate attributes
86
+ if ( has_action( 'wp_enqueue_scripts', 'cff_scripts_method' ) ) {
87
+ /**
88
+ * Consent not given - no cache
89
+ */
90
+ $this->script_loader_tag->add_tag( 'cffscripts', $this->get_cookie_types(), false );
91
+ }
92
+ }
93
+
94
+ /**
95
+ * Return addon/plugin name
96
+ *
97
+ * @return string
98
+ *
99
+ * @since 1.3.0
100
+ */
101
+ public function get_addon_name() {
102
+ return 'Custom Facebook Feed (<= 2.17.1)';
103
+ }
104
+
105
+ /**
106
+ * Option name in the database
107
+ *
108
+ * @return string
109
+ *
110
+ * @since 1.3.0
111
+ */
112
+ public function get_option_name() {
113
+ return 'custom_facebook_feed';
114
+ }
115
+
116
+ /**
117
+ * Plugin file name
118
+ *
119
+ * @return string
120
+ *
121
+ * @since 1.3.0
122
+ */
123
+ public function get_plugin_file() {
124
+ return 'custom-facebook-feed/custom-facebook-feed.php';
125
+ }
126
+
127
+ /**
128
+ * Returns checked cookie types
129
+ * @return mixed
130
+ *
131
+ * @since 1.3.0
132
+ */
133
+ public function get_cookie_types() {
134
+ return $this->settings->get_cookie_types( $this->get_option_name(), $this->get_default_cookie_types() );
135
+ }
136
+
137
+ /**
138
+ * Returns default cookie types
139
+ * @return array
140
+ *
141
+ * @since 1.5.0
142
+ */
143
+ public function get_default_cookie_types() {
144
+ return array( 'marketing' );
145
+ }
146
+
147
+ /**
148
+ * Check if plugin is activated and checked in the backend
149
+ *
150
+ * @since 1.3.0
151
+ */
152
+ public function is_addon_enabled() {
153
+ return $this->settings->is_addon_enabled( $this->get_option_name() );
154
+ }
155
+
156
+ /**
157
+ * Checks if addon is installed
158
+ *
159
+ * @since 1.3.0
160
+ */
161
+ public function is_addon_installed() {
162
+ $installed = $this->settings->is_addon_installed( $this->get_plugin_file() );
163
+
164
+ if ( $installed && version_compare( $this->get_addon_version(), '2.17.1', '>' ) ) {
165
+ $installed = false;
166
+ }
167
+
168
+ return $installed;
169
+ }
170
+
171
+ /**
172
+ * Checks if addon is activated
173
+ *
174
+ * @since 1.3.0
175
+ */
176
+ public function is_addon_activated() {
177
+ return $this->settings->is_addon_activated( $this->get_plugin_file() );
178
+ }
179
+
180
+ /**
181
+ * Retrieves current installed version of the addon
182
+ *
183
+ * @return bool
184
+ *
185
+ * @since 2.2.1
186
+ */
187
+ public function get_addon_version() {
188
+ return $this->settings->get_addon_version( $this->get_plugin_file() );
189
+ }
190
+
191
+ /**
192
+ * Default placeholder content
193
+ *
194
+ * @return string
195
+ *
196
+ * @since 1.8.0
197
+ */
198
+ public function get_default_placeholder() {
199
+ return 'Please accept [renew_consent]%cookie_types[/renew_consent] cookies to watch this video.';
200
+ }
201
+
202
+ /**
203
+ * Get placeholder content
204
+ *
205
+ * This function will check following features:
206
+ * - Current language
207
+ *
208
+ * @param $src
209
+ *
210
+ * @return bool|mixed
211
+ *
212
+ * @since 1.8.0
213
+ */
214
+ public function get_placeholder( $src = '' ) {
215
+ return $this->settings->get_placeholder( $this->get_option_name(), $this->get_default_placeholder(), cookiebot_addons_output_cookie_types( $this->get_cookie_types() ), $src );
216
+ }
217
+
218
+ /**
219
+ * Checks if it does have custom placeholder content
220
+ *
221
+ * @return mixed
222
+ *
223
+ * @since 1.8.0
224
+ */
225
+ public function has_placeholder() {
226
+ return $this->settings->has_placeholder( $this->get_option_name() );
227
+ }
228
+
229
+ /**
230
+ * returns all placeholder contents
231
+ *
232
+ * @return mixed
233
+ *
234
+ * @since 1.8.0
235
+ */
236
+ public function get_placeholders() {
237
+ return $this->settings->get_placeholders( $this->get_option_name() );
238
+ }
239
+
240
+ /**
241
+ * Return true if the placeholder is enabled
242
+ *
243
+ * @return mixed
244
+ *
245
+ * @since 1.8.0
246
+ */
247
+ public function is_placeholder_enabled() {
248
+ return $this->settings->is_placeholder_enabled( $this->get_option_name() );
249
+ }
250
+
251
+ /**
252
+ * Adds extra information under the label
253
+ *
254
+ * @return string
255
+ *
256
+ * @since 1.8.0
257
+ */
258
+ public function get_extra_information() {
259
+ return false;
260
+ }
261
+
262
+ /**
263
+ * Returns the url of WordPress SVN repository or another link where we can verify the plugin file.
264
+ *
265
+ * @return string
266
+ *
267
+ * @since 1.8.0
268
+ */
269
+ public function get_svn_url() {
270
+ return 'http://plugins.svn.wordpress.org/custom-facebook-feed/tags/2.17.1/custom-facebook-feed.php';
271
+ }
272
+
273
+ /**
274
+ * Placeholder helper overlay in the settings page.
275
+ *
276
+ * @return string
277
+ *
278
+ * @since 1.8.0
279
+ */
280
+ public function get_placeholder_helper() {
281
+ return '<p>Merge tags you can use in the placeholder text:</p><ul><li>%cookie_types - Lists required cookie types</li><li>[renew_consent]text[/renew_consent] - link to display cookie settings in frontend</li></ul>';
282
+ }
283
+
284
+ /**
285
+ * Returns parent class or false
286
+ *
287
+ * @return string|bool
288
+ *
289
+ * @since 2.1.3
290
+ */
291
+ public function get_parent_class() {
292
+ return get_parent_class( $this );
293
+ }
294
+
295
+ /**
296
+ * Action after enabling the addon on the settings page
297
+ *
298
+ * @since 2.2.0
299
+ */
300
+ public function post_hook_after_enabling() {
301
+ //do nothing
302
+ }
303
+
304
+ /**
305
+ * Cookiebot plugin is deactivated
306
+ *
307
+ * @since 2.2.0
308
+ */
309
+ public function plugin_deactivated() {
310
+ //do nothing
311
+ }
312
+
313
+ /**
314
+ * @return mixed
315
+ *
316
+ * @since 2.4.5
317
+ */
318
+ public function extra_available_addon_option() {
319
+ //do nothing
320
+ }
321
+
322
+ /**
323
+ * Returns boolean to enable/disable plugin by default
324
+ *
325
+ * @return bool
326
+ *
327
+ * @since 3.6.3
328
+ */
329
+ public function enable_by_default() {
330
+ return false;
331
+ }
332
+
333
+ /**
334
+ * Sets default settings for this addon
335
+ *
336
+ * @return array
337
+ *
338
+ * @since 3.6.3
339
+ */
340
+ public function get_default_enable_setting() {
341
+ return array(
342
+ 'enabled' => 1,
343
+ 'cookie_type' => $this->get_default_cookie_types(),
344
+ 'placeholder' => $this->get_default_placeholder(),
345
+ );
346
+ }
347
+ }
addons/controller/addons/custom-facebook-feed/custom-facebook-feed.php CHANGED
@@ -3,93 +3,13 @@
3
  namespace cookiebot_addons\controller\addons\custom_facebook_feed;
4
 
5
  use cookiebot_addons\controller\addons\Cookiebot_Addons_Interface;
 
6
  use cookiebot_addons\lib\buffer\Buffer_Output_Interface;
7
  use cookiebot_addons\lib\script_loader_tag\Script_Loader_Tag_Interface;
8
  use cookiebot_addons\lib\Cookie_Consent_Interface;
9
  use cookiebot_addons\lib\Settings_Service_Interface;
10
 
11
- class Custom_Facebook_Feed implements Cookiebot_Addons_Interface {
12
-
13
- /**
14
- * @var Settings_Service_Interface
15
- *
16
- * @since 1.3.0
17
- */
18
- protected $settings;
19
-
20
- /**
21
- * @var Script_Loader_Tag_Interface
22
- *
23
- * @since 1.3.0
24
- */
25
- protected $script_loader_tag;
26
-
27
- /**
28
- * @var Cookie_Consent_Interface
29
- *
30
- * @since 1.3.0
31
- */
32
- public $cookie_consent;
33
-
34
- /**
35
- * @var Buffer_Output_Interface
36
- *
37
- * @since 1.3.0
38
- */
39
- protected $buffer_output;
40
-
41
- /**
42
- * Jetpack constructor.
43
- *
44
- * @param $settings Settings_Service_Interface
45
- * @param $script_loader_tag Script_Loader_Tag_Interface
46
- * @param $cookie_consent Cookie_Consent_Interface
47
- * @param $buffer_output Buffer_Output_Interface
48
- *
49
- * @since 1.2.0
50
- */
51
- public function __construct( Settings_Service_Interface $settings, Script_Loader_Tag_Interface $script_loader_tag, Cookie_Consent_Interface $cookie_consent, Buffer_Output_Interface $buffer_output ) {
52
- $this->settings = $settings;
53
- $this->script_loader_tag = $script_loader_tag;
54
- $this->cookie_consent = $cookie_consent;
55
- $this->buffer_output = $buffer_output;
56
- }
57
-
58
- /**
59
- * Loads addon configuration
60
- *
61
- * @since 1.3.0
62
- */
63
- public function load_configuration() {
64
- /**
65
- * We add the action after wp_loaded and replace the original GA Google
66
- * Analytics action with our own adjusted version.
67
- */
68
- add_action( 'wp_loaded', array( $this, 'cookiebot_addon_custom_facebook_feed' ), 5 );
69
- }
70
-
71
- /**
72
- * Manipulate the scripts if they are loaded.
73
- *
74
- * @since 1.1.0
75
- */
76
- public function cookiebot_addon_custom_facebook_feed() {
77
-
78
- if ( has_action( 'wp_footer', 'cff_js' ) ) {
79
- /**
80
- * Consent not given - no cache
81
- */
82
- $this->buffer_output->add_tag( 'wp_footer', 10, array( 'cfflinkhashtags' => $this->get_cookie_types() ), false );
83
- }
84
-
85
- // External js, so manipulate attributes
86
- if ( has_action( 'wp_enqueue_scripts', 'cff_scripts_method' ) ) {
87
- /**
88
- * Consent not given - no cache
89
- */
90
- $this->script_loader_tag->add_tag( 'cffscripts', $this->get_cookie_types(), false );
91
- }
92
- }
93
 
94
  /**
95
  * Return addon/plugin name
@@ -102,155 +22,19 @@ class Custom_Facebook_Feed implements Cookiebot_Addons_Interface {
102
  return 'Custom Facebook Feed';
103
  }
104
 
105
- /**
106
- * Option name in the database
107
- *
108
- * @return string
109
- *
110
- * @since 1.3.0
111
- */
112
- public function get_option_name() {
113
- return 'custom_facebook_feed';
114
- }
115
-
116
- /**
117
- * Plugin file name
118
- *
119
- * @return string
120
- *
121
- * @since 1.3.0
122
- */
123
- public function get_plugin_file() {
124
- return 'custom-facebook-feed/custom-facebook-feed.php';
125
- }
126
-
127
- /**
128
- * Returns checked cookie types
129
- * @return mixed
130
- *
131
- * @since 1.3.0
132
- */
133
- public function get_cookie_types() {
134
- return $this->settings->get_cookie_types( $this->get_option_name(), $this->get_default_cookie_types() );
135
- }
136
-
137
- /**
138
- * Returns default cookie types
139
- * @return array
140
- *
141
- * @since 1.5.0
142
- */
143
- public function get_default_cookie_types() {
144
- return array( 'marketing' );
145
- }
146
-
147
- /**
148
- * Check if plugin is activated and checked in the backend
149
- *
150
- * @since 1.3.0
151
- */
152
- public function is_addon_enabled() {
153
- return $this->settings->is_addon_enabled( $this->get_option_name() );
154
- }
155
-
156
  /**
157
  * Checks if addon is installed
158
  *
159
  * @since 1.3.0
160
  */
161
  public function is_addon_installed() {
162
- return $this->settings->is_addon_installed( $this->get_plugin_file() );
163
- }
164
 
165
- /**
166
- * Checks if addon is activated
167
- *
168
- * @since 1.3.0
169
- */
170
- public function is_addon_activated() {
171
- return $this->settings->is_addon_activated( $this->get_plugin_file() );
172
- }
173
 
174
- /**
175
- * Retrieves current installed version of the addon
176
- *
177
- * @return bool
178
- *
179
- * @since 2.2.1
180
- */
181
- public function get_addon_version() {
182
- return $this->settings->get_addon_version( $this->get_plugin_file() );
183
- }
184
-
185
- /**
186
- * Default placeholder content
187
- *
188
- * @return string
189
- *
190
- * @since 1.8.0
191
- */
192
- public function get_default_placeholder() {
193
- return 'Please accept [renew_consent]%cookie_types[/renew_consent] cookies to watch this video.';
194
- }
195
-
196
- /**
197
- * Get placeholder content
198
- *
199
- * This function will check following features:
200
- * - Current language
201
- *
202
- * @param $src
203
- *
204
- * @return bool|mixed
205
- *
206
- * @since 1.8.0
207
- */
208
- public function get_placeholder( $src = '' ) {
209
- return $this->settings->get_placeholder( $this->get_option_name(), $this->get_default_placeholder(), cookiebot_addons_output_cookie_types( $this->get_cookie_types() ), $src );
210
- }
211
-
212
- /**
213
- * Checks if it does have custom placeholder content
214
- *
215
- * @return mixed
216
- *
217
- * @since 1.8.0
218
- */
219
- public function has_placeholder() {
220
- return $this->settings->has_placeholder( $this->get_option_name() );
221
- }
222
-
223
- /**
224
- * returns all placeholder contents
225
- *
226
- * @return mixed
227
- *
228
- * @since 1.8.0
229
- */
230
- public function get_placeholders() {
231
- return $this->settings->get_placeholders( $this->get_option_name() );
232
- }
233
-
234
- /**
235
- * Return true if the placeholder is enabled
236
- *
237
- * @return mixed
238
- *
239
- * @since 1.8.0
240
- */
241
- public function is_placeholder_enabled() {
242
- return $this->settings->is_placeholder_enabled( $this->get_option_name() );
243
- }
244
-
245
- /**
246
- * Adds extra information under the label
247
- *
248
- * @return string
249
- *
250
- * @since 1.8.0
251
- */
252
- public function get_extra_information() {
253
- return false;
254
  }
255
 
256
  /**
@@ -264,78 +48,31 @@ class Custom_Facebook_Feed implements Cookiebot_Addons_Interface {
264
  return 'http://plugins.svn.wordpress.org/custom-facebook-feed/trunk/custom-facebook-feed.php';
265
  }
266
 
267
- /**
268
- * Placeholder helper overlay in the settings page.
269
- *
270
- * @return string
271
- *
272
- * @since 1.8.0
273
- */
274
- public function get_placeholder_helper() {
275
- return '<p>Merge tags you can use in the placeholder text:</p><ul><li>%cookie_types - Lists required cookie types</li><li>[renew_consent]text[/renew_consent] - link to display cookie settings in frontend</li></ul>';
276
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
277
 
278
- /**
279
- * Returns parent class or false
280
- *
281
- * @return string|bool
282
- *
283
- * @since 2.1.3
284
- */
285
- public function get_parent_class() {
286
- return get_parent_class( $this );
287
- }
288
-
289
- /**
290
- * Action after enabling the addon on the settings page
291
- *
292
- * @since 2.2.0
293
- */
294
- public function post_hook_after_enabling() {
295
- //do nothing
296
- }
297
-
298
- /**
299
- * Cookiebot plugin is deactivated
300
- *
301
- * @since 2.2.0
302
- */
303
- public function plugin_deactivated() {
304
- //do nothing
305
- }
306
-
307
- /**
308
- * @return mixed
309
- *
310
- * @since 2.4.5
311
- */
312
- public function extra_available_addon_option() {
313
- //do nothing
314
- }
315
-
316
- /**
317
- * Returns boolean to enable/disable plugin by default
318
- *
319
- * @return bool
320
- *
321
- * @since 3.6.3
322
- */
323
- public function enable_by_default() {
324
- return false;
325
- }
326
-
327
- /**
328
- * Sets default settings for this addon
329
- *
330
- * @return array
331
- *
332
- * @since 3.6.3
333
- */
334
- public function get_default_enable_setting() {
335
- return array(
336
- 'enabled' => 1,
337
- 'cookie_type' => $this->get_default_cookie_types(),
338
- 'placeholder' => $this->get_default_placeholder(),
339
- );
340
- }
341
  }
3
  namespace cookiebot_addons\controller\addons\custom_facebook_feed;
4
 
5
  use cookiebot_addons\controller\addons\Cookiebot_Addons_Interface;
6
+ use cookiebot_addons\controller\addons\custom_facebook_feed_old\Custom_Facebook_Feed_Old;
7
  use cookiebot_addons\lib\buffer\Buffer_Output_Interface;
8
  use cookiebot_addons\lib\script_loader_tag\Script_Loader_Tag_Interface;
9
  use cookiebot_addons\lib\Cookie_Consent_Interface;
10
  use cookiebot_addons\lib\Settings_Service_Interface;
11
 
12
+ class Custom_Facebook_Feed extends Custom_Facebook_Feed_Old {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
 
14
  /**
15
  * Return addon/plugin name
22
  return 'Custom Facebook Feed';
23
  }
24
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  /**
26
  * Checks if addon is installed
27
  *
28
  * @since 1.3.0
29
  */
30
  public function is_addon_installed() {
31
+ $installed = $this->settings->is_addon_installed( $this->get_plugin_file() );
 
32
 
33
+ if ( $installed && version_compare( $this->get_addon_version(), '2.17.1', '<=' ) ) {
34
+ $installed = false;
35
+ }
 
 
 
 
 
36
 
37
+ return $installed;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  }
39
 
40
  /**
48
  return 'http://plugins.svn.wordpress.org/custom-facebook-feed/trunk/custom-facebook-feed.php';
49
  }
50
 
51
+ /**
52
+ * Manipulate the scripts if they are loaded.
53
+ *
54
+ * @since 1.1.0
55
+ */
56
+ public function cookiebot_addon_custom_facebook_feed() {
57
+
58
+ if(class_exists("\CustomFacebookFeed\Custom_Facebook_Feed")) {
59
+ $instance = \CustomFacebookFeed\Custom_Facebook_Feed::instance();
60
+
61
+ if ( has_action( 'wp_footer', array($instance, 'cff_js') ) ) {
62
+ /**
63
+ * Consent not given - no cache
64
+ */
65
+ $this->buffer_output->add_tag( 'wp_footer', 10, array( 'cfflinkhashtags' => $this->get_cookie_types() ), false );
66
+ }
67
+
68
+ // External js, so manipulate attributes
69
+ if ( has_action( 'wp_enqueue_scripts', array($instance, 'enqueue_scripts_assets') ) ) {
70
+ /**
71
+ * Consent not given - no cache
72
+ */
73
+ $this->script_loader_tag->add_tag( 'cffscripts', $this->get_cookie_types(), false );
74
+ }
75
+ }
76
+ }
77
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  }
addons/controller/addons/embed-autocorrect/embed-autocorrect.php CHANGED
@@ -129,7 +129,9 @@ class Embed_Autocorrect implements Cookiebot_Addons_Interface {
129
  $this->get_cookie_types() ); ?>) {
130
  jQuery( '.wp-video-shortcode__disabled' ).addClass( 'wp-video-shortcode' ).removeClass( 'wp-video-shortcode__disabled' );
131
  jQuery( '.wp-audio-shortcode__disabled' ).addClass( 'wp-audio-shortcode' ).removeClass( 'wp-audio-shortcode__disabled' );
132
- window.wp.mediaelement.initialize();
 
 
133
  }
134
  }, false );
135
  </script><?php
@@ -257,7 +259,7 @@ class Embed_Autocorrect implements Cookiebot_Addons_Interface {
257
  }
258
 
259
  unset( $matches );
260
- preg_match_all( '/<script.*(instagram|issuu|imgur|polldaddy|tumblr)+.*<\/script>/mi', $content, $matches );
261
  foreach ( $matches[0] as $x => $match ) {
262
  //Replace - and add cookie consent notice.
263
  $adjusted = str_replace( ' src=',
@@ -282,7 +284,6 @@ class Embed_Autocorrect implements Cookiebot_Addons_Interface {
282
  }
283
  unset( $matches );
284
 
285
-
286
  return $content;
287
  }
288
 
@@ -354,7 +355,7 @@ class Embed_Autocorrect implements Cookiebot_Addons_Interface {
354
  * @return string
355
  */
356
  public function generate_placeholder_with_src( $src = '' ) {
357
- $cookieContentNotice = '<div class="cookieconsent-optout-' . cookiebot_addons_get_one_cookie_type( $this->get_cookie_types() ) . '">';
358
  $cookieContentNotice .= $this->get_placeholder( $src );
359
  $cookieContentNotice .= '</div>';
360
 
@@ -521,7 +522,7 @@ class Embed_Autocorrect implements Cookiebot_Addons_Interface {
521
  * @since 1.8.0
522
  */
523
  public function get_extra_information() {
524
- return '<p>' . __( 'Blocks embedded videos from Youtube, Twitter, Vimeo and Facebook.',
525
  'cookiebot-addons' ) . '</p>';
526
  }
527
 
@@ -598,7 +599,7 @@ class Embed_Autocorrect implements Cookiebot_Addons_Interface {
598
  */
599
  private function get_default_regex() {
600
  return apply_filters( 'cookiebot_embed_default_regex',
601
- '/<iframe[^>]* src=("|\').*(facebook\.com|youtu\.be|youtube\.com|youtube-nocookie\.com|player\.vimeo\.com).*[^>].*>.*?<\/iframe>/mi' );
602
  }
603
 
604
  /**
@@ -620,13 +621,13 @@ class Embed_Autocorrect implements Cookiebot_Addons_Interface {
620
  public function extra_available_addon_option() {
621
  ?>
622
  <div class="show_advanced_options">
623
- <button class="button button-secondary"><?php _e( 'Show advanced options', 'cookiebot-addons' ); ?></button>
624
  <span class="help-tip"
625
- title="<?php echo __( 'This is for more advanced users.', 'cookiebot-addons' ); ?>"></span>
626
  </div>
627
  <div class="advanced_options">
628
 
629
- <label for="embed_regex"><?php _e( 'Regex:', 'cookiebot-addons' ); ?></label>
630
  <textarea
631
  id="embed_regex"
632
  cols="80"
@@ -636,14 +637,14 @@ class Embed_Autocorrect implements Cookiebot_Addons_Interface {
636
  ><?php echo esc_html( $this->get_regex() ); ?></textarea>
637
 
638
  <?php if ( $this->is_regex_default() ) : ?>
639
- <button id="edit_embed_regex" class="button"><?php _e( 'Edit regex', 'cookiebot-addons' ); ?></button>
640
  <?php endif; ?>
641
 
642
  <button
643
  id="btn_default_embed_regex"
644
  class="button<?php echo ( $this->is_regex_default() ) ? ' hidden' : ''; ?>"
645
  type="button"
646
- value="Reset to default regex"><?php _e( 'Reset to default regex', 'cookiebot-addons' ); ?></button>
647
  <input
648
  type="hidden"
649
  name="default_embed_regex"
129
  $this->get_cookie_types() ); ?>) {
130
  jQuery( '.wp-video-shortcode__disabled' ).addClass( 'wp-video-shortcode' ).removeClass( 'wp-video-shortcode__disabled' );
131
  jQuery( '.wp-audio-shortcode__disabled' ).addClass( 'wp-audio-shortcode' ).removeClass( 'wp-audio-shortcode__disabled' );
132
+ if (window.wp && window.wp.mediaelement && window.wp.mediaelement.initialize) {
133
+ window.wp.mediaelement.initialize();
134
+ }
135
  }
136
  }, false );
137
  </script><?php
259
  }
260
 
261
  unset( $matches );
262
+ preg_match_all( '/<script.*(instagram|twitter|issuu|imgur|redditmedia\.com|tiktok\.com|polldaddy|tumblr)+.*<\/script>/mi', $content, $matches );
263
  foreach ( $matches[0] as $x => $match ) {
264
  //Replace - and add cookie consent notice.
265
  $adjusted = str_replace( ' src=',
284
  }
285
  unset( $matches );
286
 
 
287
  return $content;
288
  }
289
 
355
  * @return string
356
  */
357
  public function generate_placeholder_with_src( $src = '' ) {
358
+ $cookieContentNotice = '<div class="' . cookiebot_addons_cookieconsent_optout( $this->get_cookie_types() ) . '">';
359
  $cookieContentNotice .= $this->get_placeholder( $src );
360
  $cookieContentNotice .= '</div>';
361
 
522
  * @since 1.8.0
523
  */
524
  public function get_extra_information() {
525
+ return '<p>' . esc_html__( 'Blocks embedded videos from Youtube, Twitter, Vimeo and Facebook.',
526
  'cookiebot-addons' ) . '</p>';
527
  }
528
 
599
  */
600
  private function get_default_regex() {
601
  return apply_filters( 'cookiebot_embed_default_regex',
602
+ '/<iframe[^>]* src=("|\').*(facebook\.com|youtu\.be|youtube\.com|youtube-nocookie\.com|player\.vimeo\.com|soundcloud\.com|spotify\.com|speakerdeck\.com|slideshare\.net|screencast\.com|reverbnation\.com|mixcloud\.com|cloudup\.com|animoto\.com|video\.wordpress\.com|embed\.ted\.com|embedly\.com|kickstarter\.com).*[^>].*>.*?<\/iframe>/mi' );
603
  }
604
 
605
  /**
621
  public function extra_available_addon_option() {
622
  ?>
623
  <div class="show_advanced_options">
624
+ <button class="button button-secondary"><?php esc_html_e( 'Show advanced options', 'cookiebot-addons' ); ?></button>
625
  <span class="help-tip"
626
+ title="<?php echo esc_html__( 'This is for more advanced users.', 'cookiebot-addons' ); ?>"></span>
627
  </div>
628
  <div class="advanced_options">
629
 
630
+ <label for="embed_regex"><?php esc_html_e( 'Regex:', 'cookiebot-addons' ); ?></label>
631
  <textarea
632
  id="embed_regex"
633
  cols="80"
637
  ><?php echo esc_html( $this->get_regex() ); ?></textarea>
638
 
639
  <?php if ( $this->is_regex_default() ) : ?>
640
+ <button id="edit_embed_regex" class="button"><?php esc_html_e( 'Edit regex', 'cookiebot-addons' ); ?></button>
641
  <?php endif; ?>
642
 
643
  <button
644
  id="btn_default_embed_regex"
645
  class="button<?php echo ( $this->is_regex_default() ) ? ' hidden' : ''; ?>"
646
  type="button"
647
+ value="Reset to default regex"><?php esc_html_e( 'Reset to default regex', 'cookiebot-addons' ); ?></button>
648
  <input
649
  type="hidden"
650
  name="default_embed_regex"
addons/controller/addons/enfold/enfold.php ADDED
@@ -0,0 +1,326 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\controller\addons\enfold;
4
+
5
+ use cookiebot_addons\controller\addons\Cookiebot_Addons_Interface;
6
+ use cookiebot_addons\lib\Cookie_Consent_Interface;
7
+ use cookiebot_addons\lib\Settings_Service_Interface;
8
+ use cookiebot_addons\lib\script_loader_tag\Script_Loader_Tag_Interface;
9
+ use cookiebot_addons\lib\buffer\Buffer_Output_Interface;
10
+
11
+ class Enfold implements Cookiebot_Addons_Interface {
12
+
13
+ /**
14
+ * @var Settings_Service_Interface
15
+ *
16
+ * @since 1.3.0
17
+ */
18
+ protected $settings;
19
+
20
+ /**
21
+ * @var Script_Loader_Tag_Interface
22
+ *
23
+ * @since 1.3.0
24
+ */
25
+ protected $script_loader_tag;
26
+
27
+ /**
28
+ * @var Cookie_Consent_Interface
29
+ *
30
+ * @since 1.3.0
31
+ */
32
+ public $cookie_consent;
33
+
34
+ /**
35
+ * @var Buffer_Output_Interface
36
+ *
37
+ * @since 1.3.0
38
+ */
39
+ protected $buffer_output;
40
+
41
+ /**
42
+ * Jetpack constructor.
43
+ *
44
+ * @param $settings Settings_Service_Interface
45
+ * @param $script_loader_tag Script_Loader_Tag_Interface
46
+ * @param $cookie_consent Cookie_Consent_Interface
47
+ * @param $buffer_output Buffer_Output_Interface
48
+ *
49
+ * @since 1.3.0
50
+ */
51
+ public function __construct( Settings_Service_Interface $settings, Script_Loader_Tag_Interface $script_loader_tag, Cookie_Consent_Interface $cookie_consent, Buffer_Output_Interface $buffer_output ) {
52
+ $this->settings = $settings;
53
+ $this->script_loader_tag = $script_loader_tag;
54
+ $this->cookie_consent = $cookie_consent;
55
+ $this->buffer_output = $buffer_output;
56
+ }
57
+
58
+ /**
59
+ * Loads addon configuration
60
+ *
61
+ * @since 1.3.0
62
+ */
63
+ public function load_configuration() {
64
+ add_action( 'wp_loaded', array( $this, 'cookiebot_addon_enfold' ), 10 );
65
+ }
66
+
67
+ /**
68
+ * Disable scripts if state not accepted
69
+ *
70
+ * @since 1.3.0
71
+ */
72
+ public function cookiebot_addon_enfold() {
73
+ $this->buffer_output->add_tag( 'wp_footer', 10000, array(
74
+ 'google_analytics_script' => $this->get_cookie_types()
75
+ ) );
76
+ }
77
+
78
+ /**
79
+ * Return addon/plugin name
80
+ *
81
+ * @return string
82
+ *
83
+ * @since 1.3.0
84
+ */
85
+ public function get_addon_name() {
86
+ return 'Enfold';
87
+ }
88
+
89
+ /**
90
+ * Default placeholder content
91
+ *
92
+ * @return string
93
+ *
94
+ * @since 1.8.0
95
+ */
96
+ public function get_default_placeholder() {
97
+ return 'Please accept [renew_consent]%cookie_types[/renew_consent] cookies to enable Google Services.';
98
+ }
99
+
100
+ /**
101
+ * Get placeholder content
102
+ *
103
+ * This function will check following features:
104
+ * - Current language
105
+ *
106
+ * @param $src
107
+ *
108
+ * @return bool|mixed
109
+ *
110
+ * @since 1.8.0
111
+ */
112
+ public function get_placeholder( $src = '' ) {
113
+ return $this->settings->get_placeholder( $this->get_option_name(), $this->get_default_placeholder(), cookiebot_addons_output_cookie_types( $this->get_cookie_types() ), $src );
114
+ }
115
+
116
+ /**
117
+ * Option name in the database
118
+ *
119
+ * @return string
120
+ *
121
+ * @since 1.3.0
122
+ */
123
+ public function get_option_name() {
124
+ return 'enfold';
125
+ }
126
+
127
+ /**
128
+ * Plugin file name
129
+ *
130
+ * @return string
131
+ *
132
+ * @since 1.3.0
133
+ */
134
+ public function get_plugin_file() {
135
+ return '';
136
+ }
137
+
138
+ /**
139
+ * Returns checked cookie types
140
+ * @return mixed
141
+ *
142
+ * @since 1.3.0
143
+ */
144
+ public function get_cookie_types() {
145
+ return $this->settings->get_cookie_types( $this->get_option_name(), $this->get_default_cookie_types() );
146
+ }
147
+
148
+ /**
149
+ * Returns default cookie types
150
+ * @return array
151
+ *
152
+ * @since 1.5.0
153
+ */
154
+ public function get_default_cookie_types() {
155
+ return array( 'marketing', 'statistics' );
156
+ }
157
+
158
+ /**
159
+ * Check if plugin is activated and checked in the backend
160
+ *
161
+ * @since 1.3.0
162
+ */
163
+ public function is_addon_enabled() {
164
+ return $this->settings->is_addon_enabled( $this->get_option_name() );
165
+ }
166
+
167
+ /**
168
+ * Checks if addon is installed
169
+ *
170
+ * @since 1.3.0
171
+ */
172
+ public function is_addon_installed() {
173
+ return $this->settings->is_addon_installed( $this->get_option_name() );
174
+ }
175
+
176
+ /**
177
+ * Checks if addon is activated
178
+ *
179
+ * @since 1.3.0
180
+ */
181
+ public function is_addon_activated() {
182
+ return $this->settings->is_addon_activated( $this->get_option_name() );
183
+ }
184
+
185
+ /**
186
+ * Retrieves current installed version of the addon
187
+ *
188
+ * @return bool
189
+ *
190
+ * @since 2.2.1
191
+ */
192
+ public function get_addon_version() {
193
+ return $this->settings->get_addon_version( $this->get_option_name() );
194
+ }
195
+
196
+ /**
197
+ * Checks if it does have custom placeholder content
198
+ *
199
+ * @return mixed
200
+ *
201
+ * @since 1.8.0
202
+ */
203
+ public function has_placeholder() {
204
+ return $this->settings->has_placeholder( $this->get_option_name() );
205
+ }
206
+
207
+ /**
208
+ * returns all placeholder contents
209
+ *
210
+ * @return mixed
211
+ *
212
+ * @since 1.8.0
213
+ */
214
+ public function get_placeholders() {
215
+ return $this->settings->get_placeholders( $this->get_option_name() );
216
+ }
217
+
218
+ /**
219
+ * Return true if the placeholder is enabled
220
+ *
221
+ * @return mixed
222
+ *
223
+ * @since 1.8.0
224
+ */
225
+ public function is_placeholder_enabled() {
226
+ return $this->settings->is_placeholder_enabled( $this->get_option_name() );
227
+ }
228
+
229
+ /**
230
+ * Adds extra information under the label
231
+ *
232
+ * @return string
233
+ *
234
+ * @since 1.8.0
235
+ */
236
+ public function get_extra_information() {
237
+ return '<p>' . __( 'Blocks cookies created by Enfold theme\'s Google Services.', 'cookiebot-addons' ) . '</p>';
238
+ }
239
+
240
+ /**
241
+ * Returns the url of WordPress SVN repository or another link where we can verify the plugin file.
242
+ *
243
+ * @return string
244
+ *
245
+ * @since 1.8.0
246
+ */
247
+ public function get_svn_url() {
248
+ return ''; // Premium theme doesn't have this
249
+ }
250
+
251
+ /**
252
+ * Placeholder helper overlay in the settings page.
253
+ *
254
+ * @return string
255
+ *
256
+ * @since 1.8.0
257
+ */
258
+ public function get_placeholder_helper() {
259
+ return '<p>Merge tags you can use in the placeholder text:</p><ul><li>%cookie_types - Lists required cookie types</li><li>[renew_consent]text[/renew_consent] - link to display cookie settings in frontend</li></ul>';
260
+ }
261
+
262
+
263
+ /**
264
+ * Returns parent class or false
265
+ *
266
+ * @return string|bool
267
+ *
268
+ * @since 2.1.3
269
+ */
270
+ public function get_parent_class() {
271
+ return get_parent_class( $this );
272
+ }
273
+
274
+ /**
275
+ * Action after enabling the addon on the settings page
276
+ *
277
+ * @since 2.2.0
278
+ */
279
+ public function post_hook_after_enabling() {
280
+ //do nothing
281
+ }
282
+
283
+ /**
284
+ * Cookiebot plugin is deactivated
285
+ *
286
+ * @since 2.2.0
287
+ */
288
+ public function plugin_deactivated() {
289
+ //do nothing
290
+ }
291
+
292
+ /**
293
+ * @return mixed
294
+ *
295
+ * @since 2.4.5
296
+ */
297
+ public function extra_available_addon_option() {
298
+ //do nothing
299
+ }
300
+
301
+ /**
302
+ * Returns boolean to enable/disable plugin by default
303
+ *
304
+ * @return bool
305
+ *
306
+ * @since 3.6.3
307
+ */
308
+ public function enable_by_default() {
309
+ return false;
310
+ }
311
+
312
+ /**
313
+ * Sets default settings for this addon
314
+ *
315
+ * @return array
316
+ *
317
+ * @since 3.6.3
318
+ */
319
+ public function get_default_enable_setting() {
320
+ return array(
321
+ 'enabled' => 1,
322
+ 'cookie_type' => $this->get_default_cookie_types(),
323
+ 'placeholder' => $this->get_default_placeholder(),
324
+ );
325
+ }
326
+ }
addons/controller/addons/enhanced-ecommerce-for-woocommerce-store/enhanced-ecommerce-for-woocommerce-store.php CHANGED
@@ -239,7 +239,7 @@
239
  * @since 1.8.0
240
  */
241
  public function get_extra_information() {
242
- return '<p>' . __( 'Blocks enhanced e-commerce for WooCommerce store', 'cookiebot-addons' ) . '</p>';
243
  }
244
 
245
  /**
239
  * @since 1.8.0
240
  */
241
  public function get_extra_information() {
242
+ return '<p>' . esc_html__( 'Blocks enhanced e-commerce for WooCommerce store', 'cookiebot-addons' ) . '</p>';
243
  }
244
 
245
  /**
addons/controller/addons/gadwp/gadwp.php CHANGED
@@ -54,10 +54,10 @@ class Gadwp implements Cookiebot_Addons_Interface {
54
  Cookie_Consent_Interface $cookie_consent,
55
  Buffer_Output_Interface $buffer_output
56
  ) {
57
- $this->settings = $settings;
58
  $this->script_loader_tag = $script_loader_tag;
59
- $this->cookie_consent = $cookie_consent;
60
- $this->buffer_output = $buffer_output;
61
  }
62
 
63
  /**
@@ -76,7 +76,7 @@ class Gadwp implements Cookiebot_Addons_Interface {
76
  /**
77
  * Manipulate the scripts if they are loaded.
78
  *
79
- * @version 1.3.0
80
  * @since 1.1.0
81
  */
82
  public function cookiebot_addon_ga_google_analytics() {
@@ -107,17 +107,26 @@ class Gadwp implements Cookiebot_Addons_Interface {
107
  'ga-disable-' => $this->get_cookie_types(),
108
  ),
109
  false );
110
-
111
-
112
- /* For new versions of GADWP */
113
- $this->script_loader_tag->add_tag( 'exactmetrics-frontend-script', $this->get_cookie_types() );
114
- $this->buffer_output->add_tag( 'wp_head',
115
  6,
116
  array(
117
  'GoogleAnalyticsObject' => $this->get_cookie_types(),
 
118
  ),
119
  false );
120
 
 
 
 
 
 
 
 
 
121
  }
122
 
123
  /**
@@ -128,7 +137,7 @@ class Gadwp implements Cookiebot_Addons_Interface {
128
  * @since 1.3.0
129
  */
130
  public function get_addon_name() {
131
- return 'Google Analytics Dashboard for WP (GADWP)';
132
  }
133
 
134
  /**
54
  Cookie_Consent_Interface $cookie_consent,
55
  Buffer_Output_Interface $buffer_output
56
  ) {
57
+ $this->settings = $settings;
58
  $this->script_loader_tag = $script_loader_tag;
59
+ $this->cookie_consent = $cookie_consent;
60
+ $this->buffer_output = $buffer_output;
61
  }
62
 
63
  /**
76
  /**
77
  * Manipulate the scripts if they are loaded.
78
  *
79
+ * @version 3.9.0
80
  * @since 1.1.0
81
  */
82
  public function cookiebot_addon_ga_google_analytics() {
107
  'ga-disable-' => $this->get_cookie_types(),
108
  ),
109
  false );
110
+
111
+
112
+ /* For new versions of GADWP */
113
+ $this->script_loader_tag->add_tag( 'exactmetrics-frontend-script', $this->get_cookie_types() );
114
+ $this->buffer_output->add_tag( 'wp_head',
115
  6,
116
  array(
117
  'GoogleAnalyticsObject' => $this->get_cookie_types(),
118
+ 'googletagmanager' => $this->get_cookie_types()
119
  ),
120
  false );
121
 
122
+
123
+ add_filter('exactmetrics_tracking_analytics_script_attributes', function($atts){
124
+ $atts['type'] = 'text/plain';
125
+ $atts['data-cookieconsent'] = cookiebot_addons_output_cookie_types( $this->get_cookie_types() );
126
+
127
+ return $atts;
128
+ });
129
+
130
  }
131
 
132
  /**
137
  * @since 1.3.0
138
  */
139
  public function get_addon_name() {
140
+ return 'Google Analytics Dashboard for WP by ExactMetrics';
141
  }
142
 
143
  /**
addons/controller/addons/google-analytics-plus/google-analytics-plus.php CHANGED
@@ -235,7 +235,7 @@ class Google_Analytics_Plus implements Cookiebot_Addons_Interface {
235
  * @since 1.8.0
236
  */
237
  public function get_extra_information() {
238
- return '<p>' . __( 'Google Analytics is a simple, easy-to-use tool that helps website owners measure how users interact with website content', 'cookiebot-addons' ) . '</p>';
239
  }
240
 
241
  /**
235
  * @since 1.8.0
236
  */
237
  public function get_extra_information() {
238
+ return '<p>' . esc_html__( 'Google Analytics is a simple, easy-to-use tool that helps website owners measure how users interact with website content', 'cookiebot-addons' ) . '</p>';
239
  }
240
 
241
  /**
addons/controller/addons/google-analytics/google-analytics.php CHANGED
@@ -240,7 +240,7 @@ class Google_Analytics implements Cookiebot_Addons_Interface {
240
  * @since 1.8.0
241
  */
242
  public function get_extra_information() {
243
- return '<p>' . __( 'Google Analytics is used to track how visitor interact with website content.', 'cookiebot-addons' ) . '</p>';
244
  }
245
 
246
  /**
240
  * @since 1.8.0
241
  */
242
  public function get_extra_information() {
243
+ return '<p>' . esc_html__( 'Google Analytics is used to track how visitor interact with website content.', 'cookiebot-addons' ) . '</p>';
244
  }
245
 
246
  /**
addons/controller/addons/google-site-kit/google-site-kit.php CHANGED
@@ -239,7 +239,7 @@ class Google_Site_Kit implements Cookiebot_Addons_Interface {
239
  * @since 1.8.0
240
  */
241
  public function get_extra_information() {
242
- return '<p>' . __( 'Blocks Google Analytics scripts', 'cookiebot-addons' ) . '</p>';
243
  }
244
 
245
  /**
239
  * @since 1.8.0
240
  */
241
  public function get_extra_information() {
242
+ return '<p>' . esc_html__( 'Blocks Google Analytics scripts', 'cookiebot-addons' ) . '</p>';
243
  }
244
 
245
  /**
addons/controller/addons/jetpack/visitor-cookies.php CHANGED
@@ -241,7 +241,7 @@ class Visitor_Cookies implements Jetpack_Widget_Interface {
241
  * Show message to accept preferences consent to save
242
  */
243
  if ( $this->is_widget_placeholder_enabled() ) {
244
- add_action( 'wp_mobile_theme_footer', array( $this, 'view_accept_preferences_consent' ) );
245
  }
246
  }
247
 
@@ -251,7 +251,7 @@ class Visitor_Cookies implements Jetpack_Widget_Interface {
251
  * @since 1.2.0
252
  */
253
  public function view_accept_preferences_consent() {
254
- echo '<div class="cookieconsent-optout-' . cookiebot_addons_get_one_cookie_type( $this->get_widget_cookie_types() ) . '">
255
  ' . $this->get_default_placeholder() . '
256
  </div>';
257
  }
241
  * Show message to accept preferences consent to save
242
  */
243
  if ( $this->is_widget_placeholder_enabled() ) {
244
+ add_action( 'wp_footer', array( $this, 'view_accept_preferences_consent' ) );
245
  }
246
  }
247
 
251
  * @since 1.2.0
252
  */
253
  public function view_accept_preferences_consent() {
254
+ echo '<div class="' . cookiebot_addons_cookieconsent_optout( $this->get_widget_cookie_types() ) . '">
255
  ' . $this->get_default_placeholder() . '
256
  </div>';
257
  }
addons/controller/addons/jetpack/widget/facebook-widget.php CHANGED
@@ -215,7 +215,7 @@ class Facebook_Widget {
215
  public function cookie_consent_div( $view, $widget ) {
216
  if ( $widget == 'facebook-likebox' && $view == 'widget_view' ) {
217
  if ( is_array( $this->get_widget_cookie_types() ) && count( $this->get_widget_cookie_types() ) > 0 ) {
218
- echo '<div class="cookieconsent-optout-' . cookiebot_addons_get_one_cookie_type( $this->get_widget_cookie_types() ) . '">
219
  ' . $this->get_widget_placeholder() . '
220
  </div>';
221
  }
@@ -230,7 +230,7 @@ class Facebook_Widget {
230
  * @since 1.8.0
231
  */
232
  public function get_extra_information() {
233
- return '<p>' . __( 'Facebook widget.', 'cookiebot-addons' ) . '</p>';
234
  }
235
 
236
  /**
215
  public function cookie_consent_div( $view, $widget ) {
216
  if ( $widget == 'facebook-likebox' && $view == 'widget_view' ) {
217
  if ( is_array( $this->get_widget_cookie_types() ) && count( $this->get_widget_cookie_types() ) > 0 ) {
218
+ echo '<div class="' . cookiebot_addons_cookieconsent_optout( $this->get_widget_cookie_types() ) . '">
219
  ' . $this->get_widget_placeholder() . '
220
  </div>';
221
  }
230
  * @since 1.8.0
231
  */
232
  public function get_extra_information() {
233
+ return '<p>' . esc_html__( 'Facebook widget.', 'cookiebot-addons' ) . '</p>';
234
  }
235
 
236
  /**
addons/controller/addons/jetpack/widget/goodreads-widget.php CHANGED
@@ -271,7 +271,7 @@ class Goodreads_Widget implements Jetpack_Widget_Interface {
271
  public function cookie_consent_div( $view, $widget ) {
272
  if ( $widget == 'goodreads' && $view == 'widget_view' ) {
273
  if ( is_array( $this->get_widget_cookie_types() ) && count( $this->get_widget_cookie_types() ) > 0 ) {
274
- echo '<div class="cookieconsent-optout-' . cookiebot_addons_get_one_cookie_type( $this->get_widget_cookie_types() ) . '">
275
  ' . $this->get_widget_placeholder() . '
276
  </div>';
277
  }
271
  public function cookie_consent_div( $view, $widget ) {
272
  if ( $widget == 'goodreads' && $view == 'widget_view' ) {
273
  if ( is_array( $this->get_widget_cookie_types() ) && count( $this->get_widget_cookie_types() ) > 0 ) {
274
+ echo '<div class="' . cookiebot_addons_cookieconsent_optout( $this->get_widget_cookie_types() ) . '">
275
  ' . $this->get_widget_placeholder() . '
276
  </div>';
277
  }
addons/controller/addons/jetpack/widget/google-maps-widget.php CHANGED
@@ -268,7 +268,7 @@ class Google_Maps_Widget implements Jetpack_Widget_Interface {
268
  public function cookie_consent_div( $view, $widget ) {
269
  if ( $widget == 'contact_info' && $view == 'widget_view' ) {
270
  if ( is_array( $this->get_widget_cookie_types() ) && count( $this->get_widget_cookie_types() ) > 0 ) {
271
- echo '<div class="cookieconsent-optout-' . cookiebot_addons_get_one_cookie_type( $this->get_widget_cookie_types() ) . '">
272
  ' . $this->get_widget_placeholder() . '
273
  </div>';
274
  }
268
  public function cookie_consent_div( $view, $widget ) {
269
  if ( $widget == 'contact_info' && $view == 'widget_view' ) {
270
  if ( is_array( $this->get_widget_cookie_types() ) && count( $this->get_widget_cookie_types() ) > 0 ) {
271
+ echo '<div class="' . cookiebot_addons_cookieconsent_optout( $this->get_widget_cookie_types() ) . '">
272
  ' . $this->get_widget_placeholder() . '
273
  </div>';
274
  }
addons/controller/addons/jetpack/widget/googleplus-badge-widget.php CHANGED
@@ -208,7 +208,7 @@ class Googleplus_Badge_Widget {
208
  public function display_div_message_to_go_to_consent_settings( $view, $widget ) {
209
  if ( $widget == 'googleplus-badge' && $view == 'widget_view' ) {
210
  if ( is_array( $this->cookie_types ) && count( $this->cookie_types ) > 0 ) {
211
- echo '<div class="cookieconsent-optout-' . cookiebot_addons_get_one_cookie_type( $this->cookie_types ) . '">' . $this->get_widget_placeholder() . '</div>';
212
  }
213
 
214
  }
208
  public function display_div_message_to_go_to_consent_settings( $view, $widget ) {
209
  if ( $widget == 'googleplus-badge' && $view == 'widget_view' ) {
210
  if ( is_array( $this->cookie_types ) && count( $this->cookie_types ) > 0 ) {
211
+ echo '<div class="' . cookiebot_addons_cookieconsent_optout( $this->cookie_types ) . '">' . $this->get_widget_placeholder() . '</div>';
212
  }
213
 
214
  }
addons/controller/addons/jetpack/widget/internet-defense-league-widget.php CHANGED
@@ -203,7 +203,7 @@ class Internet_Defense_league_Widget implements Jetpack_Widget_Interface {
203
  public function cookie_consent_div( $view, $widget ) {
204
  if ( $widget == 'internet_defense_league' && $view == 'widget_view' ) {
205
  if ( is_array( $this->get_widget_cookie_types() ) && count( $this->get_widget_cookie_types() ) > 0 ) {
206
- echo '<div class="cookieconsent-optout-' . cookiebot_addons_get_one_cookie_type( $this->get_widget_cookie_types() ) . '">
207
  ' . $this->get_widget_placeholder() . '
208
  </div>';
209
  }
203
  public function cookie_consent_div( $view, $widget ) {
204
  if ( $widget == 'internet_defense_league' && $view == 'widget_view' ) {
205
  if ( is_array( $this->get_widget_cookie_types() ) && count( $this->get_widget_cookie_types() ) > 0 ) {
206
+ echo '<div class="' . cookiebot_addons_cookieconsent_optout( $this->get_widget_cookie_types() ) . '">
207
  ' . $this->get_widget_placeholder() . '
208
  </div>';
209
  }
addons/controller/addons/jetpack/widget/twitter-timeline-widget.php CHANGED
@@ -204,7 +204,7 @@ class Twitter_Timeline_Widget {
204
  public function display_div_message_to_go_to_consent_settings( $view, $widget ) {
205
  if ( $widget == 'twitter_timeline' && $view == 'widget_view' ) {
206
  if ( is_array( $this->get_widget_cookie_types() ) && count( $this->get_widget_cookie_types() ) > 0 ) {
207
- echo '<div class="cookieconsent-optout-' . cookiebot_addons_get_one_cookie_type( $this->get_widget_cookie_types() ) . '">' . $this->get_widget_placeholder() . '</div>';
208
  }
209
  }
210
  }
204
  public function display_div_message_to_go_to_consent_settings( $view, $widget ) {
205
  if ( $widget == 'twitter_timeline' && $view == 'widget_view' ) {
206
  if ( is_array( $this->get_widget_cookie_types() ) && count( $this->get_widget_cookie_types() ) > 0 ) {
207
+ echo '<div class="' . cookiebot_addons_cookieconsent_optout( $this->get_widget_cookie_types() ) . '">' . $this->get_widget_placeholder() . '</div>';
208
  }
209
  }
210
  }
addons/controller/addons/litespeed-cache/litespeed-cache.php CHANGED
@@ -250,7 +250,7 @@ class Litespeed_Cache implements Cookiebot_Addons_Interface {
250
  * @since 1.8.0
251
  */
252
  public function get_extra_information() {
253
- return '<p>' . __( 'Excludes cookiebot javascript files when the Litespeed Cache deter option is enabled.',
254
  'cookiebot-addons' ) . '</p>';;
255
  }
256
 
250
  * @since 1.8.0
251
  */
252
  public function get_extra_information() {
253
+ return '<p>' . esc_html__( 'Excludes cookiebot javascript files when the Litespeed Cache deter option is enabled.',
254
  'cookiebot-addons' ) . '</p>';;
255
  }
256
 
addons/controller/addons/official-facebook-pixel/official-facebook-pixel.php CHANGED
@@ -126,6 +126,8 @@ class Official_Facebook_Pixel implements Cookiebot_Addons_Interface {
126
  'FacebookPixelPlugin\Integration\FacebookWordpressContactForm7', 'trackServerEvent' );
127
  cookiebot_addons_remove_class_action( 'wpcf7_ajax_json_echo',
128
  'FacebookPixelPlugin\Integration\FacebookWordpressContactForm7', 'injectLeadEvent', 20 );
 
 
129
 
130
  // Formidable Form integration
131
  cookiebot_addons_remove_class_action( 'frm_after_create_entry',
@@ -339,7 +341,7 @@ class Official_Facebook_Pixel implements Cookiebot_Addons_Interface {
339
  * @since 1.8.0
340
  */
341
  public function get_extra_information() {
342
- return '<p>' . __( 'Blocks Official Facebook Pixel scripts', 'cookiebot-addons' ) . '</p>';
343
  }
344
 
345
  /**
126
  'FacebookPixelPlugin\Integration\FacebookWordpressContactForm7', 'trackServerEvent' );
127
  cookiebot_addons_remove_class_action( 'wpcf7_ajax_json_echo',
128
  'FacebookPixelPlugin\Integration\FacebookWordpressContactForm7', 'injectLeadEvent', 20 );
129
+ cookiebot_addons_remove_class_action( 'wpcf7_feedback_response',
130
+ 'FacebookPixelPlugin\Integration\FacebookWordpressContactForm7', 'injectLeadEvent', 20 );
131
 
132
  // Formidable Form integration
133
  cookiebot_addons_remove_class_action( 'frm_after_create_entry',
341
  * @since 1.8.0
342
  */
343
  public function get_extra_information() {
344
+ return '<p>' . esc_html__( 'Blocks Official Facebook Pixel scripts', 'cookiebot-addons' ) . '</p>';
345
  }
346
 
347
  /**
addons/controller/addons/optinmonster/optinmonster.php CHANGED
@@ -232,7 +232,7 @@ class Optinmonster implements Cookiebot_Addons_Interface {
232
  * @since 1.8.0
233
  */
234
  public function get_extra_information() {
235
- return '<p>' . __( 'OptinMonster API plugin to connect your WordPress site to your OptinMonster account.', 'cookiebot-addons' ) . '</p>';
236
  }
237
 
238
  /**
232
  * @since 1.8.0
233
  */
234
  public function get_extra_information() {
235
+ return '<p>' . esc_html__( 'OptinMonster API plugin to connect your WordPress site to your OptinMonster account.', 'cookiebot-addons' ) . '</p>';
236
  }
237
 
238
  /**
addons/controller/addons/pixel-caffeine/pixel-caffeine.php CHANGED
@@ -70,7 +70,7 @@ class Pixel_Caffeine implements Cookiebot_Addons_Interface {
70
  * @since 1.4.0
71
  */
72
  public function cookiebot_addon_pixel_caffeine() {
73
- $this->script_loader_tag->add_tag( 'aepc-pixel-events', array( 'facebook' => $this->get_cookie_types() ) );
74
 
75
  $this->buffer_output->add_tag( 'wp_head', 99, array(
76
  'aepc_pixel' => $this->get_cookie_types(),
70
  * @since 1.4.0
71
  */
72
  public function cookiebot_addon_pixel_caffeine() {
73
+ $this->script_loader_tag->add_tag( 'aepc-pixel-events', $this->get_cookie_types() );
74
 
75
  $this->buffer_output->add_tag( 'wp_head', 99, array(
76
  'aepc_pixel' => $this->get_cookie_types(),
addons/controller/addons/simple-share-buttons-adder/simple-share-buttons-adder.php CHANGED
@@ -232,7 +232,7 @@ class Simple_Share_Buttons_Adder implements Cookiebot_Addons_Interface {
232
  * @since 1.8.0
233
  */
234
  public function get_extra_information() {
235
- return '<p>' . __( 'Blocks Simple Share Buttons Adder.', 'cookiebot-addons' ) . '</p>';
236
  }
237
 
238
  /**
232
  * @since 1.8.0
233
  */
234
  public function get_extra_information() {
235
+ return '<p>' . esc_html__( 'Blocks Simple Share Buttons Adder.', 'cookiebot-addons' ) . '</p>';
236
  }
237
 
238
  /**
addons/controller/addons/wp-rocket/wp-rocket.php CHANGED
@@ -250,7 +250,7 @@ class Wp_Rocket implements Cookiebot_Addons_Interface {
250
  * @since 1.8.0
251
  */
252
  public function get_extra_information() {
253
- return '<p>' . __( 'Excludes cookiebot javascript files when the WP-Rocket deter option is enabled.',
254
  'cookiebot-addons' ) . '</p>';;
255
  }
256
 
250
  * @since 1.8.0
251
  */
252
  public function get_extra_information() {
253
+ return '<p>' . esc_html__( 'Excludes cookiebot javascript files when the WP-Rocket deter option is enabled.',
254
  'cookiebot-addons' ) . '</p>';;
255
  }
256
 
addons/controller/addons/wpforms/wpforms.php CHANGED
@@ -267,9 +267,9 @@ class Wpforms implements Cookiebot_Addons_Interface {
267
  */
268
  public function get_extra_information() {
269
  return '<p>' .
270
- __( 'If the user gives correct consent, IP and Unique User ID will be saved on form submissions, otherwise not.', 'cookiebot-addons' ) .
271
  '<br />' .
272
- __( 'Increases opt-in rate compared to WPForms "GDPR mode".', 'cookiebot-addons' ) .
273
  '</p>';
274
  }
275
 
267
  */
268
  public function get_extra_information() {
269
  return '<p>' .
270
+ esc_html__( 'If the user gives correct consent, IP and Unique User ID will be saved on form submissions, otherwise not.', 'cookiebot-addons' ) .
271
  '<br />' .
272
+ esc_html__( 'Increases opt-in rate compared to WPForms "GDPR mode".', 'cookiebot-addons' ) .
273
  '</p>';
274
  }
275
 
addons/controller/plugin-controller.php CHANGED
@@ -5,6 +5,7 @@ namespace cookiebot_addons\controller;
5
  use cookiebot_addons\controller\addons\Cookiebot_Addons_Interface;
6
  use cookiebot_addons\lib\buffer\Buffer_Output_Interface;
7
  use cookiebot_addons\lib\Settings_Service_Interface;
 
8
 
9
  class Plugin_Controller {
10
 
@@ -26,7 +27,6 @@ class Plugin_Controller {
26
  */
27
  public function __construct( Settings_Service_Interface $settings_service ) {
28
  $this->settings_service = $settings_service;
29
-
30
  $this->load_init_files();
31
  }
32
 
@@ -46,8 +46,8 @@ class Plugin_Controller {
46
  /**
47
  * Load addon configuration if the plugin is activated
48
  *
49
- * @throws \DI\DependencyException
50
- * @throws \DI\NotFoundException
51
  *
52
  * @version 1.3.0
53
  * @since 1.2.0
@@ -95,8 +95,8 @@ class Plugin_Controller {
95
  add_action('admin_notices', function() {
96
  echo '<div class="notice notice-warning">
97
  <p>
98
- <strong>'.__('You enabled Cookiebot auto blocking mode but still using addons').'</strong><br>
99
- '.__('In some occasions this may cause client side errors. If you notice any errors please try to disable Cookiebot addons or contact Cookiebot support.').'
100
  </p>
101
  </div>';
102
  });
5
  use cookiebot_addons\controller\addons\Cookiebot_Addons_Interface;
6
  use cookiebot_addons\lib\buffer\Buffer_Output_Interface;
7
  use cookiebot_addons\lib\Settings_Service_Interface;
8
+ use Cybot\Dependencies\DI;
9
 
10
  class Plugin_Controller {
11
 
27
  */
28
  public function __construct( Settings_Service_Interface $settings_service ) {
29
  $this->settings_service = $settings_service;
 
30
  $this->load_init_files();
31
  }
32
 
46
  /**
47
  * Load addon configuration if the plugin is activated
48
  *
49
+ * @throws DI\DependencyException
50
+ * @throws DI\NotFoundException
51
  *
52
  * @version 1.3.0
53
  * @since 1.2.0
95
  add_action('admin_notices', function() {
96
  echo '<div class="notice notice-warning">
97
  <p>
98
+ <strong>'.esc_html__('You enabled Cookiebot auto blocking mode but still using addons').'</strong><br>
99
+ '.esc_html__('In some occasions this may cause client side errors. If you notice any errors please try to disable Cookiebot addons or contact Cookiebot support.').'
100
  </p>
101
  </div>';
102
  });
addons/cookiebot-addons-init.php CHANGED
@@ -5,8 +5,8 @@ namespace cookiebot_addons;
5
  use cookiebot_addons\config\Settings_Config;
6
  use cookiebot_addons\controller\Plugin_Controller;
7
  use cookiebot_addons\lib\Settings_Service_Interface;
8
- use DI\ContainerBuilder;
9
- use DI;
10
 
11
  if ( ! defined( 'ABSPATH' ) ) {
12
  exit;
@@ -40,14 +40,14 @@ include_once COOKIEBOT_ADDONS_DIR . 'lib/helper.php';
40
  *
41
  * "php-di/php-di": "5.0"
42
  */
43
- include_once COOKIEBOT_ADDONS_DIR . 'lib/ioc/autoload.php';
44
 
45
  class Cookiebot_Addons {
46
 
47
  /**
48
  * IoC Container - is used for dependency injections
49
  *
50
- * @var \DI\Container
51
  *
52
  * @since 1.3.0
53
  */
@@ -83,7 +83,7 @@ class Cookiebot_Addons {
83
  if ( is_null( self::$_instance ) ) {
84
  try {
85
  self::$_instance = new self();
86
- } catch ( \DI\DependencyException $e ) {
87
  echo 'Dependencies are not loaded.';
88
  } catch ( DI\NotFoundException $e ) {
89
  echo 'Dependencies are not found.';
@@ -183,6 +183,9 @@ class Cookiebot_Addons {
183
 
184
  $this->container->set( 'Settings_Service_Interface', DI\object( 'cookiebot_addons\lib\Settings_Service' )
185
  ->constructor( $this->container ) );
 
 
 
186
  }
187
 
188
  /**
@@ -201,9 +204,11 @@ class Cookiebot_Addons {
201
  /**
202
  * Load addon class to the container
203
  */
204
- $this->container->set( $plugin->class, \DI\object( $plugin->class )
205
  ->constructor(
206
- $this->container->get( 'Settings_Service_Interface' ),
 
 
207
  $this->container->get( 'Script_Loader_Tag_Interface' ),
208
  $this->container->get( 'Cookie_Consent_Interface' ),
209
  $this->container->get( 'Buffer_Output_Interface' ) )
5
  use cookiebot_addons\config\Settings_Config;
6
  use cookiebot_addons\controller\Plugin_Controller;
7
  use cookiebot_addons\lib\Settings_Service_Interface;
8
+ use Cybot\Dependencies\DI\ContainerBuilder;
9
+ use Cybot\Dependencies\DI;
10
 
11
  if ( ! defined( 'ABSPATH' ) ) {
12
  exit;
40
  *
41
  * "php-di/php-di": "5.0"
42
  */
43
+ include_once COOKIEBOT_ADDONS_DIR . 'vendor/autoload.php';
44
 
45
  class Cookiebot_Addons {
46
 
47
  /**
48
  * IoC Container - is used for dependency injections
49
  *
50
+ * @var DI\Container
51
  *
52
  * @since 1.3.0
53
  */
83
  if ( is_null( self::$_instance ) ) {
84
  try {
85
  self::$_instance = new self();
86
+ } catch ( DI\DependencyException $e ) {
87
  echo 'Dependencies are not loaded.';
88
  } catch ( DI\NotFoundException $e ) {
89
  echo 'Dependencies are not found.';
183
 
184
  $this->container->set( 'Settings_Service_Interface', DI\object( 'cookiebot_addons\lib\Settings_Service' )
185
  ->constructor( $this->container ) );
186
+
187
+ $this->container->set( 'Theme_Settings_Service_Interface', DI\object( 'cookiebot_addons\lib\Theme_Settings_Service' )
188
+ ->constructor( $this->container ) );
189
  }
190
 
191
  /**
204
  /**
205
  * Load addon class to the container
206
  */
207
+ $this->container->set( $plugin->class, DI\object( $plugin->class )
208
  ->constructor(
209
+ isset( $plugin->is_theme ) && $plugin->is_theme
210
+ ? $this->container->get( 'Theme_Settings_Service_Interface' )
211
+ : $this->container->get( 'Settings_Service_Interface' ),
212
  $this->container->get( 'Script_Loader_Tag_Interface' ),
213
  $this->container->get( 'Cookie_Consent_Interface' ),
214
  $this->container->get( 'Buffer_Output_Interface' ) )
addons/inc/Dependencies/DI/Annotation/Inject.php ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Annotation;
11
+
12
+ use Cybot\Dependencies\DI\Definition\Exception\AnnotationException;
13
+
14
+ /**
15
+ * "Inject" annotation
16
+ *
17
+ * Marks a property or method as an injection point
18
+ *
19
+ * @Annotation
20
+ * @Target({"METHOD","PROPERTY"})
21
+ *
22
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
23
+ */
24
+ final class Inject
25
+ {
26
+ /**
27
+ * Entry name
28
+ * @var string
29
+ */
30
+ private $name;
31
+
32
+ /**
33
+ * Parameters, indexed by the parameter number (index) or name
34
+ *
35
+ * Used if the annotation is set on a method
36
+ * @var array
37
+ */
38
+ private $parameters = [];
39
+
40
+ /**
41
+ * @param array $values
42
+ */
43
+ public function __construct(array $values)
44
+ {
45
+ // Process the parameters as a list AND as a parameter array (we don't know on what the annotation is)
46
+
47
+ // @Inject(name="foo")
48
+ if (isset($values['name']) && is_string($values['name'])) {
49
+ $this->name = $values['name'];
50
+ return;
51
+ }
52
+
53
+ // @Inject
54
+ if (! isset($values['value'])) {
55
+ return;
56
+ }
57
+
58
+ $values = $values['value'];
59
+
60
+ // @Inject("foo")
61
+ if (is_string($values)) {
62
+ $this->name = $values;
63
+ }
64
+
65
+ // @Inject({...}) on a method
66
+ if (is_array($values)) {
67
+ foreach ($values as $key => $value) {
68
+ if (! is_string($value)) {
69
+ throw new AnnotationException(sprintf(
70
+ '@Inject({"param" = "value"}) expects "value" to be a string, %s given.',
71
+ json_encode($value)
72
+ ));
73
+ }
74
+
75
+ $this->parameters[$key] = $value;
76
+ }
77
+ }
78
+ }
79
+
80
+ /**
81
+ * @return string Name of the entry to inject
82
+ */
83
+ public function getName()
84
+ {
85
+ return $this->name;
86
+ }
87
+
88
+ /**
89
+ * @return array Parameters, indexed by the parameter number (index) or name
90
+ */
91
+ public function getParameters()
92
+ {
93
+ return $this->parameters;
94
+ }
95
+ }
addons/inc/Dependencies/DI/Annotation/Injectable.php ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Annotation;
11
+
12
+ use Cybot\Dependencies\DI\Scope;
13
+ use UnexpectedValueException;
14
+
15
+ /**
16
+ * "Injectable" annotation
17
+ *
18
+ * Marks a class as injectable
19
+ *
20
+ * @Annotation
21
+ * @Target("CLASS")
22
+ *
23
+ * @author Domenic Muskulus <domenic@muskulus.eu>
24
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
25
+ */
26
+ final class Injectable
27
+ {
28
+ /**
29
+ * The scope of an class: prototype, singleton
30
+ * @var string|null
31
+ */
32
+ private $scope;
33
+
34
+ /**
35
+ * Should the object be lazy-loaded
36
+ * @var boolean|null
37
+ */
38
+ private $lazy;
39
+
40
+ /**
41
+ * @param array $values
42
+ */
43
+ public function __construct(array $values)
44
+ {
45
+ if (isset($values['scope'])) {
46
+ if ($values['scope'] === 'prototype') {
47
+ $this->scope = Scope::PROTOTYPE;
48
+ } elseif ($values['scope'] === 'singleton') {
49
+ $this->scope = Scope::SINGLETON;
50
+ } else {
51
+ throw new UnexpectedValueException(sprintf("Value '%s' is not a valid scope", $values['scope']));
52
+ }
53
+ }
54
+ if (isset($values['lazy'])) {
55
+ $this->lazy = (boolean) $values['lazy'];
56
+ }
57
+ }
58
+
59
+ /**
60
+ * @return string|null
61
+ */
62
+ public function getScope()
63
+ {
64
+ return $this->scope;
65
+ }
66
+
67
+ /**
68
+ * @return boolean|null
69
+ */
70
+ public function isLazy()
71
+ {
72
+ return $this->lazy;
73
+ }
74
+ }
addons/inc/Dependencies/DI/Container.php ADDED
@@ -0,0 +1,340 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI;
11
+
12
+ use Cybot\Dependencies\DI\Definition\ObjectDefinition;
13
+ use Cybot\Dependencies\DI\Definition\Definition;
14
+ use Cybot\Dependencies\DI\Definition\FactoryDefinition;
15
+ use Cybot\Dependencies\DI\Definition\InstanceDefinition;
16
+ use Cybot\Dependencies\DI\Definition\Resolver\ResolverDispatcher;
17
+ use Cybot\Dependencies\DI\Definition\Source\CachedDefinitionSource;
18
+ use Cybot\Dependencies\DI\Definition\Source\DefinitionSource;
19
+ use Cybot\Dependencies\DI\Definition\Source\MutableDefinitionSource;
20
+ use Cybot\Dependencies\DI\Definition\Helper\DefinitionHelper;
21
+ use Cybot\Dependencies\DI\Definition\Resolver\DefinitionResolver;
22
+ use Cybot\Dependencies\DI\Cybot\Dependencies\Invoker\DefinitionParameterResolver;
23
+ use Cybot\Dependencies\DI\Proxy\ProxyFactory;
24
+ use Exception;
25
+ use Cybot\Dependencies\Interop\Container\ContainerInterface;
26
+ use InvalidArgumentException;
27
+ use Cybot\Dependencies\Invoker\Invoker;
28
+ use Cybot\Dependencies\Invoker\ParameterResolver\AssociativeArrayResolver;
29
+ use Cybot\Dependencies\Invoker\ParameterResolver\Container\TypeHintContainerResolver;
30
+ use Cybot\Dependencies\Invoker\ParameterResolver\NumericArrayResolver;
31
+ use Cybot\Dependencies\Invoker\ParameterResolver\ResolverChain;
32
+
33
+ /**
34
+ * Dependency Injection Container.
35
+ *
36
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
37
+ */
38
+ class Container implements ContainerInterface, FactoryInterface, \Cybot\Dependencies\DI\InvokerInterface
39
+ {
40
+ /**
41
+ * Map of entries with Singleton scope that are already resolved.
42
+ * @var array
43
+ */
44
+ private $singletonEntries = [];
45
+
46
+ /**
47
+ * @var DefinitionSource
48
+ */
49
+ private $definitionSource;
50
+
51
+ /**
52
+ * @var DefinitionResolver
53
+ */
54
+ private $definitionResolver;
55
+
56
+ /**
57
+ * Array of entries being resolved. Used to avoid circular dependencies and infinite loops.
58
+ * @var array
59
+ */
60
+ private $entriesBeingResolved = [];
61
+
62
+ /**
63
+ * @var \Cybot\Dependencies\Invoker\InvokerInterface|null
64
+ */
65
+ private $invoker;
66
+
67
+ /**
68
+ * Container that wraps this container. If none, points to $this.
69
+ *
70
+ * @var ContainerInterface
71
+ */
72
+ private $wrapperContainer;
73
+
74
+ /**
75
+ * Use the ContainerBuilder to ease constructing the Container.
76
+ *
77
+ * @see ContainerBuilder
78
+ *
79
+ * @param DefinitionSource $definitionSource
80
+ * @param ProxyFactory $proxyFactory
81
+ * @param ContainerInterface $wrapperContainer If the container is wrapped by another container.
82
+ */
83
+ public function __construct(
84
+ DefinitionSource $definitionSource,
85
+ ProxyFactory $proxyFactory,
86
+ ContainerInterface $wrapperContainer = null
87
+ ) {
88
+ $this->wrapperContainer = $wrapperContainer ?: $this;
89
+
90
+ $this->definitionSource = $definitionSource;
91
+ $this->definitionResolver = new ResolverDispatcher($this->wrapperContainer, $proxyFactory);
92
+
93
+ // Auto-register the container
94
+ $this->singletonEntries['Cybot\Dependencies\DI\Container'] = $this;
95
+ $this->singletonEntries['Cybot\Dependencies\DI\ContainerInterface'] = $this;
96
+ $this->singletonEntries['Cybot\Dependencies\DI\FactoryInterface'] = $this;
97
+ $this->singletonEntries['Cybot\Dependencies\DI\InvokerInterface'] = $this;
98
+ }
99
+
100
+ /**
101
+ * Returns an entry of the container by its name.
102
+ *
103
+ * @param string $name Entry name or a class name.
104
+ *
105
+ * @throws InvalidArgumentException The name parameter must be of type string.
106
+ * @throws DependencyException Error while resolving the entry.
107
+ * @throws NotFoundException No entry found for the given name.
108
+ * @return mixed
109
+ */
110
+ public function get($name)
111
+ {
112
+ if (! is_string($name)) {
113
+ throw new InvalidArgumentException(sprintf(
114
+ 'The name parameter must be of type string, %s given',
115
+ is_object($name) ? get_class($name) : gettype($name)
116
+ ));
117
+ }
118
+
119
+ // Try to find the entry in the singleton map
120
+ if (array_key_exists($name, $this->singletonEntries)) {
121
+ return $this->singletonEntries[$name];
122
+ }
123
+
124
+ $definition = $this->definitionSource->getDefinition($name);
125
+ if (! $definition) {
126
+ throw new NotFoundException("No entry or class found for '$name'");
127
+ }
128
+
129
+ $value = $this->resolveDefinition($definition);
130
+
131
+ // If the entry is singleton, we store it to always return it without recomputing it
132
+ if ($definition->getScope() === Scope::SINGLETON) {
133
+ $this->singletonEntries[$name] = $value;
134
+ }
135
+
136
+ return $value;
137
+ }
138
+
139
+ /**
140
+ * Build an entry of the container by its name.
141
+ *
142
+ * This method behave like get() except it forces the scope to "prototype",
143
+ * which means the definition of the entry will be re-evaluated each time.
144
+ * For example, if the entry is a class, then a new instance will be created each time.
145
+ *
146
+ * This method makes the container behave like a factory.
147
+ *
148
+ * @param string $name Entry name or a class name.
149
+ * @param array $parameters Optional parameters to use to build the entry. Use this to force specific parameters
150
+ * to specific values. Parameters not defined in this array will be resolved using
151
+ * the container.
152
+ *
153
+ * @throws InvalidArgumentException The name parameter must be of type string.
154
+ * @throws DependencyException Error while resolving the entry.
155
+ * @throws NotFoundException No entry found for the given name.
156
+ * @return mixed
157
+ */
158
+ public function make($name, array $parameters = [])
159
+ {
160
+ if (! is_string($name)) {
161
+ throw new InvalidArgumentException(sprintf(
162
+ 'The name parameter must be of type string, %s given',
163
+ is_object($name) ? get_class($name) : gettype($name)
164
+ ));
165
+ }
166
+
167
+ $definition = $this->definitionSource->getDefinition($name);
168
+ if (! $definition) {
169
+ // Try to find the entry in the singleton map
170
+ if (array_key_exists($name, $this->singletonEntries)) {
171
+ return $this->singletonEntries[$name];
172
+ }
173
+
174
+ throw new NotFoundException("No entry or class found for '$name'");
175
+ }
176
+
177
+ return $this->resolveDefinition($definition, $parameters);
178
+ }
179
+
180
+ /**
181
+ * Test if the container can provide something for the given name.
182
+ *
183
+ * @param string $name Entry name or a class name.
184
+ *
185
+ * @throws InvalidArgumentException The name parameter must be of type string.
186
+ * @return bool
187
+ */
188
+ public function has($name)
189
+ {
190
+ if (! is_string($name)) {
191
+ throw new InvalidArgumentException(sprintf(
192
+ 'The name parameter must be of type string, %s given',
193
+ is_object($name) ? get_class($name) : gettype($name)
194
+ ));
195
+ }
196
+
197
+ if (array_key_exists($name, $this->singletonEntries)) {
198
+ return true;
199
+ }
200
+
201
+ $definition = $this->definitionSource->getDefinition($name);
202
+ if ($definition === null) {
203
+ return false;
204
+ }
205
+
206
+ return $this->definitionResolver->isResolvable($definition);
207
+ }
208
+
209
+ /**
210
+ * Inject all dependencies on an existing instance
211
+ *
212
+ * @param object $instance Object to perform injection upon
213
+ * @throws InvalidArgumentException
214
+ * @throws DependencyException Error while injecting dependencies
215
+ * @return object $instance Returns the same instance
216
+ */
217
+ public function injectOn($instance)
218
+ {
219
+ $objectDefinition = $this->definitionSource->getDefinition(get_class($instance));
220
+ if (! $objectDefinition instanceof ObjectDefinition) {
221
+ return $instance;
222
+ }
223
+
224
+ $definition = new InstanceDefinition($instance, $objectDefinition);
225
+
226
+ $this->definitionResolver->resolve($definition);
227
+
228
+ return $instance;
229
+ }
230
+
231
+ /**
232
+ * Call the given function using the given parameters.
233
+ *
234
+ * Missing parameters will be resolved from the container.
235
+ *
236
+ * @param callable $callable Function to call.
237
+ * @param array $parameters Parameters to use. Can be indexed by the parameter names
238
+ * or not indexed (same order as the parameters).
239
+ * The array can also contain DI definitions, e.g. Cybot\Dependencies\DI\get().
240
+ *
241
+ * @return mixed Result of the function.
242
+ */
243
+ public function call($callable, array $parameters = [])
244
+ {
245
+ return $this->getInvoker()->call($callable, $parameters);
246
+ }
247
+
248
+ /**
249
+ * Define an object or a value in the container.
250
+ *
251
+ * @param string $name Entry name
252
+ * @param mixed|DefinitionHelper $value Value, use definition helpers to define objects
253
+ */
254
+ public function set($name, $value)
255
+ {
256
+ if ($value instanceof DefinitionHelper) {
257
+ $value = $value->getDefinition($name);
258
+ } elseif ($value instanceof \Closure) {
259
+ $value = new FactoryDefinition($name, $value);
260
+ }
261
+
262
+ if ($value instanceof Definition) {
263
+ $this->setDefinition($name, $value);
264
+ } else {
265
+ $this->singletonEntries[$name] = $value;
266
+ }
267
+ }
268
+
269
+ /**
270
+ * Resolves a definition.
271
+ *
272
+ * Checks for circular dependencies while resolving the definition.
273
+ *
274
+ * @param Definition $definition
275
+ * @param array $parameters
276
+ *
277
+ * @throws DependencyException Error while resolving the entry.
278
+ * @return mixed
279
+ */
280
+ private function resolveDefinition(Definition $definition, array $parameters = [])
281
+ {
282
+ $entryName = $definition->getName();
283
+
284
+ // Check if we are already getting this entry -> circular dependency
285
+ if (isset($this->entriesBeingResolved[$entryName])) {
286
+ throw new DependencyException("Circular dependency detected while trying to resolve entry '$entryName'");
287
+ }
288
+ $this->entriesBeingResolved[$entryName] = true;
289
+
290
+ // Resolve the definition
291
+ try {
292
+ $value = $this->definitionResolver->resolve($definition, $parameters);
293
+ } catch (Exception $exception) {
294
+ unset($this->entriesBeingResolved[$entryName]);
295
+ throw $exception;
296
+ }
297
+
298
+ unset($this->entriesBeingResolved[$entryName]);
299
+
300
+ return $value;
301
+ }
302
+
303
+ private function setDefinition($name, Definition $definition)
304
+ {
305
+ if ($this->definitionSource instanceof CachedDefinitionSource) {
306
+ throw new \LogicException('You cannot set a definition at runtime on a container that has a cache configured. Doing so would risk caching the definition for the next execution, where it might be different. You can either put your definitions in a file, remove the cache or ->set() a raw value directly (PHP object, string, int, ...) instead of a PHP-DI definition.');
307
+ }
308
+
309
+ if (! $this->definitionSource instanceof MutableDefinitionSource) {
310
+ // This can happen if you instantiate the container yourself
311
+ throw new \LogicException('The container has not been initialized correctly');
312
+ }
313
+
314
+ // Clear existing entry if it exists
315
+ if (array_key_exists($name, $this->singletonEntries)) {
316
+ unset($this->singletonEntries[$name]);
317
+ }
318
+
319
+ $this->definitionSource->addDefinition($definition);
320
+ }
321
+
322
+ /**
323
+ * @return \Cybot\Dependencies\Invoker\InvokerInterface
324
+ */
325
+ private function getInvoker()
326
+ {
327
+ if (! $this->invoker) {
328
+ $parameterResolver = new ResolverChain([
329
+ new NumericArrayResolver,
330
+ new AssociativeArrayResolver,
331
+ new DefinitionParameterResolver($this->definitionResolver),
332
+ new TypeHintContainerResolver($this->wrapperContainer),
333
+ ]);
334
+
335
+ $this->invoker = new Invoker($parameterResolver, $this);
336
+ }
337
+
338
+ return $this->invoker;
339
+ }
340
+ }
addons/inc/Dependencies/DI/ContainerBuilder.php ADDED
@@ -0,0 +1,258 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI;
11
+
12
+ use Cybot\Dependencies\DI\Definition\Source\AnnotationReader;
13
+ use Cybot\Dependencies\DI\Definition\Source\DefinitionArray;
14
+ use Cybot\Dependencies\DI\Definition\Source\CachedDefinitionSource;
15
+ use Cybot\Dependencies\DI\Definition\Source\DefinitionSource;
16
+ use Cybot\Dependencies\DI\Definition\Source\DefinitionFile;
17
+ use Cybot\Dependencies\DI\Definition\Source\Autowiring;
18
+ use Cybot\Dependencies\DI\Definition\Source\SourceChain;
19
+ use Cybot\Dependencies\DI\Proxy\ProxyFactory;
20
+ use Doctrine\Common\Cache\Cache;
21
+ use Cybot\Dependencies\Interop\Container\ContainerInterface;
22
+ use InvalidArgumentException;
23
+
24
+ /**
25
+ * Helper to create and configure a Container.
26
+ *
27
+ * With the default options, the container created is appropriate for the development environment.
28
+ *
29
+ * Example:
30
+ *
31
+ * $builder = new ContainerBuilder();
32
+ * $container = $builder->build();
33
+ *
34
+ * @since 3.2
35
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
36
+ */
37
+ class ContainerBuilder
38
+ {
39
+ /**
40
+ * Name of the container class, used to create the container.
41
+ * @var string
42
+ */
43
+ private $containerClass;
44
+
45
+ /**
46
+ * @var boolean
47
+ */
48
+ private $useAutowiring = true;
49
+
50
+ /**
51
+ * @var boolean
52
+ */
53
+ private $useAnnotations = false;
54
+
55
+ /**
56
+ * @var boolean
57
+ */
58
+ private $ignorePhpDocErrors = false;
59
+
60
+ /**
61
+ * @var Cache
62
+ */
63
+ private $cache;
64
+
65
+ /**
66
+ * If true, write the proxies to disk to improve performances.
67
+ * @var boolean
68
+ */
69
+ private $writeProxiesToFile = false;
70
+
71
+ /**
72
+ * Directory where to write the proxies (if $writeProxiesToFile is enabled).
73
+ * @var string
74
+ */
75
+ private $proxyDirectory;
76
+
77
+ /**
78
+ * If PHP-DI is wrapped in another container, this references the wrapper.
79
+ * @var ContainerInterface
80
+ */
81
+ private $wrapperContainer;
82
+
83
+ /**
84
+ * @var DefinitionSource[]
85
+ */
86
+ private $definitionSources = [];
87
+
88
+ /**
89
+ * Build a container configured for the dev environment.
90
+ *
91
+ * @return Container
92
+ */
93
+ public static function buildDevContainer()
94
+ {
95
+ $builder = new self();
96
+ return $builder->build();
97
+ }
98
+
99
+ /**
100
+ * @param string $containerClass Name of the container class, used to create the container.
101
+ */
102
+ public function __construct($containerClass = 'Cybot\Dependencies\DI\Container')
103
+ {
104
+ $this->containerClass = $containerClass;
105
+ }
106
+
107
+ /**
108
+ * Build and return a container.
109
+ *
110
+ * @return Container
111
+ */
112
+ public function build()
113
+ {
114
+ $sources = array_reverse($this->definitionSources);
115
+ if ($this->useAnnotations) {
116
+ $sources[] = new AnnotationReader($this->ignorePhpDocErrors);
117
+ } elseif ($this->useAutowiring) {
118
+ $sources[] = new Autowiring();
119
+ }
120
+
121
+ $chain = new SourceChain($sources);
122
+
123
+ if ($this->cache) {
124
+ $source = new CachedDefinitionSource($chain, $this->cache);
125
+ $chain->setRootDefinitionSource($source);
126
+ } else {
127
+ $source = $chain;
128
+ // Mutable definition source
129
+ $source->setMutableDefinitionSource(new DefinitionArray());
130
+ }
131
+
132
+ $proxyFactory = new ProxyFactory($this->writeProxiesToFile, $this->proxyDirectory);
133
+
134
+ $containerClass = $this->containerClass;
135
+
136
+ return new $containerClass($source, $proxyFactory, $this->wrapperContainer);
137
+ }
138
+
139
+ /**
140
+ * Enable or disable the use of autowiring to guess injections.
141
+ *
142
+ * Enabled by default.
143
+ *
144
+ * @param boolean $bool
145
+ * @return ContainerBuilder
146
+ */
147
+ public function useAutowiring($bool)
148
+ {
149
+ $this->useAutowiring = $bool;
150
+ return $this;
151
+ }
152
+
153
+ /**
154
+ * Enable or disable the use of annotations to guess injections.
155
+ *
156
+ * Disabled by default.
157
+ *
158
+ * @param boolean $bool
159
+ * @return ContainerBuilder
160
+ */
161
+ public function useAnnotations($bool)
162
+ {
163
+ $this->useAnnotations = $bool;
164
+ return $this;
165
+ }
166
+
167
+ /**
168
+ * Enable or disable ignoring phpdoc errors (non-existent classes in `@param` or `@var`)
169
+ *
170
+ * @param boolean $bool
171
+ * @return ContainerBuilder
172
+ */
173
+ public function ignorePhpDocErrors($bool)
174
+ {
175
+ $this->ignorePhpDocErrors = $bool;
176
+ return $this;
177
+ }
178
+
179
+ /**
180
+ * Enables the use of a cache for the definitions.
181
+ *
182
+ * @param Cache $cache Cache backend to use
183
+ * @return ContainerBuilder
184
+ */
185
+ public function setDefinitionCache(Cache $cache)
186
+ {
187
+ $this->cache = $cache;
188
+ return $this;
189
+ }
190
+
191
+ /**
192
+ * Configure the proxy generation
193
+ *
194
+ * For dev environment, use writeProxiesToFile(false) (default configuration)
195
+ * For production environment, use writeProxiesToFile(true, 'tmp/proxies')
196
+ *
197
+ * @param boolean $writeToFile If true, write the proxies to disk to improve performances
198
+ * @param string|null $proxyDirectory Directory where to write the proxies
199
+ * @return ContainerBuilder
200
+ *
201
+ * @throws InvalidArgumentException when writeToFile is set to true and the proxy directory is null
202
+ */
203
+ public function writeProxiesToFile($writeToFile, $proxyDirectory = null)
204
+ {
205
+ $this->writeProxiesToFile = $writeToFile;
206
+
207
+ if ($writeToFile && $proxyDirectory === null) {
208
+ throw new InvalidArgumentException(
209
+ "The proxy directory must be specified if you want to write proxies on disk"
210
+ );
211
+ }
212
+ $this->proxyDirectory = $proxyDirectory;
213
+
214
+ return $this;
215
+ }
216
+
217
+ /**
218
+ * If PHP-DI's container is wrapped by another container, we can
219
+ * set this so that PHP-DI will use the wrapper rather than itself for building objects.
220
+ *
221
+ * @param ContainerInterface $otherContainer
222
+ * @return $this
223
+ */
224
+ public function wrapContainer(ContainerInterface $otherContainer)
225
+ {
226
+ $this->wrapperContainer = $otherContainer;
227
+
228
+ return $this;
229
+ }
230
+
231
+ /**
232
+ * Add definitions to the container.
233
+ *
234
+ * @param string|array|DefinitionSource $definitions Can be an array of definitions, the
235
+ * name of a file containing definitions
236
+ * or a DefinitionSource object.
237
+ * @return $this
238
+ */
239
+ public function addDefinitions($definitions)
240
+ {
241
+ if (is_string($definitions)) {
242
+ // File
243
+ $definitions = new DefinitionFile($definitions);
244
+ } elseif (is_array($definitions)) {
245
+ $definitions = new DefinitionArray($definitions);
246
+ } elseif (! $definitions instanceof DefinitionSource) {
247
+ throw new InvalidArgumentException(sprintf(
248
+ '%s parameter must be a string, an array or a DefinitionSource object, %s given',
249
+ 'ContainerBuilder::addDefinitions()',
250
+ is_object($definitions) ? get_class($definitions) : gettype($definitions)
251
+ ));
252
+ }
253
+
254
+ $this->definitionSources[] = $definitions;
255
+
256
+ return $this;
257
+ }
258
+ }
addons/inc/Dependencies/DI/Debug.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI;
11
+
12
+ use Cybot\Dependencies\DI\Definition\Definition;
13
+ use Cybot\Dependencies\DI\Definition\Dumper\DefinitionDumperDispatcher;
14
+
15
+ /**
16
+ * Debug utilities.
17
+ *
18
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
19
+ */
20
+ class Debug
21
+ {
22
+ /**
23
+ * Dump the definition to a string.
24
+ *
25
+ * @param Definition $definition
26
+ *
27
+ * @return string
28
+ */
29
+ public static function dumpDefinition(Definition $definition)
30
+ {
31
+ static $dumper;
32
+
33
+ if (! $dumper) {
34
+ $dumper = new DefinitionDumperDispatcher();
35
+ }
36
+
37
+ return $dumper->dump($definition);
38
+ }
39
+ }
addons/inc/Dependencies/DI/Definition/AbstractFunctionCallDefinition.php ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition;
11
+
12
+ use Cybot\Dependencies\DI\Scope;
13
+
14
+ /**
15
+ * Describe a function call.
16
+ *
17
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
18
+ */
19
+ abstract class AbstractFunctionCallDefinition implements Definition
20
+ {
21
+ /**
22
+ * @var array
23
+ */
24
+ protected $parameters = [];
25
+
26
+ /**
27
+ * @return array
28
+ */
29
+ public function getParameters()
30
+ {
31
+ return $this->parameters;
32
+ }
33
+
34
+ /**
35
+ * @param int $index Position of the parameter (starting at 0)
36
+ * @return mixed|null Value to inject, or null if no injection defined.
37
+ */
38
+ public function hasParameter($index)
39
+ {
40
+ return array_key_exists($index, $this->parameters);
41
+ }
42
+
43
+ /**
44
+ * @param int $index Position of the parameter (starting at 0)
45
+ * @throws \InvalidArgumentException
46
+ * @return mixed Value to inject
47
+ */
48
+ public function getParameter($index)
49
+ {
50
+ if (! array_key_exists($index, $this->parameters)) {
51
+ throw new \InvalidArgumentException('There is no parameter value for index ' . $index);
52
+ }
53
+
54
+ return $this->parameters[$index];
55
+ }
56
+
57
+ /**
58
+ * Replace the parameters of the definition by a new array of parameters.
59
+ *
60
+ * @param array $parameters
61
+ */
62
+ public function replaceParameters(array $parameters)
63
+ {
64
+ $this->parameters = $parameters;
65
+ }
66
+
67
+ /**
68
+ * {@inheritdoc}
69
+ */
70
+ public function getName()
71
+ {
72
+ return null;
73
+ }
74
+
75
+ /**
76
+ * {@inheritdoc}
77
+ */
78
+ public function getScope()
79
+ {
80
+ return Scope::PROTOTYPE;
81
+ }
82
+ }
addons/inc/Dependencies/DI/Definition/AliasDefinition.php ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition;
11
+
12
+ use Cybot\Dependencies\DI\Scope;
13
+
14
+ /**
15
+ * Defines an alias from an entry to another.
16
+ *
17
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
18
+ */
19
+ class AliasDefinition implements CacheableDefinition
20
+ {
21
+ /**
22
+ * Entry name
23
+ * @var string
24
+ */
25
+ private $name;
26
+
27
+ /**
28
+ * Name of the target entry
29
+ * @var string
30
+ */
31
+ private $targetEntryName;
32
+
33
+ /**
34
+ * @param string $name Entry name
35
+ * @param string $targetEntryName Name of the target entry
36
+ */
37
+ public function __construct($name, $targetEntryName)
38
+ {
39
+ $this->name = $name;
40
+ $this->targetEntryName = $targetEntryName;
41
+ }
42
+
43
+ /**
44
+ * @return string Entry name
45
+ */
46
+ public function getName()
47
+ {
48
+ return $this->name;
49
+ }
50
+
51
+ /**
52
+ * {@inheritdoc}
53
+ */
54
+ public function getScope()
55
+ {
56
+ return Scope::PROTOTYPE;
57
+ }
58
+
59
+ /**
60
+ * @return string
61
+ */
62
+ public function getTargetEntryName()
63
+ {
64
+ return $this->targetEntryName;
65
+ }
66
+ }
addons/inc/Dependencies/DI/Definition/ArrayDefinition.php ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition;
11
+
12
+ use Cybot\Dependencies\DI\Scope;
13
+
14
+ /**
15
+ * Definition of an array containing values or references.
16
+ *
17
+ * @since 5.0
18
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
19
+ */
20
+ class ArrayDefinition implements Definition
21
+ {
22
+ /**
23
+ * Entry name
24
+ * @var string
25
+ */
26
+ private $name;
27
+
28
+ /**
29
+ * @var array
30
+ */
31
+ private $values;
32
+
33
+ /**
34
+ * @param string $name Entry name
35
+ * @param array $values
36
+ */
37
+ public function __construct($name, array $values)
38
+ {
39
+ $this->name = $name;
40
+ $this->values = $values;
41
+ }
42
+
43
+ /**
44
+ * @return string Entry name
45
+ */
46
+ public function getName()
47
+ {
48
+ return $this->name;
49
+ }
50
+
51
+ /**
52
+ * {@inheritdoc}
53
+ */
54
+ public function getScope()
55
+ {
56
+ return Scope::SINGLETON;
57
+ }
58
+
59
+ /**
60
+ * @return array
61
+ */
62
+ public function getValues()
63
+ {
64
+ return $this->values;
65
+ }
66
+ }
addons/inc/Dependencies/DI/Definition/ArrayDefinitionExtension.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition;
11
+
12
+ use Cybot\Dependencies\DI\Definition\Exception\DefinitionException;
13
+
14
+ /**
15
+ * Extends an array definition by adding new elements into it.
16
+ *
17
+ * @since 5.0
18
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
19
+ */
20
+ class ArrayDefinitionExtension extends ArrayDefinition implements HasSubDefinition
21
+ {
22
+ /**
23
+ * @var ArrayDefinition
24
+ */
25
+ private $subDefinition;
26
+
27
+ /**
28
+ * {@inheritdoc}
29
+ */
30
+ public function getValues()
31
+ {
32
+ if (! $this->subDefinition) {
33
+ return parent::getValues();
34
+ }
35
+
36
+ return array_merge($this->subDefinition->getValues(), parent::getValues());
37
+ }
38
+
39
+ /**
40
+ * @return string
41
+ */
42
+ public function getSubDefinitionName()
43
+ {
44
+ return $this->getName();
45
+ }
46
+
47
+ /**
48
+ * {@inheritdoc}
49
+ */
50
+ public function setSubDefinition(Definition $definition)
51
+ {
52
+ if (! $definition instanceof ArrayDefinition) {
53
+ throw new DefinitionException(sprintf(
54
+ 'Definition %s tries to add array entries but the previous definition is not an array',
55
+ $this->getName()
56
+ ));
57
+ }
58
+
59
+ $this->subDefinition = $definition;
60
+ }
61
+ }
addons/inc/Dependencies/DI/Definition/CacheableDefinition.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition;
11
+
12
+ /**
13
+ * Cacheable definition
14
+ *
15
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
16
+ */
17
+ interface CacheableDefinition extends Definition
18
+ {
19
+ }
addons/inc/Dependencies/DI/Definition/DecoratorDefinition.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition;
11
+
12
+ /**
13
+ * Factory that decorates a sub-definition.
14
+ *
15
+ * @since 5.0
16
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
17
+ */
18
+ class DecoratorDefinition extends FactoryDefinition implements Definition, HasSubDefinition
19
+ {
20
+ /**
21
+ * @var Definition
22
+ */
23
+ private $decorated;
24
+
25
+ /**
26
+ * @return string
27
+ */
28
+ public function getSubDefinitionName()
29
+ {
30
+ return $this->getName();
31
+ }
32
+
33
+ /**
34
+ * @param Definition $definition
35
+ */
36
+ public function setSubDefinition(Definition $definition)
37
+ {
38
+ $this->decorated = $definition;
39
+ }
40
+
41
+ /**
42
+ * @return Definition
43
+ */
44
+ public function getDecoratedDefinition()
45
+ {
46
+ return $this->decorated;
47
+ }
48
+ }
addons/inc/Dependencies/DI/Definition/Definition.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition;
11
+
12
+ /**
13
+ * Definition
14
+ *
15
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
16
+ */
17
+ interface Definition
18
+ {
19
+ /**
20
+ * Returns the name of the entry in the container
21
+ *
22
+ * @return string
23
+ */
24
+ public function getName();
25
+
26
+ /**
27
+ * Returns the scope of the entry
28
+ *
29
+ * @return string
30
+ */
31
+ public function getScope();
32
+ }
addons/inc/Dependencies/DI/Definition/Dumper/AliasDefinitionDumper.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Dumper;
11
+
12
+ use Cybot\Dependencies\DI\Definition\AliasDefinition;
13
+ use Cybot\Dependencies\DI\Definition\Definition;
14
+
15
+ /**
16
+ * Dumps alias definitions.
17
+ *
18
+ * @since 4.1
19
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
20
+ */
21
+ class AliasDefinitionDumper implements DefinitionDumper
22
+ {
23
+ /**
24
+ * {@inheritdoc}
25
+ */
26
+ public function dump(Definition $definition)
27
+ {
28
+ if (! $definition instanceof AliasDefinition) {
29
+ throw new \InvalidArgumentException(sprintf(
30
+ 'This definition dumper is only compatible with AliasDefinition objects, %s given',
31
+ get_class($definition)
32
+ ));
33
+ }
34
+
35
+ if ($definition->getName()) {
36
+ return sprintf(
37
+ "get(%s => %s)",
38
+ $definition->getName(),
39
+ $definition->getTargetEntryName()
40
+ );
41
+ }
42
+
43
+ return sprintf(
44
+ "get(%s)",
45
+ $definition->getTargetEntryName()
46
+ );
47
+ }
48
+ }
addons/inc/Dependencies/DI/Definition/Dumper/ArrayDefinitionDumper.php ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Dumper;
11
+
12
+ use Cybot\Dependencies\DI\Debug;
13
+ use Cybot\Dependencies\DI\Definition\ArrayDefinition;
14
+ use Cybot\Dependencies\DI\Definition\Definition;
15
+ use Cybot\Dependencies\DI\Definition\Helper\DefinitionHelper;
16
+
17
+ /**
18
+ * Dumps array definitions.
19
+ *
20
+ * @since 5.0
21
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
22
+ */
23
+ class ArrayDefinitionDumper implements DefinitionDumper
24
+ {
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ public function dump(Definition $definition)
29
+ {
30
+ if (! $definition instanceof ArrayDefinition) {
31
+ throw new \InvalidArgumentException(sprintf(
32
+ 'This definition dumper is only compatible with ArrayDefinition objects, %s given',
33
+ get_class($definition)
34
+ ));
35
+ }
36
+
37
+ $str = '[' . PHP_EOL;
38
+
39
+ foreach ($definition->getValues() as $key => $value) {
40
+ if (is_string($key)) {
41
+ $key = "'" . $key . "'";
42
+ }
43
+
44
+ $str .= ' ' . $key . ' => ';
45
+
46
+ if ($value instanceof DefinitionHelper) {
47
+ $nestedDefinition = Debug::dumpDefinition($value->getDefinition(''));
48
+ $str .= $this->indent($nestedDefinition);
49
+ } else {
50
+ $str .= var_export($value, true);
51
+ }
52
+
53
+ $str .= ',' . PHP_EOL;
54
+ }
55
+
56
+ $str .= ']';
57
+
58
+ return $str;
59
+ }
60
+
61
+ private function indent($str)
62
+ {
63
+ return str_replace("\n", "\n ", $str);
64
+ }
65
+ }
addons/inc/Dependencies/DI/Definition/Dumper/DecoratorDefinitionDumper.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Dumper;
11
+
12
+ use Cybot\Dependencies\DI\Definition\DecoratorDefinition;
13
+ use Cybot\Dependencies\DI\Definition\Definition;
14
+
15
+ /**
16
+ * Dumps decorator definitions.
17
+ *
18
+ * @since 5.0
19
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
20
+ */
21
+ class DecoratorDefinitionDumper implements DefinitionDumper
22
+ {
23
+ /**
24
+ * {@inheritdoc}
25
+ */
26
+ public function dump(Definition $definition)
27
+ {
28
+ if (! $definition instanceof DecoratorDefinition) {
29
+ throw new \InvalidArgumentException(sprintf(
30
+ 'This definition dumper is only compatible with DecoratorDefinition objects, %s given',
31
+ get_class($definition)
32
+ ));
33
+ }
34
+
35
+ return 'Decorate(' . $definition->getSubDefinitionName() . ')';
36
+ }
37
+ }
addons/inc/Dependencies/DI/Definition/Dumper/DefinitionDumper.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Dumper;
11
+
12
+ use Cybot\Dependencies\DI\Definition\Definition;
13
+
14
+ /**
15
+ * Dumps definitions to help debugging.
16
+ *
17
+ * @since 4.1
18
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
19
+ */
20
+ interface DefinitionDumper
21
+ {
22
+ /**
23
+ * Returns the given definition as string representation.
24
+ *
25
+ * @param Definition $definition
26
+ *
27
+ * @return string
28
+ */
29
+ public function dump(Definition $definition);
30
+ }
addons/inc/Dependencies/DI/Definition/Dumper/DefinitionDumperDispatcher.php ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Dumper;
11
+
12
+ use Cybot\Dependencies\DI\Definition\Definition;
13
+
14
+ /**
15
+ * Dispatch a definition to the appropriate dumper.
16
+ *
17
+ * @since 4.1
18
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
19
+ */
20
+ class DefinitionDumperDispatcher implements DefinitionDumper
21
+ {
22
+ /**
23
+ * Definition dumpers, indexed by the class of the definition they can dump.
24
+ *
25
+ * @var DefinitionDumper[]|null
26
+ */
27
+ private $dumpers = [];
28
+
29
+ public function __construct($dumpers = null)
30
+ {
31
+ $this->dumpers = $dumpers;
32
+ }
33
+
34
+ /**
35
+ * {@inheritdoc}
36
+ */
37
+ public function dump(Definition $definition)
38
+ {
39
+ $this->initialize();
40
+
41
+ $class = get_class($definition);
42
+
43
+ if (! array_key_exists($class, $this->dumpers)) {
44
+ throw new \RuntimeException(sprintf(
45
+ 'There is no DefinitionDumper capable of dumping this definition of type %s',
46
+ $class
47
+ ));
48
+ }
49
+
50
+ $dumper = $this->dumpers[$class];
51
+
52
+ return $dumper->dump($definition);
53
+ }
54
+
55
+ private function initialize()
56
+ {
57
+ if ($this->dumpers === null) {
58
+ $this->dumpers = [
59
+ 'Cybot\Dependencies\DI\Definition\ValueDefinition' => new ValueDefinitionDumper(),
60
+ 'Cybot\Dependencies\DI\Definition\FactoryDefinition' => new FactoryDefinitionDumper(),
61
+ 'Cybot\Dependencies\DI\Definition\DecoratorDefinition' => new DecoratorDefinitionDumper(),
62
+ 'Cybot\Dependencies\DI\Definition\AliasDefinition' => new AliasDefinitionDumper(),
63
+ 'Cybot\Dependencies\DI\Definition\ObjectDefinition' => new ObjectDefinitionDumper(),
64
+ 'Cybot\Dependencies\DI\Definition\EnvironmentVariableDefinition' => new EnvironmentVariableDefinitionDumper(),
65
+ ];
66
+ }
67
+ }
68
+ }
addons/inc/Dependencies/DI/Definition/Dumper/EnvironmentVariableDefinitionDumper.php ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Dumper;
11
+
12
+ use Cybot\Dependencies\DI\Debug;
13
+ use Cybot\Dependencies\DI\Definition\Definition;
14
+ use Cybot\Dependencies\DI\Definition\EntryReference;
15
+ use Cybot\Dependencies\DI\Definition\EnvironmentVariableDefinition;
16
+ use Cybot\Dependencies\DI\Definition\Helper\DefinitionHelper;
17
+
18
+ /**
19
+ * Dumps environment variable definitions.
20
+ *
21
+ * @author James Harris <james.harris@icecave.com.au>
22
+ */
23
+ class EnvironmentVariableDefinitionDumper implements DefinitionDumper
24
+ {
25
+ /**
26
+ * {@inheritdoc}
27
+ */
28
+ public function dump(Definition $definition)
29
+ {
30
+ if (! $definition instanceof EnvironmentVariableDefinition) {
31
+ throw new \InvalidArgumentException(sprintf(
32
+ 'This definition dumper is only compatible with EnvironmentVariableDefinition objects, %s given',
33
+ get_class($definition)
34
+ ));
35
+ }
36
+
37
+ $str = " variable = " . $definition->getVariableName();
38
+ $str .= "\n optional = " . ($definition->isOptional() ? 'yes' : 'no');
39
+
40
+ if ($definition->isOptional()) {
41
+ $defaultValue = $definition->getDefaultValue();
42
+
43
+ if ($defaultValue instanceof DefinitionHelper) {
44
+ $nestedDefinition = Debug::dumpDefinition($defaultValue->getDefinition(''));
45
+ $defaultValueStr = $this->indent($nestedDefinition);
46
+ } else {
47
+ $defaultValueStr = var_export($defaultValue, true);
48
+ }
49
+
50
+ $str .= "\n default = " . $defaultValueStr;
51
+ }
52
+
53
+ return sprintf(
54
+ "Environment variable (\n%s\n)",
55
+ $str
56
+ );
57
+ }
58
+
59
+ private function indent($str)
60
+ {
61
+ return str_replace("\n", "\n ", $str);
62
+ }
63
+ }
addons/inc/Dependencies/DI/Definition/Dumper/FactoryDefinitionDumper.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Dumper;
11
+
12
+ use Cybot\Dependencies\DI\Definition\Definition;
13
+ use Cybot\Dependencies\DI\Definition\FactoryDefinition;
14
+
15
+ /**
16
+ * Dumps factory definitions.
17
+ *
18
+ * @since 4.1
19
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
20
+ */
21
+ class FactoryDefinitionDumper implements DefinitionDumper
22
+ {
23
+ /**
24
+ * {@inheritdoc}
25
+ */
26
+ public function dump(Definition $definition)
27
+ {
28
+ if (! $definition instanceof FactoryDefinition) {
29
+ throw new \InvalidArgumentException(sprintf(
30
+ 'This definition dumper is only compatible with FactoryDefinition objects, %s given',
31
+ get_class($definition)
32
+ ));
33
+ }
34
+
35
+ return 'Factory';
36
+ }
37
+ }
addons/inc/Dependencies/DI/Definition/Dumper/ObjectDefinitionDumper.php ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Dumper;
11
+
12
+ use Cybot\Dependencies\DI\Definition\ObjectDefinition;
13
+ use Cybot\Dependencies\DI\Definition\ObjectDefinition\MethodInjection;
14
+ use Cybot\Dependencies\DI\Definition\Definition;
15
+ use Cybot\Dependencies\DI\Definition\EntryReference;
16
+ use ReflectionException;
17
+ use ReflectionMethod;
18
+
19
+ /**
20
+ * Dumps object definitions.
21
+ *
22
+ * @since 4.1
23
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
24
+ */
25
+ class ObjectDefinitionDumper implements DefinitionDumper
26
+ {
27
+ /**
28
+ * {@inheritdoc}
29
+ */
30
+ public function dump(Definition $definition)
31
+ {
32
+ if (! $definition instanceof ObjectDefinition) {
33
+ throw new \InvalidArgumentException(sprintf(
34
+ 'This definition dumper is only compatible with ObjectDefinition objects, %s given',
35
+ get_class($definition)
36
+ ));
37
+ }
38
+
39
+ $className = $definition->getClassName();
40
+ $classExist = class_exists($className) || interface_exists($className);
41
+
42
+ // Class
43
+ if (! $classExist) {
44
+ $warning = '#UNKNOWN# ';
45
+ } else {
46
+ $class = new \ReflectionClass($className);
47
+ $warning = $class->isInstantiable() ? '' : '#NOT INSTANTIABLE# ';
48
+ }
49
+ $str = sprintf(' class = %s%s', $warning, $className);
50
+
51
+ // Scope
52
+ $str .= "\n scope = " . $definition->getScope();
53
+
54
+ // Lazy
55
+ $str .= "\n lazy = " . var_export($definition->isLazy(), true);
56
+
57
+ if ($classExist) {
58
+ // Constructor
59
+ $str .= $this->dumpConstructor($className, $definition);
60
+
61
+ // Properties
62
+ $str .= $this->dumpProperties($definition);
63
+
64
+ // Methods
65
+ $str .= $this->dumpMethods($className, $definition);
66
+ }
67
+
68
+ return sprintf("Object (\n%s\n)", $str);
69
+ }
70
+
71
+ private function dumpConstructor($className, ObjectDefinition $definition)
72
+ {
73
+ $str = '';
74
+
75
+ $constructorInjection = $definition->getConstructorInjection();
76
+
77
+ if ($constructorInjection !== null) {
78
+ $parameters = $this->dumpMethodParameters($className, $constructorInjection);
79
+
80
+ $str .= sprintf("\n __construct(\n %s\n )", $parameters);
81
+ }
82
+
83
+ return $str;
84
+ }
85
+
86
+ private function dumpProperties(ObjectDefinition $definition)
87
+ {
88
+ $str = '';
89
+
90
+ foreach ($definition->getPropertyInjections() as $propertyInjection) {
91
+ $value = $propertyInjection->getValue();
92
+ if ($value instanceof EntryReference) {
93
+ $valueStr = sprintf('get(%s)', $value->getName());
94
+ } else {
95
+ $valueStr = var_export($value, true);
96
+ }
97
+
98
+ $str .= sprintf("\n $%s = %s", $propertyInjection->getPropertyName(), $valueStr);
99
+ }
100
+
101
+ return $str;
102
+ }
103
+
104
+ private function dumpMethods($className, ObjectDefinition $definition)
105
+ {
106
+ $str = '';
107
+
108
+ foreach ($definition->getMethodInjections() as $methodInjection) {
109
+ $parameters = $this->dumpMethodParameters($className, $methodInjection);
110
+
111
+ $str .= sprintf("\n %s(\n %s\n )", $methodInjection->getMethodName(), $parameters);
112
+ }
113
+
114
+ return $str;
115
+ }
116
+
117
+ private function dumpMethodParameters($className, MethodInjection $methodInjection)
118
+ {
119
+ $methodReflection = new \ReflectionMethod($className, $methodInjection->getMethodName());
120
+
121
+ $args = [];
122
+
123
+ foreach ($methodReflection->getParameters() as $index => $parameter) {
124
+ if ($methodInjection->hasParameter($index)) {
125
+ $value = $methodInjection->getParameter($index);
126
+
127
+ if ($value instanceof EntryReference) {
128
+ $args[] = sprintf('$%s = get(%s)', $parameter->getName(), $value->getName());
129
+ } else {
130
+ $args[] = sprintf('$%s = %s', $parameter->getName(), var_export($value, true));
131
+ }
132
+ continue;
133
+ }
134
+
135
+ // If the parameter is optional and wasn't specified, we take its default value
136
+ if ($parameter->isOptional()) {
137
+ try {
138
+ $value = $parameter->getDefaultValue();
139
+
140
+ $args[] = sprintf(
141
+ '$%s = (default value) %s',
142
+ $parameter->getName(),
143
+ var_export($value, true)
144
+ );
145
+ continue;
146
+ } catch (ReflectionException $e) {
147
+ // The default value can't be read through Reflection because it is a PHP internal class
148
+ }
149
+ }
150
+
151
+ $args[] = sprintf('$%s = #UNDEFINED#', $parameter->getName());
152
+ }
153
+
154
+ return implode(PHP_EOL . ' ', $args);
155
+ }
156
+ }
addons/inc/Dependencies/DI/Definition/Dumper/StringDefinitionDumper.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Dumper;
11
+
12
+ use Cybot\Dependencies\DI\Definition\Definition;
13
+ use Cybot\Dependencies\DI\Definition\StringDefinition;
14
+
15
+ /**
16
+ * Dumps string definitions.
17
+ *
18
+ * @since 5.0
19
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
20
+ */
21
+ class StringDefinitionDumper implements DefinitionDumper
22
+ {
23
+ /**
24
+ * {@inheritdoc}
25
+ */
26
+ public function dump(Definition $definition)
27
+ {
28
+ if (! $definition instanceof StringDefinition) {
29
+ throw new \InvalidArgumentException(sprintf(
30
+ 'This definition dumper is only compatible with StringDefinition objects, %s given',
31
+ get_class($definition)
32
+ ));
33
+ }
34
+
35
+ return $definition->getExpression();
36
+ }
37
+ }
addons/inc/Dependencies/DI/Definition/Dumper/ValueDefinitionDumper.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Dumper;
11
+
12
+ use Cybot\Dependencies\DI\Definition\Definition;
13
+ use Cybot\Dependencies\DI\Definition\ValueDefinition;
14
+
15
+ /**
16
+ * Dumps value definitions.
17
+ *
18
+ * @since 4.1
19
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
20
+ */
21
+ class ValueDefinitionDumper implements DefinitionDumper
22
+ {
23
+ /**
24
+ * {@inheritdoc}
25
+ */
26
+ public function dump(Definition $definition)
27
+ {
28
+ if (! $definition instanceof ValueDefinition) {
29
+ throw new \InvalidArgumentException(sprintf(
30
+ 'This definition dumper is only compatible with ValueDefinition objects, %s given',
31
+ get_class($definition)
32
+ ));
33
+ }
34
+
35
+ ob_start();
36
+
37
+ var_dump($definition->getValue());
38
+
39
+ return sprintf(
40
+ "Value (\n %s\n)",
41
+ trim(ob_get_clean())
42
+ );
43
+ }
44
+ }
addons/inc/Dependencies/DI/Definition/EntryReference.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition;
11
+
12
+ use Cybot\Dependencies\DI\Definition\Helper\DefinitionHelper;
13
+
14
+ /**
15
+ * Represents a reference to a container entry.
16
+ *
17
+ * TODO should EntryReference and AliasDefinition be merged into a ReferenceDefinition?
18
+ *
19
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
20
+ */
21
+ class EntryReference implements DefinitionHelper
22
+ {
23
+ /**
24
+ * Entry name
25
+ * @var string
26
+ */
27
+ private $name;
28
+
29
+ /**
30
+ * @param string $entryName Entry name
31
+ */
32
+ public function __construct($entryName)
33
+ {
34
+ $this->name = $entryName;
35
+ }
36
+
37
+ /**
38
+ * @return string Entry name
39
+ */
40
+ public function getName()
41
+ {
42
+ return $this->name;
43
+ }
44
+
45
+ /**
46
+ * {@inheritdoc}
47
+ */
48
+ public function getDefinition($entryName)
49
+ {
50
+ return new AliasDefinition($entryName, $this->name);
51
+ }
52
+ }
addons/inc/Dependencies/DI/Definition/EnvironmentVariableDefinition.php ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition;
11
+
12
+ use Cybot\Dependencies\DI\Scope;
13
+
14
+ /**
15
+ * Defines a reference to an environment variable, with fallback to a default
16
+ * value if the environment variable is not defined.
17
+ *
18
+ * @author James Harris <james.harris@icecave.com.au>
19
+ */
20
+ class EnvironmentVariableDefinition implements CacheableDefinition
21
+ {
22
+ /**
23
+ * Entry name
24
+ * @var string
25
+ */
26
+ private $name;
27
+
28
+ /**
29
+ * The name of the environment variable
30
+ * @var string
31
+ */
32
+ private $variableName;
33
+
34
+ /**
35
+ * Whether or not the environment variable definition is optional
36
+ *
37
+ * If true and the environment variable given by $variableName has not been
38
+ * defined, $defaultValue is used.
39
+ *
40
+ * @var boolean
41
+ */
42
+ private $isOptional;
43
+
44
+ /**
45
+ * The default value to use if the environment variable is optional and not provided
46
+ * @var mixed
47
+ */
48
+ private $defaultValue;
49
+
50
+ /**
51
+ * @var string|null
52
+ */
53
+ private $scope;
54
+
55
+ /**
56
+ * @param string $name Entry name
57
+ * @param string $variableName The name of the environment variable
58
+ * @param boolean $isOptional Whether or not the environment variable definition is optional
59
+ * @param mixed $defaultValue The default value to use if the environment variable is optional and not provided
60
+ */
61
+ public function __construct($name, $variableName, $isOptional = false, $defaultValue = null)
62
+ {
63
+ $this->name = $name;
64
+ $this->variableName = $variableName;
65
+ $this->isOptional = $isOptional;
66
+ $this->defaultValue = $defaultValue;
67
+ }
68
+
69
+ /**
70
+ * @return string Entry name
71
+ */
72
+ public function getName()
73
+ {
74
+ return $this->name;
75
+ }
76
+
77
+ /**
78
+ * @return string The name of the environment variable
79
+ */
80
+ public function getVariableName()
81
+ {
82
+ return $this->variableName;
83
+ }
84
+
85
+ /**
86
+ * @return boolean Whether or not the environment variable definition is optional
87
+ */
88
+ public function isOptional()
89
+ {
90
+ return $this->isOptional;
91
+ }
92
+
93
+ /**
94
+ * @return mixed The default value to use if the environment variable is optional and not provided
95
+ */
96
+ public function getDefaultValue()
97
+ {
98
+ return $this->defaultValue;
99
+ }
100
+
101
+ /**
102
+ * @param string $scope
103
+ */
104
+ public function setScope($scope)
105
+ {
106
+ $this->scope = $scope;
107
+ }
108
+
109
+ /**
110
+ * {@inheritdoc}
111
+ */
112
+ public function getScope()
113
+ {
114
+ return $this->scope ?: Scope::SINGLETON;
115
+ }
116
+ }
addons/inc/Dependencies/DI/Definition/Exception/AnnotationException.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Exception;
11
+
12
+ /**
13
+ * Exception in the definitions using annotations
14
+ *
15
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
16
+ */
17
+ class AnnotationException extends DefinitionException
18
+ {
19
+ }
addons/inc/Dependencies/DI/Definition/Exception/DefinitionException.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Exception;
11
+
12
+ use Cybot\Dependencies\DI\Debug;
13
+ use Cybot\Dependencies\DI\Definition\Definition;
14
+
15
+ /**
16
+ * Invalid DI definitions
17
+ *
18
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
19
+ */
20
+ class DefinitionException extends \Exception
21
+ {
22
+ public static function create(Definition $definition, $message)
23
+ {
24
+ return new self(sprintf(
25
+ "%s\nFull definition:\n%s",
26
+ $message,
27
+ Debug::dumpDefinition($definition)
28
+ ));
29
+ }
30
+ }
addons/inc/Dependencies/DI/Definition/FactoryDefinition.php ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition;
11
+
12
+ use Cybot\Dependencies\DI\Scope;
13
+
14
+ /**
15
+ * Definition of a value or class with a factory.
16
+ *
17
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
18
+ */
19
+ class FactoryDefinition implements Definition
20
+ {
21
+ /**
22
+ * Entry name.
23
+ * @var string
24
+ */
25
+ private $name;
26
+
27
+ /**
28
+ * @var string
29
+ */
30
+ private $scope;
31
+
32
+ /**
33
+ * Callable that returns the value.
34
+ * @var callable
35
+ */
36
+ private $factory;
37
+
38
+ /**
39
+ * @param string $name Entry name
40
+ * @param callable $factory Callable that returns the value associated to the entry name.
41
+ * @param string|null $scope
42
+ */
43
+ public function __construct($name, $factory, $scope = null)
44
+ {
45
+ $this->name = $name;
46
+ $this->factory = $factory;
47
+ $this->scope = $scope;
48
+ }
49
+
50
+ /**
51
+ * @return string Entry name.
52
+ */
53
+ public function getName()
54
+ {
55
+ return $this->name;
56
+ }
57
+
58
+ /**
59
+ * Default scope is singleton: the callable is called once and the result is shared.
60
+ *
61
+ * {@inheritdoc}
62
+ */
63
+ public function getScope()
64
+ {
65
+ return $this->scope ?: Scope::SINGLETON;
66
+ }
67
+
68
+ /**
69
+ * @return callable Callable that returns the value associated to the entry name.
70
+ */
71
+ public function getCallable()
72
+ {
73
+ return $this->factory;
74
+ }
75
+ }
addons/inc/Dependencies/DI/Definition/HasSubDefinition.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition;
11
+
12
+ /**
13
+ * A definition that has a sub-definition.
14
+ *
15
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
16
+ */
17
+ interface HasSubDefinition extends Definition
18
+ {
19
+ /**
20
+ * @return string
21
+ */
22
+ public function getSubDefinitionName();
23
+
24
+ /**
25
+ * @param Definition $definition
26
+ */
27
+ public function setSubDefinition(Definition $definition);
28
+ }
addons/inc/Dependencies/DI/Definition/Helper/ArrayDefinitionExtensionHelper.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Helper;
11
+
12
+ use Cybot\Dependencies\DI\Definition\ArrayDefinitionExtension;
13
+
14
+ /**
15
+ * Helps extending the definition of an array.
16
+ *
17
+ * For example you can add new entries to the array.
18
+ *
19
+ * @since 5.0
20
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
21
+ */
22
+ class ArrayDefinitionExtensionHelper implements DefinitionHelper
23
+ {
24
+ /**
25
+ * @var array
26
+ */
27
+ private $values = [];
28
+
29
+ /**
30
+ * @param array $values Values to add to the array.
31
+ */
32
+ public function __construct(array $values)
33
+ {
34
+ $this->values = $values;
35
+ }
36
+
37
+ /**
38
+ * @param string $entryName Container entry name
39
+ *
40
+ * @return ArrayDefinitionExtension
41
+ */
42
+ public function getDefinition($entryName)
43
+ {
44
+ return new ArrayDefinitionExtension($entryName, $this->values);
45
+ }
46
+ }
addons/inc/Dependencies/DI/Definition/Helper/DefinitionHelper.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Helper;
11
+
12
+ /**
13
+ * Helps defining container entries.
14
+ *
15
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
16
+ */
17
+ interface DefinitionHelper
18
+ {
19
+ /**
20
+ * @param string $entryName Container entry name
21
+ * @return \Cybot\Dependencies\DI\Definition\Definition
22
+ */
23
+ public function getDefinition($entryName);
24
+ }
addons/inc/Dependencies/DI/Definition/Helper/EnvironmentVariableDefinitionHelper.php ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Helper;
11
+
12
+ use Cybot\Dependencies\DI\Definition\EnvironmentVariableDefinition;
13
+
14
+ /**
15
+ * Helps defining how to create an instance of an environment variable definition.
16
+ *
17
+ * @author James Harris <james.harris@icecave.com.au>
18
+ */
19
+ class EnvironmentVariableDefinitionHelper implements DefinitionHelper
20
+ {
21
+ /**
22
+ * The name of the environment variable
23
+ * @var string
24
+ */
25
+ private $variableName;
26
+
27
+ /**
28
+ * Whether or not the environment variable definition is optional
29
+ *
30
+ * If true and the environment variable given by $variableName has not been
31
+ * defined, $defaultValue is used.
32
+ *
33
+ * @var boolean
34
+ */
35
+ private $isOptional;
36
+
37
+ /**
38
+ * The default value to use if the environment variable is optional and not provided
39
+ * @var mixed
40
+ */
41
+ private $defaultValue;
42
+
43
+ /**
44
+ * @param string $variableName The name of the environment variable
45
+ * @param boolean $isOptional Whether or not the environment variable definition is optional
46
+ * @param mixed $defaultValue The default value to use if the environment variable is optional and not provided
47
+ */
48
+ public function __construct($variableName, $isOptional, $defaultValue = null)
49
+ {
50
+ $this->variableName = $variableName;
51
+ $this->isOptional = $isOptional;
52
+ $this->defaultValue = $defaultValue;
53
+ }
54
+
55
+ /**
56
+ * @param string $entryName Container entry name
57
+ *
58
+ * @return EnvironmentVariableDefinition
59
+ */
60
+ public function getDefinition($entryName)
61
+ {
62
+ return new EnvironmentVariableDefinition($entryName, $this->variableName, $this->isOptional, $this->defaultValue);
63
+ }
64
+ }
addons/inc/Dependencies/DI/Definition/Helper/FactoryDefinitionHelper.php ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Helper;
11
+
12
+ use Cybot\Dependencies\DI\Definition\DecoratorDefinition;
13
+ use Cybot\Dependencies\DI\Definition\FactoryDefinition;
14
+
15
+ /**
16
+ * Helps defining how to create an instance of a class using a factory (callable).
17
+ *
18
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
19
+ */
20
+ class FactoryDefinitionHelper implements DefinitionHelper
21
+ {
22
+ /**
23
+ * @var callable
24
+ */
25
+ private $factory;
26
+
27
+ /**
28
+ * @var string|null
29
+ */
30
+ private $scope;
31
+
32
+ /**
33
+ * @var bool
34
+ */
35
+ private $decorate;
36
+
37
+ /**
38
+ * @param callable $factory
39
+ * @param bool $decorate Is the factory decorating a previous definition?
40
+ */
41
+ public function __construct($factory, $decorate = false)
42
+ {
43
+ $this->factory = $factory;
44
+ $this->decorate = $decorate;
45
+ }
46
+
47
+ /**
48
+ * Defines the scope of the entry.
49
+ *
50
+ * @param string $scope
51
+ *
52
+ * @return FactoryDefinitionHelper
53
+ */
54
+ public function scope($scope)
55
+ {
56
+ $this->scope = $scope;
57
+ return $this;
58
+ }
59
+
60
+ /**
61
+ * @param string $entryName Container entry name
62
+ * @return FactoryDefinition
63
+ */
64
+ public function getDefinition($entryName)
65
+ {
66
+ if ($this->decorate) {
67
+ return new DecoratorDefinition($entryName, $this->factory, $this->scope);
68
+ }
69
+
70
+ return new FactoryDefinition($entryName, $this->factory, $this->scope);
71
+ }
72
+ }
addons/inc/Dependencies/DI/Definition/Helper/ObjectDefinitionHelper.php ADDED
@@ -0,0 +1,273 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Helper;
11
+
12
+ use Cybot\Dependencies\DI\Definition\ObjectDefinition;
13
+ use Cybot\Dependencies\DI\Definition\ObjectDefinition\MethodInjection;
14
+ use Cybot\Dependencies\DI\Definition\ObjectDefinition\PropertyInjection;
15
+
16
+ /**
17
+ * Helps defining how to create an instance of a class.
18
+ *
19
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
20
+ */
21
+ class ObjectDefinitionHelper implements DefinitionHelper
22
+ {
23
+ /**
24
+ * @var string|null
25
+ */
26
+ private $className;
27
+
28
+ /**
29
+ * @var boolean|null
30
+ */
31
+ private $lazy;
32
+
33
+ /**
34
+ * @var string|null
35
+ */
36
+ private $scope;
37
+
38
+ /**
39
+ * Array of constructor parameters.
40
+ * @var array
41
+ */
42
+ private $constructor = [];
43
+
44
+ /**
45
+ * Array of properties and their value.
46
+ * @var array
47
+ */
48
+ private $properties = [];
49
+
50
+ /**
51
+ * Array of methods and their parameters.
52
+ * @var array
53
+ */
54
+ private $methods = [];
55
+
56
+ /**
57
+ * Helper for defining an object.
58
+ *
59
+ * @param string|null $className Class name of the object.
60
+ * If null, the name of the entry (in the container) will be used as class name.
61
+ */
62
+ public function __construct($className = null)
63
+ {
64
+ $this->className = $className;
65
+ }
66
+
67
+ /**
68
+ * Define the entry as lazy.
69
+ *
70
+ * A lazy entry is created only when it is used, a proxy is injected instead.
71
+ *
72
+ * @return ObjectDefinitionHelper
73
+ */
74
+ public function lazy()
75
+ {
76
+ $this->lazy = true;
77
+ return $this;
78
+ }
79
+
80
+ /**
81
+ * Defines the scope of the entry.
82
+ *
83
+ * @param string $scope
84
+ *
85
+ * @return ObjectDefinitionHelper
86
+ */
87
+ public function scope($scope)
88
+ {
89
+ $this->scope = $scope;
90
+ return $this;
91
+ }
92
+
93
+ /**
94
+ * Defines the arguments to use to call the constructor.
95
+ *
96
+ * This method takes a variable number of arguments, example:
97
+ * ->constructor($param1, $param2, $param3)
98
+ *
99
+ * @param mixed ... Parameters to use for calling the constructor of the class.
100
+ *
101
+ * @return ObjectDefinitionHelper
102
+ */
103
+ public function constructor()
104
+ {
105
+ $this->constructor = func_get_args();
106
+ return $this;
107
+ }
108
+
109
+ /**
110
+ * Defines a value for a specific argument of the constructor.
111
+ *
112
+ * This method is usually used together with annotations or autowiring, when a parameter
113
+ * is not (or cannot be) type-hinted. Using this method instead of constructor() allows to
114
+ * avoid defining all the parameters (letting them being resolved using annotations or autowiring)
115
+ * and only define one.
116
+ *
117
+ * @param string $parameter Parameter for which the value will be given.
118
+ * @param mixed $value Value to give to this parameter.
119
+ *
120
+ * @return ObjectDefinitionHelper
121
+ */
122
+ public function constructorParameter($parameter, $value)
123
+ {
124
+ $this->constructor[$parameter] = $value;
125
+ return $this;
126
+ }
127
+
128
+ /**
129
+ * Defines a value to inject in a property of the object.
130
+ *
131
+ * @param string $property Entry in which to inject the value.
132
+ * @param mixed $value Value to inject in the property.
133
+ *
134
+ * @return ObjectDefinitionHelper
135
+ */
136
+ public function property($property, $value)
137
+ {
138
+ $this->properties[$property] = $value;
139
+ return $this;
140
+ }
141
+
142
+ /**
143
+ * Defines a method to call and the arguments to use.
144
+ *
145
+ * This method takes a variable number of arguments after the method name, example:
146
+ *
147
+ * ->method('myMethod', $param1, $param2)
148
+ *
149
+ * Can be used multiple times to declare multiple calls.
150
+ *
151
+ * @param string $method Name of the method to call.
152
+ * @param mixed ... Parameters to use for calling the method.
153
+ *
154
+ * @return ObjectDefinitionHelper
155
+ */
156
+ public function method($method)
157
+ {
158
+ $args = func_get_args();
159
+ array_shift($args);
160
+
161
+ if (! isset($this->methods[$method])) {
162
+ $this->methods[$method] = [];
163
+ }
164
+
165
+ $this->methods[$method][] = $args;
166
+
167
+ return $this;
168
+ }
169
+
170
+ /**
171
+ * Defines a method to call and a value for a specific argument.
172
+ *
173
+ * This method is usually used together with annotations or autowiring, when a parameter
174
+ * is not (or cannot be) type-hinted. Using this method instead of method() allows to
175
+ * avoid defining all the parameters (letting them being resolved using annotations or
176
+ * autowiring) and only define one.
177
+ *
178
+ * If multiple calls to the method have been configured already (e.g. in a previous definition)
179
+ * then this method only overrides the parameter for the *first* call.
180
+ *
181
+ * @param string $method Name of the method to call.
182
+ * @param string $parameter Name or index of the parameter for which the value will be given.
183
+ * @param mixed $value Value to give to this parameter.
184
+ *
185
+ * @return ObjectDefinitionHelper
186
+ */
187
+ public function methodParameter($method, $parameter, $value)
188
+ {
189
+ // Special case for the constructor
190
+ if ($method === '__construct') {
191
+ $this->constructor[$parameter] = $value;
192
+ return $this;
193
+ }
194
+
195
+ if (! isset($this->methods[$method])) {
196
+ $this->methods[$method] = [0 => []];
197
+ }
198
+
199
+ $this->methods[$method][0][$parameter] = $value;
200
+
201
+ return $this;
202
+ }
203
+
204
+ /**
205
+ * {@inheritdoc}
206
+ */
207
+ public function getDefinition($entryName)
208
+ {
209
+ $definition = new ObjectDefinition($entryName, $this->className);
210
+
211
+ if ($this->lazy !== null) {
212
+ $definition->setLazy($this->lazy);
213
+ }
214
+ if ($this->scope !== null) {
215
+ $definition->setScope($this->scope);
216
+ }
217
+
218
+ if (! empty($this->constructor)) {
219
+ $parameters = $this->fixParameters($definition, '__construct', $this->constructor);
220
+ $constructorInjection = MethodInjection::constructor($parameters);
221
+ $definition->setConstructorInjection($constructorInjection);
222
+ }
223
+
224
+ if (! empty($this->properties)) {
225
+ foreach ($this->properties as $property => $value) {
226
+ $definition->addPropertyInjection(
227
+ new PropertyInjection($property, $value)
228
+ );
229
+ }
230
+ }
231
+
232
+ if (! empty($this->methods)) {
233
+ foreach ($this->methods as $method => $calls) {
234
+ foreach ($calls as $parameters) {
235
+ $parameters = $this->fixParameters($definition, $method, $parameters);
236
+ $methodInjection = new MethodInjection($method, $parameters);
237
+ $definition->addMethodInjection($methodInjection);
238
+ }
239
+ }
240
+ }
241
+
242
+ return $definition;
243
+ }
244
+
245
+ /**
246
+ * Fixes parameters indexed by the parameter name -> reindex by position.
247
+ *
248
+ * This is necessary so that merging definitions between sources is possible.
249
+ *
250
+ * @param ObjectDefinition $definition
251
+ * @param string $method
252
+ * @param array $parameters
253
+ * @return array
254
+ */
255
+ private function fixParameters(ObjectDefinition $definition, $method, $parameters)
256
+ {
257
+ $fixedParameters = [];
258
+
259
+ foreach ($parameters as $index => $parameter) {
260
+ // Parameter indexed by the parameter name, we reindex it with its position
261
+ if (is_string($index)) {
262
+ $callable = [$definition->getClassName(), $method];
263
+ $reflectionParameter = new \ReflectionParameter($callable, $index);
264
+
265
+ $index = $reflectionParameter->getPosition();
266
+ }
267
+
268
+ $fixedParameters[$index] = $parameter;
269
+ }
270
+
271
+ return $fixedParameters;
272
+ }
273
+ }
addons/inc/Dependencies/DI/Definition/Helper/StringDefinitionHelper.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Helper;
11
+
12
+ use Cybot\Dependencies\DI\Definition\StringDefinition;
13
+
14
+ /**
15
+ * @since 5.0
16
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
17
+ */
18
+ class StringDefinitionHelper implements DefinitionHelper
19
+ {
20
+ /**
21
+ * @var string
22
+ */
23
+ private $expression;
24
+
25
+ public function __construct($expression)
26
+ {
27
+ $this->expression = $expression;
28
+ }
29
+
30
+ /**
31
+ * @param string $entryName Container entry name
32
+ *
33
+ * @return StringDefinition
34
+ */
35
+ public function getDefinition($entryName)
36
+ {
37
+ return new StringDefinition($entryName, $this->expression);
38
+ }
39
+ }
addons/inc/Dependencies/DI/Definition/Helper/ValueDefinitionHelper.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Helper;
11
+
12
+ use Cybot\Dependencies\DI\Definition\ValueDefinition;
13
+
14
+ /**
15
+ * Helps defining a value.
16
+ *
17
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
18
+ */
19
+ class ValueDefinitionHelper implements DefinitionHelper
20
+ {
21
+ /**
22
+ * @var mixed
23
+ */
24
+ private $value;
25
+
26
+ /**
27
+ * @param mixed $value
28
+ */
29
+ public function __construct($value)
30
+ {
31
+ $this->value = $value;
32
+ }
33
+
34
+ /**
35
+ * @param string $entryName Container entry name
36
+ * @return ValueDefinition
37
+ */
38
+ public function getDefinition($entryName)
39
+ {
40
+ return new ValueDefinition($entryName, $this->value);
41
+ }
42
+ }
addons/inc/Dependencies/DI/Definition/InstanceDefinition.php ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition;
11
+
12
+ use Cybot\Dependencies\DI\Scope;
13
+
14
+ /**
15
+ * Defines injections on an existing class instance.
16
+ *
17
+ * @since 5.0
18
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
19
+ */
20
+ class InstanceDefinition implements Definition
21
+ {
22
+ /**
23
+ * Instance on which to inject dependencies.
24
+ *
25
+ * @var object
26
+ */
27
+ private $instance;
28
+
29
+ /**
30
+ * @var ObjectDefinition
31
+ */
32
+ private $objectDefinition;
33
+
34
+ /**
35
+ * @param object $instance
36
+ * @param ObjectDefinition $objectDefinition
37
+ */
38
+ public function __construct($instance, ObjectDefinition $objectDefinition)
39
+ {
40
+ $this->instance = $instance;
41
+ $this->objectDefinition = $objectDefinition;
42
+ }
43
+
44
+ /**
45
+ * {@inheritdoc}
46
+ */
47
+ public function getName()
48
+ {
49
+ // Name are superfluous for instance definitions
50
+ return '';
51
+ }
52
+
53
+ /**
54
+ * {@inheritdoc}
55
+ */
56
+ public function getScope()
57
+ {
58
+ return Scope::PROTOTYPE;
59
+ }
60
+
61
+ /**
62
+ * @return object
63
+ */
64
+ public function getInstance()
65
+ {
66
+ return $this->instance;
67
+ }
68
+
69
+ /**
70
+ * @return ObjectDefinition
71
+ */
72
+ public function getObjectDefinition()
73
+ {
74
+ return $this->objectDefinition;
75
+ }
76
+ }
addons/inc/Dependencies/DI/Definition/ObjectDefinition.php ADDED
@@ -0,0 +1,294 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition;
11
+
12
+ use Cybot\Dependencies\DI\Definition\ObjectDefinition\MethodInjection;
13
+ use Cybot\Dependencies\DI\Definition\ObjectDefinition\PropertyInjection;
14
+ use Cybot\Dependencies\DI\Definition\Exception\DefinitionException;
15
+ use Cybot\Dependencies\DI\Scope;
16
+
17
+ /**
18
+ * Defines how an object can be instantiated.
19
+ *
20
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
21
+ */
22
+ class ObjectDefinition implements Definition, CacheableDefinition, HasSubDefinition
23
+ {
24
+ /**
25
+ * Entry name (most of the time, same as $classname)
26
+ * @var string
27
+ */
28
+ private $name;
29
+
30
+ /**
31
+ * Class name (if null, then the class name is $name)
32
+ * @var string|null
33
+ */
34
+ private $className;
35
+
36
+ /**
37
+ * Constructor parameter injection
38
+ * @var MethodInjection|null
39
+ */
40
+ private $constructorInjection;
41
+
42
+ /**
43
+ * Property injections
44
+ * @var PropertyInjection[]
45
+ */
46
+ private $propertyInjections = [];
47
+
48
+ /**
49
+ * Method calls
50
+ * @var MethodInjection[][]
51
+ */
52
+ private $methodInjections = [];
53
+
54
+ /**
55
+ * @var string|null
56
+ */
57
+ private $scope;
58
+
59
+ /**
60
+ * @var boolean|null
61
+ */
62
+ private $lazy;
63
+
64
+ /**
65
+ * @param string $name Class name
66
+ * @param string $className
67
+ */
68
+ public function __construct($name, $className = null)
69
+ {
70
+ $this->name = (string) $name;
71
+ $this->className = $className;
72
+ }
73
+
74
+ /**
75
+ * @return string Entry name
76
+ */
77
+ public function getName()
78
+ {
79
+ return $this->name;
80
+ }
81
+
82
+ /**
83
+ * @param string $className
84
+ */
85
+ public function setClassName($className)
86
+ {
87
+ $this->className = $className;
88
+ }
89
+
90
+ /**
91
+ * @return string Class name
92
+ */
93
+ public function getClassName()
94
+ {
95
+ if ($this->className !== null) {
96
+ return $this->className;
97
+ }
98
+ return $this->name;
99
+ }
100
+
101
+ /**
102
+ * @return MethodInjection|null
103
+ */
104
+ public function getConstructorInjection()
105
+ {
106
+ return $this->constructorInjection;
107
+ }
108
+
109
+ /**
110
+ * @param MethodInjection $constructorInjection
111
+ */
112
+ public function setConstructorInjection(MethodInjection $constructorInjection)
113
+ {
114
+ $this->constructorInjection = $constructorInjection;
115
+ }
116
+
117
+ /**
118
+ * @return PropertyInjection[] Property injections
119
+ */
120
+ public function getPropertyInjections()
121
+ {
122
+ return $this->propertyInjections;
123
+ }
124
+
125
+ /**
126
+ * @param string $propertyName
127
+ * @return PropertyInjection
128
+ */
129
+ public function getPropertyInjection($propertyName)
130
+ {
131
+ return isset($this->propertyInjections[$propertyName]) ? $this->propertyInjections[$propertyName] : null;
132
+ }
133
+
134
+ /**
135
+ * @param PropertyInjection $propertyInjection
136
+ */
137
+ public function addPropertyInjection(PropertyInjection $propertyInjection)
138
+ {
139
+ $this->propertyInjections[$propertyInjection->getPropertyName()] = $propertyInjection;
140
+ }
141
+
142
+ /**
143
+ * @return MethodInjection[] Method injections
144
+ */
145
+ public function getMethodInjections()
146
+ {
147
+ // Return array leafs
148
+ $injections = [];
149
+ array_walk_recursive($this->methodInjections, function ($injection) use (&$injections) {
150
+ $injections[] = $injection;
151
+ });;
152
+ return $injections;
153
+ }
154
+
155
+ /**
156
+ * @param MethodInjection $methodInjection
157
+ */
158
+ public function addMethodInjection(MethodInjection $methodInjection)
159
+ {
160
+ $method = $methodInjection->getMethodName();
161
+ if (! isset($this->methodInjections[$method])) {
162
+ $this->methodInjections[$method] = [];
163
+ }
164
+ $this->methodInjections[$method][] = $methodInjection;
165
+ }
166
+
167
+ /**
168
+ * @param string $scope
169
+ */
170
+ public function setScope($scope)
171
+ {
172
+ $this->scope = $scope;
173
+ }
174
+
175
+ /**
176
+ * {@inheritdoc}
177
+ */
178
+ public function getScope()
179
+ {
180
+ return $this->scope ?: Scope::SINGLETON;
181
+ }
182
+
183
+ /**
184
+ * @param boolean|null $lazy
185
+ */
186
+ public function setLazy($lazy)
187
+ {
188
+ $this->lazy = $lazy;
189
+ }
190
+
191
+ /**
192
+ * @return bool
193
+ */
194
+ public function isLazy()
195
+ {
196
+ if ($this->lazy !== null) {
197
+ return $this->lazy;
198
+ } else {
199
+ // Default value
200
+ return false;
201
+ }
202
+ }
203
+
204
+ /**
205
+ * {@inheritdoc}
206
+ */
207
+ public function getSubDefinitionName()
208
+ {
209
+ return $this->getClassName();
210
+ }
211
+
212
+ /**
213
+ * {@inheritdoc}
214
+ */
215
+ public function setSubDefinition(Definition $definition)
216
+ {
217
+ if (! $definition instanceof ObjectDefinition) {
218
+ throw new DefinitionException(sprintf(
219
+ "Container entry '%s' extends entry '%s' which is not an object",
220
+ $this->getName(),
221
+ $definition->getName()
222
+ ));
223
+ }
224
+
225
+ // The current prevails
226
+ if ($this->className === null) {
227
+ $this->className = $definition->className;
228
+ }
229
+ if ($this->scope === null) {
230
+ $this->scope = $definition->scope;
231
+ }
232
+ if ($this->lazy === null) {
233
+ $this->lazy = $definition->lazy;
234
+ }
235
+
236
+ // Merge constructor injection
237
+ $this->mergeConstructorInjection($definition);
238
+
239
+ // Merge property injections
240
+ $this->mergePropertyInjections($definition);
241
+
242
+ // Merge method injections
243
+ $this->mergeMethodInjections($definition);
244
+ }
245
+
246
+ private function mergeConstructorInjection(ObjectDefinition $definition)
247
+ {
248
+ if ($definition->getConstructorInjection() !== null) {
249
+ if ($this->constructorInjection !== null) {
250
+ // Merge
251
+ $this->constructorInjection->merge($definition->getConstructorInjection());
252
+ } else {
253
+ // Set
254
+ $this->constructorInjection = $definition->getConstructorInjection();
255
+ }
256
+ }
257
+ }
258
+
259
+ private function mergePropertyInjections(ObjectDefinition $definition)
260
+ {
261
+ foreach ($definition->getPropertyInjections() as $propertyName => $propertyInjection) {
262
+ if (! array_key_exists($propertyName, $this->propertyInjections)) {
263
+ // Add
264
+ $this->propertyInjections[$propertyName] = $propertyInjection;
265
+ }
266
+ }
267
+ }
268
+
269
+ private function mergeMethodInjections(ObjectDefinition $definition)
270
+ {
271
+ foreach ($definition->methodInjections as $methodName => $calls) {
272
+ if (array_key_exists($methodName, $this->methodInjections)) {
273
+ $this->mergeMethodCalls($calls, $methodName);
274
+ } else {
275
+ // Add
276
+ $this->methodInjections[$methodName] = $calls;
277
+ }
278
+ }
279
+ }
280
+
281
+ private function mergeMethodCalls(array $calls, $methodName)
282
+ {
283
+ foreach ($calls as $index => $methodInjection) {
284
+ // Merge
285
+ if (array_key_exists($index, $this->methodInjections[$methodName])) {
286
+ // Merge
287
+ $this->methodInjections[$methodName][$index]->merge($methodInjection);
288
+ } else {
289
+ // Add
290
+ $this->methodInjections[$methodName][$index] = $methodInjection;
291
+ }
292
+ }
293
+ }
294
+ }
addons/inc/Dependencies/DI/Definition/ObjectDefinition/MethodInjection.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\ObjectDefinition;
11
+
12
+ use Cybot\Dependencies\DI\Definition\AbstractFunctionCallDefinition;
13
+
14
+ /**
15
+ * Describe an injection in an object method.
16
+ *
17
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
18
+ */
19
+ class MethodInjection extends AbstractFunctionCallDefinition
20
+ {
21
+ /**
22
+ * @var string
23
+ */
24
+ private $methodName;
25
+
26
+ /**
27
+ * @param string $methodName
28
+ * @param array $parameters
29
+ */
30
+ public function __construct($methodName, array $parameters = [])
31
+ {
32
+ $this->methodName = (string) $methodName;
33
+ $this->parameters = $parameters;
34
+ }
35
+
36
+ public static function constructor(array $parameters = [])
37
+ {
38
+ return new self('__construct', $parameters);
39
+ }
40
+
41
+ /**
42
+ * @return string Method name
43
+ */
44
+ public function getMethodName()
45
+ {
46
+ return $this->methodName;
47
+ }
48
+
49
+ public function merge(MethodInjection $definition)
50
+ {
51
+ // In case of conflicts, the current definition prevails.
52
+ $this->parameters = $this->parameters + $definition->parameters;
53
+ }
54
+ }
addons/inc/Dependencies/DI/Definition/ObjectDefinition/PropertyInjection.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\ObjectDefinition;
11
+
12
+ /**
13
+ * Describe an injection in a class property.
14
+ *
15
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
16
+ */
17
+ class PropertyInjection
18
+ {
19
+ /**
20
+ * Property name
21
+ * @var string
22
+ */
23
+ private $propertyName;
24
+
25
+ /**
26
+ * Value that should be injected in the property
27
+ * @var mixed
28
+ */
29
+ private $value;
30
+
31
+ /**
32
+ * @param string $propertyName Property name
33
+ * @param mixed $value Value that should be injected in the property
34
+ */
35
+ public function __construct($propertyName, $value)
36
+ {
37
+ $this->propertyName = (string) $propertyName;
38
+ $this->value = $value;
39
+ }
40
+
41
+ /**
42
+ * @return string Property name
43
+ */
44
+ public function getPropertyName()
45
+ {
46
+ return $this->propertyName;
47
+ }
48
+
49
+ /**
50
+ * @return string Value that should be injected in the property
51
+ */
52
+ public function getValue()
53
+ {
54
+ return $this->value;
55
+ }
56
+ }
addons/inc/Dependencies/DI/Definition/Resolver/AliasResolver.php ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://mnapoli.github.com/PHP-DI/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Resolver;
11
+
12
+ use Cybot\Dependencies\DI\Definition\AliasDefinition;
13
+ use Cybot\Dependencies\DI\Definition\Definition;
14
+ use Cybot\Dependencies\Interop\Container\ContainerInterface;
15
+
16
+ /**
17
+ * Resolves an alias definition to a value.
18
+ *
19
+ * @since 4.0
20
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
21
+ */
22
+ class AliasResolver implements DefinitionResolver
23
+ {
24
+ /**
25
+ * @var ContainerInterface
26
+ */
27
+ private $container;
28
+
29
+ /**
30
+ * The resolver needs a container.
31
+ * This container will be used to get the entry to which the alias points to.
32
+ *
33
+ * @param ContainerInterface $container
34
+ */
35
+ public function __construct(ContainerInterface $container)
36
+ {
37
+ $this->container = $container;
38
+ }
39
+
40
+ /**
41
+ * Resolve an alias definition to a value.
42
+ *
43
+ * This will return the entry the alias points to.
44
+ *
45
+ * @param AliasDefinition $definition
46
+ *
47
+ * {@inheritdoc}
48
+ */
49
+ public function resolve(Definition $definition, array $parameters = [])
50
+ {
51
+ $this->assertIsAliasDefinition($definition);
52
+
53
+ return $this->container->get($definition->getTargetEntryName());
54
+ }
55
+
56
+ /**
57
+ * @param AliasDefinition $definition
58
+ *
59
+ * {@inheritdoc}
60
+ */
61
+ public function isResolvable(Definition $definition, array $parameters = [])
62
+ {
63
+ $this->assertIsAliasDefinition($definition);
64
+
65
+ return $this->container->has($definition->getTargetEntryName());
66
+ }
67
+
68
+ private function assertIsAliasDefinition(Definition $definition)
69
+ {
70
+ if (!$definition instanceof AliasDefinition) {
71
+ throw new \InvalidArgumentException(sprintf(
72
+ 'This definition resolver is only compatible with AliasDefinition objects, %s given',
73
+ get_class($definition)
74
+ ));
75
+ }
76
+ }
77
+ }
addons/inc/Dependencies/DI/Definition/Resolver/ArrayResolver.php ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://mnapoli.github.com/PHP-DI/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Resolver;
11
+
12
+ use Cybot\Dependencies\DI\Definition\ArrayDefinition;
13
+ use Cybot\Dependencies\DI\Definition\Definition;
14
+ use Cybot\Dependencies\DI\Definition\Helper\DefinitionHelper;
15
+ use Cybot\Dependencies\DI\DependencyException;
16
+ use Exception;
17
+
18
+ /**
19
+ * Resolves an array definition to a value.
20
+ *
21
+ * @since 5.0
22
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
23
+ */
24
+ class ArrayResolver implements DefinitionResolver
25
+ {
26
+ /**
27
+ * @var DefinitionResolver
28
+ */
29
+ private $definitionResolver;
30
+
31
+ /**
32
+ * @param DefinitionResolver $definitionResolver Used to resolve nested definitions.
33
+ */
34
+ public function __construct(DefinitionResolver $definitionResolver)
35
+ {
36
+ $this->definitionResolver = $definitionResolver;
37
+ }
38
+
39
+ /**
40
+ * Resolve an array definition to a value.
41
+ *
42
+ * An array definition can contain simple values or references to other entries.
43
+ *
44
+ * @param ArrayDefinition $definition
45
+ *
46
+ * {@inheritdoc}
47
+ */
48
+ public function resolve(Definition $definition, array $parameters = [])
49
+ {
50
+ $this->assertIsArrayDefinition($definition);
51
+
52
+ $values = $definition->getValues();
53
+
54
+ $values = $this->resolveNestedDefinitions($definition, $values);
55
+
56
+ return $values;
57
+ }
58
+
59
+ /**
60
+ * {@inheritdoc}
61
+ */
62
+ public function isResolvable(Definition $definition, array $parameters = [])
63
+ {
64
+ $this->assertIsArrayDefinition($definition);
65
+
66
+ return true;
67
+ }
68
+
69
+ private function assertIsArrayDefinition(Definition $definition)
70
+ {
71
+ if (!$definition instanceof ArrayDefinition) {
72
+ throw new \InvalidArgumentException(sprintf(
73
+ 'This definition resolver is only compatible with ArrayDefinition objects, %s given',
74
+ get_class($definition)
75
+ ));
76
+ }
77
+ }
78
+
79
+ private function resolveNestedDefinitions(ArrayDefinition $definition, array $values)
80
+ {
81
+ foreach ($values as $key => $value) {
82
+ if ($value instanceof DefinitionHelper) {
83
+ $values[$key] = $this->resolveDefinition($value, $definition, $key);
84
+ }
85
+ }
86
+
87
+ return $values;
88
+ }
89
+
90
+ private function resolveDefinition(DefinitionHelper $value, ArrayDefinition $definition, $key)
91
+ {
92
+ try {
93
+ return $this->definitionResolver->resolve($value->getDefinition(''));
94
+ } catch (DependencyException $e) {
95
+ throw $e;
96
+ } catch (Exception $e) {
97
+ throw new DependencyException(sprintf(
98
+ "Error while resolving %s[%s]. %s",
99
+ $definition->getName(),
100
+ $key,
101
+ $e->getMessage()
102
+ ), 0, $e);
103
+ }
104
+ }
105
+ }
addons/inc/Dependencies/DI/Definition/Resolver/DecoratorResolver.php ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://mnapoli.github.com/PHP-DI/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Resolver;
11
+
12
+ use Cybot\Dependencies\DI\Definition\DecoratorDefinition;
13
+ use Cybot\Dependencies\DI\Definition\Exception\DefinitionException;
14
+ use Cybot\Dependencies\DI\Definition\Definition;
15
+ use Cybot\Dependencies\Interop\Container\ContainerInterface;
16
+
17
+ /**
18
+ * Resolves a decorator definition to a value.
19
+ *
20
+ * @since 5.0
21
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
22
+ */
23
+ class DecoratorResolver implements DefinitionResolver
24
+ {
25
+ /**
26
+ * @var ContainerInterface
27
+ */
28
+ private $container;
29
+
30
+ /**
31
+ * @var DefinitionResolver
32
+ */
33
+ private $definitionResolver;
34
+
35
+ /**
36
+ * The resolver needs a container. This container will be passed to the factory as a parameter
37
+ * so that the factory can access other entries of the container.
38
+ *
39
+ * @param ContainerInterface $container
40
+ * @param DefinitionResolver $definitionResolver Used to resolve nested definitions.
41
+ */
42
+ public function __construct(ContainerInterface $container, DefinitionResolver $definitionResolver)
43
+ {
44
+ $this->container = $container;
45
+ $this->definitionResolver = $definitionResolver;
46
+ }
47
+
48
+ /**
49
+ * Resolve a decorator definition to a value.
50
+ *
51
+ * This will call the callable of the definition and pass it the decorated entry.
52
+ *
53
+ * @param DecoratorDefinition $definition
54
+ *
55
+ * {@inheritdoc}
56
+ */
57
+ public function resolve(Definition $definition, array $parameters = [])
58
+ {
59
+ $this->assertIsDecoratorDefinition($definition);
60
+
61
+ $callable = $definition->getCallable();
62
+
63
+ if (! is_callable($callable)) {
64
+ throw new DefinitionException(sprintf(
65
+ 'The decorator "%s" is not callable',
66
+ $definition->getName()
67
+ ));
68
+ }
69
+
70
+ $decoratedDefinition = $definition->getDecoratedDefinition();
71
+
72
+ if (! $decoratedDefinition instanceof Definition) {
73
+ if (! $definition->getSubDefinitionName()) {
74
+ throw new DefinitionException('Decorators cannot be nested in another definition');
75
+ }
76
+
77
+ throw new DefinitionException(sprintf(
78
+ 'Entry "%s" decorates nothing: no previous definition with the same name was found',
79
+ $definition->getName()
80
+ ));
81
+ }
82
+
83
+ $decorated = $this->definitionResolver->resolve($decoratedDefinition);
84
+
85
+ return call_user_func($callable, $decorated, $this->container);
86
+ }
87
+
88
+ /**
89
+ * {@inheritdoc}
90
+ */
91
+ public function isResolvable(Definition $definition, array $parameters = [])
92
+ {
93
+ $this->assertIsDecoratorDefinition($definition);
94
+
95
+ return true;
96
+ }
97
+
98
+ private function assertIsDecoratorDefinition(Definition $definition)
99
+ {
100
+ if (!$definition instanceof DecoratorDefinition) {
101
+ throw new \InvalidArgumentException(sprintf(
102
+ 'This definition resolver is only compatible with DecoratorDefinition objects, %s given',
103
+ get_class($definition)
104
+ ));
105
+ }
106
+ }
107
+ }
addons/inc/Dependencies/DI/Definition/Resolver/DefinitionResolver.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://mnapoli.github.com/PHP-DI/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Resolver;
11
+
12
+ use Cybot\Dependencies\DI\Definition\Definition;
13
+ use Cybot\Dependencies\DI\Definition\Exception\DefinitionException;
14
+
15
+ /**
16
+ * Resolves a definition to a value.
17
+ *
18
+ * @since 4.0
19
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
20
+ */
21
+ interface DefinitionResolver
22
+ {
23
+ /**
24
+ * Resolve a definition to a value.
25
+ *
26
+ * @param Definition $definition Object that defines how the value should be obtained.
27
+ * @param array $parameters Optional parameters to use to build the entry.
28
+ *
29
+ * @throws DefinitionException If the definition cannot be resolved.
30
+ *
31
+ * @return mixed Value obtained from the definition.
32
+ */
33
+ public function resolve(Definition $definition, array $parameters = []);
34
+
35
+ /**
36
+ * Check if a definition can be resolved.
37
+ *
38
+ * @param Definition $definition Object that defines how the value should be obtained.
39
+ * @param array $parameters Optional parameters to use to build the entry.
40
+ *
41
+ * @return bool
42
+ */
43
+ public function isResolvable(Definition $definition, array $parameters = []);
44
+ }
addons/inc/Dependencies/DI/Definition/Resolver/EnvironmentVariableResolver.php ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://mnapoli.github.com/PHP-DI/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Resolver;
11
+
12
+ use Cybot\Dependencies\DI\Definition\Definition;
13
+ use Cybot\Dependencies\DI\Definition\EnvironmentVariableDefinition;
14
+ use Cybot\Dependencies\DI\Definition\Exception\DefinitionException;
15
+ use Cybot\Dependencies\DI\Definition\Helper\DefinitionHelper;
16
+
17
+ /**
18
+ * Resolves a environment variable definition to a value.
19
+ *
20
+ * @author James Harris <james.harris@icecave.com.au>
21
+ */
22
+ class EnvironmentVariableResolver implements DefinitionResolver
23
+ {
24
+ /**
25
+ * @var DefinitionResolver
26
+ */
27
+ private $definitionResolver;
28
+
29
+ /**
30
+ * @var callable
31
+ */
32
+ private $variableReader;
33
+
34
+ public function __construct(DefinitionResolver $definitionResolver, $variableReader = 'getenv')
35
+ {
36
+ $this->definitionResolver = $definitionResolver;
37
+ $this->variableReader = $variableReader;
38
+ }
39
+
40
+ /**
41
+ * Resolve an environment variable definition to a value.
42
+ *
43
+ * @param EnvironmentVariableDefinition $definition
44
+ *
45
+ * {@inheritdoc}
46
+ */
47
+ public function resolve(Definition $definition, array $parameters = [])
48
+ {
49
+ $this->assertIsEnvironmentVariableDefinition($definition);
50
+
51
+ $value = call_user_func($this->variableReader, $definition->getVariableName());
52
+
53
+ if (false !== $value) {
54
+ return $value;
55
+ } elseif (!$definition->isOptional()) {
56
+ throw new DefinitionException(sprintf(
57
+ "The environment variable '%s' has not been defined",
58
+ $definition->getVariableName()
59
+ ));
60
+ }
61
+
62
+ $value = $definition->getDefaultValue();
63
+
64
+ // Nested definition
65
+ if ($value instanceof DefinitionHelper) {
66
+ return $this->definitionResolver->resolve($value->getDefinition(''));
67
+ }
68
+
69
+ return $value;
70
+ }
71
+
72
+ /**
73
+ * @param EnvironmentVariableDefinition $definition
74
+ *
75
+ * {@inheritdoc}
76
+ */
77
+ public function isResolvable(Definition $definition, array $parameters = [])
78
+ {
79
+ $this->assertIsEnvironmentVariableDefinition($definition);
80
+
81
+ return $definition->isOptional()
82
+ || false !== call_user_func($this->variableReader, $definition->getVariableName());
83
+ }
84
+
85
+ private function assertIsEnvironmentVariableDefinition(Definition $definition)
86
+ {
87
+ if (!$definition instanceof EnvironmentVariableDefinition) {
88
+ throw new \InvalidArgumentException(sprintf(
89
+ 'This definition resolver is only compatible with EnvironmentVariableDefinition objects, %s given',
90
+ get_class($definition)
91
+ ));
92
+ }
93
+ }
94
+ }
addons/inc/Dependencies/DI/Definition/Resolver/FactoryResolver.php ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://mnapoli.github.com/PHP-DI/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Resolver;
11
+
12
+ use Cybot\Dependencies\DI\Definition\Exception\DefinitionException;
13
+ use Cybot\Dependencies\DI\Definition\FactoryDefinition;
14
+ use Cybot\Dependencies\DI\Definition\Definition;
15
+ use Cybot\Dependencies\Interop\Container\ContainerInterface;
16
+
17
+ /**
18
+ * Resolves a factory definition to a value.
19
+ *
20
+ * @since 4.0
21
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
22
+ */
23
+ class FactoryResolver implements DefinitionResolver
24
+ {
25
+ /**
26
+ * @var ContainerInterface
27
+ */
28
+ private $container;
29
+
30
+ /**
31
+ * The resolver needs a container. This container will be passed to the factory as a parameter
32
+ * so that the factory can access other entries of the container.
33
+ *
34
+ * @param ContainerInterface $container
35
+ */
36
+ public function __construct(ContainerInterface $container)
37
+ {
38
+ $this->container = $container;
39
+ }
40
+
41
+ /**
42
+ * Resolve a factory definition to a value.
43
+ *
44
+ * This will call the callable of the definition.
45
+ *
46
+ * @param FactoryDefinition $definition
47
+ *
48
+ * {@inheritdoc}
49
+ */
50
+ public function resolve(Definition $definition, array $parameters = [])
51
+ {
52
+ $this->assertIsFactoryDefinition($definition);
53
+
54
+ $callable = $definition->getCallable();
55
+
56
+ if (! is_callable($callable)) {
57
+ throw new DefinitionException(sprintf(
58
+ 'The factory definition "%s" is not callable',
59
+ $definition->getName()
60
+ ));
61
+ }
62
+
63
+ return call_user_func($callable, $this->container);
64
+ }
65
+
66
+ /**
67
+ * {@inheritdoc}
68
+ */
69
+ public function isResolvable(Definition $definition, array $parameters = [])
70
+ {
71
+ $this->assertIsFactoryDefinition($definition);
72
+
73
+ return true;
74
+ }
75
+
76
+ private function assertIsFactoryDefinition(Definition $definition)
77
+ {
78
+ if (!$definition instanceof FactoryDefinition) {
79
+ throw new \InvalidArgumentException(sprintf(
80
+ 'This definition resolver is only compatible with FactoryDefinition objects, %s given',
81
+ get_class($definition)
82
+ ));
83
+ }
84
+ }
85
+ }
addons/inc/Dependencies/DI/Definition/Resolver/InstanceInjector.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://mnapoli.github.com/PHP-DI/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Resolver;
11
+
12
+ use Cybot\Dependencies\DI\Definition\Definition;
13
+ use Cybot\Dependencies\DI\Definition\InstanceDefinition;
14
+ use Cybot\Dependencies\DI\DependencyException;
15
+ use Cybot\Dependencies\Interop\Container\Exception\NotFoundException;
16
+
17
+ /**
18
+ * Injects dependencies on an existing instance.
19
+ *
20
+ * @since 5.0
21
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
22
+ */
23
+ class InstanceInjector extends ObjectCreator
24
+ {
25
+ /**
26
+ * Injects dependencies on an existing instance.
27
+ *
28
+ * @param InstanceDefinition $definition
29
+ *
30
+ * {@inheritdoc}
31
+ */
32
+ public function resolve(Definition $definition, array $parameters = [])
33
+ {
34
+ $this->assertIsInstanceDefinition($definition);
35
+
36
+ try {
37
+ $this->injectMethodsAndProperties($definition->getInstance(), $definition->getObjectDefinition());
38
+ } catch (NotFoundException $e) {
39
+ $message = sprintf(
40
+ "Error while injecting dependencies into %s: %s",
41
+ get_class($definition->getInstance()),
42
+ $e->getMessage()
43
+ );
44
+ throw new DependencyException($message, 0, $e);
45
+ }
46
+ }
47
+
48
+ /**
49
+ * {@inheritdoc}
50
+ */
51
+ public function isResolvable(Definition $definition, array $parameters = [])
52
+ {
53
+ $this->assertIsInstanceDefinition($definition);
54
+
55
+ return true;
56
+ }
57
+
58
+ private function assertIsInstanceDefinition(Definition $definition)
59
+ {
60
+ if (!$definition instanceof InstanceDefinition) {
61
+ throw new \InvalidArgumentException(sprintf(
62
+ 'This definition resolver is only compatible with InstanceDefinition objects, %s given',
63
+ get_class($definition)
64
+ ));
65
+ }
66
+ }
67
+ }
addons/inc/Dependencies/DI/Definition/Resolver/ObjectCreator.php ADDED
@@ -0,0 +1,266 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://mnapoli.github.com/PHP-DI/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Resolver;
11
+
12
+ use Cybot\Dependencies\DI\Definition\ObjectDefinition;
13
+ use Cybot\Dependencies\DI\Definition\Definition;
14
+ use Cybot\Dependencies\DI\Definition\Exception\DefinitionException;
15
+ use Cybot\Dependencies\DI\Definition\ObjectDefinition\PropertyInjection;
16
+ use Cybot\Dependencies\DI\Definition\Helper\DefinitionHelper;
17
+ use Cybot\Dependencies\DI\DependencyException;
18
+ use Cybot\Dependencies\DI\Proxy\ProxyFactory;
19
+ use Exception;
20
+ use Cybot\Dependencies\Interop\Container\Exception\NotFoundException;
21
+ use ProxyManager\Proxy\LazyLoadingInterface;
22
+ use ReflectionClass;
23
+ use ReflectionProperty;
24
+
25
+ /**
26
+ * Create objects based on an object definition.
27
+ *
28
+ * @since 4.0
29
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
30
+ */
31
+ class ObjectCreator implements DefinitionResolver
32
+ {
33
+ /**
34
+ * @var ProxyFactory
35
+ */
36
+ private $proxyFactory;
37
+
38
+ /**
39
+ * @var ParameterResolver
40
+ */
41
+ private $parameterResolver;
42
+
43
+ /**
44
+ * @var DefinitionResolver
45
+ */
46
+ private $definitionResolver;
47
+
48
+ /**
49
+ * @param DefinitionResolver $definitionResolver Used to resolve nested definitions.
50
+ * @param ProxyFactory $proxyFactory Used to create proxies for lazy injections.
51
+ */
52
+ public function __construct(
53
+ DefinitionResolver $definitionResolver,
54
+ ProxyFactory $proxyFactory
55
+ ) {
56
+ $this->definitionResolver = $definitionResolver;
57
+ $this->proxyFactory = $proxyFactory;
58
+ $this->parameterResolver = new ParameterResolver($definitionResolver);
59
+ }
60
+
61
+ /**
62
+ * Resolve a class definition to a value.
63
+ *
64
+ * This will create a new instance of the class using the injections points defined.
65
+ *
66
+ * @param ObjectDefinition $definition
67
+ *
68
+ * {@inheritdoc}
69
+ */
70
+ public function resolve(Definition $definition, array $parameters = [])
71
+ {
72
+ $this->assertIsObjectDefinition($definition);
73
+
74
+ // Lazy?
75
+ if ($definition->isLazy()) {
76
+ return $this->createProxy($definition, $parameters);
77
+ }
78
+
79
+ return $this->createInstance($definition, $parameters);
80
+ }
81
+
82
+ /**
83
+ * The definition is not resolvable if the class is not instantiable (interface or abstract)
84
+ * or if the class doesn't exist.
85
+ *
86
+ * @param ObjectDefinition $definition
87
+ *
88
+ * {@inheritdoc}
89
+ */
90
+ public function isResolvable(Definition $definition, array $parameters = [])
91
+ {
92
+ $this->assertIsObjectDefinition($definition);
93
+
94
+ if (! class_exists($definition->getClassName())) {
95
+ return false;
96
+ }
97
+
98
+ $classReflection = new ReflectionClass($definition->getClassName());
99
+
100
+ return $classReflection->isInstantiable();
101
+ }
102
+
103
+ /**
104
+ * Returns a proxy instance
105
+ *
106
+ * @param ObjectDefinition $definition
107
+ * @param array $parameters
108
+ *
109
+ * @return LazyLoadingInterface Proxy instance
110
+ */
111
+ private function createProxy(ObjectDefinition $definition, array $parameters)
112
+ {
113
+ /** @noinspection PhpUnusedParameterInspection */
114
+ $proxy = $this->proxyFactory->createProxy(
115
+ $definition->getClassName(),
116
+ function (& $wrappedObject, $proxy, $method, $params, & $initializer) use ($definition, $parameters) {
117
+ $wrappedObject = $this->createInstance($definition, $parameters);
118
+ $initializer = null; // turning off further lazy initialization
119
+ return true;
120
+ }
121
+ );
122
+
123
+ return $proxy;
124
+ }
125
+
126
+ /**
127
+ * Creates an instance of the class and injects dependencies..
128
+ *
129
+ * @param ObjectDefinition $definition
130
+ * @param array $parameters Optional parameters to use to create the instance.
131
+ *
132
+ * @throws DefinitionException
133
+ * @throws DependencyException
134
+ * @return object
135
+ */
136
+ private function createInstance(ObjectDefinition $definition, array $parameters)
137
+ {
138
+ $this->assertClassExists($definition);
139
+
140
+ $classReflection = new ReflectionClass($definition->getClassName());
141
+
142
+ $this->assertClassIsInstantiable($definition, $classReflection);
143
+
144
+ $constructorInjection = $definition->getConstructorInjection();
145
+
146
+ try {
147
+ $args = $this->parameterResolver->resolveParameters(
148
+ $constructorInjection,
149
+ $classReflection->getConstructor(),
150
+ $parameters
151
+ );
152
+
153
+ if (count($args) > 0) {
154
+ $object = $classReflection->newInstanceArgs($args);
155
+ } else {
156
+ $object = $classReflection->newInstance();
157
+ }
158
+
159
+ $this->injectMethodsAndProperties($object, $definition);
160
+ } catch (NotFoundException $e) {
161
+ throw new DependencyException(sprintf(
162
+ "Error while injecting dependencies into %s: %s",
163
+ $classReflection->getName(),
164
+ $e->getMessage()
165
+ ), 0, $e);
166
+ } catch (DefinitionException $e) {
167
+ throw DefinitionException::create($definition, sprintf(
168
+ "Entry %s cannot be resolved: %s",
169
+ $definition->getName(),
170
+ $e->getMessage()
171
+ ));
172
+ }
173
+
174
+ return $object;
175
+ }
176
+
177
+ protected function injectMethodsAndProperties($object, ObjectDefinition $objectDefinition)
178
+ {
179
+ // Property injections
180
+ foreach ($objectDefinition->getPropertyInjections() as $propertyInjection) {
181
+ $this->injectProperty($object, $propertyInjection);
182
+ }
183
+
184
+ // Method injections
185
+ foreach ($objectDefinition->getMethodInjections() as $methodInjection) {
186
+ $methodReflection = new \ReflectionMethod($object, $methodInjection->getMethodName());
187
+ $args = $this->parameterResolver->resolveParameters($methodInjection, $methodReflection);
188
+
189
+ $methodReflection->invokeArgs($object, $args);
190
+ }
191
+ }
192
+
193
+ /**
194
+ * Inject dependencies into properties.
195
+ *
196
+ * @param object $object Object to inject dependencies into
197
+ * @param PropertyInjection $propertyInjection Property injection definition
198
+ *
199
+ * @throws DependencyException
200
+ * @throws DefinitionException
201
+ */
202
+ private function injectProperty($object, PropertyInjection $propertyInjection)
203
+ {
204
+ $propertyName = $propertyInjection->getPropertyName();
205
+ $property = new ReflectionProperty(get_class($object), $propertyName);
206
+
207
+ $value = $propertyInjection->getValue();
208
+
209
+ if ($value instanceof DefinitionHelper) {
210
+ /** @var Definition $nestedDefinition */
211
+ $nestedDefinition = $value->getDefinition('');
212
+
213
+ try {
214
+ $value = $this->definitionResolver->resolve($nestedDefinition);
215
+ } catch (DependencyException $e) {
216
+ throw $e;
217
+ } catch (Exception $e) {
218
+ throw new DependencyException(sprintf(
219
+ "Error while injecting in %s::%s. %s",
220
+ get_class($object),
221
+ $propertyName,
222
+ $e->getMessage()
223
+ ), 0, $e);
224
+ }
225
+ }
226
+
227
+ if (! $property->isPublic()) {
228
+ $property->setAccessible(true);
229
+ }
230
+ $property->setValue($object, $value);
231
+ }
232
+
233
+ private function assertIsObjectDefinition(Definition $definition)
234
+ {
235
+ if (!$definition instanceof ObjectDefinition) {
236
+ throw new \InvalidArgumentException(sprintf(
237
+ 'This definition resolver is only compatible with ObjectDefinition objects, %s given',
238
+ get_class($definition)
239
+ ));
240
+ }
241
+ }
242
+
243
+ private function assertClassExists(ObjectDefinition $definition)
244
+ {
245
+ if (!class_exists($definition->getClassName()) && !interface_exists($definition->getClassName())) {
246
+ throw DefinitionException::create($definition,
247
+ sprintf(
248
+ "Entry %s cannot be resolved: class %s doesn't exist",
249
+ $definition->getName(),
250
+ $definition->getClassName()
251
+ ));
252
+ }
253
+ }
254
+
255
+ private function assertClassIsInstantiable(ObjectDefinition $definition, ReflectionClass $classReflection)
256
+ {
257
+ if (!$classReflection->isInstantiable()) {
258
+ throw DefinitionException::create($definition,
259
+ sprintf(
260
+ "Entry %s cannot be resolved: class %s is not instantiable",
261
+ $definition->getName(),
262
+ $definition->getClassName()
263
+ ));
264
+ }
265
+ }
266
+ }
addons/inc/Dependencies/DI/Definition/Resolver/ParameterResolver.php ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://mnapoli.github.com/PHP-DI/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Resolver;
11
+
12
+ use Cybot\Dependencies\DI\Definition\AbstractFunctionCallDefinition;
13
+ use Cybot\Dependencies\DI\Definition\ObjectDefinition;
14
+ use Cybot\Dependencies\DI\Definition\Exception\DefinitionException;
15
+ use Cybot\Dependencies\DI\Definition\Helper\DefinitionHelper;
16
+
17
+ /**
18
+ * Resolves parameters for a function call.
19
+ *
20
+ * @since 4.2
21
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
22
+ */
23
+ class ParameterResolver
24
+ {
25
+ /**
26
+ * @var DefinitionResolver
27
+ */
28
+ private $definitionResolver;
29
+
30
+ /**
31
+ * @param DefinitionResolver $definitionResolver Will be used to resolve nested definitions.
32
+ */
33
+ public function __construct(DefinitionResolver $definitionResolver)
34
+ {
35
+ $this->definitionResolver = $definitionResolver;
36
+ }
37
+
38
+ /**
39
+ * @param AbstractFunctionCallDefinition $definition
40
+ * @param \ReflectionFunctionAbstract $functionReflection
41
+ * @param array $parameters
42
+ *
43
+ * @throws DefinitionException A parameter has no value defined or guessable.
44
+ * @return array Parameters to use to call the function.
45
+ */
46
+ public function resolveParameters(
47
+ AbstractFunctionCallDefinition $definition = null,
48
+ \ReflectionFunctionAbstract $functionReflection = null,
49
+ array $parameters = []
50
+ ) {
51
+ $args = [];
52
+
53
+ if (! $functionReflection) {
54
+ return $args;
55
+ }
56
+
57
+ foreach ($functionReflection->getParameters() as $index => $parameter) {
58
+ if (array_key_exists($parameter->getName(), $parameters)) {
59
+ // Look in the $parameters array
60
+ $value = $parameters[$parameter->getName()];
61
+ } elseif ($definition && $definition->hasParameter($index)) {
62
+ // Look in the definition
63
+ $value = $definition->getParameter($index);
64
+ } else {
65
+ // If the parameter is optional and wasn't specified, we take its default value
66
+ if ($parameter->isOptional()) {
67
+ $args[] = $this->getParameterDefaultValue($parameter, $functionReflection);
68
+ continue;
69
+ }
70
+
71
+ throw new DefinitionException(sprintf(
72
+ "The parameter '%s' of %s has no value defined or guessable",
73
+ $parameter->getName(),
74
+ $this->getFunctionName($functionReflection)
75
+ ));
76
+ }
77
+
78
+ if ($value instanceof DefinitionHelper) {
79
+ $nestedDefinition = $value->getDefinition('');
80
+
81
+ // If the container cannot produce the entry, we can use the default parameter value
82
+ if (!$this->definitionResolver->isResolvable($nestedDefinition) && $parameter->isOptional()) {
83
+ $value = $this->getParameterDefaultValue($parameter, $functionReflection);
84
+ } else {
85
+ $value = $this->definitionResolver->resolve($nestedDefinition);
86
+ }
87
+ }
88
+
89
+ $args[] = $value;
90
+ }
91
+
92
+ return $args;
93
+ }
94
+
95
+ /**
96
+ * Returns the default value of a function parameter.
97
+ *
98
+ * @param \ReflectionParameter $parameter
99
+ * @param \ReflectionFunctionAbstract $function
100
+ *
101
+ * @throws DefinitionException Can't get default values from PHP internal classes and functions
102
+ * @return mixed
103
+ */
104
+ private function getParameterDefaultValue(
105
+ \ReflectionParameter $parameter,
106
+ \ReflectionFunctionAbstract $function
107
+ ) {
108
+ try {
109
+ return $parameter->getDefaultValue();
110
+ } catch (\ReflectionException $e) {
111
+ throw new DefinitionException(sprintf(
112
+ "The parameter '%s' of %s has no type defined or guessable. It has a default value, "
113
+ . "but the default value can't be read through Reflection because it is a PHP internal class.",
114
+ $parameter->getName(),
115
+ $this->getFunctionName($function)
116
+ ));
117
+ }
118
+ }
119
+
120
+ private function getFunctionName(\ReflectionFunctionAbstract $reflectionFunction)
121
+ {
122
+ if ($reflectionFunction instanceof \ReflectionMethod) {
123
+ return sprintf(
124
+ '%s::%s',
125
+ $reflectionFunction->getDeclaringClass()->getName(),
126
+ $reflectionFunction->getName()
127
+ );
128
+ } elseif ($reflectionFunction->isClosure()) {
129
+ return sprintf(
130
+ 'closure defined in %s at line %d',
131
+ $reflectionFunction->getFileName(),
132
+ $reflectionFunction->getStartLine()
133
+ );
134
+ }
135
+
136
+ return $reflectionFunction->getName();
137
+ }
138
+ }
addons/inc/Dependencies/DI/Definition/Resolver/ResolverDispatcher.php ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Cybot\Dependencies\DI\Definition\Resolver;
4
+
5
+ use Cybot\Dependencies\DI\Definition\Definition;
6
+ use Cybot\Dependencies\DI\Definition\Exception\DefinitionException;
7
+ use Cybot\Dependencies\DI\Proxy\ProxyFactory;
8
+ use Cybot\Dependencies\Interop\Container\ContainerInterface;
9
+
10
+ /**
11
+ * Dispatches to more specific resolvers.
12
+ *
13
+ * Dynamic dispatch pattern.
14
+ *
15
+ * @since 5.0
16
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
17
+ */
18
+ class ResolverDispatcher implements DefinitionResolver
19
+ {
20
+ /**
21
+ * @var ContainerInterface
22
+ */
23
+ private $container;
24
+
25
+ /**
26
+ * @var ProxyFactory
27
+ */
28
+ private $proxyFactory;
29
+
30
+ private $valueResolver;
31
+ private $arrayResolver;
32
+ private $factoryResolver;
33
+ private $decoratorResolver;
34
+ private $aliasResolver;
35
+ private $objectResolver;
36
+ private $instanceResolver;
37
+ private $envVariableResolver;
38
+ private $stringResolver;
39
+
40
+ public function __construct(ContainerInterface $container, ProxyFactory $proxyFactory)
41
+ {
42
+ $this->container = $container;
43
+ $this->proxyFactory = $proxyFactory;
44
+ }
45
+
46
+ /**
47
+ * Resolve a definition to a value.
48
+ *
49
+ * @param Definition $definition Object that defines how the value should be obtained.
50
+ * @param array $parameters Optional parameters to use to build the entry.
51
+ *
52
+ * @throws DefinitionException If the definition cannot be resolved.
53
+ *
54
+ * @return mixed Value obtained from the definition.
55
+ */
56
+ public function resolve(Definition $definition, array $parameters = [])
57
+ {
58
+ $definitionResolver = $this->getDefinitionResolver($definition);
59
+
60
+ return $definitionResolver->resolve($definition, $parameters);
61
+ }
62
+
63
+ /**
64
+ * Check if a definition can be resolved.
65
+ *
66
+ * @param Definition $definition Object that defines how the value should be obtained.
67
+ * @param array $parameters Optional parameters to use to build the entry.
68
+ *
69
+ * @return bool
70
+ */
71
+ public function isResolvable(Definition $definition, array $parameters = [])
72
+ {
73
+ $definitionResolver = $this->getDefinitionResolver($definition);
74
+
75
+ return $definitionResolver->isResolvable($definition, $parameters);
76
+ }
77
+
78
+ /**
79
+ * Returns a resolver capable of handling the given definition.
80
+ *
81
+ * @param Definition $definition
82
+ *
83
+ * @throws \RuntimeException No definition resolver was found for this type of definition.
84
+ * @return DefinitionResolver
85
+ */
86
+ private function getDefinitionResolver(Definition $definition)
87
+ {
88
+ $definitionType = get_class($definition);
89
+
90
+ switch ($definitionType) {
91
+ case 'Cybot\Dependencies\DI\Definition\ValueDefinition':
92
+ if (! $this->valueResolver) {
93
+ $this->valueResolver = new ValueResolver();
94
+ }
95
+ return $this->valueResolver;
96
+ case 'Cybot\Dependencies\DI\Definition\ArrayDefinition':
97
+ case 'Cybot\Dependencies\DI\Definition\ArrayDefinitionExtension':
98
+ if (! $this->arrayResolver) {
99
+ $this->arrayResolver = new ArrayResolver($this);
100
+ }
101
+ return $this->arrayResolver;
102
+ case 'Cybot\Dependencies\DI\Definition\FactoryDefinition':
103
+ if (! $this->factoryResolver) {
104
+ $this->factoryResolver = new FactoryResolver($this->container);
105
+ }
106
+ return $this->factoryResolver;
107
+ case 'Cybot\Dependencies\DI\Definition\DecoratorDefinition':
108
+ if (! $this->decoratorResolver) {
109
+ $this->decoratorResolver = new DecoratorResolver($this->container, $this);
110
+ }
111
+ return $this->decoratorResolver;
112
+ case 'Cybot\Dependencies\DI\Definition\AliasDefinition':
113
+ if (! $this->aliasResolver) {
114
+ $this->aliasResolver = new AliasResolver($this->container);
115
+ }
116
+ return $this->aliasResolver;
117
+ case 'Cybot\Dependencies\DI\Definition\ObjectDefinition':
118
+ if (! $this->objectResolver) {
119
+ $this->objectResolver = new ObjectCreator($this, $this->proxyFactory);
120
+ }
121
+ return $this->objectResolver;
122
+ case 'Cybot\Dependencies\DI\Definition\InstanceDefinition':
123
+ if (! $this->instanceResolver) {
124
+ $this->instanceResolver = new InstanceInjector($this, $this->proxyFactory);
125
+ }
126
+ return $this->instanceResolver;
127
+ case 'Cybot\Dependencies\DI\Definition\EnvironmentVariableDefinition':
128
+ if (! $this->envVariableResolver) {
129
+ $this->envVariableResolver = new EnvironmentVariableResolver($this);
130
+ }
131
+ return $this->envVariableResolver;
132
+ case 'Cybot\Dependencies\DI\Definition\StringDefinition':
133
+ if (! $this->stringResolver) {
134
+ $this->stringResolver = new StringResolver($this->container);
135
+ }
136
+ return $this->stringResolver;
137
+ default:
138
+ throw new \RuntimeException("No definition resolver was configured for definition of type $definitionType");
139
+ }
140
+ }
141
+ }
addons/inc/Dependencies/DI/Definition/Resolver/StringResolver.php ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://mnapoli.github.com/PHP-DI/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Resolver;
11
+
12
+ use Cybot\Dependencies\DI\Definition\Definition;
13
+ use Cybot\Dependencies\DI\Definition\StringDefinition;
14
+ use Cybot\Dependencies\DI\DependencyException;
15
+ use Cybot\Dependencies\DI\NotFoundException;
16
+ use Cybot\Dependencies\Interop\Container\ContainerInterface;
17
+
18
+ /**
19
+ * Resolves a string expression.
20
+ *
21
+ * @since 5.0
22
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
23
+ */
24
+ class StringResolver implements DefinitionResolver
25
+ {
26
+ /**
27
+ * @var ContainerInterface
28
+ */
29
+ private $container;
30
+
31
+ /**
32
+ * The resolver needs a container.
33
+ * This container will be used to get the entry to which the alias points to.
34
+ *
35
+ * @param ContainerInterface $container
36
+ */
37
+ public function __construct(ContainerInterface $container)
38
+ {
39
+ $this->container = $container;
40
+ }
41
+
42
+ /**
43
+ * Resolve a value definition to a value.
44
+ *
45
+ * A value definition is simple, so this will just return the value of the ValueDefinition.
46
+ *
47
+ * @param StringDefinition $definition
48
+ *
49
+ * {@inheritdoc}
50
+ */
51
+ public function resolve(Definition $definition, array $parameters = [])
52
+ {
53
+ $this->assertIsStringDefinition($definition);
54
+
55
+ $expression = $definition->getExpression();
56
+
57
+ $result = preg_replace_callback('#\{([^\{\}]+)\}#', function (array $matches) use ($definition) {
58
+ try {
59
+ return $this->container->get($matches[1]);
60
+ } catch (NotFoundException $e) {
61
+ throw new DependencyException(sprintf(
62
+ "Error while parsing string expression for entry '%s': %s",
63
+ $definition->getName(),
64
+ $e->getMessage()
65
+ ), 0, $e);
66
+ }
67
+ }, $expression);
68
+
69
+ if ($result === null) {
70
+ throw new \RuntimeException(sprintf('An unknown error occurred while parsing the string definition: \'%s\'', $expression));
71
+ }
72
+
73
+ return $result;
74
+ }
75
+
76
+ /**
77
+ * {@inheritdoc}
78
+ */
79
+ public function isResolvable(Definition $definition, array $parameters = [])
80
+ {
81
+ $this->assertIsStringDefinition($definition);
82
+
83
+ return true;
84
+ }
85
+
86
+ private function assertIsStringDefinition(Definition $definition)
87
+ {
88
+ if (!$definition instanceof StringDefinition) {
89
+ throw new \InvalidArgumentException(sprintf(
90
+ 'This definition resolver is only compatible with StringDefinition objects, %s given',
91
+ get_class($definition)
92
+ ));
93
+ }
94
+ }
95
+ }
addons/inc/Dependencies/DI/Definition/Resolver/ValueResolver.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://mnapoli.github.com/PHP-DI/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Resolver;
11
+
12
+ use Cybot\Dependencies\DI\Definition\Definition;
13
+ use Cybot\Dependencies\DI\Definition\ValueDefinition;
14
+
15
+ /**
16
+ * Resolves a value definition to a value.
17
+ *
18
+ * @since 4.0
19
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
20
+ */
21
+ class ValueResolver implements DefinitionResolver
22
+ {
23
+ /**
24
+ * Resolve a value definition to a value.
25
+ *
26
+ * A value definition is simple, so this will just return the value of the ValueDefinition.
27
+ *
28
+ * @param ValueDefinition $definition
29
+ *
30
+ * {@inheritdoc}
31
+ */
32
+ public function resolve(Definition $definition, array $parameters = [])
33
+ {
34
+ $this->assertIsValueDefinition($definition);
35
+
36
+ return $definition->getValue();
37
+ }
38
+
39
+ /**
40
+ * {@inheritdoc}
41
+ */
42
+ public function isResolvable(Definition $definition, array $parameters = [])
43
+ {
44
+ $this->assertIsValueDefinition($definition);
45
+
46
+ return true;
47
+ }
48
+
49
+ private function assertIsValueDefinition(Definition $definition)
50
+ {
51
+ if (!$definition instanceof ValueDefinition) {
52
+ throw new \InvalidArgumentException(sprintf(
53
+ 'This definition resolver is only compatible with ValueDefinition objects, %s given',
54
+ get_class($definition)
55
+ ));
56
+ }
57
+ }
58
+ }
addons/inc/Dependencies/DI/Definition/Source/AnnotationReader.php ADDED
@@ -0,0 +1,298 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Source;
11
+
12
+ use Cybot\Dependencies\DI\Annotation\Inject;
13
+ use Cybot\Dependencies\DI\Annotation\Injectable;
14
+ use Cybot\Dependencies\DI\Definition\ObjectDefinition;
15
+ use Cybot\Dependencies\DI\Definition\EntryReference;
16
+ use Cybot\Dependencies\DI\Definition\Exception\AnnotationException;
17
+ use Cybot\Dependencies\DI\Definition\Exception\DefinitionException;
18
+ use Cybot\Dependencies\DI\Definition\ObjectDefinition\MethodInjection;
19
+ use Cybot\Dependencies\DI\Definition\ObjectDefinition\PropertyInjection;
20
+ use Doctrine\Common\Annotations\AnnotationRegistry;
21
+ use Doctrine\Common\Annotations\Reader;
22
+ use Doctrine\Common\Annotations\SimpleAnnotationReader;
23
+ use InvalidArgumentException;
24
+ use Cybot\Dependencies\PhpDocReader\PhpDocReader;
25
+ use ReflectionClass;
26
+ use ReflectionMethod;
27
+ use ReflectionParameter;
28
+ use ReflectionProperty;
29
+ use UnexpectedValueException;
30
+
31
+ /**
32
+ * Provides DI definitions by reading annotations such as @ Inject and @ var annotations.
33
+ *
34
+ * Uses Autowiring, Doctrine's Annotations and regex docblock parsing.
35
+ * This source automatically includes the reflection source.
36
+ *
37
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
38
+ */
39
+ class AnnotationReader implements DefinitionSource
40
+ {
41
+ /**
42
+ * @var Reader
43
+ */
44
+ private $annotationReader;
45
+
46
+ /**
47
+ * @var PhpDocReader
48
+ */
49
+ private $phpDocReader;
50
+
51
+ /**
52
+ * @var bool
53
+ */
54
+ private $ignorePhpDocErrors;
55
+
56
+ /**
57
+ * @param bool $ignorePhpDocErrors
58
+ */
59
+ public function __construct($ignorePhpDocErrors = false)
60
+ {
61
+ $this->ignorePhpDocErrors = (bool) $ignorePhpDocErrors;
62
+ }
63
+
64
+ /**
65
+ * {@inheritdoc}
66
+ * @throws AnnotationException
67
+ * @throws InvalidArgumentException The class doesn't exist
68
+ */
69
+ public function getDefinition($name)
70
+ {
71
+ if (!class_exists($name) && !interface_exists($name)) {
72
+ return null;
73
+ }
74
+
75
+ $class = new ReflectionClass($name);
76
+ $definition = new ObjectDefinition($name);
77
+
78
+ $this->readInjectableAnnotation($class, $definition);
79
+
80
+ // Browse the class properties looking for annotated properties
81
+ $this->readProperties($class, $definition);
82
+
83
+ // Browse the object's methods looking for annotated methods
84
+ $this->readMethods($class, $definition);
85
+
86
+ return $definition;
87
+ }
88
+
89
+ /**
90
+ * Browse the class properties looking for annotated properties.
91
+ *
92
+ * @param ReflectionClass $reflectionClass
93
+ * @param ObjectDefinition $objectDefinition
94
+ */
95
+ private function readProperties(ReflectionClass $reflectionClass, ObjectDefinition $objectDefinition)
96
+ {
97
+ // This will look in all the properties, including those of the parent classes
98
+ foreach ($reflectionClass->getProperties() as $property) {
99
+ // Ignore static properties
100
+ if ($property->isStatic()) {
101
+ continue;
102
+ }
103
+
104
+ $propertyInjection = $this->getPropertyInjection($property);
105
+
106
+ if ($propertyInjection) {
107
+ $objectDefinition->addPropertyInjection($propertyInjection);
108
+ }
109
+ }
110
+ }
111
+
112
+ /**
113
+ * @param ReflectionProperty $property
114
+ * @return PropertyInjection|null
115
+ */
116
+ private function getPropertyInjection(ReflectionProperty $property)
117
+ {
118
+ // Look for @Inject annotation
119
+ /** @var $annotation Inject */
120
+ $annotation = $this->getAnnotationReader()->getPropertyAnnotation($property, 'Cybot\Dependencies\DI\Annotation\Inject');
121
+ if ($annotation === null) {
122
+ return null;
123
+ }
124
+
125
+ // @Inject("name") or look for @var content
126
+ $entryName = $annotation->getName() ?: $this->getPhpDocReader()->getPropertyClass($property);
127
+
128
+ if ($entryName === null) {
129
+ throw new AnnotationException(sprintf(
130
+ '@Inject found on property %s::%s but unable to guess what to inject, use a @var annotation',
131
+ $property->getDeclaringClass()->getName(),
132
+ $property->getName()
133
+ ));
134
+ }
135
+
136
+ return new PropertyInjection($property->getName(), new EntryReference($entryName));
137
+ }
138
+
139
+ /**
140
+ * Browse the object's methods looking for annotated methods.
141
+ *
142
+ * @param ReflectionClass $class
143
+ * @param ObjectDefinition $objectDefinition
144
+ */
145
+ private function readMethods(ReflectionClass $class, ObjectDefinition $objectDefinition)
146
+ {
147
+ // This will look in all the methods, including those of the parent classes
148
+ foreach ($class->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
149
+ if ($method->isStatic()) {
150
+ continue;
151
+ }
152
+
153
+ $methodInjection = $this->getMethodInjection($method);
154
+
155
+ if (! $methodInjection) {
156
+ continue;
157
+ }
158
+
159
+ if ($method->isConstructor()) {
160
+ $objectDefinition->setConstructorInjection($methodInjection);
161
+ } else {
162
+ $objectDefinition->addMethodInjection($methodInjection);
163
+ }
164
+ }
165
+ }
166
+
167
+ /**
168
+ * {@inheritdoc}
169
+ */
170
+ private function getMethodInjection(ReflectionMethod $method)
171
+ {
172
+ // Look for @Inject annotation
173
+ /** @var $annotation Inject|null */
174
+ try {
175
+ $annotation = $this->getAnnotationReader()->getMethodAnnotation($method, 'Cybot\Dependencies\DI\Annotation\Inject');
176
+ } catch (AnnotationException $e) {
177
+ throw new AnnotationException(sprintf(
178
+ '@Inject annotation on %s::%s is malformed. %s',
179
+ $method->getDeclaringClass()->getName(),
180
+ $method->getName(),
181
+ $e->getMessage()
182
+ ), 0, $e);
183
+ }
184
+ $annotationParameters = $annotation ? $annotation->getParameters() : [];
185
+
186
+ // @Inject on constructor is implicit
187
+ if (! ($annotation || $method->isConstructor())) {
188
+ return null;
189
+ }
190
+
191
+ $parameters = [];
192
+ foreach ($method->getParameters() as $index => $parameter) {
193
+ $entryName = $this->getMethodParameter($index, $parameter, $annotationParameters);
194
+
195
+ if ($entryName !== null) {
196
+ $parameters[$index] = new EntryReference($entryName);
197
+ }
198
+ }
199
+
200
+ if ($method->isConstructor()) {
201
+ return MethodInjection::constructor($parameters);
202
+ } else {
203
+ return new MethodInjection($method->getName(), $parameters);
204
+ }
205
+ }
206
+
207
+ /**
208
+ * @param int $parameterIndex
209
+ * @param ReflectionParameter $parameter
210
+ * @param array $annotationParameters
211
+ *
212
+ * @return string|null Entry name or null if not found.
213
+ */
214
+ private function getMethodParameter($parameterIndex, ReflectionParameter $parameter, array $annotationParameters)
215
+ {
216
+ // @Inject has definition for this parameter (by index, or by name)
217
+ if (isset($annotationParameters[$parameterIndex])) {
218
+ return $annotationParameters[$parameterIndex];
219
+ }
220
+ if (isset($annotationParameters[$parameter->getName()])) {
221
+ return $annotationParameters[$parameter->getName()];
222
+ }
223
+
224
+ // Skip optional parameters if not explicitly defined
225
+ if ($parameter->isOptional()) {
226
+ return null;
227
+ }
228
+
229
+ // Try to use the type-hinting
230
+ $parameterClass = $parameter->getClass();
231
+ if ($parameterClass) {
232
+ return $parameterClass->getName();
233
+ }
234
+
235
+ // Last resort, look for @param tag
236
+ return $this->getPhpDocReader()->getParameterClass($parameter);
237
+ }
238
+
239
+ /**
240
+ * @return Reader The annotation reader
241
+ */
242
+ public function getAnnotationReader()
243
+ {
244
+ if ($this->annotationReader == null) {
245
+ AnnotationRegistry::registerAutoloadNamespace('Cybot\Dependencies\DI\Annotation', __DIR__ . '/../../../');
246
+ $this->annotationReader = new SimpleAnnotationReader();
247
+ $this->annotationReader->addNamespace('Cybot\Dependencies\DI\Annotation');
248
+ }
249
+
250
+ return $this->annotationReader;
251
+ }
252
+
253
+ /**
254
+ * @param Reader $annotationReader The annotation reader
255
+ */
256
+ public function setAnnotationReader(Reader $annotationReader)
257
+ {
258
+ $this->annotationReader = $annotationReader;
259
+ }
260
+
261
+ /**
262
+ * @return PhpDocReader
263
+ */
264
+ private function getPhpDocReader()
265
+ {
266
+ if ($this->phpDocReader === null) {
267
+ $this->phpDocReader = new PhpDocReader($this->ignorePhpDocErrors);
268
+ }
269
+
270
+ return $this->phpDocReader;
271
+ }
272
+
273
+ private function readInjectableAnnotation(ReflectionClass $class, ObjectDefinition $definition)
274
+ {
275
+ try {
276
+ /** @var $annotation Injectable|null */
277
+ $annotation = $this->getAnnotationReader()
278
+ ->getClassAnnotation($class, 'Cybot\Dependencies\DI\Annotation\Injectable');
279
+ } catch (UnexpectedValueException $e) {
280
+ throw new DefinitionException(sprintf(
281
+ 'Error while reading @Injectable on %s: %s',
282
+ $class->getName(),
283
+ $e->getMessage()
284
+ ), 0, $e);
285
+ }
286
+
287
+ if (! $annotation) {
288
+ return;
289
+ }
290
+
291
+ if ($annotation->getScope()) {
292
+ $definition->setScope($annotation->getScope());
293
+ }
294
+ if ($annotation->isLazy() !== null) {
295
+ $definition->setLazy($annotation->isLazy());
296
+ }
297
+ }
298
+ }
addons/inc/Dependencies/DI/Definition/Source/Autowiring.php ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Source;
11
+
12
+ use Cybot\Dependencies\DI\Definition\ObjectDefinition;
13
+ use Cybot\Dependencies\DI\Definition\EntryReference;
14
+ use Cybot\Dependencies\DI\Definition\ObjectDefinition\MethodInjection;
15
+
16
+ /**
17
+ * Reads DI class definitions using reflection.
18
+ *
19
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
20
+ */
21
+ class Autowiring implements DefinitionSource
22
+ {
23
+ /**
24
+ * {@inheritdoc}
25
+ */
26
+ public function getDefinition($name)
27
+ {
28
+ if (!class_exists($name) && !interface_exists($name)) {
29
+ return null;
30
+ }
31
+
32
+ $definition = new ObjectDefinition($name);
33
+
34
+ // Constructor
35
+ $class = new \ReflectionClass($name);
36
+ $constructor = $class->getConstructor();
37
+ if ($constructor && $constructor->isPublic()) {
38
+ $definition->setConstructorInjection(
39
+ MethodInjection::constructor($this->getParametersDefinition($constructor))
40
+ );
41
+ }
42
+
43
+ return $definition;
44
+ }
45
+
46
+ /**
47
+ * Read the type-hinting from the parameters of the function.
48
+ */
49
+ private function getParametersDefinition(\ReflectionFunctionAbstract $constructor)
50
+ {
51
+ $parameters = [];
52
+
53
+ foreach ($constructor->getParameters() as $index => $parameter) {
54
+ // Skip optional parameters
55
+ if ($parameter->isOptional()) {
56
+ continue;
57
+ }
58
+
59
+ $parameterClass = $parameter->getClass();
60
+
61
+ if ($parameterClass) {
62
+ $parameters[$index] = new EntryReference($parameterClass->getName());
63
+ }
64
+ }
65
+
66
+ return $parameters;
67
+ }
68
+ }
addons/inc/Dependencies/DI/Definition/Source/CachedDefinitionSource.php ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Source;
11
+
12
+ use Cybot\Dependencies\DI\Definition\CacheableDefinition;
13
+ use Cybot\Dependencies\DI\Definition\Definition;
14
+ use Doctrine\Common\Cache\Cache;
15
+
16
+ /**
17
+ * Caches another definition source.
18
+ *
19
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
20
+ */
21
+ class CachedDefinitionSource implements DefinitionSource
22
+ {
23
+ /**
24
+ * Prefix for cache key, to avoid conflicts with other systems using the same cache
25
+ * @var string
26
+ */
27
+ const CACHE_PREFIX = 'Cybot\Dependencies\DI\\Definition\\';
28
+
29
+ /**
30
+ * @var DefinitionSource
31
+ */
32
+ private $source;
33
+
34
+ /**
35
+ * @var Cache
36
+ */
37
+ private $cache;
38
+
39
+ public function __construct(DefinitionSource $source, Cache $cache)
40
+ {
41
+ $this->source = $source;
42
+ $this->cache = $cache;
43
+ }
44
+
45
+ /**
46
+ * {@inheritdoc}
47
+ */
48
+ public function getDefinition($name)
49
+ {
50
+ // Look in cache
51
+ $definition = $this->fetchFromCache($name);
52
+
53
+ if ($definition === false) {
54
+ $definition = $this->source->getDefinition($name);
55
+
56
+ // Save to cache
57
+ if ($definition === null || ($definition instanceof CacheableDefinition)) {
58
+ $this->saveToCache($name, $definition);
59
+ }
60
+ }
61
+
62
+ return $definition;
63
+ }
64
+
65
+ /**
66
+ * @return Cache
67
+ */
68
+ public function getCache()
69
+ {
70
+ return $this->cache;
71
+ }
72
+
73
+ /**
74
+ * Fetches a definition from the cache
75
+ *
76
+ * @param string $name Entry name
77
+ * @return Definition|null|boolean The cached definition, null or false if the value is not already cached
78
+ */
79
+ private function fetchFromCache($name)
80
+ {
81
+ $cacheKey = self::CACHE_PREFIX . $name;
82
+
83
+ $data = $this->cache->fetch($cacheKey);
84
+
85
+ if ($data !== false) {
86
+ return $data;
87
+ }
88
+
89
+ return false;
90
+ }
91
+
92
+ /**
93
+ * Saves a definition to the cache
94
+ *
95
+ * @param string $name Entry name
96
+ * @param Definition|null $definition
97
+ */
98
+ private function saveToCache($name, Definition $definition = null)
99
+ {
100
+ $cacheKey = self::CACHE_PREFIX . $name;
101
+
102
+ $this->cache->save($cacheKey, $definition);
103
+ }
104
+ }
addons/inc/Dependencies/DI/Definition/Source/DefinitionArray.php ADDED
@@ -0,0 +1,142 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Source;
11
+
12
+ use Cybot\Dependencies\DI\Definition\ArrayDefinition;
13
+ use Cybot\Dependencies\DI\Definition\ObjectDefinition;
14
+ use Cybot\Dependencies\DI\Definition\Definition;
15
+ use Cybot\Dependencies\DI\Definition\FactoryDefinition;
16
+ use Cybot\Dependencies\DI\Definition\ValueDefinition;
17
+ use Cybot\Dependencies\DI\Definition\Helper\DefinitionHelper;
18
+
19
+ /**
20
+ * Reads DI definitions from a PHP array.
21
+ *
22
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
23
+ */
24
+ class DefinitionArray implements DefinitionSource, MutableDefinitionSource
25
+ {
26
+ const WILDCARD = '*';
27
+ /**
28
+ * Matches anything except "\"
29
+ */
30
+ const WILDCARD_PATTERN = '([^\\\\]+)';
31
+
32
+ /**
33
+ * DI definitions in a PHP array
34
+ * @var array
35
+ */
36
+ private $definitions = [];
37
+
38
+ /**
39
+ * @param array $definitions
40
+ */
41
+ public function __construct(array $definitions = [])
42
+ {
43
+ $this->definitions = $definitions;
44
+ }
45
+
46
+ /**
47
+ * @param array $definitions DI definitions in a PHP array indexed by the definition name.
48
+ */
49
+ public function addDefinitions(array $definitions)
50
+ {
51
+ // The newly added data prevails
52
+ // "for keys that exist in both arrays, the elements from the left-hand array will be used"
53
+ $this->definitions = $definitions + $this->definitions;
54
+ }
55
+
56
+ /**
57
+ * {@inheritdoc}
58
+ */
59
+ public function addDefinition(Definition $definition)
60
+ {
61
+ $this->definitions[$definition->getName()] = $definition;
62
+ }
63
+
64
+ /**
65
+ * {@inheritdoc}
66
+ */
67
+ public function getDefinition($name)
68
+ {
69
+ // Look for the definition by name
70
+ if (array_key_exists($name, $this->definitions)) {
71
+ return $this->castDefinition($this->definitions[$name], $name);
72
+ }
73
+
74
+ // Look if there are wildcards definitions
75
+ foreach ($this->definitions as $key => $definition) {
76
+ if (strpos($key, self::WILDCARD) === false) {
77
+ continue;
78
+ }
79
+
80
+ // Turn the pattern into a regex
81
+ $key = addslashes($key);
82
+ $key = '#' . str_replace(self::WILDCARD, self::WILDCARD_PATTERN, $key) . '#';
83
+ if (preg_match($key, $name, $matches) === 1) {
84
+ $definition = $this->castDefinition($definition, $name);
85
+
86
+ // For a class definition, we replace * in the class name with the matches
87
+ // *Interface -> *Impl => FooInterface -> FooImpl
88
+ if ($definition instanceof ObjectDefinition) {
89
+ array_shift($matches);
90
+ $definition->setClassName(
91
+ $this->replaceWildcards($definition->getClassName(), $matches)
92
+ );
93
+ }
94
+
95
+ return $definition;
96
+ }
97
+ }
98
+
99
+ return null;
100
+ }
101
+
102
+ /**
103
+ * @param mixed $definition
104
+ * @param string $name
105
+ * @return Definition
106
+ */
107
+ private function castDefinition($definition, $name)
108
+ {
109
+ if ($definition instanceof DefinitionHelper) {
110
+ $definition = $definition->getDefinition($name);
111
+ }
112
+ if (! $definition instanceof Definition && is_array($definition)) {
113
+ $definition = new ArrayDefinition($name, $definition);
114
+ }
115
+ if ($definition instanceof \Closure) {
116
+ $definition = new FactoryDefinition($name, $definition);
117
+ }
118
+ if (! $definition instanceof Definition) {
119
+ $definition = new ValueDefinition($name, $definition);
120
+ }
121
+
122
+ return $definition;
123
+ }
124
+
125
+ /**
126
+ * Replaces all the wildcards in the string with the given replacements.
127
+ * @param string $string
128
+ * @param string[] $replacements
129
+ * @return string
130
+ */
131
+ private function replaceWildcards($string, array $replacements)
132
+ {
133
+ foreach ($replacements as $replacement) {
134
+ $pos = strpos($string, self::WILDCARD);
135
+ if ($pos !== false) {
136
+ $string = substr_replace($string, $replacement, $pos, 1);
137
+ }
138
+ }
139
+
140
+ return $string;
141
+ }
142
+ }
addons/inc/Dependencies/DI/Definition/Source/DefinitionFile.php ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Source;
11
+
12
+ use Cybot\Dependencies\DI\Definition\Definition;
13
+ use Cybot\Dependencies\DI\Definition\Exception\DefinitionException;
14
+
15
+ /**
16
+ * Reads DI definitions from a file returning a PHP array.
17
+ *
18
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
19
+ */
20
+ class DefinitionFile extends DefinitionArray
21
+ {
22
+ /**
23
+ * @var bool
24
+ */
25
+ private $initialized = false;
26
+
27
+ /**
28
+ * File containing definitions, or null if the definitions are given as a PHP array.
29
+ * @var string|null
30
+ */
31
+ private $file;
32
+
33
+ /**
34
+ * @param string $file File in which the definitions are returned as an array.
35
+ */
36
+ public function __construct($file)
37
+ {
38
+ // Lazy-loading to improve performances
39
+ $this->file = $file;
40
+
41
+ parent::__construct([]);
42
+ }
43
+
44
+ /**
45
+ * {@inheritdoc}
46
+ */
47
+ public function getDefinition($name)
48
+ {
49
+ $this->initialize();
50
+
51
+ return parent::getDefinition($name);
52
+ }
53
+
54
+ /**
55
+ * Lazy-loading of the definitions.
56
+ * @throws DefinitionException
57
+ */
58
+ private function initialize()
59
+ {
60
+ if ($this->initialized === true) {
61
+ return;
62
+ }
63
+
64
+ $definitions = require $this->file;
65
+
66
+ if (! is_array($definitions)) {
67
+ throw new DefinitionException("File {$this->file} should return an array of definitions");
68
+ }
69
+
70
+ $this->addDefinitions($definitions);
71
+
72
+ $this->initialized = true;
73
+ }
74
+ }
addons/inc/Dependencies/DI/Definition/Source/DefinitionSource.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Source;
11
+
12
+ use Cybot\Dependencies\DI\Definition\Definition;
13
+ use Cybot\Dependencies\DI\Definition\Exception\DefinitionException;
14
+
15
+ /**
16
+ * Source of definitions for entries of the container.
17
+ *
18
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
19
+ */
20
+ interface DefinitionSource
21
+ {
22
+ /**
23
+ * Returns the DI definition for the entry name.
24
+ *
25
+ * @param string $name
26
+ *
27
+ * @throws DefinitionException An invalid definition was found.
28
+ * @return Definition|null
29
+ */
30
+ public function getDefinition($name);
31
+ }
addons/inc/Dependencies/DI/Definition/Source/MutableDefinitionSource.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Cybot\Dependencies\DI\Definition\Source;
4
+
5
+ use Cybot\Dependencies\DI\Definition\Definition;
6
+
7
+ /**
8
+ * Describes a definition source to which we can add new definitions.
9
+ *
10
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
11
+ */
12
+ interface MutableDefinitionSource extends DefinitionSource
13
+ {
14
+ public function addDefinition(Definition $definition);
15
+ }
addons/inc/Dependencies/DI/Definition/Source/SourceChain.php ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition\Source;
11
+
12
+ use Cybot\Dependencies\DI\Definition\Definition;
13
+ use Cybot\Dependencies\DI\Definition\HasSubDefinition;
14
+
15
+ /**
16
+ * Manages a chain of other definition sources.
17
+ *
18
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
19
+ */
20
+ class SourceChain implements DefinitionSource, MutableDefinitionSource
21
+ {
22
+ /**
23
+ * @var DefinitionSource[]
24
+ */
25
+ private $sources;
26
+
27
+ /**
28
+ * @var DefinitionSource
29
+ */
30
+ private $rootSource;
31
+
32
+ /**
33
+ * @var MutableDefinitionSource|null
34
+ */
35
+ private $mutableSource;
36
+
37
+ /**
38
+ * @param DefinitionSource[] $sources
39
+ */
40
+ public function __construct(array $sources)
41
+ {
42
+ // We want a numerically indexed array to ease the traversal later
43
+ $this->sources = array_values($sources);
44
+ $this->rootSource = $this;
45
+ }
46
+
47
+ /**
48
+ * {@inheritdoc}
49
+ * @param int $startIndex Use this parameter to start looking from a specific
50
+ * point in the source chain.
51
+ */
52
+ public function getDefinition($name, $startIndex = 0)
53
+ {
54
+ $count = count($this->sources);
55
+ for ($i = $startIndex; $i < $count; $i++) {
56
+ $source = $this->sources[$i];
57
+
58
+ $definition = $source->getDefinition($name);
59
+
60
+ if ($definition) {
61
+ if ($definition instanceof HasSubDefinition) {
62
+ $this->resolveSubDefinition($definition, $i);
63
+ }
64
+ return $definition;
65
+ }
66
+ }
67
+
68
+ return null;
69
+ }
70
+
71
+ public function addDefinition(Definition $definition)
72
+ {
73
+ if (! $this->mutableSource) {
74
+ throw new \LogicException("The container's definition source has not been initialized correctly");
75
+ }
76
+
77
+ $this->mutableSource->addDefinition($definition);
78
+ }
79
+
80
+ public function setRootDefinitionSource(DefinitionSource $rootSource)
81
+ {
82
+ $this->rootSource = $rootSource;
83
+ }
84
+
85
+ private function resolveSubDefinition(HasSubDefinition $definition, $currentIndex)
86
+ {
87
+ $subDefinitionName = $definition->getSubDefinitionName();
88
+
89
+ if ($subDefinitionName === $definition->getName()) {
90
+ // Extending itself: look in the next sources only (else infinite recursion)
91
+ $subDefinition = $this->getDefinition($subDefinitionName, $currentIndex + 1);
92
+ } else {
93
+ // Extending another definition: look from the root
94
+ $subDefinition = $this->rootSource->getDefinition($subDefinitionName);
95
+ }
96
+
97
+ if ($subDefinition) {
98
+ $definition->setSubDefinition($subDefinition);
99
+ }
100
+ }
101
+
102
+ public function setMutableDefinitionSource(MutableDefinitionSource $mutableSource)
103
+ {
104
+ $this->mutableSource = $mutableSource;
105
+
106
+ array_unshift($this->sources, $mutableSource);
107
+ }
108
+ }
addons/inc/Dependencies/DI/Definition/StringDefinition.php ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition;
11
+
12
+ use Cybot\Dependencies\DI\Scope;
13
+
14
+ /**
15
+ * Definition of a string composed of other strings.
16
+ *
17
+ * @since 5.0
18
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
19
+ */
20
+ class StringDefinition implements Definition
21
+ {
22
+ /**
23
+ * Entry name
24
+ * @var string
25
+ */
26
+ private $name;
27
+
28
+ /**
29
+ * @var string
30
+ */
31
+ private $expression;
32
+
33
+ /**
34
+ * @param string $name Entry name
35
+ * @param string $expression
36
+ */
37
+ public function __construct($name, $expression)
38
+ {
39
+ $this->name = $name;
40
+ $this->expression = $expression;
41
+ }
42
+
43
+ /**
44
+ * @return string Entry name
45
+ */
46
+ public function getName()
47
+ {
48
+ return $this->name;
49
+ }
50
+
51
+ /**
52
+ * {@inheritdoc}
53
+ */
54
+ public function getScope()
55
+ {
56
+ return Scope::SINGLETON;
57
+ }
58
+
59
+ /**
60
+ * @return string
61
+ */
62
+ public function getExpression()
63
+ {
64
+ return $this->expression;
65
+ }
66
+ }
addons/inc/Dependencies/DI/Definition/ValueDefinition.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Definition;
11
+
12
+ use Cybot\Dependencies\DI\Scope;
13
+
14
+ /**
15
+ * Definition of a value for dependency injection.
16
+ *
17
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
18
+ */
19
+ class ValueDefinition implements Definition
20
+ {
21
+ /**
22
+ * Entry name
23
+ * @var string
24
+ */
25
+ private $name;
26
+
27
+ /**
28
+ * @var mixed
29
+ */
30
+ private $value;
31
+
32
+ /**
33
+ * @param string $name Entry name
34
+ * @param mixed $value
35
+ */
36
+ public function __construct($name, $value)
37
+ {
38
+ $this->name = $name;
39
+ $this->value = $value;
40
+ }
41
+
42
+ /**
43
+ * @return string Entry name
44
+ */
45
+ public function getName()
46
+ {
47
+ return $this->name;
48
+ }
49
+
50
+ /**
51
+ * A value definition is like a constant, there is nothing to compute, the value is the same for everyone.
52
+ *
53
+ * {@inheritdoc}
54
+ */
55
+ public function getScope()
56
+ {
57
+ return Scope::SINGLETON;
58
+ }
59
+
60
+ /**
61
+ * @return mixed
62
+ */
63
+ public function getValue()
64
+ {
65
+ return $this->value;
66
+ }
67
+ }
addons/inc/Dependencies/DI/DependencyException.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI;
11
+
12
+ use Cybot\Dependencies\Interop\Container\Exception\ContainerException;
13
+
14
+ /**
15
+ * Exception for the Container
16
+ */
17
+ class DependencyException extends \Exception implements ContainerException
18
+ {
19
+ }
addons/inc/Dependencies/DI/FactoryInterface.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI;
11
+
12
+ /**
13
+ * Describes the basic interface of a factory.
14
+ *
15
+ * @since 4.0
16
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
17
+ */
18
+ interface FactoryInterface
19
+ {
20
+ /**
21
+ * Resolves an entry by its name. If given a class name, it will return a new instance of that class.
22
+ *
23
+ * @param string $name Entry name or a class name.
24
+ * @param array $parameters Optional parameters to use to build the entry. Use this to force specific
25
+ * parameters to specific values. Parameters not defined in this array will
26
+ * be automatically resolved.
27
+ *
28
+ * @throws \InvalidArgumentException The name parameter must be of type string.
29
+ * @throws DependencyException Error while resolving the entry.
30
+ * @throws NotFoundException No entry or class found for the given name.
31
+ * @return mixed
32
+ */
33
+ public function make($name, array $parameters = []);
34
+ }
addons/inc/Dependencies/DI/Invoker/DefinitionParameterResolver.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Cybot\Dependencies\DI\Cybot\Dependencies\Invoker;
4
+
5
+ use Cybot\Dependencies\DI\Definition\Helper\DefinitionHelper;
6
+ use Cybot\Dependencies\DI\Definition\Resolver\DefinitionResolver;
7
+ use Cybot\Dependencies\Invoker\ParameterResolver\ParameterResolver;
8
+ use ReflectionFunctionAbstract;
9
+
10
+ /**
11
+ * Resolves callable parameters using definitions.
12
+ *
13
+ * @since 5.0
14
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
15
+ */
16
+ class DefinitionParameterResolver implements ParameterResolver
17
+ {
18
+ /**
19
+ * @var DefinitionResolver
20
+ */
21
+ private $definitionResolver;
22
+
23
+ public function __construct(DefinitionResolver $definitionResolver)
24
+ {
25
+ $this->definitionResolver = $definitionResolver;
26
+ }
27
+
28
+ /**
29
+ * {@inheritdoc}
30
+ */
31
+ public function getParameters(
32
+ ReflectionFunctionAbstract $reflection,
33
+ array $providedParameters,
34
+ array $resolvedParameters
35
+ ) {
36
+ foreach ($resolvedParameters as &$parameter) {
37
+ if ($parameter instanceof DefinitionHelper) {
38
+ $definition = $parameter->getDefinition('');
39
+ $parameter = $this->definitionResolver->resolve($definition);
40
+ }
41
+ }
42
+
43
+ return $resolvedParameters;
44
+ }
45
+ }
addons/inc/Dependencies/DI/InvokerInterface.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI;
11
+
12
+ /**
13
+ * Invoke a callable.
14
+ *
15
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
16
+ */
17
+ interface InvokerInterface extends \Cybot\Dependencies\Invoker\InvokerInterface
18
+ {
19
+ }
addons/inc/Dependencies/DI/NotFoundException.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI;
11
+
12
+ use Cybot\Dependencies\Interop\Container\Exception\NotFoundException as BaseNotFoundException;
13
+
14
+ /**
15
+ * Exception thrown when a class or a value is not found in the container
16
+ */
17
+ class NotFoundException extends \Exception implements BaseNotFoundException
18
+ {
19
+ }
addons/inc/Dependencies/DI/Proxy/ProxyFactory.php ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Proxy;
11
+
12
+ use ProxyManager\Configuration;
13
+ use ProxyManager\Factory\LazyLoadingValueHolderFactory;
14
+ use ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy;
15
+
16
+ /**
17
+ * Creates proxy classes.
18
+ *
19
+ * Wraps Ocramius/ProxyManager LazyLoadingValueHolderFactory.
20
+ *
21
+ * @see ProxyManager\Factory\LazyLoadingValueHolderFactory
22
+ *
23
+ * @since 5.0
24
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
25
+ */
26
+ class ProxyFactory
27
+ {
28
+ /**
29
+ * If true, write the proxies to disk to improve performances.
30
+ * @var boolean
31
+ */
32
+ private $writeProxiesToFile;
33
+
34
+ /**
35
+ * Directory where to write the proxies (if $writeProxiesToFile is enabled).
36
+ * @var string
37
+ */
38
+ private $proxyDirectory;
39
+
40
+ /**
41
+ * @var LazyLoadingValueHolderFactory|null
42
+ */
43
+ private $proxyManager;
44
+
45
+ public function __construct($writeProxiesToFile, $proxyDirectory = null)
46
+ {
47
+ $this->writeProxiesToFile = $writeProxiesToFile;
48
+ $this->proxyDirectory = $proxyDirectory;
49
+ }
50
+
51
+ /**
52
+ * Creates a new lazy proxy instance of the given class with
53
+ * the given initializer
54
+ *
55
+ * @param string $className name of the class to be proxied
56
+ * @param \Closure $initializer initializer to be passed to the proxy
57
+ *
58
+ * @return \ProxyManager\Proxy\LazyLoadingInterface
59
+ */
60
+ public function createProxy($className, \Closure $initializer)
61
+ {
62
+ $this->createProxyManager();
63
+
64
+ return $this->proxyManager->createProxy($className, $initializer);
65
+ }
66
+
67
+ private function createProxyManager()
68
+ {
69
+ if ($this->proxyManager !== null) {
70
+ return;
71
+ }
72
+
73
+ if (! class_exists('ProxyManager\Configuration')) {
74
+ throw new \RuntimeException('The ocramius/proxy-manager library is not installed. Lazy injection requires that library to be installed with Composer in order to work. Run "composer require ocramius/proxy-manager:~0.3".');
75
+ }
76
+
77
+ $config = new Configuration();
78
+
79
+ if ($this->writeProxiesToFile) {
80
+ $config->setProxiesTargetDir($this->proxyDirectory);
81
+ spl_autoload_register($config->getProxyAutoloader());
82
+ } else {
83
+ $config->setGeneratorStrategy(new EvaluatingGeneratorStrategy());
84
+ }
85
+
86
+ $this->proxyManager = new LazyLoadingValueHolderFactory($config);
87
+ }
88
+ }
addons/inc/Dependencies/DI/Reflection/CallableReflectionFactory.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI\Reflection;
11
+
12
+ /**
13
+ * Create a reflection object from a callable.
14
+ *
15
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
16
+ */
17
+ class CallableReflectionFactory
18
+ {
19
+ /**
20
+ * @param callable $callable
21
+ *
22
+ * @return \ReflectionFunctionAbstract
23
+ */
24
+ public static function fromCallable($callable)
25
+ {
26
+ // Array callable
27
+ if (is_array($callable)) {
28
+ list($class, $method) = $callable;
29
+
30
+ return new \ReflectionMethod($class, $method);
31
+ }
32
+
33
+ // Closure
34
+ if ($callable instanceof \Closure) {
35
+ return new \ReflectionFunction($callable);
36
+ }
37
+
38
+ // Callable object (i.e. implementing __invoke())
39
+ if (is_object($callable) && method_exists($callable, '__invoke')) {
40
+ return new \ReflectionMethod($callable, '__invoke');
41
+ }
42
+
43
+ // Callable class (i.e. implementing __invoke())
44
+ if (is_string($callable) && class_exists($callable) && method_exists($callable, '__invoke')) {
45
+ return new \ReflectionMethod($callable, '__invoke');
46
+ }
47
+
48
+ // Standard function
49
+ return new \ReflectionFunction($callable);
50
+ }
51
+ }
addons/inc/Dependencies/DI/Scope.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI;
11
+
12
+ /**
13
+ * Scope enum.
14
+ *
15
+ * The scope defines the lifecycle of an entry.
16
+ *
17
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
18
+ */
19
+ class Scope
20
+ {
21
+ /**
22
+ * A singleton entry will be computed once and shared.
23
+ *
24
+ * For a class, only a single instance of the class will be created.
25
+ */
26
+ const SINGLETON = 'singleton';
27
+
28
+ /**
29
+ * A prototype entry will be recomputed each time it is asked.
30
+ *
31
+ * For a class, this will create a new instance each time.
32
+ */
33
+ const PROTOTYPE = 'prototype';
34
+
35
+ /**
36
+ * Method kept for backward compatibility, use the constant instead.
37
+ *
38
+ * @return string
39
+ */
40
+ public static function SINGLETON()
41
+ {
42
+ return self::SINGLETON;
43
+ }
44
+
45
+ /**
46
+ * Method kept for backward compatibility, use the constant instead.
47
+ *
48
+ * @return string
49
+ */
50
+ public static function PROTOTYPE()
51
+ {
52
+ return self::PROTOTYPE;
53
+ }
54
+ }
addons/inc/Dependencies/DI/functions.php ADDED
@@ -0,0 +1,181 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHP-DI
4
+ *
5
+ * @link http://php-di.org/
6
+ * @copyright Matthieu Napoli (http://mnapoli.fr/)
7
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
8
+ */
9
+
10
+ namespace Cybot\Dependencies\DI;
11
+
12
+ use Cybot\Dependencies\DI\Definition\EntryReference;
13
+ use Cybot\Dependencies\DI\Definition\Helper\ArrayDefinitionExtensionHelper;
14
+ use Cybot\Dependencies\DI\Definition\Helper\FactoryDefinitionHelper;
15
+ use Cybot\Dependencies\DI\Definition\Helper\ObjectDefinitionHelper;
16
+ use Cybot\Dependencies\DI\Definition\Helper\EnvironmentVariableDefinitionHelper;
17
+ use Cybot\Dependencies\DI\Definition\Helper\ValueDefinitionHelper;
18
+ use Cybot\Dependencies\DI\Definition\Helper\StringDefinitionHelper;
19
+
20
+ if (! function_exists('Cybot\Dependencies\DI\value')) {
21
+ /**
22
+ * Helper for defining an object.
23
+ *
24
+ * @param mixed $value
25
+ *
26
+ * @return ValueDefinitionHelper
27
+ */
28
+ function value($value)
29
+ {
30
+ return new ValueDefinitionHelper($value);
31
+ }
32
+ }
33
+
34
+ if (! function_exists('Cybot\Dependencies\DI\object')) {
35
+ /**
36
+ * Helper for defining an object.
37
+ *
38
+ * @param string|null $className Class name of the object.
39
+ * If null, the name of the entry (in the container) will be used as class name.
40
+ *
41
+ * @return ObjectDefinitionHelper
42
+ */
43
+ function object($className = null)
44
+ {
45
+ return new ObjectDefinitionHelper($className);
46
+ }
47
+ }
48
+
49
+ if (! function_exists('Cybot\Dependencies\DI\factory')) {
50
+ /**
51
+ * Helper for defining a container entry using a factory function/callable.
52
+ *
53
+ * @param callable $factory The factory is a callable that takes the container as parameter
54
+ * and returns the value to register in the container.
55
+ *
56
+ * @return FactoryDefinitionHelper
57
+ */
58
+ function factory($factory)
59
+ {
60
+ return new FactoryDefinitionHelper($factory);
61
+ }
62
+ }
63
+
64
+ if (! function_exists('Cybot\Dependencies\DI\decorate')) {
65
+ /**
66
+ * Decorate the previous definition using a callable.
67
+ *
68
+ * Example:
69
+ *
70
+ * 'foo' => decorate(function ($foo, $container) {
71
+ * return new CachedFoo($foo, $container->get('cache'));
72
+ * })
73
+ *
74
+ * @param callable $callable The callable takes the decorated object as first parameter and
75
+ * the container as second.
76
+ *
77
+ * @return FactoryDefinitionHelper
78
+ */
79
+ function decorate($callable)
80
+ {
81
+ return new FactoryDefinitionHelper($callable, true);
82
+ }
83
+ }
84
+
85
+ if (! function_exists('Cybot\Dependencies\DI\get')) {
86
+ /**
87
+ * Helper for referencing another container entry in an object definition.
88
+ *
89
+ * @param string $entryName
90
+ *
91
+ * @return EntryReference
92
+ */
93
+ function get($entryName)
94
+ {
95
+ return new EntryReference($entryName);
96
+ }
97
+ }
98
+
99
+ if (! function_exists('Cybot\Dependencies\DI\link')) {
100
+ /**
101
+ * Helper for referencing another container entry in an object definition.
102
+ *
103
+ * @deprecated \Cybot\Dependencies\DI\link() has been replaced by \Cybot\Dependencies\DI\get()
104
+ *
105
+ * @param string $entryName
106
+ *
107
+ * @return EntryReference
108
+ */
109
+ function link($entryName)
110
+ {
111
+ return new EntryReference($entryName);
112
+ }
113
+ }
114
+
115
+ if (! function_exists('Cybot\Dependencies\DI\env')) {
116
+ /**
117
+ * Helper for referencing environment variables.
118
+ *
119
+ * @param string $variableName The name of the environment variable.
120
+ * @param mixed $defaultValue The default value to be used if the environment variable is not defined.
121
+ *
122
+ * @return EnvironmentVariableDefinitionHelper
123
+ */
124
+ function env($variableName, $defaultValue = null)
125
+ {
126
+ // Only mark as optional if the default value was *explicitly* provided.
127
+ $isOptional = 2 === func_num_args();
128
+
129
+ return new EnvironmentVariableDefinitionHelper($variableName, $isOptional, $defaultValue);
130
+ }
131
+ }
132
+
133
+ if (! function_exists('Cybot\Dependencies\DI\add')) {
134
+ /**
135
+ * Helper for extending another definition.
136
+ *
137
+ * Example:
138
+ *
139
+ * 'log.backends' => Cybot\Dependencies\DI\add(Cybot\Dependencies\DI\get('My\Custom\LogBackend'))
140
+ *
141
+ * or:
142
+ *
143
+ * 'log.backends' => Cybot\Dependencies\DI\add([
144
+ * Cybot\Dependencies\DI\get('My\Custom\LogBackend')
145
+ * ])
146
+ *
147
+ * @param mixed|array $values A value or an array of values to add to the array.
148
+ *
149
+ * @return ArrayDefinitionExtensionHelper
150
+ *
151
+ * @since 5.0
152
+ */
153
+ function add($values)
154
+ {
155
+ if (! is_array($values)) {
156
+ $values = [$values];
157
+ }
158
+
159
+ return new ArrayDefinitionExtensionHelper($values);
160
+ }
161
+ }
162
+
163
+ if (! function_exists('Cybot\Dependencies\DI\string')) {
164
+ /**
165
+ * Helper for concatenating strings.
166
+ *
167
+ * Example:
168
+ *
169
+ * 'log.filename' => Cybot\Dependencies\DI\string('{app.path}/app.log')
170
+ *
171
+ * @param string $expression A string expression. Use the `{}` placeholders to reference other container entries.
172
+ *
173
+ * @return StringDefinitionHelper
174
+ *
175
+ * @since 5.0
176
+ */
177
+ function string($expression)
178
+ {
179
+ return new StringDefinitionHelper((string) $expression);
180
+ }
181
+ }
addons/inc/Dependencies/Interop/Container/ContainerInterface.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
4
+ */
5
+
6
+ namespace Cybot\Dependencies\Interop\Container;
7
+
8
+ use Cybot\Dependencies\Psr\Container\ContainerInterface as PsrContainerInterface;
9
+
10
+ /**
11
+ * Describes the interface of a container that exposes methods to read its entries.
12
+ */
13
+ interface ContainerInterface extends PsrContainerInterface
14
+ {
15
+ }
addons/inc/Dependencies/Interop/Container/Exception/ContainerException.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
4
+ */
5
+
6
+ namespace Cybot\Dependencies\Interop\Container\Exception;
7
+
8
+ use Cybot\Dependencies\Psr\Container\ContainerExceptionInterface as PsrContainerException;
9
+
10
+ /**
11
+ * Base interface representing a generic exception in a container.
12
+ */
13
+ interface ContainerException extends PsrContainerException
14
+ {
15
+ }
addons/inc/Dependencies/Interop/Container/Exception/NotFoundException.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
4
+ */
5
+
6
+ namespace Cybot\Dependencies\Interop\Container\Exception;
7
+
8
+ use Cybot\Dependencies\Psr\Container\NotFoundExceptionInterface as PsrNotFoundException;
9
+
10
+ /**
11
+ * No entry was found in the container.
12
+ */
13
+ interface NotFoundException extends ContainerException, PsrNotFoundException
14
+ {
15
+ }
addons/inc/Dependencies/Invoker/CallableResolver.php ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Cybot\Dependencies\Invoker;
4
+
5
+ use Cybot\Dependencies\Interop\Container\ContainerInterface;
6
+ use Cybot\Dependencies\Interop\Container\Exception\NotFoundException;
7
+ use Cybot\Dependencies\Invoker\Exception\NotCallableException;
8
+
9
+ /**
10
+ * Resolves a callable from a container.
11
+ *
12
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
13
+ */
14
+ class CallableResolver
15
+ {
16
+ /**
17
+ * @var ContainerInterface
18
+ */
19
+ private $container;
20
+
21
+ public function __construct(ContainerInterface $container)
22
+ {
23
+ $this->container = $container;
24
+ }
25
+
26
+ /**
27
+ * Resolve the given callable into a real PHP callable.
28
+ *
29
+ * @param callable|string|array $callable
30
+ *
31
+ * @return callable Real PHP callable.
32
+ *
33
+ * @throws NotCallableException
34
+ */
35
+ public function resolve($callable)
36
+ {
37
+ if (is_string($callable) && strpos($callable, '::') !== false) {
38
+ $callable = explode('::', $callable, 2);
39
+ }
40
+
41
+ $callable = $this->resolveFromContainer($callable);
42
+
43
+ if (! is_callable($callable)) {
44
+ throw NotCallableException::fromInvalidCallable($callable, true);
45
+ }
46
+
47
+ return $callable;
48
+ }
49
+
50
+ /**
51
+ * @param callable|string|array $callable
52
+ * @return callable
53
+ * @throws NotCallableException
54
+ */
55
+ private function resolveFromContainer($callable)
56
+ {
57
+ // Shortcut for a very common use case
58
+ if ($callable instanceof \Closure) {
59
+ return $callable;
60
+ }
61
+
62
+ $isStaticCallToNonStaticMethod = false;
63
+
64
+ // If it's already a callable there is nothing to do
65
+ if (is_callable($callable)) {
66
+ $isStaticCallToNonStaticMethod = $this->isStaticCallToNonStaticMethod($callable);
67
+ if (! $isStaticCallToNonStaticMethod) {
68
+ return $callable;
69
+ }
70
+ }
71
+
72
+ // The callable is a container entry name
73
+ if (is_string($callable)) {
74
+ try {
75
+ return $this->container->get($callable);
76
+ } catch (NotFoundException $e) {
77
+ throw NotCallableException::fromInvalidCallable($callable, true);
78
+ }
79
+ }
80
+
81
+ // The callable is an array whose first item is a container entry name
82
+ // e.g. ['some-container-entry', 'methodToCall']
83
+ if (is_array($callable) && is_string($callable[0])) {
84
+ try {
85
+ // Replace the container entry name by the actual object
86
+ $callable[0] = $this->container->get($callable[0]);
87
+ return $callable;
88
+ } catch (NotFoundException $e) {
89
+ if ($isStaticCallToNonStaticMethod) {
90
+ throw new NotCallableException(sprintf(
91
+ 'Cannot call %s::%s() because %s() is not a static method and "%s" is not a container entry',
92
+ $callable[0],
93
+ $callable[1],
94
+ $callable[1],
95
+ $callable[0]
96
+ ));
97
+ }
98
+ throw new NotCallableException(sprintf(
99
+ 'Cannot call %s on %s because it is not a class nor a valid container entry',
100
+ $callable[1],
101
+ $callable[0]
102
+ ));
103
+ }
104
+ }
105
+
106
+ // Unrecognized stuff, we let it fail later
107
+ return $callable;
108
+ }
109
+
110
+ /**
111
+ * Check if the callable represents a static call to a non-static method.
112
+ *
113
+ * @param mixed $callable
114
+ * @return bool
115
+ */
116
+ private function isStaticCallToNonStaticMethod($callable)
117
+ {
118
+ if (is_array($callable) && is_string($callable[0])) {
119
+ list($class, $method) = $callable;
120
+ $reflection = new \ReflectionMethod($class, $method);
121
+
122
+ return ! $reflection->isStatic();
123
+ }
124
+
125
+ return false;
126
+ }
127
+ }
addons/inc/Dependencies/Invoker/Exception/InvocationException.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Cybot\Dependencies\Invoker\Exception;
4
+
5
+ /**
6
+ * Impossible to invoke the callable.
7
+ *
8
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
9
+ */
10
+ class InvocationException extends \Exception
11
+ {
12
+ }
addons/inc/Dependencies/Invoker/Exception/NotCallableException.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Cybot\Dependencies\Invoker\Exception;
4
+
5
+ /**
6
+ * The given callable is not actually callable.
7
+ *
8
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
9
+ */
10
+ class NotCallableException extends InvocationException
11
+ {
12
+ /**
13
+ * @param string $value
14
+ * @param bool $containerEntry
15
+ * @return self
16
+ */
17
+ public static function fromInvalidCallable($value, $containerEntry = false)
18
+ {
19
+ if (is_object($value)) {
20
+ $message = sprintf('Instance of %s is not a callable', get_class($value));
21
+ } elseif (is_array($value) && isset($value[0]) && isset($value[1])) {
22
+ $class = is_object($value[0]) ? get_class($value[0]) : $value[0];
23
+ $extra = method_exists($class, '__call') ? ' A __call() method exists but magic methods are not supported.' : '';
24
+ $message = sprintf('%s::%s() is not a callable.%s', $class, $value[1], $extra);
25
+ } else {
26
+ if ($containerEntry) {
27
+ $message = var_export($value, true) . ' is neither a callable nor a valid container entry';
28
+ } else {
29
+ $message = var_export($value, true) . ' is not a callable';
30
+ }
31
+ }
32
+
33
+ return new self($message);
34
+ }
35
+ }
addons/inc/Dependencies/Invoker/Exception/NotEnoughParametersException.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Cybot\Dependencies\Invoker\Exception;
4
+
5
+ /**
6
+ * Not enough parameters could be resolved to invoke the callable.
7
+ *
8
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
9
+ */
10
+ class NotEnoughParametersException extends InvocationException
11
+ {
12
+ }
addons/inc/Dependencies/Invoker/Invoker.php ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Cybot\Dependencies\Invoker;
4
+
5
+ use Cybot\Dependencies\Interop\Container\ContainerInterface;
6
+ use Cybot\Dependencies\Invoker\Exception\NotCallableException;
7
+ use Cybot\Dependencies\Invoker\Exception\NotEnoughParametersException;
8
+ use Cybot\Dependencies\Invoker\ParameterResolver\AssociativeArrayResolver;
9
+ use Cybot\Dependencies\Invoker\ParameterResolver\DefaultValueResolver;
10
+ use Cybot\Dependencies\Invoker\ParameterResolver\NumericArrayResolver;
11
+ use Cybot\Dependencies\Invoker\ParameterResolver\ParameterResolver;
12
+ use Cybot\Dependencies\Invoker\ParameterResolver\ResolverChain;
13
+ use Cybot\Dependencies\Invoker\Reflection\CallableReflection;
14
+
15
+ /**
16
+ * Invoke a callable.
17
+ *
18
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
19
+ */
20
+ class Invoker implements InvokerInterface
21
+ {
22
+ /**
23
+ * @var CallableResolver|null
24
+ */
25
+ private $callableResolver;
26
+
27
+ /**
28
+ * @var ParameterResolver
29
+ */
30
+ private $parameterResolver;
31
+
32
+ /**
33
+ * @var ContainerInterface|null
34
+ */
35
+ private $container;
36
+
37
+ public function __construct(ParameterResolver $parameterResolver = null, ContainerInterface $container = null)
38
+ {
39
+ $this->parameterResolver = $parameterResolver ?: $this->createParameterResolver();
40
+ $this->container = $container;
41
+
42
+ if ($container) {
43
+ $this->callableResolver = new CallableResolver($container);
44
+ }
45
+ }
46
+
47
+ /**
48
+ * {@inheritdoc}
49
+ */
50
+ public function call($callable, array $parameters = array())
51
+ {
52
+ if ($this->callableResolver) {
53
+ $callable = $this->callableResolver->resolve($callable);
54
+ }
55
+
56
+ if (! is_callable($callable)) {
57
+ throw new NotCallableException(sprintf(
58
+ '%s is not a callable',
59
+ is_object($callable) ? 'Instance of ' . get_class($callable) : var_export($callable, true)
60
+ ));
61
+ }
62
+
63
+ $callableReflection = CallableReflection::create($callable);
64
+
65
+ $args = $this->parameterResolver->getParameters($callableReflection, $parameters, array());
66
+
67
+ // Sort by array key because call_user_func_array ignores numeric keys
68
+ ksort($args);
69
+
70
+ // Check all parameters are resolved
71
+ $diff = array_diff_key($callableReflection->getParameters(), $args);
72
+ if (! empty($diff)) {
73
+ /** @var \ReflectionParameter $parameter */
74
+ $parameter = reset($diff);
75
+ throw new NotEnoughParametersException(sprintf(
76
+ 'Unable to invoke the callable because no value was given for parameter %d ($%s)',
77
+ $parameter->getPosition() + 1,
78
+ $parameter->name
79
+ ));
80
+ }
81
+
82
+ return call_user_func_array($callable, $args);
83
+ }
84
+
85
+ /**
86
+ * Create the default parameter resolver.
87
+ *
88
+ * @return ParameterResolver
89
+ */
90
+ private function createParameterResolver()
91
+ {
92
+ return new ResolverChain(array(
93
+ new NumericArrayResolver,
94
+ new AssociativeArrayResolver,
95
+ new DefaultValueResolver,
96
+ ));
97
+ }
98
+
99
+ /**
100
+ * @return ParameterResolver By default it's a ResolverChain
101
+ */
102
+ public function getParameterResolver()
103
+ {
104
+ return $this->parameterResolver;
105
+ }
106
+
107
+ /**
108
+ * @return ContainerInterface|null
109
+ */
110
+ public function getContainer()
111
+ {
112
+ return $this->container;
113
+ }
114
+
115
+ /**
116
+ * @return CallableResolver|null Returns null if no container was given in the constructor.
117
+ */
118
+ public function getCallableResolver()
119
+ {
120
+ return $this->callableResolver;
121
+ }
122
+ }
addons/inc/Dependencies/Invoker/InvokerInterface.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Cybot\Dependencies\Invoker;
4
+
5
+ use Cybot\Dependencies\Invoker\Exception\InvocationException;
6
+ use Cybot\Dependencies\Invoker\Exception\NotCallableException;
7
+ use Cybot\Dependencies\Invoker\Exception\NotEnoughParametersException;
8
+
9
+ /**
10
+ * Invoke a callable.
11
+ *
12
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
13
+ */
14
+ interface InvokerInterface
15
+ {
16
+ /**
17
+ * Call the given function using the given parameters.
18
+ *
19
+ * @param callable $callable Function to call.
20
+ * @param array $parameters Parameters to use.
21
+ *
22
+ * @return mixed Result of the function.
23
+ *
24
+ * @throws InvocationException Base exception class for all the sub-exceptions below.
25
+ * @throws NotCallableException
26
+ * @throws NotEnoughParametersException
27
+ */
28
+ public function call($callable, array $parameters = array());
29
+ }
addons/inc/Dependencies/Invoker/ParameterResolver/AssociativeArrayResolver.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Cybot\Dependencies\Invoker\ParameterResolver;
4
+
5
+ use ReflectionFunctionAbstract;
6
+
7
+ /**
8
+ * Tries to map an associative array (string-indexed) to the parameter names.
9
+ *
10
+ * E.g. `->call($callable, ['foo' => 'bar'])` will inject the string `'bar'`
11
+ * in the parameter named `$foo`.
12
+ *
13
+ * Parameters that are not indexed by a string are ignored.
14
+ *
15
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
16
+ */
17
+ class AssociativeArrayResolver implements ParameterResolver
18
+ {
19
+ public function getParameters(
20
+ ReflectionFunctionAbstract $reflection,
21
+ array $providedParameters,
22
+ array $resolvedParameters
23
+ ) {
24
+ $parameters = $reflection->getParameters();
25
+
26
+ // Skip parameters already resolved
27
+ if (! empty($resolvedParameters)) {
28
+ $parameters = array_diff_key($parameters, $resolvedParameters);
29
+ }
30
+
31
+ foreach ($parameters as $index => $parameter) {
32
+ if (array_key_exists($parameter->name, $providedParameters)) {
33
+ $resolvedParameters[$index] = $providedParameters[$parameter->name];
34
+ }
35
+ }
36
+
37
+ return $resolvedParameters;
38
+ }
39
+ }
addons/inc/Dependencies/Invoker/ParameterResolver/Container/ParameterNameContainerResolver.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Cybot\Dependencies\Invoker\ParameterResolver\Container;
4
+
5
+ use Cybot\Dependencies\Interop\Container\ContainerInterface;
6
+ use Cybot\Dependencies\Invoker\ParameterResolver\ParameterResolver;
7
+ use ReflectionFunctionAbstract;
8
+
9
+ /**
10
+ * Inject entries from a DI container using the parameter names.
11
+ *
12
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
13
+ */
14
+ class ParameterNameContainerResolver implements ParameterResolver
15
+ {
16
+ /**
17
+ * @var ContainerInterface
18
+ */
19
+ private $container;
20
+
21
+ /**
22
+ * @param ContainerInterface $container The container to get entries from.
23
+ */
24
+ public function __construct(ContainerInterface $container)
25
+ {
26
+ $this->container = $container;
27
+ }
28
+
29
+ public function getParameters(
30
+ ReflectionFunctionAbstract $reflection,
31
+ array $providedParameters,
32
+ array $resolvedParameters
33
+ ) {
34
+ $parameters = $reflection->getParameters();
35
+
36
+ // Skip parameters already resolved
37
+ if (! empty($resolvedParameters)) {
38
+ $parameters = array_diff_key($parameters, $resolvedParameters);
39
+ }
40
+
41
+ foreach ($parameters as $index => $parameter) {
42
+ $name = $parameter->name;
43
+
44
+ if ($name && $this->container->has($name)) {
45
+ $resolvedParameters[$index] = $this->container->get($name);
46
+ }
47
+ }
48
+
49
+ return $resolvedParameters;
50
+ }
51
+ }
addons/inc/Dependencies/Invoker/ParameterResolver/Container/TypeHintContainerResolver.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Cybot\Dependencies\Invoker\ParameterResolver\Container;
4
+
5
+ use Cybot\Dependencies\Interop\Container\ContainerInterface;
6
+ use Cybot\Dependencies\Invoker\ParameterResolver\ParameterResolver;
7
+ use ReflectionFunctionAbstract;
8
+
9
+ /**
10
+ * Inject entries from a DI container using the type-hints.
11
+ *
12
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
13
+ */
14
+ class TypeHintContainerResolver implements ParameterResolver
15
+ {
16
+ /**
17
+ * @var ContainerInterface
18
+ */
19
+ private $container;
20
+
21
+ /**
22
+ * @param ContainerInterface $container The container to get entries from.
23
+ */
24
+ public function __construct(ContainerInterface $container)
25
+ {
26
+ $this->container = $container;
27
+ }
28
+
29
+ public function getParameters(
30
+ ReflectionFunctionAbstract $reflection,
31
+ array $providedParameters,
32
+ array $resolvedParameters
33
+ ) {
34
+ $parameters = $reflection->getParameters();
35
+
36
+ // Skip parameters already resolved
37
+ if (! empty($resolvedParameters)) {
38
+ $parameters = array_diff_key($parameters, $resolvedParameters);
39
+ }
40
+
41
+ foreach ($parameters as $index => $parameter) {
42
+ $parameterClass = $parameter->getClass();
43
+
44
+ if ($parameterClass && $this->container->has($parameterClass->name)) {
45
+ $resolvedParameters[$index] = $this->container->get($parameterClass->name);
46
+ }
47
+ }
48
+
49
+ return $resolvedParameters;
50
+ }
51
+ }
addons/inc/Dependencies/Invoker/ParameterResolver/DefaultValueResolver.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Cybot\Dependencies\Invoker\ParameterResolver;
4
+
5
+ use ReflectionException;
6
+ use ReflectionFunctionAbstract;
7
+
8
+ /**
9
+ * Finds the default value for a parameter, *if it exists*.
10
+ *
11
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
12
+ */
13
+ class DefaultValueResolver implements ParameterResolver
14
+ {
15
+ public function getParameters(
16
+ ReflectionFunctionAbstract $reflection,
17
+ array $providedParameters,
18
+ array $resolvedParameters
19
+ ) {
20
+ $parameters = $reflection->getParameters();
21
+
22
+ // Skip parameters already resolved
23
+ if (! empty($resolvedParameters)) {
24
+ $parameters = array_diff_key($parameters, $resolvedParameters);
25
+ }
26
+
27
+ foreach ($parameters as $index => $parameter) {
28
+ /** @var \ReflectionParameter $parameter */
29
+ if ($parameter->isOptional()) {
30
+ try {
31
+ $resolvedParameters[$index] = $parameter->getDefaultValue();
32
+ } catch (ReflectionException $e) {
33
+ // Can't get default values from PHP internal classes and functions
34
+ }
35
+ }
36
+ }
37
+
38
+ return $resolvedParameters;
39
+ }
40
+ }
addons/inc/Dependencies/Invoker/ParameterResolver/NumericArrayResolver.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Cybot\Dependencies\Invoker\ParameterResolver;
4
+
5
+ use ReflectionFunctionAbstract;
6
+
7
+ /**
8
+ * Simply returns all the values of the $providedParameters array that are
9
+ * indexed by the parameter position (i.e. a number).
10
+ *
11
+ * E.g. `->call($callable, ['foo', 'bar'])` will simply resolve the parameters
12
+ * to `['foo', 'bar']`.
13
+ *
14
+ * Parameters that are not indexed by a number (i.e. parameter position)
15
+ * will be ignored.
16
+ *
17
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
18
+ */
19
+ class NumericArrayResolver implements ParameterResolver
20
+ {
21
+ public function getParameters(
22
+ ReflectionFunctionAbstract $reflection,
23
+ array $providedParameters,
24
+ array $resolvedParameters
25
+ ) {
26
+ // Skip parameters already resolved
27
+ if (! empty($resolvedParameters)) {
28
+ $providedParameters = array_diff_key($providedParameters, $resolvedParameters);
29
+ }
30
+
31
+ foreach ($providedParameters as $key => $value) {
32
+ if (is_int($key)) {
33
+ $resolvedParameters[$key] = $value;
34
+ }
35
+ }
36
+
37
+ return $resolvedParameters;
38
+ }
39
+ }
addons/inc/Dependencies/Invoker/ParameterResolver/ParameterResolver.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Cybot\Dependencies\Invoker\ParameterResolver;
4
+
5
+ use ReflectionFunctionAbstract;
6
+
7
+ /**
8
+ * Resolves the parameters to use to call the callable.
9
+ *
10
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
11
+ */
12
+ interface ParameterResolver
13
+ {
14
+ /**
15
+ * Resolves the parameters to use to call the callable.
16
+ *
17
+ * `$resolvedParameters` contains parameters that have already been resolved.
18
+ *
19
+ * Each ParameterResolver must resolve parameters that are not already
20
+ * in `$resolvedParameters`. That allows to chain multiple ParameterResolver.
21
+ *
22
+ * @param ReflectionFunctionAbstract $reflection Reflection object for the callable.
23
+ * @param array $providedParameters Parameters provided by the caller.
24
+ * @param array $resolvedParameters Parameters resolved (indexed by parameter position).
25
+ *
26
+ * @return array
27
+ */
28
+ public function getParameters(
29
+ ReflectionFunctionAbstract $reflection,
30
+ array $providedParameters,
31
+ array $resolvedParameters
32
+ );
33
+ }
addons/inc/Dependencies/Invoker/ParameterResolver/ResolverChain.php ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Cybot\Dependencies\Invoker\ParameterResolver;
4
+
5
+ use ReflectionFunctionAbstract;
6
+
7
+ /**
8
+ * Dispatches the call to other resolvers until all parameters are resolved.
9
+ *
10
+ * Chain of responsibility pattern.
11
+ *
12
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
13
+ */
14
+ class ResolverChain implements ParameterResolver
15
+ {
16
+ /**
17
+ * @var ParameterResolver[]
18
+ */
19
+ private $resolvers = array();
20
+
21
+ public function __construct(array $resolvers = array())
22
+ {
23
+ $this->resolvers = $resolvers;
24
+ }
25
+
26
+ public function getParameters(
27
+ ReflectionFunctionAbstract $reflection,
28
+ array $providedParameters,
29
+ array $resolvedParameters
30
+ ) {
31
+ $reflectionParameters = $reflection->getParameters();
32
+
33
+ foreach ($this->resolvers as $resolver) {
34
+ $resolvedParameters = $resolver->getParameters(
35
+ $reflection,
36
+ $providedParameters,
37
+ $resolvedParameters
38
+ );
39
+
40
+ $diff = array_diff_key($reflectionParameters, $resolvedParameters);
41
+ if (empty($diff)) {
42
+ // Stop traversing: all parameters are resolved
43
+ return $resolvedParameters;
44
+ }
45
+ }
46
+
47
+ return $resolvedParameters;
48
+ }
49
+
50
+ /**
51
+ * Push a parameter resolver after the ones already registered.
52
+ *
53
+ * @param ParameterResolver $resolver
54
+ */
55
+ public function appendResolver(ParameterResolver $resolver)
56
+ {
57
+ $this->resolvers[] = $resolver;
58
+ }
59
+
60
+ /**
61
+ * Insert a parameter resolver before the ones already registered.
62
+ *
63
+ * @param ParameterResolver $resolver
64
+ */
65
+ public function prependResolver(ParameterResolver $resolver)
66
+ {
67
+ array_unshift($this->resolvers, $resolver);
68
+ }
69
+ }
addons/inc/Dependencies/Invoker/ParameterResolver/TypeHintResolver.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Cybot\Dependencies\Invoker\ParameterResolver;
4
+
5
+ use Cybot\Dependencies\Invoker\ParameterResolver\ParameterResolver;
6
+ use ReflectionFunctionAbstract;
7
+
8
+ /**
9
+ * Inject entries using type-hints.
10
+ *
11
+ * Tries to match type-hints with the parameters provided.
12
+ *
13
+ * @author Felix Becker <f.becker@outlook.com>
14
+ */
15
+ class TypeHintResolver implements ParameterResolver
16
+ {
17
+ public function getParameters(
18
+ ReflectionFunctionAbstract $reflection,
19
+ array $providedParameters,
20
+ array $resolvedParameters
21
+ ) {
22
+ $parameters = $reflection->getParameters();
23
+
24
+ // Skip parameters already resolved
25
+ if (! empty($resolvedParameters)) {
26
+ $parameters = array_diff_key($parameters, $resolvedParameters);
27
+ }
28
+
29
+ foreach ($parameters as $index => $parameter) {
30
+ $parameterClass = $parameter->getClass();
31
+
32
+ if ($parameterClass && array_key_exists($parameterClass->name, $providedParameters)) {
33
+ $resolvedParameters[$index] = $providedParameters[$parameterClass->name];
34
+ }
35
+ }
36
+
37
+ return $resolvedParameters;
38
+ }
39
+ }
addons/inc/Dependencies/Invoker/Reflection/CallableReflection.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Cybot\Dependencies\Invoker\Reflection;
4
+
5
+ use Cybot\Dependencies\Invoker\Exception\NotCallableException;
6
+
7
+ /**
8
+ * Create a reflection object from a callable.
9
+ *
10
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
11
+ */
12
+ class CallableReflection
13
+ {
14
+ /**
15
+ * @param callable $callable
16
+ *
17
+ * @return \ReflectionFunctionAbstract
18
+ *
19
+ * @throws NotCallableException
20
+ *
21
+ * TODO Use the `callable` type-hint once support for PHP 5.4 and up.
22
+ */
23
+ public static function create($callable)
24
+ {
25
+ // Closure
26
+ if ($callable instanceof \Closure) {
27
+ return new \ReflectionFunction($callable);
28
+ }
29
+
30
+ // Array callable
31
+ if (is_array($callable)) {
32
+ list($class, $method) = $callable;
33
+
34
+ if (! method_exists($class, $method)) {
35
+ throw NotCallableException::fromInvalidCallable($callable);
36
+ }
37
+
38
+ return new \ReflectionMethod($class, $method);
39
+ }
40
+
41
+ // Callable object (i.e. implementing __invoke())
42
+ if (is_object($callable) && method_exists($callable, '__invoke')) {
43
+ return new \ReflectionMethod($callable, '__invoke');
44
+ }
45
+
46
+ // Callable class (i.e. implementing __invoke())
47
+ if (is_string($callable) && class_exists($callable) && method_exists($callable, '__invoke')) {
48
+ return new \ReflectionMethod($callable, '__invoke');
49
+ }
50
+
51
+ // Standard function
52
+ if (is_string($callable) && function_exists($callable)) {
53
+ return new \ReflectionFunction($callable);
54
+ }
55
+
56
+ throw new NotCallableException(sprintf(
57
+ '%s is not a callable',
58
+ is_string($callable) ? $callable : 'Instance of ' . get_class($callable)
59
+ ));
60
+ }
61
+ }
addons/inc/Dependencies/PhpDocReader/AnnotationException.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare(strict_types=1);
2
+
3
+ namespace Cybot\Dependencies\PhpDocReader;
4
+
5
+ /**
6
+ * We stumbled upon an invalid class/property/method annotation.
7
+ */
8
+ class AnnotationException extends \Exception
9
+ {
10
+ }
addons/inc/Dependencies/PhpDocReader/PhpDocReader.php ADDED
@@ -0,0 +1,307 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare(strict_types=1);
2
+
3
+ namespace Cybot\Dependencies\PhpDocReader;
4
+
5
+ use Cybot\Dependencies\PhpDocReader\PhpParser\UseStatementParser;
6
+ use ReflectionClass;
7
+ use ReflectionMethod;
8
+ use ReflectionParameter;
9
+ use ReflectionProperty;
10
+ use Reflector;
11
+
12
+ /**
13
+ * PhpDoc reader
14
+ */
15
+ class PhpDocReader
16
+ {
17
+ /** @var UseStatementParser */
18
+ private $parser;
19
+
20
+ private const PRIMITIVE_TYPES = [
21
+ 'bool' => 'bool',
22
+ 'boolean' => 'bool',
23
+ 'string' => 'string',
24
+ 'int' => 'int',
25
+ 'integer' => 'int',
26
+ 'float' => 'float',
27
+ 'double' => 'float',
28
+ 'array' => 'array',
29
+ 'object' => 'object',
30
+ 'callable' => 'callable',
31
+ 'resource' => 'resource',
32
+ 'mixed' => 'mixed',
33
+ 'iterable' => 'iterable',
34
+ ];
35
+
36
+ /** @var bool */
37
+ private $ignorePhpDocErrors;
38
+
39
+ /**
40
+ * @param bool $ignorePhpDocErrors Enable or disable throwing errors when PhpDoc errors occur (when parsing annotations).
41
+ */
42
+ public function __construct(bool $ignorePhpDocErrors = false)
43
+ {
44
+ $this->parser = new UseStatementParser;
45
+ $this->ignorePhpDocErrors = $ignorePhpDocErrors;
46
+ }
47
+
48
+ /**
49
+ * Parse the docblock of the property to get the type (class or primitive type) of the var annotation.
50
+ *
51
+ * @return string|null Type of the property (content of var annotation)
52
+ * @throws AnnotationException
53
+ */
54
+ public function getPropertyType(ReflectionProperty $property): ?string
55
+ {
56
+ return $this->readPropertyType($property, true);
57
+ }
58
+
59
+ /**
60
+ * Parse the docblock of the property to get the class of the var annotation.
61
+ *
62
+ * @return string|null Type of the property (content of var annotation)
63
+ * @throws AnnotationException
64
+ */
65
+ public function getPropertyClass(ReflectionProperty $property): ?string
66
+ {
67
+ return $this->readPropertyType($property, false);
68
+ }
69
+
70
+ private function readPropertyType(ReflectionProperty $property, bool $allowPrimitiveTypes): ?string
71
+ {
72
+ // Get the content of the @var annotation
73
+ $docComment = $property->getDocComment();
74
+ if (! $docComment) {
75
+ return null;
76
+ }
77
+ if (preg_match('/@var\s+([^\s]+)/', $docComment, $matches)) {
78
+ [, $type] = $matches;
79
+ } else {
80
+ return null;
81
+ }
82
+
83
+ // Ignore primitive types
84
+ if (isset(self::PRIMITIVE_TYPES[$type])) {
85
+ if ($allowPrimitiveTypes) {
86
+ return self::PRIMITIVE_TYPES[$type];
87
+ }
88
+ return null;
89
+ }
90
+
91
+ // Ignore types containing special characters ([], <> ...)
92
+ if (! preg_match('/^[a-zA-Z0-9\\\\_]+$/', $type)) {
93
+ return null;
94
+ }
95
+
96
+ $class = $property->getDeclaringClass();
97
+
98
+ // If the class name is not fully qualified (i.e. doesn't start with a \)
99
+ if ($type[0] !== '\\') {
100
+ // Try to resolve the FQN using the class context
101
+ $resolvedType = $this->tryResolveFqn($type, $class, $property);
102
+
103
+ if (! $resolvedType && ! $this->ignorePhpDocErrors) {
104
+ throw new AnnotationException(sprintf(
105
+ 'The @var annotation on %s::%s contains a non existent class "%s". '
106
+ . 'Did you maybe forget to add a "use" statement for this annotation?',
107
+ $class->name,
108
+ $property->getName(),
109
+ $type
110
+ ));
111
+ }
112
+
113
+ $type = $resolvedType;
114
+ }
115
+
116
+ if (! $this->ignorePhpDocErrors && ! $this->classExists($type)) {
117
+ throw new AnnotationException(sprintf(
118
+ 'The @var annotation on %s::%s contains a non existent class "%s"',
119
+ $class->name,
120
+ $property->getName(),
121
+ $type
122
+ ));
123
+ }
124
+
125
+ // Remove the leading \ (FQN shouldn't contain it)
126
+ $type = is_string($type) ? ltrim($type, '\\') : null;
127
+
128
+ return $type;
129
+ }
130
+
131
+ /**
132
+ * Parse the docblock of the property to get the type (class or primitive type) of the param annotation.
133
+ *
134
+ * @return string|null Type of the property (content of var annotation)
135
+ * @throws AnnotationException
136
+ */
137
+ public function getParameterType(ReflectionParameter $parameter): ?string
138
+ {
139
+ return $this->readParameterClass($parameter, true);
140
+ }
141
+
142
+ /**
143
+ * Parse the docblock of the property to get the class of the param annotation.
144
+ *
145
+ * @return string|null Type of the property (content of var annotation)
146
+ * @throws AnnotationException
147
+ */
148
+ public function getParameterClass(ReflectionParameter $parameter): ?string
149
+ {
150
+ return $this->readParameterClass($parameter, false);
151
+ }
152
+
153
+ private function readParameterClass(ReflectionParameter $parameter, bool $allowPrimitiveTypes): ?string
154
+ {
155
+ // Use reflection
156
+ $parameterType = $parameter->getType();
157
+ if ($parameterType && $parameterType instanceof \ReflectionNamedType && ! $parameterType->isBuiltin()) {
158
+ return $parameterType->getName();
159
+ }
160
+
161
+ $parameterName = $parameter->name;
162
+ // Get the content of the @param annotation
163
+ $method = $parameter->getDeclaringFunction();
164
+ $docComment = $method->getDocComment();
165
+ if (! $docComment) {
166
+ return null;
167
+ }
168
+ if (preg_match('/@param\s+([^\s]+)\s+\$' . $parameterName . '/', $docComment, $matches)) {
169
+ [, $type] = $matches;
170
+ } else {
171
+ return null;
172
+ }
173
+
174
+ // Ignore primitive types
175
+ if (isset(self::PRIMITIVE_TYPES[$type])) {
176
+ if ($allowPrimitiveTypes) {
177
+ return self::PRIMITIVE_TYPES[$type];
178
+ }
179
+ return null;
180
+ }
181
+
182
+ // Ignore types containing special characters ([], <> ...)
183
+ if (! preg_match('/^[a-zA-Z0-9\\\\_]+$/', $type)) {
184
+ return null;
185
+ }
186
+
187
+ $class = $parameter->getDeclaringClass();
188
+
189
+ // If the class name is not fully qualified (i.e. doesn't start with a \)
190
+ if ($type[0] !== '\\') {
191
+ // Try to resolve the FQN using the class context
192
+ $resolvedType = $this->tryResolveFqn($type, $class, $parameter);
193
+
194
+ if (! $resolvedType && ! $this->ignorePhpDocErrors) {
195
+ throw new AnnotationException(sprintf(
196
+ 'The @param annotation for parameter "%s" of %s::%s contains a non existent class "%s". '
197
+ . 'Did you maybe forget to add a "use" statement for this annotation?',
198
+ $parameterName,
199
+ $class->name,
200
+ $method->name,
201
+ $type
202
+ ));
203
+ }
204
+
205
+ $type = $resolvedType;
206
+ }
207
+
208
+ if (! $this->ignorePhpDocErrors && ! $this->classExists($type)) {
209
+ throw new AnnotationException(sprintf(
210
+ 'The @param annotation for parameter "%s" of %s::%s contains a non existent class "%s"',
211
+ $parameterName,
212
+ $class->name,
213
+ $method->name,
214
+ $type
215
+ ));
216
+ }
217
+
218
+ // Remove the leading \ (FQN shouldn't contain it)
219
+ $type = is_string($type) ? ltrim($type, '\\') : null;
220
+
221
+ return $type;
222
+ }
223
+
224
+ /**
225
+ * Attempts to resolve the FQN of the provided $type based on the $class and $member context.
226
+ *
227
+ * @return string|null Fully qualified name of the type, or null if it could not be resolved
228
+ */
229
+ private function tryResolveFqn(string $type, ReflectionClass $class, Reflector $member): ?string
230
+ {
231
+ $alias = ($pos = strpos($type, '\\')) === false ? $type : substr($type, 0, $pos);
232
+ $loweredAlias = strtolower($alias);
233
+
234
+ // Retrieve "use" statements
235
+ $uses = $this->parser->parseUseStatements($class);
236
+
237
+ if (isset($uses[$loweredAlias])) {
238
+ // Imported classes
239
+ if ($pos !== false) {
240
+ return $uses[$loweredAlias] . substr($type, $pos);
241
+ }
242
+ return $uses[$loweredAlias];
243
+ }
244
+
245
+ if ($this->classExists($class->getNamespaceName() . '\\' . $type)) {
246
+ return $class->getNamespaceName() . '\\' . $type;
247
+ }
248
+
249
+ if (isset($uses['__NAMESPACE__']) && $this->classExists($uses['__NAMESPACE__'] . '\\' . $type)) {
250
+ // Class namespace
251
+ return $uses['__NAMESPACE__'] . '\\' . $type;
252
+ }
253
+
254
+ if ($this->classExists($type)) {
255
+ // No namespace
256
+ return $type;
257
+ }
258
+
259
+ // If all fail, try resolving through related traits
260
+ return $this->tryResolveFqnInTraits($type, $class, $member);
261
+ }
262
+
263
+ /**
264
+ * Attempts to resolve the FQN of the provided $type based on the $class and $member context, specifically searching
265
+ * through the traits that are used by the provided $class.
266
+ *
267
+ * @return string|null Fully qualified name of the type, or null if it could not be resolved
268
+ */
269
+ private function tryResolveFqnInTraits(string $type, ReflectionClass $class, Reflector $member): ?string
270
+ {
271
+ /** @var ReflectionClass[] $traits */
272
+ $traits = [];
273
+
274
+ // Get traits for the class and its parents
275
+ while ($class) {
276
+ $traits = array_merge($traits, $class->getTraits());
277
+ $class = $class->getParentClass();
278
+ }
279
+
280
+ foreach ($traits as $trait) {
281
+ // Eliminate traits that don't have the property/method/parameter
282
+ if ($member instanceof ReflectionProperty && ! $trait->hasProperty($member->name)) {
283
+ continue;
284
+ }
285
+ if ($member instanceof ReflectionMethod && ! $trait->hasMethod($member->name)) {
286
+ continue;
287
+ }
288
+ if ($member instanceof ReflectionParameter && ! $trait->hasMethod($member->getDeclaringFunction()->name)) {
289
+ continue;
290
+ }
291
+
292
+ // Run the resolver again with the ReflectionClass instance for the trait
293
+ $resolvedType = $this->tryResolveFqn($type, $trait, $member);
294
+
295
+ if ($resolvedType) {
296
+ return $resolvedType;
297
+ }
298
+ }
299
+
300
+ return null;
301
+ }
302
+
303
+ private function classExists(string $class): bool
304
+ {
305
+ return class_exists($class) || interface_exists($class);
306
+ }
307
+ }
addons/inc/Dependencies/PhpDocReader/PhpParser/TokenParser.php ADDED
@@ -0,0 +1,182 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare(strict_types=1);
2
+
3
+ namespace Cybot\Dependencies\PhpDocReader\PhpParser;
4
+
5
+ /**
6
+ * Parses a file for namespaces/use/class declarations.
7
+ *
8
+ * Class taken and adapted from doctrine/annotations to avoid pulling the whole package.
9
+ *
10
+ * @author Fabien Potencier <fabien@symfony.com>
11
+ * @author Christian Kaps <christian.kaps@mohiva.com>
12
+ */
13
+ class TokenParser
14
+ {
15
+ /**
16
+ * The token list.
17
+ *
18
+ * @var list<mixed[]>
19
+ */
20
+ private $tokens;
21
+
22
+ /**
23
+ * The number of tokens.
24
+ *
25
+ * @var int
26
+ */
27
+ private $numTokens;
28
+
29
+ /**
30
+ * The current array pointer.
31
+ *
32
+ * @var int
33
+ */
34
+ private $pointer = 0;
35
+
36
+ /**
37
+ * @param string $contents
38
+ */
39
+ public function __construct($contents)
40
+ {
41
+ $this->tokens = token_get_all($contents);
42
+
43
+ // The PHP parser sets internal compiler globals for certain things. Annoyingly, the last docblock comment it
44
+ // saw gets stored in doc_comment. When it comes to compile the next thing to be include()d this stored
45
+ // doc_comment becomes owned by the first thing the compiler sees in the file that it considers might have a
46
+ // docblock. If the first thing in the file is a class without a doc block this would cause calls to
47
+ // getDocBlock() on said class to return our long lost doc_comment. Argh.
48
+ // To workaround, cause the parser to parse an empty docblock. Sure getDocBlock() will return this, but at least
49
+ // it's harmless to us.
50
+ token_get_all("<?php\n/**\n *\n */");
51
+
52
+ $this->numTokens = count($this->tokens);
53
+ }
54
+
55
+ /**
56
+ * Gets all use statements.
57
+ *
58
+ * @param string $namespaceName The namespace name of the reflected class.
59
+ *
60
+ * @return array<string, string> A list with all found use statements.
61
+ */
62
+ public function parseUseStatements($namespaceName)
63
+ {
64
+ $statements = [];
65
+ while (($token = $this->next())) {
66
+ if ($token[0] === T_USE) {
67
+ $statements = array_merge($statements, $this->parseUseStatement());
68
+ continue;
69
+ }
70
+
71
+ if ($token[0] !== T_NAMESPACE || $this->parseNamespace() !== $namespaceName) {
72
+ continue;
73
+ }
74
+
75
+ // Get fresh array for new namespace. This is to prevent the parser to collect the use statements
76
+ // for a previous namespace with the same name. This is the case if a namespace is defined twice
77
+ // or if a namespace with the same name is commented out.
78
+ $statements = [];
79
+ }
80
+
81
+ return $statements;
82
+ }
83
+
84
+ /**
85
+ * Gets the next non whitespace and non comment token.
86
+ *
87
+ * @param bool $docCommentIsComment If TRUE then a doc comment is considered a comment and skipped.
88
+ * If FALSE then only whitespace and normal comments are skipped.
89
+ *
90
+ * @return mixed[]|string|null The token if exists, null otherwise.
91
+ */
92
+ private function next($docCommentIsComment = true)
93
+ {
94
+ for ($i = $this->pointer; $i < $this->numTokens; $i++) {
95
+ $this->pointer++;
96
+ if (
97
+ $this->tokens[$i][0] === T_WHITESPACE ||
98
+ $this->tokens[$i][0] === T_COMMENT ||
99
+ ($docCommentIsComment && $this->tokens[$i][0] === T_DOC_COMMENT)
100
+ ) {
101
+ continue;
102
+ }
103
+
104
+ return $this->tokens[$i];
105
+ }
106
+
107
+ return null;
108
+ }
109
+
110
+ /**
111
+ * Parses a single use statement.
112
+ *
113
+ * @return array<string, string> A list with all found class names for a use statement.
114
+ */
115
+ private function parseUseStatement()
116
+ {
117
+ $groupRoot = '';
118
+ $class = '';
119
+ $alias = '';
120
+ $statements = [];
121
+ $explicitAlias = false;
122
+ while (($token = $this->next())) {
123
+ if (! $explicitAlias && $token[0] === T_STRING) {
124
+ $class .= $token[1];
125
+ $alias = $token[1];
126
+ } elseif ($explicitAlias && $token[0] === T_STRING) {
127
+ $alias = $token[1];
128
+ } elseif (
129
+ PHP_VERSION_ID >= 80000 &&
130
+ ($token[0] === T_NAME_QUALIFIED || $token[0] === T_NAME_FULLY_QUALIFIED)
131
+ ) {
132
+ $class .= $token[1];
133
+
134
+ $classSplit = explode('\\', $token[1]);
135
+ $alias = $classSplit[count($classSplit) - 1];
136
+ } elseif ($token[0] === T_NS_SEPARATOR) {
137
+ $class .= '\\';
138
+ $alias = '';
139
+ } elseif ($token[0] === T_AS) {
140
+ $explicitAlias = true;
141
+ $alias = '';
142
+ } elseif ($token === ',') {
143
+ $statements[strtolower($alias)] = $groupRoot . $class;
144
+ $class = '';
145
+ $alias = '';
146
+ $explicitAlias = false;
147
+ } elseif ($token === ';') {
148
+ $statements[strtolower($alias)] = $groupRoot . $class;
149
+ break;
150
+ } elseif ($token === '{') {
151
+ $groupRoot = $class;
152
+ $class = '';
153
+ } elseif ($token === '}') {
154
+ continue;
155
+ } else {
156
+ break;
157
+ }
158
+ }
159
+
160
+ return $statements;
161
+ }
162
+
163
+ /**
164
+ * Gets the namespace.
165
+ *
166
+ * @return string The found namespace.
167
+ */
168
+ private function parseNamespace()
169
+ {
170
+ $name = '';
171
+ while (
172
+ ($token = $this->next()) && ($token[0] === T_STRING || $token[0] === T_NS_SEPARATOR || (
173
+ PHP_VERSION_ID >= 80000 &&
174
+ ($token[0] === T_NAME_QUALIFIED || $token[0] === T_NAME_FULLY_QUALIFIED)
175
+ ))
176
+ ) {
177
+ $name .= $token[1];
178
+ }
179
+
180
+ return $name;
181
+ }
182
+ }
addons/inc/Dependencies/PhpDocReader/PhpParser/UseStatementParser.php ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php declare(strict_types=1);
2
+
3
+ namespace Cybot\Dependencies\PhpDocReader\PhpParser;
4
+
5
+ use SplFileObject;
6
+
7
+ /**
8
+ * Parses a file for "use" declarations.
9
+ *
10
+ * Class taken and adapted from doctrine/annotations to avoid pulling the whole package.
11
+ *
12
+ * Authors: Fabien Potencier <fabien@symfony.com> and Christian Kaps <christian.kaps@mohiva.com>
13
+ */
14
+ class UseStatementParser
15
+ {
16
+ /**
17
+ * @return array A list with use statements in the form (Alias => FQN).
18
+ */
19
+ public function parseUseStatements(\ReflectionClass $class): array
20
+ {
21
+ $filename = $class->getFilename();
22
+ if ($filename === false) {
23
+ return [];
24
+ }
25
+
26
+ $content = $this->getFileContent($filename, $class->getStartLine());
27
+
28
+ if ($content === null) {
29
+ return [];
30
+ }
31
+
32
+ $namespace = preg_quote($class->getNamespaceName(), '/');
33
+ $content = preg_replace('/^.*?(\bnamespace\s+' . $namespace . '\s*[;{].*)$/s', '\\1', $content);
34
+ $tokenizer = new TokenParser('<?php ' . $content);
35
+
36
+ return $tokenizer->parseUseStatements($class->getNamespaceName());
37
+ }
38
+
39
+ /**
40
+ * Gets the content of the file right up to the given line number.
41
+ *
42
+ * @param string $filename The name of the file to load.
43
+ * @param int $lineNumber The number of lines to read from file.
44
+ */
45
+ private function getFileContent(string $filename, int $lineNumber): string
46
+ {
47
+ if (! is_file($filename)) {
48
+ throw new \RuntimeException("Unable to read file $filename");
49
+ }
50
+
51
+ $content = '';
52
+ $lineCnt = 0;
53
+ $file = new SplFileObject($filename);
54
+ while (! $file->eof()) {
55
+ if ($lineCnt++ === $lineNumber) {
56
+ break;
57
+ }
58
+
59
+ $content .= $file->fgets();
60
+ }
61
+
62
+ return $content;
63
+ }
64
+ }
addons/inc/Dependencies/Psr/Container/ContainerExceptionInterface.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
4
+ */
5
+
6
+ namespace Cybot\Dependencies\Psr\Container;
7
+
8
+ /**
9
+ * Base interface representing a generic exception in a container.
10
+ */
11
+ interface ContainerExceptionInterface
12
+ {
13
+ }
addons/inc/Dependencies/Psr/Container/ContainerInterface.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
4
+ */
5
+
6
+ namespace Cybot\Dependencies\Psr\Container;
7
+
8
+ /**
9
+ * Describes the interface of a container that exposes methods to read its entries.
10
+ */
11
+ interface ContainerInterface
12
+ {
13
+ /**
14
+ * Finds an entry of the container by its identifier and returns it.
15
+ *
16
+ * @param string $id Identifier of the entry to look for.
17
+ *
18
+ * @throws NotFoundExceptionInterface No entry was found for **this** identifier.
19
+ * @throws ContainerExceptionInterface Error while retrieving the entry.
20
+ *
21
+ * @return mixed Entry.
22
+ */
23
+ public function get($id);
24
+
25
+ /**
26
+ * Returns true if the container can return an entry for the given identifier.
27
+ * Returns false otherwise.
28
+ *
29
+ * `has($id)` returning true does not mean that `get($id)` will not throw an exception.
30
+ * It does however mean that `get($id)` will not throw a `NotFoundExceptionInterface`.
31
+ *
32
+ * @param string $id Identifier of the entry to look for.
33
+ *
34
+ * @return bool
35
+ */
36
+ public function has($id);
37
+ }
addons/inc/Dependencies/Psr/Container/NotFoundExceptionInterface.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @license http://www.opensource.org/licenses/mit-license.php MIT (see the LICENSE file)
4
+ */
5
+
6
+ namespace Cybot\Dependencies\Psr\Container;
7
+
8
+ /**
9
+ * No entry was found in the container.
10
+ */
11
+ interface NotFoundExceptionInterface extends ContainerExceptionInterface
12
+ {
13
+ }
addons/inc/classes/dependencies/.gitkeep ADDED
File without changes
addons/lib/helper.php CHANGED
@@ -210,15 +210,42 @@ function cookiebot_addons_checked_selected_helper( $helper, $current, $echo = tr
210
  * @return string
211
  *
212
  * @since 1.3.0
 
213
  */
214
  function cookiebot_addons_output_cookie_types( $cookie_types ) {
215
  if ( is_array( $cookie_types ) && count( $cookie_types ) > 0 ) {
216
- return implode( ', ', $cookie_types );
 
 
217
  } elseif ( is_string( $cookie_types ) && $cookie_types != '' ) {
218
- return $cookie_types;
219
  }
220
 
221
- return 'statistics';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
222
  }
223
 
224
  /**
@@ -244,6 +271,23 @@ function cookiebot_addons_get_one_cookie_type( $cookie_types ) {
244
  return '';
245
  }
246
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
247
  /**
248
  * Returns current site language
249
  *
210
  * @return string
211
  *
212
  * @since 1.3.0
213
+ * @version 3.9.1
214
  */
215
  function cookiebot_addons_output_cookie_types( $cookie_types ) {
216
  if ( is_array( $cookie_types ) && count( $cookie_types ) > 0 ) {
217
+ return implode( ', ', array_map( function ( $value ) {
218
+ return cookiebot_translate_type_name( $value );
219
+ }, $cookie_types ) );
220
  } elseif ( is_string( $cookie_types ) && $cookie_types != '' ) {
221
+ return cookiebot_translate_type_name( $cookie_types );
222
  }
223
 
224
+ return cookiebot_translate_type_name( 'statistics' );
225
+ }
226
+
227
+ /**
228
+ * Translates the cookie type to different language
229
+ *
230
+ * @param $type string
231
+ *
232
+ * @return string
233
+ *
234
+ * @since 3.9.1
235
+ */
236
+ function cookiebot_translate_type_name( $type ) {
237
+ switch ( $type ) {
238
+ case 'marketing':
239
+ return esc_html__( 'marketing', 'cookiebot' );
240
+ case 'statistics':
241
+ return esc_html__( 'statistics', 'cookiebot' );
242
+ case 'preferences':
243
+ return esc_html__( 'preferences', 'cookiebot' );
244
+ case 'necessary':
245
+ return esc_html__( 'necessary', 'cookiebot' );
246
+ default:
247
+ return $type;
248
+ }
249
  }
250
 
251
  /**
271
  return '';
272
  }
273
 
274
+ /**
275
+ * @param $cookie_types
276
+ *
277
+ * @return string
278
+ *
279
+ * @version 3.9.0
280
+ */
281
+ function cookiebot_addons_cookieconsent_optout( $cookie_types ) {
282
+ $output = '';
283
+
284
+ foreach ( $cookie_types as $cookie_type ) {
285
+ $output .= 'cookieconsent-optout-' . $cookie_type . ' ';
286
+ }
287
+
288
+ return trim( $output );
289
+ }
290
+
291
  /**
292
  * Returns current site language
293
  *
addons/lib/settings-service-interface.php CHANGED
@@ -3,13 +3,14 @@
3
  namespace cookiebot_addons\lib;
4
 
5
  use cookiebot_addons\controller\addons\Cookiebot_Addons_Interface;
 
6
 
7
  Interface Settings_Service_Interface {
8
 
9
  /**
10
  * Settings_Service constructor.
11
  *
12
- * @param $container \DI\Container
13
  *
14
  * @since 1.3.0
15
  */
@@ -87,8 +88,8 @@ Interface Settings_Service_Interface {
87
  * Returns addons one by one through a generator
88
  *
89
  * @return \Generator
90
- * @throws \DI\DependencyException
91
- * @throws \DI\NotFoundException
92
  *
93
  * @since 1.3.0
94
  */
@@ -98,8 +99,8 @@ Interface Settings_Service_Interface {
98
  * Returns active addons
99
  *
100
  * @return array
101
- * @throws \DI\DependencyException
102
- * @throws \DI\NotFoundException
103
  *
104
  * @since 1.3.0
105
  */
3
  namespace cookiebot_addons\lib;
4
 
5
  use cookiebot_addons\controller\addons\Cookiebot_Addons_Interface;
6
+ use Cybot\Dependencies\DI;
7
 
8
  Interface Settings_Service_Interface {
9
 
10
  /**
11
  * Settings_Service constructor.
12
  *
13
+ * @param $container DI\Container
14
  *
15
  * @since 1.3.0
16
  */
88
  * Returns addons one by one through a generator
89
  *
90
  * @return \Generator
91
+ * @throws DI\DependencyException
92
+ * @throws DI\NotFoundException
93
  *
94
  * @since 1.3.0
95
  */
99
  * Returns active addons
100
  *
101
  * @return array
102
+ * @throws DI\DependencyException
103
+ * @throws DI\NotFoundException
104
  *
105
  * @since 1.3.0
106
  */
addons/lib/settings-service.php CHANGED
@@ -2,10 +2,13 @@
2
 
3
  namespace cookiebot_addons\lib;
4
 
 
 
 
5
  class Settings_Service implements Settings_Service_Interface {
6
 
7
  /**
8
- * @var \DI\Container
9
  */
10
  public $container;
11
 
@@ -127,8 +130,8 @@ class Settings_Service implements Settings_Service_Interface {
127
  * Returns addons one by one through a generator
128
  *
129
  * @return array
130
- * @throws \DI\DependencyException
131
- * @throws \DI\NotFoundException
132
  *
133
  * @since 1.3.0
134
  */
@@ -146,8 +149,8 @@ class Settings_Service implements Settings_Service_Interface {
146
  * Returns active addons
147
  *
148
  * @return array
149
- * @throws \DI\DependencyException
150
- * @throws \DI\NotFoundException
151
  *
152
  * @since 1.3.0
153
  */
@@ -155,7 +158,8 @@ class Settings_Service implements Settings_Service_Interface {
155
  $active_addons = array();
156
 
157
  foreach ( $this->get_addons() as $addon ) {
158
- /**
 
159
  * Load addon code if the plugin is active and addon is activated
160
  */
161
  if ( $addon->is_addon_enabled() && $addon->is_addon_installed() && $addon->is_addon_activated() ) {
@@ -487,8 +491,8 @@ class Settings_Service implements Settings_Service_Interface {
487
  *
488
  * @param $addon_option_name string Addon option name
489
  *
490
- * @throws \DI\DependencyException
491
- * @throws \DI\NotFoundException
492
  *
493
  * @since 2.2.0
494
  */
2
 
3
  namespace cookiebot_addons\lib;
4
 
5
+ use cookiebot_addons\controller\addons\Cookiebot_Addons_Interface;
6
+ use Cybot\Dependencies\DI;
7
+
8
  class Settings_Service implements Settings_Service_Interface {
9
 
10
  /**
11
+ * @var DI\Container
12
  */
13
  public $container;
14
 
130
  * Returns addons one by one through a generator
131
  *
132
  * @return array
133
+ * @throws DI\DependencyException
134
+ * @throws DI\NotFoundException
135
  *
136
  * @since 1.3.0
137
  */
149
  * Returns active addons
150
  *
151
  * @return array
152
+ * @throws DI\DependencyException
153
+ * @throws DI\NotFoundException
154
  *
155
  * @since 1.3.0
156
  */
158
  $active_addons = array();
159
 
160
  foreach ( $this->get_addons() as $addon ) {
161
+ /**
162
+ * @var $addon Cookiebot_Addons_Interface
163
  * Load addon code if the plugin is active and addon is activated
164
  */
165
  if ( $addon->is_addon_enabled() && $addon->is_addon_installed() && $addon->is_addon_activated() ) {
491
  *
492
  * @param $addon_option_name string Addon option name
493
  *
494
+ * @throws DI\DependencyException
495
+ * @throws DI\NotFoundException
496
  *
497
  * @since 2.2.0
498
  */
addons/lib/theme-settings-service.php ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\lib;
4
+
5
+ class Theme_Settings_Service extends Settings_Service {
6
+
7
+
8
+ /**
9
+ * Returns true if the addon is installed
10
+ *
11
+ * @param $addon
12
+ *
13
+ * @return bool
14
+ *
15
+ * @since 1.3.0
16
+ */
17
+ public function is_addon_installed( $addon ) {
18
+ return wp_get_theme($addon)->exists();
19
+ }
20
+
21
+ /**
22
+ * Returns the addon version
23
+ *
24
+ * @param $addon
25
+ *
26
+ * @return bool
27
+ *
28
+ * @since 2.2.1
29
+ */
30
+ public function get_addon_version( $addon ) {
31
+ $theme = wp_get_theme($addon);
32
+ if($theme->exists()) {
33
+ return $theme->get('Version');
34
+ }
35
+
36
+ return false;
37
+ }
38
+
39
+ /**
40
+ * Returns true if the addon plugin is activated
41
+ *
42
+ * @param $addon
43
+ *
44
+ * @return bool
45
+ *
46
+ * @since 1.3.0
47
+ */
48
+ public function is_addon_activated( $addon ) {
49
+ if ( empty( $addon ) ) {
50
+ return false;
51
+ }
52
+
53
+ $addon = strtolower( $addon );
54
+
55
+ $addon_theme = wp_get_theme( $addon );
56
+ $addon_theme_name = strtolower( $addon_theme->get( 'Name' ) );
57
+ $active_theme = wp_get_theme();
58
+ if ( $addon_theme_name === strtolower( $active_theme->get( 'Name' ) ) ) {
59
+ return true;
60
+ }
61
+
62
+ $active_theme_parent = $active_theme->parent();
63
+ if ( $active_theme_parent !== false && $addon_theme_name === strtolower( $active_theme_parent->get( 'Name' ) ) ) {
64
+ return true;
65
+ }
66
+
67
+ return false;
68
+ }
69
+
70
+ }
addons/tests/integration/addons/test-custom-facebook-feed-old.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\tests\integration\addons;
4
+
5
+ class Test_Custom_Facebook_Feed_Old extends Addons_Base {
6
+
7
+ public function setUp() {
8
+
9
+ }
10
+
11
+ /**
12
+ * This will validate if the hook "caos_analytics_render_tracking_code" still exists
13
+ *
14
+ * @since 2.1.0
15
+ */
16
+ public function test_host_analyticsjs_local() {
17
+ $content = $this->curl_get_content( 'http://plugins.svn.wordpress.org/custom-facebook-feed/tags/2.17.1/custom-facebook-feed.php' );
18
+
19
+ $this->assertNotFalse( strpos( $content, 'echo \'var cfflinkhashtags = "\' .') );
20
+ $this->assertNotFalse( strpos( $content, "wp_register_script( 'cffscripts',") );
21
+ $this->assertNotFalse( strpos( $content, "add_action( 'wp_footer', 'cff_js' );") );
22
+ $this->assertNotFalse( strpos( $content, "add_action( 'wp_enqueue_scripts', 'cff_scripts_method' );") );
23
+ }
24
+ }
addons/tests/integration/addons/test-custom-facebook-feed.php CHANGED
@@ -14,11 +14,10 @@ class Test_Custom_Facebook_Feed extends Addons_Base {
14
  * @since 2.1.0
15
  */
16
  public function test_host_analyticsjs_local() {
17
- $content = $this->curl_get_content( 'http://plugins.svn.wordpress.org/custom-facebook-feed/trunk/custom-facebook-feed.php' );
18
-
19
- $this->assertNotFalse( strpos( $content, 'echo \'var cfflinkhashtags = "\' .') );
20
- $this->assertNotFalse( strpos( $content, "wp_register_script( 'cffscripts',") );
21
- $this->assertNotFalse( strpos( $content, "add_action( 'wp_footer', 'cff_js' );") );
22
- $this->assertNotFalse( strpos( $content, "add_action( 'wp_enqueue_scripts', 'cff_scripts_method' );") );
23
  }
24
  }
14
  * @since 2.1.0
15
  */
16
  public function test_host_analyticsjs_local() {
17
+ $content = $this->curl_get_content( 'http://plugins.svn.wordpress.org/custom-facebook-feed/trunk/inc/Custom_Facebook_Feed.php' );
18
+
19
+ $this->assertNotFalse( strpos( $content, 'echo \'var cfflinkhashtags = "\' . $cff_link_hashtags . \'";\';') );
20
+ $this->assertNotFalse( strpos( $content, 'wp_enqueue_script( \'cffscripts\' );') );
21
+ $this->assertNotFalse( strpos( $content, 'add_action( \'wp_footer\', [ self::$instance, \'cff_js\' ] );') );
 
22
  }
23
  }
addons/tests/integration/addons/test-google-site-kit.php CHANGED
@@ -13,7 +13,7 @@ class Test_Google_Site_Kit extends Addons_Base {
13
  *
14
  */
15
  public function test_google_site_kit() {
16
- $content = $this->curl_get_content( 'http://plugins.svn.wordpress.org/google-site-kit/trunk/includes/Modules/Analytics.php' );
17
 
18
  $this->assertNotFalse( strpos( $content, "wp_script_add_data( 'google_gtagjs', 'script_execution', 'async' );") );
19
 
13
  *
14
  */
15
  public function test_google_site_kit() {
16
+ $content = $this->curl_get_content( 'http://plugins.svn.wordpress.org/google-site-kit/trunk/includes/Modules/Analytics/Web_Tag.php' );
17
 
18
  $this->assertNotFalse( strpos( $content, "wp_script_add_data( 'google_gtagjs', 'script_execution', 'async' );") );
19
 
addons/tests/integration/addons/test-official-facebook-pixel.php CHANGED
@@ -42,7 +42,7 @@ document,'script','https://connect.facebook.net/en_US/fbevents.js');
42
  10, 2);";
43
 
44
  $snippets[] = "add_action(
45
- 'wpcf7_ajax_json_echo',
46
  array(__CLASS__, 'injectLeadEvent'),
47
  20, 2);";
48
 
42
  10, 2);";
43
 
44
  $snippets[] = "add_action(
45
+ 'wpcf7_feedback_response',
46
  array(__CLASS__, 'injectLeadEvent'),
47
  20, 2);";
48
 
addons/tests/integration/test-buffer-priorities.php CHANGED
@@ -10,15 +10,6 @@ class Test_Buffer_Priorities extends Addons_Base {
10
 
11
  }
12
 
13
- /**
14
- * @covers \cookiebot_addons\controller\addons\custom_facebook_feed\Custom_Facebook_Feed
15
- */
16
- public function test_custom_facebook_feed() {
17
- $content = $this->curl_get_content( 'http://plugins.svn.wordpress.org/custom-facebook-feed/trunk/custom-facebook-feed.php' );
18
-
19
- $this->assertNotFalse( strpos( $content, "add_action( 'wp_footer', 'cff_js' );" ) );
20
- }
21
-
22
  /**
23
  * @covers \cookiebot_addons\controller\addons\caos_host_analyticsjs_local\CAOS_Host_Analyticsjs_Local
24
  */
10
 
11
  }
12
 
 
 
 
 
 
 
 
 
 
13
  /**
14
  * @covers \cookiebot_addons\controller\addons\caos_host_analyticsjs_local\CAOS_Host_Analyticsjs_Local
15
  */
addons/vendor/autoload.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload.php @generated by Composer
4
+
5
+ require_once __DIR__ . '/composer/autoload_real.php';
6
+
7
+ return ComposerAutoloaderInit9d0c6155a5d010fd47a5e41be5d8833a::getLoader();
addons/vendor/composer/ClassLoader.php ADDED
@@ -0,0 +1,445 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Composer.
5
+ *
6
+ * (c) Nils Adermann <naderman@naderman.de>
7
+ * Jordi Boggiano <j.boggiano@seld.be>
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ namespace Composer\Autoload;
14
+
15
+ /**
16
+ * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
17
+ *
18
+ * $loader = new \Composer\Autoload\ClassLoader();
19
+ *
20
+ * // register classes with namespaces
21
+ * $loader->add('Symfony\Component', __DIR__.'/component');
22
+ * $loader->add('Symfony', __DIR__.'/framework');
23
+ *
24
+ * // activate the autoloader
25
+ * $loader->register();
26
+ *
27
+ * // to enable searching the include path (eg. for PEAR packages)
28
+ * $loader->setUseIncludePath(true);
29
+ *
30
+ * In this example, if you try to use a class in the Symfony\Component
31
+ * namespace or one of its children (Symfony\Component\Console for instance),
32
+ * the autoloader will first look for the class under the component/
33
+ * directory, and it will then fallback to the framework/ directory if not
34
+ * found before giving up.
35
+ *
36
+ * This class is loosely based on the Symfony UniversalClassLoader.
37
+ *
38
+ * @author Fabien Potencier <fabien@symfony.com>
39
+ * @author Jordi Boggiano <j.boggiano@seld.be>
40
+ * @see http://www.php-fig.org/psr/psr-0/
41
+ * @see http://www.php-fig.org/psr/psr-4/
42
+ */
43
+ class ClassLoader
44
+ {
45
+ // PSR-4
46
+ private $prefixLengthsPsr4 = array();
47
+ private $prefixDirsPsr4 = array();
48
+ private $fallbackDirsPsr4 = array();
49
+
50
+ // PSR-0
51
+ private $prefixesPsr0 = array();
52
+ private $fallbackDirsPsr0 = array();
53
+
54
+ private $useIncludePath = false;
55
+ private $classMap = array();
56
+ private $classMapAuthoritative = false;
57
+ private $missingClasses = array();
58
+ private $apcuPrefix;
59
+
60
+ public function getPrefixes()
61
+ {
62
+ if (!empty($this->prefixesPsr0)) {
63
+ return call_user_func_array('array_merge', $this->prefixesPsr0);
64
+ }
65
+
66
+ return array();
67
+ }
68
+
69
+ public function getPrefixesPsr4()
70
+ {
71
+ return $this->prefixDirsPsr4;
72
+ }
73
+
74
+ public function getFallbackDirs()
75
+ {
76
+ return $this->fallbackDirsPsr0;
77
+ }
78
+
79
+ public function getFallbackDirsPsr4()
80
+ {
81
+ return $this->fallbackDirsPsr4;
82
+ }
83
+
84
+ public function getClassMap()
85
+ {
86
+ return $this->classMap;
87
+ }
88
+
89
+ /**
90
+ * @param array $classMap Class to filename map
91
+ */
92
+ public function addClassMap(array $classMap)
93
+ {
94
+ if ($this->classMap) {
95
+ $this->classMap = array_merge($this->classMap, $classMap);
96
+ } else {
97
+ $this->classMap = $classMap;
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Registers a set of PSR-0 directories for a given prefix, either
103
+ * appending or prepending to the ones previously set for this prefix.
104
+ *
105
+ * @param string $prefix The prefix
106
+ * @param array|string $paths The PSR-0 root directories
107
+ * @param bool $prepend Whether to prepend the directories
108
+ */
109
+ public function add($prefix, $paths, $prepend = false)
110
+ {
111
+ if (!$prefix) {
112
+ if ($prepend) {
113
+ $this->fallbackDirsPsr0 = array_merge(
114
+ (array) $paths,
115
+ $this->fallbackDirsPsr0
116
+ );
117
+ } else {
118
+ $this->fallbackDirsPsr0 = array_merge(
119
+ $this->fallbackDirsPsr0,
120
+ (array) $paths
121
+ );
122
+ }
123
+
124
+ return;
125
+ }
126
+
127
+ $first = $prefix[0];
128
+ if (!isset($this->prefixesPsr0[$first][$prefix])) {
129
+ $this->prefixesPsr0[$first][$prefix] = (array) $paths;
130
+
131
+ return;
132
+ }
133
+ if ($prepend) {
134
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
135
+ (array) $paths,
136
+ $this->prefixesPsr0[$first][$prefix]
137
+ );
138
+ } else {
139
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
140
+ $this->prefixesPsr0[$first][$prefix],
141
+ (array) $paths
142
+ );
143
+ }
144
+ }
145
+
146
+ /**
147
+ * Registers a set of PSR-4 directories for a given namespace, either
148
+ * appending or prepending to the ones previously set for this namespace.
149
+ *
150
+ * @param string $prefix The prefix/namespace, with trailing '\\'
151
+ * @param array|string $paths The PSR-4 base directories
152
+ * @param bool $prepend Whether to prepend the directories
153
+ *
154
+ * @throws \InvalidArgumentException
155
+ */
156
+ public function addPsr4($prefix, $paths, $prepend = false)
157
+ {
158
+ if (!$prefix) {
159
+ // Register directories for the root namespace.
160
+ if ($prepend) {
161
+ $this->fallbackDirsPsr4 = array_merge(
162
+ (array) $paths,
163
+ $this->fallbackDirsPsr4
164
+ );
165
+ } else {
166
+ $this->fallbackDirsPsr4 = array_merge(
167
+ $this->fallbackDirsPsr4,
168
+ (array) $paths
169
+ );
170
+ }
171
+ } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
172
+ // Register directories for a new namespace.
173
+ $length = strlen($prefix);
174
+ if ('\\' !== $prefix[$length - 1]) {
175
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
176
+ }
177
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
178
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
179
+ } elseif ($prepend) {
180
+ // Prepend directories for an already registered namespace.
181
+ $this->prefixDirsPsr4[$prefix] = array_merge(
182
+ (array) $paths,
183
+ $this->prefixDirsPsr4[$prefix]
184
+ );
185
+ } else {
186
+ // Append directories for an already registered namespace.
187
+ $this->prefixDirsPsr4[$prefix] = array_merge(
188
+ $this->prefixDirsPsr4[$prefix],
189
+ (array) $paths
190
+ );
191
+ }
192
+ }
193
+
194
+ /**
195
+ * Registers a set of PSR-0 directories for a given prefix,
196
+ * replacing any others previously set for this prefix.
197
+ *
198
+ * @param string $prefix The prefix
199
+ * @param array|string $paths The PSR-0 base directories
200
+ */
201
+ public function set($prefix, $paths)
202
+ {
203
+ if (!$prefix) {
204
+ $this->fallbackDirsPsr0 = (array) $paths;
205
+ } else {
206
+ $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
207
+ }
208
+ }
209
+
210
+ /**
211
+ * Registers a set of PSR-4 directories for a given namespace,
212
+ * replacing any others previously set for this namespace.
213
+ *
214
+ * @param string $prefix The prefix/namespace, with trailing '\\'
215
+ * @param array|string $paths The PSR-4 base directories
216
+ *
217
+ * @throws \InvalidArgumentException
218
+ */
219
+ public function setPsr4($prefix, $paths)
220
+ {
221
+ if (!$prefix) {
222
+ $this->fallbackDirsPsr4 = (array) $paths;
223
+ } else {
224
+ $length = strlen($prefix);
225
+ if ('\\' !== $prefix[$length - 1]) {
226
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
227
+ }
228
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
229
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
230
+ }
231
+ }
232
+
233
+ /**
234
+ * Turns on searching the include path for class files.
235
+ *
236
+ * @param bool $useIncludePath
237
+ */
238
+ public function setUseIncludePath($useIncludePath)
239
+ {
240
+ $this->useIncludePath = $useIncludePath;
241
+ }
242
+
243
+ /**
244
+ * Can be used to check if the autoloader uses the include path to check
245
+ * for classes.
246
+ *
247
+ * @return bool
248
+ */
249
+ public function getUseIncludePath()
250
+ {
251
+ return $this->useIncludePath;
252
+ }
253
+
254
+ /**
255
+ * Turns off searching the prefix and fallback directories for classes
256
+ * that have not been registered with the class map.
257
+ *
258
+ * @param bool $classMapAuthoritative
259
+ */
260
+ public function setClassMapAuthoritative($classMapAuthoritative)
261
+ {
262
+ $this->classMapAuthoritative = $classMapAuthoritative;
263
+ }
264
+
265
+ /**
266
+ * Should class lookup fail if not found in the current class map?
267
+ *
268
+ * @return bool
269
+ */
270
+ public function isClassMapAuthoritative()
271
+ {
272
+ return $this->classMapAuthoritative;
273
+ }
274
+
275
+ /**
276
+ * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
277
+ *
278
+ * @param string|null $apcuPrefix
279
+ */
280
+ public function setApcuPrefix($apcuPrefix)
281
+ {
282
+ $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
283
+ }
284
+
285
+ /**
286
+ * The APCu prefix in use, or null if APCu caching is not enabled.
287
+ *
288
+ * @return string|null
289
+ */
290
+ public function getApcuPrefix()
291
+ {
292
+ return $this->apcuPrefix;
293
+ }
294
+
295
+ /**
296
+ * Registers this instance as an autoloader.
297
+ *
298
+ * @param bool $prepend Whether to prepend the autoloader or not
299
+ */
300
+ public function register($prepend = false)
301
+ {
302
+ spl_autoload_register(array($this, 'loadClass'), true, $prepend);
303
+ }
304
+
305
+ /**
306
+ * Unregisters this instance as an autoloader.
307
+ */
308
+ public function unregister()
309
+ {
310
+ spl_autoload_unregister(array($this, 'loadClass'));
311
+ }
312
+
313
+ /**
314
+ * Loads the given class or interface.
315
+ *
316
+ * @param string $class The name of the class
317
+ * @return bool|null True if loaded, null otherwise
318
+ */
319
+ public function loadClass($class)
320
+ {
321
+ if ($file = $this->findFile($class)) {
322
+ includeFile($file);
323
+
324
+ return true;
325
+ }
326
+ }
327
+
328
+ /**
329
+ * Finds the path to the file where the class is defined.
330
+ *
331
+ * @param string $class The name of the class
332
+ *
333
+ * @return string|false The path if found, false otherwise
334
+ */
335
+ public function findFile($class)
336
+ {
337
+ // class map lookup
338
+ if (isset($this->classMap[$class])) {
339
+ return $this->classMap[$class];
340
+ }
341
+ if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
342
+ return false;
343
+ }
344
+ if (null !== $this->apcuPrefix) {
345
+ $file = apcu_fetch($this->apcuPrefix.$class, $hit);
346
+ if ($hit) {
347
+ return $file;
348
+ }
349
+ }
350
+
351
+ $file = $this->findFileWithExtension($class, '.php');
352
+
353
+ // Search for Hack files if we are running on HHVM
354
+ if (false === $file && defined('HHVM_VERSION')) {
355
+ $file = $this->findFileWithExtension($class, '.hh');
356
+ }
357
+
358
+ if (null !== $this->apcuPrefix) {
359
+ apcu_add($this->apcuPrefix.$class, $file);
360
+ }
361
+
362
+ if (false === $file) {
363
+ // Remember that this class does not exist.
364
+ $this->missingClasses[$class] = true;
365
+ }
366
+
367
+ return $file;
368
+ }
369
+
370
+ private function findFileWithExtension($class, $ext)
371
+ {
372
+ // PSR-4 lookup
373
+ $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
374
+
375
+ $first = $class[0];
376
+ if (isset($this->prefixLengthsPsr4[$first])) {
377
+ $subPath = $class;
378
+ while (false !== $lastPos = strrpos($subPath, '\\')) {
379
+ $subPath = substr($subPath, 0, $lastPos);
380
+ $search = $subPath . '\\';
381
+ if (isset($this->prefixDirsPsr4[$search])) {
382
+ $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
383
+ foreach ($this->prefixDirsPsr4[$search] as $dir) {
384
+ if (file_exists($file = $dir . $pathEnd)) {
385
+ return $file;
386
+ }
387
+ }
388
+ }
389
+ }
390
+ }
391
+
392
+ // PSR-4 fallback dirs
393
+ foreach ($this->fallbackDirsPsr4 as $dir) {
394
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
395
+ return $file;
396
+ }
397
+ }
398
+
399
+ // PSR-0 lookup
400
+ if (false !== $pos = strrpos($class, '\\')) {
401
+ // namespaced class name
402
+ $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
403
+ . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
404
+ } else {
405
+ // PEAR-like class name
406
+ $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
407
+ }
408
+
409
+ if (isset($this->prefixesPsr0[$first])) {
410
+ foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
411
+ if (0 === strpos($class, $prefix)) {
412
+ foreach ($dirs as $dir) {
413
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
414
+ return $file;
415
+ }
416
+ }
417
+ }
418
+ }
419
+ }
420
+
421
+ // PSR-0 fallback dirs
422
+ foreach ($this->fallbackDirsPsr0 as $dir) {
423
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
424
+ return $file;
425
+ }
426
+ }
427
+
428
+ // PSR-0 include paths.
429
+ if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
430
+ return $file;
431
+ }
432
+
433
+ return false;
434
+ }
435
+ }
436
+
437
+ /**
438
+ * Scope isolated include.
439
+ *
440
+ * Prevents access to $this/self from included files.
441
+ */
442
+ function includeFile($file)
443
+ {
444
+ include $file;
445
+ }
addons/vendor/composer/LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ Copyright (c) Nils Adermann, Jordi Boggiano
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is furnished
9
+ to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all
12
+ copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ THE SOFTWARE.
21
+
addons/vendor/composer/autoload_classmap.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_classmap.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ );
addons/vendor/composer/autoload_files.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_files.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ '1189f6b6b50c267de6a30d7721bb532e' => $baseDir . '/inc/Dependencies/DI/functions.php',
10
+ );
addons/vendor/composer/autoload_namespaces.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_namespaces.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ );
addons/vendor/composer/autoload_psr4.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_psr4.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ 'Cybot\\' => array($baseDir . '/inc'),
10
+ );
addons/vendor/composer/autoload_real.php ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_real.php @generated by Composer
4
+
5
+ class ComposerAutoloaderInit9d0c6155a5d010fd47a5e41be5d8833a
6
+ {
7
+ private static $loader;
8
+
9
+ public static function loadClassLoader($class)
10
+ {
11
+ if ('Composer\Autoload\ClassLoader' === $class) {
12
+ require __DIR__ . '/ClassLoader.php';
13
+ }
14
+ }
15
+
16
+ /**
17
+ * @return \Composer\Autoload\ClassLoader
18
+ */
19
+ public static function getLoader()
20
+ {
21
+ if (null !== self::$loader) {
22
+ return self::$loader;
23
+ }
24
+
25
+ spl_autoload_register(array('ComposerAutoloaderInit9d0c6155a5d010fd47a5e41be5d8833a', 'loadClassLoader'), true, true);
26
+ self::$loader = $loader = new \Composer\Autoload\ClassLoader();
27
+ spl_autoload_unregister(array('ComposerAutoloaderInit9d0c6155a5d010fd47a5e41be5d8833a', 'loadClassLoader'));
28
+
29
+ $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
30
+ if ($useStaticLoader) {
31
+ require_once __DIR__ . '/autoload_static.php';
32
+
33
+ call_user_func(\Composer\Autoload\ComposerStaticInit9d0c6155a5d010fd47a5e41be5d8833a::getInitializer($loader));
34
+ } else {
35
+ $map = require __DIR__ . '/autoload_namespaces.php';
36
+ foreach ($map as $namespace => $path) {
37
+ $loader->set($namespace, $path);
38
+ }
39
+
40
+ $map = require __DIR__ . '/autoload_psr4.php';
41
+ foreach ($map as $namespace => $path) {
42
+ $loader->setPsr4($namespace, $path);
43
+ }
44
+
45
+ $classMap = require __DIR__ . '/autoload_classmap.php';
46
+ if ($classMap) {
47
+ $loader->addClassMap($classMap);
48
+ }
49
+ }
50
+
51
+ $loader->register(true);
52
+
53
+ if ($useStaticLoader) {
54
+ $includeFiles = Composer\Autoload\ComposerStaticInit9d0c6155a5d010fd47a5e41be5d8833a::$files;
55
+ } else {
56
+ $includeFiles = require __DIR__ . '/autoload_files.php';
57
+ }
58
+ foreach ($includeFiles as $fileIdentifier => $file) {
59
+ composerRequire9d0c6155a5d010fd47a5e41be5d8833a($fileIdentifier, $file);
60
+ }
61
+
62
+ return $loader;
63
+ }
64
+ }
65
+
66
+ function composerRequire9d0c6155a5d010fd47a5e41be5d8833a($fileIdentifier, $file)
67
+ {
68
+ if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
69
+ require $file;
70
+
71
+ $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
72
+ }
73
+ }
addons/vendor/composer/autoload_static.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_static.php @generated by Composer
4
+
5
+ namespace Composer\Autoload;
6
+
7
+ class ComposerStaticInit9d0c6155a5d010fd47a5e41be5d8833a
8
+ {
9
+ public static $files = array (
10
+ '1189f6b6b50c267de6a30d7721bb532e' => __DIR__ . '/../..' . '/inc/Dependencies/DI/functions.php',
11
+ );
12
+
13
+ public static $prefixLengthsPsr4 = array (
14
+ 'C' =>
15
+ array (
16
+ 'Cybot\\' => 6,
17
+ ),
18
+ );
19
+
20
+ public static $prefixDirsPsr4 = array (
21
+ 'Cybot\\' =>
22
+ array (
23
+ 0 => __DIR__ . '/../..' . '/inc',
24
+ ),
25
+ );
26
+
27
+ public static function getInitializer(ClassLoader $loader)
28
+ {
29
+ return \Closure::bind(function () use ($loader) {
30
+ $loader->prefixLengthsPsr4 = ComposerStaticInit9d0c6155a5d010fd47a5e41be5d8833a::$prefixLengthsPsr4;
31
+ $loader->prefixDirsPsr4 = ComposerStaticInit9d0c6155a5d010fd47a5e41be5d8833a::$prefixDirsPsr4;
32
+
33
+ }, null, ClassLoader::class);
34
+ }
35
+ }
addons/vendor/composer/installed.json ADDED
@@ -0,0 +1,1224 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "name": "coenjacobs/mozart",
4
+ "version": "0.6.0-beta-3",
5
+ "version_normalized": "0.6.0.0-beta3",
6
+ "source": {
7
+ "type": "git",
8
+ "url": "https://github.com/coenjacobs/mozart.git",
9
+ "reference": "965d698d76639587b26c878b22f4373c32f3d9ee"
10
+ },
11
+ "dist": {
12
+ "type": "zip",
13
+ "url": "https://api.github.com/repos/coenjacobs/mozart/zipball/965d698d76639587b26c878b22f4373c32f3d9ee",
14
+ "reference": "965d698d76639587b26c878b22f4373c32f3d9ee",
15
+ "shasum": ""
16
+ },
17
+ "require": {
18
+ "league/flysystem": "^1.0",
19
+ "php": "^7.2",
20
+ "symfony/console": "^4|^5",
21
+ "symfony/finder": "^4|^5"
22
+ },
23
+ "require-dev": {
24
+ "phpunit/phpunit": "^8.5",
25
+ "squizlabs/php_codesniffer": "^3.5"
26
+ },
27
+ "time": "2020-06-02T06:54:01+00:00",
28
+ "bin": [
29
+ "bin/mozart"
30
+ ],
31
+ "type": "library",
32
+ "installation-source": "dist",
33
+ "autoload": {
34
+ "psr-4": {
35
+ "CoenJacobs\\Mozart\\": "src/"
36
+ }
37
+ },
38
+ "notification-url": "https://packagist.org/downloads/",
39
+ "license": [
40
+ "MIT"
41
+ ],
42
+ "authors": [
43
+ {
44
+ "name": "Coen Jacobs",
45
+ "email": "coenjacobs@gmail.com"
46
+ }
47
+ ],
48
+ "description": "Composes all dependencies as a package inside a WordPress plugin",
49
+ "funding": [
50
+ {
51
+ "url": "https://github.com/coenjacobs",
52
+ "type": "github"
53
+ }
54
+ ]
55
+ },
56
+ {
57
+ "name": "container-interop/container-interop",
58
+ "version": "1.2.0",
59
+ "version_normalized": "1.2.0.0",
60
+ "source": {
61
+ "type": "git",
62
+ "url": "https://github.com/container-interop/container-interop.git",
63
+ "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8"
64
+ },
65
+ "dist": {
66
+ "type": "zip",
67
+ "url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8",
68
+ "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8",
69
+ "shasum": ""
70
+ },
71
+ "require": {
72
+ "psr/container": "^1.0"
73
+ },
74
+ "time": "2017-02-14T19:40:03+00:00",
75
+ "type": "library",
76
+ "installation-source": "dist",
77
+ "autoload": {
78
+ "psr-4": {
79
+ "Interop\\Container\\": "src/Interop/Container/"
80
+ }
81
+ },
82
+ "notification-url": "https://packagist.org/downloads/",
83
+ "license": [
84
+ "MIT"
85
+ ],
86
+ "description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
87
+ "homepage": "https://github.com/container-interop/container-interop",
88
+ "abandoned": "psr/container"
89
+ },
90
+ {
91
+ "name": "league/flysystem",
92
+ "version": "1.1.3",
93
+ "version_normalized": "1.1.3.0",
94
+ "source": {
95
+ "type": "git",
96
+ "url": "https://github.com/thephpleague/flysystem.git",
97
+ "reference": "9be3b16c877d477357c015cec057548cf9b2a14a"
98
+ },
99
+ "dist": {
100
+ "type": "zip",
101
+ "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/9be3b16c877d477357c015cec057548cf9b2a14a",
102
+ "reference": "9be3b16c877d477357c015cec057548cf9b2a14a",
103
+ "shasum": ""
104
+ },
105
+ "require": {
106
+ "ext-fileinfo": "*",
107
+ "league/mime-type-detection": "^1.3",
108
+ "php": "^7.2.5 || ^8.0"
109
+ },
110
+ "conflict": {
111
+ "league/flysystem-sftp": "<1.0.6"
112
+ },
113
+ "require-dev": {
114
+ "phpspec/prophecy": "^1.11.1",
115
+ "phpunit/phpunit": "^8.5.8"
116
+ },
117
+ "suggest": {
118
+ "ext-fileinfo": "Required for MimeType",
119
+ "ext-ftp": "Allows you to use FTP server storage",
120
+ "ext-openssl": "Allows you to use FTPS server storage",
121
+ "league/flysystem-aws-s3-v2": "Allows you to use S3 storage with AWS SDK v2",
122
+ "league/flysystem-aws-s3-v3": "Allows you to use S3 storage with AWS SDK v3",
123
+ "league/flysystem-azure": "Allows you to use Windows Azure Blob storage",
124
+ "league/flysystem-cached-adapter": "Flysystem adapter decorator for metadata caching",
125
+ "league/flysystem-eventable-filesystem": "Allows you to use EventableFilesystem",
126
+ "league/flysystem-rackspace": "Allows you to use Rackspace Cloud Files",
127
+ "league/flysystem-sftp": "Allows you to use SFTP server storage via phpseclib",
128
+ "league/flysystem-webdav": "Allows you to use WebDAV storage",
129
+ "league/flysystem-ziparchive": "Allows you to use ZipArchive adapter",
130
+ "spatie/flysystem-dropbox": "Allows you to use Dropbox storage",
131
+ "srmklive/flysystem-dropbox-v2": "Allows you to use Dropbox storage for PHP 5 applications"
132
+ },
133
+ "time": "2020-08-23T07:39:11+00:00",
134
+ "type": "library",
135
+ "extra": {
136
+ "branch-alias": {
137
+ "dev-master": "1.1-dev"
138
+ }
139
+ },
140
+ "installation-source": "dist",
141
+ "autoload": {
142
+ "psr-4": {
143
+ "League\\Flysystem\\": "src/"
144
+ }
145
+ },
146
+ "notification-url": "https://packagist.org/downloads/",
147
+ "license": [
148
+ "MIT"
149
+ ],
150
+ "authors": [
151
+ {
152
+ "name": "Frank de Jonge",
153
+ "email": "info@frenky.net"
154
+ }
155
+ ],
156
+ "description": "Filesystem abstraction: Many filesystems, one API.",
157
+ "keywords": [
158
+ "Cloud Files",
159
+ "WebDAV",
160
+ "abstraction",
161
+ "aws",
162
+ "cloud",
163
+ "copy.com",
164
+ "dropbox",
165
+ "file systems",
166
+ "files",
167
+ "filesystem",
168
+ "filesystems",
169
+ "ftp",
170
+ "rackspace",
171
+ "remote",
172
+ "s3",
173
+ "sftp",
174
+ "storage"
175
+ ],
176
+ "funding": [
177
+ {
178
+ "url": "https://offset.earth/frankdejonge",
179
+ "type": "other"
180
+ }
181
+ ]
182
+ },
183
+ {
184
+ "name": "league/mime-type-detection",
185
+ "version": "1.5.1",
186
+ "version_normalized": "1.5.1.0",
187
+ "source": {
188
+ "type": "git",
189
+ "url": "https://github.com/thephpleague/mime-type-detection.git",
190
+ "reference": "353f66d7555d8a90781f6f5e7091932f9a4250aa"
191
+ },
192
+ "dist": {
193
+ "type": "zip",
194
+ "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/353f66d7555d8a90781f6f5e7091932f9a4250aa",
195
+ "reference": "353f66d7555d8a90781f6f5e7091932f9a4250aa",
196
+ "shasum": ""
197
+ },
198
+ "require": {
199
+ "ext-fileinfo": "*",
200
+ "php": "^7.2 || ^8.0"
201
+ },
202
+ "require-dev": {
203
+ "phpstan/phpstan": "^0.12.36",
204
+ "phpunit/phpunit": "^8.5.8"
205
+ },
206
+ "time": "2020-10-18T11:50:25+00:00",
207
+ "type": "library",
208
+ "installation-source": "dist",
209
+ "autoload": {
210
+ "psr-4": {
211
+ "League\\MimeTypeDetection\\": "src"
212
+ }
213
+ },
214
+ "notification-url": "https://packagist.org/downloads/",
215
+ "license": [
216
+ "MIT"
217
+ ],
218
+ "authors": [
219
+ {
220
+ "name": "Frank de Jonge",
221
+ "email": "info@frankdejonge.nl"
222
+ }
223
+ ],
224
+ "description": "Mime-type detection for Flysystem",
225
+ "funding": [
226
+ {
227
+ "url": "https://github.com/frankdejonge",
228
+ "type": "github"
229
+ },
230
+ {
231
+ "url": "https://tidelift.com/funding/github/packagist/league/flysystem",
232
+ "type": "tidelift"
233
+ }
234
+ ]
235
+ },
236
+ {
237
+ "name": "php-di/invoker",
238
+ "version": "1.3.3",
239
+ "version_normalized": "1.3.3.0",
240
+ "source": {
241
+ "type": "git",
242
+ "url": "https://github.com/PHP-DI/Invoker.git",
243
+ "reference": "1f4ca63b9abc66109e53b255e465d0ddb5c2e3f7"
244
+ },
245
+ "dist": {
246
+ "type": "zip",
247
+ "url": "https://api.github.com/repos/PHP-DI/Invoker/zipball/1f4ca63b9abc66109e53b255e465d0ddb5c2e3f7",
248
+ "reference": "1f4ca63b9abc66109e53b255e465d0ddb5c2e3f7",
249
+ "shasum": ""
250
+ },
251
+ "require": {
252
+ "container-interop/container-interop": "~1.1"
253
+ },
254
+ "require-dev": {
255
+ "athletic/athletic": "~0.1.8",
256
+ "phpunit/phpunit": "~4.5"
257
+ },
258
+ "time": "2016-07-14T13:09:58+00:00",
259
+ "type": "library",
260
+ "installation-source": "dist",
261
+ "autoload": {
262
+ "psr-4": {
263
+ "Invoker\\": "src/"
264
+ }
265
+ },
266
+ "notification-url": "https://packagist.org/downloads/",
267
+ "license": [
268
+ "MIT"
269
+ ],
270
+ "description": "Generic and extensible callable invoker",
271
+ "homepage": "https://github.com/PHP-DI/Invoker",
272
+ "keywords": [
273
+ "callable",
274
+ "dependency",
275
+ "dependency-injection",
276
+ "injection",
277
+ "invoke",
278
+ "invoker"
279
+ ]
280
+ },
281
+ {
282
+ "name": "php-di/php-di",
283
+ "version": "5.0.0",
284
+ "version_normalized": "5.0.0.0",
285
+ "source": {
286
+ "type": "git",
287
+ "url": "https://github.com/PHP-DI/PHP-DI.git",
288
+ "reference": "c3bbc0d334b888ec8baa75f95b4900ee17b18fa7"
289
+ },
290
+ "dist": {
291
+ "type": "zip",
292
+ "url": "https://api.github.com/repos/PHP-DI/PHP-DI/zipball/c3bbc0d334b888ec8baa75f95b4900ee17b18fa7",
293
+ "reference": "c3bbc0d334b888ec8baa75f95b4900ee17b18fa7",
294
+ "shasum": ""
295
+ },
296
+ "require": {
297
+ "container-interop/container-interop": "~1.0",
298
+ "php": ">=5.4.0",
299
+ "php-di/invoker": "~1.0",
300
+ "php-di/phpdoc-reader": "~2.0"
301
+ },
302
+ "require-dev": {
303
+ "doctrine/annotations": "~1.2",
304
+ "doctrine/cache": "~1.0",
305
+ "mnapoli/phpunit-easymock": "~0.1.4",
306
+ "ocramius/proxy-manager": "~1.0",
307
+ "phpunit/phpunit": "~4.5"
308
+ },
309
+ "suggest": {
310
+ "doctrine/annotations": "Install it if you want to use annotations (version ~1.2)",
311
+ "doctrine/cache": "Install it if you want to use the cache (version ~1.0)",
312
+ "ocramius/proxy-manager": "Install it if you want to use lazy injection (version ~1.0)"
313
+ },
314
+ "time": "2015-06-10T06:16:52+00:00",
315
+ "type": "library",
316
+ "installation-source": "dist",
317
+ "autoload": {
318
+ "psr-4": {
319
+ "DI\\": "src/DI/"
320
+ },
321
+ "files": [
322
+ "src/DI/functions.php"
323
+ ]
324
+ },
325
+ "notification-url": "https://packagist.org/downloads/",
326
+ "license": [
327
+ "MIT"
328
+ ],
329
+ "description": "The dependency injection container for humans",
330
+ "homepage": "http://php-di.org/",
331
+ "keywords": [
332
+ "container",
333
+ "dependency injection",
334
+ "di"
335
+ ]
336
+ },
337
+ {
338
+ "name": "php-di/phpdoc-reader",
339
+ "version": "2.2.1",
340
+ "version_normalized": "2.2.1.0",
341
+ "source": {
342
+ "type": "git",
343
+ "url": "https://github.com/PHP-DI/PhpDocReader.git",
344
+ "reference": "66daff34cbd2627740ffec9469ffbac9f8c8185c"
345
+ },
346
+ "dist": {
347
+ "type": "zip",
348
+ "url": "https://api.github.com/repos/PHP-DI/PhpDocReader/zipball/66daff34cbd2627740ffec9469ffbac9f8c8185c",
349
+ "reference": "66daff34cbd2627740ffec9469ffbac9f8c8185c",
350
+ "shasum": ""
351
+ },
352
+ "require": {
353
+ "php": ">=7.2.0"
354
+ },
355
+ "require-dev": {
356
+ "mnapoli/hard-mode": "~0.3.0",
357
+ "phpunit/phpunit": "^8.5|^9.0"
358
+ },
359
+ "time": "2020-10-12T12:39:22+00:00",
360
+ "type": "library",
361
+ "installation-source": "dist",
362
+ "autoload": {
363
+ "psr-4": {
364
+ "PhpDocReader\\": "src/PhpDocReader"
365
+ }
366
+ },
367
+ "notification-url": "https://packagist.org/downloads/",
368
+ "license": [
369
+ "MIT"
370
+ ],
371
+ "description": "PhpDocReader parses @var and @param values in PHP docblocks (supports namespaced class names with the same resolution rules as PHP)",
372
+ "keywords": [
373
+ "phpdoc",
374
+ "reflection"
375
+ ]
376
+ },
377
+ {
378
+ "name": "psr/container",
379
+ "version": "1.0.0",
380
+ "version_normalized": "1.0.0.0",
381
+ "source": {
382
+ "type": "git",
383
+ "url": "https://github.com/php-fig/container.git",
384
+ "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f"
385
+ },
386
+ "dist": {
387
+ "type": "zip",
388
+ "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
389
+ "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
390
+ "shasum": ""
391
+ },
392
+ "require": {
393
+ "php": ">=5.3.0"
394
+ },
395
+ "time": "2017-02-14T16:28:37+00:00",
396
+ "type": "library",
397
+ "extra": {
398
+ "branch-alias": {
399
+ "dev-master": "1.0.x-dev"
400
+ }
401
+ },
402
+ "installation-source": "dist",
403
+ "autoload": {
404
+ "psr-4": {
405
+ "Psr\\Container\\": "src/"
406
+ }
407
+ },
408
+ "notification-url": "https://packagist.org/downloads/",
409
+ "license": [
410
+ "MIT"
411
+ ],
412
+ "authors": [
413
+ {
414
+ "name": "PHP-FIG",
415
+ "homepage": "http://www.php-fig.org/"
416
+ }
417
+ ],
418
+ "description": "Common Container Interface (PHP FIG PSR-11)",
419
+ "homepage": "https://github.com/php-fig/container",
420
+ "keywords": [
421
+ "PSR-11",
422
+ "container",
423
+ "container-interface",
424
+ "container-interop",
425
+ "psr"
426
+ ]
427
+ },
428
+ {
429
+ "name": "symfony/console",
430
+ "version": "v5.2.1",
431
+ "version_normalized": "5.2.1.0",
432
+ "source": {
433
+ "type": "git",
434
+ "url": "https://github.com/symfony/console.git",
435
+ "reference": "47c02526c532fb381374dab26df05e7313978976"
436
+ },
437
+ "dist": {
438
+ "type": "zip",
439
+ "url": "https://api.github.com/repos/symfony/console/zipball/47c02526c532fb381374dab26df05e7313978976",
440
+ "reference": "47c02526c532fb381374dab26df05e7313978976",
441
+ "shasum": ""
442
+ },
443
+ "require": {
444
+ "php": ">=7.2.5",
445
+ "symfony/polyfill-mbstring": "~1.0",
446
+ "symfony/polyfill-php73": "^1.8",
447
+ "symfony/polyfill-php80": "^1.15",
448
+ "symfony/service-contracts": "^1.1|^2",
449
+ "symfony/string": "^5.1"
450
+ },
451
+ "conflict": {
452
+ "symfony/dependency-injection": "<4.4",
453
+ "symfony/dotenv": "<5.1",
454
+ "symfony/event-dispatcher": "<4.4",
455
+ "symfony/lock": "<4.4",
456
+ "symfony/process": "<4.4"
457
+ },
458
+ "provide": {
459
+ "psr/log-implementation": "1.0"
460
+ },
461
+ "require-dev": {
462
+ "psr/log": "~1.0",
463
+ "symfony/config": "^4.4|^5.0",
464
+ "symfony/dependency-injection": "^4.4|^5.0",
465
+ "symfony/event-dispatcher": "^4.4|^5.0",
466
+ "symfony/lock": "^4.4|^5.0",
467
+ "symfony/process": "^4.4|^5.0",
468
+ "symfony/var-dumper": "^4.4|^5.0"
469
+ },
470
+ "suggest": {
471
+ "psr/log": "For using the console logger",
472
+ "symfony/event-dispatcher": "",
473
+ "symfony/lock": "",
474
+ "symfony/process": ""
475
+ },
476
+ "time": "2020-12-18T08:03:05+00:00",
477
+ "type": "library",
478
+ "installation-source": "dist",
479
+ "autoload": {
480
+ "psr-4": {
481
+ "Symfony\\Component\\Console\\": ""
482
+ },
483
+ "exclude-from-classmap": [
484
+ "/Tests/"
485
+ ]
486
+ },
487
+ "notification-url": "https://packagist.org/downloads/",
488
+ "license": [
489
+ "MIT"
490
+ ],
491
+ "authors": [
492
+ {
493
+ "name": "Fabien Potencier",
494
+ "email": "fabien@symfony.com"
495
+ },
496
+ {
497
+ "name": "Symfony Community",
498
+ "homepage": "https://symfony.com/contributors"
499
+ }
500
+ ],
501
+ "description": "Symfony Console Component",
502
+ "homepage": "https://symfony.com",
503
+ "keywords": [
504
+ "cli",
505
+ "command line",
506
+ "console",
507
+ "terminal"
508
+ ],
509
+ "funding": [
510
+ {
511
+ "url": "https://symfony.com/sponsor",
512
+ "type": "custom"
513
+ },
514
+ {
515
+ "url": "https://github.com/fabpot",
516
+ "type": "github"
517
+ },
518
+ {
519
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
520
+ "type": "tidelift"
521
+ }
522
+ ]
523
+ },
524
+ {
525
+ "name": "symfony/finder",
526
+ "version": "v5.2.1",
527
+ "version_normalized": "5.2.1.0",
528
+ "source": {
529
+ "type": "git",
530
+ "url": "https://github.com/symfony/finder.git",
531
+ "reference": "0b9231a5922fd7287ba5b411893c0ecd2733e5ba"
532
+ },
533
+ "dist": {
534
+ "type": "zip",
535
+ "url": "https://api.github.com/repos/symfony/finder/zipball/0b9231a5922fd7287ba5b411893c0ecd2733e5ba",
536
+ "reference": "0b9231a5922fd7287ba5b411893c0ecd2733e5ba",
537
+ "shasum": ""
538
+ },
539
+ "require": {
540
+ "php": ">=7.2.5"
541
+ },
542
+ "time": "2020-12-08T17:02:38+00:00",
543
+ "type": "library",
544
+ "installation-source": "dist",
545
+ "autoload": {
546
+ "psr-4": {
547
+ "Symfony\\Component\\Finder\\": ""
548
+ },
549
+ "exclude-from-classmap": [
550
+ "/Tests/"
551
+ ]
552
+ },
553
+ "notification-url": "https://packagist.org/downloads/",
554
+ "license": [
555
+ "MIT"
556
+ ],
557
+ "authors": [
558
+ {
559
+ "name": "Fabien Potencier",
560
+ "email": "fabien@symfony.com"
561
+ },
562
+ {
563
+ "name": "Symfony Community",
564
+ "homepage": "https://symfony.com/contributors"
565
+ }
566
+ ],
567
+ "description": "Symfony Finder Component",
568
+ "homepage": "https://symfony.com",
569
+ "funding": [
570
+ {
571
+ "url": "https://symfony.com/sponsor",
572
+ "type": "custom"
573
+ },
574
+ {
575
+ "url": "https://github.com/fabpot",
576
+ "type": "github"
577
+ },
578
+ {
579
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
580
+ "type": "tidelift"
581
+ }
582
+ ]
583
+ },
584
+ {
585
+ "name": "symfony/polyfill-ctype",
586
+ "version": "v1.22.0",
587
+ "version_normalized": "1.22.0.0",
588
+ "source": {
589
+ "type": "git",
590
+ "url": "https://github.com/symfony/polyfill-ctype.git",
591
+ "reference": "c6c942b1ac76c82448322025e084cadc56048b4e"
592
+ },
593
+ "dist": {
594
+ "type": "zip",
595
+ "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/c6c942b1ac76c82448322025e084cadc56048b4e",
596
+ "reference": "c6c942b1ac76c82448322025e084cadc56048b4e",
597
+ "shasum": ""
598
+ },
599
+ "require": {
600
+ "php": ">=7.1"
601
+ },
602
+ "suggest": {
603
+ "ext-ctype": "For best performance"
604
+ },
605
+ "time": "2021-01-07T16:49:33+00:00",
606
+ "type": "library",
607
+ "extra": {
608
+ "branch-alias": {
609
+ "dev-main": "1.22-dev"
610
+ },
611
+ "thanks": {
612
+ "name": "symfony/polyfill",
613
+ "url": "https://github.com/symfony/polyfill"
614
+ }
615
+ },
616
+ "installation-source": "dist",
617
+ "autoload": {
618
+ "psr-4": {
619
+ "Symfony\\Polyfill\\Ctype\\": ""
620
+ },
621
+ "files": [
622
+ "bootstrap.php"
623
+ ]
624
+ },
625
+ "notification-url": "https://packagist.org/downloads/",
626
+ "license": [
627
+ "MIT"
628
+ ],
629
+ "authors": [
630
+ {
631
+ "name": "Gert de Pagter",
632
+ "email": "BackEndTea@gmail.com"
633
+ },
634
+ {
635
+ "name": "Symfony Community",
636
+ "homepage": "https://symfony.com/contributors"
637
+ }
638
+ ],
639
+ "description": "Symfony polyfill for ctype functions",
640
+ "homepage": "https://symfony.com",
641
+ "keywords": [
642
+ "compatibility",
643
+ "ctype",
644
+ "polyfill",
645
+ "portable"
646
+ ],
647
+ "funding": [
648
+ {
649
+ "url": "https://symfony.com/sponsor",
650
+ "type": "custom"
651
+ },
652
+ {
653
+ "url": "https://github.com/fabpot",
654
+ "type": "github"
655
+ },
656
+ {
657
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
658
+ "type": "tidelift"
659
+ }
660
+ ]
661
+ },
662
+ {
663
+ "name": "symfony/polyfill-intl-grapheme",
664
+ "version": "v1.22.0",
665
+ "version_normalized": "1.22.0.0",
666
+ "source": {
667
+ "type": "git",
668
+ "url": "https://github.com/symfony/polyfill-intl-grapheme.git",
669
+ "reference": "267a9adeb8ecb8071040a740930e077cdfb987af"
670
+ },
671
+ "dist": {
672
+ "type": "zip",
673
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/267a9adeb8ecb8071040a740930e077cdfb987af",
674
+ "reference": "267a9adeb8ecb8071040a740930e077cdfb987af",
675
+ "shasum": ""
676
+ },
677
+ "require": {
678
+ "php": ">=7.1"
679
+ },
680
+ "suggest": {
681
+ "ext-intl": "For best performance"
682
+ },
683
+ "time": "2021-01-07T16:49:33+00:00",
684
+ "type": "library",
685
+ "extra": {
686
+ "branch-alias": {
687
+ "dev-main": "1.22-dev"
688
+ },
689
+ "thanks": {
690
+ "name": "symfony/polyfill",
691
+ "url": "https://github.com/symfony/polyfill"
692
+ }
693
+ },
694
+ "installation-source": "dist",
695
+ "autoload": {
696
+ "psr-4": {
697
+ "Symfony\\Polyfill\\Intl\\Grapheme\\": ""
698
+ },
699
+ "files": [
700
+ "bootstrap.php"
701
+ ]
702
+ },
703
+ "notification-url": "https://packagist.org/downloads/",
704
+ "license": [
705
+ "MIT"
706
+ ],
707
+ "authors": [
708
+ {
709
+ "name": "Nicolas Grekas",
710
+ "email": "p@tchwork.com"
711
+ },
712
+ {
713
+ "name": "Symfony Community",
714
+ "homepage": "https://symfony.com/contributors"
715
+ }
716
+ ],
717
+ "description": "Symfony polyfill for intl's grapheme_* functions",
718
+ "homepage": "https://symfony.com",
719
+ "keywords": [
720
+ "compatibility",
721
+ "grapheme",
722
+ "intl",
723
+ "polyfill",
724
+ "portable",
725
+ "shim"
726
+ ],
727
+ "funding": [
728
+ {
729
+ "url": "https://symfony.com/sponsor",
730
+ "type": "custom"
731
+ },
732
+ {
733
+ "url": "https://github.com/fabpot",
734
+ "type": "github"
735
+ },
736
+ {
737
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
738
+ "type": "tidelift"
739
+ }
740
+ ]
741
+ },
742
+ {
743
+ "name": "symfony/polyfill-intl-normalizer",
744
+ "version": "v1.22.0",
745
+ "version_normalized": "1.22.0.0",
746
+ "source": {
747
+ "type": "git",
748
+ "url": "https://github.com/symfony/polyfill-intl-normalizer.git",
749
+ "reference": "6e971c891537eb617a00bb07a43d182a6915faba"
750
+ },
751
+ "dist": {
752
+ "type": "zip",
753
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/6e971c891537eb617a00bb07a43d182a6915faba",
754
+ "reference": "6e971c891537eb617a00bb07a43d182a6915faba",
755
+ "shasum": ""
756
+ },
757
+ "require": {
758
+ "php": ">=7.1"
759
+ },
760
+ "suggest": {
761
+ "ext-intl": "For best performance"
762
+ },
763
+ "time": "2021-01-07T17:09:11+00:00",
764
+ "type": "library",
765
+ "extra": {
766
+ "branch-alias": {
767
+ "dev-main": "1.22-dev"
768
+ },
769
+ "thanks": {
770
+ "name": "symfony/polyfill",
771
+ "url": "https://github.com/symfony/polyfill"
772
+ }
773
+ },
774
+ "installation-source": "dist",
775
+ "autoload": {
776
+ "psr-4": {
777
+ "Symfony\\Polyfill\\Intl\\Normalizer\\": ""
778
+ },
779
+ "files": [
780
+ "bootstrap.php"
781
+ ],
782
+ "classmap": [
783
+ "Resources/stubs"
784
+ ]
785
+ },
786
+ "notification-url": "https://packagist.org/downloads/",
787
+ "license": [
788
+ "MIT"
789
+ ],
790
+ "authors": [
791
+ {
792
+ "name": "Nicolas Grekas",
793
+ "email": "p@tchwork.com"
794
+ },
795
+ {
796
+ "name": "Symfony Community",
797
+ "homepage": "https://symfony.com/contributors"
798
+ }
799
+ ],
800
+ "description": "Symfony polyfill for intl's Normalizer class and related functions",
801
+ "homepage": "https://symfony.com",
802
+ "keywords": [
803
+ "compatibility",
804
+ "intl",
805
+ "normalizer",
806
+ "polyfill",
807
+ "portable",
808
+ "shim"
809
+ ],
810
+ "funding": [
811
+ {
812
+ "url": "https://symfony.com/sponsor",
813
+ "type": "custom"
814
+ },
815
+ {
816
+ "url": "https://github.com/fabpot",
817
+ "type": "github"
818
+ },
819
+ {
820
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
821
+ "type": "tidelift"
822
+ }
823
+ ]
824
+ },
825
+ {
826
+ "name": "symfony/polyfill-mbstring",
827
+ "version": "v1.22.0",
828
+ "version_normalized": "1.22.0.0",
829
+ "source": {
830
+ "type": "git",
831
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
832
+ "reference": "f377a3dd1fde44d37b9831d68dc8dea3ffd28e13"
833
+ },
834
+ "dist": {
835
+ "type": "zip",
836
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/f377a3dd1fde44d37b9831d68dc8dea3ffd28e13",
837
+ "reference": "f377a3dd1fde44d37b9831d68dc8dea3ffd28e13",
838
+ "shasum": ""
839
+ },
840
+ "require": {
841
+ "php": ">=7.1"
842
+ },
843
+ "suggest": {
844
+ "ext-mbstring": "For best performance"
845
+ },
846
+ "time": "2021-01-07T16:49:33+00:00",
847
+ "type": "library",
848
+ "extra": {
849
+ "branch-alias": {
850
+ "dev-main": "1.22-dev"
851
+ },
852
+ "thanks": {
853
+ "name": "symfony/polyfill",
854
+ "url": "https://github.com/symfony/polyfill"
855
+ }
856
+ },
857
+ "installation-source": "dist",
858
+ "autoload": {
859
+ "psr-4": {
860
+ "Symfony\\Polyfill\\Mbstring\\": ""
861
+ },
862
+ "files": [
863
+ "bootstrap.php"
864
+ ]
865
+ },
866
+ "notification-url": "https://packagist.org/downloads/",
867
+ "license": [
868
+ "MIT"
869
+ ],
870
+ "authors": [
871
+ {
872
+ "name": "Nicolas Grekas",
873
+ "email": "p@tchwork.com"
874
+ },
875
+ {
876
+ "name": "Symfony Community",
877
+ "homepage": "https://symfony.com/contributors"
878
+ }
879
+ ],
880
+ "description": "Symfony polyfill for the Mbstring extension",
881
+ "homepage": "https://symfony.com",
882
+ "keywords": [
883
+ "compatibility",
884
+ "mbstring",
885
+ "polyfill",
886
+ "portable",
887
+ "shim"
888
+ ],
889
+ "funding": [
890
+ {
891
+ "url": "https://symfony.com/sponsor",
892
+ "type": "custom"
893
+ },
894
+ {
895
+ "url": "https://github.com/fabpot",
896
+ "type": "github"
897
+ },
898
+ {
899
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
900
+ "type": "tidelift"
901
+ }
902
+ ]
903
+ },
904
+ {
905
+ "name": "symfony/polyfill-php73",
906
+ "version": "v1.22.0",
907
+ "version_normalized": "1.22.0.0",
908
+ "source": {
909
+ "type": "git",
910
+ "url": "https://github.com/symfony/polyfill-php73.git",
911
+ "reference": "a678b42e92f86eca04b7fa4c0f6f19d097fb69e2"
912
+ },
913
+ "dist": {
914
+ "type": "zip",
915
+ "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/a678b42e92f86eca04b7fa4c0f6f19d097fb69e2",
916
+ "reference": "a678b42e92f86eca04b7fa4c0f6f19d097fb69e2",
917
+ "shasum": ""
918
+ },
919
+ "require": {
920
+ "php": ">=7.1"
921
+ },
922
+ "time": "2021-01-07T16:49:33+00:00",
923
+ "type": "library",
924
+ "extra": {
925
+ "branch-alias": {
926
+ "dev-main": "1.22-dev"
927
+ },
928
+ "thanks": {
929
+ "name": "symfony/polyfill",
930
+ "url": "https://github.com/symfony/polyfill"
931
+ }
932
+ },
933
+ "installation-source": "dist",
934
+ "autoload": {
935
+ "psr-4": {
936
+ "Symfony\\Polyfill\\Php73\\": ""
937
+ },
938
+ "files": [
939
+ "bootstrap.php"
940
+ ],
941
+ "classmap": [
942
+ "Resources/stubs"
943
+ ]
944
+ },
945
+ "notification-url": "https://packagist.org/downloads/",
946
+ "license": [
947
+ "MIT"
948
+ ],
949
+ "authors": [
950
+ {
951
+ "name": "Nicolas Grekas",
952
+ "email": "p@tchwork.com"
953
+ },
954
+ {
955
+ "name": "Symfony Community",
956
+ "homepage": "https://symfony.com/contributors"
957
+ }
958
+ ],
959
+ "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions",
960
+ "homepage": "https://symfony.com",
961
+ "keywords": [
962
+ "compatibility",
963
+ "polyfill",
964
+ "portable",
965
+ "shim"
966
+ ],
967
+ "funding": [
968
+ {
969
+ "url": "https://symfony.com/sponsor",
970
+ "type": "custom"
971
+ },
972
+ {
973
+ "url": "https://github.com/fabpot",
974
+ "type": "github"
975
+ },
976
+ {
977
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
978
+ "type": "tidelift"
979
+ }
980
+ ]
981
+ },
982
+ {
983
+ "name": "symfony/polyfill-php80",
984
+ "version": "v1.22.0",
985
+ "version_normalized": "1.22.0.0",
986
+ "source": {
987
+ "type": "git",
988
+ "url": "https://github.com/symfony/polyfill-php80.git",
989
+ "reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91"
990
+ },
991
+ "dist": {
992
+ "type": "zip",
993
+ "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/dc3063ba22c2a1fd2f45ed856374d79114998f91",
994
+ "reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91",
995
+ "shasum": ""
996
+ },
997
+ "require": {
998
+ "php": ">=7.1"
999
+ },
1000
+ "time": "2021-01-07T16:49:33+00:00",
1001
+ "type": "library",
1002
+ "extra": {
1003
+ "branch-alias": {
1004
+ "dev-main": "1.22-dev"
1005
+ },
1006
+ "thanks": {
1007
+ "name": "symfony/polyfill",
1008
+ "url": "https://github.com/symfony/polyfill"
1009
+ }
1010
+ },
1011
+ "installation-source": "dist",
1012
+ "autoload": {
1013
+ "psr-4": {
1014
+ "Symfony\\Polyfill\\Php80\\": ""
1015
+ },
1016
+ "files": [
1017
+ "bootstrap.php"
1018
+ ],
1019
+ "classmap": [
1020
+ "Resources/stubs"
1021
+ ]
1022
+ },
1023
+ "notification-url": "https://packagist.org/downloads/",
1024
+ "license": [
1025
+ "MIT"
1026
+ ],
1027
+ "authors": [
1028
+ {
1029
+ "name": "Ion Bazan",
1030
+ "email": "ion.bazan@gmail.com"
1031
+ },
1032
+ {
1033
+ "name": "Nicolas Grekas",
1034
+ "email": "p@tchwork.com"
1035
+ },
1036
+ {
1037
+ "name": "Symfony Community",
1038
+ "homepage": "https://symfony.com/contributors"
1039
+ }
1040
+ ],
1041
+ "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
1042
+ "homepage": "https://symfony.com",
1043
+ "keywords": [
1044
+ "compatibility",
1045
+ "polyfill",
1046
+ "portable",
1047
+ "shim"
1048
+ ],
1049
+ "funding": [
1050
+ {
1051
+ "url": "https://symfony.com/sponsor",
1052
+ "type": "custom"
1053
+ },
1054
+ {
1055
+ "url": "https://github.com/fabpot",
1056
+ "type": "github"
1057
+ },
1058
+ {
1059
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
1060
+ "type": "tidelift"
1061
+ }
1062
+ ]
1063
+ },
1064
+ {
1065
+ "name": "symfony/service-contracts",
1066
+ "version": "v2.2.0",
1067
+ "version_normalized": "2.2.0.0",
1068
+ "source": {
1069
+ "type": "git",
1070
+ "url": "https://github.com/symfony/service-contracts.git",
1071
+ "reference": "d15da7ba4957ffb8f1747218be9e1a121fd298a1"
1072
+ },
1073
+ "dist": {
1074
+ "type": "zip",
1075
+ "url": "https://api.github.com/repos/symfony/service-contracts/zipball/d15da7ba4957ffb8f1747218be9e1a121fd298a1",
1076
+ "reference": "d15da7ba4957ffb8f1747218be9e1a121fd298a1",
1077
+ "shasum": ""
1078
+ },
1079
+ "require": {
1080
+ "php": ">=7.2.5",
1081
+ "psr/container": "^1.0"
1082
+ },
1083
+ "suggest": {
1084
+ "symfony/service-implementation": ""
1085
+ },
1086
+ "time": "2020-09-07T11:33:47+00:00",
1087
+ "type": "library",
1088
+ "extra": {
1089
+ "branch-alias": {
1090
+ "dev-master": "2.2-dev"
1091
+ },
1092
+ "thanks": {
1093
+ "name": "symfony/contracts",
1094
+ "url": "https://github.com/symfony/contracts"
1095
+ }
1096
+ },
1097
+ "installation-source": "dist",
1098
+ "autoload": {
1099
+ "psr-4": {
1100
+ "Symfony\\Contracts\\Service\\": ""
1101
+ }
1102
+ },
1103
+ "notification-url": "https://packagist.org/downloads/",
1104
+ "license": [
1105
+ "MIT"
1106
+ ],
1107
+ "authors": [
1108
+ {
1109
+ "name": "Nicolas Grekas",
1110
+ "email": "p@tchwork.com"
1111
+ },
1112
+ {
1113
+ "name": "Symfony Community",
1114
+ "homepage": "https://symfony.com/contributors"
1115
+ }
1116
+ ],
1117
+ "description": "Generic abstractions related to writing services",
1118
+ "homepage": "https://symfony.com",
1119
+ "keywords": [
1120
+ "abstractions",
1121
+ "contracts",
1122
+ "decoupling",
1123
+ "interfaces",
1124
+ "interoperability",
1125
+ "standards"
1126
+ ],
1127
+ "funding": [
1128
+ {
1129
+ "url": "https://symfony.com/sponsor",
1130
+ "type": "custom"
1131
+ },
1132
+ {
1133
+ "url": "https://github.com/fabpot",
1134
+ "type": "github"
1135
+ },
1136
+ {
1137
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
1138
+ "type": "tidelift"
1139
+ }
1140
+ ]
1141
+ },
1142
+ {
1143
+ "name": "symfony/string",
1144
+ "version": "v5.2.1",
1145
+ "version_normalized": "5.2.1.0",
1146
+ "source": {
1147
+ "type": "git",
1148
+ "url": "https://github.com/symfony/string.git",
1149
+ "reference": "5bd67751d2e3f7d6f770c9154b8fbcb2aa05f7ed"
1150
+ },
1151
+ "dist": {
1152
+ "type": "zip",
1153
+ "url": "https://api.github.com/repos/symfony/string/zipball/5bd67751d2e3f7d6f770c9154b8fbcb2aa05f7ed",
1154
+ "reference": "5bd67751d2e3f7d6f770c9154b8fbcb2aa05f7ed",
1155
+ "shasum": ""
1156
+ },
1157
+ "require": {
1158
+ "php": ">=7.2.5",
1159
+ "symfony/polyfill-ctype": "~1.8",
1160
+ "symfony/polyfill-intl-grapheme": "~1.0",
1161
+ "symfony/polyfill-intl-normalizer": "~1.0",
1162
+ "symfony/polyfill-mbstring": "~1.0",
1163
+ "symfony/polyfill-php80": "~1.15"
1164
+ },
1165
+ "require-dev": {
1166
+ "symfony/error-handler": "^4.4|^5.0",
1167
+ "symfony/http-client": "^4.4|^5.0",
1168
+ "symfony/translation-contracts": "^1.1|^2",
1169
+ "symfony/var-exporter": "^4.4|^5.0"
1170
+ },
1171
+ "time": "2020-12-05T07:33:16+00:00",
1172
+ "type": "library",
1173
+ "installation-source": "dist",
1174
+ "autoload": {
1175
+ "psr-4": {
1176
+ "Symfony\\Component\\String\\": ""
1177
+ },
1178
+ "files": [
1179
+ "Resources/functions.php"
1180
+ ],
1181
+ "exclude-from-classmap": [
1182
+ "/Tests/"
1183
+ ]
1184
+ },
1185
+ "notification-url": "https://packagist.org/downloads/",
1186
+ "license": [
1187
+ "MIT"
1188
+ ],
1189
+ "authors": [
1190
+ {
1191
+ "name": "Nicolas Grekas",
1192
+ "email": "p@tchwork.com"
1193
+ },
1194
+ {
1195
+ "name": "Symfony Community",
1196
+ "homepage": "https://symfony.com/contributors"
1197
+ }
1198
+ ],
1199
+ "description": "Symfony String component",
1200
+ "homepage": "https://symfony.com",
1201
+ "keywords": [
1202
+ "grapheme",
1203
+ "i18n",
1204
+ "string",
1205
+ "unicode",
1206
+ "utf-8",
1207
+ "utf8"
1208
+ ],
1209
+ "funding": [
1210
+ {
1211
+ "url": "https://symfony.com/sponsor",
1212
+ "type": "custom"
1213
+ },
1214
+ {
1215
+ "url": "https://github.com/fabpot",
1216
+ "type": "github"
1217
+ },
1218
+ {
1219
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
1220
+ "type": "tidelift"
1221
+ }
1222
+ ]
1223
+ }
1224
+ ]
addons/view/admin/settings/available-addon-callback.php CHANGED
@@ -7,12 +7,12 @@ require_once( ABSPATH . '/wp-admin/includes/translation-install.php' );
7
  ?>
8
  <div class="postbox cookiebot-addon">
9
  <p>
10
- <label for="<?php echo 'enabled_' . $addon->get_option_name(); ?>"><?php _e( 'Enable', 'cookie' ); ?></label>
11
  <input type="checkbox" id="<?php echo 'enabled_' . $addon->get_option_name(); ?>"
12
  name="cookiebot_available_addons[<?php echo $addon->get_option_name() ?>][enabled]"
13
  value="1" <?php checked( 1, $addon->is_addon_enabled(), true ); ?> />
14
  </p>
15
- <p><?php _e( 'Check one or multiple cookie types:', 'cookiebot' ); ?></p>
16
  <ul class="cookietypes">
17
  <li><input type="checkbox" id="cookie_type_preferences_<?php echo $addon->get_option_name(); ?>"
18
  value="preferences"
@@ -32,7 +32,7 @@ require_once( ABSPATH . '/wp-admin/includes/translation-install.php' );
32
  </ul>
33
 
34
  <p>
35
- <label><?php _e( 'Display a placeholder', 'cookiebot-addons' ); ?></label>
36
  <input type="checkbox"
37
  class="placeholder_enable"
38
  data-addon="<?php echo $addon->get_option_name(); ?>"
@@ -48,14 +48,14 @@ require_once( ABSPATH . '/wp-admin/includes/translation-install.php' );
48
  <?php foreach ( $addon->get_placeholders() as $placeholder_lang => $placeholder_value ): ?>
49
  <div class="placeholder_content submitbox">
50
  <p>
51
- <label><?php _e( 'Language', 'cookiebot-addons' ); ?></label>
52
  <?php
53
  $name = 'cookiebot_available_addons[' . $addon->get_option_name() . '][placeholder][languages][' . $placeholder_lang . ']';
54
  echo cookiebot_addons_get_dropdown_languages( 'placeholder_select_language', $name, $placeholder_lang );
55
  ?>
56
  <?php if ( $count != 0 ): ?>
57
  <a href=""
58
- class="submitdelete deletion"><?php _e( 'Remove language', 'cookiebot-addons' ); ?></a>
59
  <?php endif; ?>
60
  </p>
61
  <p>
@@ -69,20 +69,7 @@ require_once( ABSPATH . '/wp-admin/includes/translation-install.php' );
69
  <?php else: ?>
70
  <div class="placeholder_content">
71
  <p>
72
- <label><?php _e( 'Language', 'cookiebot-addons' ); ?></label>
73
- <select class="placeholder_select_language"
74
- name="cookiebot_available_addons[<?php echo $addon->get_option_name(); ?>][placeholder][languages][site-default]">
75
- <?php
76
- if ( function_exists( 'cookiebot' ) ) {
77
- ?>
78
- <option value=""><?php _e( 'Default (Autodetect)', 'cookiebot' ); ?></option>
79
- <?php
80
- foreach ( wp_get_available_translations() as $key => $value ) {
81
- echo '<option value="' . $key . '">' . $value . '</option>';
82
- }
83
- }
84
- ?>
85
- </select>
86
  <?php
87
  $name = 'cookiebot_available_addons[' . $addon->get_option_name() . '][placeholder][languages][site-default]';
88
  echo cookiebot_addons_get_dropdown_languages( 'placeholder_select_language', $name, '' );
@@ -98,7 +85,7 @@ require_once( ABSPATH . '/wp-admin/includes/translation-install.php' );
98
 
99
  <p class="add_placeholder_language">
100
  <button class="btn_add_language button button-secondary"
101
- data-addon="<?php echo $addon->get_option_name(); ?>"><?php _e( '+ Add language', 'cookiebot-addons' ); ?></button>
102
  </p>
103
  </div>
104
  <?php
7
  ?>
8
  <div class="postbox cookiebot-addon">
9
  <p>
10
+ <label for="<?php echo 'enabled_' . $addon->get_option_name(); ?>"><?php esc_html_e( 'Enable', 'cookie' ); ?></label>
11
  <input type="checkbox" id="<?php echo 'enabled_' . $addon->get_option_name(); ?>"
12
  name="cookiebot_available_addons[<?php echo $addon->get_option_name() ?>][enabled]"
13
  value="1" <?php checked( 1, $addon->is_addon_enabled(), true ); ?> />
14
  </p>
15
+ <p><?php esc_html_e( 'Check one or multiple cookie types:', 'cookiebot' ); ?></p>
16
  <ul class="cookietypes">
17
  <li><input type="checkbox" id="cookie_type_preferences_<?php echo $addon->get_option_name(); ?>"
18
  value="preferences"
32
  </ul>
33
 
34
  <p>
35
+ <label><?php esc_html_e( 'Display a placeholder', 'cookiebot-addons' ); ?></label>
36
  <input type="checkbox"
37
  class="placeholder_enable"
38
  data-addon="<?php echo $addon->get_option_name(); ?>"
48
  <?php foreach ( $addon->get_placeholders() as $placeholder_lang => $placeholder_value ): ?>
49
  <div class="placeholder_content submitbox">
50
  <p>
51
+ <label><?php esc_html_e( 'Language', 'cookiebot-addons' ); ?></label>
52
  <?php
53
  $name = 'cookiebot_available_addons[' . $addon->get_option_name() . '][placeholder][languages][' . $placeholder_lang . ']';
54
  echo cookiebot_addons_get_dropdown_languages( 'placeholder_select_language', $name, $placeholder_lang );
55
  ?>
56
  <?php if ( $count != 0 ): ?>
57
  <a href=""
58
+ class="submitdelete deletion"><?php esc_html_e( 'Remove language', 'cookiebot-addons' ); ?></a>
59
  <?php endif; ?>
60
  </p>
61
  <p>
69
  <?php else: ?>
70
  <div class="placeholder_content">
71
  <p>
72
+ <label><?php esc_html_e( 'Language', 'cookiebot-addons' ); ?></label>
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  <?php
74
  $name = 'cookiebot_available_addons[' . $addon->get_option_name() . '][placeholder][languages][site-default]';
75
  echo cookiebot_addons_get_dropdown_languages( 'placeholder_select_language', $name, '' );
85
 
86
  <p class="add_placeholder_language">
87
  <button class="btn_add_language button button-secondary"
88
+ data-addon="<?php echo $addon->get_option_name(); ?>"><?php esc_html_e( '+ Add language', 'cookiebot-addons' ); ?></button>
89
  </p>
90
  </div>
91
  <?php
addons/view/admin/settings/jetpack-addon-callback.php CHANGED
@@ -5,13 +5,13 @@ $addon = $args['addon'];
5
  ?>
6
  <div class="postbox cookiebot-addon">
7
  <p>
8
- <label for="<?php echo 'enabled_' . $widget->get_widget_option_name(); ?>"><?php _e( 'Enable', 'cookiebot' ); ?></label>
9
  <input type="checkbox" id="<?php echo 'enabled_' . $widget->get_widget_option_name(); ?>"
10
  name="cookiebot_jetpack_addon[<?php echo $widget->get_widget_option_name(); ?>][enabled]"
11
  value="1" <?php checked( 1, $widget->is_widget_enabled(), true ); ?> />
12
  </p>
13
  <p>
14
- <span><?php _e( 'Check one or multiple cookie types:', 'cookiebot' ); ?></span><br>
15
  <ul class="cookietypes">
16
  <li><input type="checkbox" id="cookie_type_preferences_<?php echo $widget->get_widget_option_name(); ?>"
17
  value="preferences"
@@ -32,7 +32,7 @@ $addon = $args['addon'];
32
  </p>
33
 
34
  <p>
35
- <label><?php _e( 'Display a placeholder', 'cookiebot' ); ?></label>
36
  <input type="checkbox"
37
  class="placeholder_enable"
38
  data-addon="<?php echo $widget->get_widget_option_name(); ?>"
@@ -48,14 +48,14 @@ $addon = $args['addon'];
48
  <?php foreach ( $widget->get_widget_placeholders() as $placeholder_lang => $placeholder_value ): ?>
49
  <div class="placeholder_content submitbox">
50
  <p>
51
- <label><?php _e( 'Language', 'cookiebot-addons' ); ?></label>
52
  <?php
53
  $name = 'cookiebot_jetpack_addon[' . $widget->get_widget_option_name() . '][placeholder][languages][' . $placeholder_lang . ']';
54
  echo cookiebot_addons_get_dropdown_languages( 'placeholder_select_language', $name, $placeholder_lang );
55
  ?>
56
  <?php if ( $count != 0 ): ?>
57
  <a href=""
58
- class="submitdelete deletion"><?php _e( 'Remove language', 'cookiebot-addons' ); ?></a>
59
  <?php endif; ?>
60
  </p>
61
  <p>
@@ -69,7 +69,7 @@ $addon = $args['addon'];
69
  <?php else: ?>
70
  <div class="placeholder_content">
71
  <p>
72
- <label><?php _e( 'Language', 'cookiebot-addons' ); ?></label>
73
  <?php
74
  $name = 'cookiebot_jetpack_addon[' . $widget->get_widget_option_name() . '][placeholder][languages][site-default]';
75
  echo cookiebot_addons_get_dropdown_languages( 'placeholder_select_language', $name, '' );
@@ -86,7 +86,7 @@ $addon = $args['addon'];
86
 
87
  <p class="add_placeholder_language">
88
  <button class="btn_add_language button button-secondary"
89
- data-addon="<?php echo $widget->get_widget_option_name(); ?>"><?php _e( '+ Add language', 'cookiebot-addons' ); ?></button>
90
  </p>
91
  </div>
92
  </div>
5
  ?>
6
  <div class="postbox cookiebot-addon">
7
  <p>
8
+ <label for="<?php echo 'enabled_' . $widget->get_widget_option_name(); ?>"><?php esc_html_e( 'Enable', 'cookiebot' ); ?></label>
9
  <input type="checkbox" id="<?php echo 'enabled_' . $widget->get_widget_option_name(); ?>"
10
  name="cookiebot_jetpack_addon[<?php echo $widget->get_widget_option_name(); ?>][enabled]"
11
  value="1" <?php checked( 1, $widget->is_widget_enabled(), true ); ?> />
12
  </p>
13
  <p>
14
+ <span><?php esc_html_e( 'Check one or multiple cookie types:', 'cookiebot' ); ?></span><br>
15
  <ul class="cookietypes">
16
  <li><input type="checkbox" id="cookie_type_preferences_<?php echo $widget->get_widget_option_name(); ?>"
17
  value="preferences"
32
  </p>
33
 
34
  <p>
35
+ <label><?php esc_html_e( 'Display a placeholder', 'cookiebot' ); ?></label>
36
  <input type="checkbox"
37
  class="placeholder_enable"
38
  data-addon="<?php echo $widget->get_widget_option_name(); ?>"
48
  <?php foreach ( $widget->get_widget_placeholders() as $placeholder_lang => $placeholder_value ): ?>
49
  <div class="placeholder_content submitbox">
50
  <p>
51
+ <label><?php esc_html_e( 'Language', 'cookiebot-addons' ); ?></label>
52
  <?php
53
  $name = 'cookiebot_jetpack_addon[' . $widget->get_widget_option_name() . '][placeholder][languages][' . $placeholder_lang . ']';
54
  echo cookiebot_addons_get_dropdown_languages( 'placeholder_select_language', $name, $placeholder_lang );
55
  ?>
56
  <?php if ( $count != 0 ): ?>
57
  <a href=""
58
+ class="submitdelete deletion"><?php esc_html_e( 'Remove language', 'cookiebot-addons' ); ?></a>
59
  <?php endif; ?>
60
  </p>
61
  <p>
69
  <?php else: ?>
70
  <div class="placeholder_content">
71
  <p>
72
+ <label><?php esc_html_e( 'Language', 'cookiebot-addons' ); ?></label>
73
  <?php
74
  $name = 'cookiebot_jetpack_addon[' . $widget->get_widget_option_name() . '][placeholder][languages][site-default]';
75
  echo cookiebot_addons_get_dropdown_languages( 'placeholder_select_language', $name, '' );
86
 
87
  <p class="add_placeholder_language">
88
  <button class="btn_add_language button button-secondary"
89
+ data-addon="<?php echo $widget->get_widget_option_name(); ?>"><?php esc_html_e( '+ Add language', 'cookiebot-addons' ); ?></button>
90
  </p>
91
  </div>
92
  </div>
addons/view/admin/settings/setting-page.php CHANGED
@@ -2,20 +2,20 @@
2
  <div class="wrap">
3
 
4
  <div id="icon-themes" class="icon32"></div>
5
- <h2><?php _e( 'Prior consent', 'cookiebot' ); ?></h2>
6
  <div class="notice inline notice-warning notice-alt cookiebot-notice">
7
  <p>
8
- <?php _e( 'These add-ons are produced by an open-source community of developers. This is done to help make it easier for Wordpress users to implement ‘prior consent’ for cookies and trackers set by plugins that do not offer this as a built-in functionality.' ); ?>
9
  </p>
10
  <p>
11
- <?php _e( 'The add-ons are currently the best alternative to a Wordpress Core framework that can signal the user’s consent state to other plugins (if and when this will be implemented is unknown) and to those plugins who do not yet offer native support for Cookiebot built into the plugin itself.' ); ?>
12
  </p>
13
  <p>
14
- <?php _e( 'We do not assume any responsibility for the use of these add-ons. If one of the plugins that the add-ons hook into makes a ‘breaking change’, there may be a period of time where the add-on will not work properly until it has been updated to accommodate the changes in the plugin.' ); ?>
15
  </p>
16
  <p>
17
  <strong>
18
- <?php echo sprintf( __( 'If your favourite plugin isn\'t supported you\'re welcome to contribute or request on our <a href="%s" target="_blank">Github development page.</a>' ), 'https://github.com/CybotAS/CookiebotAddons' ); ?>
19
  </strong>
20
  </p>
21
 
@@ -25,7 +25,7 @@
25
  ?>
26
  <p><strong>
27
  <?php
28
- _e('This feature is only available in PHP 5.4 and above.');
29
  ?>
30
  </strong></p>
31
  <?php
2
  <div class="wrap">
3
 
4
  <div id="icon-themes" class="icon32"></div>
5
+ <h2><?php esc_html_e( 'Prior consent', 'cookiebot' ); ?></h2>
6
  <div class="notice inline notice-warning notice-alt cookiebot-notice">
7
  <p>
8
+ <?php esc_html_e( 'These add-ons are produced by an open-source community of developers. This is done to help make it easier for Wordpress users to implement ‘prior consent’ for cookies and trackers set by plugins that do not offer this as a built-in functionality.' ); ?>
9
  </p>
10
  <p>
11
+ <?php esc_html_e( 'The add-ons are currently the best alternative to a Wordpress Core framework that can signal the user’s consent state to other plugins (if and when this will be implemented is unknown) and to those plugins who do not yet offer native support for Cookiebot built into the plugin itself.' ); ?>
12
  </p>
13
  <p>
14
+ <?php esc_html_e( 'We do not assume any responsibility for the use of these add-ons. If one of the plugins that the add-ons hook into makes a ‘breaking change’, there may be a period of time where the add-on will not work properly until it has been updated to accommodate the changes in the plugin.' ); ?>
15
  </p>
16
  <p>
17
  <strong>
18
+ <?php echo sprintf( esc_html__( 'If your favourite plugin isn\'t supported you\'re welcome to contribute or request on our <a href="%s" target="_blank">Github development page.</a>' ), 'https://github.com/CybotAS/CookiebotAddons' ); ?>
19
  </strong>
20
  </p>
21
 
25
  ?>
26
  <p><strong>
27
  <?php
28
+ esc_html_e('This feature is only available in PHP 5.4 and above.');
29
  ?>
30
  </strong></p>
31
  <?php
cookiebot.php CHANGED
@@ -4,554 +4,567 @@ Plugin Name: Cookiebot | GDPR/CCPA Compliant Cookie Consent and Control
4
  Plugin URI: https://cookiebot.com/
5
  Description: Cookiebot is a cloud-driven solution that automatically controls cookies and trackers, enabling full GDPR/ePrivacy and CCPA compliance for websites.
6
  Author: Cybot A/S
7
- Version: 3.9.0
8
  Author URI: http://cookiebot.com
9
  Text Domain: cookiebot
10
  Domain Path: /langs
11
  */
12
 
13
- if(!defined('ABSPATH')) exit; // Exit if accessed directly
 
 
14
 
15
- if(!class_exists('Cookiebot_WP')):
16
 
17
- final class Cookiebot_WP {
18
- /**
19
- * Plugin version.
20
- *
21
- * @var string
22
- * @since 1.0.0
23
- */
24
- public $version = '3.9.0';
25
 
26
- /**
27
- * @var Cookiebot_WP The single instance of the class
28
- * @since 1.0.0
29
- */
30
- protected static $_instance = null;
31
 
32
- /**
33
- * Main Cookiebot_WP Instance
34
- *
35
- * Ensures only one instance of Cookiebot_WP is loaded or can be loaded.
36
- *
37
- * @version 1.0.0
38
- * @since 1.0.0
39
- * @static
40
- * @return Cookiebot_WP - Main instance
41
- */
42
- public static function instance() {
43
- if(is_null(self::$_instance)) {
44
- self::$_instance = new self();
 
 
45
  }
46
- return self::$_instance;
47
- }
48
-
49
- /**
50
- * Cookiebot_WP Constructor.
51
- *
52
- * @version 2.1.4
53
- * @since 1.0.0
54
- * @access public
55
- */
56
- function __construct() {
57
- add_action('after_setup_theme', array($this, 'cookiebot_init'), 5);
58
- register_activation_hook( __FILE__ , array($this, 'activation'));
59
- register_deactivation_hook( __FILE__, 'cookiebot_addons_plugin_deactivated' );
60
 
61
- $this->cookiebot_fix_plugin_conflicts();
62
- }
 
 
 
 
 
 
 
 
 
63
 
64
- /**
65
- * Cookiebot_WP Installation actions
66
- *
67
- * @version 2.1.4
68
- * @since 2.1.4
69
- * @accces public
70
- */
71
- function activation() {
72
- //Delay display of recommendation notice in 3 days if not activated ealier
73
- if(get_option('cookiebot_notice_recommend',false) === false) {
74
- //Not set yet - this must be first activation - delay in 3 days
75
- update_option('cookiebot_notice_recommend', strtotime('+3 days'));
76
- }
77
- if($this->get_cbid() == '') {
78
- if(is_multisite()) {
79
- update_site_option('cookiebot-cookie-blocking-mode','auto');
80
- update_site_option('cookiebot-nooutput-admin',true);
81
- }
82
- else {
83
- update_option('cookiebot-cookie-blocking-mode','auto');
84
- update_option('cookiebot-nooutput-admin',true);
85
- }
86
  }
87
 
88
  /**
89
- * Run through the addons and enable the default ones
 
 
 
 
90
  */
91
- if( (!defined('COOKIEBOT_ADDONS_STANDALONE') || COOKIEBOT_ADDONS_STANDALONE != true || !defined('COOKIE_ADDONS_LOADED')) ) {
92
- //Make sure we got a PHP version that works
93
- if ( version_compare( PHP_VERSION, '5.4.0', '>=' ) ) {
94
- define( 'COOKIEBOT_URL', plugin_dir_url( __FILE__ ) );
95
- // activation hook doesn't have the addons loaded - so load it extra when the plugin is activated
96
- include_once( dirname( __FILE__ ) . '/addons/cookiebot-addons-init.php' );
97
- // run activated hook on the addons
98
- cookiebot_addons_plugin_activated();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  }
100
  }
101
- }
102
 
103
- /**
104
- * Cookiebot_WP Init Cookiebot.
105
- *
106
- * @version 3.8.1
107
- * @since 1.6.2
108
- * @access public
109
- */
110
- function cookiebot_init() {
111
- /* Load Cookiebot Addons Framework */
112
- $dismissAddons = false;
113
- if(defined('CAF_DIR')) {
114
- $dismissAddons = true;
115
- /*add_action('admin_notices', function() {
116
  ?>
117
  <div class="notice notice-warning">
118
  <p>
119
- <?php _e( 'You have Cookiebot Addons installed.', 'cookiebot' ); ?><br />
120
- <?php _e( 'In this and future releases of Cookiebot all available Addons are bundled directly with the Cookiebot plugin.', 'cookiebot' ); ?><br />
121
- <?php _e( 'To ensure up-to-date addons - please disable and remove your Cookiebot Addons plugin and configure you addons under "Prior consent" in the Cookiebot menu.', 'cookiebot' ); ?>
122
  </p>
123
  </div>
124
  <?php
125
  });*/
126
- }
127
- //elseif( $this->get_cookie_blocking_mode() !== 'auto' ) {
128
- else {
129
- if( (!defined('COOKIEBOT_ADDONS_STANDALONE') || COOKIEBOT_ADDONS_STANDALONE != true || !defined('COOKIE_ADDONS_LOADED')) && $dismissAddons !== true ) {
130
- //Make sure we got a PHP version that works
131
- if(version_compare(PHP_VERSION, '5.4.0', '>=')) {
132
- define('COOKIEBOT_URL', plugin_dir_url( __FILE__ ));
133
- include_once( dirname( __FILE__ ) . '/addons/cookiebot-addons-init.php' );
134
- }
135
- else {
136
- define('COOKIEBOT_ADDONS_UNSUPPORTED_PHPVERSION',true);
137
- }
138
  }
 
139
  else {
140
- add_action('admin_notices', function() {
141
- ?>
 
 
 
 
 
 
 
 
 
 
 
142
  <div class="notice notice-warning">
143
  <p>
144
- <?php _e( 'You are using Cookiebot Addons Standalone.', 'cookiebot' ); ?>
145
  </p>
146
  </div>
147
- <?php
148
- });
 
 
149
  }
150
- }
151
- if(is_admin()) {
 
 
 
 
 
 
 
 
 
 
 
 
152
 
153
- //Adding menu to WP admin
154
- add_action('admin_menu', array($this,'add_menu'),1);
155
- add_action('admin_menu', array($this,'add_menu_legislations'),40);
156
- add_action('admin_menu', array($this,'add_menu_debug'),50);
157
 
 
 
158
 
159
- if(is_multisite()) {
160
- add_action('network_admin_menu', array($this,'add_network_menu'),1);
161
- add_action('network_admin_edit_cookiebot_network_settings', array($this,'network_settings_save'));
 
 
162
  }
163
 
164
- //Register settings
165
- add_action('admin_init', array($this,'register_cookiebot_settings'));
 
 
166
 
167
- //Adding dashboard widgets
168
- add_action('wp_dashboard_setup', array($this,'add_dashboard_widgets'));
169
 
170
- add_action('admin_notices', array( $this, 'cookiebot_admin_notices' ) );
171
- add_action('admin_init', array($this,'save_notice_link'));
 
 
 
172
 
173
- //Check if we should show cookie consent banner on admin pages
174
- if(!$this->cookiebot_disabled_in_admin()) {
175
- //adding cookie banner in admin area too
176
- add_action('admin_head', array($this,'add_js'),-9999);
177
  }
178
- }
179
 
180
- //Include integration to WP Consent Level API if available
181
- if($this->is_wp_consent_api_active()) {
182
- add_action( 'wp_enqueue_scripts', array($this, 'cookiebot_enqueue_consent_api_scripts') );
183
- }
184
 
185
- // Set up localisation
186
- load_plugin_textdomain('cookiebot', false, dirname( plugin_basename( __FILE__ ) ) . '/langs/' );
 
 
187
 
188
- //add JS
189
- add_action('wp_head', array($this,'add_js'), -9997);
190
- add_action('wp_head', array($this,'add_GTM'), -9998);
191
- add_action('wp_head', array($this,'add_GCM'), -9999);
192
- add_shortcode('cookie_declaration', array($this,'show_declaration'));
193
 
194
- //Add filter if WP rocket is enabled
195
- if(defined('WP_ROCKET_VERSION')) {
196
- add_filter('rocket_minify_excluded_external_js', array($this,'wp_rocket_exclude_external_js'));
197
  }
198
 
199
- //Add filter
200
- add_filter( 'sgo_javascript_combine_excluded_external_paths', array($this,'sgo_exclude_external_js') );
201
 
202
- //Automatic update plugin
203
- if(is_admin() || (defined('DOING_CRON') && DOING_CRON)) {
204
- add_filter('auto_update_plugin', array($this,'automatic_updates'), 10, 2);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
  }
206
 
207
- //Loading widgets
208
- include_once( dirname( __FILE__ ) . '/widgets/cookiebot-declaration-widget.php' );
209
- add_action( 'widgets_init', array($this,'register_widgets') );
210
-
211
-
212
- //Add Gutenberg block
213
- add_action( 'enqueue_block_assets', array($this,'gutenberg_block_setup') );
214
- add_action( 'enqueue_block_editor_assets', array($this,'gutenberg_block_admin_assets') );
215
- }
216
-
217
-
218
- /**
219
- * Cookiebot_WP Setup Gutenberg block
220
- *
221
- * @version 3.7.0
222
- * @since 3.7.0
223
- */
224
- function gutenberg_block_setup() {
225
- if ( ! function_exists( 'register_block_type' ) ) {
226
- return; //gutenberg not active
227
  }
228
-
229
- register_block_type( 'cookiebot/cookie-declaration', array(
230
- 'render_callback' => array( $this, 'block_cookie_declaration' )
231
- ) );
232
- }
233
-
234
- /**
235
- * Cookiebot_WP Add block JS
236
- *
237
- * @version 3.7.1
238
- * @since 3.7.1
239
- */
240
- function gutenberg_block_admin_assets() {
241
- //Add Gutenberg Widget
242
- wp_enqueue_script(
243
- 'cookiebot-declaration',
244
- plugin_dir_url( __FILE__ ) . 'js/block.js',
245
- array('wp-blocks', 'wp-i18n', 'wp-element'), // Required scripts for the block
246
- $this->version
247
- );
248
- }
249
-
250
- /**
251
- * Cookiebot_WP Render Cookiebot Declaration as Gutenberg block
252
- *
253
- * @version 3.7.0
254
- * @since 3.7.0
255
- */
256
- function block_cookie_declaration() {
257
- return $this->show_declaration();
258
- }
259
 
260
- /**
261
- * Cookiebot_WP Load text domain
262
- *
263
- * @version 2.0.0
264
- * @since 2.0.0
265
- */
266
- function load_textdomain() {
267
- load_plugin_textdomain( 'cookiebot', false, basename( dirname( __FILE__ ) ) . '/langs' );
268
- }
269
 
270
- /**
271
- * Cookiebot_WP Register widgets
272
- *
273
- * @version 2.5.0
274
- * @since 2.5.0
275
- */
276
- function register_widgets() {
277
- register_widget( 'Cookiebot_Declaration_Widget' );
278
- }
279
 
280
- /**
281
- * Cookiebot_WP Add dashboard widgets to admin
282
- *
283
- * @version 1.0.0
284
- * @since 1.0.0
285
- */
 
 
 
286
 
287
- function add_dashboard_widgets() {
288
- wp_add_dashboard_widget('cookiebot_status', __('Cookiebot Status','cookiebot'), array($this,'dashboard_widget_status'));
289
- }
 
 
 
290
 
291
- /**
292
- * Cookiebot_WP Output Dashboard Status Widget
293
- *
294
- * @version 1.0.0
295
- * @since 1.0.0
296
- */
297
- function dashboard_widget_status() {
298
- $cbid = $this->get_cbid();
299
- if(empty($cbid)) {
300
- echo '<p>'.__('You need to enter your Cookiebot ID.','cookiebot').'</p>';
301
- echo '<p><a href="options-general.php?page=cookiebot">';
302
- echo __('Update your Cookiebot ID','cookiebot');
303
- echo '</a></p>';
304
- }
305
- else {
306
- echo '<p>'._e('Your Cookiebot is working!','cookiebot').'</p>';
307
  }
308
- }
309
 
310
- /**
311
- * Cookiebot_WP Add option menu page for Cookiebot
312
- *
313
- * @version 2.2.0
314
- * @since 1.0.0
315
- */
316
- function add_menu() {
317
- //Cookiebot Icon SVG base64 encoded
318
- $icon = 'data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNTQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGcgZmlsbD0iI0ZGRkZGRiIgZmlsbC1ydWxlPSJldmVub2RkIj48cGF0aCBkPSJNNDYuODcyNTkwMyA4Ljc3MzU4MzM0QzQxLjk0MzkwMzkgMy4zODI5NTAxMSAzNC44NDI0OTQ2IDAgMjYuOTQ4MjgxOSAwIDEyLjA2NTE1NjggMCAwIDEyLjAyNDQ3NzQgMCAyNi44NTc0MjE5YzAgMTQuODMyOTQ0NSAxMi4wNjUxNTY4IDI2Ljg1NzQyMTkgMjYuOTQ4MjgxOSAyNi44NTc0MjE5IDcuODk0MjEyNyAwIDE0Ljk5NTYyMi0zLjM4Mjk1MDIgMTkuOTI0MzA4NC04Ljc3MzU4MzQtMi44ODk2OTY3LTEuMzY4ODY2My01LjM5OTMxMS0zLjQwNTQzOS03LjMyODA4MzgtNS45MDk2MzU4LTMuMTIxNDMwNiAzLjIwOTQxMDQtNy40OTI5OTQ0IDUuMjA0MTI5MS0xMi4zMzIwMjU4IDUuMjA0MTI5MS05LjQ4NDM0NDQgMC0xNy4xNzI5MjQ3LTcuNjYyNjU3Mi0xNy4xNzI5MjQ3LTE3LjExNTAyMzhzNy42ODg1ODAzLTE3LjExNTAyMzcgMTcuMTcyOTI0Ny0xNy4xMTUwMjM3YzQuNzIzNDgyMiAwIDkuMDAxNTU1MiAxLjkwMDU5MzkgMTIuMTA2MjkyIDQuOTc2MzA5IDEuOTU2OTIzNy0yLjY0MTEzMSA0LjU1MDAyNjMtNC43ODU1MTgzIDcuNTUzODE3Ni02LjIwODQzMTg2eiIvPjxwYXRoIGQ9Ik01NS4zODAzMjgyIDQyLjY1MDE5OTFDNDYuMzMzNzIyNyA0Mi42NTAxOTkxIDM5IDM1LjM0MTIwMzEgMzkgMjYuMzI1MDk5NiAzOSAxNy4zMDg5OTYgNDYuMzMzNzIyNyAxMCA1NS4zODAzMjgyIDEwYzkuMDQ2NjA1NSAwIDE2LjM4MDMyODIgNy4zMDg5OTYgMTYuMzgwMzI4MiAxNi4zMjUwOTk2IDAgOS4wMTYxMDM1LTcuMzMzNzIyNyAxNi4zMjUwOTk1LTE2LjM4MDMyODIgMTYuMzI1MDk5NXptLjAyMTMwOTItNy43NTU2MzQyYzQuNzM3MDI3NiAwIDguNTc3MTQ3MS0zLjgyNzE3MiA4LjU3NzE0NzEtOC41NDgyMjc5IDAtNC43MjEwNTYtMy44NDAxMTk1LTguNTQ4MjI4LTguNTc3MTQ3MS04LjU0ODIyOC00LjczNzAyNzUgMC04LjU3NzE0NyAzLjgyNzE3Mi04LjU3NzE0NyA4LjU0ODIyOCAwIDQuNzIxMDU1OSAzLjg0MDExOTUgOC41NDgyMjc5IDguNTc3MTQ3IDguNTQ4MjI3OXoiLz48L2c+PC9zdmc+';
319
- add_menu_page( 'Cookiebot', __('Cookiebot','cookiebot'), 'manage_options', 'cookiebot', array($this,'settings_page'),$icon);
320
-
321
- add_submenu_page('cookiebot',__('Cookiebot Settings','cookiebot'),__('Settings','cookiebot'), 'manage_options', 'cookiebot',array($this,'settings_page'), 10 );
322
- add_submenu_page('cookiebot',__('Cookiebot Support','cookiebot'),__('Support','cookiebot'), 'manage_options', 'cookiebot_support',array($this,'support_page'), 20 );
323
- add_submenu_page('cookiebot',__('Google Tag Manager','cookiebot'),__('Google Tag Manager','cookiebot'), 'manage_options', 'cookiebot_GTM',array($this,'GTM_page') );
324
- add_submenu_page('cookiebot',__('IAB','cookiebot'),__('IAB','cookiebot'), 'manage_options', 'cookiebot_iab',array($this,'iab_page'), 30 );
325
-
326
- if(defined('COOKIEBOT_ADDONS_UNSUPPORTED_PHPVERSION')) {
327
- //Load prior consent page anyway - but from Cookiebot WP Core plugin.
328
- add_submenu_page( 'cookiebot', __( 'Prior Consent', 'cookiebot' ), __( 'Prior Consent', 'cookiebot' ), 'manage_options', 'cookiebot-addons', array($this,'setting_page_placeholder' ), 40 );
329
  }
330
- }
331
-
332
- function add_menu_legislations() {
333
- add_submenu_page( 'cookiebot', __( 'Legislations', 'cookiebot' ), __( 'Legislations', 'cookiebot' ), 'manage_options', 'cookiebot-legislations', array($this,'legislations_page' ), 50 );
334
- }
335
 
336
- /**
337
- * Cookiebot_WP Add debug menu - we need to add this seperate to ensure it is placed last (after menu items from Addons).
338
- *
339
- * @version 3.6.0
340
- * @since 3.6.0
341
- */
342
- function add_menu_debug() {
343
- add_submenu_page('cookiebot',__('Debug info','cookiebot'),__('Debug info','cookiebot'), 'manage_options', 'cookiebot_debug',array($this,'debug_page') );
344
- }
 
 
 
 
 
 
 
 
 
 
 
 
345
 
346
- /**
347
- * Cookiebot_WP Add menu for network sites
348
- *
349
- * @version 2.2.0
350
- * @since 2.2.0
351
- */
352
- function add_network_menu() {
353
- $icon = 'data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNTQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGcgZmlsbD0iI0ZGRkZGRiIgZmlsbC1ydWxlPSJldmVub2RkIj48cGF0aCBkPSJNNDYuODcyNTkwMyA4Ljc3MzU4MzM0QzQxLjk0MzkwMzkgMy4zODI5NTAxMSAzNC44NDI0OTQ2IDAgMjYuOTQ4MjgxOSAwIDEyLjA2NTE1NjggMCAwIDEyLjAyNDQ3NzQgMCAyNi44NTc0MjE5YzAgMTQuODMyOTQ0NSAxMi4wNjUxNTY4IDI2Ljg1NzQyMTkgMjYuOTQ4MjgxOSAyNi44NTc0MjE5IDcuODk0MjEyNyAwIDE0Ljk5NTYyMi0zLjM4Mjk1MDIgMTkuOTI0MzA4NC04Ljc3MzU4MzQtMi44ODk2OTY3LTEuMzY4ODY2My01LjM5OTMxMS0zLjQwNTQzOS03LjMyODA4MzgtNS45MDk2MzU4LTMuMTIxNDMwNiAzLjIwOTQxMDQtNy40OTI5OTQ0IDUuMjA0MTI5MS0xMi4zMzIwMjU4IDUuMjA0MTI5MS05LjQ4NDM0NDQgMC0xNy4xNzI5MjQ3LTcuNjYyNjU3Mi0xNy4xNzI5MjQ3LTE3LjExNTAyMzhzNy42ODg1ODAzLTE3LjExNTAyMzcgMTcuMTcyOTI0Ny0xNy4xMTUwMjM3YzQuNzIzNDgyMiAwIDkuMDAxNTU1MiAxLjkwMDU5MzkgMTIuMTA2MjkyIDQuOTc2MzA5IDEuOTU2OTIzNy0yLjY0MTEzMSA0LjU1MDAyNjMtNC43ODU1MTgzIDcuNTUzODE3Ni02LjIwODQzMTg2eiIvPjxwYXRoIGQ9Ik01NS4zODAzMjgyIDQyLjY1MDE5OTFDNDYuMzMzNzIyNyA0Mi42NTAxOTkxIDM5IDM1LjM0MTIwMzEgMzkgMjYuMzI1MDk5NiAzOSAxNy4zMDg5OTYgNDYuMzMzNzIyNyAxMCA1NS4zODAzMjgyIDEwYzkuMDQ2NjA1NSAwIDE2LjM4MDMyODIgNy4zMDg5OTYgMTYuMzgwMzI4MiAxNi4zMjUwOTk2IDAgOS4wMTYxMDM1LTcuMzMzNzIyNyAxNi4zMjUwOTk1LTE2LjM4MDMyODIgMTYuMzI1MDk5NXptLjAyMTMwOTItNy43NTU2MzQyYzQuNzM3MDI3NiAwIDguNTc3MTQ3MS0zLjgyNzE3MiA4LjU3NzE0NzEtOC41NDgyMjc5IDAtNC43MjEwNTYtMy44NDAxMTk1LTguNTQ4MjI4LTguNTc3MTQ3MS04LjU0ODIyOC00LjczNzAyNzUgMC04LjU3NzE0NyAzLjgyNzE3Mi04LjU3NzE0NyA4LjU0ODIyOCAwIDQuNzIxMDU1OSAzLjg0MDExOTUgOC41NDgyMjc5IDguNTc3MTQ3IDguNTQ4MjI3OXoiLz48L2c+PC9zdmc+';
354
- add_menu_page( 'Cookiebot', __('Cookiebot','cookiebot'), 'manage_network_options', 'cookiebot_network', array($this,'network_settings_page'),$icon);
355
 
356
- add_submenu_page('cookiebot_network',__('Cookiebot Settings','cookiebot'),__('Settings','cookiebot'), 'network_settings_page', 'cookiebot_network',array($this,'network_settings_page'));
357
- add_submenu_page('cookiebot_network',__('Cookiebot Support','cookiebot'),__('Support','cookiebot'), 'network_settings_page', 'cookiebot_support',array($this,'support_page'));
 
 
 
 
 
 
 
358
 
359
- }
 
 
 
 
 
 
 
 
360
 
361
- /**
362
- * Cookiebot_WP Cookiebot prior consent placeholder page
363
- *
364
- * @version 1.4.0
365
- * @since 1.0.0
366
- */
367
- function setting_page_placeholder() {
368
- include __DIR__ . DIRECTORY_SEPARATOR . 'addons' . DIRECTORY_SEPARATOR . 'view/admin/settings/setting-page.php';
369
- }
370
 
371
- /**
372
- * Cookiebot_WP Register Cookiebot settings
373
- *
374
- * @version 3.9.0
375
- * @since 1.0.0
376
- */
377
- function register_cookiebot_settings() {
378
- register_setting('cookiebot', 'cookiebot-cbid');
379
- register_setting('cookiebot', 'cookiebot-language');
380
- register_setting('cookiebot', 'cookiebot-nooutput');
381
- register_setting('cookiebot', 'cookiebot-nooutput-admin');
382
- register_setting('cookiebot', 'cookiebot-output-logged-in');
383
- register_setting('cookiebot', 'cookiebot-autoupdate');
384
- register_setting('cookiebot', 'cookiebot-script-tag-uc-attribute');
385
- register_setting('cookiebot', 'cookiebot-script-tag-cd-attribute');
386
- register_setting('cookiebot', 'cookiebot-cookie-blocking-mode');
387
- register_setting('cookiebot', 'cookiebot-consent-mapping');
388
- register_setting('cookiebot-iab', 'cookiebot-iab');
389
- register_setting('cookiebot-legislations', 'cookiebot-ccpa');
390
- register_setting('cookiebot-legislations', 'cookiebot-ccpa-domain-group-id');
391
- register_setting('cookiebot-gtm', 'cookiebot-gtm');
392
- register_setting('cookiebot-gtm', 'cookiebot-gtm-id');
393
- register_setting('cookiebot-gtm', 'cookiebot-data-layer');
394
- register_setting('cookiebot-gtm', 'cookiebot-gcm');
395
- }
396
 
397
- /**
398
- * Cookiebot_WP Automatic update plugin if activated
399
- *
400
- * @version 2.2.0
401
- * @since 1.5.0
402
- */
403
- function automatic_updates($update, $item) {
404
- //Do not update from subsite on a multisite installation
405
- if(is_multisite() && ! is_main_site()) {
406
- return $update;
407
  }
408
 
409
- //Check if we have everything we need
410
- $item = (array)$item;
411
- if(!isset($item['new_version']) || !isset($item['slug'])) {
412
- return $update;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
413
  }
414
 
415
- //It is not Cookiebot
416
- if($item['slug'] !== 'cookiebot') {
417
- return $update;
418
- }
 
 
 
 
 
 
 
419
 
420
- // Check if cookiebot autoupdate is disabled
421
- if(!get_option('cookiebot-autoupdate',false)) {
422
- return $update;
423
- }
 
424
 
425
- // Check if multisite autoupdate is disabled
426
- if(is_multisite() && !get_site_option('cookiebot-autoupdate',false)) {
427
- return $update;
428
- }
429
 
430
- return true;
431
- }
 
 
432
 
 
 
 
 
433
 
434
- /**
435
- * Cookiebot_WP Get list of supported languages
436
- *
437
- * @version 1.4.0
438
- * @since 1.4.0
439
- */
440
- public static function get_supported_languages() {
441
- $supportedLanguages = array();
442
- $supportedLanguages['nb'] = __('Norwegian Bokmål','cookiebot');
443
- $supportedLanguages['tr'] = __('Turkish','cookiebot');
444
- $supportedLanguages['de'] = __('German','cookiebot');
445
- $supportedLanguages['cs'] = __('Czech','cookiebot');
446
- $supportedLanguages['da'] = __('Danish','cookiebot');
447
- $supportedLanguages['sq'] = __('Albanian','cookiebot');
448
- $supportedLanguages['he'] = __('Hebrew','cookiebot');
449
- $supportedLanguages['ko'] = __('Korean','cookiebot');
450
- $supportedLanguages['it'] = __('Italian','cookiebot');
451
- $supportedLanguages['nl'] = __('Dutch','cookiebot');
452
- $supportedLanguages['vi'] = __('Vietnamese','cookiebot');
453
- $supportedLanguages['ta'] = __('Tamil','cookiebot');
454
- $supportedLanguages['is'] = __('Icelandic','cookiebot');
455
- $supportedLanguages['ro'] = __('Romanian','cookiebot');
456
- $supportedLanguages['si'] = __('Sinhala','cookiebot');
457
- $supportedLanguages['ca'] = __('Catalan','cookiebot');
458
- $supportedLanguages['bg'] = __('Bulgarian','cookiebot');
459
- $supportedLanguages['uk'] = __('Ukrainian','cookiebot');
460
- $supportedLanguages['zh'] = __('Chinese','cookiebot');
461
- $supportedLanguages['en'] = __('English','cookiebot');
462
- $supportedLanguages['ar'] = __('Arabic','cookiebot');
463
- $supportedLanguages['hr'] = __('Croatian','cookiebot');
464
- $supportedLanguages['th'] = __('Thai','cookiebot');
465
- $supportedLanguages['el'] = __('Greek','cookiebot');
466
- $supportedLanguages['lt'] = __('Lithuanian','cookiebot');
467
- $supportedLanguages['pl'] = __('Polish','cookiebot');
468
- $supportedLanguages['lv'] = __('Latvian','cookiebot');
469
- $supportedLanguages['fr'] = __('French','cookiebot');
470
- $supportedLanguages['id'] = __('Indonesian','cookiebot');
471
- $supportedLanguages['mk'] = __('Macedonian','cookiebot');
472
- $supportedLanguages['et'] = __('Estonian','cookiebot');
473
- $supportedLanguages['pt'] = __('Portuguese','cookiebot');
474
- $supportedLanguages['ga'] = __('Irish','cookiebot');
475
- $supportedLanguages['ms'] = __('Malay','cookiebot');
476
- $supportedLanguages['sl'] = __('Slovenian','cookiebot');
477
- $supportedLanguages['ru'] = __('Russian','cookiebot');
478
- $supportedLanguages['ja'] = __('Japanese','cookiebot');
479
- $supportedLanguages['hi'] = __('Hindi','cookiebot');
480
- $supportedLanguages['sk'] = __('Slovak','cookiebot');
481
- $supportedLanguages['es'] = __('Spanish','cookiebot');
482
- $supportedLanguages['sv'] = __('Swedish','cookiebot');
483
- $supportedLanguages['sr'] = __('Serbian','cookiebot');
484
- $supportedLanguages['fi'] = __('Finnish','cookiebot');
485
- $supportedLanguages['eu'] = __('Basque','cookiebot');
486
- $supportedLanguages['hu'] = __('Hungarian','cookiebot');
487
- asort($supportedLanguages,SORT_LOCALE_STRING);
488
- return $supportedLanguages;
489
- }
490
 
491
- /**
492
- * Cookiebot_WP Output settings page
493
- *
494
- * @version 3.9.0
495
- * @since 1.0.0
496
- */
497
- function settings_page() {
498
- wp_enqueue_style( 'cookiebot-consent-mapping-table', plugins_url( 'css/consent_mapping_table.css', __FILE__ ), array(), '3.5.0' );
499
-
500
- /* Check if multisite */
501
- if($is_ms = is_multisite()) {
502
- //Receive settings from multisite - this might change the way we render the form
503
- $network_cbid = get_site_option('cookiebot-cbid','');
504
- $network_scrip_tag_uc_attr = get_site_option('cookiebot-script-tag-uc-attribute','custom');
505
- $network_scrip_tag_cd_attr = get_site_option('cookiebot-script-tag-cd-attribute','custom');
506
- $network_cookie_blocking_mode = get_site_option('cookiebot-cookie-blocking-mode','manual');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
507
  }
508
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
509
  <div class="wrap">
510
- <h1><?php _e('Cookiebot Settings','cookiebot'); ?></h1>
511
  <a href="https://www.cookiebot.com">
512
  <img src="<?php echo plugins_url( 'cookiebot-logo.png', __FILE__ ); ?>" style="float:right;margin-left:1em;">
513
  </a>
514
  <p>
515
- <?php _e('Cookiebot enables your website to comply with current legislation in the EU on the use of cookies for user tracking and profiling. The EU ePrivacy Directive requires prior, informed consent of your site users, while the <a href="https://www.cookiebot.com/goto/gdpr" target="_blank">General Data Protection Regulation (GDPR)</a> requires you to document each consent. At the same time you must be able to account for what user data you share with embedded third-party services on your website and where in the world the user data is sent.','cookiebot'); ?>
 
 
 
 
 
 
 
 
 
 
 
516
  </p>
517
  <form method="post" action="options.php">
518
- <?php settings_fields( 'cookiebot' ); ?>
519
  <?php do_settings_sections( 'cookiebot' ); ?>
520
  <table class="form-table">
521
  <tr valign="top">
522
- <th scope="row"><?php _e('Cookiebot ID','cookiebot'); ?></th>
523
  <td>
524
- <input type="text" name="cookiebot-cbid" value="<?php echo esc_attr( get_option('cookiebot-cbid') ); ?>"<?php echo ($is_ms) ? ' placeholder="'.$network_cbid.'"' : ''; ?> style="width:300px" />
525
  <p class="description">
526
- <?php _e('Need an ID?','cookiebot'); ?>
527
- <a href="https://www.cookiebot.com/goto/signup" target="_blank"><?php _e('Sign up for free on cookiebot.com','cookiebot'); ?></a>
528
  </p>
529
  </td>
530
  </tr>
531
  <tr valign="top">
532
  <th scope="row">
533
- <?php _e('Cookie-blocking mode','cookiebot'); ?>
534
  </th>
535
  <td>
536
  <?php
537
- $cbm = get_option('cookiebot-cookie-blocking-mode','manual');
538
- if($is_ms && $network_cookie_blocking_mode != 'custom') {
539
  $cbm = $network_cookie_blocking_mode;
540
  }
541
  ?>
542
  <label>
543
- <input type="radio" name="cookiebot-cookie-blocking-mode" value="auto" <?php checked('auto', $cbm, true); ?> />
544
- <?php _e('Automatic','cookiebot'); ?>
545
  </label>
546
  &nbsp; &nbsp;
547
  <label>
548
- <input type="radio" name="cookiebot-cookie-blocking-mode" value="manual" <?php checked('manual',$cbm, true); ?> />
549
- <?php _e('Manual','cookiebot'); ?>
550
  </label>
551
  <p class="description">
552
- <?php _e('Automatic block cookies (except necessary) until the user has given their consent.','cookiebot') ?>
553
  <a href="https://support.cookiebot.com/hc/en-us/articles/360009063100-Automatic-Cookie-Blocking-How-does-it-work-" target="_blank">
554
- <?php _e('Learn more','cookiebot'); ?>
555
  </a>
556
  </p>
557
  <script>
@@ -577,44 +590,44 @@ final class Cookiebot_WP {
577
  </td>
578
  </tr>
579
  <tr valign="top">
580
- <th scope="row"><?php _e('Cookiebot Language','cookiebot'); ?></th>
581
  <td>
582
  <div>
583
  <select name="cookiebot-language" id="cookiebot-language">
584
  <?php
585
- $currentLang = $this->get_language(true);
586
  ?>
587
- <option value=""><?php _e('Default (Autodetect)','cookiebot'); ?></option>
588
- <option value="_wp"<?php echo ($currentLang == '_wp') ? ' selected' : ''; ?>><?php _e('Use Wordpress Language','cookiebot'); ?></option>
589
  <?php
590
  $supportedLanguages = $this->get_supported_languages();
591
- foreach($supportedLanguages as $langCode=>$langName) {
592
- echo '<option value="'.$langCode.'"'.(($currentLang==$langCode) ? ' selected' : '').'>'.$langName.'</option>';
593
  }
594
  ?>
595
  </select>
596
  </div>
597
  <div class="notice inline notice-warning notice-alt cookiebot-notice" style="padding:12px;font-size:13px;display:inline-block;">
598
- <div style="<?php echo ($currentLang=='') ? 'display:none;' : '' ?>" id="info_lang_specified">
599
- <?php _e('You need to add the language in the Cookiebot administration tool.'); ?>
600
  </div>
601
- <div style="<?php echo ($currentLang=='') ? '' : 'display:none;' ?>" id="info_lang_autodetect">
602
- <?php _e('You need to add all languages that you want auto-detected in the Cookiebot administration tool.'); ?> <br/>
603
- <?php _e('The auto-detect checkbox needs to be enabled in the Cookiebot administration tool.'); ?><br/>
604
- <?php _e('If the auto-detected language is not supported, Cookiebot will use the default language.'); ?>
605
  </div>
606
  <br />
607
 
608
- <a href="#" id="show_add_language_guide"><?php _e('Show guide to add languages'); ?></a>
609
  &nbsp;
610
  <a href="https://support.cookiebot.com/hc/en-us/articles/360003793394-How-do-I-set-the-language-of-the-consent-banner-dialog-" target="_blank">
611
- <?php _e('Read more here'); ?>
612
  </a>
613
 
614
  <div id="add_language_guide" style="display:none;">
615
  <img src="<?php echo plugin_dir_url( __FILE__ ); ?>/assets/guide_add_language.gif" alt="Add language in Cookiebot administration tool" />
616
  <br />
617
- <a href="#" id="hide_add_language_guide"><?php _e('Hide guide'); ?></a>
618
  </div>
619
  </div>
620
  <script>
@@ -669,186 +682,204 @@ final class Cookiebot_WP {
669
  content: "\f142";
670
  }
671
  </style>
672
- <h3 id="advanced_settings_link" class="cookiebot_fieldset_header"><?php _e('Advanced settings', 'cookiebot'); ?></h3>
673
  <div id="advanced_settings" style="display:none;">
674
  <table class="form-table">
675
  <tr valign="top" id="cookiebot-setting-async">
676
  <th scope="row">
677
- <?php _e('Add async or defer attribute','cookiebot'); ?>
678
- <br /><?php _e('Consent banner script tag'); ?>
679
  </th>
680
  <td>
681
- <?php
682
- $cv = get_option('cookiebot-script-tag-uc-attribute','async');
683
- $disabled = false;
684
- if($is_ms && $network_scrip_tag_uc_attr != 'custom') {
685
- $disabled = true;
686
- $cv = $network_scrip_tag_uc_attr;
687
- }
688
- ?>
689
  <label>
690
- <input type="radio" name="cookiebot-script-tag-uc-attribute"<?php echo ($disabled) ? ' disabled' : ''; ?> value="" <?php checked('', $cv, true); ?> />
691
- <i>None</i>
692
  </label>
693
  &nbsp; &nbsp;
694
  <label>
695
- <input type="radio" name="cookiebot-script-tag-uc-attribute"<?php echo ($disabled) ? ' disabled' : ''; ?> value="async" <?php checked('async',$cv, true); ?> />
696
  async
697
  </label>
698
  &nbsp; &nbsp;
699
  <label>
700
- <input type="radio" name="cookiebot-script-tag-uc-attribute"<?php echo ($disabled) ? ' disabled' : ''; ?> value="defer" <?php checked('defer',$cv, true); ?> />
701
  defer
702
  </label>
703
  <p class="description">
704
- <?php if($disabled) { echo '<b>'._('Network setting applied. Please contact website administrator to change this setting.').'</b><br />'; } ?>
705
- <?php _e('Add async or defer attribute to Cookiebot script tag. Default: async','cookiebot') ?>
 
 
 
706
  </p>
707
  </td>
708
  </tr>
709
  <tr valign="top">
710
  <th scope="row">
711
- <?php _e('Add async or defer attribute','cookiebot'); ?>
712
- <br /><?php _e('Cookie declaration script tag'); ?>
713
  </th>
714
  <td>
715
  <?php
716
- $cv = get_option('cookiebot-script-tag-cd-attribute','async');
717
  $disabled = false;
718
- if($is_ms && $network_scrip_tag_cd_attr != 'custom') {
719
  $disabled = true;
720
- $cv = $network_scrip_tag_cd_attr;
721
  }
722
  ?>
723
  <label>
724
- <input type="radio" name="cookiebot-script-tag-cd-attribute"<?php echo ($disabled) ? ' disabled' : ''; ?> value="" <?php checked('', $cv, true); ?> />
725
- <i>None</i>
726
  </label>
727
  &nbsp; &nbsp;
728
  <label>
729
- <input type="radio" name="cookiebot-script-tag-cd-attribute"<?php echo ($disabled) ? ' disabled' : ''; ?> value="async" <?php checked('async',$cv, true); ?> />
730
  async
731
  </label>
732
  &nbsp; &nbsp;
733
  <label>
734
- <input type="radio" name="cookiebot-script-tag-cd-attribute"<?php echo ($disabled) ? ' disabled' : ''; ?> value="defer" <?php checked('defer',$cv, true); ?> />
735
  defer
736
  </label>
737
  <p class="description">
738
- <?php if($disabled) { echo '<b>'._('Network setting applied. Please contact website administrator to change this setting.').'</b><br />'; } ?>
739
- <?php _e('Add async or defer attribute to Cookiebot script tag. Default: async','cookiebot') ?>
 
 
 
740
  </p>
741
  </td>
742
  </tr>
743
- <?php
744
- if(!is_multisite()) {
745
- ?>
746
  <tr valign="top">
747
- <th scope="row"><?php _e('Auto-update Cookiebot','cookiebot'); ?></th>
748
  <td>
749
- <input type="checkbox" name="cookiebot-autoupdate" value="1" <?php checked(1,get_option('cookiebot-autoupdate',false), true); ?> />
750
  <p class="description">
751
- <?php _e('Automatic update your Cookiebot plugin when new releases becomes available.','cookiebot') ?>
752
  </p>
753
  </td>
754
  </tr>
755
- <?php
756
- }
757
- ?>
758
  <tr valign="top" id="cookiebot-setting-hide-popup">
759
- <th scope="row"><?php _e('Hide Cookie Popup','cookiebot'); ?></th>
760
  <td>
761
  <?php
762
  $disabled = false;
763
- if($is_ms && get_site_option('cookiebot-nooutput',false)) {
764
  $disabled = true;
765
  echo '<input type="checkbox" checked disabled />';
766
- }
767
- else {
768
  ?>
769
- <input type="checkbox" name="cookiebot-nooutput" value="1" <?php checked(1,get_option('cookiebot-nooutput',false), true); ?> />
770
  <?php
771
  }
772
  ?>
773
  <p class="description">
774
- <?php if($disabled) { echo '<b>'._('Network setting applied. Please contact website administrator to change this setting.').'</b><br />'; } ?>
775
- <b><?php _e('This checkbox will remove the cookie consent banner from your website. The <i>[cookie_declaration]</i> shortcode will still be available.','cookiebot') ?></b><br />
776
- <?php _e('If you are using Google Tag Manager (or equal), you need to add the Cookiebot script in your Tag Manager.','cookiebot') ?><br />
777
- <?php _e('<a href="https://support.cookiebot.com/hc/en-us/articles/360003793854-Google-Tag-Manager-deployment" target="_blank">See a detailed guide here</a>','cookiebot') ?>
 
 
 
 
 
778
  </p>
779
  </td>
780
  </tr>
781
  <tr valign="top">
782
- <th scope="row"><?php _e('Disable Cookiebot in WP Admin','cookiebot'); ?></th>
783
  <td>
784
  <?php
785
  $disabled = false;
786
- if($is_ms && get_site_option('cookiebot-nooutput-admin',false)) {
787
  echo '<input type="checkbox" checked disabled />';
788
  $disabled = true;
789
- }
790
- else {
791
  ?>
792
- <input type="checkbox" name="cookiebot-nooutput-admin" value="1" <?php checked(1,get_option('cookiebot-nooutput-admin',false), true); ?> />
793
  <?php
794
  }
795
  ?>
796
  <p class="description">
797
- <?php if($disabled) { echo '<b>'._('Network setting applied. Please contact website administrator to change this setting.').'</b><br />'; } ?>
798
- <b><?php _e('This checkbox will disable Cookiebot in the Wordpress Admin area.','cookiebot') ?></b>
 
 
 
799
  </p>
800
  </td>
801
  </tr>
802
  <tr valign="top">
803
- <th scope="row"><?php _e('Enable Cookiebot on front end while logged in','cookiebot'); ?></th>
804
  <td>
805
  <?php
806
  $disabled = false;
807
- if($is_ms && get_site_option('cookiebot-output-logged-in',false)) {
808
  echo '<input type="checkbox" checked disabled />';
809
  $disabled = true;
810
- }
811
- else {
812
  ?>
813
- <input type="checkbox" name="cookiebot-output-logged-in" value="1" <?php checked(1,get_option('cookiebot-output-logged-in',false), true); ?> />
814
  <?php
815
  }
816
  ?>
817
  <p class="description">
818
- <?php if($disabled) { echo '<b>'._('Network setting applied. Please contact website administrator to change this setting.').'</b><br />'; } ?>
819
- <b><?php _e('This checkbox will enable Cookiebot on front end while you\'re logged in','cookiebot') ?></b>
 
 
 
820
  </p>
821
  </td>
822
  </tr>
823
  </table>
824
  </div>
825
- <?php if($this->is_wp_consent_api_active()) { ?>
826
- <h3 id="consent_level_api_settings" class="cookiebot_fieldset_header"><?php _e('Consent Level API Settings', 'cookiebot'); ?></h3>
827
  <div id="consent_level_api_settings" style="display:none;">
828
- <p><?php _e('WP Consent Level API and Cookiebot categorise cookies a bit different. The default settings should fit mosts needs - but if you need to change the mapping you are able to do it below.','cookiebot'); ?></p>
829
 
830
  <?php
831
  $mDefault = $this->get_default_wp_consent_api_mapping();
832
 
833
  $m = $this->get_wp_consent_api_mapping();
834
 
835
- $consentTypes = ['preferences', 'statistics', 'marketing'];
836
- $states = array_reduce($consentTypes, function ($t, $v) {
837
- $newt = [];
838
- if (empty($t)) {
839
- $newt = [
840
- [$v => true],
841
- [$v => false],
842
- ];
 
 
843
  } else {
844
- foreach ($t as $item) {
845
- $newt[] = array_merge($item, [$v => true]);
846
- $newt[] = array_merge($item, [$v => false]);
847
- }
848
  }
849
 
850
  return $newt;
851
- }, []);
 
 
852
 
853
  ?>
854
 
@@ -856,36 +887,65 @@ final class Cookiebot_WP {
856
  <table class="widefat striped consent_mapping_table">
857
  <thead>
858
  <tr>
859
- <th><?php _e('Cookiebot categories','cookiebot'); ?></th>
860
- <th class="consent_mapping"><?php _e('WP Consent Level categories','cookiebot'); ?></th>
861
  </tr>
862
  </thead>
863
  <?php
864
- foreach($states as $state) {
865
 
866
- $key = [];
867
  $key[] = 'n=1';
868
- $key[] = 'p='.($state['preferences'] ? '1' : '0');
869
- $key[] = 's='.($state['statistics'] ? '1' : '0');
870
- $key[] = 'm='.($state['marketing'] ? '1' : '0');
871
- $key = implode(';',$key);
872
  ?>
873
  <tr valign="top">
874
  <td>
875
  <div class="cb_consent">
876
- <span class="forceconsent">Necessary</span>
877
- <span class="<?php echo ($state['preferences'] ? 'consent' : 'noconsent'); ?>"><?php _e('Preferences','cookiebot'); ?></span>
878
- <span class="<?php echo ($state['statistics'] ? 'consent' : 'noconsent'); ?>"><?php _e('Statistics','cookiebot'); ?></span>
879
- <span class="<?php echo ($state['marketing'] ? 'consent' : 'noconsent'); ?>"><?php _e('Marketing','cookiebot'); ?></span>
 
 
 
 
 
 
 
 
880
  </div>
881
  </td>
882
  <td>
883
  <div class="consent_mapping">
884
- <label><input type="checkbox" name="cookiebot-consent-mapping[<?php echo $key; ?>][functional]" data-default-value="1" value="1" checked disabled> Functional </label>
885
- <label><input type="checkbox" name="cookiebot-consent-mapping[<?php echo $key; ?>][preferences]" data-default-value="<?php echo $mDefault[$key]['preferences']; ?>" value="1" <?php if($m[$key]['preferences']) { echo 'checked'; } ?>> <?php _e('Preferences','cookiebot'); ?> </label>
886
- <label><input type="checkbox" name="cookiebot-consent-mapping[<?php echo $key; ?>][statistics]" data-default-value="<?php echo $mDefault[$key]['statistics']; ?>" value="1" <?php if($m[$key]['statistics']) { echo 'checked'; } ?>> <?php _e('Statistics','cookiebot'); ?> </label>
887
- <label><input type="checkbox" name="cookiebot-consent-mapping[<?php echo $key; ?>][statistics-anonymous]" data-default-value="<?php echo $mDefault[$key]['statistics-anonymous']; ?>" value="1" <?php if($m[$key]['statistics-anonymous']) { echo 'checked'; } ?>> <?php _e('Statistics Anonymous','cookiebot'); ?></label>
888
- <label><input type="checkbox" name="cookiebot-consent-mapping[<?php echo $key; ?>][marketing]" data-default-value="<?php echo $mDefault[$key]['marketing']; ?>" value="1" <?php if($m[$key]['marketing']) { echo 'checked'; } ?>> <?php _e('Marketing','cookiebot'); ?></label>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
889
  </div>
890
  </td>
891
  </tr>
@@ -894,7 +954,7 @@ final class Cookiebot_WP {
894
  ?>
895
  <tfoot>
896
  <tr>
897
- <td colspan="2" style="text-align:right;"><button class="button" onclick="return resetConsentMapping();"><?php _e('Reset to default mapping','cookiebot'); ?></button></td>
898
  </tr>
899
  </tfoot>
900
  </table>
@@ -912,65 +972,76 @@ final class Cookiebot_WP {
912
  </script>
913
  </div>
914
  <?php } ?>
915
- <?php submit_button(); ?>
916
  </form>
917
  </div>
918
- <?php
919
- }
920
 
921
- /**
922
- * Cookiebot_WP Cookiebot network setting page
923
- *
924
- * @version 2.2.0
925
- * @since 2.2.0
926
- */
927
- function network_settings_page() {
928
- ?>
929
  <div class="wrap">
930
- <h1><?php _e('Cookiebot Network Settings','cookiebot'); ?></h1>
931
  <a href="https://www.cookiebot.com">
932
  <img src="<?php echo plugins_url( 'cookiebot-logo.png', __FILE__ ); ?>" style="float:right;margin-left:1em;">
933
  </a>
934
  <p>
935
- <?php _e('Cookiebot enables your website to comply with current legislation in the EU on the use of cookies for user tracking and profiling. The EU ePrivacy Directive requires prior, informed consent of your site users, while the <a href="https://www.cookiebot.com/goto/gdpr" target="_blank">General Data Protection Regulation (GDPR)</a> requires you to document each consent. At the same time you must be able to account for what user data you share with embedded third-party services on your website and where in the world the user data is sent.','cookiebot'); ?>
 
 
 
 
 
 
 
 
 
 
 
936
  </p>
937
  <p>
938
- <b><big style="color:red;"><?php _e('The settings below is network wide settings. See notes below each field.','cookiebot'); ?></big></b>
939
  </p>
940
  <form method="post" action="edit.php?action=cookiebot_network_settings">
941
- <?php wp_nonce_field( 'cookiebot-network-settings' ); ?>
942
  <table class="form-table">
943
  <tr valign="top">
944
- <th scope="row"><?php _e('Network Cookiebot ID','cookiebot'); ?></th>
945
  <td>
946
- <input type="text" name="cookiebot-cbid" value="<?php echo esc_attr( get_site_option('cookiebot-cbid','') ); ?>" style="width:300px" />
947
  <p class="description">
948
- <b><?php _e('If added this will be the default Cookiebot ID for all subsites. Subsites are able to override the Cookiebot ID.','cookiebot'); ?></b>
949
  <br />
950
- <?php _e('Need an ID?','cookiebot'); ?>
951
- <a href="https://www.cookiebot.com/goto/signup" target="_blank"><?php _e('Sign up for free on cookiebot.com','cookiebot'); ?></a>
952
  </p>
953
  </td>
954
  </tr>
955
  <tr valign="top">
956
  <th scope="row">
957
- <?php _e('Cookie-blocking mode','cookiebot'); ?>
958
  </th>
959
  <td>
960
- <?php
961
- $cbm = get_site_option('cookiebot-cookie-blocking-mode','manual');
962
- ?>
963
  <label>
964
- <input type="radio" name="cookiebot-cookie-blocking-mode" value="auto" <?php checked('auto', $cbm, true); ?> />
965
- <?php _e('Automatic','cookiebot'); ?>
966
  </label>
967
  &nbsp; &nbsp;
968
  <label>
969
- <input type="radio" name="cookiebot-cookie-blocking-mode" value="manual" <?php checked('manual',$cbm, true); ?> />
970
- <?php _e('Manual','cookiebot'); ?>
971
  </label>
972
  <p class="description">
973
- <?php _e('Should Cookiebot automatic block cookies by tagging known tags.','cookiebot') ?>
974
  </p>
975
  </td>
976
  </tr>
@@ -996,197 +1067,201 @@ final class Cookiebot_WP {
996
  </script>
997
  <tr valign="top" id="cookiebot-setting-async">
998
  <th scope="row">
999
- <?php _e('Add async or defer attribute','cookiebot'); ?>
1000
- <br /><?php _e('Consent banner script tag'); ?>
1001
  </th>
1002
  <td>
1003
  <?php
1004
- $cv = get_site_option('cookiebot-script-tag-uc-attribute','custom');
1005
  ?>
1006
  <label>
1007
- <input type="radio" name="cookiebot-script-tag-uc-attribute" value="" <?php checked('', $cv, true); ?> />
1008
- <i><?php _e('None','cookiebot'); ?></i>
1009
  </label>
1010
  &nbsp; &nbsp;
1011
  <label>
1012
- <input type="radio" name="cookiebot-script-tag-uc-attribute" value="async" <?php checked('async',$cv, true); ?> />
1013
  async
1014
  </label>
1015
  &nbsp; &nbsp;
1016
  <label>
1017
- <input type="radio" name="cookiebot-script-tag-uc-attribute" value="defer" <?php checked('defer',$cv, true); ?> />
1018
  defer
1019
  </label>
1020
  &nbsp; &nbsp;
1021
  <label>
1022
- <input type="radio" name="cookiebot-script-tag-uc-attribute" value="custom" <?php checked('custom',$cv, true); ?> />
1023
- <i><?php _e('Choose per subsite','cookiebot'); ?></i>
1024
  </label>
1025
  <p class="description">
1026
- <b><?php _e('Setting will apply for all subsites. Subsites will not be able to override.','cookiebot'); ?></b><br />
1027
- <?php _e('Add async or defer attribute to Cookiebot script tag. Default: Choose per subsite','cookiebot') ?>
1028
  </p>
1029
  </td>
1030
  </tr>
1031
  <tr valign="top">
1032
  <th scope="row">
1033
- <?php _e('Add async or defer attribute','cookiebot'); ?>
1034
- <br /><?php _e('Cookie declaration script tag','cookiebot'); ?>
1035
  </th>
1036
  <td>
1037
  <?php
1038
- $cv = get_site_option('cookiebot-script-tag-cd-attribute','custom');
1039
  ?>
1040
  <label>
1041
- <input type="radio" name="cookiebot-script-tag-cd-attribute" value="" <?php checked('', $cv, true); ?> />
1042
- <i><?php _e('None','cookiebot'); ?></i>
1043
  </label>
1044
  &nbsp; &nbsp;
1045
  <label>
1046
- <input type="radio" name="cookiebot-script-tag-cd-attribute" value="async" <?php checked('async',$cv, true); ?> />
1047
  async
1048
  </label>
1049
  &nbsp; &nbsp;
1050
  <label>
1051
- <input type="radio" name="cookiebot-script-tag-cd-attribute" value="defer" <?php checked('defer',$cv, true); ?> />
1052
  defer
1053
  </label>
1054
  &nbsp; &nbsp;
1055
  <label>
1056
- <input type="radio" name="cookiebot-script-tag-cd-attribute" value="custom" <?php checked('custom',$cv, true); ?> />
1057
- <i><?php _e('Choose per subsite','cookiebot'); ?></i>
1058
  </label>
1059
  <p class="description">
1060
- <b><?php _e('Setting will apply for all subsites. Subsites will not be able to override.','cookiebot'); ?></b><br />
1061
- <?php _e('Add async or defer attribute to Cookiebot script tag. Default: Choose per subsite','cookiebot') ?>
1062
  </p>
1063
  </td>
1064
  </tr>
1065
  <tr valign="top">
1066
- <th scope="row"><?php _e('Auto-update Cookiebot','cookiebot'); ?></th>
1067
  <td>
1068
- <input type="checkbox" name="cookiebot-autoupdate" value="1" <?php checked(1,get_site_option('cookiebot-autoupdate',false), true); ?> />
1069
  <p class="description">
1070
- <?php _e('Automatic update your Cookiebot plugin when new releases becomes available.','cookiebot') ?>
1071
  </p>
1072
  </td>
1073
  </tr>
1074
  <tr valign="top" id="cookiebot-setting-hide-popup">
1075
- <th scope="row"><?php _e('Hide Cookie Popup','cookiebot'); ?></th>
1076
  <td>
1077
- <input type="checkbox" name="cookiebot-nooutput" value="1" <?php checked(1,get_site_option('cookiebot-nooutput',false), true); ?> />
1078
  <p class="description">
1079
- <b><?php _e('Remove the cookie consent banner from all subsites. This cannot be changed by subsites. The <i>[cookie_declaration]</i> shortcode will still be available.','cookiebot') ?></b><br />
1080
- <?php _e('If you are using Google Tag Manager (or equal), you need to add the Cookiebot script in your Tag Manager.','cookiebot') ?><br />
1081
- <?php _e('<a href="https://support.cookiebot.com/hc/en-us/articles/360003793854-Google-Tag-Manager-deployment" target="_blank">See a detailed guide here</a>','cookiebot') ?>
1082
  </p>
1083
  </td>
1084
  </tr>
1085
  <tr valign="top">
1086
- <th scope="row"><?php _e('Hide Cookie Popup in WP Admin','cookiebot'); ?></th>
1087
  <td>
1088
- <input type="checkbox" name="cookiebot-nooutput-admin" value="1" <?php checked(1,get_site_option('cookiebot-nooutput-admin',false), true); ?> />
1089
  <p class="description">
1090
- <b><?php _e('Remove the cookie consent banner the Wordpress Admin area for all subsites. This cannot be changed by subsites.','cookiebot') ?></b>
1091
  </p>
1092
  </td>
1093
  </tr>
1094
  </table>
1095
- <?php submit_button(); ?>
1096
  </form>
1097
  </div>
1098
- <?php
1099
- }
1100
 
1101
 
1102
- /**
1103
- * Cookiebot_WP Cookiebot save network settings
1104
- *
1105
- * @version 2.2.0
1106
- * @since 2.2.0
1107
- */
1108
- function network_settings_save() {
1109
- check_admin_referer( 'cookiebot-network-settings' );
1110
-
1111
- update_site_option('cookiebot-cbid', $_POST['cookiebot-cbid'] );
1112
- update_site_option('cookiebot-script-tag-uc-attribute', $_POST['cookiebot-script-tag-uc-attribute'] );
1113
- update_site_option('cookiebot-script-tag-cd-attribute', $_POST['cookiebot-script-tag-cd-attribute'] );
1114
- update_site_option('cookiebot-autoupdate', $_POST['cookiebot-autoupdate'] );
1115
- update_site_option('cookiebot-nooutput', $_POST['cookiebot-nooutput'] );
1116
- update_site_option('cookiebot-nooutput-admin', $_POST['cookiebot-nooutput-admin'] );
1117
- update_site_option('cookiebot-cookie-blocking-mode', $_POST['cookiebot-cookie-blocking-mode'] );
1118
-
1119
-
1120
- wp_redirect( add_query_arg( array(
1121
- 'page' => 'cookiebot_network',
1122
- 'updated' => true ), network_admin_url('admin.php')
1123
- ));
1124
- exit;
1125
- }
 
 
 
 
1126
 
1127
- /**
1128
- * Cookiebot_WP Cookiebot support page
1129
- *
1130
- * @version 2.2.0
1131
- * @since 2.0.0
1132
- */
1133
- function support_page() {
1134
- ?>
1135
  <div class="wrap">
1136
- <h1><?php _e('Support','cookiebot'); ?></h1>
1137
- <h2><?php _e('How to find my Cookiebot ID','cookiebot'); ?></h2>
1138
  <p>
1139
  <ol>
1140
- <li><?php _e('Log in to your <a href="https://www.cookiebot.com/goto/account" target="_blank">Cookiebot account</a>.','cookiebot'); ?></li>
1141
- <li><?php _e('Go to <b>Manage</b> > <b>Settings</b> and add setup your Cookiebot','cookiebot'); ?></li>
1142
- <li><?php _e('Go to the <b>"Your scripts"</b> tab','cookiebot'); ?></li>
1143
- <li><?php _e('Copy the value inside the data-cid parameter - eg.: abcdef12-3456-7890-abcd-ef1234567890','cookiebot'); ?></li>
1144
- <li><?php _e('Add <b>[cookie_declaration]</b> shortcode to a page to show the declation','cookiebot'); ?></li>
1145
- <li><?php _e('Remember to change your scripts as descripted below','cookiebot'); ?></li>
1146
  </ol>
1147
  </p>
1148
- <h2><?php _e('Add the Cookie Declaration to your website'); ?></h2>
1149
  <p>
1150
- <?php _e('Use the shortcode <b>[cookie_declaration]</b> to add the cookie declaration a page or post. The cookie declaration will always show the latest version from Cookiebot.','cookiebot'); ?>
1151
  <br />
1152
- <?php _e('If you need to force language of the cookie declaration, you can add the <i>lang</i> attribute. Eg. <b>[cookie_declaration lang="de"]</b>.','cookiebot'); ?>
1153
  </p>
1154
  <p>
1155
- <a href="https://www.youtube.com/watch?v=OCXz2bt4H_w" target="_blank" class="button"><?php _e('Watch video demonstration','cookiebot'); ?></a>
1156
  </p>
1157
- <h2><?php _e('Update your script tags','cookiebot'); ?></h2>
1158
  <p>
1159
- <?php _e('To enable prior consent, apply the attribute "data-cookieconsent" to cookie-setting script tags on your website. Set the comma-separated value to one or more of the cookie categories "preferences", "statistics" and "marketing" in accordance with the types of cookies being set by each script. Finally change the attribute "type" from "text/javascript" to "text/plain". Example on modifying an existing Google Analytics Universal script tag.','cookiebot'); ?>
1160
  </p>
1161
  <code>
1162
  <?php
1163
- echo htmlentities("<script type=\"text/plain\" data-cookieconsent=\"statistics\">").'<br />';
1164
- echo htmlentities("(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)})(window,document,'script','//www.google-analytics.com/analytics.js','ga');").'<br />';
1165
- echo htmlentities("ga('create', 'UA-00000000-0', 'auto');").'<br />';
1166
- echo htmlentities("ga('send', 'pageview');").'<br />';
1167
- echo htmlentities("</script>").'<br />';
1168
  ?>
1169
  </code>
1170
  <p>
1171
- <a href="https://www.youtube.com/watch?v=MeHycvV2QCQ" target="_blank" class="button"><?php _e('Watch video demonstration','cookiebot'); ?></a>
1172
  </p>
1173
 
1174
- <h2><?php _e('Helper function to update your scripts','cookiebot'); ?></h2>
1175
  <p>
1176
- <?php _e('You are able to update your scripts yourself. However, Cookiebot also offers a small helper function that makes the work easier.','cookiebot'); ?>
1177
  <br />
1178
- <?php _e('Update your script tags this way:','cookiebot'); ?>
1179
  </p>
1180
- <?php
1181
- printf(
1182
- __('%s to %s'),
1183
- '<code>'.htmlentities('<script type="text/javascript">').'</code>',
1184
- '<code>'.htmlentities('<script<?php echo cookiebot_assist(\'marketing\') ?>>').'</code>'
1185
- );
1186
- ?>
1187
  </div>
1188
- <?php
1189
- }
1190
 
1191
  /**
1192
  * Cookiebot_WP Google Tag Manager page
@@ -1195,200 +1270,210 @@ final class Cookiebot_WP {
1195
  * @since 3.8.1
1196
  */
1197
 
1198
- function GTM_page(){
1199
- ?>
1200
  <div class="wrap">
1201
- <h1><?php _e('Google Tag Manager', 'cookiebot')?></h1>
1202
 
1203
  <form method="post" action="options.php" style="display: grid; grid-template-columns: 35% 65%; grid-row-gap: 20px; width: 700px; align-items: center;">
1204
  <?php settings_fields( 'cookiebot-gtm' ); ?>
1205
  <?php do_settings_sections( 'cookiebot-gtm' ); ?>
1206
 
1207
- <p><?php _e('Enable GTM', 'cookiebot')?></p>
1208
  <div class="GTM_check">
1209
- <input type="checkbox" name="cookiebot-gtm" id="cookiebot-gtm" value="1" <?php checked(1,get_option('cookiebot-gtm'), true); ?> style="float: left; margin: 2px 4px 0 0">
1210
- <p style="margin: 0; font-style: italic;"><?php _e('For more details about Cookiebot and Google Tag Manager click', 'cookiebot') ?><a target="_blank" href="https://www.cookiebot.com/en/google-tag-manager-and-gdpr-compliance-with-cookiebot/" style="margin: 0; font-style: italic;">&nbsp;<?php _e('here', 'cookiebot')?></a></p>
1211
  </div>
1212
 
1213
- <p><?php _e('GTM ID', 'cookiebot')?></p>
1214
- <input type="text" name="cookiebot-gtm-id" id="cookiebot-gtm-id" value="<?php echo get_option('cookiebot-gtm-id'); ?>" style="height: 30px;">
1215
 
1216
- <p><?php _e('DataLayer name', 'cookiebot')?></p>
1217
  <div>
1218
- <input type="text" name="cookiebot-data-layer" id="data_layer" placeholder="dataLayer" value="<?php echo get_option('cookiebot-data-layer'); ?>" style="height: 30px;">
1219
- <p style="margin: 0;"><?php _e('Optional, only change if necessary', 'cookiebot')?></p>
1220
  </div>
1221
 
1222
- <p><?php _e('Google Consent Mode', 'cookiebot')?></p>
1223
  <div class="GTM_check">
1224
- <input type="checkbox" name="cookiebot-gcm" id="gcm" value="1" <?php checked(1,get_option('cookiebot-gcm'), true); ?> style="float: left; margin: 2px 4px 0 0">
1225
- <p style="margin: 0; font-style: italic;"><?php _e('For more details about Cookiebot and Google Consent Mode click', 'cookiebot') ?><a target="_blank" href="https://support.cookiebot.com/hc/en-us/articles/360016047000-Cookiebot-and-Google-Consent-Mode" style="margin: 0; font-style: italic;">&nbsp;<?php _e('here', 'cookiebot')?></a></p>
1226
  </div>
1227
  <input type="submit" value="Save" name="gtm_save" style="background-color: rgb(0, 124, 186); color: white; padding: 5px 10px; border: none; border-radius: 5px; justify-self: start;">
1228
  </form>
1229
  </div>
1230
- <?php
1231
- }
1232
 
1233
- /**
1234
- * Cookiebot_WP Cookiebot IAB page
1235
- *
1236
- * @version 2.0.0
1237
- * @since 2.0.0
1238
- */
1239
- function iab_page() {
1240
- ?>
1241
- <div class="wrap">
1242
- <h1><?php _e('IAB','cookiebot'); ?></h1>
1243
 
1244
- <p>For more details about Cookiebot's IAB integration, see <a href="https://support.cookiebot.com/hc/en-us/articles/360007652694-Cookiebot-and-the-IAB-Consent-Framework" target="_blank">article about cookiebot and the IAB consent framework</a></p>
 
 
 
 
 
 
1245
 
1246
- <form method="post" action="options.php">
1247
- <?php settings_fields( 'cookiebot-iab' ); ?>
1248
- <?php do_settings_sections( 'cookiebot-iab' ); ?>
1249
 
1250
- <label>Enable IAB integration</label>
1251
- <input type="checkbox" name="cookiebot-iab" value="1" <?php checked(1,get_option('cookiebot-iab'), true); ?>>
1252
 
1253
- <?php submit_button(); ?>
1254
- </form>
1255
- </div>
1256
- <?php
1257
- }
1258
 
1259
- /**
1260
- * Cookiebot_WP Cookiebot legislations page
1261
- *
1262
- * @version 3.6.6
1263
- * @since 3.6.6
1264
- */
1265
- function legislations_page() {
1266
- ?>
1267
- <div class="wrap">
1268
- <h1><?php _e('Legislations','cookiebot'); ?></h1>
1269
 
1270
- <p>For more details about Cookiebot's CCPA Legislation integration, see <a href="https://support.cookiebot.com/hc/en-us/articles/360010932419-Use-multiple-banners-on-the-same-website-support-both-CCPA-GDPR-compliance-" target="_blank">article about cookiebot and the CCPA compliance</a></p>
 
 
 
 
 
 
1271
 
1272
- <form method="post" action="options.php">
1273
  <?php settings_fields( 'cookiebot-legislations' ); ?>
1274
  <?php do_settings_sections( 'cookiebot-legislations' ); ?>
1275
 
1276
 
1277
- <table class="form-table">
1278
- <tbody>
1279
- <tr valign="top">
1280
- <th scope="row"><label>Enable CCPA configuration for visitors from California</label></th>
1281
- <td>
1282
- <input type="checkbox" name="cookiebot-ccpa" value="1" <?php checked(1,get_option('cookiebot-ccpa'), true); ?>>
1283
- </td>
1284
- </tr>
1285
- <tr>
1286
- <th valign="top"><label>Domain Group ID</label></th>
1287
- <td>
1288
- <input type="text" style="width: 300px;" name="cookiebot-ccpa-domain-group-id" value="<?php echo get_option('cookiebot-ccpa-domain-group-id'); ?>">
1289
- </td>
1290
- </tr>
1291
- </tbody>
1292
- </table>
1293
 
1294
  <?php submit_button(); ?>
1295
- </form>
1296
- </div>
1297
- <?php
1298
- }
1299
-
1300
- /**
1301
- * Cookiebot_WP Debug Page
1302
- *
1303
- * @version 3.9.
1304
- * @since 3.6.0
1305
- */
1306
-
1307
- function debug_page() {
1308
- global $wpdb;
1309
-
1310
- include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
1311
- $plugins = get_plugins();
1312
- $active_plugins = get_option( 'active_plugins' );
1313
-
1314
-
1315
- //$foo = new cookiebot_addons\lib\Settings_Service;
1316
- //$addons = $foo->get_active_addons();
1317
-
1318
- $debugStr = "";
1319
- $debugStr.= "##### Debug Information for ".get_site_url()." generated at ".date("c")." #####\n\n";
1320
- $debugStr.= "Wordpress Version: ".get_bloginfo('version')."\n";
1321
- $debugStr.= "Wordpress Language: ".get_bloginfo('language')."\n";
1322
- $debugStr.= "PHP Version: ".phpversion()."\n";
1323
- $debugStr.= "MySQL Version: ".$wpdb->db_version()."\n";
1324
- $debugStr.= "\n--- Cookiebot Information ---\n";
1325
- $debugStr.= "Plugin Version: ".$this->version."\n";
1326
- $debugStr.= "Cookiebot ID: ".$this->get_cbid()."\n";
1327
- $debugStr.= "Blocking mode: ".get_option('cookiebot-cookie-blocking-mode')."\n";
1328
- $debugStr.= "Language: ".get_option('cookiebot-language')."\n";
1329
- $debugStr.= "IAB: ".(get_option('cookiebot-iab') == '1' ? 'Enabled' : 'Not enabled')."\n";
1330
- $debugStr.= "CCPA banner for visitors from California: ".(get_option('cookiebot-ccpa') == '1' ? 'Enabled' : 'Not enabled')."\n";
1331
- $debugStr.= "CCPA domain group id: ". get_option('cookiebot-ccpa-domain-group-id') ."\n";
1332
- $debugStr.= "Add async/defer to banner tag: ".(get_option('cookiebot-script-tag-uc-attribute') != '' ? get_option('cookiebot-script-tag-uc-attribute') : 'None')."\n";
1333
- $debugStr.= "Add async/defer to declaration tag: ".(get_option('cookiebot-script-tag-cd-attribute') != '' ? get_option('cookiebot-script-tag-cd-attribute') : 'None')."\n";
1334
- $debugStr.= "Auto update: ".(get_option('cookiebot-autoupdate') == '1' ? 'Enabled' : 'Not enabled')."\n";
1335
- $debugStr.= "Hide Cookie Popup: ".(get_option('cookiebot-nooutput') == '1' ? 'Yes' : 'No')."\n";
1336
- $debugStr.= "Disable Cookiebot in WP Admin: ".(get_option('cookiebot-nooutput-admin') == '1' ? 'Yes' : 'No')."\n";
1337
- $debugStr.= "Enable Cookiebot on front end while logged in: ".(get_option('cookiebot-output-logged-in') == '1' ? 'Yes' : 'No')."\n";
1338
- $debugStr.= "Banner tag: ".$this->add_js(false)."\n";
1339
- $debugStr.= "Declaration tag: ".$this->show_declaration()."\n";
1340
-
1341
- if(get_option('cookiebot-gtm') != false ){
1342
- $debugStr.= "GTM tag: ".$this->add_GTM(false)."\n";
1343
- }
1344
-
1345
- if(get_option('cookiebot-gcm') != false ){
1346
- $debugStr.= "GCM tag: ".$this->add_GCM(false)."\n";
1347
  }
1348
 
1349
- if($this->is_wp_consent_api_active()) {
1350
- $debugStr.= "\n--- WP Consent Level API Mapping ---\n";
1351
- $debugStr .= 'F = Functional, N = Necessary, P = Preferences, M = Marketing, S = Statistics, SA = Statistics Anonymous'."\n";
1352
- $m = $this->get_wp_consent_api_mapping();
1353
- foreach($m as $k=>$v) {
1354
- $cb = array();
1355
-
1356
- $debugStr .= strtoupper( str_replace(';', ', ', $k ) ) . ' => ';
1357
 
1358
- $debugStr .= 'F=1, ';
1359
- $debugStr .= 'P=' . $v['preferences'] . ', ';
1360
- $debugStr .= 'M=' . $v['marketing'] . ', ';
1361
- $debugStr .= 'S=' . $v['statistics'] . ', ';
1362
- $debugStr .= 'SA=' . $v['statistics-anonymous'] . "\n";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1363
 
 
 
1364
  }
1365
 
1366
- }
 
 
 
 
 
 
 
1367
 
1368
- if(class_exists('cookiebot_addons\Cookiebot_Addons')) {
1369
- $ca = new cookiebot_addons\Cookiebot_Addons();
1370
- $settingservice = $ca->container->get( 'Settings_Service_Interface' );
1371
- $addons = $settingservice->get_active_addons();
1372
- $debugStr.= "\n--- Activated Cookiebot Addons ---\n";
1373
- foreach($addons as $addon) {
1374
- $debugStr.= $addon->get_addon_name()." (".implode( ", ", $addon->get_cookie_types() ).")\n";
 
 
 
 
 
 
 
 
 
 
1375
  }
1376
- }
1377
 
1378
- $debugStr.= "\n--- Activated Plugins ---\n";
1379
- foreach($active_plugins as $p) {
1380
- if($p != 'cookiebot/cookiebot.php') {
1381
- $debugStr.= $plugins[$p]['Name'] . " (Version: ".$plugins[$p]['Version'].")\n";
 
1382
  }
1383
- }
1384
 
1385
- $debugStr.= "\n##### Debug Information END #####";
1386
 
1387
- ?>
1388
  <div class="wrap">
1389
- <h1><?php _e('Debug information','cookiebot'); ?></h1>
1390
- <p><?php _e('The information below is for debugging purpose. If you have any issues with your Cookiebot integration, the information below is usefull for a supporter to help you the best way.'); ?></p>
1391
- <p><button class="button button-primary" onclick="copyDebugInfo();"><?php _e('Copy debug information to clipboard'); ?></button></p>
1392
  <textarea cols="100" rows="40" style="width:800px;max-width:100%;" id="cookiebot-debug-info" readonly><?php echo $debugStr; ?></textarea>
1393
  <script>
1394
  function copyDebugInfo() {
@@ -1399,67 +1484,66 @@ final class Cookiebot_WP {
1399
  }
1400
  </script>
1401
  </div>
1402
- <?php
1403
- }
1404
 
1405
- /**
1406
- * Cookiebot_WP Add Cookiebot JS to <head>
1407
- *
1408
- * @version 3.9.0
1409
- * @since 1.0.0
1410
- */
1411
- function add_js($printTag=true) {
1412
- $cbid = $this->get_cbid();
1413
- if(!empty($cbid) && !defined('COOKIEBOT_DISABLE_ON_PAGE')) {
1414
- if(is_multisite() && get_site_option('cookiebot-nooutput',false)) {
1415
- return; //Is multisite - and disabled output is checked as network setting
1416
- }
1417
 
1418
- if(get_option('cookiebot-nooutput',false)) {
1419
- return; //Do not show JS - output disabled
1420
- }
1421
 
1422
- if($this->get_cookie_blocking_mode() == 'auto' && $this->can_current_user_edit_theme() && $printTag !== false && get_site_option('cookiebot-output-logged-in') == false) {
1423
- return;
1424
- }
1425
 
1426
- $lang = $this->get_language();
1427
- if(!empty($lang)) {
1428
- $lang = ' data-culture="'.strtoupper($lang).'"'; //Use data-culture to define language
1429
- }
1430
 
1431
- if(!is_multisite() || get_site_option('cookiebot-script-tag-uc-attribute','custom') == 'custom') {
1432
- $tagAttr = get_option('cookiebot-script-tag-uc-attribute','async');
1433
- }
1434
- else {
1435
- $tagAttr = get_site_option('cookiebot-script-tag-uc-attribute');
1436
- }
1437
 
1438
- if($this->get_cookie_blocking_mode() == 'auto') {
1439
- $tagAttr = 'data-blockingmode="auto"';
1440
- }
1441
 
1442
- if (get_option('cookiebot-gtm') != false) {
1443
- if (empty(get_option('cookiebot-data-layer'))) {
1444
- $data_layer = 'data-layer-name="dataLayer"';
1445
- } else {
1446
- $data_layer = 'data-layer-name="' . get_option('cookiebot-data-layer') . '"';
1447
- }
1448
- } else {
1449
- $data_layer = '';
1450
- }
1451
 
1452
- $iab = ( get_option('cookiebot-iab') != false ) ? 'data-framework="IAB"' : '';
1453
 
1454
- $ccpa = ( get_option('cookiebot-ccpa') != false ) ? 'data-georegions="{\'region\':\'US-06\',\'cbid\':\''.get_option('cookiebot-ccpa-domain-group-id').'\'}"' : '';
1455
 
1456
- $tag = '<script id="Cookiebot" src="https://consent.cookiebot.com/uc.js" '.$iab.' '.$ccpa.' '.$data_layer.' data-cbid="'.$cbid.'"'.$lang.' type="text/javascript" '.$tagAttr.'></script>';
1457
- if($printTag===false) {
1458
- return $tag;
 
 
1459
  }
1460
- echo $tag;
1461
  }
1462
- }
1463
 
1464
  /**
1465
  * Cookiebot_WP Add Google Tag Manager JS to <head>
@@ -1468,38 +1552,37 @@ final class Cookiebot_WP {
1468
  * @since 3.8.1
1469
  */
1470
 
1471
- function add_GTM($printTag=true) {
1472
 
1473
- if(get_option('cookiebot-gtm') != false ){
1474
-
1475
- if(empty(get_option('cookiebot-data-layer'))){
1476
- $data_layer = 'dataLayer';
1477
- }else{
1478
- $data_layer = get_option('cookiebot-data-layer');
1479
- }
1480
 
1481
- $GTM = "<script>";
1482
- if( get_option('cookiebot-iab') ) {
1483
- $GTM .= 'window ["gtag_enable_tcf_support"] = true;';
1484
- }
1485
-
1486
- $GTM .= "(function (w, d, s, l, i) {
1487
  w[l] = w[l] || []; w[l].push({'gtm.start':new Date().getTime(), event: 'gtm.js'});
1488
  var f = d.getElementsByTagName(s)[0], j = d.createElement(s), dl = l != 'dataLayer' ? '&l=' + l : '';
1489
  j.async = true; j.src = 'https://www.googletagmanager.com/gtm.js?id=' + i + dl;
1490
  f.parentNode.insertBefore(j, f);})
1491
- (window, document, 'script', '" . $data_layer . "', '" . get_option('cookiebot-gtm-id') . "');";
1492
-
1493
-
1494
- $GTM .= "</script>";
1495
 
1496
- if($printTag===false) {
1497
- return $GTM;
1498
- }
1499
 
1500
- echo $GTM;
 
 
 
 
 
1501
  }
1502
- }
1503
 
1504
  /**
1505
  * Cookiebot_WP Add Google Consent Mode JS to <head>
@@ -1508,303 +1591,343 @@ final class Cookiebot_WP {
1508
  * @since 3.8.1
1509
  */
1510
 
1511
- function add_GCM($printTag=true) {
1512
 
1513
- if(get_option('cookiebot-gcm') != false ){
1514
 
1515
- if(empty(get_option('cookiebot-data-layer'))){
1516
- $data_layer = 'dataLayer';
1517
- }else{
1518
- $data_layer = get_option('cookiebot-data-layer');
1519
- }
1520
 
1521
- $GCM = '<script data-cookieconsent="ignore">
1522
  (function(w,d,l){w[l]=w[l]||[];function gtag(){w[l].push(arguments)};
1523
  gtag("consent","default",{ad_storage:d,analytics_storage:d,wait_for_update:500,});
1524
  gtag("set", "ads_data_redaction", true);})(window,"denied","' . $data_layer . '");';
1525
 
1526
- $GCM .= '</script>';
1527
 
1528
- if($printTag===false) {
1529
- return $GCM;
1530
- }
1531
 
1532
- echo $GCM;
 
1533
  }
1534
- }
1535
 
1536
- /**
1537
- * Returns true if an user is logged in and has an edit_themes capability
1538
- *
1539
- * @return bool
1540
- *
1541
- * @since 3.3.1
1542
- * @version 3.4.1
1543
- */
1544
- function can_current_user_edit_theme() {
1545
- if( is_user_logged_in() ) {
1546
- if( current_user_can('edit_themes') ) {
1547
- return true;
1548
- }
1549
 
1550
- if( current_user_can( 'edit_pages' ) ) {
1551
- return true;
1552
- }
1553
 
1554
- if( current_user_can( 'edit_posts' ) ) {
1555
- return true;
1556
- }
1557
- }
1558
 
1559
- return false;
1560
- }
1561
 
1562
- /**
1563
- * Cookiebot_WP Output declation shortcode [cookie_declaration]
1564
- * Support attribute lang="LANGUAGE_CODE". Eg. lang="en".
1565
- *
1566
- * @version 2.2.0
1567
- * @since 1.0.0
1568
- */
1569
- function show_declaration($atts=array()) {
1570
- $cbid = $this->get_cbid();
1571
- $lang = '';
1572
- if(!empty($cbid)) {
1573
-
1574
- $atts = shortcode_atts(array(
1575
- 'lang' => $this->get_language(),
1576
- ), $atts, 'cookie_declaration'
1577
- );
 
 
 
 
 
 
 
1578
 
1579
- if(!empty($atts['lang'])) {
1580
- $lang = ' data-culture="'.strtoupper($atts['lang']).'"'; //Use data-culture to define language
1581
- }
 
 
1582
 
1583
- if(!is_multisite() || get_site_option('cookiebot-script-tag-cd-attribute','custom') == 'custom') {
1584
- $tagAttr = get_option('cookiebot-script-tag-cd-attribute','async');
1585
- }
1586
- else {
1587
- $tagAttr = get_site_option('cookiebot-script-tag-cd-attribute');
1588
  }
1589
-
1590
- return '<script id="CookieDeclaration" src="https://consent.cookiebot.com/'.$cbid.'/cd.js"'.$lang.' type="text/javascript" '.$tagAttr.'></script>';
1591
  }
1592
- else {
1593
- return __('Please add your Cookiebot ID to show Cookie Declarations','cookiebot');
1594
- }
1595
- }
1596
 
1597
- /**
1598
- * Cookiebot_WP Get cookiebot cbid
1599
- *
1600
- * @version 2.2.0
1601
- * @since 1.0.0
1602
- */
1603
- public static function get_cbid() {
1604
- $cbid = get_option('cookiebot-cbid');
1605
- if(is_multisite() && ($network_cbid = get_site_option('cookiebot-cbid'))) {
1606
- if(empty($cbid)) {
1607
- return $network_cbid;
 
1608
  }
 
1609
  }
1610
- return $cbid;
1611
- }
1612
 
1613
- /**
1614
- * Cookiebot_WP Get cookie blocking mode (auto | manual)
1615
- *
1616
- * @version 2.2.0
1617
- * @since 1.0.0
1618
- */
1619
- public static function get_cookie_blocking_mode() {
1620
- $cbm = get_option('cookiebot-cookie-blocking-mode');
1621
- if(is_multisite() && ($network_cbm = get_site_option('cookiebot-cookie-blocking-mode'))) {
1622
- if(empty($cbm)) {
1623
- return $network_cbm;
 
1624
  }
 
 
 
1625
  }
1626
- if(empty($cbm)) { $cbm = 'manual'; }
1627
- return $cbm;
1628
- }
1629
 
1630
 
1631
- /**
1632
- * Cookiebot_WP Check if Cookiebot is active in admin
1633
- *
1634
- * @version 3.1.0
1635
- * @since 3.1.0
1636
- */
1637
- public static function cookiebot_disabled_in_admin() {
1638
- if(is_multisite() && get_site_option('cookiebot-nooutput-admin',false)) {
1639
  return true;
1640
- }
1641
- elseif(get_option('cookiebot-nooutput-admin',false)) {
1642
  return true;
1643
  }
1644
  return false;
1645
- }
1646
 
1647
- /**
1648
- * Cookiebot_WP Get the language code for Cookiebot
1649
- *
1650
- * @version 1.4.0
1651
- * @since 1.4.0
1652
- */
1653
- function get_language($onlyFromSetting=false) {
1654
- // Get language set in setting page - if empty use WP language info
1655
- $lang = get_option('cookiebot-language');
1656
- if(!empty($lang)) {
1657
- if($lang != '_wp') {
1658
- return $lang;
 
1659
  }
1660
- }
1661
 
1662
- if($onlyFromSetting) {
1663
- return $lang; //We want only to get if already set
1664
- }
1665
 
1666
- //Language not set - use WP language
1667
- if($lang == '_wp') {
1668
- $lang = get_bloginfo('language'); //Gets language in en-US format
1669
- if(!empty($lang)) {
1670
- list($lang) = explode('-',$lang); //Changes format from eg. en-US to en.
 
1671
  }
 
1672
  }
1673
- return $lang;
1674
- }
1675
-
1676
- /**
1677
- * Cookiebot_WP Adding Cookiebot domain(s) to exclude list for WP Rocket minification.
1678
- *
1679
- * @version 1.6.1
1680
- * @since 1.6.1
1681
- */
1682
- function wp_rocket_exclude_external_js($external_js_hosts) {
1683
- $external_js_hosts[] = 'consent.cookiebot.com'; // Add cookiebot domains
1684
- $external_js_hosts[] = 'consentcdn.cookiebot.com';
1685
- return $external_js_hosts;
1686
- }
1687
-
1688
- /**
1689
- * Cookiebot_WP Adding Cookiebot domain(s) to exclude list for SGO minification.
1690
- *
1691
- * @version 3.6.5
1692
- * @since 3.6.5
1693
- */
1694
- function sgo_exclude_external_js( $exclude_list ) {
1695
- //Uses same format as WP Rocket - for now we just use WP Rocket function
1696
- return wp_rocket_exclude_external_js( $exclude_list );
1697
- }
1698
 
 
 
 
 
 
 
 
 
 
 
 
1699
 
1700
- /**
1701
- * Cookiebot_WP Check if WP Cookie Consent API is active
1702
- *
1703
- * @version 3.5.0
1704
- * @since 3.5.0
1705
- */
1706
- public function is_wp_consent_api_active() {
1707
- if ( class_exists( 'WP_CONSENT_API' ) ) {
1708
- return true;
1709
  }
1710
- return false;
1711
- }
1712
 
1713
- /**
1714
- * Cookiebot_WP Default consent level mappings
1715
- *
1716
- * @version 3.5.0
1717
- * @since 3.5.0
1718
- */
1719
- public function get_default_wp_consent_api_mapping() {
1720
- return array(
1721
- 'n=1;p=1;s=1;m=1' =>
1722
- array('preferences'=>1,'statistics'=>1,'statistics-anonymous'=>0,'marketing'=>1),
1723
- 'n=1;p=1;s=1;m=0' =>
1724
- array('preferences'=>1,'statistics'=>1,'statistics-anonymous'=>1,'marketing'=>0),
1725
- 'n=1;p=1;s=0;m=1' =>
1726
- array('preferences'=>1,'statistics'=>0,'statistics-anonymous'=>0,'marketing'=>1),
1727
- 'n=1;p=1;s=0;m=0' =>
1728
- array('preferences'=>1,'statistics'=>0,'statistics-anonymous'=>0,'marketing'=>0),
1729
- 'n=1;p=0;s=1;m=1' =>
1730
- array('preferences'=>0,'statistics'=>1,'statistics-anonymous'=>0,'marketing'=>1),
1731
- 'n=1;p=0;s=1;m=0' =>
1732
- array('preferences'=>0,'statistics'=>1,'statistics-anonymous'=>0,'marketing'=>0),
1733
- 'n=1;p=0;s=0;m=1' =>
1734
- array('preferences'=>0,'statistics'=>0,'statistics-anonymous'=>0,'marketing'=>1),
1735
- 'n=1;p=0;s=0;m=0' =>
1736
- array('preferences'=>0,'statistics'=>0,'statistics-anonymous'=>0,'marketing'=>0),
1737
- );
1738
 
1739
- }
 
 
 
 
 
 
 
 
 
 
 
1740
 
1741
- /**
1742
- * Cookiebot_WP Get the mapping between Consent Level API and Cookiebot
1743
- * Returns array where key is the consent level api category and value
1744
- * is the mapped Cookiebot category.
1745
- *
1746
- * @version 3.5.0
1747
- * @since 3.5.0
1748
- */
1749
- public function get_wp_consent_api_mapping() {
1750
- $mDefault = $this->get_default_wp_consent_api_mapping();
1751
- $mapping = get_option( 'cookiebot-consent-mapping', $mDefault);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1752
 
1753
- $mapping = ( '' === $mapping ) ? $mDefault : $mapping;
1754
 
1755
- foreach($mDefault as $k=>$v) {
1756
- if(!isset($mapping[$k])) {
1757
- $mapping[$k] = $v;
1758
- }
1759
- else {
1760
- foreach($v as $vck=>$vcv) {
1761
- if(!isset($mapping[$k][$vck])) {
1762
- $mapping[$k][$vck] = $vcv;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1763
  }
1764
  }
1765
  }
 
1766
  }
1767
- return $mapping;
1768
- }
1769
 
1770
- /**
1771
- * Cookiebot_WP Enqueue JS for integration with WP Consent Level API
1772
- *
1773
- * @version 3.5.0
1774
- * @since 3.5.0
1775
- */
1776
- function cookiebot_enqueue_consent_api_scripts() {
1777
- wp_register_script( 'cookiebot-wp-consent-level-api-integration', plugins_url( 'cookiebot/js/cookiebot-wp-consent-level-api-integration.js', 'cookiebot' ) );
1778
- wp_enqueue_script( 'cookiebot-wp-consent-level-api-integration' );
1779
- wp_localize_script( 'cookiebot-wp-consent-level-api-integration', 'cookiebot_category_mapping', $this->get_wp_consent_api_mapping() );
1780
- }
1781
 
1782
 
1783
- /**
1784
- * Display admin notice for recommending cookiebot
1785
- *
1786
- * @version 2.0.5
1787
- * @since 2.0.5
1788
- */
1789
- function cookiebot_admin_notices() {
1790
- if( ! $this->cookiebot_valid_admin_recommendation() ) {
1791
- return false;
1792
- }
1793
- $two_week_review_ignore = add_query_arg( array( 'cookiebot_admin_notice' => 'hide' ) );
1794
- $two_week_review_temp = add_query_arg( array( 'cookiebot_admin_notice' => 'two_week' ) );
1795
-
1796
- $notices = array(
1797
- 'title' => __('Leave A Review?', 'cookiebot'),
1798
- 'msg' => __('We hope you enjoy using WordPress Cookiebot! Would you consider leaving us a review on WordPress.org?', 'cookiebot'),
1799
- 'link' => '<li><span class="dashicons dashicons-external"></span><a href="https://wordpress.org/support/plugin/cookiebot/reviews?filter=5&rate=5#new-post" target="_blank">' . __('Sure! I\'d love to!', 'cookiebot') . '</a></li>
1800
- <li><span class="dashicons dashicons-smiley"></span><a href="' . $two_week_review_ignore . '"> ' . __('I\'ve already left a review', 'cookiebot') . '</a></li>
1801
- <li><span class="dashicons dashicons-calendar-alt"></span><a href="' . $two_week_review_temp . '">' . __('Maybe Later', 'cookiebot') . '</a></li>
1802
- <li><span class="dashicons dashicons-dismiss"></span><a href="' . $two_week_review_ignore . '">' . __('Never show again', 'cookiebot') . '</a></li>',
1803
- 'later_link' => $two_week_review_temp,
1804
- 'int' => 14
1805
- );
1806
-
1807
- echo '<div class="update-nag cookiebot-admin-notice">
1808
  <div class="cookiebot-notice-logo"></div>
1809
  <p class="cookiebot-notice-title">' . $notices['title'] . '</p>
1810
  <p class="cookiebot-notice-body">' . $notices['msg'] . '</p>
@@ -1812,139 +1935,143 @@ final class Cookiebot_WP {
1812
  <a href="' . $notices['later_link'] . '" class="dashicons dashicons-dismiss"></a>
1813
  </div>';
1814
 
1815
- wp_enqueue_style( 'cookiebot-admin-notices', plugins_url( 'css/notice.css', __FILE__ ), array(), '2.0.4' );
1816
- }
1817
-
1818
-
1819
- /**
1820
- * Validate if the last user action is valid for plugin recommendation
1821
- *
1822
- * @return bool
1823
- *
1824
- * @version 2.0.5
1825
- * @since 2.0.5
1826
- */
1827
- function cookiebot_valid_admin_recommendation() {
1828
- //Default - the recommendation is allowed to be visible
1829
- $return = true;
1830
 
1831
- $option = get_option('cookiebot_notice_recommend');
1832
 
1833
- if( $option != false ) {
1834
- //Never show again is clicked
1835
- if( $option == 'hide' ) {
1836
- $return = false;
1837
- }
1838
- elseif( is_numeric($option) && strtotime('now') < $option ) {
1839
- //Show me after 2 weeks is clicked and the time is not valid yet
1840
- $return = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1841
  }
 
1842
  }
1843
- return $return;
1844
- }
1845
 
1846
- /**
1847
- * Save the user action on cookiebot recommendation link
1848
- *
1849
- * @version 2.0.5
1850
- * @since 2.0.5
1851
- */
1852
- function save_notice_link() {
1853
- if( isset( $_GET['cookiebot_admin_notice'] ) ) {
1854
- if( $_GET['cookiebot_admin_notice'] == 'hide' ) {
1855
- update_option('cookiebot_notice_recommend', 'hide' );
1856
- }
1857
- else {
1858
- update_option('cookiebot_notice_recommend', strtotime('+2 weeks') );
1859
  }
1860
  }
1861
- }
1862
 
1863
 
1864
 
1865
 
1866
- /**
1867
- * Cookiebot_WP Fix plugin conflicts related to Cookiebot
1868
- *
1869
- * @version 3.2.0
1870
- * @since 3.3.0
1871
- */
1872
- function cookiebot_fix_plugin_conflicts() {
1873
- //Fix for Divi Page Builder
1874
- //Disabled - using another method now (can_current_user_edit_theme())
1875
- //add_action( 'wp', array( $this, '_cookiebot_plugin_conflict_divi' ), 100 );
1876
-
1877
- //Fix for Elementor and WPBakery Page Builder Builder
1878
- //Disabled - using another method now (can_current_user_edit_theme())
1879
- //add_filter( 'script_loader_tag', array( $this, '_cookiebot_plugin_conflict_scripttags' ), 10, 2 );
1880
- }
1881
 
1882
- /**
1883
- * Cookiebot_WP Fix Divi builder conflict when blocking mode is in auto.
1884
- *
1885
- * @version 3.2.0
1886
- * @since 3.2.0
1887
- */
1888
- function _cookiebot_plugin_conflict_divi() {
1889
- if ( defined( 'ET_FB_ENABLED' ) ) {
1890
- if ( ET_FB_ENABLED &&
1891
  $this->cookiebot_disabled_in_admin() &&
1892
  $this->get_cookie_blocking_mode() == 'auto' ) {
1893
 
1894
- define('COOKIEBOT_DISABLE_ON_PAGE',true); //Disable Cookiebot on the current page
1895
 
 
1896
  }
1897
  }
1898
- }
1899
 
1900
- /**
1901
- * Cookiebot_WP Fix plugin conflicts with page builders - whitelist JS files in automode
1902
- *
1903
- * @version 3.2.0
1904
- * @since 3.3.0
1905
- */
1906
- function _cookiebot_plugin_conflict_scripttags( $tag, $handle ) {
1907
-
1908
- //Check if Elementor Page Builder active
1909
- if( defined( 'ELEMENTOR_VERSION' ) ) {
1910
- if( in_array( $handle, [
1911
- 'jquery-core',
1912
- 'elementor-frontend-modules',
1913
- 'elementor-frontend',
1914
- 'wp-tinymce' ,
1915
- 'underscore',
1916
- 'backbone',
1917
- 'backbone-marionette',
1918
- 'backbone-radio',
1919
- 'elementor-common-modules',
1920
- 'elementor-dialog',
1921
- 'elementor-common',
1922
- ] ) ) {
1923
- $tag = str_replace( '<script ', '<script data-cookieconsent="ignore" ', $tag );
 
 
 
 
1924
  }
1925
- }
1926
 
1927
- //Check if WPBakery Page Builder active
1928
- if ( defined( 'WPB_VC_VERSION' ) ) {
1929
- if( in_array( $handle, [
1930
- 'jquery-core',
1931
- 'jquery-ui-core',
1932
- 'jquery-ui-sortable',
1933
- 'jquery-ui-mouse',
1934
- 'jquery-ui-widget',
1935
- 'vc_editors-templates-preview-js',
1936
- 'vc-frontend-editor-min-js',
1937
- 'vc_inline_iframe_js',
1938
- 'wpb_composer_front_js',
1939
- ] ) ) {
1940
- $tag = str_replace( '<script ', '<script data-cookieconsent="ignore" ', $tag );
 
 
 
 
1941
  }
 
 
1942
  }
1943
 
1944
- return $tag;
1945
  }
1946
-
1947
- }
1948
  endif;
1949
 
1950
 
@@ -1955,17 +2082,18 @@ endif;
1955
  * @since 1.0
1956
  * @return string
1957
  */
1958
- function cookiebot_assist($type='statistics') {
1959
  //change to array
1960
- if(!is_array($type)) { $type = array($type); }
 
1961
 
1962
- foreach($type as $tk=>$tv) {
1963
- if(!in_array($tv,array('marketing','statistics','preferences'))) {
1964
- unset($type[$tk]);
1965
  }
1966
  }
1967
- if(sizeof($type) > 0) {
1968
- return ' type="text/plain" data-cookieconsent="'.implode(',',$type).'"';
1969
  }
1970
  return '';
1971
  }
@@ -1981,14 +2109,14 @@ function cookiebot_assist($type='statistics') {
1981
  */
1982
  function cookiebot_active() {
1983
  $cbid = Cookiebot_WP::get_cbid();
1984
- if(!empty($cbid)) {
1985
  return true;
1986
  }
1987
  return false;
1988
  }
1989
 
1990
 
1991
- if(!function_exists('cookiebot')) {
1992
  /**
1993
  * Returns the main instance of Cookiebot_WO to prevent the need to use globals.
1994
  *
4
  Plugin URI: https://cookiebot.com/
5
  Description: Cookiebot is a cloud-driven solution that automatically controls cookies and trackers, enabling full GDPR/ePrivacy and CCPA compliance for websites.
6
  Author: Cybot A/S
7
+ Version: 3.10.0
8
  Author URI: http://cookiebot.com
9
  Text Domain: cookiebot
10
  Domain Path: /langs
11
  */
12
 
13
+ if ( ! defined( 'ABSPATH' ) ) {
14
+ exit; // Exit if accessed directly
15
+ }
16
 
17
+ if ( ! class_exists( 'Cookiebot_WP' ) ) :
18
 
19
+ final class Cookiebot_WP {
20
+ /**
21
+ * Plugin version.
22
+ *
23
+ * @var string
24
+ * @since 1.0.0
25
+ */
26
+ public $version = '3.10.0';
27
 
28
+ /**
29
+ * @var Cookiebot_WP The single instance of the class
30
+ * @since 1.0.0
31
+ */
32
+ protected static $_instance = null;
33
 
34
+ /**
35
+ * Main Cookiebot_WP Instance
36
+ *
37
+ * Ensures only one instance of Cookiebot_WP is loaded or can be loaded.
38
+ *
39
+ * @version 1.0.0
40
+ * @since 1.0.0
41
+ * @static
42
+ * @return Cookiebot_WP - Main instance
43
+ */
44
+ public static function instance() {
45
+ if ( is_null( self::$_instance ) ) {
46
+ self::$_instance = new self();
47
+ }
48
+ return self::$_instance;
49
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
 
51
+ /**
52
+ * Cookiebot_WP Constructor.
53
+ *
54
+ * @version 2.1.4
55
+ * @since 1.0.0
56
+ * @access public
57
+ */
58
+ function __construct() {
59
+ add_action( 'after_setup_theme', array( $this, 'cookiebot_init' ), 5 );
60
+ register_activation_hook( __FILE__, array( $this, 'activation' ) );
61
+ register_deactivation_hook( __FILE__, 'cookiebot_addons_plugin_deactivated' );
62
 
63
+ $this->cookiebot_fix_plugin_conflicts();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  }
65
 
66
  /**
67
+ * Cookiebot_WP Installation actions
68
+ *
69
+ * @version 2.1.4
70
+ * @since 2.1.4
71
+ * @accces public
72
  */
73
+ function activation() {
74
+ //Delay display of recommendation notice in 3 days if not activated ealier
75
+ if ( get_option( 'cookiebot_notice_recommend', false ) === false ) {
76
+ //Not set yet - this must be first activation - delay in 3 days
77
+ update_option( 'cookiebot_notice_recommend', strtotime( '+3 days' ) );
78
+ }
79
+ if ( $this->get_cbid() == '' ) {
80
+ if ( is_multisite() ) {
81
+ update_site_option( 'cookiebot-cookie-blocking-mode', 'auto' );
82
+ update_site_option( 'cookiebot-nooutput-admin', true );
83
+ } else {
84
+ update_option( 'cookiebot-cookie-blocking-mode', 'auto' );
85
+ update_option( 'cookiebot-nooutput-admin', true );
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Run through the addons and enable the default ones
91
+ */
92
+ if ( ( ! defined( 'COOKIEBOT_ADDONS_STANDALONE' ) || COOKIEBOT_ADDONS_STANDALONE != true || ! defined( 'COOKIE_ADDONS_LOADED' ) ) ) {
93
+ //Make sure we got a PHP version that works
94
+ if ( version_compare( PHP_VERSION, '5.4.0', '>=' ) ) {
95
+ define( 'COOKIEBOT_URL', plugin_dir_url( __FILE__ ) );
96
+ // activation hook doesn't have the addons loaded - so load it extra when the plugin is activated
97
+ include_once dirname( __FILE__ ) . '/addons/cookiebot-addons-init.php';
98
+ // run activated hook on the addons
99
+ cookiebot_addons_plugin_activated();
100
+ }
101
  }
102
  }
 
103
 
104
+ /**
105
+ * Cookiebot_WP Init Cookiebot.
106
+ *
107
+ * @version 3.8.1
108
+ * @since 1.6.2
109
+ * @access public
110
+ */
111
+ function cookiebot_init() {
112
+ /* Load Cookiebot Addons Framework */
113
+ $dismissAddons = false;
114
+ if ( defined( 'CAF_DIR' ) ) {
115
+ $dismissAddons = true;
116
+ /*add_action('admin_notices', function() {
117
  ?>
118
  <div class="notice notice-warning">
119
  <p>
120
+ <?php esc_html_e( 'You have Cookiebot Addons installed.', 'cookiebot' ); ?><br />
121
+ <?php esc_html_e( 'In this and future releases of Cookiebot all available Addons are bundled directly with the Cookiebot plugin.', 'cookiebot' ); ?><br />
122
+ <?php esc_html_e( 'To ensure up-to-date addons - please disable and remove your Cookiebot Addons plugin and configure you addons under "Prior consent" in the Cookiebot menu.', 'cookiebot' ); ?>
123
  </p>
124
  </div>
125
  <?php
126
  });*/
 
 
 
 
 
 
 
 
 
 
 
 
127
  }
128
+ //elseif( $this->get_cookie_blocking_mode() !== 'auto' ) {
129
  else {
130
+ if ( ( ! defined( 'COOKIEBOT_ADDONS_STANDALONE' ) || COOKIEBOT_ADDONS_STANDALONE != true || ! defined( 'COOKIE_ADDONS_LOADED' ) ) && $dismissAddons !== true ) {
131
+ //Make sure we got a PHP version that works
132
+ if ( version_compare( PHP_VERSION, '5.4.0', '>=' ) ) {
133
+ define( 'COOKIEBOT_URL', plugin_dir_url( __FILE__ ) );
134
+ include_once dirname( __FILE__ ) . '/addons/cookiebot-addons-init.php';
135
+ } else {
136
+ define( 'COOKIEBOT_ADDONS_UNSUPPORTED_PHPVERSION', true );
137
+ }
138
+ } else {
139
+ add_action(
140
+ 'admin_notices',
141
+ function() {
142
+ ?>
143
  <div class="notice notice-warning">
144
  <p>
145
+ <?php esc_html_e( 'You are using Cookiebot Addons Standalone.', 'cookiebot' ); ?>
146
  </p>
147
  </div>
148
+ <?php
149
+ }
150
+ );
151
+ }
152
  }
153
+ if ( is_admin() ) {
154
+
155
+ //Adding menu to WP admin
156
+ add_action( 'admin_menu', array( $this, 'add_menu' ), 1 );
157
+ add_action( 'admin_menu', array( $this, 'add_menu_legislations' ), 40 );
158
+ add_action( 'admin_menu', array( $this, 'add_menu_debug' ), 50 );
159
+
160
+ if ( is_multisite() ) {
161
+ add_action( 'network_admin_menu', array( $this, 'add_network_menu' ), 1 );
162
+ add_action( 'network_admin_edit_cookiebot_network_settings', array( $this, 'network_settings_save' ) );
163
+ }
164
+
165
+ //Register settings
166
+ add_action( 'admin_init', array( $this, 'register_cookiebot_settings' ) );
167
 
168
+ //Adding dashboard widgets
169
+ add_action( 'wp_dashboard_setup', array( $this, 'add_dashboard_widgets' ) );
 
 
170
 
171
+ add_action( 'admin_notices', array( $this, 'cookiebot_admin_notices' ) );
172
+ add_action( 'admin_init', array( $this, 'save_notice_link' ) );
173
 
174
+ //Check if we should show cookie consent banner on admin pages
175
+ if ( ! $this->cookiebot_disabled_in_admin() ) {
176
+ //adding cookie banner in admin area too
177
+ add_action( 'admin_head', array( $this, 'add_js' ), -9999 );
178
+ }
179
  }
180
 
181
+ //Include integration to WP Consent Level API if available
182
+ if ( $this->is_wp_consent_api_active() ) {
183
+ add_action( 'wp_enqueue_scripts', array( $this, 'cookiebot_enqueue_consent_api_scripts' ) );
184
+ }
185
 
186
+ // Set up localisation
187
+ load_plugin_textdomain( 'cookiebot', false, dirname( plugin_basename( __FILE__ ) ) . '/langs/' );
188
 
189
+ //add JS
190
+ add_action( 'wp_head', array( $this, 'add_js' ), -9997 );
191
+ add_action( 'wp_head', array( $this, 'add_GTM' ), -9998 );
192
+ add_action( 'wp_head', array( $this, 'add_GCM' ), -9999 );
193
+ add_shortcode( 'cookie_declaration', array( $this, 'show_declaration' ) );
194
 
195
+ //Add filter if WP rocket is enabled
196
+ if ( defined( 'WP_ROCKET_VERSION' ) ) {
197
+ add_filter( 'rocket_minify_excluded_external_js', array( $this, 'wp_rocket_exclude_external_js' ) );
 
198
  }
 
199
 
200
+ //Add filter
201
+ add_filter( 'sgo_javascript_combine_excluded_external_paths', array( $this, 'sgo_exclude_external_js' ) );
 
 
202
 
203
+ //Automatic update plugin
204
+ if ( is_admin() || ( defined( 'DOING_CRON' ) && DOING_CRON ) ) {
205
+ add_filter( 'auto_update_plugin', array( $this, 'automatic_updates' ), 10, 2 );
206
+ }
207
 
208
+ //Loading widgets
209
+ include_once dirname( __FILE__ ) . '/widgets/cookiebot-declaration-widget.php';
210
+ add_action( 'widgets_init', array( $this, 'register_widgets' ) );
 
 
211
 
212
+ //Add Gutenberg block
213
+ add_action( 'init', array( $this, 'gutenberg_block_setup' ) );
214
+ add_action( 'enqueue_block_editor_assets', array( $this, 'gutenberg_block_admin_assets' ) );
215
  }
216
 
 
 
217
 
218
+ /**
219
+ * Cookiebot_WP Setup Gutenberg block
220
+ *
221
+ * @version 3.7.0
222
+ * @since 3.7.0
223
+ */
224
+ function gutenberg_block_setup() {
225
+ if ( ! function_exists( 'register_block_type' ) ) {
226
+ return; //gutenberg not active
227
+ }
228
+
229
+ register_block_type(
230
+ 'cookiebot/cookie-declaration',
231
+ array(
232
+ 'render_callback' => array( $this, 'block_cookie_declaration' ),
233
+ )
234
+ );
235
  }
236
 
237
+ /**
238
+ * Cookiebot_WP Add block JS
239
+ *
240
+ * @version 3.7.1
241
+ * @since 3.7.1
242
+ */
243
+ function gutenberg_block_admin_assets() {
244
+ //Add Gutenberg Widget
245
+ wp_enqueue_script(
246
+ 'cookiebot-declaration',
247
+ plugin_dir_url( __FILE__ ) . 'js/block.js',
248
+ array( 'wp-blocks', 'wp-i18n', 'wp-element' ), // Required scripts for the block
249
+ $this->version
250
+ );
 
 
 
 
 
 
251
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
252
 
253
+ /**
254
+ * Cookiebot_WP Render Cookiebot Declaration as Gutenberg block
255
+ *
256
+ * @version 3.7.0
257
+ * @since 3.7.0
258
+ */
259
+ function block_cookie_declaration() {
260
+ return $this->show_declaration();
261
+ }
262
 
263
+ /**
264
+ * Cookiebot_WP Load text domain
265
+ *
266
+ * @version 2.0.0
267
+ * @since 2.0.0
268
+ */
269
+ function load_textdomain() {
270
+ load_plugin_textdomain( 'cookiebot', false, basename( dirname( __FILE__ ) ) . '/langs' );
271
+ }
272
 
273
+ /**
274
+ * Cookiebot_WP Register widgets
275
+ *
276
+ * @version 2.5.0
277
+ * @since 2.5.0
278
+ */
279
+ function register_widgets() {
280
+ register_widget( 'Cookiebot_Declaration_Widget' );
281
+ }
282
 
283
+ /**
284
+ * Cookiebot_WP Add dashboard widgets to admin
285
+ *
286
+ * @version 1.0.0
287
+ * @since 1.0.0
288
+ */
289
 
290
+ function add_dashboard_widgets() {
291
+ wp_add_dashboard_widget( 'cookiebot_status', esc_html__( 'Cookiebot Status', 'cookiebot' ), array( $this, 'dashboard_widget_status' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
292
  }
 
293
 
294
+ /**
295
+ * Cookiebot_WP Output Dashboard Status Widget
296
+ *
297
+ * @version 1.0.0
298
+ * @since 1.0.0
299
+ */
300
+ function dashboard_widget_status() {
301
+ $cbid = $this->get_cbid();
302
+ if ( empty( $cbid ) ) {
303
+ echo '<p>' . esc_html__( 'You need to enter your Cookiebot ID.', 'cookiebot' ) . '</p>';
304
+ echo '<p><a href="options-general.php?page=cookiebot">';
305
+ echo esc_html__( 'Update your Cookiebot ID', 'cookiebot' );
306
+ echo '</a></p>';
307
+ } else {
308
+ echo '<p>' . esc_html_e( 'Your Cookiebot is working!', 'cookiebot' ) . '</p>';
309
+ }
 
 
 
310
  }
 
 
 
 
 
311
 
312
+ /**
313
+ * Cookiebot_WP Add option menu page for Cookiebot
314
+ *
315
+ * @version 2.2.0
316
+ * @since 1.0.0
317
+ */
318
+ function add_menu() {
319
+ //Cookiebot Icon SVG base64 encoded
320
+ $icon = 'data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNTQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGcgZmlsbD0iI0ZGRkZGRiIgZmlsbC1ydWxlPSJldmVub2RkIj48cGF0aCBkPSJNNDYuODcyNTkwMyA4Ljc3MzU4MzM0QzQxLjk0MzkwMzkgMy4zODI5NTAxMSAzNC44NDI0OTQ2IDAgMjYuOTQ4MjgxOSAwIDEyLjA2NTE1NjggMCAwIDEyLjAyNDQ3NzQgMCAyNi44NTc0MjE5YzAgMTQuODMyOTQ0NSAxMi4wNjUxNTY4IDI2Ljg1NzQyMTkgMjYuOTQ4MjgxOSAyNi44NTc0MjE5IDcuODk0MjEyNyAwIDE0Ljk5NTYyMi0zLjM4Mjk1MDIgMTkuOTI0MzA4NC04Ljc3MzU4MzQtMi44ODk2OTY3LTEuMzY4ODY2My01LjM5OTMxMS0zLjQwNTQzOS03LjMyODA4MzgtNS45MDk2MzU4LTMuMTIxNDMwNiAzLjIwOTQxMDQtNy40OTI5OTQ0IDUuMjA0MTI5MS0xMi4zMzIwMjU4IDUuMjA0MTI5MS05LjQ4NDM0NDQgMC0xNy4xNzI5MjQ3LTcuNjYyNjU3Mi0xNy4xNzI5MjQ3LTE3LjExNTAyMzhzNy42ODg1ODAzLTE3LjExNTAyMzcgMTcuMTcyOTI0Ny0xNy4xMTUwMjM3YzQuNzIzNDgyMiAwIDkuMDAxNTU1MiAxLjkwMDU5MzkgMTIuMTA2MjkyIDQuOTc2MzA5IDEuOTU2OTIzNy0yLjY0MTEzMSA0LjU1MDAyNjMtNC43ODU1MTgzIDcuNTUzODE3Ni02LjIwODQzMTg2eiIvPjxwYXRoIGQ9Ik01NS4zODAzMjgyIDQyLjY1MDE5OTFDNDYuMzMzNzIyNyA0Mi42NTAxOTkxIDM5IDM1LjM0MTIwMzEgMzkgMjYuMzI1MDk5NiAzOSAxNy4zMDg5OTYgNDYuMzMzNzIyNyAxMCA1NS4zODAzMjgyIDEwYzkuMDQ2NjA1NSAwIDE2LjM4MDMyODIgNy4zMDg5OTYgMTYuMzgwMzI4MiAxNi4zMjUwOTk2IDAgOS4wMTYxMDM1LTcuMzMzNzIyNyAxNi4zMjUwOTk1LTE2LjM4MDMyODIgMTYuMzI1MDk5NXptLjAyMTMwOTItNy43NTU2MzQyYzQuNzM3MDI3NiAwIDguNTc3MTQ3MS0zLjgyNzE3MiA4LjU3NzE0NzEtOC41NDgyMjc5IDAtNC43MjEwNTYtMy44NDAxMTk1LTguNTQ4MjI4LTguNTc3MTQ3MS04LjU0ODIyOC00LjczNzAyNzUgMC04LjU3NzE0NyAzLjgyNzE3Mi04LjU3NzE0NyA4LjU0ODIyOCAwIDQuNzIxMDU1OSAzLjg0MDExOTUgOC41NDgyMjc5IDguNTc3MTQ3IDguNTQ4MjI3OXoiLz48L2c+PC9zdmc+';
321
+ add_menu_page( 'Cookiebot', __( 'Cookiebot', 'cookiebot' ), 'manage_options', 'cookiebot', array( $this, 'settings_page' ), $icon );
322
+
323
+ add_submenu_page( 'cookiebot', __( 'Cookiebot Settings', 'cookiebot' ), __( 'Settings', 'cookiebot' ), 'manage_options', 'cookiebot', array( $this, 'settings_page' ), 10 );
324
+ add_submenu_page( 'cookiebot', __( 'Cookiebot Support', 'cookiebot' ), __( 'Support', 'cookiebot' ), 'manage_options', 'cookiebot_support', array( $this, 'support_page' ), 20 );
325
+ add_submenu_page( 'cookiebot', __( 'Google Tag Manager', 'cookiebot' ), __( 'Google Tag Manager', 'cookiebot' ), 'manage_options', 'cookiebot_GTM', array( $this, 'GTM_page' ) );
326
+ add_submenu_page( 'cookiebot', __( 'IAB', 'cookiebot' ), __( 'IAB', 'cookiebot' ), 'manage_options', 'cookiebot_iab', array( $this, 'iab_page' ), 30 );
327
+
328
+ if ( defined( 'COOKIEBOT_ADDONS_UNSUPPORTED_PHPVERSION' ) ) {
329
+ //Load prior consent page anyway - but from Cookiebot WP Core plugin.
330
+ add_submenu_page( 'cookiebot', __( 'Prior Consent', 'cookiebot' ), __( 'Prior Consent', 'cookiebot' ), 'manage_options', 'cookiebot-addons', array( $this, 'setting_page_placeholder' ), 40 );
331
+ }
332
+ }
333
 
334
+ function add_menu_legislations() {
335
+ add_submenu_page( 'cookiebot', __( 'Legislations', 'cookiebot' ), __( 'Legislations', 'cookiebot' ), 'manage_options', 'cookiebot-legislations', array( $this, 'legislations_page' ), 50 );
336
+ }
 
 
 
 
 
 
337
 
338
+ /**
339
+ * Cookiebot_WP Add debug menu - we need to add this seperate to ensure it is placed last (after menu items from Addons).
340
+ *
341
+ * @version 3.6.0
342
+ * @since 3.6.0
343
+ */
344
+ function add_menu_debug() {
345
+ add_submenu_page( 'cookiebot', __( 'Debug info', 'cookiebot' ), __( 'Debug info', 'cookiebot' ), 'manage_options', 'cookiebot_debug', array( $this, 'debug_page' ) );
346
+ }
347
 
348
+ /**
349
+ * Cookiebot_WP Add menu for network sites
350
+ *
351
+ * @version 2.2.0
352
+ * @since 2.2.0
353
+ */
354
+ function add_network_menu() {
355
+ $icon = 'data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNTQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGcgZmlsbD0iI0ZGRkZGRiIgZmlsbC1ydWxlPSJldmVub2RkIj48cGF0aCBkPSJNNDYuODcyNTkwMyA4Ljc3MzU4MzM0QzQxLjk0MzkwMzkgMy4zODI5NTAxMSAzNC44NDI0OTQ2IDAgMjYuOTQ4MjgxOSAwIDEyLjA2NTE1NjggMCAwIDEyLjAyNDQ3NzQgMCAyNi44NTc0MjE5YzAgMTQuODMyOTQ0NSAxMi4wNjUxNTY4IDI2Ljg1NzQyMTkgMjYuOTQ4MjgxOSAyNi44NTc0MjE5IDcuODk0MjEyNyAwIDE0Ljk5NTYyMi0zLjM4Mjk1MDIgMTkuOTI0MzA4NC04Ljc3MzU4MzQtMi44ODk2OTY3LTEuMzY4ODY2My01LjM5OTMxMS0zLjQwNTQzOS03LjMyODA4MzgtNS45MDk2MzU4LTMuMTIxNDMwNiAzLjIwOTQxMDQtNy40OTI5OTQ0IDUuMjA0MTI5MS0xMi4zMzIwMjU4IDUuMjA0MTI5MS05LjQ4NDM0NDQgMC0xNy4xNzI5MjQ3LTcuNjYyNjU3Mi0xNy4xNzI5MjQ3LTE3LjExNTAyMzhzNy42ODg1ODAzLTE3LjExNTAyMzcgMTcuMTcyOTI0Ny0xNy4xMTUwMjM3YzQuNzIzNDgyMiAwIDkuMDAxNTU1MiAxLjkwMDU5MzkgMTIuMTA2MjkyIDQuOTc2MzA5IDEuOTU2OTIzNy0yLjY0MTEzMSA0LjU1MDAyNjMtNC43ODU1MTgzIDcuNTUzODE3Ni02LjIwODQzMTg2eiIvPjxwYXRoIGQ9Ik01NS4zODAzMjgyIDQyLjY1MDE5OTFDNDYuMzMzNzIyNyA0Mi42NTAxOTkxIDM5IDM1LjM0MTIwMzEgMzkgMjYuMzI1MDk5NiAzOSAxNy4zMDg5OTYgNDYuMzMzNzIyNyAxMCA1NS4zODAzMjgyIDEwYzkuMDQ2NjA1NSAwIDE2LjM4MDMyODIgNy4zMDg5OTYgMTYuMzgwMzI4MiAxNi4zMjUwOTk2IDAgOS4wMTYxMDM1LTcuMzMzNzIyNyAxNi4zMjUwOTk1LTE2LjM4MDMyODIgMTYuMzI1MDk5NXptLjAyMTMwOTItNy43NTU2MzQyYzQuNzM3MDI3NiAwIDguNTc3MTQ3MS0zLjgyNzE3MiA4LjU3NzE0NzEtOC41NDgyMjc5IDAtNC43MjEwNTYtMy44NDAxMTk1LTguNTQ4MjI4LTguNTc3MTQ3MS04LjU0ODIyOC00LjczNzAyNzUgMC04LjU3NzE0NyAzLjgyNzE3Mi04LjU3NzE0NyA4LjU0ODIyOCAwIDQuNzIxMDU1OSAzLjg0MDExOTUgOC41NDgyMjc5IDguNTc3MTQ3IDguNTQ4MjI3OXoiLz48L2c+PC9zdmc+';
356
+ add_menu_page( 'Cookiebot', __( 'Cookiebot', 'cookiebot' ), 'manage_network_options', 'cookiebot_network', array( $this, 'network_settings_page' ), $icon );
357
 
358
+ add_submenu_page( 'cookiebot_network', __( 'Cookiebot Settings', 'cookiebot' ), __( 'Settings', 'cookiebot' ), 'network_settings_page', 'cookiebot_network', array( $this, 'network_settings_page' ) );
359
+ add_submenu_page( 'cookiebot_network', __( 'Cookiebot Support', 'cookiebot' ), __( 'Support', 'cookiebot' ), 'network_settings_page', 'cookiebot_support', array( $this, 'support_page' ) );
 
 
 
 
 
 
 
360
 
361
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
362
 
363
+ /**
364
+ * Cookiebot_WP Cookiebot prior consent placeholder page
365
+ *
366
+ * @version 1.4.0
367
+ * @since 1.0.0
368
+ */
369
+ function setting_page_placeholder() {
370
+ include __DIR__ . DIRECTORY_SEPARATOR . 'addons' . DIRECTORY_SEPARATOR . 'view/admin/settings/setting-page.php';
 
 
371
  }
372
 
373
+ /**
374
+ * Cookiebot_WP Register Cookiebot settings
375
+ *
376
+ * @version 3.9.0
377
+ * @since 1.0.0
378
+ */
379
+ function register_cookiebot_settings() {
380
+ register_setting( 'cookiebot', 'cookiebot-cbid' );
381
+ register_setting( 'cookiebot', 'cookiebot-language' );
382
+ register_setting( 'cookiebot', 'cookiebot-nooutput' );
383
+ register_setting( 'cookiebot', 'cookiebot-nooutput-admin' );
384
+ register_setting( 'cookiebot', 'cookiebot-output-logged-in' );
385
+ register_setting( 'cookiebot', 'cookiebot-autoupdate' );
386
+ register_setting( 'cookiebot', 'cookiebot-script-tag-uc-attribute' );
387
+ register_setting( 'cookiebot', 'cookiebot-script-tag-cd-attribute' );
388
+ register_setting( 'cookiebot', 'cookiebot-cookie-blocking-mode' );
389
+ register_setting( 'cookiebot', 'cookiebot-consent-mapping' );
390
+ register_setting( 'cookiebot-iab', 'cookiebot-iab' );
391
+ register_setting( 'cookiebot-legislations', 'cookiebot-ccpa' );
392
+ register_setting( 'cookiebot-legislations', 'cookiebot-ccpa-domain-group-id' );
393
+ register_setting( 'cookiebot-gtm', 'cookiebot-gtm' );
394
+ register_setting( 'cookiebot-gtm', 'cookiebot-gtm-id' );
395
+ register_setting( 'cookiebot-gtm', 'cookiebot-data-layer' );
396
+ register_setting( 'cookiebot-gtm', 'cookiebot-gcm' );
397
  }
398
 
399
+ /**
400
+ * Cookiebot_WP Automatic update plugin if activated
401
+ *
402
+ * @version 2.2.0
403
+ * @since 1.5.0
404
+ */
405
+ function automatic_updates( $update, $item ) {
406
+ //Do not update from subsite on a multisite installation
407
+ if ( is_multisite() && ! is_main_site() ) {
408
+ return $update;
409
+ }
410
 
411
+ //Check if we have everything we need
412
+ $item = (array) $item;
413
+ if ( ! isset( $item['new_version'] ) || ! isset( $item['slug'] ) ) {
414
+ return $update;
415
+ }
416
 
417
+ //It is not Cookiebot
418
+ if ( $item['slug'] !== 'cookiebot' ) {
419
+ return $update;
420
+ }
421
 
422
+ // Check if cookiebot autoupdate is disabled
423
+ if ( ! get_option( 'cookiebot-autoupdate', false ) ) {
424
+ return $update;
425
+ }
426
 
427
+ // Check if multisite autoupdate is disabled
428
+ if ( is_multisite() && ! get_site_option( 'cookiebot-autoupdate', false ) ) {
429
+ return $update;
430
+ }
431
 
432
+ return true;
433
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
434
 
435
+
436
+ /**
437
+ * Cookiebot_WP Get list of supported languages
438
+ *
439
+ * @version 1.4.0
440
+ * @since 1.4.0
441
+ */
442
+ public static function get_supported_languages() {
443
+ $supportedLanguages = array();
444
+ $supportedLanguages['nb'] = __( 'Norwegian Bokmål', 'cookiebot' );
445
+ $supportedLanguages['tr'] = __( 'Turkish', 'cookiebot' );
446
+ $supportedLanguages['de'] = __( 'German', 'cookiebot' );
447
+ $supportedLanguages['cs'] = __( 'Czech', 'cookiebot' );
448
+ $supportedLanguages['da'] = __( 'Danish', 'cookiebot' );
449
+ $supportedLanguages['sq'] = __( 'Albanian', 'cookiebot' );
450
+ $supportedLanguages['he'] = __( 'Hebrew', 'cookiebot' );
451
+ $supportedLanguages['ko'] = __( 'Korean', 'cookiebot' );
452
+ $supportedLanguages['it'] = __( 'Italian', 'cookiebot' );
453
+ $supportedLanguages['nl'] = __( 'Dutch', 'cookiebot' );
454
+ $supportedLanguages['vi'] = __( 'Vietnamese', 'cookiebot' );
455
+ $supportedLanguages['ta'] = __( 'Tamil', 'cookiebot' );
456
+ $supportedLanguages['is'] = __( 'Icelandic', 'cookiebot' );
457
+ $supportedLanguages['ro'] = __( 'Romanian', 'cookiebot' );
458
+ $supportedLanguages['si'] = __( 'Sinhala', 'cookiebot' );
459
+ $supportedLanguages['ca'] = __( 'Catalan', 'cookiebot' );
460
+ $supportedLanguages['bg'] = __( 'Bulgarian', 'cookiebot' );
461
+ $supportedLanguages['uk'] = __( 'Ukrainian', 'cookiebot' );
462
+ $supportedLanguages['zh'] = __( 'Chinese', 'cookiebot' );
463
+ $supportedLanguages['en'] = __( 'English', 'cookiebot' );
464
+ $supportedLanguages['ar'] = __( 'Arabic', 'cookiebot' );
465
+ $supportedLanguages['hr'] = __( 'Croatian', 'cookiebot' );
466
+ $supportedLanguages['th'] = __( 'Thai', 'cookiebot' );
467
+ $supportedLanguages['el'] = __( 'Greek', 'cookiebot' );
468
+ $supportedLanguages['lt'] = __( 'Lithuanian', 'cookiebot' );
469
+ $supportedLanguages['pl'] = __( 'Polish', 'cookiebot' );
470
+ $supportedLanguages['lv'] = __( 'Latvian', 'cookiebot' );
471
+ $supportedLanguages['fr'] = __( 'French', 'cookiebot' );
472
+ $supportedLanguages['id'] = __( 'Indonesian', 'cookiebot' );
473
+ $supportedLanguages['mk'] = __( 'Macedonian', 'cookiebot' );
474
+ $supportedLanguages['et'] = __( 'Estonian', 'cookiebot' );
475
+ $supportedLanguages['pt'] = __( 'Portuguese', 'cookiebot' );
476
+ $supportedLanguages['ga'] = __( 'Irish', 'cookiebot' );
477
+ $supportedLanguages['ms'] = __( 'Malay', 'cookiebot' );
478
+ $supportedLanguages['sl'] = __( 'Slovenian', 'cookiebot' );
479
+ $supportedLanguages['ru'] = __( 'Russian', 'cookiebot' );
480
+ $supportedLanguages['ja'] = __( 'Japanese', 'cookiebot' );
481
+ $supportedLanguages['hi'] = __( 'Hindi', 'cookiebot' );
482
+ $supportedLanguages['sk'] = __( 'Slovak', 'cookiebot' );
483
+ $supportedLanguages['es'] = __( 'Spanish', 'cookiebot' );
484
+ $supportedLanguages['sv'] = __( 'Swedish', 'cookiebot' );
485
+ $supportedLanguages['sr'] = __( 'Serbian', 'cookiebot' );
486
+ $supportedLanguages['fi'] = __( 'Finnish', 'cookiebot' );
487
+ $supportedLanguages['eu'] = __( 'Basque', 'cookiebot' );
488
+ $supportedLanguages['hu'] = __( 'Hungarian', 'cookiebot' );
489
+ asort( $supportedLanguages, SORT_LOCALE_STRING );
490
+ return $supportedLanguages;
491
  }
492
+
493
+ /**
494
+ * Cookiebot_WP Output settings page
495
+ *
496
+ * @version 3.9.0
497
+ * @since 1.0.0
498
+ */
499
+ function settings_page() {
500
+ wp_enqueue_style( 'cookiebot-consent-mapping-table', plugins_url( 'css/consent_mapping_table.css', __FILE__ ), array(), '3.5.0' );
501
+
502
+ /* Check if multisite */
503
+ if ( $is_ms = is_multisite() ) {
504
+ //Receive settings from multisite - this might change the way we render the form
505
+ $network_cbid = get_site_option( 'cookiebot-cbid', '' );
506
+ $network_scrip_tag_uc_attr = get_site_option( 'cookiebot-script-tag-uc-attribute', 'custom' );
507
+ $network_scrip_tag_cd_attr = get_site_option( 'cookiebot-script-tag-cd-attribute', 'custom' );
508
+ $network_cookie_blocking_mode = get_site_option( 'cookiebot-cookie-blocking-mode', 'manual' );
509
+ }
510
+ ?>
511
  <div class="wrap">
512
+ <h1><?php esc_html_e( 'Cookiebot Settings', 'cookiebot' ); ?></h1>
513
  <a href="https://www.cookiebot.com">
514
  <img src="<?php echo plugins_url( 'cookiebot-logo.png', __FILE__ ); ?>" style="float:right;margin-left:1em;">
515
  </a>
516
  <p>
517
+ <?php
518
+ $cookiebot_gdpr_url = 'https://www.cookiebot.com/goto/gdpr';
519
+ printf(
520
+ esc_html__( 'Cookiebot enables your website to comply with current legislation in the EU on the use of cookies for user tracking and profiling. The EU ePrivacy Directive requires prior, informed consent of your site users, while the %1$s %2$s.', 'cookiebot' ),
521
+ sprintf(
522
+ '<a href="%s" target="_blank">%s</a>',
523
+ esc_url( $cookiebot_gdpr_url ),
524
+ esc_html__( 'General Data Protection Regulation (GDPR)', 'cookiebot' )
525
+ ),
526
+ esc_html__( ' requires you to document each consent. At the same time you must be able to account for what user data you share with embedded third-party services on your website and where in the world the user data is sent.', 'cookiebot' )
527
+ );
528
+ ?>
529
  </p>
530
  <form method="post" action="options.php">
531
+ <?php settings_fields( 'cookiebot' ); ?>
532
  <?php do_settings_sections( 'cookiebot' ); ?>
533
  <table class="form-table">
534
  <tr valign="top">
535
+ <th scope="row"><?php esc_html_e( 'Cookiebot ID', 'cookiebot' ); ?></th>
536
  <td>
537
+ <input type="text" name="cookiebot-cbid" value="<?php echo esc_attr( get_option( 'cookiebot-cbid' ) ); ?>"<?php echo ( $is_ms ) ? ' placeholder="' . $network_cbid . '"' : ''; ?> style="width:300px" />
538
  <p class="description">
539
+ <?php esc_html_e( 'Need an ID?', 'cookiebot' ); ?>
540
+ <a href="https://www.cookiebot.com/goto/signup" target="_blank"><?php esc_html_e( 'Sign up for free on cookiebot.com', 'cookiebot' ); ?></a>
541
  </p>
542
  </td>
543
  </tr>
544
  <tr valign="top">
545
  <th scope="row">
546
+ <?php esc_html_e( 'Cookie-blocking mode', 'cookiebot' ); ?>
547
  </th>
548
  <td>
549
  <?php
550
+ $cbm = get_option( 'cookiebot-cookie-blocking-mode', 'manual' );
551
+ if ( $is_ms && $network_cookie_blocking_mode != 'custom' ) {
552
  $cbm = $network_cookie_blocking_mode;
553
  }
554
  ?>
555
  <label>
556
+ <input type="radio" name="cookiebot-cookie-blocking-mode" value="auto" <?php checked( 'auto', $cbm, true ); ?> />
557
+ <?php esc_html_e( 'Automatic', 'cookiebot' ); ?>
558
  </label>
559
  &nbsp; &nbsp;
560
  <label>
561
+ <input type="radio" name="cookiebot-cookie-blocking-mode" value="manual" <?php checked( 'manual', $cbm, true ); ?> />
562
+ <?php esc_html_e( 'Manual', 'cookiebot' ); ?>
563
  </label>
564
  <p class="description">
565
+ <?php esc_html_e( 'Automatic block cookies (except necessary) until the user has given their consent.', 'cookiebot' ); ?>
566
  <a href="https://support.cookiebot.com/hc/en-us/articles/360009063100-Automatic-Cookie-Blocking-How-does-it-work-" target="_blank">
567
+ <?php esc_html_e( 'Learn more', 'cookiebot' ); ?>
568
  </a>
569
  </p>
570
  <script>
590
  </td>
591
  </tr>
592
  <tr valign="top">
593
+ <th scope="row"><?php esc_html_e( 'Cookiebot Language', 'cookiebot' ); ?></th>
594
  <td>
595
  <div>
596
  <select name="cookiebot-language" id="cookiebot-language">
597
  <?php
598
+ $currentLang = $this->get_language( true );
599
  ?>
600
+ <option value=""><?php esc_html_e( 'Default (Autodetect)', 'cookiebot' ); ?></option>
601
+ <option value="_wp"<?php echo ( $currentLang == '_wp' ) ? ' selected' : ''; ?>><?php esc_html_e( 'Use WordPress Language', 'cookiebot' ); ?></option>
602
  <?php
603
  $supportedLanguages = $this->get_supported_languages();
604
+ foreach ( $supportedLanguages as $langCode => $langName ) {
605
+ echo '<option value="' . $langCode . '"' . ( ( $currentLang == $langCode ) ? ' selected' : '' ) . '>' . $langName . '</option>';
606
  }
607
  ?>
608
  </select>
609
  </div>
610
  <div class="notice inline notice-warning notice-alt cookiebot-notice" style="padding:12px;font-size:13px;display:inline-block;">
611
+ <div style="<?php echo ( $currentLang == '' ) ? 'display:none;' : ''; ?>" id="info_lang_specified">
612
+ <?php esc_html_e( 'You need to add the language in the Cookiebot administration tool.', 'cookiebot' ); ?>
613
  </div>
614
+ <div style="<?php echo ( $currentLang == '' ) ? '' : 'display:none;'; ?>" id="info_lang_autodetect">
615
+ <?php esc_html_e( 'You need to add all languages that you want auto-detected in the Cookiebot administration tool.', 'cookiebot' ); ?> <br/>
616
+ <?php esc_html_e( 'The auto-detect checkbox needs to be enabled in the Cookiebot administration tool.', 'cookiebot' ); ?><br/>
617
+ <?php esc_html_e( 'If the auto-detected language is not supported, Cookiebot will use the default language.', 'cookiebot' ); ?>
618
  </div>
619
  <br />
620
 
621
+ <a href="#" id="show_add_language_guide"><?php esc_html_e( 'Show guide to add languages', 'cookiebot' ); ?></a>
622
  &nbsp;
623
  <a href="https://support.cookiebot.com/hc/en-us/articles/360003793394-How-do-I-set-the-language-of-the-consent-banner-dialog-" target="_blank">
624
+ <?php esc_html_e( 'Read more here', 'cookiebot' ); ?>
625
  </a>
626
 
627
  <div id="add_language_guide" style="display:none;">
628
  <img src="<?php echo plugin_dir_url( __FILE__ ); ?>/assets/guide_add_language.gif" alt="Add language in Cookiebot administration tool" />
629
  <br />
630
+ <a href="#" id="hide_add_language_guide"><?php esc_html_e( 'Hide guide', 'cookiebot' ); ?></a>
631
  </div>
632
  </div>
633
  <script>
682
  content: "\f142";
683
  }
684
  </style>
685
+ <h3 id="advanced_settings_link" class="cookiebot_fieldset_header"><?php esc_html_e( 'Advanced settings', 'cookiebot' ); ?></h3>
686
  <div id="advanced_settings" style="display:none;">
687
  <table class="form-table">
688
  <tr valign="top" id="cookiebot-setting-async">
689
  <th scope="row">
690
+ <?php esc_html_e( 'Add async or defer attribute', 'cookiebot' ); ?>
691
+ <br /><?php esc_html_e( 'Consent banner script tag', 'cookiebot' ); ?>
692
  </th>
693
  <td>
694
+ <?php
695
+ $cv = get_option( 'cookiebot-script-tag-uc-attribute', 'async' );
696
+ $disabled = false;
697
+ if ( $is_ms && $network_scrip_tag_uc_attr != 'custom' ) {
698
+ $disabled = true;
699
+ $cv = $network_scrip_tag_uc_attr;
700
+ }
701
+ ?>
702
  <label>
703
+ <input type="radio" name="cookiebot-script-tag-uc-attribute"<?php echo ( $disabled ) ? ' disabled' : ''; ?> value="" <?php checked( '', $cv, true ); ?> />
704
+ <i><?php esc_html_e( 'None', 'cookiebot' ); ?></i>
705
  </label>
706
  &nbsp; &nbsp;
707
  <label>
708
+ <input type="radio" name="cookiebot-script-tag-uc-attribute"<?php echo ( $disabled ) ? ' disabled' : ''; ?> value="async" <?php checked( 'async', $cv, true ); ?> />
709
  async
710
  </label>
711
  &nbsp; &nbsp;
712
  <label>
713
+ <input type="radio" name="cookiebot-script-tag-uc-attribute"<?php echo ( $disabled ) ? ' disabled' : ''; ?> value="defer" <?php checked( 'defer', $cv, true ); ?> />
714
  defer
715
  </label>
716
  <p class="description">
717
+ <?php
718
+ if ( $disabled ) {
719
+ echo '<b>' . esc_html__( 'Network setting applied. Please contact website administrator to change this setting.', 'cookiebot' ) . '</b><br />'; }
720
+ ?>
721
+ <?php esc_html_e( 'Add async or defer attribute to Cookiebot script tag. Default: async', 'cookiebot' ); ?>
722
  </p>
723
  </td>
724
  </tr>
725
  <tr valign="top">
726
  <th scope="row">
727
+ <?php esc_html_e( 'Add async or defer attribute', 'cookiebot' ); ?>
728
+ <br /><?php esc_html_e( 'Cookie declaration script tag', 'cookiebot' ); ?>
729
  </th>
730
  <td>
731
  <?php
732
+ $cv = get_option( 'cookiebot-script-tag-cd-attribute', 'async' );
733
  $disabled = false;
734
+ if ( $is_ms && $network_scrip_tag_cd_attr != 'custom' ) {
735
  $disabled = true;
736
+ $cv = $network_scrip_tag_cd_attr;
737
  }
738
  ?>
739
  <label>
740
+ <input type="radio" name="cookiebot-script-tag-cd-attribute"<?php echo ( $disabled ) ? ' disabled' : ''; ?> value="" <?php checked( '', $cv, true ); ?> />
741
+ <i><?php esc_html_e( 'None', 'cookiebot' ); ?></i>
742
  </label>
743
  &nbsp; &nbsp;
744
  <label>
745
+ <input type="radio" name="cookiebot-script-tag-cd-attribute"<?php echo ( $disabled ) ? ' disabled' : ''; ?> value="async" <?php checked( 'async', $cv, true ); ?> />
746
  async
747
  </label>
748
  &nbsp; &nbsp;
749
  <label>
750
+ <input type="radio" name="cookiebot-script-tag-cd-attribute"<?php echo ( $disabled ) ? ' disabled' : ''; ?> value="defer" <?php checked( 'defer', $cv, true ); ?> />
751
  defer
752
  </label>
753
  <p class="description">
754
+ <?php
755
+ if ( $disabled ) {
756
+ echo '<b>' . esc_html__( 'Network setting applied. Please contact website administrator to change this setting.', 'cookiebot' ) . '</b><br />'; }
757
+ ?>
758
+ <?php esc_html_e( 'Add async or defer attribute to Cookiebot script tag. Default: async', 'cookiebot' ); ?>
759
  </p>
760
  </td>
761
  </tr>
762
+ <?php
763
+ if ( ! is_multisite() ) {
764
+ ?>
765
  <tr valign="top">
766
+ <th scope="row"><?php esc_html_e( 'Auto-update Cookiebot', 'cookiebot' ); ?></th>
767
  <td>
768
+ <input type="checkbox" name="cookiebot-autoupdate" value="1" <?php checked( 1, get_option( 'cookiebot-autoupdate', false ), true ); ?> />
769
  <p class="description">
770
+ <?php esc_html_e( 'Automatic update your Cookiebot plugin when new releases becomes available.', 'cookiebot' ); ?>
771
  </p>
772
  </td>
773
  </tr>
774
+ <?php
775
+ }
776
+ ?>
777
  <tr valign="top" id="cookiebot-setting-hide-popup">
778
+ <th scope="row"><?php esc_html_e( 'Hide Cookie Popup', 'cookiebot' ); ?></th>
779
  <td>
780
  <?php
781
  $disabled = false;
782
+ if ( $is_ms && get_site_option( 'cookiebot-nooutput', false ) ) {
783
  $disabled = true;
784
  echo '<input type="checkbox" checked disabled />';
785
+ } else {
 
786
  ?>
787
+ <input type="checkbox" name="cookiebot-nooutput" value="1" <?php checked( 1, get_option( 'cookiebot-nooutput', false ), true ); ?> />
788
  <?php
789
  }
790
  ?>
791
  <p class="description">
792
+ <?php
793
+ if ( $disabled ) {
794
+ echo '<b>' . esc_html__( 'Network setting applied. Please contact website administrator to change this setting.', 'cookiebot' ) . '</b><br />'; }
795
+ ?>
796
+ <b><?php esc_html_e( 'This checkbox will remove the cookie consent banner from your website. The <i>[cookie_declaration]</i> shortcode will still be available.', 'cookiebot' ); ?></b><br />
797
+ <?php esc_html_e( 'If you are using Google Tag Manager (or equal), you need to add the Cookiebot script in your Tag Manager.', 'cookiebot' ); ?><br />
798
+ <a href="https://support.cookiebot.com/hc/en-us/articles/360003793854-Google-Tag-Manager-deployment" target="_blank">
799
+ <?php esc_html_e( 'See a detailed guide here', 'cookiebot' ); ?>
800
+ </a>
801
  </p>
802
  </td>
803
  </tr>
804
  <tr valign="top">
805
+ <th scope="row"><?php esc_html_e( 'Disable Cookiebot in WP Admin', 'cookiebot' ); ?></th>
806
  <td>
807
  <?php
808
  $disabled = false;
809
+ if ( $is_ms && get_site_option( 'cookiebot-nooutput-admin', false ) ) {
810
  echo '<input type="checkbox" checked disabled />';
811
  $disabled = true;
812
+ } else {
 
813
  ?>
814
+ <input type="checkbox" name="cookiebot-nooutput-admin" value="1" <?php checked( 1, get_option( 'cookiebot-nooutput-admin', false ), true ); ?> />
815
  <?php
816
  }
817
  ?>
818
  <p class="description">
819
+ <?php
820
+ if ( $disabled ) {
821
+ echo '<b>' . __( 'Network setting applied. Please contact website administrator to change this setting.' ) . '</b><br />'; }
822
+ ?>
823
+ <b><?php esc_html_e( 'This checkbox will disable Cookiebot in the WordPress Admin area.', 'cookiebot' ); ?></b>
824
  </p>
825
  </td>
826
  </tr>
827
  <tr valign="top">
828
+ <th scope="row"><?php esc_html_e( 'Enable Cookiebot on front end while logged in', 'cookiebot' ); ?></th>
829
  <td>
830
  <?php
831
  $disabled = false;
832
+ if ( $is_ms && get_site_option( 'cookiebot-output-logged-in', false ) ) {
833
  echo '<input type="checkbox" checked disabled />';
834
  $disabled = true;
835
+ } else {
 
836
  ?>
837
+ <input type="checkbox" name="cookiebot-output-logged-in" value="1" <?php checked( 1, get_option( 'cookiebot-output-logged-in', false ), true ); ?> />
838
  <?php
839
  }
840
  ?>
841
  <p class="description">
842
+ <?php
843
+ if ( $disabled ) {
844
+ echo '<b>' . esc_html__( 'Network setting applied. Please contact website administrator to change this setting.' ) . '</b><br />'; }
845
+ ?>
846
+ <b><?php esc_html_e( 'This checkbox will enable Cookiebot on front end while you\'re logged in', 'cookiebot' ); ?></b>
847
  </p>
848
  </td>
849
  </tr>
850
  </table>
851
  </div>
852
+ <?php if ( $this->is_wp_consent_api_active() ) { ?>
853
+ <h3 id="consent_level_api_settings" class="cookiebot_fieldset_header"><?php esc_html_e( 'Consent Level API Settings', 'cookiebot' ); ?></h3>
854
  <div id="consent_level_api_settings" style="display:none;">
855
+ <p><?php esc_html_e( 'WP Consent Level API and Cookiebot categorise cookies a bit different. The default settings should fit mosts needs - but if you need to change the mapping you are able to do it below.', 'cookiebot' ); ?></p>
856
 
857
  <?php
858
  $mDefault = $this->get_default_wp_consent_api_mapping();
859
 
860
  $m = $this->get_wp_consent_api_mapping();
861
 
862
+ $consentTypes = array( 'preferences', 'statistics', 'marketing' );
863
+ $states = array_reduce(
864
+ $consentTypes,
865
+ function ( $t, $v ) {
866
+ $newt = array();
867
+ if ( empty( $t ) ) {
868
+ $newt = array(
869
+ array( $v => true ),
870
+ array( $v => false ),
871
+ );
872
  } else {
873
+ foreach ( $t as $item ) {
874
+ $newt[] = array_merge( $item, array( $v => true ) );
875
+ $newt[] = array_merge( $item, array( $v => false ) );
876
+ }
877
  }
878
 
879
  return $newt;
880
+ },
881
+ array()
882
+ );
883
 
884
  ?>
885
 
887
  <table class="widefat striped consent_mapping_table">
888
  <thead>
889
  <tr>
890
+ <th><?php esc_html_e( 'Cookiebot categories', 'cookiebot' ); ?></th>
891
+ <th class="consent_mapping"><?php esc_html_e( 'WP Consent Level categories', 'cookiebot' ); ?></th>
892
  </tr>
893
  </thead>
894
  <?php
895
+ foreach ( $states as $state ) {
896
 
897
+ $key = array();
898
  $key[] = 'n=1';
899
+ $key[] = 'p=' . ( $state['preferences'] ? '1' : '0' );
900
+ $key[] = 's=' . ( $state['statistics'] ? '1' : '0' );
901
+ $key[] = 'm=' . ( $state['marketing'] ? '1' : '0' );
902
+ $key = implode( ';', $key );
903
  ?>
904
  <tr valign="top">
905
  <td>
906
  <div class="cb_consent">
907
+ <span class="forceconsent">
908
+ <?php esc_html_e( 'Necessary', 'cookiebot' ); ?>
909
+ </span>
910
+ <span class="<?php echo( $state['preferences'] ? 'consent' : 'noconsent' ); ?>">
911
+ <?php esc_html_e( 'Preferences', 'cookiebot' ); ?>
912
+ </span>
913
+ <span class="<?php echo( $state['statistics'] ? 'consent' : 'noconsent' ); ?>">
914
+ <?php esc_html_e( 'Statistics', 'cookiebot' ); ?>
915
+ </span>
916
+ <span class="<?php echo( $state['marketing'] ? 'consent' : 'noconsent' ); ?>">
917
+ <?php esc_html_e( 'Marketing', 'cookiebot' ); ?>
918
+ </span>
919
  </div>
920
  </td>
921
  <td>
922
  <div class="consent_mapping">
923
+ <label><input type="checkbox" name="cookiebot-consent-mapping[<?php echo $key; ?>][functional]" data-default-value="1" value="1" checked disabled
924
+ > <?php esc_html_e( 'Functional', 'cookiebot' ); ?> </label>
925
+ <label><input type="checkbox" name="cookiebot-consent-mapping[<?php echo $key; ?>][preferences]" data-default-value="<?php echo $mDefault[ $key ]['preferences']; ?>" value="1"
926
+ <?php
927
+ if ( $m[ $key ]['preferences'] ) {
928
+ echo 'checked'; }
929
+ ?>
930
+ > <?php esc_html_e( 'Preferences', 'cookiebot' ); ?> </label>
931
+ <label><input type="checkbox" name="cookiebot-consent-mapping[<?php echo $key; ?>][statistics]" data-default-value="<?php echo $mDefault[ $key ]['statistics']; ?>" value="1"
932
+ <?php
933
+ if ( $m[ $key ]['statistics'] ) {
934
+ echo 'checked'; }
935
+ ?>
936
+ > <?php esc_html_e( 'Statistics', 'cookiebot' ); ?> </label>
937
+ <label><input type="checkbox" name="cookiebot-consent-mapping[<?php echo $key; ?>][statistics-anonymous]" data-default-value="<?php echo $mDefault[ $key ]['statistics-anonymous']; ?>" value="1"
938
+ <?php
939
+ if ( $m[ $key ]['statistics-anonymous'] ) {
940
+ echo 'checked'; }
941
+ ?>
942
+ > <?php esc_html_e( 'Statistics Anonymous', 'cookiebot' ); ?></label>
943
+ <label><input type="checkbox" name="cookiebot-consent-mapping[<?php echo $key; ?>][marketing]" data-default-value="<?php echo $mDefault[ $key ]['marketing']; ?>" value="1"
944
+ <?php
945
+ if ( $m[ $key ]['marketing'] ) {
946
+ echo 'checked'; }
947
+ ?>
948
+ > <?php esc_html_e( 'Marketing', 'cookiebot' ); ?></label>
949
  </div>
950
  </td>
951
  </tr>
954
  ?>
955
  <tfoot>
956
  <tr>
957
+ <td colspan="2" style="text-align:right;"><button class="button" onclick="return resetConsentMapping();"><?php esc_html_e( 'Reset to default mapping', 'cookiebot' ); ?></button></td>
958
  </tr>
959
  </tfoot>
960
  </table>
972
  </script>
973
  </div>
974
  <?php } ?>
975
+ <?php submit_button(); ?>
976
  </form>
977
  </div>
978
+ <?php
979
+ }
980
 
981
+ /**
982
+ * Cookiebot_WP Cookiebot network setting page
983
+ *
984
+ * @version 2.2.0
985
+ * @since 2.2.0
986
+ */
987
+ function network_settings_page() {
988
+ ?>
989
  <div class="wrap">
990
+ <h1><?php esc_html_e( 'Cookiebot Network Settings', 'cookiebot' ); ?></h1>
991
  <a href="https://www.cookiebot.com">
992
  <img src="<?php echo plugins_url( 'cookiebot-logo.png', __FILE__ ); ?>" style="float:right;margin-left:1em;">
993
  </a>
994
  <p>
995
+ <?php
996
+ $cookiebot_gdpr_url = 'https://www.cookiebot.com/goto/gdpr';
997
+ printf(
998
+ esc_html__( 'Cookiebot enables your website to comply with current legislation in the EU on the use of cookies for user tracking and profiling. The EU ePrivacy Directive requires prior, informed consent of your site users, while the %1$s %2$s.', 'cookiebot' ),
999
+ sprintf(
1000
+ '<a href="%s" target="_blank">%s</a>',
1001
+ esc_url( $cookiebot_gdpr_url ),
1002
+ esc_html__( 'General Data Protection Regulation (GDPR)', 'cookiebot' )
1003
+ ),
1004
+ esc_html__( ' requires you to document each consent. At the same time you must be able to account for what user data you share with embedded third-party services on your website and where in the world the user data is sent.', 'cookiebot' )
1005
+ );
1006
+ ?>
1007
  </p>
1008
  <p>
1009
+ <b><big style="color:red;"><?php esc_html_e( 'The settings below is network wide settings. See notes below each field.', 'cookiebot' ); ?></big></b>
1010
  </p>
1011
  <form method="post" action="edit.php?action=cookiebot_network_settings">
1012
+ <?php wp_nonce_field( 'cookiebot-network-settings' ); ?>
1013
  <table class="form-table">
1014
  <tr valign="top">
1015
+ <th scope="row"><?php esc_html_e( 'Network Cookiebot ID', 'cookiebot' ); ?></th>
1016
  <td>
1017
+ <input type="text" name="cookiebot-cbid" value="<?php echo esc_attr( get_site_option( 'cookiebot-cbid', '' ) ); ?>" style="width:300px" />
1018
  <p class="description">
1019
+ <b><?php esc_html_e( 'If added this will be the default Cookiebot ID for all subsites. Subsites are able to override the Cookiebot ID.', 'cookiebot' ); ?></b>
1020
  <br />
1021
+ <?php esc_html_e( 'Need an ID?', 'cookiebot' ); ?>
1022
+ <a href="https://www.cookiebot.com/goto/signup" target="_blank"><?php esc_html_e( 'Sign up for free on cookiebot.com', 'cookiebot' ); ?></a>
1023
  </p>
1024
  </td>
1025
  </tr>
1026
  <tr valign="top">
1027
  <th scope="row">
1028
+ <?php esc_html_e( 'Cookie-blocking mode', 'cookiebot' ); ?>
1029
  </th>
1030
  <td>
1031
+ <?php
1032
+ $cbm = get_site_option( 'cookiebot-cookie-blocking-mode', 'manual' );
1033
+ ?>
1034
  <label>
1035
+ <input type="radio" name="cookiebot-cookie-blocking-mode" value="auto" <?php checked( 'auto', $cbm, true ); ?> />
1036
+ <?php esc_html_e( 'Automatic', 'cookiebot' ); ?>
1037
  </label>
1038
  &nbsp; &nbsp;
1039
  <label>
1040
+ <input type="radio" name="cookiebot-cookie-blocking-mode" value="manual" <?php checked( 'manual', $cbm, true ); ?> />
1041
+ <?php esc_html_e( 'Manual', 'cookiebot' ); ?>
1042
  </label>
1043
  <p class="description">
1044
+ <?php esc_html_e( 'Should Cookiebot automatic block cookies by tagging known tags.', 'cookiebot' ); ?>
1045
  </p>
1046
  </td>
1047
  </tr>
1067
  </script>
1068
  <tr valign="top" id="cookiebot-setting-async">
1069
  <th scope="row">
1070
+ <?php esc_html_e( 'Add async or defer attribute', 'cookiebot' ); ?>
1071
+ <br /><?php esc_html_e( 'Consent banner script tag', 'cookiebot' ); ?>
1072
  </th>
1073
  <td>
1074
  <?php
1075
+ $cv = get_site_option( 'cookiebot-script-tag-uc-attribute', 'custom' );
1076
  ?>
1077
  <label>
1078
+ <input type="radio" name="cookiebot-script-tag-uc-attribute" value="" <?php checked( '', $cv, true ); ?> />
1079
+ <i><?php esc_html_e( 'None', 'cookiebot' ); ?></i>
1080
  </label>
1081
  &nbsp; &nbsp;
1082
  <label>
1083
+ <input type="radio" name="cookiebot-script-tag-uc-attribute" value="async" <?php checked( 'async', $cv, true ); ?> />
1084
  async
1085
  </label>
1086
  &nbsp; &nbsp;
1087
  <label>
1088
+ <input type="radio" name="cookiebot-script-tag-uc-attribute" value="defer" <?php checked( 'defer', $cv, true ); ?> />
1089
  defer
1090
  </label>
1091
  &nbsp; &nbsp;
1092
  <label>
1093
+ <input type="radio" name="cookiebot-script-tag-uc-attribute" value="custom" <?php checked( 'custom', $cv, true ); ?> />
1094
+ <i><?php esc_html_e( 'Choose per subsite', 'cookiebot' ); ?></i>
1095
  </label>
1096
  <p class="description">
1097
+ <b><?php esc_html_e( 'Setting will apply for all subsites. Subsites will not be able to override.', 'cookiebot' ); ?></b><br />
1098
+ <?php esc_html_e( 'Add async or defer attribute to Cookiebot script tag. Default: Choose per subsite', 'cookiebot' ); ?>
1099
  </p>
1100
  </td>
1101
  </tr>
1102
  <tr valign="top">
1103
  <th scope="row">
1104
+ <?php esc_html_e( 'Add async or defer attribute', 'cookiebot' ); ?>
1105
+ <br /><?php esc_html_e( 'Cookie declaration script tag', 'cookiebot' ); ?>
1106
  </th>
1107
  <td>
1108
  <?php
1109
+ $cv = get_site_option( 'cookiebot-script-tag-cd-attribute', 'custom' );
1110
  ?>
1111
  <label>
1112
+ <input type="radio" name="cookiebot-script-tag-cd-attribute" value="" <?php checked( '', $cv, true ); ?> />
1113
+ <i><?php esc_html_e( 'None', 'cookiebot' ); ?></i>
1114
  </label>
1115
  &nbsp; &nbsp;
1116
  <label>
1117
+ <input type="radio" name="cookiebot-script-tag-cd-attribute" value="async" <?php checked( 'async', $cv, true ); ?> />
1118
  async
1119
  </label>
1120
  &nbsp; &nbsp;
1121
  <label>
1122
+ <input type="radio" name="cookiebot-script-tag-cd-attribute" value="defer" <?php checked( 'defer', $cv, true ); ?> />
1123
  defer
1124
  </label>
1125
  &nbsp; &nbsp;
1126
  <label>
1127
+ <input type="radio" name="cookiebot-script-tag-cd-attribute" value="custom" <?php checked( 'custom', $cv, true ); ?> />
1128
+ <i><?php esc_html_e( 'Choose per subsite', 'cookiebot' ); ?></i>
1129
  </label>
1130
  <p class="description">
1131
+ <b><?php esc_html_e( 'Setting will apply for all subsites. Subsites will not be able to override.', 'cookiebot' ); ?></b><br />
1132
+ <?php esc_html_e( 'Add async or defer attribute to Cookiebot script tag. Default: Choose per subsite', 'cookiebot' ); ?>
1133
  </p>
1134
  </td>
1135
  </tr>
1136
  <tr valign="top">
1137
+ <th scope="row"><?php esc_html_e( 'Auto-update Cookiebot', 'cookiebot' ); ?></th>
1138
  <td>
1139
+ <input type="checkbox" name="cookiebot-autoupdate" value="1" <?php checked( 1, get_site_option( 'cookiebot-autoupdate', false ), true ); ?> />
1140
  <p class="description">
1141
+ <?php esc_html_e( 'Automatic update your Cookiebot plugin when new releases becomes available.', 'cookiebot' ); ?>
1142
  </p>
1143
  </td>
1144
  </tr>
1145
  <tr valign="top" id="cookiebot-setting-hide-popup">
1146
+ <th scope="row"><?php esc_html_e( 'Hide Cookie Popup', 'cookiebot' ); ?></th>
1147
  <td>
1148
+ <input type="checkbox" name="cookiebot-nooutput" value="1" <?php checked( 1, get_site_option( 'cookiebot-nooutput', false ), true ); ?> />
1149
  <p class="description">
1150
+ <b><?php esc_html_e( 'Remove the cookie consent banner from all subsites. This cannot be changed by subsites. The <i>[cookie_declaration]</i> shortcode will still be available.', 'cookiebot' ); ?></b><br />
1151
+ <?php esc_html_e( 'If you are using Google Tag Manager (or equal), you need to add the Cookiebot script in your Tag Manager.', 'cookiebot' ); ?><br />
1152
+ <?php esc_html_e( '<a href="https://support.cookiebot.com/hc/en-us/articles/360003793854-Google-Tag-Manager-deployment" target="_blank">See a detailed guide here</a>', 'cookiebot' ); ?>
1153
  </p>
1154
  </td>
1155
  </tr>
1156
  <tr valign="top">
1157
+ <th scope="row"><?php esc_html_e( 'Hide Cookie Popup in WP Admin', 'cookiebot' ); ?></th>
1158
  <td>
1159
+ <input type="checkbox" name="cookiebot-nooutput-admin" value="1" <?php checked( 1, get_site_option( 'cookiebot-nooutput-admin', false ), true ); ?> />
1160
  <p class="description">
1161
+ <b><?php esc_html_e( 'Remove the cookie consent banner the WordPress Admin area for all subsites. This cannot be changed by subsites.', 'cookiebot' ); ?></b>
1162
  </p>
1163
  </td>
1164
  </tr>
1165
  </table>
1166
+ <?php submit_button(); ?>
1167
  </form>
1168
  </div>
1169
+ <?php
1170
+ }
1171
 
1172
 
1173
+ /**
1174
+ * Cookiebot_WP Cookiebot save network settings
1175
+ *
1176
+ * @version 2.2.0
1177
+ * @since 2.2.0
1178
+ */
1179
+ function network_settings_save() {
1180
+ check_admin_referer( 'cookiebot-network-settings' );
1181
+
1182
+ update_site_option( 'cookiebot-cbid', $_POST['cookiebot-cbid'] );
1183
+ update_site_option( 'cookiebot-script-tag-uc-attribute', $_POST['cookiebot-script-tag-uc-attribute'] );
1184
+ update_site_option( 'cookiebot-script-tag-cd-attribute', $_POST['cookiebot-script-tag-cd-attribute'] );
1185
+ update_site_option( 'cookiebot-autoupdate', $_POST['cookiebot-autoupdate'] );
1186
+ update_site_option( 'cookiebot-nooutput', $_POST['cookiebot-nooutput'] );
1187
+ update_site_option( 'cookiebot-nooutput-admin', $_POST['cookiebot-nooutput-admin'] );
1188
+ update_site_option( 'cookiebot-cookie-blocking-mode', $_POST['cookiebot-cookie-blocking-mode'] );
1189
+
1190
+ wp_redirect(
1191
+ add_query_arg(
1192
+ array(
1193
+ 'page' => 'cookiebot_network',
1194
+ 'updated' => true,
1195
+ ),
1196
+ network_admin_url( 'admin.php' )
1197
+ )
1198
+ );
1199
+ exit;
1200
+ }
1201
 
1202
+ /**
1203
+ * Cookiebot_WP Cookiebot support page
1204
+ *
1205
+ * @version 2.2.0
1206
+ * @since 2.0.0
1207
+ */
1208
+ function support_page() {
1209
+ ?>
1210
  <div class="wrap">
1211
+ <h1><?php esc_html_e( 'Support', 'cookiebot' ); ?></h1>
1212
+ <h2><?php esc_html_e( 'How to find my Cookiebot ID', 'cookiebot' ); ?></h2>
1213
  <p>
1214
  <ol>
1215
+ <li><?php esc_html_e( 'Log in to your <a href="https://www.cookiebot.com/goto/account" target="_blank">Cookiebot account</a>.', 'cookiebot' ); ?></li>
1216
+ <li><?php esc_html_e( 'Go to <b>Manage</b> > <b>Settings</b> and add setup your Cookiebot', 'cookiebot' ); ?></li>
1217
+ <li><?php esc_html_e( 'Go to the <b>"Your scripts"</b> tab', 'cookiebot' ); ?></li>
1218
+ <li><?php esc_html_e( 'Copy the value inside the data-cid parameter - eg.: abcdef12-3456-7890-abcd-ef1234567890', 'cookiebot' ); ?></li>
1219
+ <li><?php esc_html_e( 'Add <b>[cookie_declaration]</b> shortcode to a page to show the declation', 'cookiebot' ); ?></li>
1220
+ <li><?php esc_html_e( 'Remember to change your scripts as descripted below', 'cookiebot' ); ?></li>
1221
  </ol>
1222
  </p>
1223
+ <h2><?php esc_html_e( 'Add the Cookie Declaration to your website', 'cookiebot' ); ?></h2>
1224
  <p>
1225
+ <?php esc_html_e( 'Use the shortcode <b>[cookie_declaration]</b> to add the cookie declaration a page or post. The cookie declaration will always show the latest version from Cookiebot.', 'cookiebot' ); ?>
1226
  <br />
1227
+ <?php esc_html_e( 'If you need to force language of the cookie declaration, you can add the <i>lang</i> attribute. Eg. <b>[cookie_declaration lang="de"]</b>.', 'cookiebot' ); ?>
1228
  </p>
1229
  <p>
1230
+ <a href="https://www.youtube.com/watch?v=OCXz2bt4H_w" target="_blank" class="button"><?php esc_html_e( 'Watch video demonstration', 'cookiebot' ); ?></a>
1231
  </p>
1232
+ <h2><?php esc_html_e( 'Update your script tags', 'cookiebot' ); ?></h2>
1233
  <p>
1234
+ <?php esc_html_e( 'To enable prior consent, apply the attribute "data-cookieconsent" to cookie-setting script tags on your website. Set the comma-separated value to one or more of the cookie categories "preferences", "statistics" and "marketing" in accordance with the types of cookies being set by each script. Finally change the attribute "type" from "text/javascript" to "text/plain". Example on modifying an existing Google Analytics Universal script tag.', 'cookiebot' ); ?>
1235
  </p>
1236
  <code>
1237
  <?php
1238
+ echo htmlentities( '<script type="text/plain" data-cookieconsent="statistics">' ) . '<br />';
1239
+ echo htmlentities( "(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)})(window,document,'script','//www.google-analytics.com/analytics.js','ga');" ) . '<br />';
1240
+ echo htmlentities( "ga('create', 'UA-00000000-0', 'auto');" ) . '<br />';
1241
+ echo htmlentities( "ga('send', 'pageview');" ) . '<br />';
1242
+ echo htmlentities( '</script>' ) . '<br />';
1243
  ?>
1244
  </code>
1245
  <p>
1246
+ <a href="https://www.youtube.com/watch?v=MeHycvV2QCQ" target="_blank" class="button"><?php esc_html_e( 'Watch video demonstration', 'cookiebot' ); ?></a>
1247
  </p>
1248
 
1249
+ <h2><?php esc_html_e( 'Helper function to update your scripts', 'cookiebot' ); ?></h2>
1250
  <p>
1251
+ <?php esc_html_e( 'You are able to update your scripts yourself. However, Cookiebot also offers a small helper function that makes the work easier.', 'cookiebot' ); ?>
1252
  <br />
1253
+ <?php esc_html_e( 'Update your script tags this way:', 'cookiebot' ); ?>
1254
  </p>
1255
+ <?php
1256
+ printf(
1257
+ esc_html__( '%1$s to %2$s', 'cookiebot' ),
1258
+ '<code>' . htmlentities( '<script type="text/javascript">' ) . '</code>',
1259
+ '<code>' . htmlentities( '<script<?php echo cookiebot_assist(\'marketing\') ?>>' ) . '</code>'
1260
+ );
1261
+ ?>
1262
  </div>
1263
+ <?php
1264
+ }
1265
 
1266
  /**
1267
  * Cookiebot_WP Google Tag Manager page
1270
  * @since 3.8.1
1271
  */
1272
 
1273
+ function GTM_page() {
1274
+ ?>
1275
  <div class="wrap">
1276
+ <h1><?php esc_html_e( 'Google Tag Manager', 'cookiebot' ); ?></h1>
1277
 
1278
  <form method="post" action="options.php" style="display: grid; grid-template-columns: 35% 65%; grid-row-gap: 20px; width: 700px; align-items: center;">
1279
  <?php settings_fields( 'cookiebot-gtm' ); ?>
1280
  <?php do_settings_sections( 'cookiebot-gtm' ); ?>
1281
 
1282
+ <p><?php esc_html_e( 'Enable GTM', 'cookiebot' ); ?></p>
1283
  <div class="GTM_check">
1284
+ <input type="checkbox" name="cookiebot-gtm" id="cookiebot-gtm" value="1" <?php checked( 1, get_option( 'cookiebot-gtm' ), true ); ?> style="float: left; margin: 2px 4px 0 0">
1285
+ <p style="margin: 0; font-style: italic;"><?php esc_html_e( 'For more details about Cookiebot and Google Tag Manager click', 'cookiebot' ); ?><a target="_blank" href="https://www.cookiebot.com/en/google-tag-manager-and-gdpr-compliance-with-cookiebot/" style="margin: 0; font-style: italic;">&nbsp;<?php esc_html_e( 'here', 'cookiebot' ); ?></a></p>
1286
  </div>
1287
 
1288
+ <p><?php esc_html_e( 'GTM ID', 'cookiebot' ); ?></p>
1289
+ <input type="text" name="cookiebot-gtm-id" id="cookiebot-gtm-id" value="<?php echo get_option( 'cookiebot-gtm-id' ); ?>" style="height: 30px;">
1290
 
1291
+ <p><?php esc_html_e( 'DataLayer name', 'cookiebot' ); ?></p>
1292
  <div>
1293
+ <input type="text" name="cookiebot-data-layer" id="data_layer" placeholder="dataLayer" value="<?php echo get_option( 'cookiebot-data-layer' ); ?>" style="height: 30px;">
1294
+ <p style="margin: 0;"><?php esc_html_e( 'Optional, only change if necessary', 'cookiebot' ); ?></p>
1295
  </div>
1296
 
1297
+ <p><?php esc_html_e( 'Google Consent Mode', 'cookiebot' ); ?></p>
1298
  <div class="GTM_check">
1299
+ <input type="checkbox" name="cookiebot-gcm" id="gcm" value="1" <?php checked( 1, get_option( 'cookiebot-gcm' ), true ); ?> style="float: left; margin: 2px 4px 0 0">
1300
+ <p style="margin: 0; font-style: italic;"><?php esc_html_e( 'For more details about Cookiebot and Google Consent Mode click', 'cookiebot' ); ?><a target="_blank" href="https://support.cookiebot.com/hc/en-us/articles/360016047000-Cookiebot-and-Google-Consent-Mode" style="margin: 0; font-style: italic;">&nbsp;<?php esc_html_e( 'here', 'cookiebot' ); ?></a></p>
1301
  </div>
1302
  <input type="submit" value="Save" name="gtm_save" style="background-color: rgb(0, 124, 186); color: white; padding: 5px 10px; border: none; border-radius: 5px; justify-self: start;">
1303
  </form>
1304
  </div>
1305
+ <?php
1306
+ }
1307
 
1308
+ /**
1309
+ * Cookiebot_WP Cookiebot IAB page
1310
+ *
1311
+ * @version 2.0.0
1312
+ * @since 2.0.0
1313
+ */
1314
+ function iab_page() {
1315
+ ?>
1316
+ <div class="wrap">
1317
+ <h1><?php esc_html_e( 'IAB', 'cookiebot' ); ?></h1>
1318
 
1319
+ <p>
1320
+ <?php echo sprintf(
1321
+ esc_html__( 'For more details about Cookiebot\'s IAB integration, see %sarticle about cookiebot and the IAB consent framework%s', 'cookiebot' ),
1322
+ '<a href="https://support.cookiebot.com/hc/en-us/articles/360007652694-Cookiebot-and-the-IAB-Consent-Framework" target="_blank">',
1323
+ '</a>'
1324
+ ); ?>
1325
+ </p>
1326
 
1327
+ <form method="post" action="options.php">
1328
+ <?php settings_fields( 'cookiebot-iab' ); ?>
1329
+ <?php do_settings_sections( 'cookiebot-iab' ); ?>
1330
 
1331
+ <label><?php esc_html_e( 'Enable IAB integration', 'cookiebot' ); ?></label>
1332
+ <input type="checkbox" name="cookiebot-iab" value="1" <?php checked( 1, get_option( 'cookiebot-iab' ), true ); ?>>
1333
 
1334
+ <?php submit_button(); ?>
1335
+ </form>
1336
+ </div>
1337
+ <?php
1338
+ }
1339
 
1340
+ /**
1341
+ * Cookiebot_WP Cookiebot legislations page
1342
+ *
1343
+ * @version 3.6.6
1344
+ * @since 3.6.6
1345
+ */
1346
+ function legislations_page() {
1347
+ ?>
1348
+ <div class="wrap">
1349
+ <h1><?php esc_html_e( 'Legislations', 'cookiebot' ); ?></h1>
1350
 
1351
+ <p>
1352
+ <?php echo sprintf(
1353
+ esc_html__( 'For more details about Cookiebot\'s CCPA Legislation integration, see %sarticle about cookiebot and the CCPA compliance%s', 'cookiebot' ),
1354
+ '<a href="https://support.cookiebot.com/hc/en-us/articles/360010932419-Use-multiple-banners-on-the-same-website-support-both-CCPA-GDPR-compliance-" target="_blank">',
1355
+ '</a>'
1356
+ ); ?>
1357
+ </p>
1358
 
1359
+ <form method="post" action="options.php">
1360
  <?php settings_fields( 'cookiebot-legislations' ); ?>
1361
  <?php do_settings_sections( 'cookiebot-legislations' ); ?>
1362
 
1363
 
1364
+ <table class="form-table">
1365
+ <tbody>
1366
+ <tr valign="top">
1367
+ <th scope="row"><label><?php esc_html_e( 'Enable CCPA configuration for visitors from California', 'cookiebot' ); ?></label></th>
1368
+ <td>
1369
+ <input type="checkbox" name="cookiebot-ccpa" value="1" <?php checked( 1, get_option( 'cookiebot-ccpa' ), true ); ?>>
1370
+ </td>
1371
+ </tr>
1372
+ <tr>
1373
+ <th valign="top"><label><?php esc_html_e('Domain Group ID', 'cookiebot'); ?></label></th>
1374
+ <td>
1375
+ <input type="text" style="width: 300px;" name="cookiebot-ccpa-domain-group-id" value="<?php echo get_option( 'cookiebot-ccpa-domain-group-id' ); ?>">
1376
+ </td>
1377
+ </tr>
1378
+ </tbody>
1379
+ </table>
1380
 
1381
  <?php submit_button(); ?>
1382
+ </form>
1383
+ </div>
1384
+ <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1385
  }
1386
 
1387
+ /**
1388
+ * Cookiebot_WP Debug Page
1389
+ *
1390
+ * @version 3.9.
1391
+ * @since 3.6.0
1392
+ */
 
 
1393
 
1394
+ function debug_page() {
1395
+ global $wpdb;
1396
+
1397
+ include_once ABSPATH . 'wp-admin/includes/plugin.php';
1398
+ $plugins = get_plugins();
1399
+ $active_plugins = get_option( 'active_plugins' );
1400
+
1401
+ //$foo = new cookiebot_addons\lib\Settings_Service;
1402
+ //$addons = $foo->get_active_addons();
1403
+
1404
+ $debugStr = '';
1405
+ $debugStr .= '##### Debug Information for ' . get_site_url() . ' generated at ' . date( 'c' ) . " #####\n\n";
1406
+ $debugStr .= 'WordPress Version: ' . get_bloginfo( 'version' ) . "\n";
1407
+ $debugStr .= 'WordPress Language: ' . get_bloginfo( 'language' ) . "\n";
1408
+ $debugStr .= 'PHP Version: ' . phpversion() . "\n";
1409
+ $debugStr .= 'MySQL Version: ' . $wpdb->db_version() . "\n";
1410
+ $debugStr .= "\n--- Cookiebot Information ---\n";
1411
+ $debugStr .= 'Plugin Version: ' . $this->version . "\n";
1412
+ $debugStr .= 'Cookiebot ID: ' . $this->get_cbid() . "\n";
1413
+ $debugStr .= 'Blocking mode: ' . get_option( 'cookiebot-cookie-blocking-mode' ) . "\n";
1414
+ $debugStr .= 'Language: ' . get_option( 'cookiebot-language' ) . "\n";
1415
+ $debugStr .= 'IAB: ' . ( get_option( 'cookiebot-iab' ) == '1' ? 'Enabled' : 'Not enabled' ) . "\n";
1416
+ $debugStr .= 'CCPA banner for visitors from California: ' . ( get_option( 'cookiebot-ccpa' ) == '1' ? 'Enabled' : 'Not enabled' ) . "\n";
1417
+ $debugStr .= 'CCPA domain group id: ' . get_option( 'cookiebot-ccpa-domain-group-id' ) . "\n";
1418
+ $debugStr .= 'Add async/defer to banner tag: ' . ( get_option( 'cookiebot-script-tag-uc-attribute' ) != '' ? get_option( 'cookiebot-script-tag-uc-attribute' ) : 'None' ) . "\n";
1419
+ $debugStr .= 'Add async/defer to declaration tag: ' . ( get_option( 'cookiebot-script-tag-cd-attribute' ) != '' ? get_option( 'cookiebot-script-tag-cd-attribute' ) : 'None' ) . "\n";
1420
+ $debugStr .= 'Auto update: ' . ( get_option( 'cookiebot-autoupdate' ) == '1' ? 'Enabled' : 'Not enabled' ) . "\n";
1421
+ $debugStr .= 'Hide Cookie Popup: ' . ( get_option( 'cookiebot-nooutput' ) == '1' ? 'Yes' : 'No' ) . "\n";
1422
+ $debugStr .= 'Disable Cookiebot in WP Admin: ' . ( get_option( 'cookiebot-nooutput-admin' ) == '1' ? 'Yes' : 'No' ) . "\n";
1423
+ $debugStr .= 'Enable Cookiebot on front end while logged in: ' . ( get_option( 'cookiebot-output-logged-in' ) == '1' ? 'Yes' : 'No' ) . "\n";
1424
+ $debugStr .= 'Banner tag: ' . $this->add_js( false ) . "\n";
1425
+ $debugStr .= 'Declaration tag: ' . $this->show_declaration() . "\n";
1426
+
1427
+ if ( get_option( 'cookiebot-gtm' ) != false ) {
1428
+ $debugStr .= 'GTM tag: ' . $this->add_GTM( false ) . "\n";
1429
+ }
1430
 
1431
+ if ( get_option( 'cookiebot-gcm' ) != false ) {
1432
+ $debugStr .= 'GCM tag: ' . $this->add_GCM( false ) . "\n";
1433
  }
1434
 
1435
+ if ( $this->is_wp_consent_api_active() ) {
1436
+ $debugStr .= "\n--- WP Consent Level API Mapping ---\n";
1437
+ $debugStr .= 'F = Functional, N = Necessary, P = Preferences, M = Marketing, S = Statistics, SA = Statistics Anonymous' . "\n";
1438
+ $m = $this->get_wp_consent_api_mapping();
1439
+ foreach ( $m as $k => $v ) {
1440
+ $cb = array();
1441
+
1442
+ $debugStr .= strtoupper( str_replace( ';', ', ', $k ) ) . ' => ';
1443
 
1444
+ $debugStr .= 'F=1, ';
1445
+ $debugStr .= 'P=' . $v['preferences'] . ', ';
1446
+ $debugStr .= 'M=' . $v['marketing'] . ', ';
1447
+ $debugStr .= 'S=' . $v['statistics'] . ', ';
1448
+ $debugStr .= 'SA=' . $v['statistics-anonymous'] . "\n";
1449
+
1450
+ }
1451
+ }
1452
+
1453
+ if ( class_exists( 'cookiebot_addons\Cookiebot_Addons' ) ) {
1454
+ $ca = new cookiebot_addons\Cookiebot_Addons();
1455
+ $settingservice = $ca->container->get( 'Settings_Service_Interface' );
1456
+ $addons = $settingservice->get_active_addons();
1457
+ $debugStr .= "\n--- Activated Cookiebot Addons ---\n";
1458
+ foreach ( $addons as $addon ) {
1459
+ $debugStr .= $addon->get_addon_name() . ' (' . implode( ', ', $addon->get_cookie_types() ) . ")\n";
1460
+ }
1461
  }
 
1462
 
1463
+ $debugStr .= "\n--- Activated Plugins ---\n";
1464
+ foreach ( $active_plugins as $p ) {
1465
+ if ( $p != 'cookiebot/cookiebot.php' ) {
1466
+ $debugStr .= $plugins[ $p ]['Name'] . ' (Version: ' . $plugins[ $p ]['Version'] . ")\n";
1467
+ }
1468
  }
 
1469
 
1470
+ $debugStr .= "\n##### Debug Information END #####";
1471
 
1472
+ ?>
1473
  <div class="wrap">
1474
+ <h1><?php esc_html_e( 'Debug information', 'cookiebot' ); ?></h1>
1475
+ <p><?php esc_html_e( 'The information below is for debugging purpose. If you have any issues with your Cookiebot integration, the information below is usefull for a supporter to help you the best way.', 'cookiebot' ); ?></p>
1476
+ <p><button class="button button-primary" onclick="copyDebugInfo();"><?php esc_html_e( 'Copy debug information to clipboard', 'cookiebot' ); ?></button></p>
1477
  <textarea cols="100" rows="40" style="width:800px;max-width:100%;" id="cookiebot-debug-info" readonly><?php echo $debugStr; ?></textarea>
1478
  <script>
1479
  function copyDebugInfo() {
1484
  }
1485
  </script>
1486
  </div>
1487
+ <?php
1488
+ }
1489
 
1490
+ /**
1491
+ * Cookiebot_WP Add Cookiebot JS to <head>
1492
+ *
1493
+ * @version 3.9.0
1494
+ * @since 1.0.0
1495
+ */
1496
+ function add_js( $printTag = true ) {
1497
+ $cbid = $this->get_cbid();
1498
+ if ( ! empty( $cbid ) && ! defined( 'COOKIEBOT_DISABLE_ON_PAGE' ) ) {
1499
+ if ( is_multisite() && get_site_option( 'cookiebot-nooutput', false ) ) {
1500
+ return; //Is multisite - and disabled output is checked as network setting
1501
+ }
1502
 
1503
+ if ( get_option( 'cookiebot-nooutput', false ) ) {
1504
+ return; //Do not show JS - output disabled
1505
+ }
1506
 
1507
+ if ( $this->get_cookie_blocking_mode() == 'auto' && $this->can_current_user_edit_theme() && $printTag !== false && get_site_option( 'cookiebot-output-logged-in' ) == false ) {
1508
+ return;
1509
+ }
1510
 
1511
+ $lang = $this->get_language();
1512
+ if ( ! empty( $lang ) ) {
1513
+ $lang = ' data-culture="' . strtoupper( $lang ) . '"'; //Use data-culture to define language
1514
+ }
1515
 
1516
+ if ( ! is_multisite() || get_site_option( 'cookiebot-script-tag-uc-attribute', 'custom' ) == 'custom' ) {
1517
+ $tagAttr = get_option( 'cookiebot-script-tag-uc-attribute', 'async' );
1518
+ } else {
1519
+ $tagAttr = get_site_option( 'cookiebot-script-tag-uc-attribute' );
1520
+ }
 
1521
 
1522
+ if ( $this->get_cookie_blocking_mode() == 'auto' ) {
1523
+ $tagAttr = 'data-blockingmode="auto"';
1524
+ }
1525
 
1526
+ if ( get_option( 'cookiebot-gtm' ) != false ) {
1527
+ if ( empty( get_option( 'cookiebot-data-layer' ) ) ) {
1528
+ $data_layer = 'data-layer-name="dataLayer"';
1529
+ } else {
1530
+ $data_layer = 'data-layer-name="' . get_option( 'cookiebot-data-layer' ) . '"';
1531
+ }
1532
+ } else {
1533
+ $data_layer = '';
1534
+ }
1535
 
1536
+ $iab = ( get_option( 'cookiebot-iab' ) != false ) ? 'data-framework="IAB"' : '';
1537
 
1538
+ $ccpa = ( get_option( 'cookiebot-ccpa' ) != false ) ? 'data-georegions="{\'region\':\'US-06\',\'cbid\':\'' . get_option( 'cookiebot-ccpa-domain-group-id' ) . '\'}"' : '';
1539
 
1540
+ $tag = '<script id="Cookiebot" src="https://consent.cookiebot.com/uc.js" ' . $iab . ' ' . $ccpa . ' ' . $data_layer . ' data-cbid="' . $cbid . '"' . $lang . ' type="text/javascript" ' . $tagAttr . '></script>';
1541
+ if ( $printTag === false ) {
1542
+ return $tag;
1543
+ }
1544
+ echo $tag;
1545
  }
 
1546
  }
 
1547
 
1548
  /**
1549
  * Cookiebot_WP Add Google Tag Manager JS to <head>
1552
  * @since 3.8.1
1553
  */
1554
 
1555
+ function add_GTM( $printTag = true ) {
1556
 
1557
+ if ( get_option( 'cookiebot-gtm' ) != false ) {
1558
+
1559
+ if ( empty( get_option( 'cookiebot-data-layer' ) ) ) {
1560
+ $data_layer = 'dataLayer';
1561
+ } else {
1562
+ $data_layer = get_option( 'cookiebot-data-layer' );
1563
+ }
1564
 
1565
+ $GTM = '<script>';
1566
+ if ( get_option( 'cookiebot-iab' ) ) {
1567
+ $GTM .= 'window ["gtag_enable_tcf_support"] = true;';
1568
+ }
1569
+
1570
+ $GTM .= "(function (w, d, s, l, i) {
1571
  w[l] = w[l] || []; w[l].push({'gtm.start':new Date().getTime(), event: 'gtm.js'});
1572
  var f = d.getElementsByTagName(s)[0], j = d.createElement(s), dl = l != 'dataLayer' ? '&l=' + l : '';
1573
  j.async = true; j.src = 'https://www.googletagmanager.com/gtm.js?id=' + i + dl;
1574
  f.parentNode.insertBefore(j, f);})
1575
+ (window, document, 'script', '" . $data_layer . "', '" . get_option( 'cookiebot-gtm-id' ) . "');";
 
 
 
1576
 
1577
+ $GTM .= '</script>';
 
 
1578
 
1579
+ if ( $printTag === false ) {
1580
+ return $GTM;
1581
+ }
1582
+
1583
+ echo $GTM;
1584
+ }
1585
  }
 
1586
 
1587
  /**
1588
  * Cookiebot_WP Add Google Consent Mode JS to <head>
1591
  * @since 3.8.1
1592
  */
1593
 
1594
+ function add_GCM( $printTag = true ) {
1595
 
1596
+ if ( get_option( 'cookiebot-gcm' ) != false ) {
1597
 
1598
+ if ( empty( get_option( 'cookiebot-data-layer' ) ) ) {
1599
+ $data_layer = 'dataLayer';
1600
+ } else {
1601
+ $data_layer = get_option( 'cookiebot-data-layer' );
1602
+ }
1603
 
1604
+ $GCM = '<script data-cookieconsent="ignore">
1605
  (function(w,d,l){w[l]=w[l]||[];function gtag(){w[l].push(arguments)};
1606
  gtag("consent","default",{ad_storage:d,analytics_storage:d,wait_for_update:500,});
1607
  gtag("set", "ads_data_redaction", true);})(window,"denied","' . $data_layer . '");';
1608
 
1609
+ $GCM .= '</script>';
1610
 
1611
+ if ( $printTag === false ) {
1612
+ return $GCM;
1613
+ }
1614
 
1615
+ echo $GCM;
1616
+ }
1617
  }
 
1618
 
1619
+ /**
1620
+ * Returns true if an user is logged in and has an edit_themes capability
1621
+ *
1622
+ * @return bool
1623
+ *
1624
+ * @since 3.3.1
1625
+ * @version 3.4.1
1626
+ */
1627
+ function can_current_user_edit_theme() {
1628
+ if ( is_user_logged_in() ) {
1629
+ if ( current_user_can( 'edit_themes' ) ) {
1630
+ return true;
1631
+ }
1632
 
1633
+ if ( current_user_can( 'edit_pages' ) ) {
1634
+ return true;
1635
+ }
1636
 
1637
+ if ( current_user_can( 'edit_posts' ) ) {
1638
+ return true;
1639
+ }
1640
+ }
1641
 
1642
+ return false;
1643
+ }
1644
 
1645
+ /**
1646
+ * Cookiebot_WP Output declation shortcode [cookie_declaration]
1647
+ * Support attribute lang="LANGUAGE_CODE". Eg. lang="en".
1648
+ *
1649
+ * @version 2.2.0
1650
+ * @since 1.0.0
1651
+ */
1652
+ function show_declaration( $atts = array() ) {
1653
+ $cbid = $this->get_cbid();
1654
+ $lang = '';
1655
+ if ( ! empty( $cbid ) ) {
1656
+
1657
+ $atts = shortcode_atts(
1658
+ array(
1659
+ 'lang' => $this->get_language(),
1660
+ ),
1661
+ $atts,
1662
+ 'cookie_declaration'
1663
+ );
1664
+
1665
+ if ( ! empty( $atts['lang'] ) ) {
1666
+ $lang = ' data-culture="' . strtoupper( $atts['lang'] ) . '"'; //Use data-culture to define language
1667
+ }
1668
 
1669
+ if ( ! is_multisite() || get_site_option( 'cookiebot-script-tag-cd-attribute', 'custom' ) == 'custom' ) {
1670
+ $tagAttr = get_option( 'cookiebot-script-tag-cd-attribute', 'async' );
1671
+ } else {
1672
+ $tagAttr = get_site_option( 'cookiebot-script-tag-cd-attribute' );
1673
+ }
1674
 
1675
+ return '<script id="CookieDeclaration" src="https://consent.cookiebot.com/' . $cbid . '/cd.js"' . $lang . ' type="text/javascript" ' . $tagAttr . '></script>';
1676
+ } else {
1677
+ return esc_html__( 'Please add your Cookiebot ID to show Cookie Declarations', 'cookiebot' );
 
 
1678
  }
 
 
1679
  }
 
 
 
 
1680
 
1681
+ /**
1682
+ * Cookiebot_WP Get cookiebot cbid
1683
+ *
1684
+ * @version 2.2.0
1685
+ * @since 1.0.0
1686
+ */
1687
+ public static function get_cbid() {
1688
+ $cbid = get_option( 'cookiebot-cbid' );
1689
+ if ( is_multisite() && ( $network_cbid = get_site_option( 'cookiebot-cbid' ) ) ) {
1690
+ if ( empty( $cbid ) ) {
1691
+ return $network_cbid;
1692
+ }
1693
  }
1694
+ return $cbid;
1695
  }
 
 
1696
 
1697
+ /**
1698
+ * Cookiebot_WP Get cookie blocking mode (auto | manual)
1699
+ *
1700
+ * @version 2.2.0
1701
+ * @since 1.0.0
1702
+ */
1703
+ public static function get_cookie_blocking_mode() {
1704
+ $cbm = get_option( 'cookiebot-cookie-blocking-mode' );
1705
+ if ( is_multisite() && ( $network_cbm = get_site_option( 'cookiebot-cookie-blocking-mode' ) ) ) {
1706
+ if ( empty( $cbm ) ) {
1707
+ return $network_cbm;
1708
+ }
1709
  }
1710
+ if ( empty( $cbm ) ) {
1711
+ $cbm = 'manual'; }
1712
+ return $cbm;
1713
  }
 
 
 
1714
 
1715
 
1716
+ /**
1717
+ * Cookiebot_WP Check if Cookiebot is active in admin
1718
+ *
1719
+ * @version 3.1.0
1720
+ * @since 3.1.0
1721
+ */
1722
+ public static function cookiebot_disabled_in_admin() {
1723
+ if ( is_multisite() && get_site_option( 'cookiebot-nooutput-admin', false ) ) {
1724
  return true;
1725
+ } elseif ( get_option( 'cookiebot-nooutput-admin', false ) ) {
 
1726
  return true;
1727
  }
1728
  return false;
1729
+ }
1730
 
1731
+ /**
1732
+ * Cookiebot_WP Get the language code for Cookiebot
1733
+ *
1734
+ * @version 1.4.0
1735
+ * @since 1.4.0
1736
+ */
1737
+ function get_language( $onlyFromSetting = false ) {
1738
+ // Get language set in setting page - if empty use WP language info
1739
+ $lang = get_option( 'cookiebot-language' );
1740
+ if ( ! empty( $lang ) ) {
1741
+ if ( $lang != '_wp' ) {
1742
+ return $lang;
1743
+ }
1744
  }
 
1745
 
1746
+ if ( $onlyFromSetting ) {
1747
+ return $lang; //We want only to get if already set
1748
+ }
1749
 
1750
+ //Language not set - use WP language
1751
+ if ( $lang == '_wp' ) {
1752
+ $lang = get_bloginfo( 'language' ); //Gets language in en-US format
1753
+ if ( ! empty( $lang ) ) {
1754
+ list($lang) = explode( '-', $lang ); //Changes format from eg. en-US to en.
1755
+ }
1756
  }
1757
+ return $lang;
1758
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1759
 
1760
+ /**
1761
+ * Cookiebot_WP Adding Cookiebot domain(s) to exclude list for WP Rocket minification.
1762
+ *
1763
+ * @version 1.6.1
1764
+ * @since 1.6.1
1765
+ */
1766
+ function wp_rocket_exclude_external_js( $external_js_hosts ) {
1767
+ $external_js_hosts[] = 'consent.cookiebot.com'; // Add cookiebot domains
1768
+ $external_js_hosts[] = 'consentcdn.cookiebot.com';
1769
+ return $external_js_hosts;
1770
+ }
1771
 
1772
+ /**
1773
+ * Cookiebot_WP Adding Cookiebot domain(s) to exclude list for SGO minification.
1774
+ *
1775
+ * @version 3.6.5
1776
+ * @since 3.6.5
1777
+ */
1778
+ function sgo_exclude_external_js( $exclude_list ) {
1779
+ //Uses same format as WP Rocket - for now we just use WP Rocket function
1780
+ return wp_rocket_exclude_external_js( $exclude_list );
1781
  }
 
 
1782
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1783
 
1784
+ /**
1785
+ * Cookiebot_WP Check if WP Cookie Consent API is active
1786
+ *
1787
+ * @version 3.5.0
1788
+ * @since 3.5.0
1789
+ */
1790
+ public function is_wp_consent_api_active() {
1791
+ if ( class_exists( 'WP_CONSENT_API' ) ) {
1792
+ return true;
1793
+ }
1794
+ return false;
1795
+ }
1796
 
1797
+ /**
1798
+ * Cookiebot_WP Default consent level mappings
1799
+ *
1800
+ * @version 3.5.0
1801
+ * @since 3.5.0
1802
+ */
1803
+ public function get_default_wp_consent_api_mapping() {
1804
+ return array(
1805
+ 'n=1;p=1;s=1;m=1' =>
1806
+ array(
1807
+ 'preferences' => 1,
1808
+ 'statistics' => 1,
1809
+ 'statistics-anonymous' => 0,
1810
+ 'marketing' => 1,
1811
+ ),
1812
+ 'n=1;p=1;s=1;m=0' =>
1813
+ array(
1814
+ 'preferences' => 1,
1815
+ 'statistics' => 1,
1816
+ 'statistics-anonymous' => 1,
1817
+ 'marketing' => 0,
1818
+ ),
1819
+ 'n=1;p=1;s=0;m=1' =>
1820
+ array(
1821
+ 'preferences' => 1,
1822
+ 'statistics' => 0,
1823
+ 'statistics-anonymous' => 0,
1824
+ 'marketing' => 1,
1825
+ ),
1826
+ 'n=1;p=1;s=0;m=0' =>
1827
+ array(
1828
+ 'preferences' => 1,
1829
+ 'statistics' => 0,
1830
+ 'statistics-anonymous' => 0,
1831
+ 'marketing' => 0,
1832
+ ),
1833
+ 'n=1;p=0;s=1;m=1' =>
1834
+ array(
1835
+ 'preferences' => 0,
1836
+ 'statistics' => 1,
1837
+ 'statistics-anonymous' => 0,
1838
+ 'marketing' => 1,
1839
+ ),
1840
+ 'n=1;p=0;s=1;m=0' =>
1841
+ array(
1842
+ 'preferences' => 0,
1843
+ 'statistics' => 1,
1844
+ 'statistics-anonymous' => 0,
1845
+ 'marketing' => 0,
1846
+ ),
1847
+ 'n=1;p=0;s=0;m=1' =>
1848
+ array(
1849
+ 'preferences' => 0,
1850
+ 'statistics' => 0,
1851
+ 'statistics-anonymous' => 0,
1852
+ 'marketing' => 1,
1853
+ ),
1854
+ 'n=1;p=0;s=0;m=0' =>
1855
+ array(
1856
+ 'preferences' => 0,
1857
+ 'statistics' => 0,
1858
+ 'statistics-anonymous' => 0,
1859
+ 'marketing' => 0,
1860
+ ),
1861
+ );
1862
 
1863
+ }
1864
 
1865
+ /**
1866
+ * Cookiebot_WP Get the mapping between Consent Level API and Cookiebot
1867
+ * Returns array where key is the consent level api category and value
1868
+ * is the mapped Cookiebot category.
1869
+ *
1870
+ * @version 3.5.0
1871
+ * @since 3.5.0
1872
+ */
1873
+ public function get_wp_consent_api_mapping() {
1874
+ $mDefault = $this->get_default_wp_consent_api_mapping();
1875
+ $mapping = get_option( 'cookiebot-consent-mapping', $mDefault );
1876
+
1877
+ $mapping = ( '' === $mapping ) ? $mDefault : $mapping;
1878
+
1879
+ foreach ( $mDefault as $k => $v ) {
1880
+ if ( ! isset( $mapping[ $k ] ) ) {
1881
+ $mapping[ $k ] = $v;
1882
+ } else {
1883
+ foreach ( $v as $vck => $vcv ) {
1884
+ if ( ! isset( $mapping[ $k ][ $vck ] ) ) {
1885
+ $mapping[ $k ][ $vck ] = $vcv;
1886
+ }
1887
  }
1888
  }
1889
  }
1890
+ return $mapping;
1891
  }
 
 
1892
 
1893
+ /**
1894
+ * Cookiebot_WP Enqueue JS for integration with WP Consent Level API
1895
+ *
1896
+ * @version 3.5.0
1897
+ * @since 3.5.0
1898
+ */
1899
+ function cookiebot_enqueue_consent_api_scripts() {
1900
+ wp_register_script( 'cookiebot-wp-consent-level-api-integration', plugins_url( 'cookiebot/js/cookiebot-wp-consent-level-api-integration.js', 'cookiebot' ) );
1901
+ wp_enqueue_script( 'cookiebot-wp-consent-level-api-integration' );
1902
+ wp_localize_script( 'cookiebot-wp-consent-level-api-integration', 'cookiebot_category_mapping', $this->get_wp_consent_api_mapping() );
1903
+ }
1904
 
1905
 
1906
+ /**
1907
+ * Display admin notice for recommending cookiebot
1908
+ *
1909
+ * @version 2.0.5
1910
+ * @since 2.0.5
1911
+ */
1912
+ function cookiebot_admin_notices() {
1913
+ if ( ! $this->cookiebot_valid_admin_recommendation() ) {
1914
+ return false;
1915
+ }
1916
+ $two_week_review_ignore = add_query_arg( array( 'cookiebot_admin_notice' => 'hide' ) );
1917
+ $two_week_review_temp = add_query_arg( array( 'cookiebot_admin_notice' => 'two_week' ) );
1918
+
1919
+ $notices = array(
1920
+ 'title' => esc_html__( 'Leave A Review?', 'cookiebot' ),
1921
+ 'msg' => esc_html__( 'We hope you enjoy using WordPress Cookiebot! Would you consider leaving us a review on WordPress.org?', 'cookiebot' ),
1922
+ 'link' => '<li><span class="dashicons dashicons-external"></span><a href="https://wordpress.org/support/plugin/cookiebot/reviews?filter=5&rate=5#new-post" target="_blank">' . esc_html__( 'Sure! I\'d love to!', 'cookiebot' ) . '</a></li>
1923
+ <li><span class="dashicons dashicons-smiley"></span><a href="' . $two_week_review_ignore . '"> ' . esc_html__( 'I\'ve already left a review', 'cookiebot' ) . '</a></li>
1924
+ <li><span class="dashicons dashicons-calendar-alt"></span><a href="' . $two_week_review_temp . '">' . esc_html__( 'Maybe Later', 'cookiebot' ) . '</a></li>
1925
+ <li><span class="dashicons dashicons-dismiss"></span><a href="' . $two_week_review_ignore . '">' . esc_html__( 'Never show again', 'cookiebot' ) . '</a></li>',
1926
+ 'later_link' => $two_week_review_temp,
1927
+ 'int' => 14,
1928
+ );
1929
+
1930
+ echo '<div class="update-nag cookiebot-admin-notice">
1931
  <div class="cookiebot-notice-logo"></div>
1932
  <p class="cookiebot-notice-title">' . $notices['title'] . '</p>
1933
  <p class="cookiebot-notice-body">' . $notices['msg'] . '</p>
1935
  <a href="' . $notices['later_link'] . '" class="dashicons dashicons-dismiss"></a>
1936
  </div>';
1937
 
1938
+ wp_enqueue_style( 'cookiebot-admin-notices', plugins_url( 'css/notice.css', __FILE__ ), array(), '2.0.4' );
1939
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
1940
 
 
1941
 
1942
+ /**
1943
+ * Validate if the last user action is valid for plugin recommendation
1944
+ *
1945
+ * @return bool
1946
+ *
1947
+ * @version 2.0.5
1948
+ * @since 2.0.5
1949
+ */
1950
+ function cookiebot_valid_admin_recommendation() {
1951
+ //Default - the recommendation is allowed to be visible
1952
+ $return = true;
1953
+
1954
+ $option = get_option( 'cookiebot_notice_recommend' );
1955
+
1956
+ if ( $option != false ) {
1957
+ //Never show again is clicked
1958
+ if ( $option == 'hide' ) {
1959
+ $return = false;
1960
+ } elseif ( is_numeric( $option ) && strtotime( 'now' ) < $option ) {
1961
+ //Show me after 2 weeks is clicked and the time is not valid yet
1962
+ $return = false;
1963
+ }
1964
  }
1965
+ return $return;
1966
  }
 
 
1967
 
1968
+ /**
1969
+ * Save the user action on cookiebot recommendation link
1970
+ *
1971
+ * @version 2.0.5
1972
+ * @since 2.0.5
1973
+ */
1974
+ function save_notice_link() {
1975
+ if ( isset( $_GET['cookiebot_admin_notice'] ) ) {
1976
+ if ( $_GET['cookiebot_admin_notice'] == 'hide' ) {
1977
+ update_option( 'cookiebot_notice_recommend', 'hide' );
1978
+ } else {
1979
+ update_option( 'cookiebot_notice_recommend', strtotime( '+2 weeks' ) );
1980
+ }
1981
  }
1982
  }
 
1983
 
1984
 
1985
 
1986
 
1987
+ /**
1988
+ * Cookiebot_WP Fix plugin conflicts related to Cookiebot
1989
+ *
1990
+ * @version 3.2.0
1991
+ * @since 3.3.0
1992
+ */
1993
+ function cookiebot_fix_plugin_conflicts() {
1994
+ //Fix for Divi Page Builder
1995
+ //Disabled - using another method now (can_current_user_edit_theme())
1996
+ //add_action( 'wp', array( $this, '_cookiebot_plugin_conflict_divi' ), 100 );
1997
+
1998
+ //Fix for Elementor and WPBakery Page Builder Builder
1999
+ //Disabled - using another method now (can_current_user_edit_theme())
2000
+ //add_filter( 'script_loader_tag', array( $this, '_cookiebot_plugin_conflict_scripttags' ), 10, 2 );
2001
+ }
2002
 
2003
+ /**
2004
+ * Cookiebot_WP Fix Divi builder conflict when blocking mode is in auto.
2005
+ *
2006
+ * @version 3.2.0
2007
+ * @since 3.2.0
2008
+ */
2009
+ function _cookiebot_plugin_conflict_divi() {
2010
+ if ( defined( 'ET_FB_ENABLED' ) ) {
2011
+ if ( ET_FB_ENABLED &&
2012
  $this->cookiebot_disabled_in_admin() &&
2013
  $this->get_cookie_blocking_mode() == 'auto' ) {
2014
 
2015
+ define( 'COOKIEBOT_DISABLE_ON_PAGE', true ); //Disable Cookiebot on the current page
2016
 
2017
+ }
2018
  }
2019
  }
 
2020
 
2021
+ /**
2022
+ * Cookiebot_WP Fix plugin conflicts with page builders - whitelist JS files in automode
2023
+ *
2024
+ * @version 3.2.0
2025
+ * @since 3.3.0
2026
+ */
2027
+ function _cookiebot_plugin_conflict_scripttags( $tag, $handle ) {
2028
+
2029
+ //Check if Elementor Page Builder active
2030
+ if ( defined( 'ELEMENTOR_VERSION' ) ) {
2031
+ if ( in_array(
2032
+ $handle,
2033
+ array(
2034
+ 'jquery-core',
2035
+ 'elementor-frontend-modules',
2036
+ 'elementor-frontend',
2037
+ 'wp-tinymce',
2038
+ 'underscore',
2039
+ 'backbone',
2040
+ 'backbone-marionette',
2041
+ 'backbone-radio',
2042
+ 'elementor-common-modules',
2043
+ 'elementor-dialog',
2044
+ 'elementor-common',
2045
+ )
2046
+ ) ) {
2047
+ $tag = str_replace( '<script ', '<script data-cookieconsent="ignore" ', $tag );
2048
+ }
2049
  }
 
2050
 
2051
+ //Check if WPBakery Page Builder active
2052
+ if ( defined( 'WPB_VC_VERSION' ) ) {
2053
+ if ( in_array(
2054
+ $handle,
2055
+ array(
2056
+ 'jquery-core',
2057
+ 'jquery-ui-core',
2058
+ 'jquery-ui-sortable',
2059
+ 'jquery-ui-mouse',
2060
+ 'jquery-ui-widget',
2061
+ 'vc_editors-templates-preview-js',
2062
+ 'vc-frontend-editor-min-js',
2063
+ 'vc_inline_iframe_js',
2064
+ 'wpb_composer_front_js',
2065
+ )
2066
+ ) ) {
2067
+ $tag = str_replace( '<script ', '<script data-cookieconsent="ignore" ', $tag );
2068
+ }
2069
  }
2070
+
2071
+ return $tag;
2072
  }
2073
 
 
2074
  }
 
 
2075
  endif;
2076
 
2077
 
2082
  * @since 1.0
2083
  * @return string
2084
  */
2085
+ function cookiebot_assist( $type = 'statistics' ) {
2086
  //change to array
2087
+ if ( ! is_array( $type ) ) {
2088
+ $type = array( $type ); }
2089
 
2090
+ foreach ( $type as $tk => $tv ) {
2091
+ if ( ! in_array( $tv, array( 'marketing', 'statistics', 'preferences' ) ) ) {
2092
+ unset( $type[ $tk ] );
2093
  }
2094
  }
2095
+ if ( sizeof( $type ) > 0 ) {
2096
+ return ' type="text/plain" data-cookieconsent="' . implode( ',', $type ) . '"';
2097
  }
2098
  return '';
2099
  }
2109
  */
2110
  function cookiebot_active() {
2111
  $cbid = Cookiebot_WP::get_cbid();
2112
+ if ( ! empty( $cbid ) ) {
2113
  return true;
2114
  }
2115
  return false;
2116
  }
2117
 
2118
 
2119
+ if ( ! function_exists( 'cookiebot' ) ) {
2120
  /**
2121
  * Returns the main instance of Cookiebot_WO to prevent the need to use globals.
2122
  *
readme.txt CHANGED
@@ -2,8 +2,8 @@
2
  * Contributors: cookiebot,phpgeekdk,aytac
3
  * Tags: cookie, compliance, eu, gdpr, europe, cookie consent, consent, ccpa
4
  * Requires at least: 4.4
5
- * Tested up to: 5.6
6
- * Stable tag: 3.9.0
7
  * Requires PHP: 5.6
8
  * License: GPLv2 or later
9
 
@@ -197,6 +197,18 @@ You are able to define the mapping between Cookiebot and the WP Consent API in t
197
 
198
  ## Changelog ##
199
 
 
 
 
 
 
 
 
 
 
 
 
 
200
  ### 3.9.0 - 2020-10-20 ###
201
  * Added support for Google Tag Manager and Google Consent Mode
202
  * Added gtag TCF support
2
  * Contributors: cookiebot,phpgeekdk,aytac
3
  * Tags: cookie, compliance, eu, gdpr, europe, cookie consent, consent, ccpa
4
  * Requires at least: 4.4
5
+ * Tested up to: 5.7.0
6
+ * Stable tag: 3.10.0
7
  * Requires PHP: 5.6
8
  * License: GPLv2 or later
9
 
197
 
198
  ## Changelog ##
199
 
200
+ ### 3.10.0 - 2021-03-22 ###
201
+ * Added support for translating the settings pages
202
+ * Added support for Enfold theme
203
+ * Added support for ExactMetrics
204
+ * Added support for Gutenberg Embed blocks
205
+ * Added support for newer version of Custom Facebook Feed
206
+ * Added support for newer version of Add To Any
207
+ * Fixed prior consent language bug
208
+ * Fixed embedding twitter
209
+ * Fixed multisite settings
210
+ * Prefixed the composer dependencies with Mozart
211
+
212
  ### 3.9.0 - 2020-10-20 ###
213
  * Added support for Google Tag Manager and Google Consent Mode
214
  * Added gtag TCF support
widgets/cookiebot-declaration-widget.php CHANGED
@@ -7,7 +7,7 @@ class Cookiebot_Declaration_Widget extends WP_Widget {
7
  public function __construct() {
8
  parent::__construct(
9
  'cookiebot_declaration_widget',
10
- __( 'Cookiebot - Cookie Declaration', 'cookiebot' ),
11
  array(
12
  'customize_selective_refresh' => true,
13
  )
@@ -21,13 +21,13 @@ class Cookiebot_Declaration_Widget extends WP_Widget {
21
  $title = (isset($title) ? $title : '');
22
  ?>
23
  <p>
24
- <label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"><?php _e( 'Title', 'Cookiebot' ); ?></label>
25
  <input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>" />
26
  </p>
27
  <p>
28
- <label for="<?php echo $this->get_field_id( 'lang' ); ?>"><?php _e( 'Language', 'cookiebot' ); ?></label>
29
  <select name="<?php echo $this->get_field_name( 'lang' ); ?>" id="<?php echo $this->get_field_id( 'lang' ); ?>" class="widefat">
30
- <option value=""><?php echo __('- Default -', 'cookiebot'); ?></option>
31
  <?php
32
  $options = Cookiebot_WP::get_supported_languages();
33
  foreach ( $options as $key => $name ) {
7
  public function __construct() {
8
  parent::__construct(
9
  'cookiebot_declaration_widget',
10
+ esc_html__( 'Cookiebot - Cookie Declaration', 'cookiebot' ),
11
  array(
12
  'customize_selective_refresh' => true,
13
  )
21
  $title = (isset($title) ? $title : '');
22
  ?>
23
  <p>
24
+ <label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"><?php esc_html_e( 'Title', 'Cookiebot' ); ?></label>
25
  <input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>" />
26
  </p>
27
  <p>
28
+ <label for="<?php echo $this->get_field_id( 'lang' ); ?>"><?php esc_html_e( 'Language', 'cookiebot' ); ?></label>
29
  <select name="<?php echo $this->get_field_name( 'lang' ); ?>" id="<?php echo $this->get_field_id( 'lang' ); ?>" class="widefat">
30
+ <option value=""><?php echo esc_html__('- Default -', 'cookiebot'); ?></option>
31
  <?php
32
  $options = Cookiebot_WP::get_supported_languages();
33
  foreach ( $options as $key => $name ) {