Cookiebot | GDPR Compliant Cookie Consent and Notice - Version 2.3.0

Version Description

Download this release

Release Info

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

Version 2.3.0

Files changed (253) hide show
  1. CookiebotAPI.md +93 -0
  2. LICENSE.txt +339 -0
  3. README.md +99 -0
  4. addons/.travis.yml +22 -0
  5. addons/addons.json +71 -0
  6. addons/bin/install-wp-tests.sh +126 -0
  7. addons/composer.json +5 -0
  8. addons/composer.lock +232 -0
  9. addons/config/script-config.php +78 -0
  10. addons/config/settings-config.php +331 -0
  11. addons/controller/addons/add-to-any/add-to-any.php +367 -0
  12. addons/controller/addons/caos-host-analyticsjs-local-save-ga-local/caos-host-analyticsjs-local-save-ga-local.php +37 -0
  13. addons/controller/addons/caos-host-analyticsjs-local/caos-host-analyticsjs-local.php +353 -0
  14. addons/controller/addons/cookiebot-addons-interface.php +201 -0
  15. addons/controller/addons/custom-facebook-feed-pro/custom-facebook-feed-pro.php +331 -0
  16. addons/controller/addons/custom-facebook-feed/custom-facebook-feed.php +331 -0
  17. addons/controller/addons/embed-autocorrect/embed-autocorrect.php +530 -0
  18. addons/controller/addons/facebook-for-woocommerce/facebook-for-woocommerce.php +373 -0
  19. addons/controller/addons/ga-google-analytics/ga-google-analytics.php +337 -0
  20. addons/controller/addons/gadwp/gadwp.php +352 -0
  21. addons/controller/addons/google-analyticator/google-analyticator.php +349 -0
  22. addons/controller/addons/google-analytics-plus/google-analytics-plus.php +334 -0
  23. addons/controller/addons/google-analytics/google-analytics.php +338 -0
  24. addons/controller/addons/hubspot-leadin/hubspot-leadin.php +319 -0
  25. addons/controller/addons/hubspot-tracking-code/hubspot-tracking-code.php +332 -0
  26. addons/controller/addons/instagram-feed/instagram-feed.php +317 -0
  27. addons/controller/addons/jetpack/jetpack.php +416 -0
  28. addons/controller/addons/jetpack/visitor-cookies.php +302 -0
  29. addons/controller/addons/jetpack/widget/facebook-widget.php +246 -0
  30. addons/controller/addons/jetpack/widget/goodreads-widget.php +301 -0
  31. addons/controller/addons/jetpack/widget/google-maps-widget.php +302 -0
  32. addons/controller/addons/jetpack/widget/googleplus-badge-widget.php +239 -0
  33. addons/controller/addons/jetpack/widget/internet-defense-league-widget.php +254 -0
  34. addons/controller/addons/jetpack/widget/jetpack-widget-interface.php +22 -0
  35. addons/controller/addons/jetpack/widget/twitter-timeline-widget.php +233 -0
  36. addons/controller/addons/ninja-forms/ninja-forms.php +334 -0
  37. addons/controller/addons/optinmonster/optinmonster.php +313 -0
  38. addons/controller/addons/pixel-caffeine/pixel-caffeine.php +339 -0
  39. addons/controller/addons/wd-google-analytics/wd-google-analytics.php +333 -0
  40. addons/controller/addons/wp-analytify/wp-analytify.php +315 -0
  41. addons/controller/addons/wp-piwik/wp-piwik.php +317 -0
  42. addons/controller/addons/wpforms/cookie-after-consent.js +51 -0
  43. addons/controller/addons/wpforms/wpforms.php +395 -0
  44. addons/controller/plugin-controller.php +88 -0
  45. addons/cookiebot-addons-init.php +208 -0
  46. addons/js/jquery.tipTip.js +193 -0
  47. addons/js/settings.js +145 -0
  48. addons/lib/autoloader.php +54 -0
  49. addons/lib/buffer/buffer-output-interface.php +32 -0
  50. addons/lib/buffer/buffer-output-tag-interface.php +43 -0
  51. addons/lib/buffer/buffer-output-tag.php +135 -0
  52. addons/lib/buffer/buffer-output.php +61 -0
  53. addons/lib/cookie-consent-interface.php +53 -0
  54. addons/lib/cookie-consent.php +144 -0
  55. addons/lib/helper.php +260 -0
  56. addons/lib/ioc/autoload.php +7 -0
  57. addons/lib/ioc/composer/ClassLoader.php +445 -0
  58. addons/lib/ioc/composer/LICENSE +21 -0
  59. addons/lib/ioc/composer/autoload_classmap.php +9 -0
  60. addons/lib/ioc/composer/autoload_files.php +10 -0
  61. addons/lib/ioc/composer/autoload_namespaces.php +9 -0
  62. addons/lib/ioc/composer/autoload_psr4.php +14 -0
  63. addons/lib/ioc/composer/autoload_real.php +70 -0
  64. addons/lib/ioc/composer/autoload_static.php +61 -0
  65. addons/lib/ioc/composer/installed.json +226 -0
  66. addons/lib/ioc/container-interop/container-interop/.gitignore +3 -0
  67. addons/lib/ioc/container-interop/container-interop/LICENSE +20 -0
  68. addons/lib/ioc/container-interop/container-interop/README.md +148 -0
  69. addons/lib/ioc/container-interop/container-interop/composer.json +15 -0
  70. addons/lib/ioc/container-interop/container-interop/docs/ContainerInterface-meta.md +114 -0
  71. addons/lib/ioc/container-interop/container-interop/docs/ContainerInterface.md +158 -0
  72. addons/lib/ioc/container-interop/container-interop/docs/Delegate-lookup-meta.md +259 -0
  73. addons/lib/ioc/container-interop/container-interop/docs/Delegate-lookup.md +60 -0
  74. addons/lib/ioc/container-interop/container-interop/docs/images/interoperating_containers.png +0 -0
  75. addons/lib/ioc/container-interop/container-interop/docs/images/priority.png +0 -0
  76. addons/lib/ioc/container-interop/container-interop/docs/images/side_by_side_containers.png +0 -0
  77. addons/lib/ioc/container-interop/container-interop/src/Interop/Container/ContainerInterface.php +15 -0
  78. addons/lib/ioc/container-interop/container-interop/src/Interop/Container/Exception/ContainerException.php +15 -0
  79. addons/lib/ioc/container-interop/container-interop/src/Interop/Container/Exception/NotFoundException.php +15 -0
  80. addons/lib/ioc/php-di/invoker/CONTRIBUTING.md +15 -0
  81. addons/lib/ioc/php-di/invoker/LICENSE +21 -0
  82. addons/lib/ioc/php-di/invoker/README.md +234 -0
  83. addons/lib/ioc/php-di/invoker/composer.json +25 -0
  84. addons/lib/ioc/php-di/invoker/doc/parameter-resolvers.md +109 -0
  85. addons/lib/ioc/php-di/invoker/src/CallableResolver.php +127 -0
  86. addons/lib/ioc/php-di/invoker/src/Exception/InvocationException.php +12 -0
  87. addons/lib/ioc/php-di/invoker/src/Exception/NotCallableException.php +35 -0
  88. addons/lib/ioc/php-di/invoker/src/Exception/NotEnoughParametersException.php +12 -0
  89. addons/lib/ioc/php-di/invoker/src/Invoker.php +122 -0
  90. addons/lib/ioc/php-di/invoker/src/InvokerInterface.php +29 -0
  91. addons/lib/ioc/php-di/invoker/src/ParameterResolver/AssociativeArrayResolver.php +39 -0
  92. addons/lib/ioc/php-di/invoker/src/ParameterResolver/Container/ParameterNameContainerResolver.php +51 -0
  93. addons/lib/ioc/php-di/invoker/src/ParameterResolver/Container/TypeHintContainerResolver.php +51 -0
  94. addons/lib/ioc/php-di/invoker/src/ParameterResolver/DefaultValueResolver.php +40 -0
  95. addons/lib/ioc/php-di/invoker/src/ParameterResolver/NumericArrayResolver.php +39 -0
  96. addons/lib/ioc/php-di/invoker/src/ParameterResolver/ParameterResolver.php +33 -0
  97. addons/lib/ioc/php-di/invoker/src/ParameterResolver/ResolverChain.php +69 -0
  98. addons/lib/ioc/php-di/invoker/src/ParameterResolver/TypeHintResolver.php +39 -0
  99. addons/lib/ioc/php-di/invoker/src/Reflection/CallableReflection.php +61 -0
  100. addons/lib/ioc/php-di/php-di/.coveralls.yml +2 -0
  101. addons/lib/ioc/php-di/php-di/.gitattributes +8 -0
  102. addons/lib/ioc/php-di/php-di/.gitignore +9 -0
  103. addons/lib/ioc/php-di/php-di/.travis.yml +26 -0
  104. addons/lib/ioc/php-di/php-di/404.md +3 -0
  105. addons/lib/ioc/php-di/php-di/CONTRIBUTING.md +52 -0
  106. addons/lib/ioc/php-di/php-di/LICENSE +18 -0
  107. addons/lib/ioc/php-di/php-di/README.md +23 -0
  108. addons/lib/ioc/php-di/php-di/change-log.md +280 -0
  109. addons/lib/ioc/php-di/php-di/composer.json +40 -0
  110. addons/lib/ioc/php-di/php-di/couscous.yml +107 -0
  111. addons/lib/ioc/php-di/php-di/phpunit.xml.dist +30 -0
  112. addons/lib/ioc/php-di/php-di/src/DI/Annotation/Inject.php +95 -0
  113. addons/lib/ioc/php-di/php-di/src/DI/Annotation/Injectable.php +74 -0
  114. addons/lib/ioc/php-di/php-di/src/DI/Container.php +340 -0
  115. addons/lib/ioc/php-di/php-di/src/DI/ContainerBuilder.php +258 -0
  116. addons/lib/ioc/php-di/php-di/src/DI/Debug.php +39 -0
  117. addons/lib/ioc/php-di/php-di/src/DI/Definition/AbstractFunctionCallDefinition.php +82 -0
  118. addons/lib/ioc/php-di/php-di/src/DI/Definition/AliasDefinition.php +66 -0
  119. addons/lib/ioc/php-di/php-di/src/DI/Definition/ArrayDefinition.php +66 -0
  120. addons/lib/ioc/php-di/php-di/src/DI/Definition/ArrayDefinitionExtension.php +61 -0
  121. addons/lib/ioc/php-di/php-di/src/DI/Definition/CacheableDefinition.php +19 -0
  122. addons/lib/ioc/php-di/php-di/src/DI/Definition/DecoratorDefinition.php +48 -0
  123. addons/lib/ioc/php-di/php-di/src/DI/Definition/Definition.php +32 -0
  124. addons/lib/ioc/php-di/php-di/src/DI/Definition/Dumper/AliasDefinitionDumper.php +48 -0
  125. addons/lib/ioc/php-di/php-di/src/DI/Definition/Dumper/ArrayDefinitionDumper.php +65 -0
  126. addons/lib/ioc/php-di/php-di/src/DI/Definition/Dumper/DecoratorDefinitionDumper.php +37 -0
  127. addons/lib/ioc/php-di/php-di/src/DI/Definition/Dumper/DefinitionDumper.php +30 -0
  128. addons/lib/ioc/php-di/php-di/src/DI/Definition/Dumper/DefinitionDumperDispatcher.php +68 -0
  129. addons/lib/ioc/php-di/php-di/src/DI/Definition/Dumper/EnvironmentVariableDefinitionDumper.php +63 -0
  130. addons/lib/ioc/php-di/php-di/src/DI/Definition/Dumper/FactoryDefinitionDumper.php +37 -0
  131. addons/lib/ioc/php-di/php-di/src/DI/Definition/Dumper/ObjectDefinitionDumper.php +156 -0
  132. addons/lib/ioc/php-di/php-di/src/DI/Definition/Dumper/StringDefinitionDumper.php +37 -0
  133. addons/lib/ioc/php-di/php-di/src/DI/Definition/Dumper/ValueDefinitionDumper.php +44 -0
  134. addons/lib/ioc/php-di/php-di/src/DI/Definition/EntryReference.php +52 -0
  135. addons/lib/ioc/php-di/php-di/src/DI/Definition/EnvironmentVariableDefinition.php +116 -0
  136. addons/lib/ioc/php-di/php-di/src/DI/Definition/Exception/AnnotationException.php +19 -0
  137. addons/lib/ioc/php-di/php-di/src/DI/Definition/Exception/DefinitionException.php +30 -0
  138. addons/lib/ioc/php-di/php-di/src/DI/Definition/FactoryDefinition.php +75 -0
  139. addons/lib/ioc/php-di/php-di/src/DI/Definition/HasSubDefinition.php +28 -0
  140. addons/lib/ioc/php-di/php-di/src/DI/Definition/Helper/ArrayDefinitionExtensionHelper.php +46 -0
  141. addons/lib/ioc/php-di/php-di/src/DI/Definition/Helper/DefinitionHelper.php +24 -0
  142. addons/lib/ioc/php-di/php-di/src/DI/Definition/Helper/EnvironmentVariableDefinitionHelper.php +64 -0
  143. addons/lib/ioc/php-di/php-di/src/DI/Definition/Helper/FactoryDefinitionHelper.php +72 -0
  144. addons/lib/ioc/php-di/php-di/src/DI/Definition/Helper/ObjectDefinitionHelper.php +273 -0
  145. addons/lib/ioc/php-di/php-di/src/DI/Definition/Helper/StringDefinitionHelper.php +39 -0
  146. addons/lib/ioc/php-di/php-di/src/DI/Definition/Helper/ValueDefinitionHelper.php +42 -0
  147. addons/lib/ioc/php-di/php-di/src/DI/Definition/InstanceDefinition.php +76 -0
  148. addons/lib/ioc/php-di/php-di/src/DI/Definition/ObjectDefinition.php +294 -0
  149. addons/lib/ioc/php-di/php-di/src/DI/Definition/ObjectDefinition/MethodInjection.php +54 -0
  150. addons/lib/ioc/php-di/php-di/src/DI/Definition/ObjectDefinition/PropertyInjection.php +56 -0
  151. addons/lib/ioc/php-di/php-di/src/DI/Definition/Resolver/AliasResolver.php +77 -0
  152. addons/lib/ioc/php-di/php-di/src/DI/Definition/Resolver/ArrayResolver.php +105 -0
  153. addons/lib/ioc/php-di/php-di/src/DI/Definition/Resolver/DecoratorResolver.php +107 -0
  154. addons/lib/ioc/php-di/php-di/src/DI/Definition/Resolver/DefinitionResolver.php +44 -0
  155. addons/lib/ioc/php-di/php-di/src/DI/Definition/Resolver/EnvironmentVariableResolver.php +94 -0
  156. addons/lib/ioc/php-di/php-di/src/DI/Definition/Resolver/FactoryResolver.php +85 -0
  157. addons/lib/ioc/php-di/php-di/src/DI/Definition/Resolver/InstanceInjector.php +67 -0
  158. addons/lib/ioc/php-di/php-di/src/DI/Definition/Resolver/ObjectCreator.php +266 -0
  159. addons/lib/ioc/php-di/php-di/src/DI/Definition/Resolver/ParameterResolver.php +138 -0
  160. addons/lib/ioc/php-di/php-di/src/DI/Definition/Resolver/ResolverDispatcher.php +141 -0
  161. addons/lib/ioc/php-di/php-di/src/DI/Definition/Resolver/StringResolver.php +95 -0
  162. addons/lib/ioc/php-di/php-di/src/DI/Definition/Resolver/ValueResolver.php +58 -0
  163. addons/lib/ioc/php-di/php-di/src/DI/Definition/Source/AnnotationReader.php +298 -0
  164. addons/lib/ioc/php-di/php-di/src/DI/Definition/Source/Autowiring.php +68 -0
  165. addons/lib/ioc/php-di/php-di/src/DI/Definition/Source/CachedDefinitionSource.php +104 -0
  166. addons/lib/ioc/php-di/php-di/src/DI/Definition/Source/DefinitionArray.php +142 -0
  167. addons/lib/ioc/php-di/php-di/src/DI/Definition/Source/DefinitionFile.php +74 -0
  168. addons/lib/ioc/php-di/php-di/src/DI/Definition/Source/DefinitionSource.php +31 -0
  169. addons/lib/ioc/php-di/php-di/src/DI/Definition/Source/MutableDefinitionSource.php +15 -0
  170. addons/lib/ioc/php-di/php-di/src/DI/Definition/Source/SourceChain.php +108 -0
  171. addons/lib/ioc/php-di/php-di/src/DI/Definition/StringDefinition.php +66 -0
  172. addons/lib/ioc/php-di/php-di/src/DI/Definition/ValueDefinition.php +67 -0
  173. addons/lib/ioc/php-di/php-di/src/DI/DependencyException.php +19 -0
  174. addons/lib/ioc/php-di/php-di/src/DI/FactoryInterface.php +34 -0
  175. addons/lib/ioc/php-di/php-di/src/DI/Invoker/DefinitionParameterResolver.php +45 -0
  176. addons/lib/ioc/php-di/php-di/src/DI/InvokerInterface.php +19 -0
  177. addons/lib/ioc/php-di/php-di/src/DI/NotFoundException.php +19 -0
  178. addons/lib/ioc/php-di/php-di/src/DI/Proxy/ProxyFactory.php +88 -0
  179. addons/lib/ioc/php-di/php-di/src/DI/Reflection/CallableReflectionFactory.php +51 -0
  180. addons/lib/ioc/php-di/php-di/src/DI/Scope.php +54 -0
  181. addons/lib/ioc/php-di/php-di/src/DI/functions.php +181 -0
  182. addons/lib/ioc/php-di/phpdoc-reader/.gitattributes +7 -0
  183. addons/lib/ioc/php-di/phpdoc-reader/.gitignore +5 -0
  184. addons/lib/ioc/php-di/phpdoc-reader/LICENSE +16 -0
  185. addons/lib/ioc/php-di/phpdoc-reader/README.md +58 -0
  186. addons/lib/ioc/php-di/phpdoc-reader/composer.json +23 -0
  187. addons/lib/ioc/php-di/phpdoc-reader/src/PhpDocReader/AnnotationException.php +10 -0
  188. addons/lib/ioc/php-di/phpdoc-reader/src/PhpDocReader/PhpDocReader.php +311 -0
  189. addons/lib/ioc/php-di/phpdoc-reader/src/PhpDocReader/PhpParser/TokenParser.php +159 -0
  190. addons/lib/ioc/php-di/phpdoc-reader/src/PhpDocReader/PhpParser/UseStatementParser.php +68 -0
  191. addons/lib/ioc/psr/container/.gitignore +3 -0
  192. addons/lib/ioc/psr/container/LICENSE +21 -0
  193. addons/lib/ioc/psr/container/README.md +5 -0
  194. addons/lib/ioc/psr/container/composer.json +27 -0
  195. addons/lib/ioc/psr/container/src/ContainerExceptionInterface.php +13 -0
  196. addons/lib/ioc/psr/container/src/ContainerInterface.php +37 -0
  197. addons/lib/ioc/psr/container/src/NotFoundExceptionInterface.php +13 -0
  198. addons/lib/script-loader-tag/script-loader-tag-interface.php +23 -0
  199. addons/lib/script-loader-tag/script-loader-tag.php +57 -0
  200. addons/lib/settings-service-interface.php +163 -0
  201. addons/lib/settings-service.php +542 -0
  202. addons/style/css/admin_styles.css +144 -0
  203. addons/tests/bootstrap.php +37 -0
  204. addons/tests/integration/addons/test-add-to-any.php +19 -0
  205. addons/tests/integration/addons/test-caos-host-analyticsjs-local-save-ga-local.php +22 -0
  206. addons/tests/integration/addons/test-caos-host-analyticsjs-local.php +22 -0
  207. addons/tests/integration/addons/test-custom-facebook-feed.php +24 -0
  208. addons/tests/integration/addons/test-facebook-for-woocommerce.php +37 -0
  209. addons/tests/integration/addons/test-ga-google-analytics.php +21 -0
  210. addons/tests/integration/addons/test-gadwp.php +29 -0
  211. addons/tests/integration/addons/test-google-analyticator.php +24 -0
  212. addons/tests/integration/addons/test-google-analytics-plus.php +25 -0
  213. addons/tests/integration/addons/test-google-analytics.php +22 -0
  214. addons/tests/integration/addons/test-hubspot-leadin.php +21 -0
  215. addons/tests/integration/addons/test-hubspot-tracking-code.php +21 -0
  216. addons/tests/integration/addons/test-instagram-feed.php +21 -0
  217. addons/tests/integration/addons/test-jetpack-facebook-widget.php +22 -0
  218. addons/tests/integration/addons/test-jetpack-goodreads-widget.php +22 -0
  219. addons/tests/integration/addons/test-jetpack-google-maps-widget.php +23 -0
  220. addons/tests/integration/addons/test-jetpack-googleplus-badge-widget.php +21 -0
  221. addons/tests/integration/addons/test-jetpack-internet-defense-league-widget.php +21 -0
  222. addons/tests/integration/addons/test-jetpack-twitter-timeline-widget.php +21 -0
  223. addons/tests/integration/addons/test-ninja-forms.php +21 -0
  224. addons/tests/integration/addons/test-optinmonster.php +21 -0
  225. addons/tests/integration/addons/test-pixel-caffeine.php +23 -0
  226. addons/tests/integration/addons/test-wd-google-analytics.php +21 -0
  227. addons/tests/integration/addons/test-wp-analytify.php +21 -0
  228. addons/tests/integration/addons/test-wp-piwik.php +21 -0
  229. addons/tests/integration/test-buffer-priorities.php +49 -0
  230. addons/tests/unit/test-addon-file-name.php +63 -0
  231. addons/tests/unit/test-get-option-name.php +86 -0
  232. addons/tests/unit/test-latest-plugin-version.php +54 -0
  233. addons/tests/unit/test-manipulate-script.php +299 -0
  234. addons/tests/unit/test-previous-version-active.php +74 -0
  235. addons/view/admin/settings/available-addon-callback.php +114 -0
  236. addons/view/admin/settings/jetpack-addon-callback.php +103 -0
  237. addons/view/admin/settings/setting-page.php +82 -0
  238. assets/guide_add_language.gif +0 -0
  239. assets/icon.svg +1 -0
  240. cookiebot-logo.png +0 -0
  241. cookiebot.php +1128 -0
  242. css/notice.css +90 -0
  243. documentation/admin-ui.md +75 -0
  244. documentation/assets/available-plugins.png +0 -0
  245. documentation/assets/jetpack.png +0 -0
  246. documentation/assets/unavailable-plugins.png +0 -0
  247. documentation/how-to-add-new-addon.md +34 -0
  248. documentation/how-to-block-cookies.md +105 -0
  249. langs/cookiebot-da_DK.mo +0 -0
  250. langs/cookiebot-da_DK.po +159 -0
  251. langs/cookiebot.pot +426 -0
  252. phpunit.xml +29 -0
  253. readme.txt +262 -0
CookiebotAPI.md ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # How do I make my plugin support Cookiebot?
2
+ If you favourite plugins doesn’t support Cookiebot you are always welcome to ask the author to add support for Cookiebot.
3
+ Cookiebot provides a helper function to check if there is an active, working version of Cookiebot on the website.
4
+ The easiest way for at developer to implement Cookiebot support is to add a check for Cookiebot where tags are outputted to the visitor.
5
+
6
+ This can be done following way:
7
+
8
+ ```php
9
+ $scriptTag = ";
10
+ if(function_exists('cookiebot_active') && cookiebot_active()) {
11
+ $scriptTag = '<script'.cookiebot_assist('statistics').'>';
12
+ }
13
+ ```
14
+
15
+ A users consent state can be be aquired through Cookiebots JS API.
16
+
17
+ The following properties are available on the Cookiebot object:
18
+
19
+ | Name | Type | Default | Description |
20
+ |---------------------|:----:|:-------:|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|
21
+ | consent.necessary | bool | true | True if current user has accepted necessary cookies. <br> The property is read only. |
22
+ | consent.preferences | bool | false | True if current user has accepted preference cookies. <br> The property is read only. |
23
+ | consent.statistics | bool | false | True if current user has accepted statistics cookies. <br> The property is read only. |
24
+ | consent.marketing | bool | false | True if current user has accepted marketing cookies. <br> The property is read only. |
25
+ | consented | bool | false | True if the user has accepted cookies. <br> The property is read only. |
26
+ | declined | bool | false | True if the user has declined the use of cookies. <br> The property is read only. |
27
+ | hasResponse | bool | false | True if the user has responded to the dialog with either 'accept' or 'decline'. |
28
+ | doNotTrack | bool | false | True if the user has enabled the web browser's 'Do not track' (DNT) setting. <br> If DNT is enabled Cookiebot will not set the third party cookie CookieConsentBulkTicket used for bulk consent. <br> The property is read only. |
29
+
30
+ Callbacks
31
+
32
+ | Name | Description |
33
+ |-------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|
34
+ | CookiebotCallback_OnLoad | The asynchronous callback is triggered when the cookie banner has loaded to get the user's consent. |
35
+ | CookiebotCallback_OnAccept | The asynchronous callback is triggered when the user clicks the accept-button of the cookie consent dialog and whenever a consented user loads a page. | |
36
+ | CookiebotCallback_OnDecline | The asynchronous callback is triggered when the user declines the use of cookies by clicking the decline-button in the cookie consent dialog. The callback is also triggered whenever a user that has declined the use of cookies loads a page. | |
37
+
38
+
39
+ And through PHP:
40
+
41
+ ```php
42
+ if (isset($_COOKIE["CookieConsent"]))
43
+ {
44
+ switch ($_COOKIE["CookieConsent"])
45
+ {
46
+ case "0":
47
+ //The user has not accepted cookies - set strictly necessary cookies only
48
+ break;
49
+
50
+ case "-1":
51
+ //The user is not within a region that requires consent - all cookies are accepted
52
+ break;
53
+
54
+ default: //The user has accepted one or more type of cookies
55
+
56
+ //Read current user consent in encoded JavaScript format
57
+ $valid_php_json = preg_replace('/\s*:\s*([a-zA-Z0-9_]+?)([}\[,])/', ':"$1"$2', preg_replace('/([{\[,])\s*([a-zA-Z0-9_]+?):/', '$1"$2":', str_replace("'", '"',stripslashes($_COOKIE["CookieConsent"]))));
58
+ $CookieConsent = json_decode($valid_php_json);
59
+
60
+ if (filter_var($CookieConsent->preferences, FILTER_VALIDATE_BOOLEAN))
61
+ {
62
+ //Current user accepts preference cookies
63
+ }
64
+ else
65
+ {
66
+ //Current user does NOT accept preference cookies
67
+ }
68
+
69
+ if (filter_var($CookieConsent->statistics, FILTER_VALIDATE_BOOLEAN))
70
+ {
71
+ //Current user accepts statistics cookies
72
+ }
73
+ else
74
+ {
75
+ //Current user does NOT accept statistics cookies
76
+ }
77
+
78
+ if (filter_var($CookieConsent->marketing, FILTER_VALIDATE_BOOLEAN))
79
+ {
80
+ //Current user accepts marketing cookies
81
+ }
82
+ else
83
+ {
84
+ //Current user does NOT accept marketing cookies
85
+ }
86
+ }
87
+ }
88
+ else
89
+ {
90
+ //The user has not accepted cookies - set strictly necessary cookies only
91
+ }
92
+ ```
93
+ More details are available at https://www.cookiebot.com/goto/developer/
LICENSE.txt ADDED
@@ -0,0 +1,339 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ GNU GENERAL PUBLIC LICENSE
2
+ Version 2, June 1991
3
+
4
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6
+ Everyone is permitted to copy and distribute verbatim copies
7
+ of this license document, but changing it is not allowed.
8
+
9
+ Preamble
10
+
11
+ The licenses for most software are designed to take away your
12
+ freedom to share and change it. By contrast, the GNU General Public
13
+ License is intended to guarantee your freedom to share and change free
14
+ software--to make sure the software is free for all its users. This
15
+ General Public License applies to most of the Free Software
16
+ Foundation's software and to any other program whose authors commit to
17
+ using it. (Some other Free Software Foundation software is covered by
18
+ the GNU Lesser General Public License instead.) You can apply it to
19
+ your programs, too.
20
+
21
+ When we speak of free software, we are referring to freedom, not
22
+ price. Our General Public Licenses are designed to make sure that you
23
+ have the freedom to distribute copies of free software (and charge for
24
+ this service if you wish), that you receive source code or can get it
25
+ if you want it, that you can change the software or use pieces of it
26
+ in new free programs; and that you know you can do these things.
27
+
28
+ To protect your rights, we need to make restrictions that forbid
29
+ anyone to deny you these rights or to ask you to surrender the rights.
30
+ These restrictions translate to certain responsibilities for you if you
31
+ distribute copies of the software, or if you modify it.
32
+
33
+ For example, if you distribute copies of such a program, whether
34
+ gratis or for a fee, you must give the recipients all the rights that
35
+ you have. You must make sure that they, too, receive or can get the
36
+ source code. And you must show them these terms so they know their
37
+ rights.
38
+
39
+ We protect your rights with two steps: (1) copyright the software, and
40
+ (2) offer you this license which gives you legal permission to copy,
41
+ distribute and/or modify the software.
42
+
43
+ Also, for each author's protection and ours, we want to make certain
44
+ that everyone understands that there is no warranty for this free
45
+ software. If the software is modified by someone else and passed on, we
46
+ want its recipients to know that what they have is not the original, so
47
+ that any problems introduced by others will not reflect on the original
48
+ authors' reputations.
49
+
50
+ Finally, any free program is threatened constantly by software
51
+ patents. We wish to avoid the danger that redistributors of a free
52
+ program will individually obtain patent licenses, in effect making the
53
+ program proprietary. To prevent this, we have made it clear that any
54
+ patent must be licensed for everyone's free use or not licensed at all.
55
+
56
+ The precise terms and conditions for copying, distribution and
57
+ modification follow.
58
+
59
+ GNU GENERAL PUBLIC LICENSE
60
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61
+
62
+ 0. This License applies to any program or other work which contains
63
+ a notice placed by the copyright holder saying it may be distributed
64
+ under the terms of this General Public License. The "Program", below,
65
+ refers to any such program or work, and a "work based on the Program"
66
+ means either the Program or any derivative work under copyright law:
67
+ that is to say, a work containing the Program or a portion of it,
68
+ either verbatim or with modifications and/or translated into another
69
+ language. (Hereinafter, translation is included without limitation in
70
+ the term "modification".) Each licensee is addressed as "you".
71
+
72
+ Activities other than copying, distribution and modification are not
73
+ covered by this License; they are outside its scope. The act of
74
+ running the Program is not restricted, and the output from the Program
75
+ is covered only if its contents constitute a work based on the
76
+ Program (independent of having been made by running the Program).
77
+ Whether that is true depends on what the Program does.
78
+
79
+ 1. You may copy and distribute verbatim copies of the Program's
80
+ source code as you receive it, in any medium, provided that you
81
+ conspicuously and appropriately publish on each copy an appropriate
82
+ copyright notice and disclaimer of warranty; keep intact all the
83
+ notices that refer to this License and to the absence of any warranty;
84
+ and give any other recipients of the Program a copy of this License
85
+ along with the Program.
86
+
87
+ You may charge a fee for the physical act of transferring a copy, and
88
+ you may at your option offer warranty protection in exchange for a fee.
89
+
90
+ 2. You may modify your copy or copies of the Program or any portion
91
+ of it, thus forming a work based on the Program, and copy and
92
+ distribute such modifications or work under the terms of Section 1
93
+ above, provided that you also meet all of these conditions:
94
+
95
+ a) You must cause the modified files to carry prominent notices
96
+ stating that you changed the files and the date of any change.
97
+
98
+ b) You must cause any work that you distribute or publish, that in
99
+ whole or in part contains or is derived from the Program or any
100
+ part thereof, to be licensed as a whole at no charge to all third
101
+ parties under the terms of this License.
102
+
103
+ c) If the modified program normally reads commands interactively
104
+ when run, you must cause it, when started running for such
105
+ interactive use in the most ordinary way, to print or display an
106
+ announcement including an appropriate copyright notice and a
107
+ notice that there is no warranty (or else, saying that you provide
108
+ a warranty) and that users may redistribute the program under
109
+ these conditions, and telling the user how to view a copy of this
110
+ License. (Exception: if the Program itself is interactive but
111
+ does not normally print such an announcement, your work based on
112
+ the Program is not required to print an announcement.)
113
+
114
+ These requirements apply to the modified work as a whole. If
115
+ identifiable sections of that work are not derived from the Program,
116
+ and can be reasonably considered independent and separate works in
117
+ themselves, then this License, and its terms, do not apply to those
118
+ sections when you distribute them as separate works. But when you
119
+ distribute the same sections as part of a whole which is a work based
120
+ on the Program, the distribution of the whole must be on the terms of
121
+ this License, whose permissions for other licensees extend to the
122
+ entire whole, and thus to each and every part regardless of who wrote it.
123
+
124
+ Thus, it is not the intent of this section to claim rights or contest
125
+ your rights to work written entirely by you; rather, the intent is to
126
+ exercise the right to control the distribution of derivative or
127
+ collective works based on the Program.
128
+
129
+ In addition, mere aggregation of another work not based on the Program
130
+ with the Program (or with a work based on the Program) on a volume of
131
+ a storage or distribution medium does not bring the other work under
132
+ the scope of this License.
133
+
134
+ 3. You may copy and distribute the Program (or a work based on it,
135
+ under Section 2) in object code or executable form under the terms of
136
+ Sections 1 and 2 above provided that you also do one of the following:
137
+
138
+ a) Accompany it with the complete corresponding machine-readable
139
+ source code, which must be distributed under the terms of Sections
140
+ 1 and 2 above on a medium customarily used for software interchange; or,
141
+
142
+ b) Accompany it with a written offer, valid for at least three
143
+ years, to give any third party, for a charge no more than your
144
+ cost of physically performing source distribution, a complete
145
+ machine-readable copy of the corresponding source code, to be
146
+ distributed under the terms of Sections 1 and 2 above on a medium
147
+ customarily used for software interchange; or,
148
+
149
+ c) Accompany it with the information you received as to the offer
150
+ to distribute corresponding source code. (This alternative is
151
+ allowed only for noncommercial distribution and only if you
152
+ received the program in object code or executable form with such
153
+ an offer, in accord with Subsection b above.)
154
+
155
+ The source code for a work means the preferred form of the work for
156
+ making modifications to it. For an executable work, complete source
157
+ code means all the source code for all modules it contains, plus any
158
+ associated interface definition files, plus the scripts used to
159
+ control compilation and installation of the executable. However, as a
160
+ special exception, the source code distributed need not include
161
+ anything that is normally distributed (in either source or binary
162
+ form) with the major components (compiler, kernel, and so on) of the
163
+ operating system on which the executable runs, unless that component
164
+ itself accompanies the executable.
165
+
166
+ If distribution of executable or object code is made by offering
167
+ access to copy from a designated place, then offering equivalent
168
+ access to copy the source code from the same place counts as
169
+ distribution of the source code, even though third parties are not
170
+ compelled to copy the source along with the object code.
171
+
172
+ 4. You may not copy, modify, sublicense, or distribute the Program
173
+ except as expressly provided under this License. Any attempt
174
+ otherwise to copy, modify, sublicense or distribute the Program is
175
+ void, and will automatically terminate your rights under this License.
176
+ However, parties who have received copies, or rights, from you under
177
+ this License will not have their licenses terminated so long as such
178
+ parties remain in full compliance.
179
+
180
+ 5. You are not required to accept this License, since you have not
181
+ signed it. However, nothing else grants you permission to modify or
182
+ distribute the Program or its derivative works. These actions are
183
+ prohibited by law if you do not accept this License. Therefore, by
184
+ modifying or distributing the Program (or any work based on the
185
+ Program), you indicate your acceptance of this License to do so, and
186
+ all its terms and conditions for copying, distributing or modifying
187
+ the Program or works based on it.
188
+
189
+ 6. Each time you redistribute the Program (or any work based on the
190
+ Program), the recipient automatically receives a license from the
191
+ original licensor to copy, distribute or modify the Program subject to
192
+ these terms and conditions. You may not impose any further
193
+ restrictions on the recipients' exercise of the rights granted herein.
194
+ You are not responsible for enforcing compliance by third parties to
195
+ this License.
196
+
197
+ 7. If, as a consequence of a court judgment or allegation of patent
198
+ infringement or for any other reason (not limited to patent issues),
199
+ conditions are imposed on you (whether by court order, agreement or
200
+ otherwise) that contradict the conditions of this License, they do not
201
+ excuse you from the conditions of this License. If you cannot
202
+ distribute so as to satisfy simultaneously your obligations under this
203
+ License and any other pertinent obligations, then as a consequence you
204
+ may not distribute the Program at all. For example, if a patent
205
+ license would not permit royalty-free redistribution of the Program by
206
+ all those who receive copies directly or indirectly through you, then
207
+ the only way you could satisfy both it and this License would be to
208
+ refrain entirely from distribution of the Program.
209
+
210
+ If any portion of this section is held invalid or unenforceable under
211
+ any particular circumstance, the balance of the section is intended to
212
+ apply and the section as a whole is intended to apply in other
213
+ circumstances.
214
+
215
+ It is not the purpose of this section to induce you to infringe any
216
+ patents or other property right claims or to contest validity of any
217
+ such claims; this section has the sole purpose of protecting the
218
+ integrity of the free software distribution system, which is
219
+ implemented by public license practices. Many people have made
220
+ generous contributions to the wide range of software distributed
221
+ through that system in reliance on consistent application of that
222
+ system; it is up to the author/donor to decide if he or she is willing
223
+ to distribute software through any other system and a licensee cannot
224
+ impose that choice.
225
+
226
+ This section is intended to make thoroughly clear what is believed to
227
+ be a consequence of the rest of this License.
228
+
229
+ 8. If the distribution and/or use of the Program is restricted in
230
+ certain countries either by patents or by copyrighted interfaces, the
231
+ original copyright holder who places the Program under this License
232
+ may add an explicit geographical distribution limitation excluding
233
+ those countries, so that distribution is permitted only in or among
234
+ countries not thus excluded. In such case, this License incorporates
235
+ the limitation as if written in the body of this License.
236
+
237
+ 9. The Free Software Foundation may publish revised and/or new versions
238
+ of the General Public License from time to time. Such new versions will
239
+ be similar in spirit to the present version, but may differ in detail to
240
+ address new problems or concerns.
241
+
242
+ Each version is given a distinguishing version number. If the Program
243
+ specifies a version number of this License which applies to it and "any
244
+ later version", you have the option of following the terms and conditions
245
+ either of that version or of any later version published by the Free
246
+ Software Foundation. If the Program does not specify a version number of
247
+ this License, you may choose any version ever published by the Free Software
248
+ Foundation.
249
+
250
+ 10. If you wish to incorporate parts of the Program into other free
251
+ programs whose distribution conditions are different, write to the author
252
+ to ask for permission. For software which is copyrighted by the Free
253
+ Software Foundation, write to the Free Software Foundation; we sometimes
254
+ make exceptions for this. Our decision will be guided by the two goals
255
+ of preserving the free status of all derivatives of our free software and
256
+ of promoting the sharing and reuse of software generally.
257
+
258
+ NO WARRANTY
259
+
260
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261
+ FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262
+ OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263
+ PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264
+ OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266
+ TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267
+ PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268
+ REPAIR OR CORRECTION.
269
+
270
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272
+ REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273
+ INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274
+ OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275
+ TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276
+ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277
+ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278
+ POSSIBILITY OF SUCH DAMAGES.
279
+
280
+ END OF TERMS AND CONDITIONS
281
+
282
+ How to Apply These Terms to Your New Programs
283
+
284
+ If you develop a new program, and you want it to be of the greatest
285
+ possible use to the public, the best way to achieve this is to make it
286
+ free software which everyone can redistribute and change under these terms.
287
+
288
+ To do so, attach the following notices to the program. It is safest
289
+ to attach them to the start of each source file to most effectively
290
+ convey the exclusion of warranty; and each file should have at least
291
+ the "copyright" line and a pointer to where the full notice is found.
292
+
293
+ <one line to give the program's name and a brief idea of what it does.>
294
+ Copyright (C) <year> <name of author>
295
+
296
+ This program is free software; you can redistribute it and/or modify
297
+ it under the terms of the GNU General Public License as published by
298
+ the Free Software Foundation; either version 2 of the License, or
299
+ (at your option) any later version.
300
+
301
+ This program is distributed in the hope that it will be useful,
302
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
303
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304
+ GNU General Public License for more details.
305
+
306
+ You should have received a copy of the GNU General Public License along
307
+ with this program; if not, write to the Free Software Foundation, Inc.,
308
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309
+
310
+ Also add information on how to contact you by electronic and paper mail.
311
+
312
+ If the program is interactive, make it output a short notice like this
313
+ when it starts in an interactive mode:
314
+
315
+ Gnomovision version 69, Copyright (C) year name of author
316
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317
+ This is free software, and you are welcome to redistribute it
318
+ under certain conditions; type `show c' for details.
319
+
320
+ The hypothetical commands `show w' and `show c' should show the appropriate
321
+ parts of the General Public License. Of course, the commands you use may
322
+ be called something other than `show w' and `show c'; they could even be
323
+ mouse-clicks or menu items--whatever suits your program.
324
+
325
+ You should also get your employer (if you work as a programmer) or your
326
+ school, if any, to sign a "copyright disclaimer" for the program, if
327
+ necessary. Here is a sample; alter the names:
328
+
329
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
331
+
332
+ <signature of Ty Coon>, 1 April 1989
333
+ Ty Coon, President of Vice
334
+
335
+ This General Public License does not permit incorporating your program into
336
+ proprietary programs. If your program is a subroutine library, you may
337
+ consider it more useful to permit linking proprietary applications with the
338
+ library. If this is what you want to do, use the GNU Lesser General
339
+ Public License instead of this License.
README.md ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Cookiebot WordPress Plugin
2
+ Cookiebot Wordpress plugin is a plugin that make other plugins compatible with Cookiebot.
3
+ The addons hook into the original plugin and render the cookie setting tags as advised by the Cookiebot guidelines at https://www.cookiebot.com/goto/help/.
4
+
5
+ Concurrently we are working with WP Core on what we believe is the real solution. A framework in WP Core that can signal the consent state to other plugins,
6
+ so that they can handle their cookie setting code without explicit support for Cookiebot, or other cookie plugins. If and when this will be implemented is unknown.
7
+
8
+ https://core.trac.wordpress.org/ticket/44043
9
+
10
+ # Travis CI Status
11
+
12
+ [![Build Status](https://travis-ci.org/CybotAS/CookiebotAddons.svg?branch=develop)](https://travis-ci.org/CybotAS/CookiebotAddons)
13
+
14
+ Table of contents
15
+ =================
16
+
17
+ <!--ts-->
18
+ * [Installation](#installation)
19
+ * [How do I make my plugin support Cookiebot?](#how-do-i-make-my-plugin-support-cookiebot)
20
+ * [Roadmap](#roadmap)
21
+ * [Contributions](#contributions)
22
+ * [Need to get in touch?](#need-to-get-in-touch)
23
+ <!--te-->
24
+
25
+ # Installation
26
+ Regular users should use [Cookiebot WordPress plugin](https://wordpress.org/plugins/cookiebot) which includes Cookiebot Addons.
27
+
28
+ If you want the most recent changes get the [latest release](https://github.com/CybotAS/CookiebotAddons/releases/latest) of the plugin and upliad it to your WP plugins folder
29
+
30
+ # How do I make my plugin support Cookiebot?
31
+ See [the Cookiebot API readme for more details about the Cookiebot API](CookiebotAPI.md)
32
+
33
+ See [How to block cookies](documentation/how-to-block-cookies.md)
34
+
35
+ See [How to add new addon](documentation/how-to-add-new-addon.md)
36
+
37
+ See [Admin UI](documentation/admin-ui.md)
38
+
39
+ # Roadmap
40
+
41
+ Following plugins have native (built-in) support for Cookiebot:
42
+ * [MonsterInsights](https://www.monsterinsights.com/addon/eu-compliance/)
43
+ * [PixelYourSite](https://wordpress.org/plugins/pixelyoursite/)
44
+
45
+ Released and tested addons:
46
+
47
+ * Autocorrection of embedded Facebook, Twitter, Youtube and Vimeo videos
48
+ * [AddToAny Share Buttons](https://wordpress.org/plugins/add-to-any/)
49
+ * [Analytify](https://wordpress.org/plugins/wp-analytify/)
50
+ * [Custom Facebook Feed from Smashballoon](https://da.wordpress.org/plugins/custom-facebook-feed/)
51
+ * [GA Google Analytics](https://wordpress.org/plugins/ga-google-analytics/)
52
+ * [Google Analyticator](https://wordpress.org/plugins/google-analyticator/)
53
+ * [Google Analytics +](https://premium.wpmudev.org/project/google-analytics-for-wordpress-mu-sitewide-and-single-blog-solution/)
54
+ * [HubSpot Tracking Code](https://wordpress.org/plugins/hubspot-tracking-code/)
55
+ * [Jetpack by WordPress.com](https://wordpress.org/plugins/jetpack/)
56
+ * Supported widgets:
57
+ * Google Maps
58
+ * Facebook
59
+ * Google Plus Badge
60
+ * Internet Defense League
61
+ * Twitter Timeline
62
+ * Goodreads
63
+ * [Pixel Caffeine]( https://wordpress.org/plugins/pixel-caffeine/)
64
+ * [WD Google Analytics](https://wordpress.org/plugins/wd-google-analytics/)
65
+ * [WP-Matomo](https://wordpress.org/plugins/wp-piwik/)
66
+ * [Complete Analytics Optimization Suite (CAOS)](https://wordpress.org/plugins/host-analyticsjs-local/)
67
+ * [Facebook for WooCommerce](https://woocommerce.com/products/facebook/)
68
+ * [Googleanalytics](https://wordpress.org/plugins/googleanalytics/)
69
+ * [HubSpot – Free Marketing Plugin for WordPress](https://wordpress.org/plugins/leadin/)
70
+ * [Ninja forms](https://wordpress.org/plugins/ninja-forms/)
71
+ * [Popups by OptinMonster](https://wordpress.org/plugins/optinmonster/)
72
+
73
+ Following addons are in pipeline:
74
+ * To be continued..
75
+
76
+
77
+ If you have a plugin that you would like integration for, please submit a request in the [Issues](https://github.com/CybotAS/CookiebotAddons/issues) section.
78
+
79
+ # Contributions
80
+ Everyone is welcome to make a pull request with new addon support, or to fix existing addons.
81
+
82
+ Shout out to
83
+
84
+ [@fschaeffler](https://github.com/fschaeffler) - HubSpot Tracking Code
85
+
86
+ [@irondan](https://github.com/irondan) - AddToAny
87
+
88
+ [@Jursdotme](https://github.com/Jursdotme) - Custom Facebook Feed from Smashballoon
89
+
90
+ [@MarcZijderveld](https://github.com/MarcZijderveld) - Popups by OptinMonster
91
+
92
+ Way to go!
93
+
94
+ # Need to get in touch?
95
+
96
+ There are several ways you can get in touch with us. <br>
97
+ We are available on the Making Wordress Slack workspace. <br>
98
+ Username: Kenan <br>
99
+ You can also reach us through our helpdesk at www.cookiebot.com/goto/helpdesk/
addons/.travis.yml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # see http://about.travis-ci.org/docs/user/languages/php/ for more hints
2
+ language: php
3
+
4
+ # list any PHP version you want to test against
5
+ php:
6
+ # aliased to a recent 5.4.x version
7
+ - '5.4'
8
+ - '5.6'
9
+ - '7.1'
10
+
11
+ env:
12
+ - WP_PROJECT_TYPE=plugin WP_VERSION=latest WP_MULTISITE=0 WP_TEST_URL=http://localhost:12000 WP_TEST_USER=test WP_TEST_USER_PASS=test
13
+
14
+ before_script:
15
+ # Install composer packages before trying to activate themes or plugins
16
+ # - composer install
17
+
18
+ - git clone https://github.com/Seravo/wordpress-test-template wp-tests
19
+ - bash wp-tests/bin/install-wp-tests.sh test root '' localhost $WP_VERSION
20
+
21
+ script:
22
+ - phpunit
addons/addons.json ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "Add_To_Any": {
3
+ "class": "cookiebot_addons\\controller\\addons\\add_to_any\\Add_To_Any"
4
+ },
5
+ "Ga_Google_Analytics": {
6
+ "class": "cookiebot_addons\\controller\\addons\\ga_google_analytics\\Ga_Google_Analytics"
7
+ },
8
+ "Google_Analytics": {
9
+ "class": "cookiebot_addons\\controller\\addons\\google_analytics\\Google_Analytics"
10
+ },
11
+ "Ga_Analyticator": {
12
+ "class": "cookiebot_addons\\controller\\addons\\google_analyticator\\Google_Analyticator"
13
+ },
14
+ "Wd_Google_Analytics": {
15
+ "class": "cookiebot_addons\\controller\\addons\\wd_google_analytics\\Wd_Google_Analytics"
16
+ },
17
+ "Jetpack": {
18
+ "class": "cookiebot_addons\\controller\\addons\\jetpack\\Jetpack"
19
+ },
20
+ "Hubspot_Leadin": {
21
+ "class": "cookiebot_addons\\controller\\addons\\hubspot_leadin\\Hubspot_Leadin"
22
+ },
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
+ },
29
+ "Custom_Facebook_Feed_Pro": {
30
+ "class": "cookiebot_addons\\controller\\addons\\custom_facebook_feed_pro\\Custom_Facebook_Feed_Pro"
31
+ },
32
+ "Embed_Autocorrect": {
33
+ "class": "cookiebot_addons\\controller\\addons\\embed_autocorrect\\Embed_Autocorrect"
34
+ },
35
+ "Instagram_Feed": {
36
+ "class": "cookiebot_addons\\controller\\addons\\instagram_feed\\Instagram_Feed"
37
+ },
38
+ "WP_Piwik": {
39
+ "class": "cookiebot_addons\\controller\\addons\\wp_piwik\\Wp_Piwik"
40
+ },
41
+ "Facebook_For_Woocommerce": {
42
+ "class": "cookiebot_addons\\controller\\addons\\facebook_for_woocommerce\\Facebook_For_Woocommerce"
43
+ },
44
+ "Pixel_Caffeine": {
45
+ "class": "cookiebot_addons\\controller\\addons\\pixel_caffeine\\Pixel_Caffeine"
46
+ },
47
+ "Wp_Analytify": {
48
+ "class": "cookiebot_addons\\controller\\addons\\wp_analytify\\Wp_Analytify"
49
+ },
50
+ "Google_Analytics_Plus": {
51
+ "class": "cookiebot_addons\\controller\\addons\\google_analytics_plus\\Google_Analytics_Plus"
52
+ },
53
+ "CAOS_Host_Analyticsjs_Local_Save_Ga_Local": {
54
+ "class": "cookiebot_addons\\controller\\addons\\caos_host_analyticsjs_local_save_ga_local\\CAOS_Host_Analyticsjs_Local_Save_Ga_Local"
55
+ },
56
+ "CAOS_Host_Analyticsjs_Local": {
57
+ "class": "cookiebot_addons\\controller\\addons\\caos_host_analyticsjs_local\\CAOS_Host_Analyticsjs_Local"
58
+ },
59
+ "Ninja_Forms": {
60
+ "class": "cookiebot_addons\\controller\\addons\\ninja_forms\\Ninja_Forms"
61
+ },
62
+ "Optinmonster": {
63
+ "class": "cookiebot_addons\\controller\\addons\\optinmonster\\Optinmonster"
64
+ },
65
+ "Wpforms": {
66
+ "class": "cookiebot_addons\\controller\\addons\\wpforms\\Wpforms"
67
+ },
68
+ "Gadwp": {
69
+ "class": "cookiebot_addons\\controller\\addons\\gadwp\\Gadwp"
70
+ }
71
+ }
addons/bin/install-wp-tests.sh ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+
3
+ if [ $# -lt 3 ]; then
4
+ echo "usage: $0 <db-name> <db-user> <db-pass> [db-host] [wp-version] [skip-database-creation]"
5
+ exit 1
6
+ fi
7
+
8
+ DB_NAME=$1
9
+ DB_USER=$2
10
+ DB_PASS=$3
11
+ DB_HOST=${4-localhost}
12
+ WP_VERSION=${5-latest}
13
+ SKIP_DB_CREATE=${6-false}
14
+
15
+ WP_TESTS_DIR=${WP_TESTS_DIR-/tmp/wordpress-tests-lib}
16
+ WP_CORE_DIR=${WP_CORE_DIR-/tmp/wordpress/}
17
+
18
+ download() {
19
+ if [ `which curl` ]; then
20
+ curl -s "$1" > "$2";
21
+ elif [ `which wget` ]; then
22
+ wget -nv -O "$2" "$1"
23
+ fi
24
+ }
25
+
26
+ if [[ $WP_VERSION =~ [0-9]+\.[0-9]+(\.[0-9]+)? ]]; then
27
+ WP_TESTS_TAG="tags/$WP_VERSION"
28
+ elif [[ $WP_VERSION == 'nightly' || $WP_VERSION == 'trunk' ]]; then
29
+ WP_TESTS_TAG="trunk"
30
+ else
31
+ # http serves a single offer, whereas https serves multiple. we only want one
32
+ download http://api.wordpress.org/core/version-check/1.7/ /tmp/wp-latest.json
33
+ grep '[0-9]+\.[0-9]+(\.[0-9]+)?' /tmp/wp-latest.json
34
+ LATEST_VERSION=$(grep -o '"version":"[^"]*' /tmp/wp-latest.json | sed 's/"version":"//')
35
+ if [[ -z "$LATEST_VERSION" ]]; then
36
+ echo "Latest WordPress version could not be found"
37
+ exit 1
38
+ fi
39
+ WP_TESTS_TAG="tags/$LATEST_VERSION"
40
+ fi
41
+
42
+ set -ex
43
+
44
+ install_wp() {
45
+
46
+ if [ -d $WP_CORE_DIR ]; then
47
+ return;
48
+ fi
49
+
50
+ mkdir -p $WP_CORE_DIR
51
+
52
+ if [[ $WP_VERSION == 'nightly' || $WP_VERSION == 'trunk' ]]; then
53
+ mkdir -p /tmp/wordpress-nightly
54
+ download https://wordpress.org/nightly-builds/wordpress-latest.zip /tmp/wordpress-nightly/wordpress-nightly.zip
55
+ unzip -q /tmp/wordpress-nightly/wordpress-nightly.zip -d /tmp/wordpress-nightly/
56
+ mv /tmp/wordpress-nightly/wordpress/* $WP_CORE_DIR
57
+ else
58
+ if [ $WP_VERSION == 'latest' ]; then
59
+ local ARCHIVE_NAME='latest'
60
+ else
61
+ local ARCHIVE_NAME="wordpress-$WP_VERSION"
62
+ fi
63
+ download https://wordpress.org/${ARCHIVE_NAME}.tar.gz /tmp/wordpress.tar.gz
64
+ tar --strip-components=1 -zxmf /tmp/wordpress.tar.gz -C $WP_CORE_DIR
65
+ fi
66
+
67
+ download https://raw.github.com/markoheijnen/wp-mysqli/master/db.php $WP_CORE_DIR/wp-content/db.php
68
+ }
69
+
70
+ install_test_suite() {
71
+ # portable in-place argument for both GNU sed and Mac OSX sed
72
+ if [[ $(uname -s) == 'Darwin' ]]; then
73
+ local ioption='-i .bak'
74
+ else
75
+ local ioption='-i'
76
+ fi
77
+
78
+ # set up testing suite if it doesn't yet exist
79
+ if [ ! -d $WP_TESTS_DIR ]; then
80
+ # set up testing suite
81
+ mkdir -p $WP_TESTS_DIR
82
+ svn co --quiet https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/includes/ $WP_TESTS_DIR/includes
83
+ fi
84
+
85
+ if [ ! -f wp-tests-config.php ]; then
86
+ download https://develop.svn.wordpress.org/${WP_TESTS_TAG}/wp-tests-config-sample.php "$WP_TESTS_DIR"/wp-tests-config.php
87
+ # remove all forward slashes in the end
88
+ WP_CORE_DIR=$(echo $WP_CORE_DIR | sed "s:/\+$::")
89
+ sed $ioption "s:dirname( __FILE__ ) . '/src/':'$WP_CORE_DIR/':" "$WP_TESTS_DIR"/wp-tests-config.php
90
+ sed $ioption "s/youremptytestdbnamehere/$DB_NAME/" "$WP_TESTS_DIR"/wp-tests-config.php
91
+ sed $ioption "s/yourusernamehere/$DB_USER/" "$WP_TESTS_DIR"/wp-tests-config.php
92
+ sed $ioption "s/yourpasswordhere/$DB_PASS/" "$WP_TESTS_DIR"/wp-tests-config.php
93
+ sed $ioption "s|localhost|${DB_HOST}|" "$WP_TESTS_DIR"/wp-tests-config.php
94
+ fi
95
+
96
+ }
97
+
98
+ install_db() {
99
+
100
+ if [ ${SKIP_DB_CREATE} = "true" ]; then
101
+ return 0
102
+ fi
103
+
104
+ # parse DB_HOST for port or socket references
105
+ local PARTS=(${DB_HOST//\:/ })
106
+ local DB_HOSTNAME=${PARTS[0]};
107
+ local DB_SOCK_OR_PORT=${PARTS[1]};
108
+ local EXTRA=""
109
+
110
+ if ! [ -z $DB_HOSTNAME ] ; then
111
+ if [ $(echo $DB_SOCK_OR_PORT | grep -e '^[0-9]\{1,\}$') ]; then
112
+ EXTRA=" --host=$DB_HOSTNAME --port=$DB_SOCK_OR_PORT --protocol=tcp"
113
+ elif ! [ -z $DB_SOCK_OR_PORT ] ; then
114
+ EXTRA=" --socket=$DB_SOCK_OR_PORT"
115
+ elif ! [ -z $DB_HOSTNAME ] ; then
116
+ EXTRA=" --host=$DB_HOSTNAME --protocol=tcp"
117
+ fi
118
+ fi
119
+
120
+ # create database
121
+ mysqladmin create $DB_NAME --user="$DB_USER" --password="$DB_PASS"$EXTRA
122
+ }
123
+
124
+ install_wp
125
+ install_test_suite
126
+ install_db
addons/composer.json ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ {
2
+ "require": {
3
+ "php-di/php-di": "5.0"
4
+ }
5
+ }
addons/composer.lock ADDED
@@ -0,0 +1,232 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "_readme": [
3
+ "This file locks the dependencies of your project to a known state",
4
+ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
5
+ "This file is @generated automatically"
6
+ ],
7
+ "content-hash": "201899dc63377043c49159a10773dd47",
8
+ "packages": [
9
+ {
10
+ "name": "container-interop/container-interop",
11
+ "version": "1.2.0",
12
+ "source": {
13
+ "type": "git",
14
+ "url": "https://github.com/container-interop/container-interop.git",
15
+ "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8"
16
+ },
17
+ "dist": {
18
+ "type": "zip",
19
+ "url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8",
20
+ "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8",
21
+ "shasum": ""
22
+ },
23
+ "require": {
24
+ "psr/container": "^1.0"
25
+ },
26
+ "type": "library",
27
+ "autoload": {
28
+ "psr-4": {
29
+ "Interop\\Container\\": "src/Interop/Container/"
30
+ }
31
+ },
32
+ "notification-url": "https://packagist.org/downloads/",
33
+ "license": [
34
+ "MIT"
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
+ {
41
+ "name": "php-di/invoker",
42
+ "version": "1.3.3",
43
+ "source": {
44
+ "type": "git",
45
+ "url": "https://github.com/PHP-DI/Invoker.git",
46
+ "reference": "1f4ca63b9abc66109e53b255e465d0ddb5c2e3f7"
47
+ },
48
+ "dist": {
49
+ "type": "zip",
50
+ "url": "https://api.github.com/repos/PHP-DI/Invoker/zipball/1f4ca63b9abc66109e53b255e465d0ddb5c2e3f7",
51
+ "reference": "1f4ca63b9abc66109e53b255e465d0ddb5c2e3f7",
52
+ "shasum": ""
53
+ },
54
+ "require": {
55
+ "container-interop/container-interop": "~1.1"
56
+ },
57
+ "require-dev": {
58
+ "athletic/athletic": "~0.1.8",
59
+ "phpunit/phpunit": "~4.5"
60
+ },
61
+ "type": "library",
62
+ "autoload": {
63
+ "psr-4": {
64
+ "Invoker\\": "src/"
65
+ }
66
+ },
67
+ "notification-url": "https://packagist.org/downloads/",
68
+ "license": [
69
+ "MIT"
70
+ ],
71
+ "description": "Generic and extensible callable invoker",
72
+ "homepage": "https://github.com/PHP-DI/Invoker",
73
+ "keywords": [
74
+ "callable",
75
+ "dependency",
76
+ "dependency-injection",
77
+ "injection",
78
+ "invoke",
79
+ "invoker"
80
+ ],
81
+ "time": "2016-07-14T13:09:58+00:00"
82
+ },
83
+ {
84
+ "name": "php-di/php-di",
85
+ "version": "5.0.0",
86
+ "source": {
87
+ "type": "git",
88
+ "url": "https://github.com/PHP-DI/PHP-DI.git",
89
+ "reference": "c3bbc0d334b888ec8baa75f95b4900ee17b18fa7"
90
+ },
91
+ "dist": {
92
+ "type": "zip",
93
+ "url": "https://api.github.com/repos/PHP-DI/PHP-DI/zipball/c3bbc0d334b888ec8baa75f95b4900ee17b18fa7",
94
+ "reference": "c3bbc0d334b888ec8baa75f95b4900ee17b18fa7",
95
+ "shasum": ""
96
+ },
97
+ "require": {
98
+ "container-interop/container-interop": "~1.0",
99
+ "php": ">=5.4.0",
100
+ "php-di/invoker": "~1.0",
101
+ "php-di/phpdoc-reader": "~2.0"
102
+ },
103
+ "require-dev": {
104
+ "doctrine/annotations": "~1.2",
105
+ "doctrine/cache": "~1.0",
106
+ "mnapoli/phpunit-easymock": "~0.1.4",
107
+ "ocramius/proxy-manager": "~1.0",
108
+ "phpunit/phpunit": "~4.5"
109
+ },
110
+ "suggest": {
111
+ "doctrine/annotations": "Install it if you want to use annotations (version ~1.2)",
112
+ "doctrine/cache": "Install it if you want to use the cache (version ~1.0)",
113
+ "ocramius/proxy-manager": "Install it if you want to use lazy injection (version ~1.0)"
114
+ },
115
+ "type": "library",
116
+ "autoload": {
117
+ "psr-4": {
118
+ "DI\\": "src/DI/"
119
+ },
120
+ "files": [
121
+ "src/DI/functions.php"
122
+ ]
123
+ },
124
+ "notification-url": "https://packagist.org/downloads/",
125
+ "license": [
126
+ "MIT"
127
+ ],
128
+ "description": "The dependency injection container for humans",
129
+ "homepage": "http://php-di.org/",
130
+ "keywords": [
131
+ "container",
132
+ "dependency injection",
133
+ "di"
134
+ ],
135
+ "time": "2015-06-10T06:16:52+00:00"
136
+ },
137
+ {
138
+ "name": "php-di/phpdoc-reader",
139
+ "version": "2.1.0",
140
+ "source": {
141
+ "type": "git",
142
+ "url": "https://github.com/PHP-DI/PhpDocReader.git",
143
+ "reference": "7d0de60b9341933c8afd172a6255cd7557601e0e"
144
+ },
145
+ "dist": {
146
+ "type": "zip",
147
+ "url": "https://api.github.com/repos/PHP-DI/PhpDocReader/zipball/7d0de60b9341933c8afd172a6255cd7557601e0e",
148
+ "reference": "7d0de60b9341933c8afd172a6255cd7557601e0e",
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": {
159
+ "psr-4": {
160
+ "PhpDocReader\\": "src/PhpDocReader"
161
+ }
162
+ },
163
+ "notification-url": "https://packagist.org/downloads/",
164
+ "license": [
165
+ "MIT"
166
+ ],
167
+ "description": "PhpDocReader parses @var and @param values in PHP docblocks (supports namespaced class names with the same resolution rules as PHP)",
168
+ "keywords": [
169
+ "phpdoc",
170
+ "reflection"
171
+ ],
172
+ "time": "2018-02-18T17:39:01+00:00"
173
+ },
174
+ {
175
+ "name": "psr/container",
176
+ "version": "1.0.0",
177
+ "source": {
178
+ "type": "git",
179
+ "url": "https://github.com/php-fig/container.git",
180
+ "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f"
181
+ },
182
+ "dist": {
183
+ "type": "zip",
184
+ "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
185
+ "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
186
+ "shasum": ""
187
+ },
188
+ "require": {
189
+ "php": ">=5.3.0"
190
+ },
191
+ "type": "library",
192
+ "extra": {
193
+ "branch-alias": {
194
+ "dev-master": "1.0.x-dev"
195
+ }
196
+ },
197
+ "autoload": {
198
+ "psr-4": {
199
+ "Psr\\Container\\": "src/"
200
+ }
201
+ },
202
+ "notification-url": "https://packagist.org/downloads/",
203
+ "license": [
204
+ "MIT"
205
+ ],
206
+ "authors": [
207
+ {
208
+ "name": "PHP-FIG",
209
+ "homepage": "http://www.php-fig.org/"
210
+ }
211
+ ],
212
+ "description": "Common Container Interface (PHP FIG PSR-11)",
213
+ "homepage": "https://github.com/php-fig/container",
214
+ "keywords": [
215
+ "PSR-11",
216
+ "container",
217
+ "container-interface",
218
+ "container-interop",
219
+ "psr"
220
+ ],
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
+ }
addons/config/script-config.php ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\config;
4
+
5
+ class Script_Config {
6
+
7
+ /**
8
+ * Script_Config constructor.
9
+ *
10
+ * @since 1.9.0
11
+ */
12
+ public function __construct() {
13
+ add_action( 'init', array( $this, 'scripts' ) );
14
+ }
15
+
16
+ /**
17
+ * Run Fix scripts
18
+ *
19
+ * @since 1.9.0
20
+ */
21
+ public function scripts() {
22
+ $this->fix_cookietypes_placeholder();
23
+ }
24
+
25
+ /**
26
+ * Fix %s mergetag into %cookie_types
27
+ * Run it once and only in the cookiebot addon version 1.9.0
28
+ *
29
+ * @since 1.9.0
30
+ */
31
+ private function fix_cookietypes_placeholder() {
32
+ /**
33
+ * Only for the version 1.9.0
34
+ */
35
+ if ( COOKIEBOT_ADDONS_VERSION == '1.9.0' ) {
36
+
37
+ /**
38
+ * Only run it once
39
+ */
40
+ if ( ! get_option( 'fix_cookietypes_placeholder' ) ) {
41
+
42
+ $options = array( 'cookiebot_jetpack_addon', 'cookiebot_available_addons' );
43
+
44
+ foreach ( $options as $option_key ) {
45
+ /**
46
+ * Cookiebot jetpack addon
47
+ */
48
+ $option = get_option( $option_key );
49
+
50
+ if ( $option ) {
51
+
52
+ foreach ( $option as $addon_key => $addon ) {
53
+
54
+ if ( isset( $addon['placeholder'] ) ) {
55
+
56
+ foreach ( $addon['placeholder']['languages'] as $addon_option_key => $addon_option ) {
57
+ /**
58
+ * Replace %s[ with %cookie_types[
59
+ */
60
+ $text = str_replace( '%s[', '%cookie_types[', $addon_option );
61
+
62
+ $option[ $addon_key ]['placeholder']['languages'][ $addon_option_key ] = $text;
63
+ }
64
+ }
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Update the uption value
70
+ */
71
+ update_option( $option_key, $option );
72
+ }
73
+
74
+ add_option( 'fix_cookietypes_placeholder' );
75
+ }
76
+ }
77
+ }
78
+ }
addons/config/settings-config.php ADDED
@@ -0,0 +1,331 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\config;
4
+
5
+ use cookiebot_addons\lib\Settings_Service_Interface;
6
+
7
+ class Settings_Config {
8
+
9
+ /**
10
+ * @var Settings_Service_Interface
11
+ */
12
+ protected $settings_service;
13
+
14
+ /**
15
+ * Settings_Config constructor.
16
+ *
17
+ * @param Settings_Service_Interface $settings_service
18
+ *
19
+ * @since 1.3.0
20
+ */
21
+ public function __construct( Settings_Service_Interface $settings_service ) {
22
+ $this->settings_service = $settings_service;
23
+ }
24
+
25
+ /**
26
+ * Load data for settings page
27
+ *
28
+ * @since 1.3.0
29
+ */
30
+ public function load() {
31
+ add_action( 'admin_menu', array( $this, 'add_submenu' ) );
32
+ add_action( 'admin_init', array( $this, 'register_settings' ) );
33
+ add_action( 'admin_enqueue_scripts', array( $this, 'add_wp_admin_style_script' ) );
34
+ add_action( 'update_option_cookiebot_available_addons', array(
35
+ $this,
36
+ 'post_hook_available_addons_update_option'
37
+ ), 10, 3 );
38
+ }
39
+
40
+ /**
41
+ * Registers submenu in options menu.
42
+ *
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
+ ) );
55
+
56
+ }
57
+
58
+ /**
59
+ * Load css styling to the settings page
60
+ *
61
+ * @since 1.3.0
62
+ */
63
+ public function add_wp_admin_style_script( $hook ) {
64
+ if ( $hook != 'cookiebot_page_cookiebot-addons' ) {
65
+ return;
66
+ }
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
+
74
+ /**
75
+ * Registers addons for settings page.
76
+ *
77
+ * @since 1.3.0
78
+ */
79
+ public function register_settings() {
80
+ global $pagenow;
81
+
82
+ if ( ( isset( $_GET['page'] ) && $_GET['page'] == 'cookiebot-addons' ) || $pagenow == 'options.php' ) {
83
+ if ( isset( $_GET['tab'] ) && 'unavailable_addons' === $_GET['tab'] ) {
84
+ $this->register_unavailable_addons();
85
+ } elseif ( ( isset( $_GET['tab'] ) && 'jetpack' === $_GET['tab'] ) ) {
86
+ $this->register_jetpack_addon();
87
+ } else {
88
+ $this->register_available_addons();
89
+ }
90
+
91
+ if ( $pagenow == 'options.php' ) {
92
+ $this->register_jetpack_addon();
93
+ }
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Register available addons
99
+ *
100
+ * @since 1.3.0
101
+ */
102
+ private function register_available_addons() {
103
+ add_settings_section( "available_addons", "Available plugins", array(
104
+ $this,
105
+ "header_available_addons"
106
+ ), "cookiebot-addons" );
107
+
108
+ foreach ( $this->settings_service->get_addons() as $addon ) {
109
+ if ( $addon->is_addon_installed() && $addon->is_addon_activated() ) {
110
+ add_settings_field(
111
+ $addon->get_option_name(),
112
+ $addon->get_addon_name() . $this->get_extra_information( $addon ),
113
+ array(
114
+ $this,
115
+ "available_addon_callback"
116
+ ),
117
+ "cookiebot-addons",
118
+ "available_addons",
119
+ array(
120
+ 'addon' => $addon
121
+ )
122
+ );
123
+
124
+ register_setting( 'cookiebot_available_addons', "cookiebot_available_addons", array(
125
+ $this,
126
+ 'sanitize_cookiebot'
127
+ ) );
128
+ }
129
+ }
130
+ }
131
+
132
+ /**
133
+ * Register jetpack addon - new tab for jetpack specific settings
134
+ *
135
+ * @since 1.3.0
136
+ */
137
+ private function register_jetpack_addon() {
138
+ add_settings_section( "jetpack_addon", "Jetpack", array(
139
+ $this,
140
+ "header_jetpack_addon"
141
+ ), "cookiebot-addons" );
142
+
143
+ foreach ( $this->settings_service->get_addons() as $addon ) {
144
+ if ( 'Jetpack' === ( new \ReflectionClass( $addon ) )->getShortName() ) {
145
+ if ( $addon->is_addon_installed() && $addon->is_addon_activated() ) {
146
+
147
+ foreach ( $addon->get_widgets() as $widget ) {
148
+ add_settings_field(
149
+ $widget->get_widget_option_name(),
150
+ $widget->get_label() . $this->get_extra_information( $widget ),
151
+ array(
152
+ $this,
153
+ "jetpack_addon_callback"
154
+ ),
155
+ "cookiebot-addons",
156
+ "jetpack_addon",
157
+ array(
158
+ 'widget' => $widget,
159
+ 'addon' => $addon
160
+ )
161
+ );
162
+
163
+ register_setting( 'cookiebot_jetpack_addon', 'cookiebot_jetpack_addon' );
164
+ }
165
+ }
166
+ }
167
+ }
168
+ }
169
+
170
+ /**
171
+ * Registers unavailabe addons
172
+ *
173
+ * @since 1.3.0
174
+ * @version 2.1.3
175
+ */
176
+ private function register_unavailable_addons() {
177
+ add_settings_section( "unavailable_addons", "Unavailable plugins", array(
178
+ $this,
179
+ "header_unavailable_addons"
180
+ ), "cookiebot-addons" );
181
+
182
+ $addons = $this->settings_service->get_addons();
183
+
184
+ foreach ( $addons as $addon ) {
185
+ if ( ( ! $addon->is_addon_installed() || ! $addon->is_addon_activated() )
186
+ && $this->settings_service->is_latest_plugin_version( $addon )
187
+ && ! $this->settings_service->is_previous_version_active(
188
+ $addons,
189
+ get_class( $addon )
190
+ )
191
+ ) {
192
+ // not installed plugins
193
+ add_settings_field(
194
+ $addon->get_addon_name(),
195
+ $addon->get_addon_name() . $this->get_extra_information( $addon ),
196
+ array(
197
+ $this,
198
+ "unavailable_addon_callback"
199
+ ),
200
+ "cookiebot-addons",
201
+ "unavailable_addons",
202
+ array( 'addon' => $addon )
203
+ );
204
+ register_setting( $addon->get_option_name(), "cookiebot_unavailable_addons" );
205
+ }
206
+ }
207
+ }
208
+
209
+ /**
210
+ * Adds extra information under the label.
211
+ *
212
+ * @param $addon
213
+ *
214
+ * @return string
215
+ */
216
+ private function get_extra_information( $addon ) {
217
+ return ( $addon->get_extra_information() !== false ) ? '<div class="extra_information">' . $addon->get_extra_information() . '</div>' : '';
218
+ }
219
+
220
+ /**
221
+ * Jetpack tab - header
222
+ *
223
+ * @since 1.3.0
224
+ */
225
+ public function header_jetpack_addon() {
226
+ echo '<p>' . __( 'Jetpack settings.', 'cookiebot' ) . '</p>';
227
+ }
228
+
229
+ /**
230
+ * Jetpack tab - widget callback
231
+ *
232
+ * @param $args array Information about the widget addon and the option
233
+ *
234
+ * @since 1.3.0
235
+ */
236
+ public function jetpack_addon_callback( $args ) {
237
+ include COOKIEBOT_ADDONS_DIR . 'view/admin/settings/jetpack-addon-callback.php';
238
+ }
239
+
240
+ /**
241
+ * Returns header for installed plugins
242
+ *
243
+ * @since 1.3.0
244
+ */
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
+ }
256
+
257
+ /**
258
+ * Available addon callback:
259
+ * - checkbox to enable
260
+ * - select field for cookie type
261
+ *
262
+ * @param $args
263
+ *
264
+ * @since 1.3.0
265
+ */
266
+ public function available_addon_callback( $args ) {
267
+ include COOKIEBOT_ADDONS_DIR . 'view/admin/settings/available-addon-callback.php';
268
+ }
269
+
270
+ /**
271
+ * Returns header for unavailable plugins
272
+ *
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
+ /**
280
+ * Unavailable addon callback
281
+ *
282
+ * @param $args
283
+ *
284
+ * @since 1.3.0
285
+ */
286
+ public function unavailable_addon_callback( $args ) {
287
+ $addon = $args['addon'];
288
+
289
+ ?>
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>
299
+ <?php
300
+ }
301
+
302
+ /**
303
+ * Build up settings page
304
+ *
305
+ * @param string $active_tab
306
+ *
307
+ * @since 1.3.0
308
+ */
309
+ public function setting_page( $active_tab = '' ) {
310
+ include COOKIEBOT_ADDONS_DIR . 'view/admin/settings/setting-page.php';
311
+ }
312
+
313
+ /**
314
+ * Post action hook after enabling the addon on the settings page.
315
+ *
316
+ * @param $old_value
317
+ * @param $value
318
+ * @param $option_name
319
+ *
320
+ * @since 2.2.0
321
+ */
322
+ public function post_hook_available_addons_update_option( $old_value, $value, $option_name ) {
323
+ if ( is_array( $value ) ) {
324
+ foreach ( $value as $addon_option_name => $addon_settings ) {
325
+ if ( isset( $addon_settings['enabled'] ) ) {
326
+ $this->settings_service->post_hook_after_enabling_addon_on_settings_page( $addon_option_name );
327
+ }
328
+ }
329
+ }
330
+ }
331
+ }
addons/controller/addons/add-to-any/add-to-any.php ADDED
@@ -0,0 +1,367 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
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;
8
+ use cookiebot_addons\lib\script_loader_tag\Script_Loader_Tag_Interface;
9
+ use cookiebot_addons\lib\buffer\Buffer_Output_Interface;
10
+
11
+ class Add_To_Any 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
+ protected $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_add_to_any' ), 5 );
65
+ }
66
+
67
+ /**
68
+ * Disable scripts if state not accepted
69
+ *
70
+ * @since 1.3.0
71
+ */
72
+ public function cookiebot_addon_add_to_any() {
73
+ // Check if Add To Any is loaded.
74
+ if ( ! function_exists( 'A2A_SHARE_SAVE_init' ) ) {
75
+ return;
76
+ }
77
+
78
+ // Check if Cookiebot is activated and active.
79
+ if ( ! function_exists( 'cookiebot_active' ) || ! cookiebot_active() ) {
80
+ return;
81
+ }
82
+
83
+ // consent is given
84
+ if ( $this->cookie_consent->are_cookie_states_accepted( $this->get_cookie_types() ) ) {
85
+ return;
86
+ }
87
+
88
+ if ( $this->is_remove_tag_enabled() ) {
89
+ add_filter( 'addtoany_script_disabled', '__return_true' );
90
+
91
+ /**
92
+ * Block head script
93
+ */
94
+ if ( has_action( 'wp_head', 'A2A_SHARE_SAVE_head_script' ) ) {
95
+ remove_action( 'wp_head', 'A2A_SHARE_SAVE_head_script' );
96
+ }
97
+
98
+ /**
99
+ * Block footer script
100
+ */
101
+ if ( has_action( 'wp_footer', 'A2A_SHARE_SAVE_footer_script' ) ) {
102
+ remove_action( 'wp_footer', 'A2A_SHARE_SAVE_footer_script' );
103
+ }
104
+
105
+ /**
106
+ * Block content addition
107
+ */
108
+ if ( has_action( 'pre_get_posts', 'A2A_SHARE_SAVE_pre_get_posts' ) ) {
109
+ remove_action( 'pre_get_posts', 'A2A_SHARE_SAVE_pre_get_posts' );
110
+ }
111
+ } else {
112
+ $this->buffer_output->add_tag( 'wp_head', 10, array(
113
+ 'data-cfasync' => $this->get_cookie_types(),
114
+ 'addtoany' => $this->get_cookie_types()
115
+ ), false );
116
+
117
+ $this->buffer_output->add_tag( 'wp_footer', 10, array(
118
+ 'data-cfasync' => $this->get_cookie_types(),
119
+ 'addtoany' => $this->get_cookie_types()
120
+ ), false );
121
+
122
+ $this->buffer_output->add_tag( 'pre_get_posts', 10, array(
123
+ 'GoogleAnalyticsObject' => $this->get_cookie_types(),
124
+ ), false );
125
+ }
126
+
127
+ // External js, so manipulate attributes
128
+ if ( has_action( 'wp_enqueue_scripts', 'A2A_SHARE_SAVE_enqueue_script' ) ) {
129
+ $this->script_loader_tag->add_tag( 'addtoany', $this->get_cookie_types() );
130
+ }
131
+ }
132
+
133
+ /**
134
+ * Return addon/plugin name
135
+ *
136
+ * @return string
137
+ *
138
+ * @since 1.3.0
139
+ */
140
+ public function get_addon_name() {
141
+ return 'addToAny Share Buttons';
142
+ }
143
+
144
+ /**
145
+ * Default placeholder content
146
+ *
147
+ * @return string
148
+ *
149
+ * @since 1.8.0
150
+ */
151
+ public function get_default_placeholder() {
152
+ return 'Please accept [renew_consent]%cookie_types[/renew_consent] cookies to enable Social Share buttons.';
153
+ }
154
+
155
+ /**
156
+ * Get placeholder content
157
+ *
158
+ * This function will check following features:
159
+ * - Current language
160
+ *
161
+ * @param $src
162
+ *
163
+ * @return bool|mixed
164
+ *
165
+ * @since 1.8.0
166
+ */
167
+ public function get_placeholder( $src = '' ) {
168
+ return $this->settings->get_placeholder( $this->get_option_name(), $this->get_default_placeholder(), cookiebot_addons_output_cookie_types( $this->get_cookie_types() ), $src );
169
+ }
170
+
171
+ /**
172
+ * Option name in the database
173
+ *
174
+ * @return string
175
+ *
176
+ * @since 1.3.0
177
+ */
178
+ public function get_option_name() {
179
+ return 'add_to_any';
180
+ }
181
+
182
+ /**
183
+ * Plugin file name
184
+ *
185
+ * @return string
186
+ *
187
+ * @since 1.3.0
188
+ */
189
+ public function get_plugin_file() {
190
+ return 'add-to-any/add-to-any.php';
191
+ }
192
+
193
+ /**
194
+ * Returns checked cookie types
195
+ * @return mixed
196
+ *
197
+ * @since 1.3.0
198
+ */
199
+ public function get_cookie_types() {
200
+ return $this->settings->get_cookie_types( $this->get_option_name(), $this->get_default_cookie_types() );
201
+ }
202
+
203
+ /**
204
+ * Returns default cookie types
205
+ * @return array
206
+ *
207
+ * @since 1.5.0
208
+ */
209
+ public function get_default_cookie_types() {
210
+ return array( 'marketing', 'statistics' );
211
+ }
212
+
213
+ /**
214
+ * Check if plugin is activated and checked in the backend
215
+ *
216
+ * @since 1.3.0
217
+ */
218
+ public function is_addon_enabled() {
219
+ return $this->settings->is_addon_enabled( $this->get_option_name() );
220
+ }
221
+
222
+ /**
223
+ * Checks if addon is installed
224
+ *
225
+ * @since 1.3.0
226
+ */
227
+ public function is_addon_installed() {
228
+ return $this->settings->is_addon_installed( $this->get_plugin_file() );
229
+ }
230
+
231
+ /**
232
+ * Checks if addon is activated
233
+ *
234
+ * @since 1.3.0
235
+ */
236
+ public function is_addon_activated() {
237
+ return $this->settings->is_addon_activated( $this->get_plugin_file() );
238
+ }
239
+
240
+ /**
241
+ * Retrieves current installed version of the addon
242
+ *
243
+ * @return bool
244
+ *
245
+ * @since 2.2.1
246
+ */
247
+ public function get_addon_version() {
248
+ return $this->settings->get_addon_version( $this->get_plugin_file() );
249
+ }
250
+
251
+ /**
252
+ * Checks if it does have custom placeholder content
253
+ *
254
+ * @return mixed
255
+ *
256
+ * @since 1.8.0
257
+ */
258
+ public function has_placeholder() {
259
+ return $this->settings->has_placeholder( $this->get_option_name() );
260
+ }
261
+
262
+ /**
263
+ * returns all placeholder contents
264
+ *
265
+ * @return mixed
266
+ *
267
+ * @since 1.8.0
268
+ */
269
+ public function get_placeholders() {
270
+ return $this->settings->get_placeholders( $this->get_option_name() );
271
+ }
272
+
273
+ /**
274
+ * Return true if the placeholder is enabled
275
+ *
276
+ * @return mixed
277
+ *
278
+ * @since 1.8.0
279
+ */
280
+ public function is_placeholder_enabled() {
281
+ return $this->settings->is_placeholder_enabled( $this->get_option_name() );
282
+ }
283
+
284
+ /**
285
+ * Adds extra information under the label
286
+ *
287
+ * @return string
288
+ *
289
+ * @since 1.8.0
290
+ */
291
+ public function get_extra_information() {
292
+ return '<p>' . __( 'Blocks embedded videos from Youtube, Twitter, Vimeo and Facebook.', 'cookiebot-addons' ) . '</p>';
293
+ }
294
+
295
+ /**
296
+ * Returns the url of WordPress SVN repository or another link where we can verify the plugin file.
297
+ *
298
+ * @return string
299
+ *
300
+ * @since 1.8.0
301
+ */
302
+ public function get_svn_url() {
303
+ return 'http://plugins.svn.wordpress.org/add-to-any/trunk/add-to-any.php';
304
+ }
305
+
306
+ /**
307
+ * Placeholder helper overlay in the settings page.
308
+ *
309
+ * @return string
310
+ *
311
+ * @since 1.8.0
312
+ */
313
+ public function get_placeholder_helper() {
314
+ 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>';
315
+ }
316
+
317
+ /**
318
+ * Returns true if addon has an option to remove tag instead of adding attributes
319
+ *
320
+ * @return boolean
321
+ *
322
+ * @since 2.1.0
323
+ */
324
+ public function has_remove_tag_option() {
325
+ return true;
326
+ }
327
+
328
+ /**
329
+ * Return true if the remove tag option is enabled
330
+ *
331
+ * @return mixed
332
+ *
333
+ * @since 2.1.0
334
+ */
335
+ public function is_remove_tag_enabled() {
336
+ return $this->settings->is_remove_tag_enabled( $this->get_option_name() );
337
+ }
338
+
339
+ /**
340
+ * Returns parent class or false
341
+ *
342
+ * @return string|bool
343
+ *
344
+ * @since 2.1.3
345
+ */
346
+ public function get_parent_class() {
347
+ return get_parent_class( $this );
348
+ }
349
+
350
+ /**
351
+ * Action after enabling the addon on the settings page
352
+ *
353
+ * @since 2.2.0
354
+ */
355
+ public function post_hook_after_enabling() {
356
+ //do nothing
357
+ }
358
+
359
+ /**
360
+ * Cookiebot plugin is deactivated
361
+ *
362
+ * @since 2.2.0
363
+ */
364
+ public function plugin_deactivated() {
365
+ //do nothing
366
+ }
367
+ }
addons/controller/addons/caos-host-analyticsjs-local-save-ga-local/caos-host-analyticsjs-local-save-ga-local.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\controller\addons\caos_host_analyticsjs_local_save_ga_local;
4
+
5
+ use cookiebot_addons\controller\addons\caos_host_analyticsjs_local\CAOS_Host_Analyticsjs_Local;
6
+
7
+ /**
8
+ * This is the older version of the plugin: CAOS_Host_Analyticsjs_Local
9
+ * Supports till the version: 2.0.0
10
+ *
11
+ * Class CAOS_Host_Analyticsjs_Local_Save_Ga_Local
12
+ * @package cookiebot_addons\controller\addons\caos_host_analyticsjs_local_save_ga_local
13
+ */
14
+ class CAOS_Host_Analyticsjs_Local_Save_Ga_Local extends CAOS_Host_Analyticsjs_Local {
15
+
16
+ /**
17
+ * plugin file name
18
+ *
19
+ * @return string
20
+ *
21
+ * @since 2.1.3
22
+ */
23
+ public function get_plugin_file() {
24
+ return 'host-analyticsjs-local/save-ga-local.php';
25
+ }
26
+
27
+ /**
28
+ * Returns the url of WordPress SVN repository or another link where we can verify the plugin file.
29
+ *
30
+ * @return string
31
+ *
32
+ * @since 2.1.3
33
+ */
34
+ public function get_svn_url() {
35
+ return 'http://plugins.svn.wordpress.org/host-analyticsjs-local/trunk/save-ga-local.php';
36
+ }
37
+ }
addons/controller/addons/caos-host-analyticsjs-local/caos-host-analyticsjs-local.php ADDED
@@ -0,0 +1,353 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\controller\addons\caos_host_analyticsjs_local;
4
+
5
+ use cookiebot_addons\controller\addons\Cookiebot_Addons_Interface;
6
+ use cookiebot_addons\lib\buffer\Buffer_Output_Interface;
7
+ use cookiebot_addons\lib\Cookie_Consent_Interface;
8
+ use cookiebot_addons\lib\script_loader_tag\Script_Loader_Tag_Interface;
9
+ use cookiebot_addons\lib\Settings_Service_Interface;
10
+
11
+ class CAOS_Host_Analyticsjs_Local 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
+ protected $cookie_consent;
33
+
34
+ /**
35
+ * @var Buffer_Output_Interface
36
+ *
37
+ * @since 1.3.0
38
+ */
39
+ protected $buffer_output;
40
+
41
+ /**
42
+ * Complete Analytics Optimization Suite (CAOS) (Host Analyticsjs Local) 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_host_analyticsjs_local' ), 5 );
65
+ }
66
+
67
+ /**
68
+ * Check for Host Analyticsjs Local action hooks
69
+ *
70
+ * @since 1.3.0
71
+ */
72
+ public function cookiebot_addon_host_analyticsjs_local() {
73
+ // Check if Cookiebot is activated and active.
74
+ if ( ! function_exists( 'cookiebot_active' ) || ! cookiebot_active() ) {
75
+ return;
76
+ }
77
+
78
+ // consent is given
79
+ if ( $this->cookie_consent->are_cookie_states_accepted( $this->get_cookie_types() ) ) {
80
+ return;
81
+ }
82
+
83
+ /* Priority need to be more than 0 so we are able to hook in before output begins */
84
+ $scriptPriority = $this->cookiebot_addon_host_analyticsjs_local_priority();
85
+ if ( $scriptPriority <= 0 ) {
86
+ //Force priority to 2
87
+ $scriptPriority = 2;
88
+ update_option( 'sgal_enqueue_order', $scriptPriority );
89
+ }
90
+
91
+ /**
92
+ * ga scripts are loaded in wp_footer priority is defined in option variable
93
+ */
94
+ if ( has_action( 'wp_footer', 'caos_analytics_render_tracking_code' ) || has_action( 'wp_footer', 'add_ga_header_script' ) ) {
95
+ /**
96
+ * Consent not given - no cache
97
+ */
98
+ $this->buffer_output->add_tag( 'wp_footer', $scriptPriority, array(
99
+ 'GoogleAnalyticsObject' => $this->get_cookie_types(),
100
+ ), false );
101
+ }
102
+
103
+ /**
104
+ * ga scripts are loaded in wp_head priority is defined in option variable
105
+ */
106
+ if ( has_action( 'wp_head', 'caos_analytics_render_tracking_code' ) || has_action( 'wp_head', 'add_ga_header_script' ) ) {
107
+ /**
108
+ * Consent not given - no cache
109
+ */
110
+ $this->buffer_output->add_tag( 'wp_head', $scriptPriority, array(
111
+ 'GoogleAnalyticsObject' => $this->get_cookie_types(),
112
+ ), false );
113
+ }
114
+
115
+ }
116
+
117
+ /**
118
+ * Get priority of script
119
+ *
120
+ * @return integer
121
+ *
122
+ * @since 1.3.0
123
+ */
124
+ public function cookiebot_addon_host_analyticsjs_local_priority() {
125
+ return ( esc_attr( get_option( 'sgal_enqueue_order' ) ) ) ? esc_attr( get_option( 'sgal_enqueue_order' ) ) : 0;
126
+ }
127
+
128
+ /**
129
+ * Return addon/plugin name
130
+ *
131
+ * @return string
132
+ *
133
+ * @since 1.3.0
134
+ */
135
+ public function get_addon_name() {
136
+ return 'Complete Analytics Optimization Suite (CAOS)';
137
+ }
138
+
139
+ /**
140
+ * Option name in the database
141
+ *
142
+ * @return string
143
+ *
144
+ * @since 1.3.0
145
+ */
146
+ public function get_option_name() {
147
+ return 'caos_host_analyticsjs_local';
148
+ }
149
+
150
+ /**
151
+ * plugin file name
152
+ *
153
+ * @return string
154
+ *
155
+ * @since 1.3.0
156
+ * @version 2.1.3
157
+ */
158
+ public function get_plugin_file() {
159
+ return 'host-analyticsjs-local/host-analyticsjs-local.php';
160
+ }
161
+
162
+ /**
163
+ * Returns checked cookie types
164
+ * @return array
165
+ *
166
+ * @since 1.3.0
167
+ */
168
+ public function get_cookie_types() {
169
+ return $this->settings->get_cookie_types( $this->get_option_name(), $this->get_default_cookie_types() );
170
+ }
171
+
172
+ /**
173
+ * Returns default cookie types
174
+ * @return array
175
+ *
176
+ * @since 1.5.0
177
+ */
178
+ public function get_default_cookie_types() {
179
+ return array( 'statistics' );
180
+ }
181
+
182
+ /**
183
+ * Check if plugin is activated and checked in the backend
184
+ *
185
+ * @since 1.3.0
186
+ */
187
+ public function is_addon_enabled() {
188
+ return $this->settings->is_addon_enabled( $this->get_option_name() );
189
+ }
190
+
191
+ /**
192
+ * Checks if addon is installed
193
+ *
194
+ * @since 1.3.0
195
+ */
196
+ public function is_addon_installed() {
197
+ return $this->settings->is_addon_installed( $this->get_plugin_file() );
198
+ }
199
+
200
+ /**
201
+ * Checks if addon is activated
202
+ *
203
+ * @since 1.3.0
204
+ */
205
+ public function is_addon_activated() {
206
+ return $this->settings->is_addon_activated( $this->get_plugin_file() );
207
+ }
208
+
209
+ /**
210
+ * Retrieves current installed version of the addon
211
+ *
212
+ * @return bool
213
+ *
214
+ * @since 2.2.1
215
+ */
216
+ public function get_addon_version() {
217
+ return $this->settings->get_addon_version( $this->get_plugin_file() );
218
+ }
219
+
220
+ /**
221
+ * Default placeholder content
222
+ *
223
+ * @return string
224
+ *
225
+ * @since 1.8.0
226
+ */
227
+ public function get_default_placeholder() {
228
+ return 'Please accept [renew_consent]%cookie_types[/renew_consent] cookies to enable tracking.';
229
+ }
230
+
231
+ /**
232
+ * Get placeholder content
233
+ *
234
+ * This function will check following features:
235
+ * - Current language
236
+ *
237
+ * @param $src
238
+ *
239
+ * @return bool|mixed
240
+ *
241
+ * @since 1.8.0
242
+ */
243
+ public function get_placeholder( $src = '' ) {
244
+ return $this->settings->get_placeholder( $this->get_option_name(), $this->get_default_placeholder(), cookiebot_addons_output_cookie_types( $this->get_cookie_types() ), $src );
245
+ }
246
+
247
+ /**
248
+ * Checks if it does have custom placeholder content
249
+ *
250
+ * @return mixed
251
+ *
252
+ * @since 1.8.0
253
+ */
254
+ public function has_placeholder() {
255
+ return $this->settings->has_placeholder( $this->get_option_name() );
256
+ }
257
+
258
+ /**
259
+ * returns all placeholder contents
260
+ *
261
+ * @return mixed
262
+ *
263
+ * @since 1.8.0
264
+ */
265
+ public function get_placeholders() {
266
+ return $this->settings->get_placeholders( $this->get_option_name() );
267
+ }
268
+
269
+ /**
270
+ * Return true if the placeholder is enabled
271
+ *
272
+ * @return mixed
273
+ *
274
+ * @since 1.8.0
275
+ */
276
+ public function is_placeholder_enabled() {
277
+ return $this->settings->is_placeholder_enabled( $this->get_option_name() );
278
+ }
279
+
280
+ /**
281
+ * Adds extra information under the label
282
+ *
283
+ * @return string
284
+ *
285
+ * @since 1.8.0
286
+ */
287
+ public function get_extra_information() {
288
+ return false;
289
+ }
290
+
291
+ /**
292
+ * Returns the url of WordPress SVN repository or another link where we can verify the plugin file.
293
+ *
294
+ * @return string
295
+ *
296
+ * @since 1.8.0
297
+ * @version 2.1.3
298
+ */
299
+ public function get_svn_url() {
300
+ return 'http://plugins.svn.wordpress.org/host-analyticsjs-local/trunk/host-analyticsjs-local.php';
301
+ }
302
+
303
+ /**
304
+ * Placeholder helper overlay in the settings page.
305
+ *
306
+ * @return string
307
+ *
308
+ * @since 1.8.0
309
+ */
310
+ public function get_placeholder_helper() {
311
+ 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>';
312
+ }
313
+
314
+ /**
315
+ * Returns true if addon has an option to remove tag instead of adding attributes
316
+ *
317
+ * @return boolean
318
+ *
319
+ * @since 2.1.0
320
+ */
321
+ public function has_remove_tag_option() {
322
+ return false;
323
+ }
324
+
325
+ /**
326
+ * Returns parent class or false
327
+ *
328
+ * @return string|bool
329
+ *
330
+ * @since 2.1.3
331
+ */
332
+ public function get_parent_class() {
333
+ return get_parent_class( $this );
334
+ }
335
+
336
+ /**
337
+ * Action after enabling the addon on the settings page
338
+ *
339
+ * @since 2.2.0
340
+ */
341
+ public function post_hook_after_enabling() {
342
+ //do nothing
343
+ }
344
+
345
+ /**
346
+ * Cookiebot plugin is deactivated
347
+ *
348
+ * @since 2.2.0
349
+ */
350
+ public function plugin_deactivated() {
351
+ //do nothing
352
+ }
353
+ }
addons/controller/addons/cookiebot-addons-interface.php ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\controller\addons;
4
+
5
+ use cookiebot_addons\lib\buffer\Buffer_Output_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
+
10
+ Interface Cookiebot_Addons_Interface {
11
+
12
+ /**
13
+ * Cookiebot_Addons_Interface constructor.
14
+ *
15
+ * @param Settings_Service_Interface $settings
16
+ * @param Script_Loader_Tag_Interface $script_loader_tag
17
+ * @param Cookie_Consent_Interface $cookie_consent
18
+ * @param Buffer_Output_Interface $buffer_output
19
+ */
20
+ public function __construct( Settings_Service_Interface $settings, Script_Loader_Tag_Interface $script_loader_tag, Cookie_Consent_Interface $cookie_consent, Buffer_Output_Interface $buffer_output );
21
+
22
+ /**
23
+ * Loads addon configuration
24
+ *
25
+ * @since 1.3.0
26
+ */
27
+ public function load_configuration();
28
+
29
+ /**
30
+ * Returns true if addon has an option to remove tag instead of adding attributes
31
+ *
32
+ * @return boolean
33
+ *
34
+ * @since 2.1.0
35
+ */
36
+ //public function has_remove_tag_option();
37
+
38
+ /**
39
+ * Return addon/plugin name
40
+ *
41
+ * @return string
42
+ *
43
+ * @since 1.3.0
44
+ */
45
+ public function get_addon_name();
46
+
47
+ /**
48
+ * Default placeholder content
49
+ *
50
+ * @return string
51
+ *
52
+ * @since 1.8.0
53
+ */
54
+ public function get_default_placeholder();
55
+
56
+ /**
57
+ * Get placeholder content
58
+ *
59
+ * This function will check following features:
60
+ * - Current language
61
+ *
62
+ * @param $src string
63
+ *
64
+ * @return bool|mixed
65
+ *
66
+ * @since 1.8.0
67
+ */
68
+ public function get_placeholder( $src = '' );
69
+
70
+ /**
71
+ * Option name in the database
72
+ *
73
+ * @return string
74
+ *
75
+ * @since 1.3.0
76
+ */
77
+ public function get_option_name();
78
+
79
+ /**
80
+ * Plugin file name
81
+ *
82
+ * @return string
83
+ *
84
+ * @since 1.3.0
85
+ */
86
+ public function get_plugin_file();
87
+
88
+ /**
89
+ * Returns checked cookie types
90
+ * @return mixed
91
+ *
92
+ * @since 1.3.0
93
+ */
94
+ public function get_cookie_types();
95
+
96
+ /**
97
+ * Returns default cookie types
98
+ * @return mixed
99
+ *
100
+ * @since 1.3.0
101
+ */
102
+ public function get_default_cookie_types();
103
+
104
+ /**
105
+ * Check if plugin is activated and checked in the backend
106
+ *
107
+ * @since 1.3.0
108
+ */
109
+ public function is_addon_enabled();
110
+
111
+ /**
112
+ * Checks if addon is installed
113
+ *
114
+ * @since 1.3.0
115
+ */
116
+ public function is_addon_installed();
117
+
118
+ /**
119
+ * Checks if addon is activated
120
+ *
121
+ * @since 1.3.0
122
+ */
123
+ public function is_addon_activated();
124
+
125
+ /**
126
+ * Retrieves current installed version of the addon
127
+ *
128
+ * @return bool
129
+ *
130
+ * @since 2.2.1
131
+ */
132
+ public function get_addon_version();
133
+
134
+ /**
135
+ * Checks if it does have custom placeholder content
136
+ *
137
+ * @return mixed
138
+ *
139
+ * @since 1.8.0
140
+ */
141
+ public function has_placeholder();
142
+
143
+ /**
144
+ * returns all placeholder contents
145
+ *
146
+ * @return mixed
147
+ *
148
+ * @since 1.8.0
149
+ */
150
+ public function get_placeholders();
151
+
152
+ /**
153
+ * Return true if the placeholder is enabled
154
+ *
155
+ * @return mixed
156
+ *
157
+ * @since 1.8.0
158
+ */
159
+ public function is_placeholder_enabled();
160
+
161
+ /**
162
+ * Adds extra information under the label
163
+ *
164
+ * @return string
165
+ *
166
+ * @since 1.8.0
167
+ */
168
+ public function get_extra_information();
169
+
170
+ /**
171
+ * Returns the url of WordPress SVN repository or another link where we can verify the plugin file.
172
+ *
173
+ * @return boolean
174
+ *
175
+ * @since 1.8.0
176
+ */
177
+ public function get_svn_url();
178
+
179
+ /**
180
+ * Placeholder helper overlay in the settings page.
181
+ *
182
+ * @return string
183
+ *
184
+ * @since 1.8.0
185
+ */
186
+ public function get_placeholder_helper();
187
+
188
+ /**
189
+ * Action after enabling the addon on the settings page
190
+ *
191
+ * @since 2.2.0
192
+ */
193
+ public function post_hook_after_enabling();
194
+
195
+ /**
196
+ * Cookiebot plugin is deactivated
197
+ *
198
+ * @since 2.2.0
199
+ */
200
+ public function plugin_deactivated();
201
+ }
addons/controller/addons/custom-facebook-feed-pro/custom-facebook-feed-pro.php ADDED
@@ -0,0 +1,331 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\controller\addons\custom_facebook_feed_pro;
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_Pro implements Cookiebot_Addons_Interface {
12
+
13
+ /**
14
+ * @var Settings_Service_Interface
15
+ *
16
+ * @since 2.1.4
17
+ */
18
+ protected $settings;
19
+
20
+ /**
21
+ * @var Script_Loader_Tag_Interface
22
+ *
23
+ * @since 2.1.4
24
+ */
25
+ protected $script_loader_tag;
26
+
27
+ /**
28
+ * @var Cookie_Consent_Interface
29
+ *
30
+ * @since 2.1.4
31
+ */
32
+ protected $cookie_consent;
33
+
34
+ /**
35
+ * @var Buffer_Output_Interface
36
+ *
37
+ * @since 2.1.4
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 2.1.4
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 2.1.4
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 2.1.4
75
+ */
76
+ public function cookiebot_addon_custom_facebook_feed() {
77
+ //Check if Custom Facebook Feed is loaded.
78
+ if ( ! shortcode_exists( 'custom-facebook-feed' ) ) {
79
+ return;
80
+ }
81
+ //Check if Cookiebot is activated and active.
82
+ if ( ! function_exists( 'cookiebot_active' ) || ! cookiebot_active() ) {
83
+ return;
84
+ }
85
+
86
+ // consent is given
87
+ if( $this->cookie_consent->are_cookie_states_accepted( $this->get_cookie_types() ) ) {
88
+ return;
89
+ }
90
+
91
+ //Remove cff_js action and replace it with our own
92
+ if ( has_action( 'wp_footer', 'cff_js' ) ) {
93
+ /**
94
+ * Consent not given - no cache
95
+ */
96
+ $this->buffer_output->add_tag( 'wp_footer', 10, array( 'cfflinkhashtags' => $this->get_cookie_types() ), false );
97
+ }
98
+
99
+ // External js, so manipulate attributes
100
+ if ( has_action( 'wp_enqueue_scripts', 'cff_scripts_method' ) ) {
101
+ /**
102
+ * Consent not given - no cache
103
+ */
104
+ $this->script_loader_tag->add_tag( 'cffscripts', $this->get_cookie_types(), false );
105
+ }
106
+ }
107
+
108
+ /**
109
+ * Return addon/plugin name
110
+ *
111
+ * @return string
112
+ *
113
+ * @since 2.1.4
114
+ */
115
+ public function get_addon_name() {
116
+ return 'Custom Facebook Feed Pro';
117
+ }
118
+
119
+ /**
120
+ * Option name in the database
121
+ *
122
+ * @return string
123
+ *
124
+ * @since 2.1.4
125
+ */
126
+ public function get_option_name() {
127
+ return 'custom_facebook_feed_pro';
128
+ }
129
+
130
+ /**
131
+ * Plugin file name
132
+ *
133
+ * @return string
134
+ *
135
+ * @since 2.1.4
136
+ */
137
+ public function get_plugin_file() {
138
+ return 'custom-facebook-feed-pro/custom-facebook-feed.php';
139
+ }
140
+
141
+ /**
142
+ * Returns checked cookie types
143
+ * @return mixed
144
+ *
145
+ * @since 2.1.4
146
+ */
147
+ public function get_cookie_types() {
148
+ return $this->settings->get_cookie_types( $this->get_option_name(), $this->get_default_cookie_types() );
149
+ }
150
+
151
+ /**
152
+ * Returns default cookie types
153
+ * @return array
154
+ *
155
+ * @since 1.5.0
156
+ */
157
+ public function get_default_cookie_types() {
158
+ return array( 'marketing' );
159
+ }
160
+
161
+ /**
162
+ * Check if plugin is activated and checked in the backend
163
+ *
164
+ * @since 2.1.4
165
+ */
166
+ public function is_addon_enabled() {
167
+ return $this->settings->is_addon_enabled( $this->get_option_name() );
168
+ }
169
+
170
+ /**
171
+ * Checks if addon is installed
172
+ *
173
+ * @since 2.1.4
174
+ */
175
+ public function is_addon_installed() {
176
+ return $this->settings->is_addon_installed( $this->get_plugin_file() );
177
+ }
178
+
179
+ /**
180
+ * Checks if addon is activated
181
+ *
182
+ * @since 2.1.4
183
+ */
184
+ public function is_addon_activated() {
185
+ return $this->settings->is_addon_activated( $this->get_plugin_file() );
186
+ }
187
+
188
+ /**
189
+ * Retrieves current installed version of the addon
190
+ *
191
+ * @return bool
192
+ *
193
+ * @since 2.2.1
194
+ */
195
+ public function get_addon_version() {
196
+ return $this->settings->get_addon_version( $this->get_plugin_file() );
197
+ }
198
+
199
+ /**
200
+ * Default placeholder content
201
+ *
202
+ * @return string
203
+ *
204
+ * @since 2.1.4
205
+ */
206
+ public function get_default_placeholder() {
207
+ return 'Please accept [renew_consent]%cookie_types[/renew_consent] cookies to watch this video.';
208
+ }
209
+
210
+ /**
211
+ * Get placeholder content
212
+ *
213
+ * This function will check following features:
214
+ * - Current language
215
+ *
216
+ * @param $src
217
+ *
218
+ * @return bool|mixed
219
+ *
220
+ * @since 2.1.4
221
+ */
222
+ public function get_placeholder( $src = '' ) {
223
+ return $this->settings->get_placeholder( $this->get_option_name(), $this->get_default_placeholder(), cookiebot_addons_output_cookie_types( $this->get_cookie_types() ), $src );
224
+ }
225
+
226
+ /**
227
+ * Checks if it does have custom placeholder content
228
+ *
229
+ * @return mixed
230
+ *
231
+ * @since 2.1.4
232
+ */
233
+ public function has_placeholder() {
234
+ return $this->settings->has_placeholder( $this->get_option_name() );
235
+ }
236
+
237
+ /**
238
+ * returns all placeholder contents
239
+ *
240
+ * @return mixed
241
+ *
242
+ * @since 2.1.4
243
+ */
244
+ public function get_placeholders() {
245
+ return $this->settings->get_placeholders( $this->get_option_name() );
246
+ }
247
+
248
+ /**
249
+ * Return true if the placeholder is enabled
250
+ *
251
+ * @return mixed
252
+ *
253
+ * @since 2.1.4
254
+ */
255
+ public function is_placeholder_enabled() {
256
+ return $this->settings->is_placeholder_enabled( $this->get_option_name() );
257
+ }
258
+
259
+ /**
260
+ * Adds extra information under the label
261
+ *
262
+ * @return string
263
+ *
264
+ * @since 2.1.4
265
+ */
266
+ public function get_extra_information() {
267
+ return false;
268
+ }
269
+
270
+ /**
271
+ * Returns the url of WordPress SVN repository or another link where we can verify the plugin file.
272
+ *
273
+ * @return string
274
+ *
275
+ * @since 2.1.4
276
+ */
277
+ public function get_svn_url() {
278
+ return false;
279
+ }
280
+
281
+ /**
282
+ * Placeholder helper overlay in the settings page.
283
+ *
284
+ * @return string
285
+ *
286
+ * @since 2.1.4
287
+ */
288
+ public function get_placeholder_helper() {
289
+ 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>';
290
+ }
291
+
292
+ /**
293
+ * Returns true if addon has an option to remove tag instead of adding attributes
294
+ *
295
+ * @return boolean
296
+ *
297
+ * @since 2.1.4
298
+ */
299
+ public function has_remove_tag_option() {
300
+ return false;
301
+ }
302
+
303
+ /**
304
+ * Returns parent class or false
305
+ *
306
+ * @return string|bool
307
+ *
308
+ * @since 2.1.4
309
+ */
310
+ public function get_parent_class() {
311
+ return get_parent_class( $this );
312
+ }
313
+
314
+ /**
315
+ * Action after enabling the addon on the settings page
316
+ *
317
+ * @since 2.2.0
318
+ */
319
+ public function post_hook_after_enabling() {
320
+ //do nothing
321
+ }
322
+
323
+ /**
324
+ * Cookiebot plugin is deactivated
325
+ *
326
+ * @since 2.2.0
327
+ */
328
+ public function plugin_deactivated() {
329
+ //do nothing
330
+ }
331
+ }
addons/controller/addons/custom-facebook-feed/custom-facebook-feed.php ADDED
@@ -0,0 +1,331 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
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
+ protected $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
+ //Check if Custom Facebook Feed is loaded.
78
+ if ( ! shortcode_exists( 'custom-facebook-feed' ) ) {
79
+ return;
80
+ }
81
+ //Check if Cookiebot is activated and active.
82
+ if ( ! function_exists( 'cookiebot_active' ) || ! cookiebot_active() ) {
83
+ return;
84
+ }
85
+
86
+ // consent is given
87
+ if( $this->cookie_consent->are_cookie_states_accepted( $this->get_cookie_types() ) ) {
88
+ return;
89
+ }
90
+
91
+ //Remove cff_js action and replace it with our own
92
+ if ( has_action( 'wp_footer', 'cff_js' ) ) {
93
+ /**
94
+ * Consent not given - no cache
95
+ */
96
+ $this->buffer_output->add_tag( 'wp_footer', 10, array( 'cfflinkhashtags' => $this->get_cookie_types() ), false );
97
+ }
98
+
99
+ // External js, so manipulate attributes
100
+ if ( has_action( 'wp_enqueue_scripts', 'cff_scripts_method' ) ) {
101
+ /**
102
+ * Consent not given - no cache
103
+ */
104
+ $this->script_loader_tag->add_tag( 'cffscripts', $this->get_cookie_types(), false );
105
+ }
106
+ }
107
+
108
+ /**
109
+ * Return addon/plugin name
110
+ *
111
+ * @return string
112
+ *
113
+ * @since 1.3.0
114
+ */
115
+ public function get_addon_name() {
116
+ return 'Custom Facebook Feed';
117
+ }
118
+
119
+ /**
120
+ * Option name in the database
121
+ *
122
+ * @return string
123
+ *
124
+ * @since 1.3.0
125
+ */
126
+ public function get_option_name() {
127
+ return 'custom_facebook_feed';
128
+ }
129
+
130
+ /**
131
+ * Plugin file name
132
+ *
133
+ * @return string
134
+ *
135
+ * @since 1.3.0
136
+ */
137
+ public function get_plugin_file() {
138
+ return 'custom-facebook-feed/custom-facebook-feed.php';
139
+ }
140
+
141
+ /**
142
+ * Returns checked cookie types
143
+ * @return mixed
144
+ *
145
+ * @since 1.3.0
146
+ */
147
+ public function get_cookie_types() {
148
+ return $this->settings->get_cookie_types( $this->get_option_name(), $this->get_default_cookie_types() );
149
+ }
150
+
151
+ /**
152
+ * Returns default cookie types
153
+ * @return array
154
+ *
155
+ * @since 1.5.0
156
+ */
157
+ public function get_default_cookie_types() {
158
+ return array( 'marketing' );
159
+ }
160
+
161
+ /**
162
+ * Check if plugin is activated and checked in the backend
163
+ *
164
+ * @since 1.3.0
165
+ */
166
+ public function is_addon_enabled() {
167
+ return $this->settings->is_addon_enabled( $this->get_option_name() );
168
+ }
169
+
170
+ /**
171
+ * Checks if addon is installed
172
+ *
173
+ * @since 1.3.0
174
+ */
175
+ public function is_addon_installed() {
176
+ return $this->settings->is_addon_installed( $this->get_plugin_file() );
177
+ }
178
+
179
+ /**
180
+ * Checks if addon is activated
181
+ *
182
+ * @since 1.3.0
183
+ */
184
+ public function is_addon_activated() {
185
+ return $this->settings->is_addon_activated( $this->get_plugin_file() );
186
+ }
187
+
188
+ /**
189
+ * Retrieves current installed version of the addon
190
+ *
191
+ * @return bool
192
+ *
193
+ * @since 2.2.1
194
+ */
195
+ public function get_addon_version() {
196
+ return $this->settings->get_addon_version( $this->get_plugin_file() );
197
+ }
198
+
199
+ /**
200
+ * Default placeholder content
201
+ *
202
+ * @return string
203
+ *
204
+ * @since 1.8.0
205
+ */
206
+ public function get_default_placeholder() {
207
+ return 'Please accept [renew_consent]%cookie_types[/renew_consent] cookies to watch this video.';
208
+ }
209
+
210
+ /**
211
+ * Get placeholder content
212
+ *
213
+ * This function will check following features:
214
+ * - Current language
215
+ *
216
+ * @param $src
217
+ *
218
+ * @return bool|mixed
219
+ *
220
+ * @since 1.8.0
221
+ */
222
+ public function get_placeholder( $src = '' ) {
223
+ return $this->settings->get_placeholder( $this->get_option_name(), $this->get_default_placeholder(), cookiebot_addons_output_cookie_types( $this->get_cookie_types() ), $src );
224
+ }
225
+
226
+ /**
227
+ * Checks if it does have custom placeholder content
228
+ *
229
+ * @return mixed
230
+ *
231
+ * @since 1.8.0
232
+ */
233
+ public function has_placeholder() {
234
+ return $this->settings->has_placeholder( $this->get_option_name() );
235
+ }
236
+
237
+ /**
238
+ * returns all placeholder contents
239
+ *
240
+ * @return mixed
241
+ *
242
+ * @since 1.8.0
243
+ */
244
+ public function get_placeholders() {
245
+ return $this->settings->get_placeholders( $this->get_option_name() );
246
+ }
247
+
248
+ /**
249
+ * Return true if the placeholder is enabled
250
+ *
251
+ * @return mixed
252
+ *
253
+ * @since 1.8.0
254
+ */
255
+ public function is_placeholder_enabled() {
256
+ return $this->settings->is_placeholder_enabled( $this->get_option_name() );
257
+ }
258
+
259
+ /**
260
+ * Adds extra information under the label
261
+ *
262
+ * @return string
263
+ *
264
+ * @since 1.8.0
265
+ */
266
+ public function get_extra_information() {
267
+ return false;
268
+ }
269
+
270
+ /**
271
+ * Returns the url of WordPress SVN repository or another link where we can verify the plugin file.
272
+ *
273
+ * @return string
274
+ *
275
+ * @since 1.8.0
276
+ */
277
+ public function get_svn_url() {
278
+ return 'http://plugins.svn.wordpress.org/custom-facebook-feed/trunk/custom-facebook-feed.php';
279
+ }
280
+
281
+ /**
282
+ * Placeholder helper overlay in the settings page.
283
+ *
284
+ * @return string
285
+ *
286
+ * @since 1.8.0
287
+ */
288
+ public function get_placeholder_helper() {
289
+ 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>';
290
+ }
291
+
292
+ /**
293
+ * Returns true if addon has an option to remove tag instead of adding attributes
294
+ *
295
+ * @return boolean
296
+ *
297
+ * @since 2.1.0
298
+ */
299
+ public function has_remove_tag_option() {
300
+ return false;
301
+ }
302
+
303
+ /**
304
+ * Returns parent class or false
305
+ *
306
+ * @return string|bool
307
+ *
308
+ * @since 2.1.3
309
+ */
310
+ public function get_parent_class() {
311
+ return get_parent_class( $this );
312
+ }
313
+
314
+ /**
315
+ * Action after enabling the addon on the settings page
316
+ *
317
+ * @since 2.2.0
318
+ */
319
+ public function post_hook_after_enabling() {
320
+ //do nothing
321
+ }
322
+
323
+ /**
324
+ * Cookiebot plugin is deactivated
325
+ *
326
+ * @since 2.2.0
327
+ */
328
+ public function plugin_deactivated() {
329
+ //do nothing
330
+ }
331
+ }
addons/controller/addons/embed-autocorrect/embed-autocorrect.php ADDED
@@ -0,0 +1,530 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\controller\addons\embed_autocorrect;
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 Embed_Autocorrect 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
+ protected $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_embed_autocorrect' ) );
69
+ }
70
+
71
+ /**
72
+ * Check for embed autocorrect action hooks
73
+ *
74
+ * @since 1.3.0
75
+ */
76
+ public function cookiebot_addon_embed_autocorrect() {
77
+ // Check if Cookiebot is activated and active.
78
+ if ( ! function_exists( 'cookiebot_active' ) || ! cookiebot_active() ) {
79
+ return;
80
+ }
81
+
82
+ // consent is given
83
+ if ( $this->cookie_consent->are_cookie_states_accepted( $this->get_cookie_types() ) ) {
84
+ return;
85
+ }
86
+
87
+ //add filters to handle autocorrection in content
88
+ add_filter( 'the_content', array(
89
+ $this,
90
+ 'cookiebot_addon_embed_autocorrect_content'
91
+ ), 1000 ); //Ensure it is executed as the last filter
92
+
93
+ //add filters to handle autocorrection in widget text
94
+ add_filter( 'widget_text', array(
95
+ $this,
96
+ 'cookiebot_addon_embed_autocorrect_content'
97
+ ), 1000 ); //Ensure it is executed as the last filter
98
+
99
+
100
+ //add fitler to handle video shortcodes
101
+ add_filter( 'wp_video_shortcode', array(
102
+ $this,
103
+ 'cookiebot_addon_embed_autocorrect_handle_video'
104
+ ), 1000 );
105
+
106
+ //add fitler to handle audio shortcodes
107
+ add_filter( 'wp_audio_shortcode', array(
108
+ $this,
109
+ 'cookiebot_addon_embed_autocorrect_handle_audio'
110
+ ), 1000 );
111
+
112
+ add_action( 'wp_head', array(
113
+ $this,
114
+ 'cookiebot_addon_embed_autocorrect_javascript'
115
+ ) );
116
+
117
+ }
118
+
119
+ /**
120
+ * Add javascript to handle videos as loaded
121
+ *
122
+ * @since 1.1.0
123
+ */
124
+ public function cookiebot_addon_embed_autocorrect_javascript() {
125
+ $library = apply_filters( 'wp_video_shortcode_library', 'mediaelement' );
126
+ if($library === 'mediaelement') {
127
+ ?><style type="text/css">video.wp-video-shortcode__disabled,audio.wp-audio-shortcode__disabled { display:none; }</style>
128
+ <script>
129
+ window.addEventListener('CookiebotOnTagsExecuted',function (e) {
130
+ if(<?php echo 'Cookiebot.consent.'.implode(' && Cookiebot.consent.',$this->get_cookie_types()); ?>) {
131
+ jQuery('.wp-video-shortcode__disabled').addClass('wp-video-shortcode').removeClass('wp-video-shortcode__disabled');
132
+ jQuery('.wp-audio-shortcode__disabled').addClass('wp-audio-shortcode').removeClass('wp-audio-shortcode__disabled');
133
+ window.wp.mediaelement.initialize();
134
+ }
135
+ }, false );
136
+ </script><?php
137
+ }
138
+ }
139
+
140
+
141
+ /**
142
+ * Autocorrection of Vimeo and Youtube tags to make them GDPR compatible
143
+ *
144
+ * @since 1.1.0
145
+ */
146
+ public function cookiebot_addon_embed_autocorrect_content( $content ) {
147
+ //Make sure Cookiebot is active and the user has enabled autocorrection
148
+
149
+ preg_match_all( '|<div[^>]*id=\"fb-root\">.*?</blockquote>|si', $content, $matches );
150
+ foreach ( $matches[0] as $match ) {
151
+ //Find src.
152
+ preg_match( '|<a href=\"([^\"]*)\">([^<]*)</a></p></blockquote>|', $match, $matchSrc );
153
+ $src = $matchSrc[1];
154
+
155
+ //Replace - and add cookie consent notice.
156
+ $adjusted = str_replace( '<script>', '<script type="text/plain" data-cookieconsent="' . cookiebot_addons_output_cookie_types( $this->get_cookie_types() ) . '">', $match );
157
+
158
+ /**
159
+ * Generate placeholder
160
+ */
161
+ $placeholder = $this->generate_placeholder_with_src( apply_filters( 'cookiebot_addons_embed_source', $src ) );
162
+
163
+ /**
164
+ * Modify placeholder by Filter
165
+ *
166
+ * @param $placeholder string Current placeholder text
167
+ * @param $src string Source attribute from the embedded video
168
+ * @param $this array Array of required cookie types
169
+ */
170
+ $placeholder = apply_filters( 'cookiebot_addons_embed_placeholder', $placeholder, $src, $this->get_cookie_types() );
171
+
172
+ $adjusted .= $placeholder;
173
+ $content = str_replace( $match, $adjusted, $content );
174
+
175
+ }
176
+ unset( $matches );
177
+
178
+ preg_match_all( '|<blockquote[^>]*class=\"twitter-tweet\"[^>]*>.*?</script></p>|si', $content, $matches );
179
+ foreach ( $matches[0] as $match ) {
180
+ //Find src.
181
+ preg_match( '|<a href=\"([^\"]*)\">([^<]*)</a></p></blockquote>|', $match, $matchSrc );
182
+ $src = $matchSrc[1];
183
+
184
+ //Replace - and add cookie consent notice.
185
+ $adjusted = str_replace( '<script ', '<script type="text/plain" data-cookieconsent="' . cookiebot_addons_output_cookie_types( $this->get_cookie_types() ) . '" ', $match );
186
+
187
+ /**
188
+ * Generate placeholder
189
+ */
190
+ $placeholder = $this->generate_placeholder_with_src( apply_filters( 'cookiebot_addons_embed_source', $src ) );
191
+
192
+ /**
193
+ * Modify placeholder by Filter
194
+ *
195
+ * @param $placeholder string Current placeholder text
196
+ * @param $src string Source attribute from the embedded video
197
+ * @param $this array Array of required cookie types
198
+ */
199
+ $placeholder = apply_filters( 'cookiebot_addons_embed_placeholder', $placeholder, $src, $this->get_cookie_types() );
200
+
201
+ $adjusted .= $placeholder;
202
+ $content = str_replace( $match, $adjusted, $content );
203
+
204
+ }
205
+ unset( $matches );
206
+
207
+
208
+ //Match all youtube, vimeo and facebook iframes.
209
+ preg_match_all( '/<iframe[^>]* src=("|\')[^("|\')](facebook\.com|youtu\.be|youtube\.com|youtube-nocookie\.com|player\.vimeo\.com)*[^>]*>.*?<\/iframe>/mi', $content, $matches );
210
+
211
+ foreach ( $matches[0] as $x=>$match ) {
212
+ /**
213
+ * Get the source attribute value
214
+ */
215
+ $start = strpos( $match, ' src=' ) + 6;
216
+ $end = strpos( $match, $matches[1][$x], $start );
217
+ $src = substr( $match, $start, $end - $start );
218
+
219
+
220
+ //Replace - and add cookie consent notice.
221
+ $adjusted = str_replace( ' src=', ' data-cookieconsent="' . cookiebot_addons_output_cookie_types( $this->get_cookie_types() ) . '" data-src=', $match );
222
+
223
+ /**
224
+ * Generate placeholder
225
+ */
226
+ $placeholder = $this->generate_placeholder_with_src( apply_filters( 'cookiebot_addons_embed_source', $src ) );
227
+
228
+ /**
229
+ * Modify placeholder by Filter
230
+ *
231
+ * @param $placeholder string Current placeholder text
232
+ * @param $src string Source attribute from the embedded video
233
+ * @param $this array Array of required cookie types
234
+ */
235
+ $placeholder = apply_filters( 'cookiebot_addons_embed_placeholder', $placeholder, $src, $this->get_cookie_types() );
236
+
237
+ $adjusted .= $placeholder;
238
+ $content = str_replace( $match, $adjusted, $content );
239
+ }
240
+
241
+
242
+
243
+
244
+
245
+ return $content;
246
+ }
247
+
248
+ /**
249
+ * Implementation of filter wp_video_shortcode - fixing code for cookiebot.
250
+ */
251
+ public function cookiebot_addon_embed_autocorrect_handle_video($output, $atts, $video, $post_id, $library) {
252
+ /**
253
+ * Generate placeholder
254
+ */
255
+ $placeholder = $this->generate_placeholder_with_src( apply_filters( 'cookiebot_addons_embed_source', $src ) );
256
+ $placeholder = apply_filters( 'cookiebot_addons_embed_placeholder', $placeholder, $src, $this->get_cookie_types() );
257
+
258
+
259
+ $output = str_replace( 'wp-video-shortcode','wp-video-shortcode__disabled', $output );
260
+ $output = str_replace( ' src=', ' data-cookieconsent="' . cookiebot_addons_output_cookie_types( $this->get_cookie_types() ) . '" data-src=', $output );
261
+ $output.= $placeholder;
262
+ return $output;
263
+ }
264
+
265
+ /**
266
+ * Implementation of filter wp_audio_shortcode - fixing code for cookiebot.
267
+ */
268
+ public function cookiebot_addon_embed_autocorrect_handle_audio($output, $atts, $video, $post_id, $library) {
269
+ /**
270
+ * Generate placeholder
271
+ */
272
+ $placeholder = $this->generate_placeholder_with_src( apply_filters( 'cookiebot_addons_embed_source', $src ) );
273
+ $placeholder = apply_filters( 'cookiebot_addons_embed_placeholder', $placeholder, $src, $this->get_cookie_types() );
274
+
275
+ $output = str_replace( 'wp-audio-shortcode','wp-audio-shortcode__disabled', $output );
276
+ $output = str_replace( ' src=', ' data-cookieconsent="' . cookiebot_addons_output_cookie_types( $this->get_cookie_types() ) . '" data-src=', $output );
277
+ $output.= $placeholder;
278
+ return $output;
279
+ }
280
+
281
+ /**
282
+ * Generates placeholder for given source
283
+ *
284
+ * @param $src
285
+ *
286
+ * @return string
287
+ */
288
+ public function generate_placeholder_with_src( $src = '' ) {
289
+ $cookieContentNotice = '<div class="cookieconsent-optout-' . cookiebot_addons_get_one_cookie_type( $this->get_cookie_types() ) . '">';
290
+ $cookieContentNotice .= $this->get_placeholder( $src );
291
+ $cookieContentNotice .= '</div>';
292
+
293
+ return $cookieContentNotice;
294
+ }
295
+
296
+ /**
297
+ * Return addon/plugin name
298
+ *
299
+ * @return string
300
+ *
301
+ * @since 1.3.0
302
+ */
303
+ public function get_addon_name() {
304
+ return 'Embed autocorrect';
305
+ }
306
+
307
+ /**
308
+ * Option name in the database
309
+ *
310
+ * @return string
311
+ *
312
+ * @since 1.3.0
313
+ */
314
+ public function get_option_name() {
315
+ return 'embed_autocorrect';
316
+ }
317
+
318
+ /**
319
+ * Plugin file path
320
+ *
321
+ * @return string
322
+ *
323
+ * @since 1.3.0
324
+ */
325
+ public function get_plugin_file() {
326
+ return false;
327
+ }
328
+
329
+ /**
330
+ * Returns checked cookie types
331
+ * @return mixed
332
+ *
333
+ * @since 1.3.0
334
+ */
335
+ public function get_cookie_types() {
336
+ return $this->settings->get_cookie_types( $this->get_option_name(), $this->get_default_cookie_types() );
337
+ }
338
+
339
+ /**
340
+ * Returns default cookie types
341
+ * @return array
342
+ *
343
+ * @since 1.5.0
344
+ */
345
+ public function get_default_cookie_types() {
346
+ return array( 'marketing', 'statistics' );
347
+ }
348
+
349
+ /**
350
+ * Check if plugin is activated and checked in the backend
351
+ *
352
+ * @since 1.3.0
353
+ */
354
+ public function is_addon_enabled() {
355
+ return $this->settings->is_addon_enabled( $this->get_option_name() );
356
+ }
357
+
358
+ /**
359
+ * Checks if addon is installed
360
+ *
361
+ * @since 1.3.0
362
+ */
363
+ public function is_addon_installed() {
364
+ return $this->settings->is_addon_installed( $this->get_plugin_file() );
365
+ }
366
+
367
+ /**
368
+ * Checks if addon is activated
369
+ *
370
+ * @since 1.3.0
371
+ */
372
+ public function is_addon_activated() {
373
+ return $this->settings->is_addon_activated( $this->get_plugin_file() );
374
+ }
375
+
376
+ /**
377
+ * Retrieves current installed version of the addon
378
+ *
379
+ * @return bool
380
+ *
381
+ * @since 2.2.1
382
+ */
383
+ public function get_addon_version() {
384
+ return false;
385
+ }
386
+
387
+ /**
388
+ * Default placeholder content
389
+ *
390
+ * @return string
391
+ *
392
+ * @since 1.8.0
393
+ */
394
+ public function get_default_placeholder() {
395
+ return 'Please accept [renew_consent]%cookie_types[/renew_consent] cookies to watch this video.';
396
+ }
397
+
398
+ /**
399
+ * Get placeholder content
400
+ *
401
+ * This function will check following features:
402
+ * - Current language
403
+ *
404
+ * @param $src
405
+ *
406
+ * @return bool|mixed
407
+ *
408
+ * @since 1.8.0
409
+ */
410
+ public function get_placeholder( $src = '' ) {
411
+ return $this->settings->get_placeholder( $this->get_option_name(), $this->get_default_placeholder(), cookiebot_addons_output_cookie_types( $this->get_cookie_types() ), $src );
412
+ }
413
+
414
+ /**
415
+ * Checks if it does have custom placeholder content
416
+ *
417
+ * @return mixed
418
+ *
419
+ * @since 1.8.0
420
+ */
421
+ public function has_placeholder() {
422
+ return $this->settings->has_placeholder( $this->get_option_name() );
423
+ }
424
+
425
+ /**
426
+ * returns all placeholder contents
427
+ *
428
+ * @return mixed
429
+ *
430
+ * @since 1.8.0
431
+ */
432
+ public function get_placeholders() {
433
+ return $this->settings->get_placeholders( $this->get_option_name() );
434
+ }
435
+
436
+ /**
437
+ * Return true if the placeholder is enabled
438
+ *
439
+ * @return mixed
440
+ *
441
+ * @since 1.8.0
442
+ */
443
+ public function is_placeholder_enabled() {
444
+ return $this->settings->is_placeholder_enabled( $this->get_option_name() );
445
+ }
446
+
447
+ /**
448
+ * Adds extra information under the label
449
+ *
450
+ * @return string
451
+ *
452
+ * @since 1.8.0
453
+ */
454
+ public function get_extra_information() {
455
+ return '<p>' . __( 'Blocks embedded videos from Youtube, Twitter, Vimeo and Facebook.', 'cookiebot-addons' ) . '</p>';
456
+ }
457
+
458
+ /**
459
+ * Returns the url of WordPress SVN repository or another link where we can verify the plugin file.
460
+ *
461
+ * @return boolean
462
+ *
463
+ * @since 1.8.0
464
+ */
465
+ public function get_svn_url() {
466
+ return false;
467
+ }
468
+
469
+ /**
470
+ * Placeholder helper overlay in the settings page.
471
+ *
472
+ * @return string
473
+ *
474
+ * @since 1.8.0
475
+ */
476
+ public function get_placeholder_helper() {
477
+ return '<p>Merge tags you can use in the placeholder text:</p><ul><li>%src - video source</li><li>%cookie_types - Lists required cookie types</li><li>[renew_consent]text[/renew_consent] - link to display cookie settings in the frontend</li></ul>';
478
+ }
479
+
480
+ /**
481
+ * Returns true if addon has an option to remove tag instead of adding attributes
482
+ *
483
+ * @return boolean
484
+ *
485
+ * @since 2.1.0
486
+ */
487
+ public function has_remove_tag_option() {
488
+ return false;
489
+ }
490
+
491
+ /**
492
+ * Return true if the remove tag option is enabled
493
+ *
494
+ * @return mixed
495
+ *
496
+ * @since 2.1.0
497
+ */
498
+ public function is_remove_tag_enabled() {
499
+ return $this->settings->is_remove_tag_enabled( $this->get_option_name() );
500
+ }
501
+
502
+ /**
503
+ * Returns parent class or false
504
+ *
505
+ * @return string|bool
506
+ *
507
+ * @since 2.1.3
508
+ */
509
+ public function get_parent_class() {
510
+ return get_parent_class( $this );
511
+ }
512
+
513
+ /**
514
+ * Action after enabling the addon on the settings page
515
+ *
516
+ * @since 2.2.0
517
+ */
518
+ public function post_hook_after_enabling() {
519
+ //do nothing
520
+ }
521
+
522
+ /**
523
+ * Cookiebot plugin is deactivated
524
+ *
525
+ * @since 2.2.0
526
+ */
527
+ public function plugin_deactivated() {
528
+ //do nothing
529
+ }
530
+ }
addons/controller/addons/facebook-for-woocommerce/facebook-for-woocommerce.php ADDED
@@ -0,0 +1,373 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\controller\addons\facebook_for_woocommerce;
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 Facebook_For_Woocommerce implements Cookiebot_Addons_Interface {
12
+ /**
13
+ * @var Settings_Service_Interface
14
+ *
15
+ * @since 1.3.0
16
+ */
17
+ protected $settings;
18
+
19
+ /**
20
+ * @var Script_Loader_Tag_Interface
21
+ *
22
+ * @since 1.3.0
23
+ */
24
+ protected $script_loader_tag;
25
+
26
+ /**
27
+ * @var Cookie_Consent_Interface
28
+ *
29
+ * @since 1.3.0
30
+ */
31
+ protected $cookie_consent;
32
+
33
+ /**
34
+ * @var Buffer_Output_Interface
35
+ *
36
+ * @since 1.3.0
37
+ */
38
+ protected $buffer_output;
39
+
40
+ /**
41
+ * Jetpack constructor.
42
+ *
43
+ * @param $settings Settings_Service_Interface
44
+ * @param $script_loader_tag Script_Loader_Tag_Interface
45
+ * @param $cookie_consent Cookie_Consent_Interface
46
+ * @param $buffer_output Buffer_Output_Interface
47
+ *
48
+ * @since 1.2.0
49
+ */
50
+ public function __construct( Settings_Service_Interface $settings, Script_Loader_Tag_Interface $script_loader_tag, Cookie_Consent_Interface $cookie_consent, Buffer_Output_Interface $buffer_output ) {
51
+ $this->settings = $settings;
52
+ $this->script_loader_tag = $script_loader_tag;
53
+ $this->cookie_consent = $cookie_consent;
54
+ $this->buffer_output = $buffer_output;
55
+ }
56
+
57
+ /**
58
+ * Loads addon configuration
59
+ *
60
+ * @since 1.3.0
61
+ */
62
+ public function load_configuration() {
63
+ /**
64
+ * We add the action after wp_loaded and replace the original GA Google
65
+ * Analytics action with our own adjusted version.
66
+ */
67
+ add_action( 'wp_loaded', array( $this, 'cookiebot_addon_facebook_for_woocommerce_tracking_code' ), 5 );
68
+ }
69
+
70
+ /**
71
+ * Manipulate the scripts if they are loaded.
72
+ *
73
+ * @since 1.3.0
74
+ */
75
+ public function cookiebot_addon_facebook_for_woocommerce_tracking_code() {
76
+ //Check Facebook for Wooocommerce is active
77
+ if ( ! class_exists( 'WC_Facebookcommerce' ) ) {
78
+ return;
79
+ }
80
+
81
+ /** Check if consent is given */
82
+ if( $this->cookie_consent->are_cookie_states_accepted( $this->get_cookie_types() ) ) {
83
+ return;
84
+ }
85
+
86
+
87
+ $this->buffer_output->add_tag( 'woocommerce_after_single_product', 2, array(
88
+ 'fbq(\'ViewContent\'' => $this->get_cookie_types()
89
+ ), false );
90
+
91
+ $this->buffer_output->add_tag( 'woocommerce_after_shop_loop', 10, array(
92
+ 'fbq(\'ViewCategory\'' => $this->get_cookie_types()
93
+ ), false );
94
+
95
+ $this->buffer_output->add_tag( 'pre_get_posts', 10, array(
96
+ 'fbq(\'Search\'' => $this->get_cookie_types()
97
+ ), false );
98
+
99
+ $this->buffer_output->add_tag( 'woocommerce_after_cart', 10, array(
100
+ 'fbq(\'AddToCart\'' => $this->get_cookie_types()
101
+ ), false );
102
+
103
+ $this->buffer_output->add_tag( 'woocommerce_add_to_cart', 2, array(
104
+ 'fbq(\'AddToCart\'' => $this->get_cookie_types()
105
+ ), false );
106
+
107
+ $this->buffer_output->add_tag( 'wc_ajax_fb_inject_add_to_cart_event', 2, array(
108
+ 'fbq(\'AddToCart\'' => $this->get_cookie_types()
109
+ ), false );
110
+
111
+ $this->buffer_output->add_tag( 'woocommerce_after_checkout_form', 10, array(
112
+ 'fbq(\'InitiateCheckout\'' => $this->get_cookie_types()
113
+ ), false );
114
+
115
+ $this->buffer_output->add_tag( 'woocommerce_thankyou', 2, array(
116
+ 'fbq(\'Purchase\'' => $this->get_cookie_types()
117
+ ), false );
118
+
119
+ $this->buffer_output->add_tag( 'woocommerce_payment_complete', 2, array(
120
+ 'fbq(\'Purchase\'' => $this->get_cookie_types()
121
+ ), false );
122
+
123
+ /**
124
+ * inject base pixel
125
+ */
126
+ //We always need to remove this untill consent is given - because we can force no execution before consent it given
127
+ cookiebot_addons_remove_class_action( 'wp_footer', 'WC_Facebookcommerce_EventsTracker', 'inject_base_pixel_noscript' );
128
+
129
+ if( $this->is_remove_tag_enabled() ) {
130
+ cookiebot_addons_remove_class_action( 'wp_head', 'WC_Facebookcommerce_EventsTracker', 'inject_base_pixel' );
131
+ }
132
+ else {
133
+ $this->buffer_output->add_tag( 'wp_head', 10, array(
134
+ 'fbq(\'track\',' => $this->get_cookie_types()
135
+ ), false );
136
+ }
137
+ }
138
+
139
+ /**
140
+ * Return addon/plugin name
141
+ *
142
+ * @return string
143
+ *
144
+ * @since 1.3.0
145
+ */
146
+ public function get_addon_name() {
147
+ return 'Facebook For WooCommerce';
148
+ }
149
+
150
+ /**
151
+ * Default placeholder content
152
+ *
153
+ * @return string
154
+ *
155
+ * @since 1.8.0
156
+ */
157
+ public function get_default_placeholder() {
158
+ return 'Please accept [renew_consent]%cookie_types[/renew_consent] cookies to enable facebook shopping feature.';
159
+ }
160
+
161
+ /**
162
+ * Get placeholder content
163
+ *
164
+ * This function will check following features:
165
+ * - Current language
166
+ *
167
+ * @param $src
168
+ *
169
+ * @return bool|mixed
170
+ *
171
+ * @since 1.8.0
172
+ */
173
+ public function get_placeholder( $src = '' ) {
174
+ return $this->settings->get_placeholder( $this->get_option_name(), $this->get_default_placeholder(), cookiebot_addons_output_cookie_types( $this->get_cookie_types() ), $src );
175
+ }
176
+
177
+ /**
178
+ * Option name in the database
179
+ *
180
+ * @return string
181
+ *
182
+ * @since 1.3.0
183
+ */
184
+ public function get_option_name() {
185
+ return 'facebook_for_woocommerce';
186
+ }
187
+
188
+ /**
189
+ * Plugin file name
190
+ *
191
+ * @return string
192
+ *
193
+ * @since 1.3.0
194
+ */
195
+ public function get_plugin_file() {
196
+ return 'facebook-for-woocommerce/facebook-for-woocommerce.php';
197
+ }
198
+
199
+ /**
200
+ * Returns checked cookie types
201
+ * @return mixed
202
+ *
203
+ * @since 1.3.0
204
+ */
205
+ public function get_cookie_types() {
206
+ return $this->settings->get_cookie_types( $this->get_option_name(), $this->get_default_cookie_types() );
207
+ }
208
+
209
+ /**
210
+ * Returns default cookie types
211
+ * @return array
212
+ *
213
+ * @since 1.5.0
214
+ */
215
+ public function get_default_cookie_types() {
216
+ return array( 'marketing' );
217
+ }
218
+
219
+ /**
220
+ * Check if plugin is activated and checked in the backend
221
+ *
222
+ * @since 1.3.0
223
+ */
224
+ public function is_addon_enabled() {
225
+ return $this->settings->is_addon_enabled( $this->get_option_name() );
226
+ }
227
+
228
+ /**
229
+ * Checks if addon is installed
230
+ *
231
+ * @since 1.3.0
232
+ */
233
+ public function is_addon_installed() {
234
+ return $this->settings->is_addon_installed( $this->get_plugin_file() );
235
+ }
236
+
237
+ /**
238
+ * Checks if addon is activated
239
+ *
240
+ * @since 1.3.0
241
+ */
242
+ public function is_addon_activated() {
243
+ return $this->settings->is_addon_activated( $this->get_plugin_file() );
244
+ }
245
+
246
+ /**
247
+ * Retrieves current installed version of the addon
248
+ *
249
+ * @return bool
250
+ *
251
+ * @since 2.2.1
252
+ */
253
+ public function get_addon_version() {
254
+ return $this->settings->get_addon_version( $this->get_plugin_file() );
255
+ }
256
+
257
+ /**
258
+ * Checks if it does have custom placeholder content
259
+ *
260
+ * @return mixed
261
+ *
262
+ * @since 1.8.0
263
+ */
264
+ public function has_placeholder() {
265
+ return $this->settings->has_placeholder( $this->get_option_name() );
266
+ }
267
+
268
+ /**
269
+ * returns all placeholder contents
270
+ *
271
+ * @return mixed
272
+ *
273
+ * @since 1.8.0
274
+ */
275
+ public function get_placeholders() {
276
+ return $this->settings->get_placeholders( $this->get_option_name() );
277
+ }
278
+
279
+ /**
280
+ * Return true if the placeholder is enabled
281
+ *
282
+ * @return mixed
283
+ *
284
+ * @since 1.8.0
285
+ */
286
+ public function is_placeholder_enabled() {
287
+ return $this->settings->is_placeholder_enabled( $this->get_option_name() );
288
+ }
289
+
290
+ /**
291
+ * Adds extra information under the label
292
+ *
293
+ * @return string
294
+ *
295
+ * @since 1.8.0
296
+ */
297
+ public function get_extra_information() {
298
+
299
+ }
300
+
301
+ /**
302
+ * Returns the url of WordPress SVN repository or another link where we can verify the plugin file.
303
+ *
304
+ * @return string
305
+ *
306
+ * @since 1.8.0
307
+ */
308
+ public function get_svn_url() {
309
+ return 'https://github.com/facebookincubator/facebook-for-woocommerce/blob/master/facebook-commerce.php';
310
+ }
311
+
312
+ /**
313
+ * Placeholder helper overlay in the settings page.
314
+ *
315
+ * @return string
316
+ *
317
+ * @since 1.8.0
318
+ */
319
+ public function get_placeholder_helper() {
320
+ 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>';
321
+ }
322
+
323
+ /**
324
+ * Returns true if addon has an option to remove tag instead of adding attributes
325
+ *
326
+ * @return boolean
327
+ *
328
+ * @since 2.1.0
329
+ */
330
+ public function has_remove_tag_option() {
331
+ return true;
332
+ }
333
+
334
+ /**
335
+ * Return true if the remove tag option is enabled
336
+ *
337
+ * @return mixed
338
+ *
339
+ * @since 2.1.0
340
+ */
341
+ public function is_remove_tag_enabled() {
342
+ return $this->settings->is_remove_tag_enabled( $this->get_option_name() );
343
+ }
344
+
345
+ /**
346
+ * Returns parent class or false
347
+ *
348
+ * @return string|bool
349
+ *
350
+ * @since 2.1.3
351
+ */
352
+ public function get_parent_class() {
353
+ return get_parent_class( $this );
354
+ }
355
+
356
+ /**
357
+ * Action after enabling the addon on the settings page
358
+ *
359
+ * @since 2.2.0
360
+ */
361
+ public function post_hook_after_enabling() {
362
+ //do nothing
363
+ }
364
+
365
+ /**
366
+ * Cookiebot plugin is deactivated
367
+ *
368
+ * @since 2.2.0
369
+ */
370
+ public function plugin_deactivated() {
371
+ //do nothing
372
+ }
373
+ }
addons/controller/addons/ga-google-analytics/ga-google-analytics.php ADDED
@@ -0,0 +1,337 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\controller\addons\ga_google_analytics;
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 Ga_Google_Analytics 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
+ protected $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_ga_google_analytics' ), 5 );
69
+ }
70
+
71
+ /**
72
+ * Manipulate the scripts if they are loaded.
73
+ *
74
+ * @version 1.3.0
75
+ * @since 1.1.0
76
+ */
77
+ public function cookiebot_addon_ga_google_analytics() {
78
+ //Check if GA Google Analytics is loaded.
79
+ if ( ! function_exists( 'ga_google_analytics_init' ) ) {
80
+ return;
81
+ }
82
+ //Check if Cookiebot is activated and active.
83
+ if ( ! function_exists( 'cookiebot_active' ) || ! cookiebot_active() ) {
84
+ return;
85
+ }
86
+
87
+ // consent is given
88
+ if( $this->cookie_consent->are_cookie_states_accepted( $this->get_cookie_types() ) ) {
89
+ return;
90
+ }
91
+
92
+ //Remove GA Google action and replace it with our own
93
+ if ( has_action( 'wp_head', 'ga_google_analytics_tracking_code' ) ) {
94
+ $this->buffer_output->add_tag( 'wp_head', 10, array(
95
+ 'gtag' => $this->get_cookie_types(),
96
+ 'google-analytics' => $this->get_cookie_types(),
97
+ '_gaq' => $this->get_cookie_types(),
98
+ 'www.googletagmanager.com/gtag/js?id=' => $this->get_cookie_types()
99
+ ), false );
100
+
101
+ } elseif ( has_action( 'wp_footer', 'ga_google_analytics_tracking_code' ) ) {
102
+ /**
103
+ * Consent not given - no cache
104
+ */
105
+ $this->buffer_output->add_tag( 'wp_footer', 10, array(
106
+ 'gtag' => $this->get_cookie_types(),
107
+ 'google-analytics' => $this->get_cookie_types(),
108
+ '_gaq' => $this->get_cookie_types(),
109
+ 'www.googletagmanager.com/gtag/js?id=' => $this->get_cookie_types()
110
+ ), false );
111
+ }
112
+ }
113
+
114
+ /**
115
+ * Return addon/plugin name
116
+ *
117
+ * @return string
118
+ *
119
+ * @since 1.3.0
120
+ */
121
+ public function get_addon_name() {
122
+ return 'GA Google Analytics';
123
+ }
124
+
125
+ /**
126
+ * Option name in the database
127
+ *
128
+ * @return string
129
+ *
130
+ * @since 1.3.0
131
+ */
132
+ public function get_option_name() {
133
+ return 'ga_google_analytics';
134
+ }
135
+
136
+ /**
137
+ * Plugin file name
138
+ *
139
+ * @return string
140
+ *
141
+ * @since 1.3.0
142
+ */
143
+ public function get_plugin_file() {
144
+ return 'ga-google-analytics/ga-google-analytics.php';
145
+ }
146
+
147
+ /**
148
+ * Returns checked cookie types
149
+ * @return mixed
150
+ *
151
+ * @since 1.3.0
152
+ */
153
+ public function get_cookie_types() {
154
+ return $this->settings->get_cookie_types( $this->get_option_name(), $this->get_default_cookie_types() );
155
+ }
156
+
157
+ /**
158
+ * Returns default cookie types
159
+ * @return array
160
+ *
161
+ * @since 1.5.0
162
+ */
163
+ public function get_default_cookie_types() {
164
+ return array( 'statistics' );
165
+ }
166
+
167
+ /**
168
+ * Check if plugin is activated and checked in the backend
169
+ *
170
+ * @since 1.3.0
171
+ */
172
+ public function is_addon_enabled() {
173
+ return $this->settings->is_addon_enabled( $this->get_option_name() );
174
+ }
175
+
176
+ /**
177
+ * Checks if addon is installed
178
+ *
179
+ * @since 1.3.0
180
+ */
181
+ public function is_addon_installed() {
182
+ return $this->settings->is_addon_installed( $this->get_plugin_file() );
183
+ }
184
+
185
+ /**
186
+ * Checks if addon is activated
187
+ *
188
+ * @since 1.3.0
189
+ */
190
+ public function is_addon_activated() {
191
+ return $this->settings->is_addon_activated( $this->get_plugin_file() );
192
+ }
193
+
194
+ /**
195
+ * Retrieves current installed version of the addon
196
+ *
197
+ * @return bool
198
+ *
199
+ * @since 2.2.1
200
+ */
201
+ public function get_addon_version() {
202
+ return $this->settings->get_addon_version( $this->get_plugin_file() );
203
+ }
204
+
205
+ /**
206
+ * Default placeholder content
207
+ *
208
+ * @return string
209
+ *
210
+ * @since 1.8.0
211
+ */
212
+ public function get_default_placeholder() {
213
+ return 'Please accept [renew_consent]%cookie_types[/renew_consent] cookies to watch this video.';
214
+ }
215
+
216
+ /**
217
+ * Get placeholder content
218
+ *
219
+ * This function will check following features:
220
+ * - Current language
221
+ *
222
+ * @param $src
223
+ *
224
+ * @return bool|mixed
225
+ *
226
+ * @since 1.8.0
227
+ */
228
+ public function get_placeholder( $src = '' ) {
229
+ return $this->settings->get_placeholder( $this->get_option_name(), $this->get_default_placeholder(), cookiebot_addons_output_cookie_types( $this->get_cookie_types() ), $src );
230
+ }
231
+
232
+ /**
233
+ * Checks if it does have custom placeholder content
234
+ *
235
+ * @return mixed
236
+ *
237
+ * @since 1.8.0
238
+ */
239
+ public function has_placeholder() {
240
+ return $this->settings->has_placeholder( $this->get_option_name() );
241
+ }
242
+
243
+ /**
244
+ * returns all placeholder contents
245
+ *
246
+ * @return mixed
247
+ *
248
+ * @since 1.8.0
249
+ */
250
+ public function get_placeholders() {
251
+ return $this->settings->get_placeholders( $this->get_option_name() );
252
+ }
253
+
254
+ /**
255
+ * Return true if the placeholder is enabled
256
+ *
257
+ * @return mixed
258
+ *
259
+ * @since 1.8.0
260
+ */
261
+ public function is_placeholder_enabled() {
262
+ return $this->settings->is_placeholder_enabled( $this->get_option_name() );
263
+ }
264
+
265
+ /**
266
+ * Adds extra information under the label
267
+ *
268
+ * @return string
269
+ *
270
+ * @since 1.8.0
271
+ */
272
+ public function get_extra_information() {
273
+ return false;
274
+ }
275
+
276
+ /**
277
+ * Returns the url of WordPress SVN repository or another link where we can verify the plugin file.
278
+ *
279
+ * @return boolean
280
+ *
281
+ * @since 1.8.0
282
+ */
283
+ public function get_svn_url() {
284
+ return 'http://plugins.svn.wordpress.org/ga-google-analytics/trunk/ga-google-analytics.php';
285
+ }
286
+
287
+ /**
288
+ * Placeholder helper overlay in the settings page.
289
+ *
290
+ * @return string
291
+ *
292
+ * @since 1.8.0
293
+ */
294
+ public function get_placeholder_helper() {
295
+ 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>';
296
+ }
297
+
298
+ /**
299
+ * Returns true if addon has an option to remove tag instead of adding attributes
300
+ *
301
+ * @return boolean
302
+ *
303
+ * @since 2.1.0
304
+ */
305
+ public function has_remove_tag_option() {
306
+ return false;
307
+ }
308
+
309
+ /**
310
+ * Returns parent class or false
311
+ *
312
+ * @return string|bool
313
+ *
314
+ * @since 2.1.3
315
+ */
316
+ public function get_parent_class() {
317
+ return get_parent_class( $this );
318
+ }
319
+
320
+ /**
321
+ * Action after enabling the addon on the settings page
322
+ *
323
+ * @since 2.2.0
324
+ */
325
+ public function post_hook_after_enabling() {
326
+ //do nothing
327
+ }
328
+
329
+ /**
330
+ * Cookiebot plugin is deactivated
331
+ *
332
+ * @since 2.2.0
333
+ */
334
+ public function plugin_deactivated() {
335
+ //do nothing
336
+ }
337
+ }
addons/controller/addons/gadwp/gadwp.php ADDED
@@ -0,0 +1,352 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\controller\addons\gadwp;
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 Gadwp 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
+ protected $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(
52
+ Settings_Service_Interface $settings,
53
+ Script_Loader_Tag_Interface $script_loader_tag,
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
+ /**
64
+ * Loads addon configuration
65
+ *
66
+ * @since 1.3.0
67
+ */
68
+ public function load_configuration() {
69
+ /**
70
+ * We add the action after wp_loaded and replace the original GA Google
71
+ * Analytics action with our own adjusted version.
72
+ */
73
+ add_action( 'wp_loaded', array( $this, 'cookiebot_addon_ga_google_analytics' ), 5 );
74
+ }
75
+
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() {
83
+ //Check if GA Google Analytics is loaded.
84
+ if ( ! class_exists( 'GADWP_Manager' ) ) {
85
+ return;
86
+ }
87
+
88
+ //Check if Cookiebot is activated and active.
89
+ if ( ! function_exists( 'cookiebot_active' ) || ! cookiebot_active() ) {
90
+ return;
91
+ }
92
+
93
+ // consent is given
94
+ if ( $this->cookie_consent->are_cookie_states_accepted( $this->get_cookie_types() ) ) {
95
+ return;
96
+ }
97
+
98
+ $this->script_loader_tag->add_tag( 'gadwp-nprogress', $this->get_cookie_types() );
99
+ $this->script_loader_tag->add_tag( 'gadwp-frontend-item-reports', $this->get_cookie_types() );
100
+
101
+ $this->script_loader_tag->add_tag( 'gadwp-tracking-analytics-events', $this->get_cookie_types() );
102
+ $this->script_loader_tag->add_tag( 'gadwp-pagescrolldepth-tracking', $this->get_cookie_types() );
103
+
104
+ $this->script_loader_tag->add_tag( 'gadwp-front-widget', $this->get_cookie_types() );
105
+ $this->script_loader_tag->add_tag( 'googlecharts', $this->get_cookie_types() );
106
+
107
+ $this->buffer_output->add_tag( 'wp_head',
108
+ 99,
109
+ array(
110
+ 'google-analytics.com' => $this->get_cookie_types(),
111
+ 'googletagmanager.com' => $this->get_cookie_types(),
112
+ 'ga-disable-' => $this->get_cookie_types(),
113
+ ),
114
+ false );
115
+
116
+ $this->buffer_output->add_tag( 'wp_footer',
117
+ 99,
118
+ array(
119
+ 'google-analytics.com' => $this->get_cookie_types(),
120
+ 'googletagmanager.com' => $this->get_cookie_types(),
121
+ 'ga-disable-' => $this->get_cookie_types(),
122
+ ),
123
+ false );
124
+ }
125
+
126
+ /**
127
+ * Return addon/plugin name
128
+ *
129
+ * @return string
130
+ *
131
+ * @since 1.3.0
132
+ */
133
+ public function get_addon_name() {
134
+ return 'Google Analytics Dashboard for WP (GADWP)';
135
+ }
136
+
137
+ /**
138
+ * Option name in the database
139
+ *
140
+ * @return string
141
+ *
142
+ * @since 1.3.0
143
+ */
144
+ public function get_option_name() {
145
+ return 'gadwp';
146
+ }
147
+
148
+ /**
149
+ * Plugin file name
150
+ *
151
+ * @return string
152
+ *
153
+ * @since 1.3.0
154
+ */
155
+ public function get_plugin_file() {
156
+ return 'google-analytics-dashboard-for-wp/gadwp.php';
157
+ }
158
+
159
+ /**
160
+ * Returns checked cookie types
161
+ * @return mixed
162
+ *
163
+ * @since 1.3.0
164
+ */
165
+ public function get_cookie_types() {
166
+ return $this->settings->get_cookie_types( $this->get_option_name(), $this->get_default_cookie_types() );
167
+ }
168
+
169
+ /**
170
+ * Returns default cookie types
171
+ * @return array
172
+ *
173
+ * @since 1.5.0
174
+ */
175
+ public function get_default_cookie_types() {
176
+ return array( 'statistics' );
177
+ }
178
+
179
+ /**
180
+ * Check if plugin is activated and checked in the backend
181
+ *
182
+ * @since 1.3.0
183
+ */
184
+ public function is_addon_enabled() {
185
+ return $this->settings->is_addon_enabled( $this->get_option_name() );
186
+ }
187
+
188
+ /**
189
+ * Checks if addon is installed
190
+ *
191
+ * @since 1.3.0
192
+ */
193
+ public function is_addon_installed() {
194
+ return $this->settings->is_addon_installed( $this->get_plugin_file() );
195
+ }
196
+
197
+ /**
198
+ * Checks if addon is activated
199
+ *
200
+ * @since 1.3.0
201
+ */
202
+ public function is_addon_activated() {
203
+ return $this->settings->is_addon_activated( $this->get_plugin_file() );
204
+ }
205
+
206
+ /**
207
+ * Retrieves current installed version of the addon
208
+ *
209
+ * @return bool
210
+ *
211
+ * @since 2.2.1
212
+ */
213
+ public function get_addon_version() {
214
+ return $this->settings->get_addon_version( $this->get_plugin_file() );
215
+ }
216
+
217
+ /**
218
+ * Default placeholder content
219
+ *
220
+ * @return string
221
+ *
222
+ * @since 1.8.0
223
+ */
224
+ public function get_default_placeholder() {
225
+ return 'Please accept [renew_consent]%cookie_types[/renew_consent] cookies to enable tracking.';
226
+ }
227
+
228
+ /**
229
+ * Get placeholder content
230
+ *
231
+ * This function will check following features:
232
+ * - Current language
233
+ *
234
+ * @param $src
235
+ *
236
+ * @return bool|mixed
237
+ *
238
+ * @since 1.8.0
239
+ */
240
+ public function get_placeholder( $src = '' ) {
241
+ return $this->settings->get_placeholder( $this->get_option_name(),
242
+ $this->get_default_placeholder(),
243
+ cookiebot_addons_output_cookie_types( $this->get_cookie_types() ),
244
+ $src );
245
+ }
246
+
247
+ /**
248
+ * Checks if it does have custom placeholder content
249
+ *
250
+ * @return mixed
251
+ *
252
+ * @since 1.8.0
253
+ */
254
+ public function has_placeholder() {
255
+ return $this->settings->has_placeholder( $this->get_option_name() );
256
+ }
257
+
258
+ /**
259
+ * returns all placeholder contents
260
+ *
261
+ * @return mixed
262
+ *
263
+ * @since 1.8.0
264
+ */
265
+ public function get_placeholders() {
266
+ return $this->settings->get_placeholders( $this->get_option_name() );
267
+ }
268
+
269
+ /**
270
+ * Return true if the placeholder is enabled
271
+ *
272
+ * @return mixed
273
+ *
274
+ * @since 1.8.0
275
+ */
276
+ public function is_placeholder_enabled() {
277
+ return $this->settings->is_placeholder_enabled( $this->get_option_name() );
278
+ }
279
+
280
+ /**
281
+ * Adds extra information under the label
282
+ *
283
+ * @return string
284
+ *
285
+ * @since 1.8.0
286
+ */
287
+ public function get_extra_information() {
288
+ return false;
289
+ }
290
+
291
+ /**
292
+ * Returns the url of WordPress SVN repository or another link where we can verify the plugin file.
293
+ *
294
+ * @return boolean
295
+ *
296
+ * @since 1.8.0
297
+ */
298
+ public function get_svn_url() {
299
+ return 'http://plugins.svn.wordpress.org/google-analytics-dashboard-for-wp/trunk/gadwp.php';
300
+ }
301
+
302
+ /**
303
+ * Placeholder helper overlay in the settings page.
304
+ *
305
+ * @return string
306
+ *
307
+ * @since 1.8.0
308
+ */
309
+ public function get_placeholder_helper() {
310
+ 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>';
311
+ }
312
+
313
+ /**
314
+ * Returns true if addon has an option to remove tag instead of adding attributes
315
+ *
316
+ * @return boolean
317
+ *
318
+ * @since 2.1.0
319
+ */
320
+ public function has_remove_tag_option() {
321
+ return false;
322
+ }
323
+
324
+ /**
325
+ * Returns parent class or false
326
+ *
327
+ * @return string|bool
328
+ *
329
+ * @since 2.1.3
330
+ */
331
+ public function get_parent_class() {
332
+ return get_parent_class( $this );
333
+ }
334
+
335
+ /**
336
+ * Action after enabling the addon on the settings page
337
+ *
338
+ * @since 2.2.0
339
+ */
340
+ public function post_hook_after_enabling() {
341
+ //do nothing
342
+ }
343
+
344
+ /**
345
+ * Cookiebot plugin is deactivated
346
+ *
347
+ * @since 2.2.0
348
+ */
349
+ public function plugin_deactivated() {
350
+ //do nothing
351
+ }
352
+ }
addons/controller/addons/google-analyticator/google-analyticator.php ADDED
@@ -0,0 +1,349 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\controller\addons\google_analyticator;
4
+
5
+ use cookiebot_addons\controller\addons\Cookiebot_Addons_Interface;
6
+ use cookiebot_addons\lib\buffer\Buffer_Output_Interface;
7
+ use cookiebot_addons\lib\Cookie_Consent_Interface;
8
+ use cookiebot_addons\lib\script_loader_tag\Script_Loader_Tag_Interface;
9
+ use cookiebot_addons\lib\Settings_Service_Interface;
10
+
11
+ class Google_Analyticator 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
+ protected $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_google_analyticator' ), 5 );
65
+ }
66
+
67
+ /**
68
+ * Check for google analyticator action hooks
69
+ *
70
+ * @since 1.3.0
71
+ */
72
+ public function cookiebot_addon_google_analyticator() {
73
+ // Check if Cookiebot is activated and active.
74
+ if ( ! function_exists( 'cookiebot_active' ) || ! cookiebot_active() ) {
75
+ return;
76
+ }
77
+
78
+ // consent is given
79
+ if( $this->cookie_consent->are_cookie_states_accepted( $this->get_cookie_types() ) ) {
80
+ return;
81
+ }
82
+
83
+ /**
84
+ * ga scripts are loaded in wp_head priority set to 99
85
+ */
86
+ if ( has_action( 'wp_head', 'add_google_analytics' ) ) {
87
+ /**
88
+ * Consent not given - no cache
89
+ */
90
+ $this->buffer_output->add_tag( 'wp_head', 99, array(
91
+ 'gtag' => $this->get_cookie_types(),
92
+ 'google-analytics' => $this->get_cookie_types(),
93
+ '_gaq' => $this->get_cookie_types(),
94
+ 'www.googletagmanager.com/gtag/js?id=' => $this->get_cookie_types()
95
+ ), false );
96
+ }
97
+
98
+ /**
99
+ * ga scripts are loaded in login_head priority set to 99
100
+ */
101
+ if ( has_action( 'login_head', 'add_google_analytics' ) ) {
102
+ /**
103
+ * Consent not given - no cache
104
+ */
105
+ $this->buffer_output->add_tag( 'login_head', 99, array(
106
+ 'gtag' => $this->get_cookie_types(),
107
+ 'google-analytics' => $this->get_cookie_types(),
108
+ '_gaq' => $this->get_cookie_types(),
109
+ 'www.googletagmanager.com/gtag/js?id=' => $this->get_cookie_types()
110
+ ) );
111
+ }
112
+
113
+ /**
114
+ * External js, so manipulate attributes
115
+ */
116
+ if ( has_action( 'wp_print_scripts', 'ga_external_tracking_js' ) ) {
117
+ /**
118
+ * Catch external js file and add cookiebot attributes to it
119
+ *
120
+ * @since 1.1.0
121
+ */
122
+ $this->script_loader_tag->add_tag( 'ga-external-tracking', $this->get_cookie_types() );
123
+ }
124
+ }
125
+
126
+ /**
127
+ * Return addon/plugin name
128
+ *
129
+ * @return string
130
+ *
131
+ * @since 1.3.0
132
+ */
133
+ public function get_addon_name() {
134
+ return 'Google Analyticator';
135
+ }
136
+
137
+ /**
138
+ * Option name in the database
139
+ *
140
+ * @return string
141
+ *
142
+ * @since 1.3.0
143
+ */
144
+ public function get_option_name() {
145
+ return 'google_analyticator';
146
+ }
147
+
148
+ /**
149
+ * plugin file name
150
+ *
151
+ * @return string
152
+ *
153
+ * @since 1.3.0
154
+ */
155
+ public function get_plugin_file() {
156
+ return 'google-analyticator/google-analyticator.php';
157
+ }
158
+
159
+ /**
160
+ * Returns checked cookie types
161
+ * @return array
162
+ *
163
+ * @since 1.3.0
164
+ */
165
+ public function get_cookie_types() {
166
+ return $this->settings->get_cookie_types( $this->get_option_name(), $this->get_default_cookie_types() );
167
+ }
168
+
169
+ /**
170
+ * Returns default cookie types
171
+ * @return array
172
+ *
173
+ * @since 1.5.0
174
+ */
175
+ public function get_default_cookie_types() {
176
+ return array( 'statistics' );
177
+ }
178
+
179
+ /**
180
+ * Check if plugin is activated and checked in the backend
181
+ *
182
+ * @since 1.3.0
183
+ */
184
+ public function is_addon_enabled() {
185
+ return $this->settings->is_addon_enabled( $this->get_option_name() );
186
+ }
187
+
188
+ /**
189
+ * Checks if addon is installed
190
+ *
191
+ * @since 1.3.0
192
+ */
193
+ public function is_addon_installed() {
194
+ return $this->settings->is_addon_installed( $this->get_plugin_file() );
195
+ }
196
+
197
+ /**
198
+ * Checks if addon is activated
199
+ *
200
+ * @since 1.3.0
201
+ */
202
+ public function is_addon_activated() {
203
+ return $this->settings->is_addon_activated( $this->get_plugin_file() );
204
+ }
205
+
206
+ /**
207
+ * Retrieves current installed version of the addon
208
+ *
209
+ * @return bool
210
+ *
211
+ * @since 2.2.1
212
+ */
213
+ public function get_addon_version() {
214
+ return $this->settings->get_addon_version( $this->get_plugin_file() );
215
+ }
216
+
217
+ /**
218
+ * Default placeholder content
219
+ *
220
+ * @return string
221
+ *
222
+ * @since 1.8.0
223
+ */
224
+ public function get_default_placeholder() {
225
+ return 'Please accept [renew_consent]%cookie_types[/renew_consent] cookies to watch this video.';
226
+ }
227
+
228
+ /**
229
+ * Get placeholder content
230
+ *
231
+ * This function will check following features:
232
+ * - Current language
233
+ *
234
+ * @param $src
235
+ *
236
+ * @return bool|mixed
237
+ *
238
+ * @since 1.8.0
239
+ */
240
+ public function get_placeholder( $src = '' ) {
241
+ return $this->settings->get_placeholder( $this->get_option_name(), $this->get_default_placeholder(), cookiebot_addons_output_cookie_types( $this->get_cookie_types() ), $src );
242
+ }
243
+
244
+ /**
245
+ * Checks if it does have custom placeholder content
246
+ *
247
+ * @return mixed
248
+ *
249
+ * @since 1.8.0
250
+ */
251
+ public function has_placeholder() {
252
+ return $this->settings->has_placeholder( $this->get_option_name() );
253
+ }
254
+
255
+ /**
256
+ * returns all placeholder contents
257
+ *
258
+ * @return mixed
259
+ *
260
+ * @since 1.8.0
261
+ */
262
+ public function get_placeholders() {
263
+ return $this->settings->get_placeholders( $this->get_option_name() );
264
+ }
265
+
266
+ /**
267
+ * Return true if the placeholder is enabled
268
+ *
269
+ * @return mixed
270
+ *
271
+ * @since 1.8.0
272
+ */
273
+ public function is_placeholder_enabled() {
274
+ return $this->settings->is_placeholder_enabled( $this->get_option_name() );
275
+ }
276
+
277
+ /**
278
+ * Adds extra information under the label
279
+ *
280
+ * @return string
281
+ *
282
+ * @since 1.8.0
283
+ */
284
+ public function get_extra_information() {
285
+
286
+ }
287
+
288
+ /**
289
+ * Returns the url of WordPress SVN repository or another link where we can verify the plugin file.
290
+ *
291
+ * @return boolean
292
+ *
293
+ * @since 1.8.0
294
+ */
295
+ public function get_svn_url() {
296
+ return 'http://plugins.svn.wordpress.org/google-analyticator/trunk/google-analyticator.php';
297
+ }
298
+
299
+ /**
300
+ * Placeholder helper overlay in the settings page.
301
+ *
302
+ * @return string
303
+ *
304
+ * @since 1.8.0
305
+ */
306
+ public function get_placeholder_helper() {
307
+ 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>';
308
+ }
309
+
310
+ /**
311
+ * Returns true if addon has an option to remove tag instead of adding attributes
312
+ *
313
+ * @return boolean
314
+ *
315
+ * @since 2.1.0
316
+ */
317
+ public function has_remove_tag_option() {
318
+ return false;
319
+ }
320
+
321
+ /**
322
+ * Returns parent class or false
323
+ *
324
+ * @return string|bool
325
+ *
326
+ * @since 2.1.3
327
+ */
328
+ public function get_parent_class() {
329
+ return get_parent_class( $this );
330
+ }
331
+
332
+ /**
333
+ * Action after enabling the addon on the settings page
334
+ *
335
+ * @since 2.2.0
336
+ */
337
+ public function post_hook_after_enabling() {
338
+ //do nothing
339
+ }
340
+
341
+ /**
342
+ * Cookiebot plugin is deactivated
343
+ *
344
+ * @since 2.2.0
345
+ */
346
+ public function plugin_deactivated() {
347
+ //do nothing
348
+ }
349
+ }
addons/controller/addons/google-analytics-plus/google-analytics-plus.php ADDED
@@ -0,0 +1,334 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\controller\addons\google_analytics_plus;
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 Google_Analytics_Plus implements Cookiebot_Addons_Interface {
12
+
13
+ /**
14
+ * @var Settings_Service_Interface
15
+ *
16
+ * @since 1.5.0
17
+ */
18
+ protected $settings;
19
+
20
+ /**
21
+ * @var Script_Loader_Tag_Interface
22
+ *
23
+ * @since 1.5.0
24
+ */
25
+ protected $script_loader_tag;
26
+
27
+ /**
28
+ * @var Cookie_Consent_Interface
29
+ *
30
+ * @since 1.5.0
31
+ */
32
+ protected $cookie_consent;
33
+
34
+ /**
35
+ * @var Buffer_Output_Interface
36
+ *
37
+ * @since 1.5.0
38
+ */
39
+ protected $buffer_output;
40
+
41
+ /**
42
+ * 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.5.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.5.0
62
+ */
63
+ public function load_configuration() {
64
+ add_action( 'wp_loaded', array( $this, 'cookiebot_addon_google_analytics_async' ), 5 );
65
+ }
66
+
67
+ /**
68
+ * Disable scripts if state not accepted
69
+ *
70
+ * @since 1.5.0
71
+ */
72
+ public function cookiebot_addon_google_analytics_async() {
73
+ // Check if Analytify is loaded.
74
+ if ( ! class_exists( 'Google_Analytics_Async' ) ) {
75
+ return;
76
+ }
77
+
78
+ // Check if Cookiebot is activated and active.
79
+ if ( ! function_exists( 'cookiebot_active' ) || ! cookiebot_active() ) {
80
+ return;
81
+ }
82
+
83
+ // consent is given
84
+ if( $this->cookie_consent->are_cookie_states_accepted( $this->get_cookie_types() ) ) {
85
+ return;
86
+ }
87
+
88
+
89
+ // Disable Analytify if cookie consent not allowed
90
+ if( $this->is_remove_tag_enabled() ) {
91
+ cookiebot_addons_remove_class_action( 'wp_head', 'Google_Analytics_Async', 'tracking_code_output' );
92
+ }
93
+ else {
94
+ $this->buffer_output->add_tag( 'wp_head', 10, array(
95
+ 'GoogleAnalyticsObject' => $this->get_cookie_types(),
96
+ ), false );
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Return addon/plugin name
102
+ *
103
+ * @return string
104
+ *
105
+ * @since 1.5.0
106
+ */
107
+ public function get_addon_name() {
108
+ return 'Google Analytics +';
109
+ }
110
+
111
+ /**
112
+ * Option name in the database
113
+ *
114
+ * @return string
115
+ *
116
+ * @since 1.5.0
117
+ */
118
+ public function get_option_name() {
119
+ return 'google_analytics_plus';
120
+ }
121
+
122
+ /**
123
+ * Plugin file name
124
+ *
125
+ * @return string
126
+ *
127
+ * @since 1.5.0
128
+ */
129
+ public function get_plugin_file() {
130
+ return 'google-analytics-async/google-analytics-async.php';
131
+ }
132
+
133
+ /**
134
+ * Returns checked cookie types
135
+ * @return mixed
136
+ *
137
+ * @since 1.5.0
138
+ */
139
+ public function get_cookie_types() {
140
+ return $this->settings->get_cookie_types( $this->get_option_name(), $this->get_default_cookie_types() );
141
+ }
142
+
143
+ /**
144
+ * Returns default cookie types
145
+ * @return array
146
+ *
147
+ * @since 1.5.0
148
+ */
149
+ public function get_default_cookie_types() {
150
+ return array( 'statistics' );
151
+ }
152
+
153
+ /**
154
+ * Check if plugin is activated and checked in the backend
155
+ *
156
+ * @since 1.5.0
157
+ */
158
+ public function is_addon_enabled() {
159
+ return $this->settings->is_addon_enabled( $this->get_option_name() );
160
+ }
161
+
162
+ /**
163
+ * Checks if addon is installed
164
+ *
165
+ * @since 1.5.0
166
+ */
167
+ public function is_addon_installed() {
168
+ return $this->settings->is_addon_installed( $this->get_plugin_file() );
169
+ }
170
+
171
+ /**
172
+ * Checks if addon is activated
173
+ *
174
+ * @since 1.5.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 '<p>' . __( 'Google Analytics is a simple, easy-to-use tool that helps website owners measure how users interact with website content', 'cookiebot-addons' ) . '</p>';
260
+ }
261
+
262
+ /**
263
+ * Returns the url of WordPress SVN repository or another link where we can verify the plugin file.
264
+ *
265
+ * @return boolean
266
+ *
267
+ * @since 1.8.0
268
+ */
269
+ public function get_svn_url() {
270
+ return false;
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 true if addon has an option to remove tag instead of adding attributes
286
+ *
287
+ * @return boolean
288
+ *
289
+ * @since 2.1.0
290
+ */
291
+ public function has_remove_tag_option() {
292
+ return true;
293
+ }
294
+
295
+ /**
296
+ * Return true if the remove tag option is enabled
297
+ *
298
+ * @return mixed
299
+ *
300
+ * @since 2.1.0
301
+ */
302
+ public function is_remove_tag_enabled() {
303
+ return $this->settings->is_remove_tag_enabled( $this->get_option_name() );
304
+ }
305
+
306
+ /**
307
+ * Returns parent class or false
308
+ *
309
+ * @return string|bool
310
+ *
311
+ * @since 2.1.3
312
+ */
313
+ public function get_parent_class() {
314
+ return get_parent_class( $this );
315
+ }
316
+
317
+ /**
318
+ * Action after enabling the addon on the settings page
319
+ *
320
+ * @since 2.2.0
321
+ */
322
+ public function post_hook_after_enabling() {
323
+ //do nothing
324
+ }
325
+
326
+ /**
327
+ * Cookiebot plugin is deactivated
328
+ *
329
+ * @since 2.2.0
330
+ */
331
+ public function plugin_deactivated() {
332
+ //do nothing
333
+ }
334
+ }
addons/controller/addons/google-analytics/google-analytics.php ADDED
@@ -0,0 +1,338 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\controller\addons\google_analytics;
4
+
5
+ use cookiebot_addons\controller\addons\Cookiebot_Addons_Interface;
6
+ use cookiebot_addons\lib\buffer\Buffer_Output_Interface;
7
+ use cookiebot_addons\lib\Cookie_Consent_Interface;
8
+ use cookiebot_addons\lib\script_loader_tag\Script_Loader_Tag_Interface;
9
+ use cookiebot_addons\lib\Settings_Service_Interface;
10
+
11
+ class Google_Analytics 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
+ protected $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_google_analyticator' ), 5 );
65
+ }
66
+
67
+ /**
68
+ * Check for google analyticator action hooks
69
+ *
70
+ * @since 1.3.0
71
+ */
72
+ public function cookiebot_addon_google_analyticator() {
73
+ // Check if Cookiebot is activated and active.
74
+ if ( ! function_exists( 'cookiebot_active' ) || ! cookiebot_active() ) {
75
+ return;
76
+ }
77
+
78
+ // consent is given
79
+ if ( $this->cookie_consent->are_cookie_states_accepted( $this->get_cookie_types() ) ) {
80
+ return;
81
+ }
82
+
83
+ if ( !$this->is_addon_enabled() ) {
84
+ return;
85
+ }
86
+
87
+ if( $this->is_remove_tag_enabled() ) {
88
+ // disable scripts
89
+ remove_action( 'wp_enqueue_scripts', 'Ga_Frontend::platform_sharethis' );
90
+ remove_action( 'wp_footer', 'Ga_Frontend::insert_ga_script' );
91
+ }
92
+ else {
93
+ $this->buffer_output->add_tag( 'wp_footer', 10, array(
94
+ 'googleanalytics_get_script' => $this->get_cookie_types(),
95
+ ), false );
96
+
97
+ if(has_action( 'wp_enqueue_scripts', 'Ga_Frontend::platform_sharethis' )) {
98
+ $this->script_loader_tag->add_tag( GA_NAME . '-platform-sharethis', $this->get_cookie_types() );
99
+ }
100
+
101
+ }
102
+ }
103
+
104
+ /**
105
+ * Return addon/plugin name
106
+ *
107
+ * @return string
108
+ *
109
+ * @since 1.3.0
110
+ */
111
+ public function get_addon_name() {
112
+ return 'Google Analytics';
113
+ }
114
+
115
+ /**
116
+ * Option name in the database
117
+ *
118
+ * @return string
119
+ *
120
+ * @since 1.3.0
121
+ */
122
+ public function get_option_name() {
123
+ return 'google_analytics';
124
+ }
125
+
126
+ /**
127
+ * plugin file name
128
+ *
129
+ * @return string
130
+ *
131
+ * @since 1.3.0
132
+ */
133
+ public function get_plugin_file() {
134
+ return 'googleanalytics/googleanalytics.php';
135
+ }
136
+
137
+ /**
138
+ * Returns checked cookie types
139
+ * @return array
140
+ *
141
+ * @since 1.3.0
142
+ */
143
+ public function get_cookie_types() {
144
+ return $this->settings->get_cookie_types( $this->get_option_name(), $this->get_default_cookie_types() );
145
+ }
146
+
147
+ /**
148
+ * Returns default cookie types
149
+ * @return array
150
+ *
151
+ * @since 1.5.0
152
+ */
153
+ public function get_default_cookie_types() {
154
+ return array( 'statistics' );
155
+ }
156
+
157
+ /**
158
+ * Check if plugin is activated and checked in the backend
159
+ *
160
+ * @since 1.3.0
161
+ */
162
+ public function is_addon_enabled() {
163
+ return $this->settings->is_addon_enabled( $this->get_option_name() );
164
+ }
165
+
166
+ /**
167
+ * Checks if addon is installed
168
+ *
169
+ * @since 1.3.0
170
+ */
171
+ public function is_addon_installed() {
172
+ return $this->settings->is_addon_installed( $this->get_plugin_file() );
173
+ }
174
+
175
+ /**
176
+ * Checks if addon is activated
177
+ *
178
+ * @since 1.3.0
179
+ */
180
+ public function is_addon_activated() {
181
+ return $this->settings->is_addon_activated( $this->get_plugin_file() );
182
+ }
183
+
184
+ /**
185
+ * Retrieves current installed version of the addon
186
+ *
187
+ * @return bool
188
+ *
189
+ * @since 2.2.1
190
+ */
191
+ public function get_addon_version() {
192
+ return $this->settings->get_addon_version( $this->get_plugin_file() );
193
+ }
194
+
195
+ /**
196
+ * Default placeholder content
197
+ *
198
+ * @return string
199
+ *
200
+ * @since 1.8.0
201
+ */
202
+ public function get_default_placeholder() {
203
+ return 'Please accept [renew_consent]%cookie_types[/renew_consent] cookies to track for google analytics.';
204
+ }
205
+
206
+ /**
207
+ * Get placeholder content
208
+ *
209
+ * This function will check following features:
210
+ * - Current language
211
+ *
212
+ * @param $src
213
+ *
214
+ * @return bool|mixed
215
+ *
216
+ * @since 1.8.0
217
+ */
218
+ public function get_placeholder( $src = '' ) {
219
+ return $this->settings->get_placeholder( $this->get_option_name(), $this->get_default_placeholder(), cookiebot_addons_output_cookie_types( $this->get_cookie_types() ), $src );
220
+ }
221
+
222
+ /**
223
+ * Checks if it does have custom placeholder content
224
+ *
225
+ * @return mixed
226
+ *
227
+ * @since 1.8.0
228
+ */
229
+ public function has_placeholder() {
230
+ return $this->settings->has_placeholder( $this->get_option_name() );
231
+ }
232
+
233
+ /**
234
+ * returns all placeholder contents
235
+ *
236
+ * @return mixed
237
+ *
238
+ * @since 1.8.0
239
+ */
240
+ public function get_placeholders() {
241
+ return $this->settings->get_placeholders( $this->get_option_name() );
242
+ }
243
+
244
+ /**
245
+ * Return true if the placeholder is enabled
246
+ *
247
+ * @return mixed
248
+ *
249
+ * @since 1.8.0
250
+ */
251
+ public function is_placeholder_enabled() {
252
+ return $this->settings->is_placeholder_enabled( $this->get_option_name() );
253
+ }
254
+
255
+ /**
256
+ * Adds extra information under the label
257
+ *
258
+ * @return string
259
+ *
260
+ * @since 1.8.0
261
+ */
262
+ public function get_extra_information() {
263
+ return '<p>' . __( 'Google Analytics is used to track how visitor interact with website content.', 'cookiebot-addons' ) . '</p>';
264
+ }
265
+
266
+ /**
267
+ * Returns the url of WordPress SVN repository or another link where we can verify the plugin file.
268
+ *
269
+ * @return boolean
270
+ *
271
+ * @since 1.8.0
272
+ */
273
+ public function get_svn_url() {
274
+ return 'http://plugins.svn.wordpress.org/googleanalytics/trunk/googleanalytics.php';
275
+ }
276
+
277
+ /**
278
+ * Placeholder helper overlay in the settings page.
279
+ *
280
+ * @return string
281
+ *
282
+ * @since 1.8.0
283
+ */
284
+ public function get_placeholder_helper() {
285
+ 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>';
286
+ }
287
+
288
+ /**
289
+ * Returns true if addon has an option to remove tag instead of adding attributes
290
+ *
291
+ * @return boolean
292
+ *
293
+ * @since 2.1.0
294
+ */
295
+ public function has_remove_tag_option() {
296
+ return true;
297
+ }
298
+
299
+ /**
300
+ * Return true if the remove tag option is enabled
301
+ *
302
+ * @return mixed
303
+ *
304
+ * @since 2.1.0
305
+ */
306
+ public function is_remove_tag_enabled() {
307
+ return $this->settings->is_remove_tag_enabled( $this->get_option_name() );
308
+ }
309
+
310
+ /**
311
+ * Returns parent class or false
312
+ *
313
+ * @return string|bool
314
+ *
315
+ * @since 2.1.3
316
+ */
317
+ public function get_parent_class() {
318
+ return get_parent_class( $this );
319
+ }
320
+
321
+ /**
322
+ * Action after enabling the addon on the settings page
323
+ *
324
+ * @since 2.2.0
325
+ */
326
+ public function post_hook_after_enabling() {
327
+ //do nothing
328
+ }
329
+
330
+ /**
331
+ * Cookiebot plugin is deactivated
332
+ *
333
+ * @since 2.2.0
334
+ */
335
+ public function plugin_deactivated() {
336
+ //do nothing
337
+ }
338
+ }
addons/controller/addons/hubspot-leadin/hubspot-leadin.php ADDED
@@ -0,0 +1,319 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\controller\addons\hubspot_leadin;
4
+
5
+ use cookiebot_addons\controller\addons\Cookiebot_Addons_Interface;
6
+ use cookiebot_addons\lib\script_loader_tag\Script_Loader_Tag_Interface;
7
+ use cookiebot_addons\lib\Cookie_Consent_Interface;
8
+ use cookiebot_addons\lib\buffer\Buffer_Output_Interface;
9
+ use cookiebot_addons\lib\Settings_Service_Interface;
10
+
11
+ class Hubspot_Leadin 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
+ protected $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
+ /**
65
+ * We add the action after wp_loaded and replace the original
66
+ * HubSpot Tracking Code action with our own adjusted version.
67
+ */
68
+ add_action( 'wp_loaded', array( $this, 'cookiebot_addon_hubspot_tracking_code' ), 10 );
69
+ }
70
+
71
+ /**
72
+ * Manipulate the scripts if they are loaded.
73
+ *
74
+ * @since 1.3.0
75
+ */
76
+ public function cookiebot_addon_hubspot_tracking_code() {
77
+ // Check if Cookiebot is activated and active.
78
+ if ( ! function_exists( 'cookiebot_active' ) || ! cookiebot_active() ) {
79
+ return;
80
+ }
81
+
82
+ // consent is given
83
+ if ( $this->cookie_consent->are_cookie_states_accepted( $this->get_cookie_types() ) ) {
84
+ return;
85
+ }
86
+
87
+ if ( $this->is_addon_enabled() && $this->is_addon_activated() ) {
88
+ if ( ! $this->cookie_consent->are_cookie_states_accepted( $this->get_cookie_types() ) ) {
89
+ // block the script untill the consent is given
90
+ $this->script_loader_tag->add_tag( 'leadin-scriptloader-js', $this->get_cookie_types() );
91
+ }
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Return addon/plugin name
97
+ *
98
+ * @return string
99
+ *
100
+ * @since 1.3.0
101
+ */
102
+ public function get_addon_name() {
103
+ return 'HubSpot - Free Marketing Plugin for WordPress';
104
+ }
105
+
106
+ /**
107
+ * Option name in the database
108
+ *
109
+ * @return string
110
+ *
111
+ * @since 1.3.0
112
+ */
113
+ public function get_option_name() {
114
+ return 'hubspot_leadin';
115
+ }
116
+
117
+ /**
118
+ * Plugin file name
119
+ *
120
+ * @return string
121
+ *
122
+ * @since 1.3.0
123
+ */
124
+ public function get_plugin_file() {
125
+ return 'leadin/leadin.php';
126
+ }
127
+
128
+ /**
129
+ * Returns checked cookie types
130
+ * @return mixed
131
+ *
132
+ * @since 1.3.0
133
+ */
134
+ public function get_cookie_types() {
135
+ return $this->settings->get_cookie_types( $this->get_option_name() );
136
+ }
137
+
138
+ /**
139
+ * Returns default cookie types
140
+ * @return array
141
+ *
142
+ * @since 1.5.0
143
+ */
144
+ public function get_default_cookie_types() {
145
+ return array( 'marketing', 'statistics' );
146
+ }
147
+
148
+
149
+ /**
150
+ * Check if plugin is activated and checked in the backend
151
+ *
152
+ * @since 1.3.0
153
+ */
154
+ public function is_addon_enabled() {
155
+ return $this->settings->is_addon_enabled( $this->get_option_name() );
156
+ }
157
+
158
+ /**
159
+ * Checks if addon is installed
160
+ *
161
+ * @since 1.3.0
162
+ */
163
+ public function is_addon_installed() {
164
+ return $this->settings->is_addon_installed( $this->get_plugin_file() );
165
+ }
166
+
167
+ /**
168
+ * Checks if addon is activated
169
+ *
170
+ * @since 1.3.0
171
+ */
172
+ public function is_addon_activated() {
173
+ return $this->settings->is_addon_activated( $this->get_plugin_file() );
174
+ }
175
+
176
+ /**
177
+ * Retrieves current installed version of the addon
178
+ *
179
+ * @return bool
180
+ *
181
+ * @since 2.2.1
182
+ */
183
+ public function get_addon_version() {
184
+ return $this->settings->get_addon_version( $this->get_plugin_file() );
185
+ }
186
+
187
+ /**
188
+ * Default placeholder content
189
+ *
190
+ * @return string
191
+ *
192
+ * @since 1.8.0
193
+ */
194
+ public function get_default_placeholder() {
195
+ return 'Please accept [renew_consent]%cookie_types[/renew_consent] cookies to watch this video.';
196
+ }
197
+
198
+ /**
199
+ * Get placeholder content
200
+ *
201
+ * This function will check following features:
202
+ * - Current language
203
+ *
204
+ * @param $src
205
+ *
206
+ * @return bool|mixed
207
+ *
208
+ * @since 1.8.0
209
+ */
210
+ public function get_placeholder( $src = '' ) {
211
+ return $this->settings->get_placeholder( $this->get_option_name(), $this->get_default_placeholder(), cookiebot_addons_output_cookie_types( $this->get_cookie_types() ), $src );
212
+ }
213
+
214
+ /**
215
+ * Checks if it does have custom placeholder content
216
+ *
217
+ * @return mixed
218
+ *
219
+ * @since 1.8.0
220
+ */
221
+ public function has_placeholder() {
222
+ return $this->settings->has_placeholder( $this->get_option_name() );
223
+ }
224
+
225
+ /**
226
+ * returns all placeholder contents
227
+ *
228
+ * @return mixed
229
+ *
230
+ * @since 1.8.0
231
+ */
232
+ public function get_placeholders() {
233
+ return $this->settings->get_placeholders( $this->get_option_name() );
234
+ }
235
+
236
+ /**
237
+ * Return true if the placeholder is enabled
238
+ *
239
+ * @return mixed
240
+ *
241
+ * @since 1.8.0
242
+ */
243
+ public function is_placeholder_enabled() {
244
+ return $this->settings->is_placeholder_enabled( $this->get_option_name() );
245
+ }
246
+
247
+ /**
248
+ * Adds extra information under the label
249
+ *
250
+ * @return string
251
+ *
252
+ * @since 1.8.0
253
+ */
254
+ public function get_extra_information() {
255
+ return false;
256
+ }
257
+
258
+ /**
259
+ * Returns the url of WordPress SVN repository or another link where we can verify the plugin file.
260
+ *
261
+ * @return boolean
262
+ *
263
+ * @since 1.8.0
264
+ */
265
+ public function get_svn_url() {
266
+ return 'http://plugins.svn.wordpress.org/leadin/trunk/leadin.php';
267
+ }
268
+
269
+ /**
270
+ * Placeholder helper overlay in the settings page.
271
+ *
272
+ * @return string
273
+ *
274
+ * @since 1.8.0
275
+ */
276
+ public function get_placeholder_helper() {
277
+ 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>';
278
+ }
279
+
280
+ /**
281
+ * Returns true if addon has an option to remove tag instead of adding attributes
282
+ *
283
+ * @return boolean
284
+ *
285
+ * @since 2.1.0
286
+ */
287
+ public function has_remove_tag_option() {
288
+ return false;
289
+ }
290
+
291
+ /**
292
+ * Returns parent class or false
293
+ *
294
+ * @return string|bool
295
+ *
296
+ * @since 2.1.3
297
+ */
298
+ public function get_parent_class() {
299
+ return get_parent_class( $this );
300
+ }
301
+
302
+ /**
303
+ * Action after enabling the addon on the settings page
304
+ *
305
+ * @since 2.2.0
306
+ */
307
+ public function post_hook_after_enabling() {
308
+ //do nothing
309
+ }
310
+
311
+ /**
312
+ * Cookiebot plugin is deactivated
313
+ *
314
+ * @since 2.2.0
315
+ */
316
+ public function plugin_deactivated() {
317
+ //do nothing
318
+ }
319
+ }
addons/controller/addons/hubspot-tracking-code/hubspot-tracking-code.php ADDED
@@ -0,0 +1,332 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\controller\addons\hubspot_tracking_code;
4
+
5
+ include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
6
+
7
+ use cookiebot_addons\controller\addons\Cookiebot_Addons_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\buffer\Buffer_Output_Interface;
11
+ use cookiebot_addons\lib\Settings_Service_Interface;
12
+
13
+ class Hubspot_Tracking_Code implements Cookiebot_Addons_Interface {
14
+
15
+ /**
16
+ * @var Settings_Service_Interface
17
+ *
18
+ * @since 1.3.0
19
+ */
20
+ protected $settings;
21
+
22
+ /**
23
+ * @var Script_Loader_Tag_Interface
24
+ *
25
+ * @since 1.3.0
26
+ */
27
+ protected $script_loader_tag;
28
+
29
+ /**
30
+ * @var Cookie_Consent_Interface
31
+ *
32
+ * @since 1.3.0
33
+ */
34
+ protected $cookie_consent;
35
+
36
+ /**
37
+ * @var Buffer_Output_Interface
38
+ *
39
+ * @since 1.3.0
40
+ */
41
+ protected $buffer_output;
42
+
43
+ /**
44
+ * Jetpack constructor.
45
+ *
46
+ * @param $settings Settings_Service_Interface
47
+ * @param $script_loader_tag Script_Loader_Tag_Interface
48
+ * @param $cookie_consent Cookie_Consent_Interface
49
+ * @param $buffer_output Buffer_Output_Interface
50
+ *
51
+ * @since 1.3.0
52
+ */
53
+ public function __construct( Settings_Service_Interface $settings, Script_Loader_Tag_Interface $script_loader_tag, Cookie_Consent_Interface $cookie_consent, Buffer_Output_Interface $buffer_output ) {
54
+ $this->settings = $settings;
55
+ $this->script_loader_tag = $script_loader_tag;
56
+ $this->cookie_consent = $cookie_consent;
57
+ $this->buffer_output = $buffer_output;
58
+ }
59
+
60
+ /**
61
+ * Loads addon configuration
62
+ *
63
+ * @since 1.3.0
64
+ */
65
+ public function load_configuration() {
66
+ /**
67
+ * We add the action after wp_loaded and replace the original
68
+ * HubSpot Tracking Code action with our own adjusted version.
69
+ */
70
+ add_action( 'wp_loaded', array( $this, 'cookiebot_addon_hubspot_tracking_code' ), 10 );
71
+ }
72
+
73
+ /**
74
+ * Manipulate the scripts if they are loaded.
75
+ *
76
+ * @since 1.3.0
77
+ */
78
+ public function cookiebot_addon_hubspot_tracking_code() {
79
+ // Check if HubSpot Tracking Code is loaded
80
+ $options = get_option( 'hs_settings' );
81
+ if ( ! isset( $options['hs_portal'] ) || $options['hs_portal'] == '' ) {
82
+ return;
83
+ }
84
+
85
+ // Check if Cookiebot is activated and active.
86
+ if ( ! function_exists( 'cookiebot_active' ) || ! cookiebot_active() ) {
87
+ return;
88
+ }
89
+
90
+ // consent is given
91
+ if( $this->cookie_consent->are_cookie_states_accepted( $this->get_cookie_types() ) ) {
92
+ return;
93
+ }
94
+
95
+ // Replace original HubSpot Tracking Code with own one and delete cookie if
96
+ // it was perviously set.
97
+ if ( is_plugin_active( 'hubspot-tracking-code/hubspot-tracking-code.php' ) ) {
98
+ /**
99
+ * Consent not given - no cache
100
+ */
101
+ $this->buffer_output->add_tag( 'wp_footer', 10, array( 'hs-script-loader' => $this->get_cookie_types() ), false );
102
+
103
+ if ( ! $this->cookie_consent->is_cookie_state_accepted( 'marketing' ) && isset( $_COOKIE['hubspotutk'] ) ) {
104
+ unset( $_COOKIE['hubspotutk'] );
105
+ }
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Return addon/plugin name
111
+ *
112
+ * @return string
113
+ *
114
+ * @since 1.3.0
115
+ */
116
+ public function get_addon_name() {
117
+ return 'Hubspot Tracking Code';
118
+ }
119
+
120
+ /**
121
+ * Option name in the database
122
+ *
123
+ * @return string
124
+ *
125
+ * @since 1.3.0
126
+ */
127
+ public function get_option_name() {
128
+ return 'hubspot_tracking_code';
129
+ }
130
+
131
+ /**
132
+ * Plugin file name
133
+ *
134
+ * @return string
135
+ *
136
+ * @since 1.3.0
137
+ */
138
+ public function get_plugin_file() {
139
+ return 'hubspot-tracking-code/hubspot-tracking-code.php';
140
+ }
141
+
142
+ /**
143
+ * Returns checked cookie types
144
+ * @return mixed
145
+ *
146
+ * @since 1.3.0
147
+ */
148
+ public function get_cookie_types() {
149
+ return $this->settings->get_cookie_types( $this->get_option_name(), $this->get_default_cookie_types() );
150
+ }
151
+
152
+ /**
153
+ * Returns default cookie types
154
+ * @return array
155
+ *
156
+ * @since 1.5.0
157
+ */
158
+ public function get_default_cookie_types() {
159
+ return array( 'marketing', 'statistics' );
160
+ }
161
+
162
+ /**
163
+ * Check if plugin is activated and checked in the backend
164
+ *
165
+ * @since 1.3.0
166
+ */
167
+ public function is_addon_enabled() {
168
+ return $this->settings->is_addon_enabled( $this->get_option_name() );
169
+ }
170
+
171
+ /**
172
+ * Checks if addon is installed
173
+ *
174
+ * @since 1.3.0
175
+ */
176
+ public function is_addon_installed() {
177
+ return $this->settings->is_addon_installed( $this->get_plugin_file() );
178
+ }
179
+
180
+ /**
181
+ * Checks if addon is activated
182
+ *
183
+ * @since 1.3.0
184
+ */
185
+ public function is_addon_activated() {
186
+ return $this->settings->is_addon_activated( $this->get_plugin_file() );
187
+ }
188
+
189
+ /**
190
+ * Retrieves current installed version of the addon
191
+ *
192
+ * @return bool
193
+ *
194
+ * @since 2.2.1
195
+ */
196
+ public function get_addon_version() {
197
+ return $this->settings->get_addon_version( $this->get_plugin_file() );
198
+ }
199
+
200
+ /**
201
+ * Default placeholder content
202
+ *
203
+ * @return string
204
+ *
205
+ * @since 1.8.0
206
+ */
207
+ public function get_default_placeholder() {
208
+ return 'Please accept [renew_consent]%cookie_types[/renew_consent] cookies to watch this video.';
209
+ }
210
+
211
+ /**
212
+ * Get placeholder content
213
+ *
214
+ * This function will check following features:
215
+ * - Current language
216
+ *
217
+ * @param $src
218
+ *
219
+ * @return bool|mixed
220
+ *
221
+ * @since 1.8.0
222
+ */
223
+ public function get_placeholder( $src = '' ) {
224
+ return $this->settings->get_placeholder( $this->get_option_name(), $this->get_default_placeholder(), cookiebot_addons_output_cookie_types( $this->get_cookie_types() ), $src );
225
+ }
226
+
227
+ /**
228
+ * Checks if it does have custom placeholder content
229
+ *
230
+ * @return mixed
231
+ *
232
+ * @since 1.8.0
233
+ */
234
+ public function has_placeholder() {
235
+ return $this->settings->has_placeholder( $this->get_option_name() );
236
+ }
237
+
238
+ /**
239
+ * returns all placeholder contents
240
+ *
241
+ * @return mixed
242
+ *
243
+ * @since 1.8.0
244
+ */
245
+ public function get_placeholders() {
246
+ return $this->settings->get_placeholders( $this->get_option_name() );
247
+ }
248
+
249
+ /**
250
+ * Return true if the placeholder is enabled
251
+ *
252
+ * @return mixed
253
+ *
254
+ * @since 1.8.0
255
+ */
256
+ public function is_placeholder_enabled() {
257
+ return $this->settings->is_placeholder_enabled( $this->get_option_name() );
258
+ }
259
+
260
+ /**
261
+ * Adds extra information under the label
262
+ *
263
+ * @return string
264
+ *
265
+ * @since 1.8.0
266
+ */
267
+ public function get_extra_information() {
268
+ return false;
269
+ }
270
+
271
+ /**
272
+ * Returns the url of WordPress SVN repository or another link where we can verify the plugin file.
273
+ *
274
+ * @return boolean
275
+ *
276
+ * @since 1.8.0
277
+ */
278
+ public function get_svn_url() {
279
+ return 'http://plugins.svn.wordpress.org/hubspot-tracking-code/trunk/hubspot-tracking-code.php';
280
+ }
281
+
282
+ /**
283
+ * Placeholder helper overlay in the settings page.
284
+ *
285
+ * @return string
286
+ *
287
+ * @since 1.8.0
288
+ */
289
+ public function get_placeholder_helper() {
290
+ 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>';
291
+ }
292
+
293
+ /**
294
+ * Returns true if addon has an option to remove tag instead of adding attributes
295
+ *
296
+ * @return boolean
297
+ *
298
+ * @since 2.1.0
299
+ */
300
+ public function has_remove_tag_option() {
301
+ return false;
302
+ }
303
+
304
+ /**
305
+ * Returns parent class or false
306
+ *
307
+ * @return string|bool
308
+ *
309
+ * @since 2.1.3
310
+ */
311
+ public function get_parent_class() {
312
+ return get_parent_class( $this );
313
+ }
314
+
315
+ /**
316
+ * Action after enabling the addon on the settings page
317
+ *
318
+ * @since 2.2.0
319
+ */
320
+ public function post_hook_after_enabling() {
321
+ //do nothing
322
+ }
323
+
324
+ /**
325
+ * Cookiebot plugin is deactivated
326
+ *
327
+ * @since 2.2.0
328
+ */
329
+ public function plugin_deactivated() {
330
+ //do nothing
331
+ }
332
+ }
addons/controller/addons/instagram-feed/instagram-feed.php ADDED
@@ -0,0 +1,317 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\controller\addons\instagram_feed;
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 Instagram_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
+ protected $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_sb_instagram' ), 5 );
65
+ }
66
+
67
+ /**
68
+ * Disable scripts if state not accepted
69
+ *
70
+ * @since 1.3.0
71
+ */
72
+ public function cookiebot_addon_sb_instagram() {
73
+ // Check if instagram feed is loaded.
74
+ if ( ! defined( 'SBIVER' ) ) {
75
+ return;
76
+ }
77
+
78
+ // Check if Cookiebot is activated and active.
79
+ if ( ! function_exists( 'cookiebot_active' ) || ! cookiebot_active() ) {
80
+ return;
81
+ }
82
+
83
+ // consent is given
84
+ if( $this->cookie_consent->are_cookie_states_accepted( $this->get_cookie_types() ) ) {
85
+ return;
86
+ }
87
+
88
+ // External js, so manipulate attributes
89
+ if ( has_action( 'wp_enqueue_scripts', 'sb_instagram_scripts_enqueue' ) ) {
90
+ $this->script_loader_tag->add_tag( 'sb_instagram_scripts', $this->get_cookie_types() );
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 'Instagram 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 'instagram 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 'instagram-feed/instagram-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
+ /**
257
+ * Returns the url of WordPress SVN repository or another link where we can verify the plugin file.
258
+ *
259
+ * @return boolean
260
+ *
261
+ * @since 1.8.0
262
+ */
263
+ public function get_svn_url() {
264
+ return 'http://plugins.svn.wordpress.org/instagram-feed/trunk/instagram-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 true if addon has an option to remove tag instead of adding attributes
280
+ *
281
+ * @return boolean
282
+ *
283
+ * @since 2.1.0
284
+ */
285
+ public function has_remove_tag_option() {
286
+ return false;
287
+ }
288
+
289
+ /**
290
+ * Returns parent class or false
291
+ *
292
+ * @return string|bool
293
+ *
294
+ * @since 2.1.3
295
+ */
296
+ public function get_parent_class() {
297
+ return get_parent_class( $this );
298
+ }
299
+
300
+ /**
301
+ * Action after enabling the addon on the settings page
302
+ *
303
+ * @since 2.2.0
304
+ */
305
+ public function post_hook_after_enabling() {
306
+ //do nothing
307
+ }
308
+
309
+ /**
310
+ * Cookiebot plugin is deactivated
311
+ *
312
+ * @since 2.2.0
313
+ */
314
+ public function plugin_deactivated() {
315
+ //do nothing
316
+ }
317
+ }
addons/controller/addons/jetpack/jetpack.php ADDED
@@ -0,0 +1,416 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\controller\addons\jetpack;
4
+
5
+ use cookiebot_addons\controller\addons\jetpack\widget\Google_Maps_Widget;
6
+ use cookiebot_addons\controller\addons\jetpack\widget\Facebook_Widget;
7
+ use cookiebot_addons\controller\addons\jetpack\widget\Googleplus_Badge_Widget;
8
+ use cookiebot_addons\controller\addons\jetpack\widget\Goodreads_Widget;
9
+ use cookiebot_addons\controller\addons\jetpack\widget\Internet_Defense_league_Widget;
10
+ use cookiebot_addons\controller\addons\jetpack\widget\Twitter_Timeline_Widget;
11
+ use cookiebot_addons\controller\addons\Cookiebot_Addons_Interface;
12
+ use cookiebot_addons\lib\buffer\Buffer_Output_Interface;
13
+ use cookiebot_addons\lib\Cookie_Consent_Interface;
14
+ use cookiebot_addons\lib\script_loader_tag\Script_Loader_Tag_Interface;
15
+ use cookiebot_addons\lib\Settings_Service_Interface;
16
+
17
+ /**
18
+ * This class is used to support jetpack in cookiebot
19
+ *
20
+ * Class Jetpack
21
+ * @package cookiebot_addons\controller\addons\jetpack
22
+ *
23
+ * @since 1.3.0
24
+ */
25
+ class Jetpack implements Cookiebot_Addons_Interface {
26
+
27
+ /**
28
+ * @var Settings_Service_Interface
29
+ *
30
+ * @since 1.3.0
31
+ */
32
+ protected $settings;
33
+
34
+ /**
35
+ * @var Script_Loader_Tag_Interface
36
+ *
37
+ * @since 1.3.0
38
+ */
39
+ protected $script_loader_tag;
40
+
41
+ /**
42
+ * @var Cookie_Consent_Interface
43
+ *
44
+ * @since 1.3.0
45
+ */
46
+ protected $cookie_consent;
47
+
48
+ /**
49
+ * @var Buffer_Output_Interface
50
+ *
51
+ * @since 1.3.0
52
+ */
53
+ protected $buffer_output;
54
+
55
+ protected $widgets = array();
56
+
57
+ /**
58
+ * Jetpack constructor.
59
+ *
60
+ * @param $settings Settings_Service_Interface
61
+ * @param $script_loader_tag Script_Loader_Tag_Interface
62
+ * @param $cookie_consent Cookie_Consent_Interface
63
+ * @param $buffer_output Buffer_Output_Interface
64
+ *
65
+ * @since 1.2.0
66
+ */
67
+ public function __construct( Settings_Service_Interface $settings, Script_Loader_Tag_Interface $script_loader_tag, Cookie_Consent_Interface $cookie_consent, Buffer_Output_Interface $buffer_output ) {
68
+ $this->settings = $settings;
69
+ $this->script_loader_tag = $script_loader_tag;
70
+ $this->cookie_consent = $cookie_consent;
71
+ $this->buffer_output = $buffer_output;
72
+
73
+ // set widgets
74
+ $this->set_widgets();
75
+ }
76
+
77
+ /**
78
+ * Loads addon configuration
79
+ *
80
+ * @since 1.3.0
81
+ */
82
+ public function load_configuration() {
83
+ // Check if Cookiebot is activated and active.
84
+ if ( ! function_exists( 'cookiebot_active' ) || ! cookiebot_active() ) {
85
+ return;
86
+ }
87
+
88
+ // consent is given
89
+ if ( $this->cookie_consent->are_cookie_states_accepted( $this->get_cookie_types() ) ) {
90
+ return;
91
+ }
92
+
93
+ // load widgets
94
+ $this->load_widgets();
95
+ }
96
+
97
+ /**
98
+ * Sets every widget into this class
99
+ *
100
+ * @since 1.8.0
101
+ */
102
+ public function set_widgets() {
103
+ /**
104
+ * Load configuration for google maps widget
105
+ *
106
+ * @since 1.2.0
107
+ */
108
+ $this->widgets[] = new Google_Maps_Widget( $this->settings, $this->script_loader_tag, $this->cookie_consent, $this->buffer_output, $this->get_widget_option() );
109
+
110
+ /**
111
+ * Load configuration for internet defense league widget
112
+ *
113
+ * @since 1.2.0
114
+ */
115
+ $this->widgets[] = new Internet_Defense_league_Widget( $this->settings, $this->script_loader_tag, $this->cookie_consent, $this->buffer_output, $this->get_widget_option() );
116
+
117
+ /**
118
+ * Load configuration for visitor cookies
119
+ *
120
+ * @since 1.2.0
121
+ */
122
+ $this->widgets[] = new Visitor_Cookies( $this->settings, $this->script_loader_tag, $this->cookie_consent, $this->buffer_output, $this->get_widget_option() );
123
+
124
+ /**
125
+ * Load configuration for twitter timeline widget
126
+ *
127
+ * @since 1.2.0
128
+ */
129
+ $this->widgets[] = new Twitter_Timeline_Widget( $this->settings, $this->script_loader_tag, $this->cookie_consent, $this->buffer_output, $this->get_widget_option() );
130
+
131
+ /**
132
+ * Load configuration for goodreads widget
133
+ *
134
+ * @since 1.2.0
135
+ */
136
+ $this->widgets[] = new Goodreads_Widget( $this->settings, $this->script_loader_tag, $this->cookie_consent, $this->buffer_output, $this->get_widget_option() );
137
+
138
+ /**
139
+ * Load configuration for facebook widget
140
+ *
141
+ * @since 1.2.0
142
+ */
143
+ $this->widgets[] = new Facebook_Widget( $this->settings, $this->script_loader_tag, $this->cookie_consent, $this->buffer_output, $this->get_widget_option() );
144
+
145
+ /**
146
+ * If jetpack version is lower than 7 than add googleplus badge widget
147
+ *
148
+ * @since 2.2.1
149
+ */
150
+ if( $this->is_addon_installed() && version_compare($this->get_addon_version(), '7', '<' ) ) {
151
+ /**
152
+ * Load configuration for googleplus badge widget
153
+ *
154
+ * @since 1.2.0
155
+ */
156
+ $this->widgets[] = new Googleplus_Badge_Widget( $this->settings, $this->script_loader_tag, $this->cookie_consent, $this->buffer_output, $this->get_widget_option() );
157
+ }
158
+ }
159
+
160
+ /**
161
+ * Load widgets configuration
162
+ *
163
+ * @since 1.8.0
164
+ */
165
+ public function load_widgets() {
166
+ foreach( $this->get_widgets() as $widget ) {
167
+ $widget->load_configuration();
168
+ }
169
+ }
170
+
171
+ /**
172
+ * Return addon/plugin name
173
+ *
174
+ * @return string
175
+ *
176
+ * @since 1.3.0
177
+ */
178
+ public function get_addon_name() {
179
+ return 'Jetpack';
180
+ }
181
+
182
+ /**
183
+ * Option name in the database
184
+ *
185
+ * @return string
186
+ *
187
+ * @since 1.3.0
188
+ */
189
+ public function get_option_name() {
190
+ return 'jetpack';
191
+ }
192
+
193
+ /**
194
+ * Returns widget option key for in the database
195
+ *
196
+ * @return string
197
+ *
198
+ * @since 1.3.0
199
+ */
200
+ public function get_widget_option() {
201
+ return 'cookiebot_jetpack_addon';
202
+ }
203
+
204
+ /**
205
+ * Plugin file name
206
+ *
207
+ * @return string
208
+ *
209
+ * @since 1.3.0
210
+ */
211
+ public function get_plugin_file() {
212
+ return 'jetpack/jetpack.php';
213
+ }
214
+
215
+ /**
216
+ * Returns checked cookie types
217
+ * @return mixed
218
+ *
219
+ * @since 1.3.0
220
+ */
221
+ public function get_cookie_types() {
222
+ return $this->settings->get_cookie_types( $this->get_option_name(), $this->get_default_cookie_types() );
223
+ }
224
+
225
+ /**
226
+ * Returns default cookie types
227
+ * @return array
228
+ *
229
+ * @since 1.5.0
230
+ */
231
+ public function get_default_cookie_types() {
232
+ return array( 'statistics' );
233
+ }
234
+
235
+ /**
236
+ * Check if plugin is activated and checked in the backend
237
+ *
238
+ * @since 1.3.0
239
+ */
240
+ public function is_addon_enabled() {
241
+ return $this->settings->is_addon_enabled( $this->get_option_name() );
242
+ }
243
+
244
+ /**
245
+ * Checks if addon is installed
246
+ *
247
+ * @since 1.3.0
248
+ */
249
+ public function is_addon_installed() {
250
+ return $this->settings->is_addon_installed( $this->get_plugin_file() );
251
+ }
252
+
253
+ /**
254
+ * Checks if addon is activated
255
+ *
256
+ * @since 1.3.0
257
+ */
258
+ public function is_addon_activated() {
259
+ return $this->settings->is_addon_activated( $this->get_plugin_file() );
260
+ }
261
+
262
+ /**
263
+ * Retrieves current installed version of the addon
264
+ *
265
+ * @return bool
266
+ *
267
+ * @since 2.2.1
268
+ */
269
+ public function get_addon_version() {
270
+ return $this->settings->get_addon_version( $this->get_plugin_file() );
271
+ }
272
+
273
+ /**
274
+ * Returns all supported widgets
275
+ *
276
+ * @return array
277
+ *
278
+ * @since 1.3.0
279
+ */
280
+ public function get_widgets() {
281
+ return $this->widgets;
282
+ }
283
+
284
+ /**
285
+ * Default placeholder content
286
+ *
287
+ * @return string
288
+ *
289
+ * @since 1.8.0
290
+ */
291
+ public function get_default_placeholder() {
292
+ return 'Please accept [renew_consent]%cookie_types[/renew_consent] cookies to watch this video.';
293
+ }
294
+
295
+ /**
296
+ * Get placeholder content
297
+ *
298
+ * This function will check following features:
299
+ * - Current language
300
+ *
301
+ * @param $src
302
+ *
303
+ * @return bool|mixed
304
+ *
305
+ * @since 1.8.0
306
+ */
307
+ public function get_placeholder( $src = '' ) {
308
+ return $this->settings->get_placeholder( $this->get_option_name(), $this->get_default_placeholder(), cookiebot_addons_output_cookie_types( $this->get_cookie_types() ), $src );
309
+ }
310
+
311
+ /**
312
+ * Checks if it does have custom placeholder content
313
+ *
314
+ * @return mixed
315
+ *
316
+ * @since 1.8.0
317
+ */
318
+ public function has_placeholder() {
319
+ return $this->settings->has_placeholder( $this->get_option_name() );
320
+ }
321
+
322
+ /**
323
+ * returns all placeholder contents
324
+ *
325
+ * @return mixed
326
+ *
327
+ * @since 1.8.0
328
+ */
329
+ public function get_placeholders() {
330
+ return $this->settings->get_placeholders( $this->get_option_name() );
331
+ }
332
+
333
+ /**
334
+ * Return true if the placeholder is enabled
335
+ *
336
+ * @return mixed
337
+ *
338
+ * @since 1.8.0
339
+ */
340
+ public function is_placeholder_enabled() {
341
+ return $this->settings->is_placeholder_enabled( $this->get_option_name() );
342
+ }
343
+
344
+ /**
345
+ * Adds extra information under the label
346
+ *
347
+ * @return string
348
+ *
349
+ * @since 1.8.0
350
+ */
351
+ public function get_extra_information() {
352
+ return false;
353
+ }
354
+
355
+ /**
356
+ * Returns the url of WordPress SVN repository or another link where we can verify the plugin file.
357
+ *
358
+ * @return boolean
359
+ *
360
+ * @since 1.8.0
361
+ */
362
+ public function get_svn_url() {
363
+ return 'http://plugins.svn.wordpress.org/jetpack/trunk/jetpack.php';
364
+ }
365
+
366
+ /**
367
+ * Placeholder helper overlay in the settings page.
368
+ *
369
+ * @return string
370
+ *
371
+ * @since 1.8.0
372
+ */
373
+ public function get_placeholder_helper() {
374
+ 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>';
375
+ }
376
+
377
+ /**
378
+ * Returns true if addon has an option to remove tag instead of adding attributes
379
+ *
380
+ * @return boolean
381
+ *
382
+ * @since 2.1.0
383
+ */
384
+ public function has_remove_tag_option() {
385
+ return false;
386
+ }
387
+
388
+ /**
389
+ * Returns parent class or false
390
+ *
391
+ * @return string|bool
392
+ *
393
+ * @since 2.1.3
394
+ */
395
+ public function get_parent_class() {
396
+ return get_parent_class( $this );
397
+ }
398
+
399
+ /**
400
+ * Action after enabling the addon on the settings page
401
+ *
402
+ * @since 2.2.0
403
+ */
404
+ public function post_hook_after_enabling() {
405
+ //do nothing
406
+ }
407
+
408
+ /**
409
+ * Cookiebot plugin is deactivated
410
+ *
411
+ * @since 2.2.0
412
+ */
413
+ public function plugin_deactivated() {
414
+ //do nothing
415
+ }
416
+ }
addons/controller/addons/jetpack/visitor-cookies.php ADDED
@@ -0,0 +1,302 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\controller\addons\jetpack;
4
+
5
+ use cookiebot_addons\controller\addons\jetpack\widget\Jetpack_Widget_Interface;
6
+ use cookiebot_addons\lib\buffer\Buffer_Output_Interface;
7
+ use cookiebot_addons\lib\Cookie_Consent_Interface;
8
+ use cookiebot_addons\lib\script_loader_tag\Script_Loader_Tag_Interface;
9
+ use cookiebot_addons\lib\Settings_Service_Interface;
10
+
11
+ class Visitor_Cookies implements Jetpack_Widget_Interface {
12
+
13
+ /**
14
+ * @var array list of supported cookie types
15
+ *
16
+ * @since 1.3.0
17
+ */
18
+ protected $cookie_types;
19
+
20
+ /**
21
+ * @var Settings_Service_Interface
22
+ *
23
+ * @since 1.3.0
24
+ */
25
+ protected $settings;
26
+
27
+ /**
28
+ * @var Script_Loader_Tag_Interface
29
+ *
30
+ * @since 1.3.0
31
+ */
32
+ protected $script_loader_tag;
33
+
34
+ /**
35
+ * @var Cookie_Consent_Interface
36
+ *
37
+ * @since 1.3.0
38
+ */
39
+ protected $cookie_consent;
40
+
41
+ /**
42
+ * @var Buffer_Output_Interface
43
+ *
44
+ * @since 1.3.0
45
+ */
46
+ protected $buffer_output;
47
+
48
+ /**
49
+ * Option name for jetpack addon
50
+ *
51
+ * @var string
52
+ */
53
+ public $widget_option;
54
+
55
+ /**
56
+ * Visitor_Cookies constructor.
57
+ *
58
+ * @param Settings_Service_Interface $settings
59
+ * @param Script_Loader_Tag_Interface $script_loader_tag
60
+ * @param Cookie_Consent_Interface $cookie_consent
61
+ * @param Buffer_Output_Interface $buffer_output
62
+ * @param $widget_option
63
+ *
64
+ * @version 1.8.0
65
+ * @since 1.2.0
66
+ */
67
+ public function __construct( Settings_Service_Interface $settings, Script_Loader_Tag_Interface $script_loader_tag, Cookie_Consent_Interface $cookie_consent, Buffer_Output_Interface $buffer_output, $widget_option ) {
68
+ $this->settings = $settings;
69
+ $this->script_loader_tag = $script_loader_tag;
70
+ $this->cookie_consent = $cookie_consent;
71
+ $this->buffer_output = $buffer_output;
72
+ $this->widget_option = $widget_option;
73
+ }
74
+
75
+ public function load_configuration() {
76
+ /**
77
+ * When preferences consent is not given
78
+ * Then disable comment cookies
79
+ */
80
+ if ( ! $this->cookie_consent->is_cookie_state_accepted( 'preferences' ) ) {
81
+ $this->disable_comment_cookies();
82
+ $this->do_not_save_mobile_or_web_view();
83
+ $this->disable_eu_cookie_law();
84
+ $this->disable_comment_subscriptions();
85
+ }
86
+ }
87
+
88
+ public function get_label() {
89
+ return 'Visitor cookies';
90
+ }
91
+
92
+ /**
93
+ * Returns widget option name
94
+ *
95
+ * @return string
96
+ *
97
+ * @since 1.8.0
98
+ */
99
+ public function get_widget_option_name() {
100
+ return 'visitor_cookies';
101
+ }
102
+
103
+ /**
104
+ * Returns cookie types for a widget
105
+ *
106
+ * @return mixed
107
+ *
108
+ * @since 1.8.0
109
+ */
110
+ public function get_widget_cookie_types() {
111
+ return $this->settings->get_widget_cookie_types( $this->widget_option, $this->get_widget_option_name() );
112
+ }
113
+
114
+ /**
115
+ * Checks if a widget is enabled
116
+ *
117
+ * @return mixed
118
+ *
119
+ * @since 1.8.0
120
+ */
121
+ public function is_widget_enabled() {
122
+ return $this->settings->is_widget_enabled( $this->widget_option, $this->get_widget_option_name() );
123
+ }
124
+
125
+ /**
126
+ * @return string
127
+ */
128
+ public function get_default_placeholder() {
129
+ return 'Please accept [renew_consent]%cookie_types[/renew_consent] cookies to watch this video.';
130
+ }
131
+
132
+ /**
133
+ * Checks if widget has existing placeholders
134
+ *
135
+ * @return mixed
136
+ *
137
+ * @since 1.8.0
138
+ */
139
+ public function widget_has_placeholder() {
140
+ return $this->settings->widget_has_placeholder( $this->widget_option, $this->get_widget_option_name() );
141
+ }
142
+
143
+ /**
144
+ * Returns all widget placeholders
145
+ *
146
+ * @return mixed
147
+ *
148
+ * @since 1.8.0
149
+ */
150
+ public function get_widget_placeholders() {
151
+ return $this->settings->get_widget_placeholders( $this->widget_option, $this->get_widget_option_name() );
152
+ }
153
+
154
+ /**
155
+ * Checks if a widget placeholder is enabled
156
+ *
157
+ * @return boolean true If widget placeholder is checked
158
+ * false If widget placeholder is not checked
159
+ *
160
+ * @since 1.8.0
161
+ */
162
+ public function is_widget_placeholder_enabled() {
163
+ return $this->settings->is_widget_placeholder_enabled( $this->widget_option, $this->get_widget_option_name() );
164
+ }
165
+
166
+ /**
167
+ * returns widget placeholder
168
+ *
169
+ * @return mixed
170
+ *
171
+ * @since 1.8.0
172
+ */
173
+ public function get_widget_placeholder() {
174
+ return $this->settings->get_widget_placeholder( $this->widget_option, $this->get_widget_option_name(), $this->get_default_placeholder(), $this->get_widget_cookie_types() );
175
+ }
176
+
177
+ /**
178
+ * Set comment subscribe cookie time to zero so it expires.
179
+ *
180
+ * @since 1.2.0
181
+ */
182
+ protected function disable_comment_subscriptions() {
183
+ add_filter( 'comment_cookie_lifetime', function ( $time ) {
184
+ return 0;
185
+ } );
186
+ }
187
+
188
+ /**
189
+ * Disable eu cookie law script
190
+ *
191
+ * @since 1.2.0
192
+ */
193
+ protected function disable_eu_cookie_law() {
194
+ $this->script_loader_tag->add_tag( 'eu-cookie-law-script', array( 'preferences' ) );
195
+ }
196
+
197
+ /**
198
+ * Disable cookie comments
199
+ *
200
+ * Cookies:
201
+ * - comment_author_{HASH}
202
+ * - comment_author_email_{HASH}
203
+ * - comment_author_url_{HASH}
204
+ * @since 1.2.0
205
+ */
206
+ protected function disable_comment_cookies() {
207
+ /**
208
+ * Remove action comment cookies in jetpack
209
+ *
210
+ * we have to remove this action, because it does manually add the cookie.
211
+ */
212
+ cookiebot_addons_remove_class_action( 'comment_post', 'Highlander_Comments_Base', 'set_comment_cookies' );
213
+
214
+ /**
215
+ * Remove action comment cookies in wordpress core
216
+ *
217
+ * we have to remove this action, because it does manually add the cookie.
218
+ */
219
+ if ( has_action( 'set_comment_cookies', 'wp_set_comment_cookies' ) ) {
220
+ remove_action( 'set_comment_cookies', 'wp_set_comment_cookies' );
221
+ }
222
+ }
223
+
224
+ /**
225
+ * Doesn't save the visitor wish in cookie
226
+ *
227
+ * Cookie:
228
+ * - akm_mobile
229
+ *
230
+ * @since 1.2.0
231
+ */
232
+ protected function do_not_save_mobile_or_web_view() {
233
+ /**
234
+ * we have to remove this action, because it does manually add the cookie.
235
+ */
236
+ if ( has_action( 'init', 'jetpack_mobile_request_handler' ) ) {
237
+ remove_action( 'init', 'jetpack_mobile_request_handler' );
238
+ }
239
+
240
+ /**
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
+
248
+ /**
249
+ * Display message to enable
250
+ *
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
+ }
258
+
259
+ /**
260
+ * Adds extra information under the label
261
+ *
262
+ * @return string
263
+ *
264
+ * @since 1.8.0
265
+ */
266
+ public function get_extra_information() {
267
+ return false;
268
+ }
269
+
270
+ /**
271
+ * Placeholder helper overlay in the settings page.
272
+ *
273
+ * @return string
274
+ *
275
+ * @since 1.8.0
276
+ */
277
+ public function get_placeholder_helper() {
278
+ 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>';
279
+ }
280
+
281
+ /**
282
+ * Returns true if addon has an option to remove tag instead of adding attributes
283
+ *
284
+ * @return boolean
285
+ *
286
+ * @since 2.1.0
287
+ */
288
+ public function has_remove_tag_option() {
289
+ return true;
290
+ }
291
+
292
+ /**
293
+ * Return true if the remove tag option is enabled
294
+ *
295
+ * @return mixed
296
+ *
297
+ * @since 2.1.0
298
+ */
299
+ public function is_widget_remove_tag_enabled() {
300
+ return $this->settings->is_widget_remove_tag_enabled( $this->widget_option, $this->get_widget_option_name() );
301
+ }
302
+ }
addons/controller/addons/jetpack/widget/facebook-widget.php ADDED
@@ -0,0 +1,246 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\controller\addons\jetpack\widget;
4
+
5
+ use cookiebot_addons\lib\Settings_Service_Interface;
6
+ use cookiebot_addons\lib\script_loader_tag\Script_Loader_Tag_Interface;
7
+ use cookiebot_addons\lib\Cookie_Consent_Interface;
8
+ use cookiebot_addons\lib\buffer\Buffer_Output_Interface;
9
+
10
+ /**
11
+ * This class is used to add cookiebot consent to facebook widget
12
+ *
13
+ * @since 1.2.0
14
+ */
15
+ class Facebook_Widget {
16
+
17
+ /**
18
+ * @var array list of supported cookie types
19
+ *
20
+ * @since 1.3.0
21
+ */
22
+ protected $cookie_types;
23
+
24
+ /**
25
+ * @var Settings_Service_Interface
26
+ *
27
+ * @since 1.3.0
28
+ */
29
+ protected $settings;
30
+
31
+ /**
32
+ * @var Script_Loader_Tag_Interface
33
+ *
34
+ * @since 1.3.0
35
+ */
36
+ protected $script_loader_tag;
37
+
38
+ /**
39
+ * @var Cookie_Consent_Interface
40
+ *
41
+ * @since 1.3.0
42
+ */
43
+ protected $cookie_consent;
44
+
45
+ /**
46
+ * @var Buffer_Output_Interface
47
+ *
48
+ * @since 1.3.0
49
+ */
50
+ protected $buffer_output;
51
+
52
+ /**
53
+ * Option name for jetpack addon
54
+ *
55
+ * @var string
56
+ */
57
+ public $widget_option;
58
+
59
+ /**
60
+ * Facebook_Widget constructor.
61
+ *
62
+ * @param Settings_Service_Interface $settings
63
+ * @param Script_Loader_Tag_Interface $script_loader_tag
64
+ * @param Cookie_Consent_Interface $cookie_consent
65
+ * @param Buffer_Output_Interface $buffer_output
66
+ * @param string $widget_option
67
+ *
68
+ * @version 1.8.0
69
+ * @since 1.2.0
70
+ */
71
+ public function __construct( Settings_Service_Interface $settings, Script_Loader_Tag_Interface $script_loader_tag, Cookie_Consent_Interface $cookie_consent, Buffer_Output_Interface $buffer_output, $widget_option ) {
72
+ $this->settings = $settings;
73
+ $this->script_loader_tag = $script_loader_tag;
74
+ $this->cookie_consent = $cookie_consent;
75
+ $this->buffer_output = $buffer_output;
76
+ $this->widget_option = $widget_option;
77
+ }
78
+
79
+ public function load_configuration() {
80
+ if ( is_active_widget( false, false, 'facebook-likebox', true ) ) {
81
+ if ( $this->is_widget_enabled() ) {
82
+ /**
83
+ * Manipulate script attribute
84
+ */
85
+ $this->add_consent_attribute_to_facebook_embed_javascript();
86
+
87
+ /**
88
+ * Display placeholder if allowed in the backend settings
89
+ */
90
+ if ( $this->is_widget_placeholder_enabled() ) {
91
+ add_action( 'jetpack_stats_extra', array( $this, 'cookie_consent_div' ), 10, 2 );
92
+ }
93
+ }
94
+ }
95
+ }
96
+
97
+ public function get_label() {
98
+ return 'Facebook';
99
+ }
100
+
101
+ /**
102
+ * Returns widget option name
103
+ *
104
+ * @return string
105
+ *
106
+ * @since 1.8.0
107
+ */
108
+ public function get_widget_option_name() {
109
+ return 'facebook';
110
+ }
111
+
112
+ /**
113
+ * Returns cookie types for a widget
114
+ *
115
+ * @return mixed
116
+ *
117
+ * @since 1.8.0
118
+ */
119
+ public function get_widget_cookie_types() {
120
+ return $this->settings->get_widget_cookie_types( $this->widget_option, $this->get_widget_option_name() );
121
+ }
122
+
123
+ /**
124
+ * Checks if a widget is enabled
125
+ *
126
+ * @return mixed
127
+ *
128
+ * @since 1.8.0
129
+ */
130
+ public function is_widget_enabled() {
131
+ return $this->settings->is_widget_enabled( $this->widget_option, $this->get_widget_option_name() );
132
+ }
133
+
134
+ /**
135
+ * @return string
136
+ */
137
+ public function get_default_placeholder() {
138
+ return 'Please accept [renew_consent]%cookie_types[/renew_consent] cookies to see facebook widget.';
139
+ }
140
+
141
+ /**
142
+ * Checks if a widget placeholder is enabled
143
+ *
144
+ * @return boolean true If widget placeholder is checked
145
+ * false If widget placeholder is not checked
146
+ *
147
+ * @since 1.8.0
148
+ */
149
+ public function is_widget_placeholder_enabled() {
150
+ return $this->settings->is_widget_placeholder_enabled( $this->widget_option, $this->get_widget_option_name() );
151
+ }
152
+
153
+ /**
154
+ * Checks if widget has existing placeholders
155
+ *
156
+ * @return mixed
157
+ *
158
+ * @since 1.8.0
159
+ */
160
+ public function widget_has_placeholder() {
161
+ return $this->settings->widget_has_placeholder( $this->widget_option, $this->get_widget_option_name() );
162
+ }
163
+
164
+ /**
165
+ * Returns all widget placeholders
166
+ *
167
+ * @return mixed
168
+ *
169
+ * @since 1.8.0
170
+ */
171
+ public function get_widget_placeholders() {
172
+ return $this->settings->get_widget_placeholders( $this->widget_option, $this->get_widget_option_name() );
173
+ }
174
+
175
+ /**
176
+ * returns widget placeholder
177
+ *
178
+ * @return mixed
179
+ *
180
+ * @since 1.8.0
181
+ */
182
+ public function get_widget_placeholder() {
183
+ return $this->settings->get_widget_placeholder( $this->widget_option, $this->get_widget_option_name(), $this->get_default_placeholder(), cookiebot_addons_output_cookie_types( $this->get_widget_cookie_types() ) );
184
+ }
185
+
186
+
187
+ /**
188
+ * Tag external Facebook javascript file with cookiebot consent.
189
+ *
190
+ * @since 1.2.0
191
+ */
192
+ protected function add_consent_attribute_to_facebook_embed_javascript() {
193
+ $this->script_loader_tag->add_tag( 'jetpack-facebook-embed', $this->get_widget_cookie_types() );
194
+ }
195
+
196
+ /**
197
+ * Show consent message when the consent is not given.
198
+ *
199
+ * @param $view string
200
+ * @param $widget string
201
+ *
202
+ * @since 1.6.0
203
+ */
204
+ public function cookie_consent_div( $view, $widget ) {
205
+ if ( $widget == 'facebook-likebox' && $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() ) . '">
208
+ ' . $this->get_widget_placeholder() . '
209
+ </div>';
210
+ }
211
+ }
212
+ }
213
+
214
+ /**
215
+ * Adds extra information under the label
216
+ *
217
+ * @return string
218
+ *
219
+ * @since 1.8.0
220
+ */
221
+ public function get_extra_information() {
222
+ return '<p>' . __( 'Facebook widget.', 'cookiebot-addons' ) . '</p>';
223
+ }
224
+
225
+ /**
226
+ * Placeholder helper overlay in the settings page.
227
+ *
228
+ * @return string
229
+ *
230
+ * @since 1.8.0
231
+ */
232
+ public function get_placeholder_helper() {
233
+ 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>';
234
+ }
235
+
236
+ /**
237
+ * Returns true if addon has an option to remove tag instead of adding attributes
238
+ *
239
+ * @return boolean
240
+ *
241
+ * @since 2.1.0
242
+ */
243
+ public function has_remove_tag_option() {
244
+ return false;
245
+ }
246
+ }
addons/controller/addons/jetpack/widget/goodreads-widget.php ADDED
@@ -0,0 +1,301 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\controller\addons\jetpack\widget;
4
+
5
+ use cookiebot_addons\lib\Settings_Service_Interface;
6
+ use cookiebot_addons\lib\script_loader_tag\Script_Loader_Tag_Interface;
7
+ use cookiebot_addons\lib\Cookie_Consent_Interface;
8
+ use cookiebot_addons\lib\buffer\Buffer_Output_Interface;
9
+
10
+ class Goodreads_Widget implements Jetpack_Widget_Interface {
11
+
12
+ protected $widget_id;
13
+
14
+ protected $transient_name;
15
+
16
+ protected $keywords;
17
+
18
+ /**
19
+ * @var array list of supported cookie types
20
+ *
21
+ * @since 1.3.0
22
+ */
23
+ protected $cookie_types;
24
+
25
+ /**
26
+ * @var Settings_Service_Interface
27
+ *
28
+ * @since 1.3.0
29
+ */
30
+ protected $settings;
31
+
32
+ /**
33
+ * @var Script_Loader_Tag_Interface
34
+ *
35
+ * @since 1.3.0
36
+ */
37
+ protected $script_loader_tag;
38
+
39
+ /**
40
+ * @var Cookie_Consent_Interface
41
+ *
42
+ * @since 1.3.0
43
+ */
44
+ protected $cookie_consent;
45
+
46
+ /**
47
+ * @var Buffer_Output_Interface
48
+ *
49
+ * @since 1.3.0
50
+ */
51
+ protected $buffer_output;
52
+
53
+ /**
54
+ * Option name for jetpack addon
55
+ *
56
+ * @var string
57
+ */
58
+ public $widget_option;
59
+
60
+ /**
61
+ * Goodreads_Widget constructor.
62
+ *
63
+ * @param Settings_Service_Interface $settings
64
+ * @param Script_Loader_Tag_Interface $script_loader_tag
65
+ * @param Cookie_Consent_Interface $cookie_consent
66
+ * @param Buffer_Output_Interface $buffer_output
67
+ * @param $widget_option
68
+ *
69
+ * @version 1.8.0
70
+ * @since 1.3.0
71
+ */
72
+ public function __construct( Settings_Service_Interface $settings, Script_Loader_Tag_Interface $script_loader_tag, Cookie_Consent_Interface $cookie_consent, Buffer_Output_Interface $buffer_output, $widget_option ) {
73
+ $this->settings = $settings;
74
+ $this->script_loader_tag = $script_loader_tag;
75
+ $this->cookie_consent = $cookie_consent;
76
+ $this->buffer_output = $buffer_output;
77
+ $this->widget_option = $widget_option;
78
+ }
79
+
80
+ public function load_configuration() {
81
+ if ( is_active_widget( false, false, 'wpcom-goodreads', true ) ) {
82
+ if ( $this->is_widget_enabled() ) {
83
+ if ( $this->is_widget_placeholder_enabled() ) {
84
+ add_action( 'jetpack_stats_extra', array( $this, 'cookie_consent_div' ), 10, 2 );
85
+ }
86
+
87
+ $this->transient_name = 'wpcom-goodreads';
88
+
89
+ $this->keywords = array( 'www.goodreads.com' => $this->get_widget_cookie_types() );
90
+ $this->block_javascript_file();
91
+ $this->output_manipulated();
92
+ }
93
+ }
94
+ }
95
+
96
+ public function get_label() {
97
+ return 'Goodreads';
98
+ }
99
+
100
+ /**
101
+ * Returns widget option name
102
+ *
103
+ * @return string
104
+ *
105
+ * @since 1.8.0
106
+ */
107
+ public function get_widget_option_name() {
108
+ return 'goodreads';
109
+ }
110
+
111
+ /**
112
+ * Returns cookie types for a widget
113
+ *
114
+ * @return mixed
115
+ *
116
+ * @since 1.8.0
117
+ */
118
+ public function get_widget_cookie_types() {
119
+ return $this->settings->get_widget_cookie_types( $this->widget_option, $this->get_widget_option_name() );
120
+ }
121
+
122
+ /**
123
+ * Checks if a widget is enabled
124
+ *
125
+ * @return mixed
126
+ *
127
+ * @since 1.8.0
128
+ */
129
+ public function is_widget_enabled() {
130
+ return $this->settings->is_widget_enabled( $this->widget_option, $this->get_widget_option_name() );
131
+ }
132
+
133
+ /**
134
+ * Checks if widget has existing placeholders
135
+ *
136
+ * @return mixed
137
+ *
138
+ * @since 1.8.0
139
+ */
140
+ public function widget_has_placeholder() {
141
+ return $this->settings->widget_has_placeholder( $this->widget_option, $this->get_widget_option_name() );
142
+ }
143
+
144
+ /**
145
+ * @return string
146
+ */
147
+ public function get_default_placeholder() {
148
+ return 'Please accept [renew_consent]%cookie_types[/renew_consent] cookies to watch goodreads.';
149
+ }
150
+
151
+ /**
152
+ * Returns all widget placeholders
153
+ *
154
+ * @return mixed
155
+ *
156
+ * @since 1.8.0
157
+ */
158
+ public function get_widget_placeholders() {
159
+ return $this->settings->get_widget_placeholders( $this->widget_option, $this->get_widget_option_name() );
160
+ }
161
+
162
+ /**
163
+ * Checks if a widget placeholder is enabled
164
+ *
165
+ * @return boolean true If widget placeholder is checked
166
+ * false If widget placeholder is not checked
167
+ *
168
+ * @since 1.8.0
169
+ */
170
+ public function is_widget_placeholder_enabled() {
171
+ return $this->settings->is_widget_placeholder_enabled( $this->widget_option, $this->get_widget_option_name() );
172
+ }
173
+
174
+ /**
175
+ * returns widget placeholder
176
+ *
177
+ * @return mixed
178
+ *
179
+ * @since 1.8.0
180
+ */
181
+ public function get_widget_placeholder() {
182
+ return $this->settings->get_widget_placeholder( $this->widget_option, $this->get_widget_option_name(), $this->get_default_placeholder(), cookiebot_addons_output_cookie_types( $this->get_widget_cookie_types() ) );
183
+ }
184
+
185
+ /**
186
+ * Add message to go to consent settings when marketing consent is not accepted
187
+ *
188
+ * @since 1.2.0
189
+ */
190
+ protected function block_javascript_file() {
191
+ add_action( 'dynamic_sidebar', array( $this, 'display_div_message_to_go_to_consent_settings' ), 10, 1 );
192
+ }
193
+
194
+ /**
195
+ * Show a messsage to go to consent settings
196
+ *
197
+ * @param $widget string
198
+ *
199
+ * @since 1.2.0
200
+ */
201
+ public function display_div_message_to_go_to_consent_settings( $widget ) {
202
+ $callback = $widget['callback'][0];
203
+
204
+ if ( $callback->id_base == 'wpcom-goodreads' ) {
205
+ ob_start( array( $this, 'manipulate_script' ) );
206
+ }
207
+ }
208
+
209
+ /**
210
+ * Return widget output after dynamic sidebar is fully processed
211
+ *
212
+ * @since 1.2.0
213
+ */
214
+ public function output_manipulated() {
215
+ add_action( 'dynamic_sidebar_after', function ( $index ) {
216
+ ob_end_flush();
217
+ } );
218
+ }
219
+
220
+ /**
221
+ * Custom manipulation of the script
222
+ *
223
+ * @param $buffer
224
+ *
225
+ * @return mixed|null|string|string[]
226
+ *
227
+ * @since 1.2.0
228
+ */
229
+ public function manipulate_script( $buffer ) {
230
+ /**
231
+ * Get wp head scripts from the cache
232
+ */
233
+ $updated_scripts = get_transient( $this->transient_name );
234
+
235
+ /**
236
+ * If cache is not set then build it
237
+ */
238
+ if ( $updated_scripts === false ) {
239
+
240
+ $updated_scripts = cookiebot_addons_manipulate_script( $buffer, $this->keywords );
241
+
242
+ /**
243
+ * Set cache for 15 minutes
244
+ */
245
+ set_transient( $this->transient_name, $updated_scripts, 60 * 15 );
246
+ }
247
+
248
+ return $updated_scripts;
249
+ }
250
+
251
+ /**
252
+ * Show consent message when the consent is not given.
253
+ *
254
+ * @param $view string
255
+ * @param $widget string
256
+ *
257
+ * @since 1.6.0
258
+ */
259
+ public function cookie_consent_div( $view, $widget ) {
260
+ if ( $widget == 'goodreads' && $view == 'widget_view' ) {
261
+ if ( is_array( $this->get_widget_cookie_types() ) && count( $this->get_widget_cookie_types() ) > 0 ) {
262
+ echo '<div class="cookieconsent-optout-' . cookiebot_addons_get_one_cookie_type( $this->get_widget_cookie_types() ) . '">
263
+ ' . $this->get_widget_placeholder() . '
264
+ </div>';
265
+ }
266
+ }
267
+ }
268
+
269
+ /**
270
+ * Adds extra information under the label
271
+ *
272
+ * @return string
273
+ *
274
+ * @since 1.8.0
275
+ */
276
+ public function get_extra_information() {
277
+ return false;
278
+ }
279
+
280
+ /**
281
+ * Placeholder helper overlay in the settings page.
282
+ *
283
+ * @return string
284
+ *
285
+ * @since 1.8.0
286
+ */
287
+ public function get_placeholder_helper() {
288
+ 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>';
289
+ }
290
+
291
+ /**
292
+ * Returns true if addon has an option to remove tag instead of adding attributes
293
+ *
294
+ * @return boolean
295
+ *
296
+ * @since 2.1.0
297
+ */
298
+ public function has_remove_tag_option() {
299
+ return false;
300
+ }
301
+ }
addons/controller/addons/jetpack/widget/google-maps-widget.php ADDED
@@ -0,0 +1,302 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\controller\addons\jetpack\widget;
4
+
5
+ use cookiebot_addons\lib\buffer\Buffer_Output_Interface;
6
+ use cookiebot_addons\lib\Cookie_Consent_Interface;
7
+ use cookiebot_addons\lib\script_loader_tag\Script_Loader_Tag_Interface;
8
+ use cookiebot_addons\lib\Settings_Service_Interface;
9
+
10
+ class Google_Maps_Widget implements Jetpack_Widget_Interface {
11
+
12
+ /**
13
+ * @var array list of supported cookie types
14
+ *
15
+ * @since 1.3.0
16
+ */
17
+ protected $cookie_types;
18
+
19
+ /**
20
+ * @var Settings_Service_Interface
21
+ *
22
+ * @since 1.3.0
23
+ */
24
+ protected $settings;
25
+
26
+ /**
27
+ * @var Script_Loader_Tag_Interface
28
+ *
29
+ * @since 1.3.0
30
+ */
31
+ protected $script_loader_tag;
32
+
33
+ /**
34
+ * @var Cookie_Consent_Interface
35
+ *
36
+ * @since 1.3.0
37
+ */
38
+ protected $cookie_consent;
39
+
40
+ /**
41
+ * @var Buffer_Output_Interface
42
+ *
43
+ * @since 1.3.0
44
+ */
45
+ protected $buffer_output;
46
+
47
+ /**
48
+ * Option name for jetpack addon
49
+ *
50
+ * @var string
51
+ */
52
+ public $widget_option;
53
+
54
+ /**
55
+ * This class is used to support facebook page widget in jetpack
56
+ *
57
+ * Google_Maps_Widget constructor.
58
+ *
59
+ * @param Settings_Service_Interface $settings
60
+ * @param Script_Loader_Tag_Interface $script_loader_tag
61
+ * @param Cookie_Consent_Interface $cookie_consent
62
+ * @param Buffer_Output_Interface $buffer_output
63
+ * @param string $widget_option
64
+ *
65
+ * @version 1.8.0
66
+ * @since 1.2.0
67
+ */
68
+ public function __construct( Settings_Service_Interface $settings, Script_Loader_Tag_Interface $script_loader_tag, Cookie_Consent_Interface $cookie_consent, Buffer_Output_Interface $buffer_output, $widget_option ) {
69
+ $this->settings = $settings;
70
+ $this->script_loader_tag = $script_loader_tag;
71
+ $this->cookie_consent = $cookie_consent;
72
+ $this->buffer_output = $buffer_output;
73
+ $this->widget_option = $widget_option;
74
+ }
75
+
76
+ public function load_configuration() {
77
+ if ( is_active_widget( false, false, 'widget_contact_info', true ) ) {
78
+ /**
79
+ * Widget is disabled in the backend
80
+ */
81
+ if ( $this->is_widget_enabled() ) {
82
+ $this->cookie_types = $this->get_widget_cookie_types();
83
+
84
+ /**
85
+ * Replace attributes of the google maps widget iframe
86
+ */
87
+ add_action( 'jetpack_contact_info_widget_start', array( $this, 'start_buffer' ) );
88
+ add_action( 'jetpack_contact_info_widget_end', array( $this, 'stop_buffer' ) );
89
+
90
+ if ( $this->is_widget_placeholder_enabled() ) {
91
+ add_action( 'jetpack_stats_extra', array( $this, 'cookie_consent_div' ), 10, 2 );
92
+ }
93
+ }
94
+ }
95
+ }
96
+
97
+ public function get_label() {
98
+ return 'Google Maps';
99
+ }
100
+
101
+ /**
102
+ * Returns widget option name
103
+ *
104
+ * @return string
105
+ *
106
+ * @since 1.8.0
107
+ */
108
+ public function get_widget_option_name() {
109
+ return 'google_maps';
110
+ }
111
+
112
+ /**
113
+ * Returns cookie types for a widget
114
+ *
115
+ * @return mixed
116
+ *
117
+ * @since 1.8.0
118
+ */
119
+ public function get_widget_cookie_types() {
120
+ return $this->settings->get_widget_cookie_types( $this->widget_option, $this->get_widget_option_name() );
121
+ }
122
+
123
+ /**
124
+ * Checks if a widget is enabled
125
+ *
126
+ * @return mixed
127
+ *
128
+ * @since 1.8.0
129
+ */
130
+ public function is_widget_enabled() {
131
+ return $this->settings->is_widget_enabled( $this->widget_option, $this->get_widget_option_name() );
132
+ }
133
+
134
+ /**
135
+ * @return string
136
+ */
137
+ public function get_default_placeholder() {
138
+ return 'Please accept [renew_consent]%cookie_types[/renew_consent] cookies to enable google maps.';
139
+ }
140
+
141
+ /**
142
+ * Checks if a widget placeholder is enabled
143
+ *
144
+ * @return boolean true If widget placeholder is checked
145
+ * false If widget placeholder is not checked
146
+ *
147
+ * @since 1.8.0
148
+ */
149
+ public function is_widget_placeholder_enabled() {
150
+ return $this->settings->is_widget_placeholder_enabled( $this->widget_option, $this->get_widget_option_name() );
151
+ }
152
+
153
+ /**
154
+ * Checks if widget has existing placeholders
155
+ *
156
+ * @return mixed
157
+ *
158
+ * @since 1.8.0
159
+ */
160
+ public function widget_has_placeholder() {
161
+ return $this->settings->widget_has_placeholder( $this->widget_option, $this->get_widget_option_name() );
162
+ }
163
+
164
+ /**
165
+ * Returns all widget placeholders
166
+ *
167
+ * @return mixed
168
+ *
169
+ * @since 1.8.0
170
+ */
171
+ public function get_widget_placeholders() {
172
+ return $this->settings->get_widget_placeholders( $this->widget_option, $this->get_widget_option_name() );
173
+ }
174
+
175
+ /**
176
+ * returns widget placeholder
177
+ *
178
+ * @return mixed
179
+ *
180
+ * @since 1.8.0
181
+ */
182
+ public function get_widget_placeholder() {
183
+ return $this->settings->get_widget_placeholder( $this->widget_option, $this->get_widget_option_name(), $this->get_default_placeholder(), cookiebot_addons_output_cookie_types( $this->get_widget_cookie_types() ) );
184
+ }
185
+
186
+ /**
187
+ * Start catching the output
188
+ *
189
+ * @since 1.2.0
190
+ */
191
+ public function start_buffer() {
192
+ ob_start( array( $this, 'manipulate_iframe' ) );
193
+ }
194
+
195
+ /**
196
+ * Clear the buffer
197
+ *
198
+ * @since 1.2.0
199
+ */
200
+ public function stop_buffer() {
201
+ ob_end_flush();
202
+ }
203
+
204
+ /**
205
+ * Return manipulated output with cookieconsent attribute
206
+ *
207
+ * @param $buffer
208
+ *
209
+ * @return mixed|null|string|string[]
210
+ *
211
+ * @since 1.2.0
212
+ */
213
+ public function manipulate_iframe( $buffer ) {
214
+ /**
215
+ * Get wp head scripts from the cache
216
+ */
217
+ $updated_scripts = get_transient( 'jetpack_google_maps_widget' );
218
+
219
+ /**
220
+ * If cache is not set then build it
221
+ */
222
+ if ( $updated_scripts === false ) {
223
+ /**
224
+ * Pattern to get all iframes
225
+ */
226
+ $pattern = "/\<iframe(.*?)?\>(.|\s)*?\<\/iframe\>/i";
227
+
228
+ /**
229
+ * Get all scripts and add cookieconsent if it does match with the criterion
230
+ */
231
+ $updated_scripts = preg_replace_callback( $pattern, function ( $matches ) {
232
+
233
+ $data = ( isset( $matches[0] ) ) ? $matches[0] : '';
234
+
235
+ $data = str_replace( 'src=', 'data-cookieconsent="' . cookiebot_addons_output_cookie_types( $this->cookie_types ) . '" data-src=', $data );
236
+
237
+ /**
238
+ * Return updated iframe tag
239
+ */
240
+ return $data;
241
+ }, $buffer );
242
+
243
+ /**
244
+ * Set cache for 15 minutes
245
+ */
246
+ set_transient( 'jetpack_google_maps_widget', $updated_scripts, 60 * 15 );
247
+ }
248
+
249
+ return $updated_scripts;
250
+ }
251
+
252
+ /**
253
+ * Show consent message when the consent is not given.
254
+ *
255
+ * @param $view string
256
+ * @param $widget string
257
+ *
258
+ * @since 1.6.0
259
+ */
260
+ public function cookie_consent_div( $view, $widget ) {
261
+ if ( $widget == 'contact_info' && $view == 'widget_view' ) {
262
+ if ( is_array( $this->get_widget_cookie_types() ) && count( $this->get_widget_cookie_types() ) > 0 ) {
263
+ echo '<div class="cookieconsent-optout-' . cookiebot_addons_get_one_cookie_type( $this->get_widget_cookie_types() ) . '">
264
+ ' . $this->get_widget_placeholder() . '
265
+ </div>';
266
+ }
267
+ }
268
+ }
269
+
270
+ /**
271
+ * Adds extra information under the label
272
+ *
273
+ * @return string
274
+ *
275
+ * @since 1.8.0
276
+ */
277
+ public function get_extra_information() {
278
+ return false;
279
+ }
280
+
281
+ /**
282
+ * Placeholder helper overlay in the settings page.
283
+ *
284
+ * @return string
285
+ *
286
+ * @since 1.8.0
287
+ */
288
+ public function get_placeholder_helper() {
289
+ 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>';
290
+ }
291
+
292
+ /**
293
+ * Returns true if addon has an option to remove tag instead of adding attributes
294
+ *
295
+ * @return boolean
296
+ *
297
+ * @since 2.1.0
298
+ */
299
+ public function has_remove_tag_option() {
300
+ return false;
301
+ }
302
+ }
addons/controller/addons/jetpack/widget/googleplus-badge-widget.php ADDED
@@ -0,0 +1,239 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\controller\addons\jetpack\widget;
4
+
5
+ use cookiebot_addons\lib\Settings_Service_Interface;
6
+ use cookiebot_addons\lib\script_loader_tag\Script_Loader_Tag_Interface;
7
+ use cookiebot_addons\lib\Cookie_Consent_Interface;
8
+ use cookiebot_addons\lib\buffer\Buffer_Output_Interface;
9
+
10
+ class Googleplus_Badge_Widget {
11
+
12
+ /**
13
+ * @var array list of supported cookie types
14
+ *
15
+ * @since 1.3.0
16
+ */
17
+ protected $cookie_types;
18
+
19
+ /**
20
+ * @var Settings_Service_Interface
21
+ *
22
+ * @since 1.3.0
23
+ */
24
+ protected $settings;
25
+
26
+ /**
27
+ * @var Script_Loader_Tag_Interface
28
+ *
29
+ * @since 1.3.0
30
+ */
31
+ protected $script_loader_tag;
32
+
33
+ /**
34
+ * @var Cookie_Consent_Interface
35
+ *
36
+ * @since 1.3.0
37
+ */
38
+ protected $cookie_consent;
39
+
40
+ /**
41
+ * @var Buffer_Output_Interface
42
+ *
43
+ * @since 1.3.0
44
+ */
45
+ protected $buffer_output;
46
+
47
+ /**
48
+ * Option name for jetpack addon
49
+ *
50
+ * @var string
51
+ */
52
+ public $widget_option;
53
+
54
+ /**
55
+ * Googleplus_Badge_Widget constructor.
56
+ *
57
+ * @param Settings_Service_Interface $settings
58
+ * @param Script_Loader_Tag_Interface $script_loader_tag
59
+ * @param Cookie_Consent_Interface $cookie_consent
60
+ * @param Buffer_Output_Interface $buffer_output
61
+ * @param $widget_option
62
+ *
63
+ * @version 1.8.0
64
+ * @since 1.2.0
65
+ */
66
+ public function __construct( Settings_Service_Interface $settings, Script_Loader_Tag_Interface $script_loader_tag, Cookie_Consent_Interface $cookie_consent, Buffer_Output_Interface $buffer_output, $widget_option ) {
67
+ $this->settings = $settings;
68
+ $this->script_loader_tag = $script_loader_tag;
69
+ $this->cookie_consent = $cookie_consent;
70
+ $this->buffer_output = $buffer_output;
71
+ $this->widget_option = $widget_option;
72
+ }
73
+
74
+ /**
75
+ * Load configuration
76
+ */
77
+ public function load_configuration() {
78
+ if ( is_active_widget( false, false, 'googleplus-badge', true ) ) {
79
+
80
+ if ( $this->is_widget_enabled() ) {
81
+ $this->cookie_types = $this->get_widget_cookie_types();
82
+
83
+ $this->disable_javascript_file();
84
+
85
+ if ( $this->is_widget_placeholder_enabled() ) {
86
+ add_action( 'jetpack_stats_extra', array( $this, 'display_div_message_to_go_to_consent_settings' ), 10, 2 );
87
+ }
88
+ }
89
+ }
90
+ }
91
+
92
+ public function get_label() {
93
+ return 'Google Plus Badge';
94
+ }
95
+
96
+ /**
97
+ * Returns widget option name
98
+ *
99
+ * @return string
100
+ *
101
+ * @since 1.8.0
102
+ */
103
+ public function get_widget_option_name() {
104
+ return 'googleplus_badge';
105
+ }
106
+
107
+ /**
108
+ * Returns cookie types for a widget
109
+ *
110
+ * @return mixed
111
+ *
112
+ * @since 1.8.0
113
+ */
114
+ public function get_widget_cookie_types() {
115
+ return $this->settings->get_widget_cookie_types( $this->widget_option, $this->get_widget_option_name() );
116
+ }
117
+
118
+ /**
119
+ * Checks if a widget is enabled
120
+ *
121
+ * @return mixed
122
+ *
123
+ * @since 1.8.0
124
+ */
125
+ public function is_widget_enabled() {
126
+ return $this->settings->is_widget_enabled( $this->widget_option, $this->get_widget_option_name() );
127
+ }
128
+
129
+ /**
130
+ * @return string
131
+ */
132
+ public function get_default_placeholder() {
133
+ return 'Please accept [renew_consent]%cookie_types[/renew_consent] cookies to enable google plus badge.';
134
+ }
135
+
136
+ /**
137
+ * Checks if a widget placeholder is enabled
138
+ *
139
+ * @return boolean true If widget placeholder is checked
140
+ * false If widget placeholder is not checked
141
+ *
142
+ * @since 1.8.0
143
+ */
144
+ public function is_widget_placeholder_enabled() {
145
+ return $this->settings->is_widget_placeholder_enabled( $this->widget_option, $this->get_widget_option_name() );
146
+ }
147
+
148
+ /**
149
+ * Checks if widget has existing placeholders
150
+ *
151
+ * @return mixed
152
+ *
153
+ * @since 1.8.0
154
+ */
155
+ public function widget_has_placeholder() {
156
+ return $this->settings->widget_has_placeholder( $this->widget_option, $this->get_widget_option_name() );
157
+ }
158
+
159
+ /**
160
+ * Returns all widget placeholders
161
+ *
162
+ * @return mixed
163
+ *
164
+ * @since 1.8.0
165
+ */
166
+ public function get_widget_placeholders() {
167
+ return $this->settings->get_widget_placeholders( $this->widget_option, $this->get_widget_option_name() );
168
+ }
169
+
170
+ /**
171
+ * returns widget placeholder
172
+ *
173
+ * @return mixed
174
+ *
175
+ * @since 1.8.0
176
+ */
177
+ public function get_widget_placeholder() {
178
+ return $this->settings->get_widget_placeholder( $this->widget_option, $this->get_widget_option_name(), $this->get_default_placeholder(), cookiebot_addons_output_cookie_types( $this->get_widget_cookie_types() ) );
179
+ }
180
+
181
+ /**
182
+ * Disable javascript file if marketing consent is not given
183
+ *
184
+ * @since 1.2.0
185
+ */
186
+ protected function disable_javascript_file() {
187
+ $this->script_loader_tag->add_tag( 'googleplus-widget', $this->cookie_types );
188
+ }
189
+
190
+ /**
191
+ * Show a messsage to go to consent settings
192
+ *
193
+ * @param $view string
194
+ * @param $widget string
195
+ *
196
+ * @since 1.2.0
197
+ */
198
+ public function display_div_message_to_go_to_consent_settings( $view, $widget ) {
199
+ if ( $widget == 'googleplus-badge' && $view == 'widget_view' ) {
200
+ if ( is_array( $this->cookie_types ) && count( $this->cookie_types ) > 0 ) {
201
+ echo '<div class="cookieconsent-optout-' . cookiebot_addons_get_one_cookie_type( $this->cookie_types ) . '">' . $this->get_widget_placeholder() . '</div>';
202
+ }
203
+
204
+ }
205
+ }
206
+
207
+ /**
208
+ * Adds extra information under the label
209
+ *
210
+ * @return string
211
+ *
212
+ * @since 1.8.0
213
+ */
214
+ public function get_extra_information() {
215
+ return false;
216
+ }
217
+
218
+ /**
219
+ * Placeholder helper overlay in the settings page.
220
+ *
221
+ * @return string
222
+ *
223
+ * @since 1.8.0
224
+ */
225
+ public function get_placeholder_helper() {
226
+ 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>';
227
+ }
228
+
229
+ /**
230
+ * Returns true if addon has an option to remove tag instead of adding attributes
231
+ *
232
+ * @return boolean
233
+ *
234
+ * @since 2.1.0
235
+ */
236
+ public function has_remove_tag_option() {
237
+ return false;
238
+ }
239
+ }
addons/controller/addons/jetpack/widget/internet-defense-league-widget.php ADDED
@@ -0,0 +1,254 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\controller\addons\jetpack\widget;
4
+
5
+ use cookiebot_addons\lib\buffer\Buffer_Output_Interface;
6
+ use cookiebot_addons\lib\Cookie_Consent_Interface;
7
+ use cookiebot_addons\lib\script_loader_tag\Script_Loader_Tag_Interface;
8
+ use cookiebot_addons\lib\Settings_Service_Interface;
9
+
10
+ class Internet_Defense_league_Widget implements Jetpack_Widget_Interface {
11
+
12
+ /**
13
+ * @var array list of supported cookie types
14
+ *
15
+ * @since 1.3.0
16
+ */
17
+ protected $cookie_types;
18
+
19
+ /**
20
+ * @var Settings_Service_Interface
21
+ *
22
+ * @since 1.3.0
23
+ */
24
+ protected $settings;
25
+
26
+ /**
27
+ * @var Script_Loader_Tag_Interface
28
+ *
29
+ * @since 1.3.0
30
+ */
31
+ protected $script_loader_tag;
32
+
33
+ /**
34
+ * @var Cookie_Consent_Interface
35
+ *
36
+ * @since 1.3.0
37
+ */
38
+ protected $cookie_consent;
39
+
40
+ /**
41
+ * @var Buffer_Output_Interface
42
+ *
43
+ * @since 1.3.0
44
+ */
45
+ protected $buffer_output;
46
+
47
+ /**
48
+ * Option name for jetpack addon
49
+ *
50
+ * @var string
51
+ */
52
+ public $widget_option;
53
+
54
+ /**
55
+ * Internet_Defense_league_Widget constructor.
56
+ *
57
+ * @param Settings_Service_Interface $settings
58
+ * @param Script_Loader_Tag_Interface $script_loader_tag
59
+ * @param Cookie_Consent_Interface $cookie_consent
60
+ * @param Buffer_Output_Interface $buffer_output
61
+ * @param $widget_option
62
+ *
63
+ * @since 1.2.0
64
+ */
65
+ public function __construct( Settings_Service_Interface $settings, Script_Loader_Tag_Interface $script_loader_tag, Cookie_Consent_Interface $cookie_consent, Buffer_Output_Interface $buffer_output, $widget_option ) {
66
+ $this->settings = $settings;
67
+ $this->script_loader_tag = $script_loader_tag;
68
+ $this->cookie_consent = $cookie_consent;
69
+ $this->buffer_output = $buffer_output;
70
+ $this->widget_option = $widget_option;
71
+ }
72
+
73
+ public function load_configuration() {
74
+ if ( is_active_widget( false, false, 'internet_defense_league_widget', true ) ) {
75
+
76
+ if ( $this->is_widget_enabled() ) {
77
+
78
+ /**
79
+ * Remove wp_footer script when the cookieconsent for marketing is not given
80
+ *
81
+ * @since 1.2.0
82
+ */
83
+ if ( ! $this->cookie_consent->are_cookie_states_accepted( $this->get_widget_cookie_types() ) ) {
84
+ if( $this->is_widget_remove_tag_enabled() ) {
85
+ cookiebot_addons_remove_class_action( 'wp_footer', 'Jetpack_Internet_Defense_League_Widget', 'footer_script' );
86
+ }
87
+ else {
88
+ $this->buffer_output->add_tag( 'wp_footer', 10, array(
89
+ 'window._idl' => $this->get_widget_cookie_types(),
90
+ ), false );
91
+ }
92
+ }
93
+
94
+ /**
95
+ * Display placeholder if allowed in the backend settings
96
+ */
97
+ if ( $this->is_widget_placeholder_enabled() ) {
98
+ add_action( 'jetpack_stats_extra', array( $this, 'cookie_consent_div' ), 10, 2 );
99
+ }
100
+ }
101
+ }
102
+ }
103
+
104
+ public function get_label() {
105
+ return 'Internet defense league';
106
+ }
107
+
108
+ /**
109
+ * Returns widget option name
110
+ *
111
+ * @return string
112
+ *
113
+ * @since 1.8.0
114
+ */
115
+ public function get_widget_option_name() {
116
+ return 'internet_defense_league';
117
+ }
118
+
119
+ /**
120
+ * Returns cookie types for a widget
121
+ *
122
+ * @return mixed
123
+ *
124
+ * @since 1.8.0
125
+ */
126
+ public function get_widget_cookie_types() {
127
+ return $this->settings->get_widget_cookie_types( $this->widget_option, $this->get_widget_option_name() );
128
+ }
129
+
130
+ /**
131
+ * Checks if a widget is enabled
132
+ *
133
+ * @return mixed
134
+ *
135
+ * @since 1.8.0
136
+ */
137
+ public function is_widget_enabled() {
138
+ return $this->settings->is_widget_enabled( $this->widget_option, $this->get_widget_option_name() );
139
+ }
140
+
141
+ /**
142
+ * @return string
143
+ */
144
+ public function get_default_placeholder() {
145
+ return 'Please accept [renew_consent]%cookie_types[/renew_consent] cookies to enable internet defense league.';
146
+ }
147
+
148
+ /**
149
+ * Checks if a widget placeholder is enabled
150
+ *
151
+ * @return boolean true If widget placeholder is checked
152
+ * false If widget placeholder is not checked
153
+ *
154
+ * @since 1.8.0
155
+ */
156
+ public function is_widget_placeholder_enabled() {
157
+ return $this->settings->is_widget_placeholder_enabled( $this->widget_option, $this->get_widget_option_name() );
158
+ }
159
+
160
+ /**
161
+ * Checks if widget has existing placeholders
162
+ *
163
+ * @return mixed
164
+ *
165
+ * @since 1.8.0
166
+ */
167
+ public function widget_has_placeholder() {
168
+ return $this->settings->widget_has_placeholder( $this->widget_option, $this->get_widget_option_name() );
169
+ }
170
+
171
+ /**
172
+ * Returns all widget placeholders
173
+ *
174
+ * @return mixed
175
+ *
176
+ * @since 1.8.0
177
+ */
178
+ public function get_widget_placeholders() {
179
+ return $this->settings->get_widget_placeholders( $this->widget_option, $this->get_widget_option_name() );
180
+ }
181
+
182
+ /**
183
+ * returns widget placeholder
184
+ *
185
+ * @return mixed
186
+ *
187
+ * @since 1.8.0
188
+ */
189
+ public function get_widget_placeholder() {
190
+ return $this->settings->get_widget_placeholder( $this->widget_option, $this->get_widget_option_name(), $this->get_default_placeholder(), cookiebot_addons_output_cookie_types( $this->get_widget_cookie_types() ) );
191
+ }
192
+
193
+ /**
194
+ * Show consent message when the consent is not given.
195
+ *
196
+ * @param $view string
197
+ * @param $widget string
198
+ *
199
+ * @since 1.6.0
200
+ */
201
+ public function cookie_consent_div( $view, $widget ) {
202
+ if ( $widget == 'internet_defense_league' && $view == 'widget_view' ) {
203
+ if ( is_array( $this->get_widget_cookie_types() ) && count( $this->get_widget_cookie_types() ) > 0 ) {
204
+ echo '<div class="cookieconsent-optout-' . cookiebot_addons_get_one_cookie_type( $this->get_widget_cookie_types() ) . '">
205
+ ' . $this->get_widget_placeholder() . '
206
+ </div>';
207
+ }
208
+ }
209
+ }
210
+
211
+ /**
212
+ * Adds extra information under the label
213
+ *
214
+ * @return string
215
+ *
216
+ * @since 1.8.0
217
+ */
218
+ public function get_extra_information() {
219
+ return false;
220
+ }
221
+
222
+ /**
223
+ * Placeholder helper overlay in the settings page.
224
+ *
225
+ * @return string
226
+ *
227
+ * @since 1.8.0
228
+ */
229
+ public function get_placeholder_helper() {
230
+ 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>';
231
+ }
232
+
233
+ /**
234
+ * Returns true if addon has an option to remove tag instead of adding attributes
235
+ *
236
+ * @return boolean
237
+ *
238
+ * @since 2.1.0
239
+ */
240
+ public function has_remove_tag_option() {
241
+ return true;
242
+ }
243
+
244
+ /**
245
+ * Return true if the remove tag option is enabled
246
+ *
247
+ * @return mixed
248
+ *
249
+ * @since 2.1.0
250
+ */
251
+ public function is_widget_remove_tag_enabled() {
252
+ return $this->settings->is_widget_remove_tag_enabled( $this->widget_option, $this->get_widget_option_name() );
253
+ }
254
+ }
addons/controller/addons/jetpack/widget/jetpack-widget-interface.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\controller\addons\jetpack\widget;
4
+
5
+ Interface Jetpack_Widget_Interface {
6
+
7
+ public function get_label();
8
+
9
+ public function get_widget_option_name();
10
+
11
+ public function get_widget_cookie_types();
12
+
13
+ public function is_widget_enabled();
14
+
15
+ public function is_widget_placeholder_enabled();
16
+
17
+ public function widget_has_placeholder();
18
+
19
+ public function get_widget_placeholder();
20
+
21
+ public function get_widget_placeholders();
22
+ }
addons/controller/addons/jetpack/widget/twitter-timeline-widget.php ADDED
@@ -0,0 +1,233 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\controller\addons\jetpack\widget;
4
+
5
+ use cookiebot_addons\lib\script_loader_tag\Script_Loader_Tag_Interface;
6
+ use cookiebot_addons\lib\Settings_Service_Interface;
7
+ use cookiebot_addons\lib\Cookie_Consent_Interface;
8
+ use cookiebot_addons\lib\buffer\Buffer_Output_Interface;
9
+
10
+ class Twitter_Timeline_Widget {
11
+
12
+ /**
13
+ * @var array list of supported cookie types
14
+ *
15
+ * @since 1.3.0
16
+ */
17
+ protected $cookie_types;
18
+
19
+ /**
20
+ * @var Settings_Service_Interface
21
+ *
22
+ * @since 1.3.0
23
+ */
24
+ protected $settings;
25
+
26
+ /**
27
+ * @var Script_Loader_Tag_Interface
28
+ *
29
+ * @since 1.3.0
30
+ */
31
+ protected $script_loader_tag;
32
+
33
+ /**
34
+ * @var Cookie_Consent_Interface
35
+ *
36
+ * @since 1.3.0
37
+ */
38
+ protected $cookie_consent;
39
+
40
+ /**
41
+ * @var Buffer_Output_Interface
42
+ *
43
+ * @since 1.3.0
44
+ */
45
+ protected $buffer_output;
46
+
47
+ /**
48
+ * Option name for jetpack addon
49
+ *
50
+ * @var string
51
+ */
52
+ public $widget_option;
53
+
54
+ /**
55
+ * Twitter_Timeline_Widget constructor.
56
+ *
57
+ * @param Settings_Service_Interface $settings
58
+ * @param Script_Loader_Tag_Interface $script_loader_tag
59
+ * @param Cookie_Consent_Interface $cookie_consent
60
+ * @param Buffer_Output_Interface $buffer_output
61
+ * @param $widget_option
62
+ *
63
+ * @since 1.8.0
64
+ */
65
+ public function __construct( Settings_Service_Interface $settings, Script_Loader_Tag_Interface $script_loader_tag, Cookie_Consent_Interface $cookie_consent, Buffer_Output_Interface $buffer_output, $widget_option ) {
66
+ $this->settings = $settings;
67
+ $this->script_loader_tag = $script_loader_tag;
68
+ $this->cookie_consent = $cookie_consent;
69
+ $this->buffer_output = $buffer_output;
70
+ $this->widget_option = $widget_option;
71
+ }
72
+
73
+ public function load_configuration() {
74
+ if ( is_active_widget( false, false, 'twitter_timeline', true ) ) {
75
+ if ( $this->is_widget_enabled() ) {
76
+ $this->cookie_types = $this->get_widget_cookie_types();
77
+
78
+ $this->disable_javascript_file();
79
+
80
+ if ( $this->is_widget_placeholder_enabled() ) {
81
+ add_action( 'jetpack_stats_extra', array( $this, 'display_div_message_to_go_to_consent_settings' ), 10, 2 );
82
+ }
83
+ }
84
+ }
85
+ }
86
+
87
+ public function get_label() {
88
+ return 'Twitter timeline';
89
+ }
90
+
91
+ /**
92
+ * Returns widget option name
93
+ *
94
+ * @return string
95
+ *
96
+ * @since 1.8.0
97
+ */
98
+ public function get_widget_option_name() {
99
+ return 'twitter_timeline';
100
+ }
101
+
102
+ /**
103
+ * Returns cookie types for a widget
104
+ *
105
+ * @return mixed
106
+ *
107
+ * @since 1.8.0
108
+ */
109
+ public function get_widget_cookie_types() {
110
+ return $this->settings->get_widget_cookie_types( $this->widget_option, $this->get_widget_option_name() );
111
+ }
112
+
113
+ /**
114
+ * Checks if a widget is enabled
115
+ *
116
+ * @return mixed
117
+ *
118
+ * @since 1.8.0
119
+ */
120
+ public function is_widget_enabled() {
121
+ return $this->settings->is_widget_enabled( $this->widget_option, $this->get_widget_option_name() );
122
+ }
123
+
124
+ /**
125
+ * @return string
126
+ */
127
+ public function get_default_placeholder() {
128
+ return 'Please accept [renew_consent]%cookie_types[/renew_consent] cookies to watch this twitterline.';
129
+ }
130
+
131
+ /**
132
+ * Checks if a widget placeholder is enabled
133
+ *
134
+ * @return boolean true If widget placeholder is checked
135
+ * false If widget placeholder is not checked
136
+ *
137
+ * @since 1.8.0
138
+ */
139
+ public function is_widget_placeholder_enabled() {
140
+ return $this->settings->is_widget_placeholder_enabled( $this->widget_option, $this->get_widget_option_name() );
141
+ }
142
+
143
+ /**
144
+ * Checks if widget has existing placeholders
145
+ *
146
+ * @return mixed
147
+ *
148
+ * @since 1.8.0
149
+ */
150
+ public function widget_has_placeholder() {
151
+ return $this->settings->widget_has_placeholder( $this->widget_option, $this->get_widget_option_name() );
152
+ }
153
+
154
+ /**
155
+ * Returns all widget placeholders
156
+ *
157
+ * @return mixed
158
+ *
159
+ * @since 1.8.0
160
+ */
161
+ public function get_widget_placeholders() {
162
+ return $this->settings->get_widget_placeholders( $this->widget_option, $this->get_widget_option_name() );
163
+ }
164
+
165
+ /**
166
+ * returns widget placeholder
167
+ *
168
+ * @return mixed
169
+ *
170
+ * @since 1.8.0
171
+ */
172
+ public function get_widget_placeholder() {
173
+ return $this->settings->get_widget_placeholder( $this->widget_option, $this->get_widget_option_name(), $this->get_default_placeholder(), cookiebot_addons_output_cookie_types( $this->get_widget_cookie_types() ) );
174
+ }
175
+
176
+ /**
177
+ * Disable javascript file if marketing consent is not given
178
+ *
179
+ * @since 1.2.0
180
+ */
181
+ protected function disable_javascript_file() {
182
+ $this->script_loader_tag->add_tag( 'jetpack-twitter-timeline', $this->cookie_types );
183
+ }
184
+
185
+ /**
186
+ * Show a messsage to go to consent settings
187
+ *
188
+ * @param $view string
189
+ * @param $widget string
190
+ *
191
+ * @since 1.2.0
192
+ */
193
+ public function display_div_message_to_go_to_consent_settings( $view, $widget ) {
194
+ if ( $widget == 'twitter_timeline' && $view == 'widget_view' ) {
195
+ if ( is_array( $this->get_widget_cookie_types() ) && count( $this->get_widget_cookie_types() ) > 0 ) {
196
+ echo '<div class="cookieconsent-optout-' . cookiebot_addons_get_one_cookie_type( $this->get_widget_cookie_types() ) . '">' . $this->get_widget_placeholder() . '</div>';
197
+ }
198
+ }
199
+ }
200
+
201
+ /**
202
+ * Adds extra information under the label
203
+ *
204
+ * @return string
205
+ *
206
+ * @since 1.8.0
207
+ */
208
+ public function get_extra_information() {
209
+ return false;
210
+ }
211
+
212
+ /**
213
+ * Placeholder helper overlay in the settings page.
214
+ *
215
+ * @return string
216
+ *
217
+ * @since 1.8.0
218
+ */
219
+ public function get_placeholder_helper() {
220
+ 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>';
221
+ }
222
+
223
+ /**
224
+ * Returns true if addon has an option to remove tag instead of adding attributes
225
+ *
226
+ * @return boolean
227
+ *
228
+ * @since 2.1.0
229
+ */
230
+ public function has_remove_tag_option() {
231
+ return false;
232
+ }
233
+ }
addons/controller/addons/ninja-forms/ninja-forms.php ADDED
@@ -0,0 +1,334 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\controller\addons\ninja_forms;
4
+
5
+ use cookiebot_addons\controller\addons\Cookiebot_Addons_Interface;
6
+ use cookiebot_addons\lib\script_loader_tag\Script_Loader_Tag_Interface;
7
+ use cookiebot_addons\lib\Cookie_Consent_Interface;
8
+ use cookiebot_addons\lib\buffer\Buffer_Output_Interface;
9
+ use cookiebot_addons\lib\Settings_Service_Interface;
10
+
11
+ class Ninja_Forms 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
+ protected $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
+ /**
65
+ * We add the action after wp_loaded and replace the original
66
+ * HubSpot Tracking Code action with our own adjusted version.
67
+ */
68
+ add_action( 'wp_loaded', array( $this, 'cookiebot_addon_ninja_forms' ), 10 );
69
+ }
70
+
71
+ /**
72
+ * Manipulate the scripts if they are loaded.
73
+ *
74
+ * @since 1.3.0
75
+ */
76
+ public function cookiebot_addon_ninja_forms() {
77
+ // Check if Cookiebot is activated and active.
78
+ if ( ! function_exists( 'cookiebot_active' ) || ! cookiebot_active() ) {
79
+ return;
80
+ }
81
+
82
+ // consent is given
83
+ if ( $this->cookie_consent->are_cookie_states_accepted( $this->get_cookie_types() ) ) {
84
+ return;
85
+ }
86
+
87
+ if ( $this->is_addon_enabled() && $this->is_addon_activated() ) {
88
+ /**
89
+ * block google captcha script
90
+ */
91
+ $this->script_loader_tag->add_tag( 'nf-google-recaptcha', $this->get_cookie_types() );
92
+
93
+ /**
94
+ * Display placeholder message
95
+ */
96
+ if ( $this->is_placeholder_enabled() ) {
97
+ add_filter( 'ninja_forms_display_fields', function ( $fields ) {
98
+ foreach ( $fields as $key => $field ) {
99
+ if ( $field['type'] == 'recaptcha' ) {
100
+ $fields[ $key ]['afterField'] = $this->get_placeholder();
101
+ }
102
+ }
103
+
104
+ return $fields;
105
+ }, 10, 1 );
106
+ }
107
+ }
108
+ }
109
+
110
+ /**
111
+ * Return addon/plugin name
112
+ *
113
+ * @return string
114
+ *
115
+ * @since 1.3.0
116
+ */
117
+ public function get_addon_name() {
118
+ return 'Ninja forms';
119
+ }
120
+
121
+ /**
122
+ * Option name in the database
123
+ *
124
+ * @return string
125
+ *
126
+ * @since 1.3.0
127
+ */
128
+ public function get_option_name() {
129
+ return 'ninja_forms';
130
+ }
131
+
132
+ /**
133
+ * Plugin file name
134
+ *
135
+ * @return string
136
+ *
137
+ * @since 1.3.0
138
+ */
139
+ public function get_plugin_file() {
140
+ return 'ninja-forms/ninja-forms.php';
141
+ }
142
+
143
+ /**
144
+ * Returns checked cookie types
145
+ * @return mixed
146
+ *
147
+ * @since 1.3.0
148
+ */
149
+ public function get_cookie_types() {
150
+ return $this->settings->get_cookie_types( $this->get_option_name() );
151
+ }
152
+
153
+ /**
154
+ * Returns default cookie types
155
+ * @return array
156
+ *
157
+ * @since 1.5.0
158
+ */
159
+ public function get_default_cookie_types() {
160
+ return array( 'marketing', 'statistics' );
161
+ }
162
+
163
+
164
+ /**
165
+ * Check if plugin is activated and checked in the backend
166
+ *
167
+ * @since 1.3.0
168
+ */
169
+ public function is_addon_enabled() {
170
+ return $this->settings->is_addon_enabled( $this->get_option_name() );
171
+ }
172
+
173
+ /**
174
+ * Checks if addon is installed
175
+ *
176
+ * @since 1.3.0
177
+ */
178
+ public function is_addon_installed() {
179
+ return $this->settings->is_addon_installed( $this->get_plugin_file() );
180
+ }
181
+
182
+ /**
183
+ * Checks if addon is activated
184
+ *
185
+ * @since 1.3.0
186
+ */
187
+ public function is_addon_activated() {
188
+ return $this->settings->is_addon_activated( $this->get_plugin_file() );
189
+ }
190
+
191
+ /**
192
+ * Retrieves current installed version of the addon
193
+ *
194
+ * @return bool
195
+ *
196
+ * @since 2.2.1
197
+ */
198
+ public function get_addon_version() {
199
+ return $this->settings->get_addon_version( $this->get_plugin_file() );
200
+ }
201
+
202
+ /**
203
+ * Default placeholder content
204
+ *
205
+ * @return string
206
+ *
207
+ * @since 1.8.0
208
+ */
209
+ public function get_default_placeholder() {
210
+ return 'Please accept [renew_consent]%cookie_types[/renew_consent] cookies to enable captcha.';
211
+ }
212
+
213
+ /**
214
+ * Get placeholder content
215
+ *
216
+ * This function will check following features:
217
+ * - Current language
218
+ *
219
+ * @param $src
220
+ *
221
+ * @return bool|mixed
222
+ *
223
+ * @since 1.8.0
224
+ */
225
+ public function get_placeholder( $src = '' ) {
226
+ return $this->settings->get_placeholder( $this->get_option_name(), $this->get_default_placeholder(), cookiebot_addons_output_cookie_types( $this->get_cookie_types() ), $src );
227
+ }
228
+
229
+ /**
230
+ * Checks if it does have custom placeholder content
231
+ *
232
+ * @return mixed
233
+ *
234
+ * @since 1.8.0
235
+ */
236
+ public function has_placeholder() {
237
+ return $this->settings->has_placeholder( $this->get_option_name() );
238
+ }
239
+
240
+ /**
241
+ * returns all placeholder contents
242
+ *
243
+ * @return mixed
244
+ *
245
+ * @since 1.8.0
246
+ */
247
+ public function get_placeholders() {
248
+ return $this->settings->get_placeholders( $this->get_option_name() );
249
+ }
250
+
251
+ /**
252
+ * Return true if the placeholder is enabled
253
+ *
254
+ * @return mixed
255
+ *
256
+ * @since 1.8.0
257
+ */
258
+ public function is_placeholder_enabled() {
259
+ return $this->settings->is_placeholder_enabled( $this->get_option_name() );
260
+ }
261
+
262
+ /**
263
+ * Adds extra information under the label
264
+ *
265
+ * @return string
266
+ *
267
+ * @since 1.8.0
268
+ */
269
+ public function get_extra_information() {
270
+ return false;
271
+ }
272
+
273
+ /**
274
+ * Returns the url of WordPress SVN repository or another link where we can verify the plugin file.
275
+ *
276
+ * @return boolean
277
+ *
278
+ * @since 1.8.0
279
+ */
280
+ public function get_svn_url() {
281
+ return 'http://plugins.svn.wordpress.org/ninja-forms/trunk/ninja-forms.php';
282
+ }
283
+
284
+ /**
285
+ * Placeholder helper overlay in the settings page.
286
+ *
287
+ * @return string
288
+ *
289
+ * @since 1.8.0
290
+ */
291
+ public function get_placeholder_helper() {
292
+ 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>';
293
+ }
294
+
295
+ /**
296
+ * Returns true if addon has an option to remove tag instead of adding attributes
297
+ *
298
+ * @return boolean
299
+ *
300
+ * @since 2.1.0
301
+ */
302
+ public function has_remove_tag_option() {
303
+ return false;
304
+ }
305
+
306
+ /**
307
+ * Returns parent class or false
308
+ *
309
+ * @return string|bool
310
+ *
311
+ * @since 2.1.3
312
+ */
313
+ public function get_parent_class() {
314
+ return get_parent_class( $this );
315
+ }
316
+
317
+ /**
318
+ * Action after enabling the addon on the settings page
319
+ *
320
+ * @since 2.2.0
321
+ */
322
+ public function post_hook_after_enabling() {
323
+ //do nothing
324
+ }
325
+
326
+ /**
327
+ * Cookiebot plugin is deactivated
328
+ *
329
+ * @since 2.2.0
330
+ */
331
+ public function plugin_deactivated() {
332
+ //do nothing
333
+ }
334
+ }
addons/controller/addons/optinmonster/optinmonster.php ADDED
@@ -0,0 +1,313 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\controller\addons\optinmonster;
4
+
5
+ use cookiebot_addons\controller\addons\Cookiebot_Addons_Interface;
6
+ use cookiebot_addons\lib\buffer\Buffer_Output_Interface;
7
+ use cookiebot_addons\lib\Cookie_Consent_Interface;
8
+ use cookiebot_addons\lib\script_loader_tag\Script_Loader_Tag_Interface;
9
+ use cookiebot_addons\lib\Settings_Service_Interface;
10
+
11
+ class Optinmonster 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
+ protected $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_optinmonster' ), 10 );
65
+ }
66
+
67
+ /**
68
+ * Check for optinmonster action hooks
69
+ *
70
+ * @since 1.3.0
71
+ */
72
+ public function cookiebot_addon_optinmonster() {
73
+ // Check if Cookiebot is activated and active.
74
+ if ( ! function_exists( 'cookiebot_active' ) || ! cookiebot_active() ) {
75
+ return;
76
+ }
77
+
78
+ // consent is given
79
+ if ( $this->cookie_consent->are_cookie_states_accepted( $this->get_cookie_types() ) ) {
80
+ return;
81
+ }
82
+
83
+ if ( $this->is_addon_enabled() ) {
84
+ if ( ! $this->cookie_consent->are_cookie_states_accepted( $this->get_cookie_types() ) ) {
85
+ $this->script_loader_tag->add_tag( 'optinmonster-api-script', $this->get_cookie_types() );
86
+ }
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Return addon/plugin name
92
+ *
93
+ * @return string
94
+ *
95
+ * @since 1.3.0
96
+ */
97
+ public function get_addon_name() {
98
+ return 'Optinmonster';
99
+ }
100
+
101
+ /**
102
+ * Option name in the database
103
+ *
104
+ * @return string
105
+ *
106
+ * @since 1.3.0
107
+ */
108
+ public function get_option_name() {
109
+ return 'optinmonster';
110
+ }
111
+
112
+ /**
113
+ * plugin file name
114
+ *
115
+ * @return string
116
+ *
117
+ * @since 1.3.0
118
+ */
119
+ public function get_plugin_file() {
120
+ return 'optinmonster/optin-monster-wp-api.php';
121
+ }
122
+
123
+ /**
124
+ * Returns checked cookie types
125
+ * @return array
126
+ *
127
+ * @since 1.3.0
128
+ */
129
+ public function get_cookie_types() {
130
+ return $this->settings->get_cookie_types( $this->get_option_name() );
131
+ }
132
+
133
+ /**
134
+ * Returns default cookie types
135
+ * @return array
136
+ *
137
+ * @since 1.5.0
138
+ */
139
+ public function get_default_cookie_types() {
140
+ return array( 'marketing', 'statistics' );
141
+ }
142
+
143
+ /**
144
+ * Check if plugin is activated and checked in the backend
145
+ *
146
+ * @since 1.3.0
147
+ */
148
+ public function is_addon_enabled() {
149
+ return $this->settings->is_addon_enabled( $this->get_option_name() );
150
+ }
151
+
152
+ /**
153
+ * Checks if addon is installed
154
+ *
155
+ * @since 1.3.0
156
+ */
157
+ public function is_addon_installed() {
158
+ return $this->settings->is_addon_installed( $this->get_plugin_file() );
159
+ }
160
+
161
+ /**
162
+ * Checks if addon is activated
163
+ *
164
+ * @since 1.3.0
165
+ */
166
+ public function is_addon_activated() {
167
+ return $this->settings->is_addon_activated( $this->get_plugin_file() );
168
+ }
169
+
170
+ /**
171
+ * Retrieves current installed version of the addon
172
+ *
173
+ * @return bool
174
+ *
175
+ * @since 2.2.1
176
+ */
177
+ public function get_addon_version() {
178
+ return $this->settings->get_addon_version( $this->get_plugin_file() );
179
+ }
180
+
181
+ /**
182
+ * Default placeholder content
183
+ *
184
+ * @return string
185
+ *
186
+ * @since 1.8.0
187
+ */
188
+ public function get_default_placeholder() {
189
+ return 'Please accept [renew_consent]%cookie_types[/renew_consent] cookies to track for optinmonster.';
190
+ }
191
+
192
+ /**
193
+ * Get placeholder content
194
+ *
195
+ * This function will check following features:
196
+ * - Current language
197
+ *
198
+ * @param $src
199
+ *
200
+ * @return bool|mixed
201
+ *
202
+ * @since 1.8.0
203
+ */
204
+ public function get_placeholder( $src = '' ) {
205
+ return $this->settings->get_placeholder( $this->get_option_name(), $this->get_default_placeholder(), cookiebot_addons_output_cookie_types( $this->get_cookie_types() ), $src );
206
+ }
207
+
208
+ /**
209
+ * Checks if it does have custom placeholder content
210
+ *
211
+ * @return mixed
212
+ *
213
+ * @since 1.8.0
214
+ */
215
+ public function has_placeholder() {
216
+ return $this->settings->has_placeholder( $this->get_option_name() );
217
+ }
218
+
219
+ /**
220
+ * returns all placeholder contents
221
+ *
222
+ * @return mixed
223
+ *
224
+ * @since 1.8.0
225
+ */
226
+ public function get_placeholders() {
227
+ return $this->settings->get_placeholders( $this->get_option_name() );
228
+ }
229
+
230
+ /**
231
+ * Return true if the placeholder is enabled
232
+ *
233
+ * @return mixed
234
+ *
235
+ * @since 1.8.0
236
+ */
237
+ public function is_placeholder_enabled() {
238
+ return $this->settings->is_placeholder_enabled( $this->get_option_name() );
239
+ }
240
+
241
+ /**
242
+ * Adds extra information under the label
243
+ *
244
+ * @return string
245
+ *
246
+ * @since 1.8.0
247
+ */
248
+ public function get_extra_information() {
249
+ return '<p>' . __( 'OptinMonster API plugin to connect your WordPress site to your OptinMonster account.', 'cookiebot-addons' ) . '</p>';
250
+ }
251
+
252
+ /**
253
+ * Returns the url of WordPress SVN repository or another link where we can verify the plugin file.
254
+ *
255
+ * @return boolean
256
+ *
257
+ * @since 1.8.0
258
+ */
259
+ public function get_svn_url() {
260
+ return 'https://plugins.svn.wordpress.org/optinmonster/trunk/optin-monster-wp-api.php';
261
+ }
262
+
263
+ /**
264
+ * Placeholder helper overlay in the settings page.
265
+ *
266
+ * @return string
267
+ *
268
+ * @since 1.8.0
269
+ */
270
+ public function get_placeholder_helper() {
271
+ 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>';
272
+ }
273
+
274
+ /**
275
+ * Returns true if addon has an option to remove tag instead of adding attributes
276
+ *
277
+ * @return boolean
278
+ *
279
+ * @since 2.1.0
280
+ */
281
+ public function has_remove_tag_option() {
282
+ return false;
283
+ }
284
+
285
+ /**
286
+ * Returns parent class or false
287
+ *
288
+ * @return string|bool
289
+ *
290
+ * @since 2.1.3
291
+ */
292
+ public function get_parent_class() {
293
+ return get_parent_class( $this );
294
+ }
295
+
296
+ /**
297
+ * Action after enabling the addon on the settings page
298
+ *
299
+ * @since 2.2.0
300
+ */
301
+ public function post_hook_after_enabling() {
302
+ //do nothing
303
+ }
304
+
305
+ /**
306
+ * Cookiebot plugin is deactivated
307
+ *
308
+ * @since 2.2.0
309
+ */
310
+ public function plugin_deactivated() {
311
+ //do nothing
312
+ }
313
+ }
addons/controller/addons/pixel-caffeine/pixel-caffeine.php ADDED
@@ -0,0 +1,339 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\controller\addons\pixel_caffeine;
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 Pixel_Caffeine implements Cookiebot_Addons_Interface {
12
+
13
+ /**
14
+ * @var Settings_Service_Interface
15
+ *
16
+ * @since 1.4.0
17
+ */
18
+ protected $settings;
19
+
20
+ /**
21
+ * @var Script_Loader_Tag_Interface
22
+ *
23
+ * @since 1.4.0
24
+ */
25
+ protected $script_loader_tag;
26
+
27
+ /**
28
+ * @var Cookie_Consent_Interface
29
+ *
30
+ * @since 1.4.0
31
+ */
32
+ protected $cookie_consent;
33
+
34
+ /**
35
+ * @var Buffer_Output_Interface
36
+ *
37
+ * @since 1.4.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.4.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.4.0
62
+ */
63
+ public function load_configuration() {
64
+ add_action( 'wp_loaded', array( $this, 'cookiebot_addon_pixel_caffeine' ), 5 );
65
+ }
66
+
67
+ /**
68
+ * Disable scripts if state not accepted
69
+ *
70
+ * @since 1.4.0
71
+ */
72
+ public function cookiebot_addon_pixel_caffeine() {
73
+ // Check if Pixel Caffeine is loaded.
74
+ if ( ! defined( 'AEPC_PLUGIN_FILE' ) ) {
75
+ return;
76
+ }
77
+
78
+ // Check if Cookiebot is activated and active.
79
+ if ( ! function_exists( 'cookiebot_active' ) || ! cookiebot_active() ) {
80
+ return;
81
+ }
82
+
83
+ // consent is given
84
+ if( $this->cookie_consent->are_cookie_states_accepted( $this->get_cookie_types() ) ) {
85
+ return;
86
+ }
87
+
88
+ $this->script_loader_tag->add_tag( 'aepc-pixel-events', array( 'facebook' => $this->get_cookie_types() ) );
89
+
90
+ if( $this->is_remove_tag_enabled() ) {
91
+ cookiebot_addons_remove_class_action( 'wp_head', 'AEPC_Pixel_Scripts', 'pixel_init', 99 );
92
+ cookiebot_addons_remove_class_action( 'wp_footer', 'AEPC_Pixel_Scripts', 'pixel_init', 1 );
93
+ }
94
+ else {
95
+ $this->buffer_output->add_tag( 'wp_head', 99, array(
96
+ 'aepc_pixel' => $this->get_cookie_types(),
97
+ ), false );
98
+
99
+ $this->buffer_output->add_tag( 'wp_footer', 1, array(
100
+ 'aepc_pixel' => $this->get_cookie_types(),
101
+ ), false );
102
+ }
103
+ }
104
+
105
+ /**
106
+ * Return addon/plugin name
107
+ *
108
+ * @return string
109
+ *
110
+ * @since 1.4.0
111
+ */
112
+ public function get_addon_name() {
113
+ return 'Pixel Caffeine';
114
+ }
115
+
116
+ /**
117
+ * Option name in the database
118
+ *
119
+ * @return string
120
+ *
121
+ * @since 1.4.0
122
+ */
123
+ public function get_option_name() {
124
+ return 'pixel_caffeine';
125
+ }
126
+
127
+ /**
128
+ * Plugin file name
129
+ *
130
+ * @return string
131
+ *
132
+ * @since 1.4.0
133
+ */
134
+ public function get_plugin_file() {
135
+ return 'pixel-caffeine/pixel-caffeine.php';
136
+ }
137
+
138
+ /**
139
+ * Returns checked cookie types
140
+ * @return mixed
141
+ *
142
+ * @since 1.4.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' );
156
+ }
157
+
158
+ /**
159
+ * Check if plugin is activated and checked in the backend
160
+ *
161
+ * @since 1.4.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.4.0
171
+ */
172
+ public function is_addon_installed() {
173
+ return $this->settings->is_addon_installed( $this->get_plugin_file() );
174
+ }
175
+
176
+ /**
177
+ * Checks if addon is activated
178
+ *
179
+ * @since 1.4.0
180
+ */
181
+ public function is_addon_activated() {
182
+ return $this->settings->is_addon_activated( $this->get_plugin_file() );
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_plugin_file() );
194
+ }
195
+
196
+ /**
197
+ * Default placeholder content
198
+ *
199
+ * @return string
200
+ *
201
+ * @since 1.8.0
202
+ */
203
+ public function get_default_placeholder() {
204
+ return 'Please accept [renew_consent]%cookie_types[/renew_consent] cookies to watch this video.';
205
+ }
206
+
207
+ /**
208
+ * Get placeholder content
209
+ *
210
+ * This function will check following features:
211
+ * - Current language
212
+ *
213
+ * @param $src
214
+ *
215
+ * @return bool|mixed
216
+ *
217
+ * @since 1.8.0
218
+ */
219
+ public function get_placeholder( $src = '' ) {
220
+ return $this->settings->get_placeholder( $this->get_option_name(), $this->get_default_placeholder(), cookiebot_addons_output_cookie_types( $this->get_cookie_types() ), $src );
221
+ }
222
+
223
+ /**
224
+ * Checks if it does have custom placeholder content
225
+ *
226
+ * @return mixed
227
+ *
228
+ * @since 1.8.0
229
+ */
230
+ public function has_placeholder() {
231
+ return $this->settings->has_placeholder( $this->get_option_name() );
232
+ }
233
+
234
+ /**
235
+ * returns all placeholder contents
236
+ *
237
+ * @return mixed
238
+ *
239
+ * @since 1.8.0
240
+ */
241
+ public function get_placeholders() {
242
+ return $this->settings->get_placeholders( $this->get_option_name() );
243
+ }
244
+
245
+ /**
246
+ * Return true if the placeholder is enabled
247
+ *
248
+ * @return mixed
249
+ *
250
+ * @since 1.8.0
251
+ */
252
+ public function is_placeholder_enabled() {
253
+ return $this->settings->is_placeholder_enabled( $this->get_option_name() );
254
+ }
255
+
256
+ /**
257
+ * Adds extra information under the label
258
+ *
259
+ * @return string
260
+ *
261
+ * @since 1.8.0
262
+ */
263
+ public function get_extra_information() {
264
+ return false;
265
+ }
266
+
267
+ /**
268
+ * Returns the url of WordPress SVN repository or another link where we can verify the plugin file.
269
+ *
270
+ * @return boolean
271
+ *
272
+ * @since 1.8.0
273
+ */
274
+ public function get_svn_url() {
275
+ return 'http://plugins.svn.wordpress.org/pixel-caffeine/trunk/pixel-caffeine.php';
276
+ }
277
+
278
+ /**
279
+ * Placeholder helper overlay in the settings page.
280
+ *
281
+ * @return string
282
+ *
283
+ * @since 1.8.0
284
+ */
285
+ public function get_placeholder_helper() {
286
+ 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>';
287
+ }
288
+
289
+ /**
290
+ * Returns true if addon has an option to remove tag instead of adding attributes
291
+ *
292
+ * @return boolean
293
+ *
294
+ * @since 2.1.0
295
+ */
296
+ public function has_remove_tag_option() {
297
+ return true;
298
+ }
299
+
300
+ /**
301
+ * Return true if the remove tag option is enabled
302
+ *
303
+ * @return mixed
304
+ *
305
+ * @since 2.1.0
306
+ */
307
+ public function is_remove_tag_enabled() {
308
+ return $this->settings->is_remove_tag_enabled( $this->get_option_name() );
309
+ }
310
+
311
+ /**
312
+ * Returns parent class or false
313
+ *
314
+ * @return string|bool
315
+ *
316
+ * @since 2.1.3
317
+ */
318
+ public function get_parent_class() {
319
+ return get_parent_class( $this );
320
+ }
321
+
322
+ /**
323
+ * Action after enabling the addon on the settings page
324
+ *
325
+ * @since 2.2.0
326
+ */
327
+ public function post_hook_after_enabling() {
328
+ //do nothing
329
+ }
330
+
331
+ /**
332
+ * Cookiebot plugin is deactivated
333
+ *
334
+ * @since 2.2.0
335
+ */
336
+ public function plugin_deactivated() {
337
+ //do nothing
338
+ }
339
+ }
addons/controller/addons/wd-google-analytics/wd-google-analytics.php ADDED
@@ -0,0 +1,333 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\controller\addons\wd_google_analytics;
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 Wd_Google_Analytics 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
+ protected $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, 'disable_cookies' ), 5 );
65
+ }
66
+
67
+ /**
68
+ * Disable scripts if state not accepted
69
+ *
70
+ * @since 1.3.0
71
+ */
72
+ public function disable_cookies() {
73
+ // Check if WD google analytics is loaded.
74
+ if ( ! defined( 'GWD_NAME' ) ) {
75
+ return;
76
+ }
77
+
78
+ // Check if Cookiebot is activated and active.
79
+ if ( ! function_exists( 'cookiebot_active' ) || ! cookiebot_active() ) {
80
+ return;
81
+ }
82
+
83
+ // consent is given
84
+ if ( $this->cookie_consent->are_cookie_states_accepted( $this->get_cookie_types() ) ) {
85
+ return;
86
+ }
87
+
88
+ if ( $this->is_remove_tag_enabled() ) {
89
+ // Disable WD google analytics wp_head hook if consent not given
90
+ cookiebot_addons_remove_class_action( 'wp_head', 'GAWD', 'gawd_tracking_code', 99 );
91
+ } else {
92
+ $this->buffer_output->add_tag( 'wp_head', 99, array(
93
+ 'GoogleAnalyticsObject' => $this->get_cookie_types(),
94
+ ), false );
95
+ }
96
+
97
+ }
98
+
99
+ /**
100
+ * Return addon/plugin name
101
+ *
102
+ * @return string
103
+ *
104
+ * @since 1.3.0
105
+ */
106
+ public function get_addon_name() {
107
+ return 'WD google analytics';
108
+ }
109
+
110
+ /**
111
+ * Option name in the database
112
+ *
113
+ * @return string
114
+ *
115
+ * @since 1.3.0
116
+ */
117
+ public function get_option_name() {
118
+ return 'wd_google_analytics';
119
+ }
120
+
121
+ /**
122
+ * Plugin file name
123
+ *
124
+ * @return string
125
+ *
126
+ * @since 1.3.0
127
+ */
128
+ public function get_plugin_file() {
129
+ return 'wd-google-analytics/google-analytics-wd.php';
130
+ }
131
+
132
+ /**
133
+ * Returns checked cookie types
134
+ * @return mixed
135
+ *
136
+ * @since 1.3.0
137
+ */
138
+ public function get_cookie_types() {
139
+ return $this->settings->get_cookie_types( $this->get_option_name(), $this->get_default_cookie_types() );
140
+ }
141
+
142
+ /**
143
+ * Returns default cookie types
144
+ * @return array
145
+ *
146
+ * @since 1.5.0
147
+ */
148
+ public function get_default_cookie_types() {
149
+ return array( 'statistics' );
150
+ }
151
+
152
+ /**
153
+ * Check if plugin is activated and checked in the backend
154
+ *
155
+ * @since 1.3.0
156
+ */
157
+ public function is_addon_enabled() {
158
+ return $this->settings->is_addon_enabled( $this->get_option_name() );
159
+ }
160
+
161
+ /**
162
+ * Checks if addon is installed
163
+ *
164
+ * @since 1.3.0
165
+ */
166
+ public function is_addon_installed() {
167
+ return $this->settings->is_addon_installed( $this->get_plugin_file() );
168
+ }
169
+
170
+ /**
171
+ * Checks if addon is activated
172
+ *
173
+ * @since 1.3.0
174
+ */
175
+ public function is_addon_activated() {
176
+ return $this->settings->is_addon_activated( $this->get_plugin_file() );
177
+ }
178
+
179
+ /**
180
+ * Retrieves current installed version of the addon
181
+ *
182
+ * @return bool
183
+ *
184
+ * @since 2.2.1
185
+ */
186
+ public function get_addon_version() {
187
+ return $this->settings->get_addon_version( $this->get_plugin_file() );
188
+ }
189
+
190
+ /**
191
+ * Default placeholder content
192
+ *
193
+ * @return string
194
+ *
195
+ * @since 1.8.0
196
+ */
197
+ public function get_default_placeholder() {
198
+ return 'Please accept [renew_consent]%cookie_types[/renew_consent] cookies to watch this video.';
199
+ }
200
+
201
+ /**
202
+ * Get placeholder content
203
+ *
204
+ * This function will check following features:
205
+ * - Current language
206
+ *
207
+ * @param $src
208
+ *
209
+ * @return bool|mixed
210
+ *
211
+ * @since 1.8.0
212
+ */
213
+ public function get_placeholder( $src = '' ) {
214
+ return $this->settings->get_placeholder( $this->get_option_name(), $this->get_default_placeholder(), cookiebot_addons_output_cookie_types( $this->get_cookie_types() ), $src );
215
+ }
216
+
217
+ /**
218
+ * Checks if it does have custom placeholder content
219
+ *
220
+ * @return mixed
221
+ *
222
+ * @since 1.8.0
223
+ */
224
+ public function has_placeholder() {
225
+ return $this->settings->has_placeholder( $this->get_option_name() );
226
+ }
227
+
228
+ /**
229
+ * returns all placeholder contents
230
+ *
231
+ * @return mixed
232
+ *
233
+ * @since 1.8.0
234
+ */
235
+ public function get_placeholders() {
236
+ return $this->settings->get_placeholders( $this->get_option_name() );
237
+ }
238
+
239
+ /**
240
+ * Return true if the placeholder is enabled
241
+ *
242
+ * @return mixed
243
+ *
244
+ * @since 1.8.0
245
+ */
246
+ public function is_placeholder_enabled() {
247
+ return $this->settings->is_placeholder_enabled( $this->get_option_name() );
248
+ }
249
+
250
+ /**
251
+ * Adds extra information under the label
252
+ *
253
+ * @return string
254
+ *
255
+ * @since 1.8.0
256
+ */
257
+ public function get_extra_information() {
258
+ return false;
259
+ }
260
+
261
+ /**
262
+ * Returns the url of WordPress SVN repository or another link where we can verify the plugin file.
263
+ *
264
+ * @return boolean
265
+ *
266
+ * @since 1.8.0
267
+ */
268
+ public function get_svn_url() {
269
+ return 'http://plugins.svn.wordpress.org/wd-google-analytics/trunk/google-analytics-wd.php';
270
+ }
271
+
272
+ /**
273
+ * Placeholder helper overlay in the settings page.
274
+ *
275
+ * @return string
276
+ *
277
+ * @since 1.8.0
278
+ */
279
+ public function get_placeholder_helper() {
280
+ 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>';
281
+ }
282
+
283
+ /**
284
+ * Returns true if addon has an option to remove tag instead of adding attributes
285
+ *
286
+ * @return boolean
287
+ *
288
+ * @since 2.1.0
289
+ */
290
+ public function has_remove_tag_option() {
291
+ return true;
292
+ }
293
+
294
+ /**
295
+ * Return true if the remove tag option is enabled
296
+ *
297
+ * @return mixed
298
+ *
299
+ * @since 2.1.0
300
+ */
301
+ public function is_remove_tag_enabled() {
302
+ return $this->settings->is_remove_tag_enabled( $this->get_option_name() );
303
+ }
304
+
305
+ /**
306
+ * Returns parent class or false
307
+ *
308
+ * @return string|bool
309
+ *
310
+ * @since 2.1.3
311
+ */
312
+ public function get_parent_class() {
313
+ return get_parent_class( $this );
314
+ }
315
+
316
+ /**
317
+ * Action after enabling the addon on the settings page
318
+ *
319
+ * @since 2.2.0
320
+ */
321
+ public function post_hook_after_enabling() {
322
+ //do nothing
323
+ }
324
+
325
+ /**
326
+ * Cookiebot plugin is deactivated
327
+ *
328
+ * @since 2.2.0
329
+ */
330
+ public function plugin_deactivated() {
331
+ //do nothing
332
+ }
333
+ }
addons/controller/addons/wp-analytify/wp-analytify.php ADDED
@@ -0,0 +1,315 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\controller\addons\wp_analytify;
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 Wp_Analytify implements Cookiebot_Addons_Interface {
12
+
13
+ /**
14
+ * @var Settings_Service_Interface
15
+ *
16
+ * @since 1.5.0
17
+ */
18
+ protected $settings;
19
+
20
+ /**
21
+ * @var Script_Loader_Tag_Interface
22
+ *
23
+ * @since 1.5.0
24
+ */
25
+ protected $script_loader_tag;
26
+
27
+ /**
28
+ * @var Cookie_Consent_Interface
29
+ *
30
+ * @since 1.5.0
31
+ */
32
+ protected $cookie_consent;
33
+
34
+ /**
35
+ * @var Buffer_Output_Interface
36
+ *
37
+ * @since 1.5.0
38
+ */
39
+ protected $buffer_output;
40
+
41
+ /**
42
+ * 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.5.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.5.0
62
+ */
63
+ public function load_configuration() {
64
+ add_action( 'wp_loaded', array( $this, 'cookiebot_addon_analytify' ), 5 );
65
+ }
66
+
67
+ /**
68
+ * Disable scripts if state not accepted
69
+ *
70
+ * @since 1.5.0
71
+ */
72
+ public function cookiebot_addon_analytify() {
73
+ // Check if Analytify is loaded.
74
+ if ( ! class_exists( 'WP_Analytify' ) ) {
75
+ return;
76
+ }
77
+
78
+ // Check if Cookiebot is activated and active.
79
+ if ( ! function_exists( 'cookiebot_active' ) || ! cookiebot_active() ) {
80
+ return;
81
+ }
82
+
83
+ // consent is given
84
+ if( $this->cookie_consent->are_cookie_states_accepted( $this->get_cookie_types() ) ) {
85
+ return;
86
+ }
87
+
88
+ // Disable Analytify if cookie consent not allowed
89
+ cookiebot_addons_remove_class_action( 'wp_head', 'WP_Analytify', 'analytify_add_analytics_code' );
90
+ }
91
+
92
+ /**
93
+ * Return addon/plugin name
94
+ *
95
+ * @return string
96
+ *
97
+ * @since 1.5.0
98
+ */
99
+ public function get_addon_name() {
100
+ return 'Analytify';
101
+ }
102
+
103
+ /**
104
+ * Option name in the database
105
+ *
106
+ * @return string
107
+ *
108
+ * @since 1.5.0
109
+ */
110
+ public function get_option_name() {
111
+ return 'analytify';
112
+ }
113
+
114
+ /**
115
+ * Plugin file name
116
+ *
117
+ * @return string
118
+ *
119
+ * @since 1.5.0
120
+ */
121
+ public function get_plugin_file() {
122
+ return 'wp-analytify/wp-analytify.php';
123
+ }
124
+
125
+ /**
126
+ * Returns checked cookie types
127
+ * @return mixed
128
+ *
129
+ * @since 1.5.0
130
+ */
131
+ public function get_cookie_types() {
132
+ return $this->settings->get_cookie_types( $this->get_option_name(), $this->get_default_cookie_types() );
133
+ }
134
+
135
+ /**
136
+ * Returns default cookie types
137
+ * @return array
138
+ *
139
+ * @since 1.5.0
140
+ */
141
+ public function get_default_cookie_types() {
142
+ return array( 'statistics' );
143
+ }
144
+
145
+ /**
146
+ * Check if plugin is activated and checked in the backend
147
+ *
148
+ * @since 1.5.0
149
+ */
150
+ public function is_addon_enabled() {
151
+ return $this->settings->is_addon_enabled( $this->get_option_name() );
152
+ }
153
+
154
+ /**
155
+ * Checks if addon is installed
156
+ *
157
+ * @since 1.5.0
158
+ */
159
+ public function is_addon_installed() {
160
+ return $this->settings->is_addon_installed( $this->get_plugin_file() );
161
+ }
162
+
163
+ /**
164
+ * Checks if addon is activated
165
+ *
166
+ * @since 1.5.0
167
+ */
168
+ public function is_addon_activated() {
169
+ return $this->settings->is_addon_activated( $this->get_plugin_file() );
170
+ }
171
+
172
+ /**
173
+ * Retrieves current installed version of the addon
174
+ *
175
+ * @return bool
176
+ *
177
+ * @since 2.2.1
178
+ */
179
+ public function get_addon_version() {
180
+ return $this->settings->get_addon_version( $this->get_plugin_file() );
181
+ }
182
+
183
+ /**
184
+ * Default placeholder content
185
+ *
186
+ * @return string
187
+ *
188
+ * @since 1.8.0
189
+ */
190
+ public function get_default_placeholder() {
191
+ return 'Please accept [renew_consent]%cookie_types[/renew_consent] cookies to watch this video.';
192
+ }
193
+
194
+ /**
195
+ * Get placeholder content
196
+ *
197
+ * This function will check following features:
198
+ * - Current language
199
+ *
200
+ * @param $src
201
+ *
202
+ * @return bool|mixed
203
+ *
204
+ * @since 1.8.0
205
+ */
206
+ public function get_placeholder( $src = '' ) {
207
+ return $this->settings->get_placeholder( $this->get_option_name(), $this->get_default_placeholder(), cookiebot_addons_output_cookie_types( $this->get_cookie_types() ), $src );
208
+ }
209
+
210
+ /**
211
+ * Checks if it does have custom placeholder content
212
+ *
213
+ * @return mixed
214
+ *
215
+ * @since 1.8.0
216
+ */
217
+ public function has_placeholder() {
218
+ return $this->settings->has_placeholder( $this->get_option_name() );
219
+ }
220
+
221
+ /**
222
+ * returns all placeholder contents
223
+ *
224
+ * @return mixed
225
+ *
226
+ * @since 1.8.0
227
+ */
228
+ public function get_placeholders() {
229
+ return $this->settings->get_placeholders( $this->get_option_name() );
230
+ }
231
+
232
+ /**
233
+ * Return true if the placeholder is enabled
234
+ *
235
+ * @return mixed
236
+ *
237
+ * @since 1.8.0
238
+ */
239
+ public function is_placeholder_enabled() {
240
+ return $this->settings->is_placeholder_enabled( $this->get_option_name() );
241
+ }
242
+
243
+ /**
244
+ * Adds extra information under the label
245
+ *
246
+ * @return string
247
+ *
248
+ * @since 1.8.0
249
+ */
250
+ public function get_extra_information() {
251
+ return false;
252
+ }
253
+
254
+ /**
255
+ * Returns the url of WordPress SVN repository or another link where we can verify the plugin file.
256
+ *
257
+ * @return boolean
258
+ *
259
+ * @since 1.8.0
260
+ */
261
+ public function get_svn_url() {
262
+ return 'http://plugins.svn.wordpress.org/wp-analytify/trunk/wp-analytify.php';
263
+ }
264
+
265
+ /**
266
+ * Placeholder helper overlay in the settings page.
267
+ *
268
+ * @return string
269
+ *
270
+ * @since 1.8.0
271
+ */
272
+ public function get_placeholder_helper() {
273
+ 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>';
274
+ }
275
+
276
+ /**
277
+ * Returns true if addon has an option to remove tag instead of adding attributes
278
+ *
279
+ * @return boolean
280
+ *
281
+ * @since 2.1.0
282
+ */
283
+ public function has_remove_tag_option() {
284
+ return false;
285
+ }
286
+
287
+ /**
288
+ * Returns parent class or false
289
+ *
290
+ * @return string|bool
291
+ *
292
+ * @since 2.1.3
293
+ */
294
+ public function get_parent_class() {
295
+ return get_parent_class( $this );
296
+ }
297
+
298
+ /**
299
+ * Action after enabling the addon on the settings page
300
+ *
301
+ * @since 2.2.0
302
+ */
303
+ public function post_hook_after_enabling() {
304
+ //do nothing
305
+ }
306
+
307
+ /**
308
+ * Cookiebot plugin is deactivated
309
+ *
310
+ * @since 2.2.0
311
+ */
312
+ public function plugin_deactivated() {
313
+ //do nothing
314
+ }
315
+ }
addons/controller/addons/wp-piwik/wp-piwik.php ADDED
@@ -0,0 +1,317 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\controller\addons\wp_piwik;
4
+
5
+ include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
6
+
7
+ use cookiebot_addons\controller\addons\Cookiebot_Addons_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\buffer\Buffer_Output_Interface;
11
+ use cookiebot_addons\lib\Settings_Service_Interface;
12
+ use WP_Piwik\Settings;
13
+
14
+ class Wp_Piwik implements Cookiebot_Addons_Interface {
15
+
16
+ /**
17
+ * @var Settings_Service_Interface
18
+ *
19
+ * @since 1.3.0
20
+ */
21
+ protected $settings;
22
+
23
+ /**
24
+ * @var Script_Loader_Tag_Interface
25
+ *
26
+ * @since 1.3.0
27
+ */
28
+ protected $script_loader_tag;
29
+
30
+ /**
31
+ * @var Cookie_Consent_Interface
32
+ *
33
+ * @since 1.3.0
34
+ */
35
+ protected $cookie_consent;
36
+
37
+ /**
38
+ * @var Buffer_Output_Interface
39
+ *
40
+ * @since 1.3.0
41
+ */
42
+ protected $buffer_output;
43
+
44
+ /**
45
+ * Jetpack constructor.
46
+ *
47
+ * @param $settings Settings_Service_Interface
48
+ * @param $script_loader_tag Script_Loader_Tag_Interface
49
+ * @param $cookie_consent Cookie_Consent_Interface
50
+ * @param $buffer_output Buffer_Output_Interface
51
+ *
52
+ * @since 1.3.0
53
+ */
54
+ public function __construct( Settings_Service_Interface $settings, Script_Loader_Tag_Interface $script_loader_tag, Cookie_Consent_Interface $cookie_consent, Buffer_Output_Interface $buffer_output ) {
55
+ $this->settings = $settings;
56
+ $this->script_loader_tag = $script_loader_tag;
57
+ $this->cookie_consent = $cookie_consent;
58
+ $this->buffer_output = $buffer_output;
59
+ }
60
+
61
+ /**
62
+ * Loads addon configuration
63
+ *
64
+ * @since 1.3.0
65
+ */
66
+ public function load_configuration() {
67
+ /**
68
+ * We add the action after wp_loaded and check cookie settings from wp-piwik
69
+ */
70
+ add_action( 'wp_loaded', array( $this, 'cookiebot_addon_wp_piwik' ), 10 );
71
+ }
72
+
73
+ /**
74
+ * Manipulate the scripts if they are loaded.
75
+ *
76
+ * @since 1.3.0
77
+ */
78
+ public function cookiebot_addon_wp_piwik() {
79
+ // Check if Cookiebot is activated and active.
80
+ if ( ! function_exists( 'cookiebot_active' ) || ! cookiebot_active() ) {
81
+ return;
82
+ }
83
+
84
+ //If plugin activated and no consent block wp-piwik global option.
85
+ if ( is_plugin_active( 'wp-piwik/wp-piwik.php' ) ) {
86
+ if ( ! $this->cookie_consent->are_cookie_states_accepted( $this->get_cookie_types() ) ) {
87
+ update_option( 'wp-piwik_global-disable_cookies', 1 );
88
+ }else{
89
+ update_option( 'wp-piwik_global-disable_cookies', 0 );
90
+ }
91
+ }
92
+ }
93
+
94
+ /**
95
+ * Check if plugin is activated and checked in the backend
96
+ *
97
+ * @since 1.3.0
98
+ */
99
+ public function is_addon_enabled() {
100
+ return $this->settings->is_addon_enabled( $this->get_option_name() );
101
+ }
102
+
103
+ /**
104
+ * Option name in the database
105
+ *
106
+ * @return string
107
+ *
108
+ * @since 1.3.0
109
+ */
110
+ public function get_option_name() {
111
+ return 'wp_piwik';
112
+ }
113
+
114
+ /**
115
+ * Returns checked cookie types
116
+ * @return mixed
117
+ *
118
+ * @since 1.3.0
119
+ */
120
+ public function get_cookie_types() {
121
+ return $this->settings->get_cookie_types( $this->get_option_name(), $this->get_default_cookie_types() );
122
+ }
123
+
124
+ /**
125
+ * Returns default cookie types
126
+ * @return array
127
+ *
128
+ * @since 1.3.0
129
+ */
130
+ public function get_default_cookie_types() {
131
+ return array( 'statistics' );
132
+ }
133
+
134
+ /**
135
+ * Return addon/plugin name
136
+ *
137
+ * @return string
138
+ *
139
+ * @since 1.3.0
140
+ */
141
+ public function get_addon_name() {
142
+ return 'WP Piwik';
143
+ }
144
+
145
+ /**
146
+ * Checks if addon is installed
147
+ *
148
+ * @since 1.3.0
149
+ */
150
+ public function is_addon_installed() {
151
+ return $this->settings->is_addon_installed( $this->get_plugin_file() );
152
+ }
153
+
154
+ /**
155
+ * Plugin file name
156
+ *
157
+ * @return string
158
+ *
159
+ * @since 1.3.0
160
+ */
161
+ public function get_plugin_file() {
162
+ return 'wp-piwik/wp-piwik.php';
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
+ /**
257
+ * Returns the url of WordPress SVN repository or another link where we can verify the plugin file.
258
+ *
259
+ * @return boolean
260
+ *
261
+ * @since 1.8.0
262
+ */
263
+ public function get_svn_url() {
264
+ return 'http://plugins.svn.wordpress.org/wp-piwik/trunk/wp-piwik.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 true if addon has an option to remove tag instead of adding attributes
280
+ *
281
+ * @return boolean
282
+ *
283
+ * @since 2.1.0
284
+ */
285
+ public function has_remove_tag_option() {
286
+ return false;
287
+ }
288
+
289
+ /**
290
+ * Returns parent class or false
291
+ *
292
+ * @return string|bool
293
+ *
294
+ * @since 2.1.3
295
+ */
296
+ public function get_parent_class() {
297
+ return get_parent_class( $this );
298
+ }
299
+
300
+ /**
301
+ * Action after enabling the addon on the settings page
302
+ *
303
+ * @since 2.2.0
304
+ */
305
+ public function post_hook_after_enabling() {
306
+ //do nothing
307
+ }
308
+
309
+ /**
310
+ * Cookiebot plugin is deactivated
311
+ *
312
+ * @since 2.2.0
313
+ */
314
+ public function plugin_deactivated() {
315
+ //do nothing
316
+ }
317
+ }
addons/controller/addons/wpforms/cookie-after-consent.js ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ( function ( $ ) {
2
+
3
+ var cookiebot_wpforms = {
4
+
5
+ init: function () {
6
+ $( document ).ready( cookiebot_wpforms.update_after_consent );
7
+ },
8
+
9
+ /**
10
+ * Async wpfuuid after the visitor clicked on cookie accept
11
+ */
12
+ update_after_consent: function () {
13
+ window.addEventListener( 'CookiebotOnAccept', function ( e ) {
14
+
15
+ if ( Cookiebot
16
+ && Cookiebot.consent
17
+ && Cookiebot.consent.preferences
18
+ && window.wpforms
19
+ && !window.wpforms.getCookie( '_wpfuuid' ) ) {
20
+ window.wpforms.setUserIndentifier();
21
+ }
22
+ }, false );
23
+ }
24
+ };
25
+
26
+ /**
27
+ * Make global hasRequiredConsent function to check cookie consent status
28
+ *
29
+ * @return {boolean}
30
+ */
31
+ window.hasRequiredConsent = function hasRequiredConsent() {
32
+ if ( Cookiebot && Cookiebot.consent ) {
33
+ let cookie_types = cookiebot_wpforms_settings.cookie_types;
34
+ let required = cookie_types.length;
35
+
36
+ const consent_given = cookie_types.filter(function(cookie_type){
37
+ return Cookiebot.consent[cookie_type];
38
+ });
39
+
40
+ if( required == consent_given.length ) {
41
+ return true;
42
+ }
43
+ }
44
+
45
+ return false;
46
+ };
47
+
48
+ cookiebot_wpforms.init();
49
+
50
+
51
+ } )( jQuery );
addons/controller/addons/wpforms/wpforms.php ADDED
@@ -0,0 +1,395 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\controller\addons\wpforms;
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 Wpforms 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
+ protected $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_wpforms' ), 5 );
65
+ }
66
+
67
+ /**
68
+ * Disable scripts if state not accepted
69
+ *
70
+ * @since 1.3.0
71
+ */
72
+ public function cookiebot_addon_wpforms() {
73
+ // Check if Add To Any is loaded.
74
+ if ( ! function_exists( 'wpforms' ) ) {
75
+ return;
76
+ }
77
+
78
+ // Check if Cookiebot is activated and active.
79
+ if ( ! function_exists( 'cookiebot_active' ) || ! cookiebot_active() ) {
80
+ return;
81
+ }
82
+
83
+ // consent is given
84
+ if ( $this->cookie_consent->are_cookie_states_accepted( $this->get_cookie_types() ) ) {
85
+ return;
86
+ }
87
+
88
+ add_filter( 'wpforms_disable_entry_user_ip', array( $this, 'gdpr_consent_is_given' ) );
89
+ add_action( 'wp_footer', array( $this, 'enqueue_script_for_adding_the_cookie_after_the_consent' ), 18 );
90
+ }
91
+
92
+ /**
93
+ * Create cookie when the visitor gives consent
94
+ */
95
+ public function enqueue_script_for_adding_the_cookie_after_the_consent() {
96
+ wp_enqueue_script( 'wpforms-gdpr-cookiebot', COOKIEBOT_URL . 'addons/controller/addons/wpforms/cookie-after-consent.js', array( 'jquery' ),
97
+ '',
98
+ true );
99
+ wp_localize_script( 'wpforms-gdpr-cookiebot', 'cookiebot_wpforms_settings', array( 'cookie_types' => $this->get_cookie_types() ) );
100
+ }
101
+
102
+ /**
103
+ * Retrieve if the cookie consent is given
104
+ *
105
+ * @return bool
106
+ *
107
+ * @since 2.1.4
108
+ */
109
+ public function gdpr_consent_is_given() {
110
+ if ( $this->cookie_consent->are_cookie_states_accepted( $this->get_cookie_types() ) ) {
111
+ return true;
112
+ }
113
+
114
+ return false;
115
+ }
116
+
117
+ /**
118
+ * Return addon/plugin name
119
+ *
120
+ * @return string
121
+ *
122
+ * @since 1.3.0
123
+ */
124
+ public function get_addon_name() {
125
+ return 'WPForms';
126
+ }
127
+
128
+ /**
129
+ * Default placeholder content
130
+ *
131
+ * @return string
132
+ *
133
+ * @since 1.8.0
134
+ */
135
+ public function get_default_placeholder() {
136
+ return 'Please accept [renew_consent]%cookie_types[/renew_consent] cookies to enable saving user information.';
137
+ }
138
+
139
+ /**
140
+ * Get placeholder content
141
+ *
142
+ * This function will check following features:
143
+ * - Current language
144
+ *
145
+ * @param $src
146
+ *
147
+ * @return bool|mixed
148
+ *
149
+ * @since 1.8.0
150
+ */
151
+ public function get_placeholder( $src = '' ) {
152
+ return $this->settings->get_placeholder( $this->get_option_name(), $this->get_default_placeholder(), cookiebot_addons_output_cookie_types( $this->get_cookie_types() ), $src );
153
+ }
154
+
155
+ /**
156
+ * Option name in the database
157
+ *
158
+ * @return string
159
+ *
160
+ * @since 1.3.0
161
+ */
162
+ public function get_option_name() {
163
+ return 'wpforms';
164
+ }
165
+
166
+ /**
167
+ * Plugin file name
168
+ *
169
+ * @return string
170
+ *
171
+ * @since 1.3.0
172
+ */
173
+ public function get_plugin_file() {
174
+ return 'wpforms/wpforms.php';
175
+ }
176
+
177
+ /**
178
+ * Returns checked cookie types
179
+ * @return mixed
180
+ *
181
+ * @since 1.3.0
182
+ */
183
+ public function get_cookie_types() {
184
+ return $this->settings->get_cookie_types( $this->get_option_name(), $this->get_default_cookie_types() );
185
+ }
186
+
187
+ /**
188
+ * Returns default cookie types
189
+ * @return array
190
+ *
191
+ * @since 1.5.0
192
+ */
193
+ public function get_default_cookie_types() {
194
+ return array( 'preferences' );
195
+ }
196
+
197
+ /**
198
+ * Check if plugin is activated and checked in the backend
199
+ *
200
+ * @since 1.3.0
201
+ */
202
+ public function is_addon_enabled() {
203
+ return $this->settings->is_addon_enabled( $this->get_option_name() );
204
+ }
205
+
206
+ /**
207
+ * Checks if addon is installed
208
+ *
209
+ * @since 1.3.0
210
+ */
211
+ public function is_addon_installed() {
212
+ $installed = $this->settings->is_addon_installed( $this->get_plugin_file() );
213
+
214
+ if ( $installed && version_compare( $this->get_addon_version(), '1.5.1', '<' ) ) {
215
+ $installed = false;
216
+ }
217
+
218
+ return $installed;
219
+ }
220
+
221
+ /**
222
+ * Checks if addon is activated
223
+ *
224
+ * @since 1.3.0
225
+ */
226
+ public function is_addon_activated() {
227
+ return $this->settings->is_addon_activated( $this->get_plugin_file() );
228
+ }
229
+
230
+ /**
231
+ * Retrieves current installed version of the addon
232
+ *
233
+ * @return bool
234
+ *
235
+ * @since 2.2.1
236
+ */
237
+ public function get_addon_version() {
238
+ return $this->settings->get_addon_version( $this->get_plugin_file() );
239
+ }
240
+
241
+ /**
242
+ * Checks if it does have custom placeholder content
243
+ *
244
+ * @return mixed
245
+ *
246
+ * @since 1.8.0
247
+ */
248
+ public function has_placeholder() {
249
+ return $this->settings->has_placeholder( $this->get_option_name() );
250
+ }
251
+
252
+ /**
253
+ * returns all placeholder contents
254
+ *
255
+ * @return mixed
256
+ *
257
+ * @since 1.8.0
258
+ */
259
+ public function get_placeholders() {
260
+ return $this->settings->get_placeholders( $this->get_option_name() );
261
+ }
262
+
263
+ /**
264
+ * Return true if the placeholder is enabled
265
+ *
266
+ * @return mixed
267
+ *
268
+ * @since 1.8.0
269
+ */
270
+ public function is_placeholder_enabled() {
271
+ return $this->settings->is_placeholder_enabled( $this->get_option_name() );
272
+ }
273
+
274
+ /**
275
+ * Adds extra information under the label
276
+ *
277
+ * @return string
278
+ *
279
+ * @since 1.8.0
280
+ */
281
+ public function get_extra_information() {
282
+ return '<p>' .
283
+ __( 'If the user gives correct consent, IP and Unique User ID will be saved on form submissions, otherwise not.', 'cookiebot-addons' ) .
284
+ '<br />' .
285
+ __( 'Increases opt-in rate compared to WPForms "GDPR mode".', 'cookiebot-addons' ) .
286
+ '</p>';
287
+ }
288
+
289
+ /**
290
+ * Returns the url of WordPress SVN repository or another link where we can verify the plugin file.
291
+ *
292
+ * @return string
293
+ *
294
+ * @since 1.8.0
295
+ */
296
+ public function get_svn_url() {
297
+ return false;
298
+ }
299
+
300
+ /**
301
+ * Placeholder helper overlay in the settings page.
302
+ *
303
+ * @return string
304
+ *
305
+ * @since 1.8.0
306
+ */
307
+ public function get_placeholder_helper() {
308
+ 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>';
309
+ }
310
+
311
+ /**
312
+ * Returns true if addon has an option to remove tag instead of adding attributes
313
+ *
314
+ * @return boolean
315
+ *
316
+ * @since 2.1.0
317
+ */
318
+ public function has_remove_tag_option() {
319
+ return false;
320
+ }
321
+
322
+ /**
323
+ * Return true if the remove tag option is enabled
324
+ *
325
+ * @return mixed
326
+ *
327
+ * @since 2.1.0
328
+ */
329
+ public function is_remove_tag_enabled() {
330
+ return $this->settings->is_remove_tag_enabled( $this->get_option_name() );
331
+ }
332
+
333
+ /**
334
+ * Returns parent class or false
335
+ *
336
+ * @return string|bool
337
+ *
338
+ * @since 2.1.3
339
+ */
340
+ public function get_parent_class() {
341
+ return get_parent_class( $this );
342
+ }
343
+
344
+ /**
345
+ * Action after enabling the addon on the settings page
346
+ *
347
+ * Clear gdpr settings in the wpforms
348
+ *
349
+ * @since 2.2.0
350
+ */
351
+ public function post_hook_after_enabling() {
352
+ $wpforms_settings = get_option( 'wpforms_settings' );
353
+
354
+ $wpforms_settings['gdpr'] = false;
355
+ $wpforms_settings['gdpr-disable-uuid'] = false;
356
+ $wpforms_settings['gdpr-disable-details'] = false;
357
+
358
+ update_option( 'wpforms_settings', $wpforms_settings );
359
+ }
360
+
361
+ /**
362
+ * Cookiebot plugin is deactivated
363
+ *
364
+ * @since 2.2.0
365
+ */
366
+ public function plugin_deactivated() {
367
+ // if the checkbox was checked and the cookiebot plugin is deactivated
368
+ // remove the setting so the default gdpr checkboxes are still visible
369
+ $this->wpforms_set_setting( 'gdpr-cookiebot', false );
370
+ }
371
+
372
+ /**
373
+ * Set the value of a specific WPForms setting.
374
+ *
375
+ * @since 1.5.0.4
376
+ *
377
+ * @param string $key
378
+ * @param mixed $new_value
379
+ * @param string $option
380
+ *
381
+ * @return mixed
382
+ */
383
+ public function wpforms_set_setting( $key, $new_value, $option = 'wpforms_settings' ) {
384
+
385
+ $key = wpforms_sanitize_key( $key );
386
+ $options = get_option( $option, false );
387
+ $option_value = is_array( $options ) && ! empty( $options[ $key ] ) ? $options[ $key ] : false;
388
+
389
+ if ( $new_value !== $option_value ) {
390
+ $options[ $key ] = $new_value;
391
+ }
392
+
393
+ update_option( $option, $options );
394
+ }
395
+ }
addons/controller/plugin-controller.php ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\controller;
4
+
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
+
11
+ /**
12
+ * IoC container - Dependency Injection
13
+ *
14
+ * @var Settings_Service_Interface
15
+ *
16
+ * @since 1.1.0
17
+ */
18
+ private $settings_service;
19
+
20
+ /**
21
+ * Plugin_Controller constructor.
22
+ *
23
+ * @param $settings_service Settings_Service_Interface IoC Container
24
+ *
25
+ * @since 1.2.0
26
+ */
27
+ public function __construct( Settings_Service_Interface $settings_service ) {
28
+ $this->settings_service = $settings_service;
29
+
30
+ $this->load_init_files();
31
+ }
32
+
33
+ /**
34
+ * Load init files to use 'validate_plugin' and 'is_plugin_active'
35
+ *
36
+ * @since 1.3.0
37
+ */
38
+ protected function load_init_files() {
39
+ if ( ! function_exists( 'is_plugin_active' ) ) {
40
+ require_once( ABSPATH . '/wp-admin/includes/plugin.php' );
41
+ require_once( ABSPATH . '/wp-includes/l10n.php' );
42
+ require_once( ABSPATH . '/wp-admin/includes/translation-install.php' );
43
+ }
44
+ }
45
+
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
54
+ */
55
+ public function load_active_addons() {
56
+ /**
57
+ * Check plugins one by one and load configuration if it is active
58
+ *
59
+ * @var $plugin Cookiebot_Addons_Interface
60
+ */
61
+ foreach ( $this->settings_service->get_active_addons() as $plugin ) {
62
+ $plugin->load_configuration();
63
+ }
64
+
65
+ /**
66
+ * After WordPress is fully loaded
67
+ *
68
+ * Run buffer output actions - this runs after scanning of every addons
69
+ */
70
+ add_action( 'parse_request', array( $this, 'run_buffer_output_manipulations' ) );
71
+ }
72
+
73
+ /**
74
+ * Runs every added action hooks to manipulate script tag
75
+ *
76
+ * @since 1.3.0
77
+ */
78
+ public function run_buffer_output_manipulations() {
79
+ /**
80
+ * @var $buffer_output Buffer_Output_Interface
81
+ */
82
+ $buffer_output = $this->settings_service->container->get( 'Buffer_Output_Interface' );
83
+
84
+ if ( $buffer_output->has_action() ) {
85
+ $buffer_output->run_actions();
86
+ }
87
+ }
88
+ }
addons/cookiebot-addons-init.php ADDED
@@ -0,0 +1,208 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons;
4
+
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;
13
+ } // Exit if accessed directly
14
+
15
+
16
+ /**
17
+ * __DIR__ of this plugin
18
+ */
19
+ define( 'COOKIEBOT_ADDONS_DIR', __DIR__ . DIRECTORY_SEPARATOR );
20
+
21
+ define( 'COOKIEBOT_ADDONS_BASE_NAME', dirname( plugin_basename( __FILE__ ) ) );
22
+
23
+ /**
24
+ * Same version as the CookiebotWP
25
+ */
26
+ define( 'COOKIEBOT_ADDONS_VERSION', '2.1.5' );
27
+
28
+ /**
29
+ * Register autoloader to load files/classes dynamically
30
+ */
31
+ include_once COOKIEBOT_ADDONS_DIR . 'lib/autoloader.php';
32
+
33
+ /**
34
+ * Load global functions for this plugin
35
+ */
36
+ include_once COOKIEBOT_ADDONS_DIR . 'lib/helper.php';
37
+
38
+ /**
39
+ * Load composer
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
+ */
54
+ public $container;
55
+
56
+ /**
57
+ * List of all supported addons
58
+ *
59
+ * @var object
60
+ *
61
+ * @since 1.3.0
62
+ */
63
+ public $plugins;
64
+
65
+ /**
66
+ * @var Cookiebot_Addons The single instance of the class
67
+ * @since 1.0.0
68
+ */
69
+ protected static $_instance = null;
70
+
71
+ /**
72
+ * Main Cookiebot_WP Instance
73
+ *
74
+ * Ensures only one instance of Cookiebot_Addons is loaded or can be loaded.
75
+ *
76
+ * @version 2.2.0
77
+ * @since 2.2.0
78
+ * @static
79
+ *
80
+ * @return Cookiebot_Addons
81
+ */
82
+ public static function instance() {
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.';
90
+ }
91
+ }
92
+
93
+ return self::$_instance;
94
+ }
95
+
96
+ /**
97
+ * Cookiebot_Addons constructor.
98
+ *
99
+ * @throws DI\DependencyException
100
+ * @throws DI\NotFoundException
101
+ *
102
+ * @since 1.3.0
103
+ */
104
+ public function __construct() {
105
+ $this->get_plugins();
106
+ $this->build_container();
107
+ $this->assign_addons_to_container();
108
+
109
+ /**
110
+ * Load plugin controller to check if addons are active
111
+ * If active then load the plugin addon configuration class
112
+ * Else skip it
113
+ *
114
+ * @since 1.1.0
115
+ */
116
+ add_action( 'plugins_loaded', array(
117
+ new Plugin_Controller( $this->container->get( 'Settings_Service_Interface' ) ),
118
+ 'load_active_addons'
119
+ ) );
120
+
121
+ /**
122
+ * Load settings config
123
+ *
124
+ * @since 1.1.0
125
+ */
126
+ $settings = new Settings_Config( $this->container->get( 'Settings_Service_Interface' ) );
127
+ $settings->load();
128
+ }
129
+
130
+ /**
131
+ * if the cookiebot is deactivated
132
+ * run this script to clean up addons.
133
+ *
134
+ * @since 2.2.0
135
+ */
136
+ public function cookiebot_deactivated() {
137
+ $settings_service = $this->container->get( 'Settings_Service_Interface' );
138
+ $settings_service->cookiebot_deactivated();
139
+ }
140
+
141
+ /**
142
+ * Loads plugins from json file
143
+ *
144
+ * All the addon plugins are defined there.
145
+ *
146
+ * The file is located at the root map of this plugin
147
+ *
148
+ * @since 1.3.0
149
+ */
150
+ protected function get_plugins() {
151
+ $file = file_get_contents( COOKIEBOT_ADDONS_DIR . 'addons.json' );
152
+ $this->plugins = json_decode( $file );
153
+ }
154
+
155
+ /**
156
+ * Build IoC container
157
+ *
158
+ * @since 1.3.0
159
+ */
160
+ protected function build_container() {
161
+ $builder = new ContainerBuilder();
162
+
163
+ $builder->addDefinitions(
164
+ array(
165
+ 'Script_Loader_Tag_Interface' => DI\object( 'cookiebot_addons\lib\script_loader_tag\Script_Loader_Tag' ),
166
+ 'Cookie_Consent_Interface' => DI\object( 'cookiebot_addons\lib\Cookie_Consent' ),
167
+ 'Buffer_Output_Interface' => DI\object( 'cookiebot_addons\lib\buffer\Buffer_Output' ),
168
+ 'plugins' => DI\value( $this->plugins )
169
+ )
170
+ );
171
+
172
+ $this->container = $builder->build();
173
+
174
+ $this->container->set( 'Settings_Service_Interface', DI\object( 'cookiebot_addons\lib\Settings_Service' )
175
+ ->constructor( $this->container ) );
176
+ }
177
+
178
+ /**
179
+ * Assign addon class to the container to use it later
180
+ *
181
+ * @throws DI\DependencyException
182
+ * @throws DI\NotFoundException
183
+ *
184
+ * @since 1.3.0
185
+ */
186
+ protected function assign_addons_to_container() {
187
+ /**
188
+ * Check plugins one by one and load addon configuration
189
+ */
190
+ foreach ( $this->plugins as $plugin_class => $plugin ) {
191
+ /**
192
+ * Load addon class to the container
193
+ */
194
+ $this->container->set( $plugin->class, \DI\object( $plugin->class )
195
+ ->constructor(
196
+ $this->container->get( 'Settings_Service_Interface' ),
197
+ $this->container->get( 'Script_Loader_Tag_Interface' ),
198
+ $this->container->get( 'Cookie_Consent_Interface' ),
199
+ $this->container->get( 'Buffer_Output_Interface' ) )
200
+ );
201
+ }
202
+ }
203
+ }
204
+
205
+ /**
206
+ * Initiate the cookiebot addons framework plugin
207
+ */
208
+ Cookiebot_Addons::instance();
addons/js/jquery.tipTip.js ADDED
@@ -0,0 +1,193 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * TipTip
3
+ * Copyright 2010 Drew Wilson
4
+ * www.drewwilson.com
5
+ * code.drewwilson.com/entry/tiptip-jquery-plugin
6
+ *
7
+ * Version 1.3 - Updated: Mar. 23, 2010
8
+ *
9
+ * This Plug-In will create a custom tooltip to replace the default
10
+ * browser tooltip. It is extremely lightweight and very smart in
11
+ * that it detects the edges of the browser window and will make sure
12
+ * the tooltip stays within the current window size. As a result the
13
+ * tooltip will adjust itself to be displayed above, below, to the left
14
+ * or to the right depending on what is necessary to stay within the
15
+ * browser window. It is completely customizable as well via CSS.
16
+ *
17
+ * This TipTip jQuery plug-in is dual licensed under the MIT and GPL licenses:
18
+ * http://www.opensource.org/licenses/mit-license.php
19
+ * http://www.gnu.org/licenses/gpl.html
20
+ */
21
+
22
+ (function($){
23
+ $.fn.tipTip = function(options) {
24
+ var defaults = {
25
+ activation: "hover",
26
+ keepAlive: false,
27
+ maxWidth: "200px",
28
+ edgeOffset: 3,
29
+ defaultPosition: "bottom",
30
+ delay: 400,
31
+ fadeIn: 200,
32
+ fadeOut: 200,
33
+ attribute: "title",
34
+ content: false, // HTML or String to fill TipTIp with
35
+ enter: function(){},
36
+ exit: function(){}
37
+ };
38
+ var opts = $.extend(defaults, options);
39
+
40
+ // Setup tip tip elements and render them to the DOM
41
+ if($("#tiptip_holder").length <= 0){
42
+ var tiptip_holder = $('<div id="tiptip_holder" style="max-width:'+ opts.maxWidth +';"></div>');
43
+ var tiptip_content = $('<div id="tiptip_content"></div>');
44
+ var tiptip_arrow = $('<div id="tiptip_arrow"></div>');
45
+ $("body").append(tiptip_holder.html(tiptip_content).prepend(tiptip_arrow.html('<div id="tiptip_arrow_inner"></div>')));
46
+ } else {
47
+ var tiptip_holder = $("#tiptip_holder");
48
+ var tiptip_content = $("#tiptip_content");
49
+ var tiptip_arrow = $("#tiptip_arrow");
50
+ }
51
+
52
+ return this.each(function(){
53
+ var org_elem = $(this);
54
+ if(opts.content){
55
+ var org_title = opts.content;
56
+ } else {
57
+ var org_title = org_elem.attr(opts.attribute);
58
+ }
59
+
60
+ if(org_title != ""){
61
+ if(!opts.content){
62
+ org_elem.removeAttr(opts.attribute); //remove original Attribute
63
+ }
64
+ var timeout = false;
65
+
66
+ if(opts.activation == "hover"){
67
+ org_elem.hover(function(){
68
+ active_tiptip();
69
+ }, function(){
70
+ if(!opts.keepAlive){
71
+ deactive_tiptip();
72
+ }
73
+ });
74
+ if(opts.keepAlive){
75
+ tiptip_holder.hover(function(){}, function(){
76
+ deactive_tiptip();
77
+ });
78
+ }
79
+ } else if(opts.activation == "focus"){
80
+ org_elem.focus(function(){
81
+ active_tiptip();
82
+ }).blur(function(){
83
+ deactive_tiptip();
84
+ });
85
+ } else if(opts.activation == "click"){
86
+ org_elem.click(function(){
87
+ active_tiptip();
88
+ return false;
89
+ }).hover(function(){},function(){
90
+ if(!opts.keepAlive){
91
+ deactive_tiptip();
92
+ }
93
+ });
94
+ if(opts.keepAlive){
95
+ tiptip_holder.hover(function(){}, function(){
96
+ deactive_tiptip();
97
+ });
98
+ }
99
+ }
100
+
101
+ function active_tiptip(){
102
+ opts.enter.call(this);
103
+ tiptip_content.html(org_title);
104
+ tiptip_holder.hide().removeAttr("class").css("margin","0");
105
+ tiptip_arrow.removeAttr("style");
106
+
107
+ var top = parseInt(org_elem.offset()['top']);
108
+ var left = parseInt(org_elem.offset()['left']);
109
+ var org_width = parseInt(org_elem.outerWidth());
110
+ var org_height = parseInt(org_elem.outerHeight());
111
+ var tip_w = tiptip_holder.outerWidth();
112
+ var tip_h = tiptip_holder.outerHeight();
113
+ var w_compare = Math.round((org_width - tip_w) / 2);
114
+ var h_compare = Math.round((org_height - tip_h) / 2);
115
+ var marg_left = Math.round(left + w_compare);
116
+ var marg_top = Math.round(top + org_height + opts.edgeOffset);
117
+ var t_class = "";
118
+ var arrow_top = "";
119
+ var arrow_left = Math.round(tip_w - 12) / 2;
120
+
121
+ if(opts.defaultPosition == "bottom"){
122
+ t_class = "_bottom";
123
+ } else if(opts.defaultPosition == "top"){
124
+ t_class = "_top";
125
+ } else if(opts.defaultPosition == "left"){
126
+ t_class = "_left";
127
+ } else if(opts.defaultPosition == "right"){
128
+ t_class = "_right";
129
+ }
130
+
131
+ var right_compare = (w_compare + left) < parseInt($(window).scrollLeft());
132
+ var left_compare = (tip_w + left) > parseInt($(window).width());
133
+
134
+ if((right_compare && w_compare < 0) || (t_class == "_right" && !left_compare) || (t_class == "_left" && left < (tip_w + opts.edgeOffset + 5))){
135
+ t_class = "_right";
136
+ arrow_top = Math.round(tip_h - 13) / 2;
137
+ arrow_left = -12;
138
+ marg_left = Math.round(left + org_width + opts.edgeOffset);
139
+ marg_top = Math.round(top + h_compare);
140
+ } else if((left_compare && w_compare < 0) || (t_class == "_left" && !right_compare)){
141
+ t_class = "_left";
142
+ arrow_top = Math.round(tip_h - 13) / 2;
143
+ arrow_left = Math.round(tip_w);
144
+ marg_left = Math.round(left - (tip_w + opts.edgeOffset + 5));
145
+ marg_top = Math.round(top + h_compare);
146
+ }
147
+
148
+ var top_compare = (top + org_height + opts.edgeOffset + tip_h + 8) > parseInt($(window).height() + $(window).scrollTop());
149
+ var bottom_compare = ((top + org_height) - (opts.edgeOffset + tip_h + 8)) < 0;
150
+
151
+ if(top_compare || (t_class == "_bottom" && top_compare) || (t_class == "_top" && !bottom_compare)){
152
+ if(t_class == "_top" || t_class == "_bottom"){
153
+ t_class = "_top";
154
+ } else {
155
+ t_class = t_class+"_top";
156
+ }
157
+ arrow_top = tip_h;
158
+ marg_top = Math.round(top - (tip_h + 5 + opts.edgeOffset));
159
+ } else if(bottom_compare | (t_class == "_top" && bottom_compare) || (t_class == "_bottom" && !top_compare)){
160
+ if(t_class == "_top" || t_class == "_bottom"){
161
+ t_class = "_bottom";
162
+ } else {
163
+ t_class = t_class+"_bottom";
164
+ }
165
+ arrow_top = -12;
166
+ marg_top = Math.round(top + org_height + opts.edgeOffset);
167
+ }
168
+
169
+ if(t_class == "_right_top" || t_class == "_left_top"){
170
+ marg_top = marg_top + 5;
171
+ } else if(t_class == "_right_bottom" || t_class == "_left_bottom"){
172
+ marg_top = marg_top - 5;
173
+ }
174
+ if(t_class == "_left_top" || t_class == "_left_bottom"){
175
+ marg_left = marg_left + 5;
176
+ }
177
+
178
+ tiptip_arrow.css({"margin-left": arrow_left+"px", "margin-top": arrow_top+"px"});
179
+ tiptip_holder.css({"margin-left": marg_left+"px", "margin-top": marg_top+"px"}).attr("class","tip"+t_class);
180
+
181
+ if (timeout){ clearTimeout(timeout); }
182
+ timeout = setTimeout(function(){ tiptip_holder.stop(true,true).fadeIn(opts.fadeIn); }, opts.delay);
183
+ }
184
+
185
+ function deactive_tiptip(){
186
+ opts.exit.call(this);
187
+ if (timeout){ clearTimeout(timeout); }
188
+ tiptip_holder.fadeOut(opts.fadeOut);
189
+ }
190
+ }
191
+ });
192
+ }
193
+ })(jQuery);
addons/js/settings.js ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Load init function when the page is ready
3
+ *
4
+ * @since 1.8.0
5
+ */
6
+ jQuery( document ).ready( init );
7
+
8
+ /**
9
+ * Init settings
10
+ *
11
+ * @since 1.8.0
12
+ */
13
+ function init() {
14
+ placeholder_select_language();
15
+ placeholder_toggle();
16
+ button_add_placeholder_language();
17
+ button_delete_language();
18
+ tooltip();
19
+ }
20
+
21
+ /**
22
+ * Enable/disable placeholder
23
+ *
24
+ * @since 1.8.0
25
+ */
26
+ function placeholder_toggle() {
27
+ jQuery( document ).on( 'change', '.placeholder_enable', function () {
28
+ var status = jQuery( this ).is( ':checked' );
29
+ var addon = jQuery( this ).data( 'addon' );
30
+
31
+ if ( status ) {
32
+ placeholder_enable( addon );
33
+ } else {
34
+ placeholder_disable( addon );
35
+ }
36
+ } );
37
+ }
38
+
39
+ /**
40
+ * Placeholder disable
41
+ *
42
+ * @param addon
43
+ *
44
+ * @since 1.8.0
45
+ */
46
+ function placeholder_disable( addon ) {
47
+ jQuery( '.placeholder[data-addon="' + addon + '"]' ).hide();
48
+ }
49
+
50
+ /**
51
+ * Placeholder enable
52
+ *
53
+ * @param addon
54
+ *
55
+ * @since 1.8.0
56
+ */
57
+ function placeholder_enable( addon ) {
58
+ jQuery( '.placeholder[data-addon="' + addon + '"]' ).show();
59
+ }
60
+
61
+ /**
62
+ * Add language for placeholder
63
+ *
64
+ * @since 1.8.0
65
+ */
66
+ function button_add_placeholder_language() {
67
+ jQuery( '.btn_add_language' ).on( 'click', function ( e ) {
68
+ e.preventDefault();
69
+
70
+ var addon = jQuery( this ).data( 'addon' );
71
+
72
+ add_placeholder_language_content( addon );
73
+
74
+ return false;
75
+ } );
76
+ }
77
+
78
+ /**
79
+ * Add placeholder language div
80
+ *
81
+ * @param addon
82
+ *
83
+ * @since 1.8.0
84
+ */
85
+ function add_placeholder_language_content( addon ) {
86
+ var data = jQuery( '.placeholder[data-addon="' + addon + '"] .placeholder_content:first' )[ 0 ].outerHTML;
87
+
88
+
89
+ jQuery( '.placeholder[data-addon="' + addon + '"] .add_placeholder_language' ).before( data );
90
+
91
+ jQuery( '.placeholder[data-addon="' + addon + '"] .placeholder_content:last select' ).after( php.remove_link );
92
+
93
+ tooltip();
94
+ }
95
+
96
+ /**
97
+ * Replace select and textarea name
98
+ *
99
+ * @since 1.8.0
100
+ */
101
+ function placeholder_select_language() {
102
+ jQuery( document ).on( 'change', '.placeholder_select_language', function () {
103
+ var new_value = jQuery( this ).val();
104
+ var select_name = jQuery( this ).attr( 'name' );
105
+
106
+ // get new name
107
+ select_name = select_name.substr( 0, select_name.lastIndexOf( '[' ) );
108
+ select_name += '[' + new_value + ']';
109
+
110
+ // rename select field
111
+ jQuery( this ).attr( 'name', select_name );
112
+
113
+ // rename textarea
114
+ jQuery( this ).parent().next().find( 'textarea' ).attr( 'name', select_name );
115
+ } )
116
+ }
117
+
118
+ /**
119
+ * Delete language
120
+ *
121
+ * @since 1.8.0
122
+ */
123
+ function button_delete_language() {
124
+ jQuery( document ).on( 'click', '.submitdelete', function ( e ) {
125
+ e.preventDefault();
126
+
127
+ jQuery( this ).parent().parent().remove();
128
+
129
+ return false;
130
+ } );
131
+ }
132
+
133
+ /**
134
+ * Show tooltip
135
+ *
136
+ * @since 1.8.0
137
+ */
138
+ function tooltip() {
139
+ jQuery( '.help-tip' ).tipTip( {
140
+ 'maxWidth': 300,
141
+ 'fadeIn': 50,
142
+ 'fadeOut': 50,
143
+ 'delay': 200
144
+ } );
145
+ }
addons/lib/autoloader.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class Cookiebot_Addons_Autoloader
5
+ *
6
+ * @since 1.1.0
7
+ */
8
+ class Cookiebot_Addons_Autoloader {
9
+
10
+ /**
11
+ * plugin root namespace
12
+ *
13
+ * @sice 1.1.0
14
+ */
15
+ const ROOT_NAMESPACE = 'cookiebot_addons\\';
16
+
17
+ /**
18
+ * Register autoload method
19
+ *
20
+ * @since 1.1.0
21
+ */
22
+ public function __construct() {
23
+ spl_autoload_register( array( $this, 'cookiebot_autoloader_callback' ) );
24
+ }
25
+
26
+ /**
27
+ * Includes file from the correct namespace
28
+ * else it will do nothing
29
+ *
30
+ * @param $class
31
+ *
32
+ * @since 1.1.0
33
+ */
34
+ public function cookiebot_autoloader_callback($class) {
35
+ if ( strpos( $class, self::ROOT_NAMESPACE ) === 0 ) {
36
+ $path = substr( $class, strlen( self::ROOT_NAMESPACE ) );
37
+ $path = strtolower( $path );
38
+ $path = str_replace( '_', '-', $path );
39
+ $path = str_replace( '\\', DIRECTORY_SEPARATOR, $path ) . '.php';
40
+ $path = COOKIEBOT_ADDONS_DIR . DIRECTORY_SEPARATOR . $path;
41
+
42
+ if ( file_exists( $path ) ) {
43
+ include $path;
44
+ }
45
+ }
46
+ }
47
+ }
48
+
49
+ /**
50
+ * Start autoloader
51
+ *
52
+ * @since 1.1.0
53
+ */
54
+ new Cookiebot_Addons_Autoloader();
addons/lib/buffer/buffer-output-interface.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\lib\buffer;
4
+
5
+ Interface Buffer_Output_Interface {
6
+
7
+ /**
8
+ * @param $tag_name string Hook name
9
+ * @param $priority integer Hook priority
10
+ * @param array $keywords List of words to search for in the script
11
+ * @param boolean $use_cache Use Cache
12
+ *
13
+ * @since 1.2.0
14
+ */
15
+ public function add_tag( $tag_name, $priority, $keywords = array(), $use_cache = true );
16
+
17
+ /**
18
+ * Process every tag
19
+ *
20
+ * @since 1.2.0
21
+ */
22
+ public function run_actions();
23
+
24
+ /**
25
+ * Returns true if tags has more than 0 item
26
+ *
27
+ * @return bool
28
+ *
29
+ * @since 1.2.0
30
+ */
31
+ public function has_action();
32
+ }
addons/lib/buffer/buffer-output-tag-interface.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\lib\buffer;
4
+
5
+ Interface Buffer_Output_Tag_Interface {
6
+
7
+ /**
8
+ * Buffer_Output_Tag_Interface constructor.
9
+ *
10
+ * @param $tag
11
+ * @param $priority
12
+ * @param array $keywords
13
+ *
14
+ * @version 1.3.0
15
+ * @since 1.1.0
16
+ */
17
+ public function __construct( $tag, $priority, $keywords = array() );
18
+
19
+ /**
20
+ * Start buffering
21
+ *
22
+ * @since 1.1.0
23
+ */
24
+ public function cookiebot_start_buffer();
25
+
26
+ /**
27
+ * End buffer and return manipulated output
28
+ *
29
+ * @since 1.1.0
30
+ */
31
+ public function cookiebot_stop_buffer();
32
+
33
+ /**
34
+ * Manipulate the output and add scritp attributes if it does match the criterion
35
+ *
36
+ * @param $buffer string Catched output
37
+ *
38
+ * @return mixed string Manipulated Output
39
+ *
40
+ * @since 1.1.0
41
+ */
42
+ public function manipulate_script( $buffer );
43
+ }
addons/lib/buffer/buffer-output-tag.php ADDED
@@ -0,0 +1,135 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\lib\buffer;
4
+
5
+ class Buffer_Output_Tag implements Buffer_Output_Tag_Interface {
6
+
7
+ /**
8
+ * Hook priority
9
+ *
10
+ * @var integer
11
+ *
12
+ * @since 1.1.0
13
+ */
14
+ public $priority;
15
+
16
+ /**
17
+ * Hook tag name
18
+ *
19
+ * @var string
20
+ *
21
+ * @since 1.2.0
22
+ */
23
+ public $tag;
24
+
25
+ /**
26
+ * Keywords to allow in the scripts
27
+ *
28
+ * @var array array
29
+ *
30
+ * @since 1.2.0
31
+ */
32
+ private $keywords;
33
+
34
+ /**
35
+ * Transient unique name
36
+ *
37
+ * @var string
38
+ *
39
+ * @since 1.1.0
40
+ */
41
+ private $transient_name;
42
+
43
+ /**
44
+ *
45
+ * Use transient cache
46
+ *
47
+ * @var boolean
48
+ *
49
+ * @since 1.2.0
50
+ */
51
+ private $use_cache;
52
+
53
+ /**
54
+ * Cookiebot_Buffer_Output_Tag constructor.
55
+ *
56
+ * @param $tag
57
+ * @param $priority
58
+ * @param array $keywords
59
+ * @param boolean $use_cache
60
+ *
61
+ * @since 1.2.0
62
+ */
63
+ public function __construct( $tag, $priority, $keywords = array(), $use_cache = true ) {
64
+ $this->tag = $tag;
65
+ $this->priority = $priority;
66
+ $this->keywords = $keywords;
67
+ $this->use_cache = $use_cache;
68
+ }
69
+
70
+ /**
71
+ * Merges new keywords in existence keywords variable
72
+ *
73
+ * @param $keywords
74
+ *
75
+ * @since 1.2.0
76
+ */
77
+ public function merge_keywords( $keywords ) {
78
+ $this->keywords = array_merge( $this->keywords, $keywords );
79
+ }
80
+
81
+ /**
82
+ * Start reading the buffer/output
83
+ *
84
+ * @since 1.1.0
85
+ */
86
+ public function cookiebot_start_buffer() {
87
+ ob_start( array( $this, 'manipulate_script' ) );
88
+ }
89
+
90
+ /**
91
+ * Stop reading the output and output buffered data through manipulate script filter.
92
+ *
93
+ * @since 1.1.0
94
+ */
95
+ public function cookiebot_stop_buffer() {
96
+ ob_end_flush();
97
+ }
98
+
99
+ /**
100
+ * Manipulate google analytic scripts to cookiebot and return it back
101
+ *
102
+ * @param $buffer
103
+ *
104
+ * @return null|string|string[]
105
+ *
106
+ * @since 1.1.0
107
+ */
108
+ public function manipulate_script( $buffer ) {
109
+ /**
110
+ * Get wp head scripts from the cache
111
+ */
112
+ if( $this->use_cache ) {
113
+ $updated_scripts = get_transient( $this->transient_name );
114
+ }
115
+
116
+ /**
117
+ * If cache is not set then build it
118
+ */
119
+ if ( !$this->use_cache || $updated_scripts === false ) {
120
+ /**
121
+ * Get all scripts and add cookieconsent if it does match with the criterion
122
+ */
123
+ $updated_scripts = cookiebot_addons_manipulate_script( $buffer, $this->keywords );
124
+
125
+ if( $this->use_cache ) {
126
+ /**
127
+ * Set cache for 15 minutes
128
+ */
129
+ set_transient( $this->transient_name, $updated_scripts, 60 * 15 );
130
+ }
131
+ }
132
+
133
+ return $updated_scripts;
134
+ }
135
+ }
addons/lib/buffer/buffer-output.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\lib\buffer;
4
+
5
+ class Buffer_Output implements Buffer_Output_Interface {
6
+
7
+ /**
8
+ * Hook tag names
9
+ *
10
+ * @var array
11
+ *
12
+ * @since 1.2.0
13
+ */
14
+ private $tags = array();
15
+
16
+ /**
17
+ * @param $tag_name string Hook name
18
+ * @param $priority integer Hook priority
19
+ * @param array $keywords array List of words to search for in the script
20
+ * @param boolean $use_cache Use Cache
21
+ *
22
+ * @since 1.2.0
23
+ */
24
+ public function add_tag( $tag_name, $priority, $keywords = array(), $use_cache = true) {
25
+ $tag = new Buffer_Output_Tag( $tag_name, $priority, $keywords, $use_cache );
26
+ $unique_id = $tag->tag . '_' . $tag->priority;
27
+
28
+ /**
29
+ * If tag_name and priority exists
30
+ * Then merge the keywords
31
+ */
32
+ if ( in_array( $unique_id, $this->tags ) ) {
33
+ $tag->merge_keywords( $keywords );
34
+ }
35
+
36
+ $this->tags[ $unique_id ] = $tag;
37
+ }
38
+
39
+ /**
40
+ * Process every tag
41
+ *
42
+ * @since 1.2.0
43
+ */
44
+ public function run_actions() {
45
+ foreach ( $this->tags as $tag ) {
46
+ add_action( $tag->tag, array( $tag, 'cookiebot_start_buffer' ), $tag->priority - 1 );
47
+ add_action( $tag->tag, array( $tag, 'cookiebot_stop_buffer' ), $tag->priority + 1 );
48
+ }
49
+ }
50
+
51
+ /**
52
+ * Returns true if tags has more than 0 item
53
+ *
54
+ * @return bool
55
+ *
56
+ * @since 1.2.0
57
+ */
58
+ public function has_action() {
59
+ return ( count( $this->tags ) > 0 ) ? true : false;
60
+ }
61
+ }
addons/lib/cookie-consent-interface.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\lib;
4
+
5
+ Interface Cookie_Consent_Interface {
6
+
7
+ /**
8
+ * Scans cookiebot consent cookie and fills in $states with accepted consents.
9
+ *
10
+ * @since 1.2.0
11
+ */
12
+ public function scan_cookie();
13
+
14
+ /**
15
+ * Adds state to $states variable
16
+ *
17
+ * @param $state string new state
18
+ *
19
+ * @since 1.2.0
20
+ */
21
+ public function add_state( $state );
22
+
23
+ /**
24
+ * Returns cookiebot cookie consent state
25
+ *
26
+ * @return array array List of accepted cookiebot consents
27
+ *
28
+ * @since 1.2.0
29
+ */
30
+ public function get_cookie_states();
31
+
32
+ /**
33
+ * Checks if the cookie state is accepted
34
+ *
35
+ * @param $state string Cookie state to check if it is accepted
36
+ *
37
+ * @return bool
38
+ *
39
+ * @since 1.2.0
40
+ */
41
+ public function is_cookie_state_accepted( $state );
42
+
43
+ /**
44
+ * Checks if the cookie states are accepted.
45
+ *
46
+ * @param $states array Cookie states to check if it is accepted.
47
+ *
48
+ * @return bool
49
+ *
50
+ * @since 1.3.0
51
+ */
52
+ public function are_cookie_states_accepted( $states );
53
+ }
addons/lib/cookie-consent.php ADDED
@@ -0,0 +1,144 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\lib;
4
+
5
+ class Cookie_Consent implements Cookie_Consent_Interface {
6
+
7
+ /**
8
+ * Array of cookiebot consent states
9
+ *
10
+ * It can have 4 items:
11
+ * - necessary
12
+ * - preferences
13
+ * - statistics
14
+ * - marketing
15
+ *
16
+ * @var array consent state
17
+ *
18
+ * @since 1.2.0
19
+ */
20
+ private $states = array();
21
+
22
+ /**
23
+ * Scan cookiebot cookie
24
+ *
25
+ * @since 1.2.0
26
+ */
27
+ public function __construct() {
28
+ $this->scan_cookie();
29
+ }
30
+
31
+ /**
32
+ * Scans cookiebot consent cookie and fills in $states with accepted consents.
33
+ *
34
+ * @since 1.2.0
35
+ */
36
+ public function scan_cookie() {
37
+ //default - set strictly necessary cookies
38
+ $this->add_state( 'necessary' );
39
+
40
+ if ( isset( $_COOKIE["CookieConsent"] ) ) {
41
+ switch ( $_COOKIE["CookieConsent"] ) {
42
+ case "0":
43
+ //The user has not accepted cookies - set strictly necessary cookies only
44
+ break;
45
+
46
+ case "-1":
47
+ //The user is not within a region that requires consent - all cookies are accepted
48
+ $this->add_state( 'preferences' );
49
+ $this->add_state( 'statistics' );
50
+ $this->add_state( 'marketing' );
51
+ break;
52
+
53
+ default: //The user has accepted one or more type of cookies
54
+
55
+ //Read current user consent in encoded JavaScript format
56
+ $valid_php_json = preg_replace( '/\s*:\s*([a-zA-Z0-9_]+?)([}\[,])/', ':"$1"$2', preg_replace( '/([{\[,])\s*([a-zA-Z0-9_]+?):/', '$1"$2":', str_replace( "'", '"', stripslashes( $_COOKIE["CookieConsent"] ) ) ) );
57
+ $CookieConsent = json_decode( $valid_php_json );
58
+
59
+ if ( filter_var( $CookieConsent->preferences, FILTER_VALIDATE_BOOLEAN ) ) {
60
+ //Current user accepts preference cookies
61
+ $this->add_state( 'preferences' );
62
+ } else {
63
+ //Current user does NOT accept preference cookies
64
+ }
65
+
66
+ if ( filter_var( $CookieConsent->statistics, FILTER_VALIDATE_BOOLEAN ) ) {
67
+ //Current user accepts statistics cookies
68
+ $this->add_state( 'statistics' );
69
+ } else {
70
+ //Current user does NOT accept statistics cookies
71
+ }
72
+
73
+ if ( filter_var( $CookieConsent->marketing, FILTER_VALIDATE_BOOLEAN ) ) {
74
+ //Current user accepts marketing cookies
75
+ $this->add_state( 'marketing' );
76
+ } else {
77
+ //Current user does NOT accept marketing cookies
78
+ }
79
+ }
80
+ } else {
81
+ //The user has not accepted cookies - set strictly necessary cookies only
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Adds state to $states variable
87
+ *
88
+ * @param $state string new state
89
+ *
90
+ * @since 1.2.0
91
+ */
92
+ public function add_state( $state ) {
93
+ if ( ! in_array( $state, $this->states ) ) {
94
+ $this->states[] = $state;
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Returns cookiebot cookie consent state
100
+ *
101
+ * @return array array List of accepted cookiebot consents
102
+ *
103
+ * @since 1.2.0
104
+ */
105
+ public function get_cookie_states() {
106
+ if ( count( $this->states ) == 0 ) {
107
+ $this->scan_cookie();
108
+ }
109
+
110
+ return $this->states;
111
+ }
112
+
113
+ /**
114
+ * Checks if the cookie states are accepted.
115
+ *
116
+ * @param $states array Cookie states to check if it is accepted.
117
+ *
118
+ * @return bool
119
+ *
120
+ * @since 1.3.0
121
+ */
122
+ public function are_cookie_states_accepted( $states ) {
123
+ if ( is_array( $states ) ) {
124
+ foreach ( $states as $state ) {
125
+ if ( ! in_array( $state, $this->states ) ) {
126
+ return false;
127
+ }
128
+ }
129
+ }
130
+
131
+ return true;
132
+ }
133
+
134
+ /**
135
+ * Checks if the cookie state is accepted
136
+ *
137
+ * @param $state string Cookie state to check if it is accepted
138
+ *
139
+ * @return bool
140
+ */
141
+ public function is_cookie_state_accepted( $state ) {
142
+ return in_array( $state, $this->states );
143
+ }
144
+ }
addons/lib/helper.php ADDED
@@ -0,0 +1,260 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Removes action with class in callback
5
+ *
6
+ * @param $action string action name
7
+ * @param $class string class name
8
+ * @param $method string method name
9
+ * @param $priority integer action priority number
10
+ *
11
+ * @return boolean True if the action hook is deleted
12
+ * False If the action hook is not deleted
13
+ *
14
+ * @since 1.2.0
15
+ */
16
+ function cookiebot_addons_remove_class_action( $action, $class, $method, $priority = 10 ) {
17
+ global $wp_filter;
18
+ $deleted = false;
19
+
20
+ if ( isset( $wp_filter[ $action ] ) && isset( $wp_filter[ $action ][ $priority ] ) ) {
21
+ $len = strlen( $method );
22
+ foreach ( $wp_filter[ $action ][ $priority ] as $name => $def ) {
23
+ if ( substr( $name, - $len ) == $method ) {
24
+ if ( is_array( $def['function'] ) ) {
25
+ if ( is_string( $def['function'][0] ) !== false ) {
26
+ $def_class = $def['function'][0];
27
+ } else {
28
+ $def_class = get_class( $def['function'][0] );
29
+ }
30
+
31
+ if ( $def_class == $class ) {
32
+ if ( is_object( $wp_filter[ $action ] ) && isset( $wp_filter[ $action ]->callbacks ) ) {
33
+ $wp_filter[ $action ]->remove_filter( $action, $name, $priority );
34
+ $deleted = true;
35
+ } else {
36
+ unset( $wp_filter[ $action ][ $priority ][ $name ] );
37
+ $deleted = true;
38
+ }
39
+ }
40
+ }
41
+ }
42
+ }
43
+ }
44
+
45
+ return $deleted;
46
+ }
47
+
48
+ /**
49
+ * Custom manipulation of the script
50
+ *
51
+ * @param $buffer
52
+ * @param $keywords
53
+ * @param $cookie_type
54
+ *
55
+ * @return mixed|null|string|string[]
56
+ *
57
+ * @version 2.0.4
58
+ * @since 1.2.0
59
+ */
60
+ function cookiebot_addons_manipulate_script( $buffer, $keywords ) {
61
+ /**
62
+ * Pattern to get all scripts
63
+ *
64
+ * @version 2.0.4
65
+ * @since 1.2.0
66
+ */
67
+ $pattern = "/<script[\s\S]*?>[\s\S]*?<\/script>/i";
68
+
69
+ /**
70
+ * Get all scripts and add cookieconsent if it does match with the criterion
71
+ */
72
+ $updated_scripts = preg_replace_callback( $pattern, function ( $matches ) use ( $keywords ) {
73
+ /**
74
+ * Matched script data
75
+ */
76
+ $data = ( isset( $matches[0] ) ) ? $matches[0] : '';
77
+
78
+ /**
79
+ * Check if the script contains the keywords, checks keywords one by one
80
+ *
81
+ * If one match, then the rest of the keywords will be skipped.
82
+ **/
83
+ foreach ( $keywords as $needle => $cookie_type ) {
84
+ /**
85
+ * The script contains the needle
86
+ **/
87
+ if ( strpos( $data, $needle ) !== false ) {
88
+ $data = preg_replace( '/\<script/', '<script type="text/plain" data-cookieconsent="' . cookiebot_addons_output_cookie_types( $cookie_type ) . '"', $data );
89
+ $data = preg_replace( '/type\=\"text\/javascript\"/', '', $data );
90
+
91
+ /**
92
+ * matched already so we can skip other keywords
93
+ **/
94
+ continue;
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Return updated script data
100
+ */
101
+ return $data;
102
+ }, $buffer );
103
+
104
+ /**
105
+ * Fallback when the regex fails to work due to PCRE_ERROR_JIT_STACKLIMIT
106
+ *
107
+ * @version 2.0.4
108
+ * @since 2.0.4
109
+ */
110
+ if ( $updated_scripts === null ) {
111
+ $updated_scripts = $buffer;
112
+
113
+ if ( get_option( 'cookiebot_regex_stacklimit' ) === false ) {
114
+ update_option( 'cookiebot_regex_stacklimit', 1 );
115
+ }
116
+ }
117
+
118
+ return $updated_scripts;
119
+ }
120
+
121
+ /**
122
+ * Compares array to string to add checked attribute in checkbox
123
+ *
124
+ * @param $helper
125
+ * @param $current
126
+ * @param bool $echo
127
+ * @param string $type
128
+ *
129
+ * @return string
130
+ *
131
+ * @since 1.3.0
132
+ */
133
+ function cookiebot_addons_checked_selected_helper( $helper, $current, $echo = true, $type = 'checked' ) {
134
+ if ( is_array( $helper ) && in_array( $current, $helper ) ) {
135
+ $result = " $type='$type'";
136
+ } elseif ( is_string( $helper ) && is_string( $current ) && $helper === $current ) {
137
+ $result = " $type='$type'";
138
+ } else {
139
+ $result = '';
140
+ }
141
+
142
+
143
+ if ( $echo ) {
144
+ echo $result;
145
+ }
146
+
147
+ return $result;
148
+ }
149
+
150
+ /**
151
+ * Returns cookie types in a string
152
+ * Default is statistics
153
+ *
154
+ * @param $cookie_types
155
+ *
156
+ * @return string
157
+ *
158
+ * @since 1.3.0
159
+ */
160
+ function cookiebot_addons_output_cookie_types( $cookie_types ) {
161
+ if ( is_array( $cookie_types ) && count( $cookie_types ) > 0 ) {
162
+ return implode( ', ', $cookie_types );
163
+ } elseif ( is_string( $cookie_types ) && $cookie_types != '' ) {
164
+ return $cookie_types;
165
+ }
166
+
167
+ return 'statistics';
168
+ }
169
+
170
+ /**
171
+ * Return 1 cookie type if more than 1 is selected
172
+ *
173
+ * @param $cookie_types
174
+ *
175
+ * @return string
176
+ *
177
+ * @since 1.3.0
178
+ */
179
+ function cookiebot_addons_get_one_cookie_type( $cookie_types ) {
180
+ if ( is_array( $cookie_types ) ) {
181
+ if ( in_array( 'marketing', $cookie_types ) ) {
182
+ return 'marketing';
183
+ } elseif ( in_array( 'statistics', $cookie_types ) ) {
184
+ return 'statistics';
185
+ } elseif ( in_array( 'preferences', $cookie_types ) ) {
186
+ return 'preferences';
187
+ }
188
+ }
189
+
190
+ return '';
191
+ }
192
+
193
+ /**
194
+ * Returns current site language
195
+ *
196
+ * @return mixed|string
197
+ *
198
+ * @since 1.9.0
199
+ */
200
+ function cookiebot_addons_get_language() {
201
+ $lang = get_locale(); //Gets language in en-US format
202
+
203
+ /**
204
+ * Add support for 3rd party plugins
205
+ */
206
+ $lang = apply_filters( 'cookiebot_addons_language', $lang );
207
+
208
+ return $lang;
209
+ }
210
+
211
+ /**
212
+ * Get supported languages by the cookiebot
213
+ *
214
+ * @return array
215
+ *
216
+ * @since 1.9.0
217
+ */
218
+ function cookiebot_addons_get_supported_languages() {
219
+ $cookiebot = cookiebot();
220
+
221
+ return $cookiebot->get_supported_languages();
222
+ }
223
+
224
+ /**
225
+ * Show languages in a select field
226
+ *
227
+ * @param $class
228
+ * @param $name
229
+ * @param $selected
230
+ *
231
+ * @return mixed
232
+ *
233
+ * @since 1.8.0
234
+ */
235
+ function cookiebot_addons_get_dropdown_languages( $class, $name, $selected ) {
236
+ $args = array(
237
+ 'name' => $name,
238
+ 'selected' => $selected,
239
+ 'show_option_site_default' => true,
240
+ 'echo' => false,
241
+ 'languages' => get_available_languages()
242
+ );
243
+ $dropdown = wp_dropdown_languages( $args );
244
+
245
+ $output = str_replace( 'select ', 'select class="' . $class . '" ', $dropdown );
246
+
247
+ $output = str_replace( 'value="" ', 'value="en_US" ', $output );
248
+
249
+ return $output;
250
+ }
251
+
252
+ /**
253
+ * Run actions when the cookiebot plugin is deactivated
254
+ *
255
+ * @since 2.2.0
256
+ */
257
+ function cookiebot_addons_plugin_deactivated( ) {
258
+ $cookiebot_addons = \cookiebot_addons\Cookiebot_Addons::instance();
259
+ $cookiebot_addons->cookiebot_deactivated();
260
+ }
addons/lib/ioc/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 ComposerAutoloaderInit3b7bc7f1dc820c2b29f44b9db898a0f8::getLoader();
addons/lib/ioc/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') && ini_get('apc.enabled') ? $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
+ foreach ($this->prefixDirsPsr4[$search] as $dir) {
383
+ $length = $this->prefixLengthsPsr4[$first][$search];
384
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
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/lib/ioc/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/lib/ioc/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/lib/ioc/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
+ 'bbf73f3db644d3dced353b837903e74c' => $vendorDir . '/php-di/php-di/src/DI/functions.php',
10
+ );
addons/lib/ioc/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/lib/ioc/composer/autoload_psr4.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ 'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
10
+ 'PhpDocReader\\' => array($vendorDir . '/php-di/phpdoc-reader/src/PhpDocReader'),
11
+ 'Invoker\\' => array($vendorDir . '/php-di/invoker/src'),
12
+ 'Interop\\Container\\' => array($vendorDir . '/container-interop/container-interop/src/Interop/Container'),
13
+ 'DI\\' => array($vendorDir . '/php-di/php-di/src/DI'),
14
+ );
addons/lib/ioc/composer/autoload_real.php ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_real.php @generated by Composer
4
+
5
+ class ComposerAutoloaderInit3b7bc7f1dc820c2b29f44b9db898a0f8
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
+ public static function getLoader()
17
+ {
18
+ if (null !== self::$loader) {
19
+ return self::$loader;
20
+ }
21
+
22
+ spl_autoload_register(array('ComposerAutoloaderInit3b7bc7f1dc820c2b29f44b9db898a0f8', 'loadClassLoader'), true, true);
23
+ self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInit3b7bc7f1dc820c2b29f44b9db898a0f8', 'loadClassLoader'));
25
+
26
+ $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
27
+ if ($useStaticLoader) {
28
+ require_once __DIR__ . '/autoload_static.php';
29
+
30
+ call_user_func(\Composer\Autoload\ComposerStaticInit3b7bc7f1dc820c2b29f44b9db898a0f8::getInitializer($loader));
31
+ } else {
32
+ $map = require __DIR__ . '/autoload_namespaces.php';
33
+ foreach ($map as $namespace => $path) {
34
+ $loader->set($namespace, $path);
35
+ }
36
+
37
+ $map = require __DIR__ . '/autoload_psr4.php';
38
+ foreach ($map as $namespace => $path) {
39
+ $loader->setPsr4($namespace, $path);
40
+ }
41
+
42
+ $classMap = require __DIR__ . '/autoload_classmap.php';
43
+ if ($classMap) {
44
+ $loader->addClassMap($classMap);
45
+ }
46
+ }
47
+
48
+ $loader->register(true);
49
+
50
+ if ($useStaticLoader) {
51
+ $includeFiles = Composer\Autoload\ComposerStaticInit3b7bc7f1dc820c2b29f44b9db898a0f8::$files;
52
+ } else {
53
+ $includeFiles = require __DIR__ . '/autoload_files.php';
54
+ }
55
+ foreach ($includeFiles as $fileIdentifier => $file) {
56
+ composerRequire3b7bc7f1dc820c2b29f44b9db898a0f8($fileIdentifier, $file);
57
+ }
58
+
59
+ return $loader;
60
+ }
61
+ }
62
+
63
+ function composerRequire3b7bc7f1dc820c2b29f44b9db898a0f8($fileIdentifier, $file)
64
+ {
65
+ if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
66
+ require $file;
67
+
68
+ $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
69
+ }
70
+ }
addons/lib/ioc/composer/autoload_static.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_static.php @generated by Composer
4
+
5
+ namespace Composer\Autoload;
6
+
7
+ class ComposerStaticInit3b7bc7f1dc820c2b29f44b9db898a0f8
8
+ {
9
+ public static $files = array (
10
+ 'bbf73f3db644d3dced353b837903e74c' => __DIR__ . '/..' . '/php-di/php-di/src/DI/functions.php',
11
+ );
12
+
13
+ public static $prefixLengthsPsr4 = array (
14
+ 'P' =>
15
+ array (
16
+ 'Psr\\Container\\' => 14,
17
+ 'PhpDocReader\\' => 13,
18
+ ),
19
+ 'I' =>
20
+ array (
21
+ 'Invoker\\' => 8,
22
+ 'Interop\\Container\\' => 18,
23
+ ),
24
+ 'D' =>
25
+ array (
26
+ 'DI\\' => 3,
27
+ ),
28
+ );
29
+
30
+ public static $prefixDirsPsr4 = array (
31
+ 'Psr\\Container\\' =>
32
+ array (
33
+ 0 => __DIR__ . '/..' . '/psr/container/src',
34
+ ),
35
+ 'PhpDocReader\\' =>
36
+ array (
37
+ 0 => __DIR__ . '/..' . '/php-di/phpdoc-reader/src/PhpDocReader',
38
+ ),
39
+ 'Invoker\\' =>
40
+ array (
41
+ 0 => __DIR__ . '/..' . '/php-di/invoker/src',
42
+ ),
43
+ 'Interop\\Container\\' =>
44
+ array (
45
+ 0 => __DIR__ . '/..' . '/container-interop/container-interop/src/Interop/Container',
46
+ ),
47
+ 'DI\\' =>
48
+ array (
49
+ 0 => __DIR__ . '/..' . '/php-di/php-di/src/DI',
50
+ ),
51
+ );
52
+
53
+ public static function getInitializer(ClassLoader $loader)
54
+ {
55
+ return \Closure::bind(function () use ($loader) {
56
+ $loader->prefixLengthsPsr4 = ComposerStaticInit3b7bc7f1dc820c2b29f44b9db898a0f8::$prefixLengthsPsr4;
57
+ $loader->prefixDirsPsr4 = ComposerStaticInit3b7bc7f1dc820c2b29f44b9db898a0f8::$prefixDirsPsr4;
58
+
59
+ }, null, ClassLoader::class);
60
+ }
61
+ }
addons/lib/ioc/composer/installed.json ADDED
@@ -0,0 +1,226 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "name": "php-di/phpdoc-reader",
4
+ "version": "2.1.0",
5
+ "version_normalized": "2.1.0.0",
6
+ "source": {
7
+ "type": "git",
8
+ "url": "https://github.com/PHP-DI/PhpDocReader.git",
9
+ "reference": "7d0de60b9341933c8afd172a6255cd7557601e0e"
10
+ },
11
+ "dist": {
12
+ "type": "zip",
13
+ "url": "https://api.github.com/repos/PHP-DI/PhpDocReader/zipball/7d0de60b9341933c8afd172a6255cd7557601e0e",
14
+ "reference": "7d0de60b9341933c8afd172a6255cd7557601e0e",
15
+ "shasum": ""
16
+ },
17
+ "require": {
18
+ "php": ">=5.4.0"
19
+ },
20
+ "require-dev": {
21
+ "phpunit/phpunit": "~4.6"
22
+ },
23
+ "time": "2018-02-18T17:39:01+00:00",
24
+ "type": "library",
25
+ "installation-source": "dist",
26
+ "autoload": {
27
+ "psr-4": {
28
+ "PhpDocReader\\": "src/PhpDocReader"
29
+ }
30
+ },
31
+ "notification-url": "https://packagist.org/downloads/",
32
+ "license": [
33
+ "MIT"
34
+ ],
35
+ "description": "PhpDocReader parses @var and @param values in PHP docblocks (supports namespaced class names with the same resolution rules as PHP)",
36
+ "keywords": [
37
+ "phpdoc",
38
+ "reflection"
39
+ ]
40
+ },
41
+ {
42
+ "name": "psr/container",
43
+ "version": "1.0.0",
44
+ "version_normalized": "1.0.0.0",
45
+ "source": {
46
+ "type": "git",
47
+ "url": "https://github.com/php-fig/container.git",
48
+ "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f"
49
+ },
50
+ "dist": {
51
+ "type": "zip",
52
+ "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
53
+ "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
54
+ "shasum": ""
55
+ },
56
+ "require": {
57
+ "php": ">=5.3.0"
58
+ },
59
+ "time": "2017-02-14T16:28:37+00:00",
60
+ "type": "library",
61
+ "extra": {
62
+ "branch-alias": {
63
+ "dev-master": "1.0.x-dev"
64
+ }
65
+ },
66
+ "installation-source": "dist",
67
+ "autoload": {
68
+ "psr-4": {
69
+ "Psr\\Container\\": "src/"
70
+ }
71
+ },
72
+ "notification-url": "https://packagist.org/downloads/",
73
+ "license": [
74
+ "MIT"
75
+ ],
76
+ "authors": [
77
+ {
78
+ "name": "PHP-FIG",
79
+ "homepage": "http://www.php-fig.org/"
80
+ }
81
+ ],
82
+ "description": "Common Container Interface (PHP FIG PSR-11)",
83
+ "homepage": "https://github.com/php-fig/container",
84
+ "keywords": [
85
+ "PSR-11",
86
+ "container",
87
+ "container-interface",
88
+ "container-interop",
89
+ "psr"
90
+ ]
91
+ },
92
+ {
93
+ "name": "container-interop/container-interop",
94
+ "version": "1.2.0",
95
+ "version_normalized": "1.2.0.0",
96
+ "source": {
97
+ "type": "git",
98
+ "url": "https://github.com/container-interop/container-interop.git",
99
+ "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8"
100
+ },
101
+ "dist": {
102
+ "type": "zip",
103
+ "url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8",
104
+ "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8",
105
+ "shasum": ""
106
+ },
107
+ "require": {
108
+ "psr/container": "^1.0"
109
+ },
110
+ "time": "2017-02-14T19:40:03+00:00",
111
+ "type": "library",
112
+ "installation-source": "dist",
113
+ "autoload": {
114
+ "psr-4": {
115
+ "Interop\\Container\\": "src/Interop/Container/"
116
+ }
117
+ },
118
+ "notification-url": "https://packagist.org/downloads/",
119
+ "license": [
120
+ "MIT"
121
+ ],
122
+ "description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
123
+ "homepage": "https://github.com/container-interop/container-interop"
124
+ },
125
+ {
126
+ "name": "php-di/invoker",
127
+ "version": "1.3.3",
128
+ "version_normalized": "1.3.3.0",
129
+ "source": {
130
+ "type": "git",
131
+ "url": "https://github.com/PHP-DI/Invoker.git",
132
+ "reference": "1f4ca63b9abc66109e53b255e465d0ddb5c2e3f7"
133
+ },
134
+ "dist": {
135
+ "type": "zip",
136
+ "url": "https://api.github.com/repos/PHP-DI/Invoker/zipball/1f4ca63b9abc66109e53b255e465d0ddb5c2e3f7",
137
+ "reference": "1f4ca63b9abc66109e53b255e465d0ddb5c2e3f7",
138
+ "shasum": ""
139
+ },
140
+ "require": {
141
+ "container-interop/container-interop": "~1.1"
142
+ },
143
+ "require-dev": {
144
+ "athletic/athletic": "~0.1.8",
145
+ "phpunit/phpunit": "~4.5"
146
+ },
147
+ "time": "2016-07-14T13:09:58+00:00",
148
+ "type": "library",
149
+ "installation-source": "dist",
150
+ "autoload": {
151
+ "psr-4": {
152
+ "Invoker\\": "src/"
153
+ }
154
+ },
155
+ "notification-url": "https://packagist.org/downloads/",
156
+ "license": [
157
+ "MIT"
158
+ ],
159
+ "description": "Generic and extensible callable invoker",
160
+ "homepage": "https://github.com/PHP-DI/Invoker",
161
+ "keywords": [
162
+ "callable",
163
+ "dependency",
164
+ "dependency-injection",
165
+ "injection",
166
+ "invoke",
167
+ "invoker"
168
+ ]
169
+ },
170
+ {
171
+ "name": "php-di/php-di",
172
+ "version": "5.0.0",
173
+ "version_normalized": "5.0.0.0",
174
+ "source": {
175
+ "type": "git",
176
+ "url": "https://github.com/PHP-DI/PHP-DI.git",
177
+ "reference": "c3bbc0d334b888ec8baa75f95b4900ee17b18fa7"
178
+ },
179
+ "dist": {
180
+ "type": "zip",
181
+ "url": "https://api.github.com/repos/PHP-DI/PHP-DI/zipball/c3bbc0d334b888ec8baa75f95b4900ee17b18fa7",
182
+ "reference": "c3bbc0d334b888ec8baa75f95b4900ee17b18fa7",
183
+ "shasum": ""
184
+ },
185
+ "require": {
186
+ "container-interop/container-interop": "~1.0",
187
+ "php": ">=5.4.0",
188
+ "php-di/invoker": "~1.0",
189
+ "php-di/phpdoc-reader": "~2.0"
190
+ },
191
+ "require-dev": {
192
+ "doctrine/annotations": "~1.2",
193
+ "doctrine/cache": "~1.0",
194
+ "mnapoli/phpunit-easymock": "~0.1.4",
195
+ "ocramius/proxy-manager": "~1.0",
196
+ "phpunit/phpunit": "~4.5"
197
+ },
198
+ "suggest": {
199
+ "doctrine/annotations": "Install it if you want to use annotations (version ~1.2)",
200
+ "doctrine/cache": "Install it if you want to use the cache (version ~1.0)",
201
+ "ocramius/proxy-manager": "Install it if you want to use lazy injection (version ~1.0)"
202
+ },
203
+ "time": "2015-06-10T06:16:52+00:00",
204
+ "type": "library",
205
+ "installation-source": "dist",
206
+ "autoload": {
207
+ "psr-4": {
208
+ "DI\\": "src/DI/"
209
+ },
210
+ "files": [
211
+ "src/DI/functions.php"
212
+ ]
213
+ },
214
+ "notification-url": "https://packagist.org/downloads/",
215
+ "license": [
216
+ "MIT"
217
+ ],
218
+ "description": "The dependency injection container for humans",
219
+ "homepage": "http://php-di.org/",
220
+ "keywords": [
221
+ "container",
222
+ "dependency injection",
223
+ "di"
224
+ ]
225
+ }
226
+ ]
addons/lib/ioc/container-interop/container-interop/.gitignore ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ composer.lock
2
+ composer.phar
3
+ /vendor/
addons/lib/ioc/container-interop/container-interop/LICENSE ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 container-interop
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
addons/lib/ioc/container-interop/container-interop/README.md ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Container Interoperability
2
+
3
+ [![Latest Stable Version](https://poser.pugx.org/container-interop/container-interop/v/stable.png)](https://packagist.org/packages/container-interop/container-interop)
4
+ [![Total Downloads](https://poser.pugx.org/container-interop/container-interop/downloads.svg)](https://packagist.org/packages/container-interop/container-interop)
5
+
6
+ ## Deprecation warning!
7
+
8
+ Starting Feb. 13th 2017, container-interop is officially deprecated in favor of [PSR-11](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-11-container.md).
9
+ Container-interop has been the test-bed of PSR-11. From v1.2, container-interop directly extends PSR-11 interfaces.
10
+ Therefore, all containers implementing container-interop are now *de-facto* compatible with PSR-11.
11
+
12
+ - Projects implementing container-interop interfaces are encouraged to directly implement PSR-11 interfaces instead.
13
+ - Projects consuming container-interop interfaces are very strongly encouraged to directly type-hint on PSR-11 interfaces, in order to be compatible with PSR-11 containers that are not compatible with container-interop.
14
+
15
+ Regarding the delegate lookup feature, that is present in container-interop and not in PSR-11, the feature is actually a design pattern. It is therefore not deprecated. Documentation regarding this design pattern will be migrated from this repository into a separate website in the future.
16
+
17
+ ## About
18
+
19
+ *container-interop* tries to identify and standardize features in *container* objects (service locators,
20
+ dependency injection containers, etc.) to achieve interoperability.
21
+
22
+ Through discussions and trials, we try to create a standard, made of common interfaces but also recommendations.
23
+
24
+ If PHP projects that provide container implementations begin to adopt these common standards, then PHP
25
+ applications and projects that use containers can depend on the common interfaces instead of specific
26
+ implementations. This facilitates a high-level of interoperability and flexibility that allows users to consume
27
+ *any* container implementation that can be adapted to these interfaces.
28
+
29
+ The work done in this project is not officially endorsed by the [PHP-FIG](http://www.php-fig.org/), but it is being
30
+ worked on by members of PHP-FIG and other good developers. We adhere to the spirit and ideals of PHP-FIG, and hope
31
+ this project will pave the way for one or more future PSRs.
32
+
33
+
34
+ ## Installation
35
+
36
+ You can install this package through Composer:
37
+
38
+ ```json
39
+ composer require container-interop/container-interop
40
+ ```
41
+
42
+ The packages adheres to the [SemVer](http://semver.org/) specification, and there will be full backward compatibility
43
+ between minor versions.
44
+
45
+ ## Standards
46
+
47
+ ### Available
48
+
49
+ - [`ContainerInterface`](src/Interop/Container/ContainerInterface.php).
50
+ [Description](docs/ContainerInterface.md) [Meta Document](docs/ContainerInterface-meta.md).
51
+ Describes the interface of a container that exposes methods to read its entries.
52
+ - [*Delegate lookup feature*](docs/Delegate-lookup.md).
53
+ [Meta Document](docs/Delegate-lookup-meta.md).
54
+ Describes the ability for a container to delegate the lookup of its dependencies to a third-party container. This
55
+ feature lets several containers work together in a single application.
56
+
57
+ ### Proposed
58
+
59
+ View open [request for comments](https://github.com/container-interop/container-interop/labels/RFC)
60
+
61
+ ## Compatible projects
62
+
63
+ ### Projects implementing `ContainerInterface`
64
+
65
+ - [Acclimate](https://github.com/jeremeamia/acclimate-container): Adapters for
66
+ Aura.Di, Laravel, Nette DI, Pimple, Symfony DI, ZF2 Service manager, ZF2
67
+ Dependency injection and any container using `ArrayAccess`
68
+ - [Aura.Di](https://github.com/auraphp/Aura.Di)
69
+ - [auryn-container-interop](https://github.com/elazar/auryn-container-interop)
70
+ - [Burlap](https://github.com/codeeverything/burlap)
71
+ - [Chernozem](https://github.com/pyrsmk/Chernozem)
72
+ - [Data Manager](https://github.com/chrismichaels84/data-manager)
73
+ - [Disco](https://github.com/bitexpert/disco)
74
+ - [InDI](https://github.com/idealogica/indi)
75
+ - [League/Container](http://container.thephpleague.com/)
76
+ - [Mouf](http://mouf-php.com)
77
+ - [Njasm Container](https://github.com/njasm/container)
78
+ - [PHP-DI](http://php-di.org)
79
+ - [Picotainer](https://github.com/thecodingmachine/picotainer)
80
+ - [PimpleInterop](https://github.com/moufmouf/pimple-interop)
81
+ - [Pimple3-ContainerInterop](https://github.com/Sam-Burns/pimple3-containerinterop) (using Pimple v3)
82
+ - [SitePoint Container](https://github.com/sitepoint/Container)
83
+ - [Thruster Container](https://github.com/ThrusterIO/container) (PHP7 only)
84
+ - [Ultra-Lite Container](https://github.com/ultra-lite/container)
85
+ - [Unbox](https://github.com/mindplay-dk/unbox)
86
+ - [XStatic](https://github.com/jeremeamia/xstatic)
87
+ - [Zend\ServiceManager](https://github.com/zendframework/zend-servicemanager)
88
+ - [Zit](https://github.com/inxilpro/Zit)
89
+
90
+ ### Projects implementing the *delegate lookup* feature
91
+
92
+ - [Aura.Di](https://github.com/auraphp/Aura.Di)
93
+ - [Burlap](https://github.com/codeeverything/burlap)
94
+ - [Chernozem](https://github.com/pyrsmk/Chernozem)
95
+ - [InDI](https://github.com/idealogica/indi)
96
+ - [League/Container](http://container.thephpleague.com/)
97
+ - [Mouf](http://mouf-php.com)
98
+ - [Picotainer](https://github.com/thecodingmachine/picotainer)
99
+ - [PHP-DI](http://php-di.org)
100
+ - [PimpleInterop](https://github.com/moufmouf/pimple-interop)
101
+ - [Ultra-Lite Container](https://github.com/ultra-lite/container)
102
+
103
+ ### Middlewares implementing `ContainerInterface`
104
+
105
+ - [Alias-Container](https://github.com/thecodingmachine/alias-container): add
106
+ aliases support to any container
107
+ - [Prefixer-Container](https://github.com/thecodingmachine/prefixer-container):
108
+ dynamically prefix identifiers
109
+ - [Lazy-Container](https://github.com/snapshotpl/lazy-container): lazy services
110
+
111
+ ### Projects using `ContainerInterface`
112
+
113
+ The list below contains only a sample of all the projects consuming `ContainerInterface`. For a more complete list have a look [here](http://packanalyst.com/class?q=Interop%5CContainer%5CContainerInterface).
114
+
115
+ | | Downloads |
116
+ | --- | --- |
117
+ | [Adroit](https://github.com/bitexpert/adroit) | ![](https://img.shields.io/packagist/dt/bitexpert/adroit.svg) |
118
+ | [Behat](https://github.com/Behat/Behat/pull/974) | ![](https://img.shields.io/packagist/dt/behat/behat.svg) |
119
+ | [blast-facades](https://github.com/phpthinktank/blast-facades): Minimize complexity and represent dependencies as facades. | ![](https://img.shields.io/packagist/dt/blast/facades.svg) |
120
+ | [interop.silex.di](https://github.com/thecodingmachine/interop.silex.di): an extension to [Silex](http://silex.sensiolabs.org/) that adds support for any *container-interop* compatible container | ![](https://img.shields.io/packagist/dt/mouf/interop.silex.di.svg) |
121
+ | [mindplay/walkway](https://github.com/mindplay-dk/walkway): a modular request router | ![](https://img.shields.io/packagist/dt/mindplay/walkway.svg) |
122
+ | [mindplay/middleman](https://github.com/mindplay-dk/middleman): minimalist PSR-7 middleware dispatcher | ![](https://img.shields.io/packagist/dt/mindplay/middleman.svg) |
123
+ | [PHP-DI/Invoker](https://github.com/PHP-DI/Invoker): extensible and configurable invoker/dispatcher | ![](https://img.shields.io/packagist/dt/php-di/invoker.svg) |
124
+ | [Prophiler](https://github.com/fabfuel/prophiler) | ![](https://img.shields.io/packagist/dt/fabfuel/prophiler.svg) |
125
+ | [Silly](https://github.com/mnapoli/silly): CLI micro-framework | ![](https://img.shields.io/packagist/dt/mnapoli/silly.svg) |
126
+ | [Slim v3](https://github.com/slimphp/Slim) | ![](https://img.shields.io/packagist/dt/slim/slim.svg) |
127
+ | [Splash](http://mouf-php.com/packages/mouf/mvc.splash-common/version/8.0-dev/README.md) | ![](https://img.shields.io/packagist/dt/mouf/mvc.splash-common.svg) |
128
+ | [Woohoo Labs. Harmony](https://github.com/woohoolabs/harmony): a flexible micro-framework | ![](https://img.shields.io/packagist/dt/woohoolabs/harmony.svg) |
129
+ | [zend-expressive](https://github.com/zendframework/zend-expressive) | ![](https://img.shields.io/packagist/dt/zendframework/zend-expressive.svg) |
130
+
131
+
132
+ ## Workflow
133
+
134
+ Everyone is welcome to join and contribute.
135
+
136
+ The general workflow looks like this:
137
+
138
+ 1. Someone opens a discussion (GitHub issue) to suggest an interface
139
+ 1. Feedback is gathered
140
+ 1. The interface is added to a development branch
141
+ 1. We release alpha versions so that the interface can be experimented with
142
+ 1. Discussions and edits ensue until the interface is deemed stable by a general consensus
143
+ 1. A new minor version of the package is released
144
+
145
+ We try to not break BC by creating new interfaces instead of editing existing ones.
146
+
147
+ While we currently work on interfaces, we are open to anything that might help towards interoperability, may that
148
+ be code, best practices, etc.
addons/lib/ioc/container-interop/container-interop/composer.json ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "container-interop/container-interop",
3
+ "type": "library",
4
+ "description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
5
+ "homepage": "https://github.com/container-interop/container-interop",
6
+ "license": "MIT",
7
+ "autoload": {
8
+ "psr-4": {
9
+ "Interop\\Container\\": "src/Interop/Container/"
10
+ }
11
+ },
12
+ "require": {
13
+ "psr/container": "^1.0"
14
+ }
15
+ }
addons/lib/ioc/container-interop/container-interop/docs/ContainerInterface-meta.md ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ContainerInterface Meta Document
2
+
3
+ ## Introduction
4
+
5
+ This document describes the process and discussions that lead to the `ContainerInterface`.
6
+ Its goal is to explain the reasons behind each decision.
7
+
8
+ ## Goal
9
+
10
+ The goal set by `ContainerInterface` is to standardize how frameworks and libraries make use of a
11
+ container to obtain objects and parameters.
12
+
13
+ By standardizing such a behavior, frameworks and libraries using the `ContainerInterface`
14
+ could work with any compatible container.
15
+ That would allow end users to choose their own container based on their own preferences.
16
+
17
+ It is important to distinguish the two usages of a container:
18
+
19
+ - configuring entries
20
+ - fetching entries
21
+
22
+ Most of the time, those two sides are not used by the same party.
23
+ While it is often end users who tend to configure entries, it is generally the framework that fetch
24
+ entries to build the application.
25
+
26
+ This is why this interface focuses only on how entries can be fetched from a container.
27
+
28
+ ## Interface name
29
+
30
+ The interface name has been thoroughly discussed and was decided by a vote.
31
+
32
+ The list of options considered with their respective votes are:
33
+
34
+ - `ContainerInterface`: +8
35
+ - `ProviderInterface`: +2
36
+ - `LocatorInterface`: 0
37
+ - `ReadableContainerInterface`: -5
38
+ - `ServiceLocatorInterface`: -6
39
+ - `ObjectFactory`: -6
40
+ - `ObjectStore`: -8
41
+ - `ConsumerInterface`: -9
42
+
43
+ [Full results of the vote](https://github.com/container-interop/container-interop/wiki/%231-interface-name:-Vote)
44
+
45
+ The complete discussion can be read in [the issue #1](https://github.com/container-interop/container-interop/issues/1).
46
+
47
+ ## Interface methods
48
+
49
+ The choice of which methods the interface would contain was made after a statistical analysis of existing containers.
50
+ The results of this analysis are available [in this document](https://gist.github.com/mnapoli/6159681).
51
+
52
+ The summary of the analysis showed that:
53
+
54
+ - all containers offer a method to get an entry by its id
55
+ - a large majority name such method `get()`
56
+ - for all containers, the `get()` method has 1 mandatory parameter of type string
57
+ - some containers have an optional additional argument for `get()`, but it doesn't have the same purpose between containers
58
+ - a large majority of the containers offer a method to test if it can return an entry by its id
59
+ - a majority name such method `has()`
60
+ - for all containers offering `has()`, the method has exactly 1 parameter of type string
61
+ - a large majority of the containers throw an exception rather than returning null when an entry is not found in `get()`
62
+ - a large majority of the containers don't implement `ArrayAccess`
63
+
64
+ The question of whether to include methods to define entries has been discussed in
65
+ [issue #1](https://github.com/container-interop/container-interop/issues/1).
66
+ It has been judged that such methods do not belong in the interface described here because it is out of its scope
67
+ (see the "Goal" section).
68
+
69
+ As a result, the `ContainerInterface` contains two methods:
70
+
71
+ - `get()`, returning anything, with one mandatory string parameter. Should throw an exception if the entry is not found.
72
+ - `has()`, returning a boolean, with one mandatory string parameter.
73
+
74
+ ### Number of parameters in `get()` method
75
+
76
+ While `ContainerInterface` only defines one mandatory parameter in `get()`, it is not incompatible with
77
+ existing containers that have additional optional parameters. PHP allows an implementation to offer more parameters
78
+ as long as they are optional, because the implementation *does* satisfy the interface.
79
+
80
+ This issue has been discussed in [issue #6](https://github.com/container-interop/container-interop/issues/6).
81
+
82
+ ### Type of the `$id` parameter
83
+
84
+ The type of the `$id` parameter in `get()` and `has()` has been discussed in
85
+ [issue #6](https://github.com/container-interop/container-interop/issues/6).
86
+ While `string` is used in all the containers that were analyzed, it was suggested that allowing
87
+ anything (such as objects) could allow containers to offer a more advanced query API.
88
+
89
+ An example given was to use the container as an object builder. The `$id` parameter would then be an
90
+ object that would describe how to create an instance.
91
+
92
+ The conclusion of the discussion was that this was beyond the scope of getting entries from a container without
93
+ knowing how the container provided them, and it was more fit for a factory.
94
+
95
+ ## Contributors
96
+
97
+ Are listed here all people that contributed in the discussions or votes, by alphabetical order:
98
+
99
+ - [Amy Stephen](https://github.com/AmyStephen)
100
+ - [David Négrier](https://github.com/moufmouf)
101
+ - [Don Gilbert](https://github.com/dongilbert)
102
+ - [Jason Judge](https://github.com/judgej)
103
+ - [Jeremy Lindblom](https://github.com/jeremeamia)
104
+ - [Marco Pivetta](https://github.com/Ocramius)
105
+ - [Matthieu Napoli](https://github.com/mnapoli)
106
+ - [Paul M. Jones](https://github.com/pmjones)
107
+ - [Stephan Hochdörfer](https://github.com/shochdoerfer)
108
+ - [Taylor Otwell](https://github.com/taylorotwell)
109
+
110
+ ## Relevant links
111
+
112
+ - [`ContainerInterface.php`](https://github.com/container-interop/container-interop/blob/master/src/Interop/Container/ContainerInterface.php)
113
+ - [List of all issues](https://github.com/container-interop/container-interop/issues?labels=ContainerInterface&milestone=&page=1&state=closed)
114
+ - [Vote for the interface name](https://github.com/container-interop/container-interop/wiki/%231-interface-name:-Vote)
addons/lib/ioc/container-interop/container-interop/docs/ContainerInterface.md ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Container interface
2
+ ===================
3
+
4
+ This document describes a common interface for dependency injection containers.
5
+
6
+ The goal set by `ContainerInterface` is to standardize how frameworks and libraries make use of a
7
+ container to obtain objects and parameters (called *entries* in the rest of this document).
8
+
9
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
10
+ "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
11
+ interpreted as described in [RFC 2119][].
12
+
13
+ The word `implementor` in this document is to be interpreted as someone
14
+ implementing the `ContainerInterface` in a dependency injection-related library or framework.
15
+ Users of dependency injections containers (DIC) are referred to as `user`.
16
+
17
+ [RFC 2119]: http://tools.ietf.org/html/rfc2119
18
+
19
+ 1. Specification
20
+ -----------------
21
+
22
+ ### 1.1 Basics
23
+
24
+ - The `Interop\Container\ContainerInterface` exposes two methods : `get` and `has`.
25
+
26
+ - `get` takes one mandatory parameter: an entry identifier. It MUST be a string.
27
+ A call to `get` can return anything (a *mixed* value), or throws an exception if the identifier
28
+ is not known to the container. Two successive calls to `get` with the same
29
+ identifier SHOULD return the same value. However, depending on the `implementor`
30
+ design and/or `user` configuration, different values might be returned, so
31
+ `user` SHOULD NOT rely on getting the same value on 2 successive calls.
32
+ While `ContainerInterface` only defines one mandatory parameter in `get()`, implementations
33
+ MAY accept additional optional parameters.
34
+
35
+ - `has` takes one unique parameter: an entry identifier. It MUST return `true`
36
+ if an entry identifier is known to the container and `false` if it is not.
37
+ `has($id)` returning true does not mean that `get($id)` will not throw an exception.
38
+ It does however mean that `get($id)` will not throw a `NotFoundException`.
39
+
40
+ ### 1.2 Exceptions
41
+
42
+ Exceptions directly thrown by the container MUST implement the
43
+ [`Interop\Container\Exception\ContainerException`](../src/Interop/Container/Exception/ContainerException.php).
44
+
45
+ A call to the `get` method with a non-existing id SHOULD throw a
46
+ [`Interop\Container\Exception\NotFoundException`](../src/Interop/Container/Exception/NotFoundException.php).
47
+
48
+ ### 1.3 Additional features
49
+
50
+ This section describes additional features that MAY be added to a container. Containers are not
51
+ required to implement these features to respect the ContainerInterface.
52
+
53
+ #### 1.3.1 Delegate lookup feature
54
+
55
+ The goal of the *delegate lookup* feature is to allow several containers to share entries.
56
+ Containers implementing this feature can perform dependency lookups in other containers.
57
+
58
+ Containers implementing this feature will offer a greater lever of interoperability
59
+ with other containers. Implementation of this feature is therefore RECOMMENDED.
60
+
61
+ A container implementing this feature:
62
+
63
+ - MUST implement the `ContainerInterface`
64
+ - MUST provide a way to register a delegate container (using a constructor parameter, or a setter,
65
+ or any possible way). The delegate container MUST implement the `ContainerInterface`.
66
+
67
+ When a container is configured to use a delegate container for dependencies:
68
+
69
+ - Calls to the `get` method should only return an entry if the entry is part of the container.
70
+ If the entry is not part of the container, an exception should be thrown
71
+ (as requested by the `ContainerInterface`).
72
+ - Calls to the `has` method should only return `true` if the entry is part of the container.
73
+ If the entry is not part of the container, `false` should be returned.
74
+ - If the fetched entry has dependencies, **instead** of performing
75
+ the dependency lookup in the container, the lookup is performed on the *delegate container*.
76
+
77
+ Important! By default, the lookup SHOULD be performed on the delegate container **only**, not on the container itself.
78
+
79
+ It is however allowed for containers to provide exception cases for special entries, and a way to lookup
80
+ into the same container (or another container) instead of the delegate container.
81
+
82
+ 2. Package
83
+ ----------
84
+
85
+ The interfaces and classes described as well as relevant exception are provided as part of the
86
+ [container-interop/container-interop](https://packagist.org/packages/container-interop/container-interop) package.
87
+
88
+ 3. `Interop\Container\ContainerInterface`
89
+ -----------------------------------------
90
+
91
+ ```php
92
+ <?php
93
+ namespace Interop\Container;
94
+
95
+ use Interop\Container\Exception\ContainerException;
96
+ use Interop\Container\Exception\NotFoundException;
97
+
98
+ /**
99
+ * Describes the interface of a container that exposes methods to read its entries.
100
+ */
101
+ interface ContainerInterface
102
+ {
103
+ /**
104
+ * Finds an entry of the container by its identifier and returns it.
105
+ *
106
+ * @param string $id Identifier of the entry to look for.
107
+ *
108
+ * @throws NotFoundException No entry was found for this identifier.
109
+ * @throws ContainerException Error while retrieving the entry.
110
+ *
111
+ * @return mixed Entry.
112
+ */
113
+ public function get($id);
114
+
115
+ /**
116
+ * Returns true if the container can return an entry for the given identifier.
117
+ * Returns false otherwise.
118
+ *
119
+ * `has($id)` returning true does not mean that `get($id)` will not throw an exception.
120
+ * It does however mean that `get($id)` will not throw a `NotFoundException`.
121
+ *
122
+ * @param string $id Identifier of the entry to look for.
123
+ *
124
+ * @return boolean
125
+ */
126
+ public function has($id);
127
+ }
128
+ ```
129
+
130
+ 4. `Interop\Container\Exception\ContainerException`
131
+ ---------------------------------------------------
132
+
133
+ ```php
134
+ <?php
135
+ namespace Interop\Container\Exception;
136
+
137
+ /**
138
+ * Base interface representing a generic exception in a container.
139
+ */
140
+ interface ContainerException
141
+ {
142
+ }
143
+ ```
144
+
145
+ 5. `Interop\Container\Exception\NotFoundException`
146
+ ---------------------------------------------------
147
+
148
+ ```php
149
+ <?php
150
+ namespace Interop\Container\Exception;
151
+
152
+ /**
153
+ * No entry was found in the container.
154
+ */
155
+ interface NotFoundException extends ContainerException
156
+ {
157
+ }
158
+ ```
addons/lib/ioc/container-interop/container-interop/docs/Delegate-lookup-meta.md ADDED
@@ -0,0 +1,259 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Delegate lookup feature Meta Document
2
+ =====================================
3
+
4
+ 1. Summary
5
+ ----------
6
+
7
+ This document describes the *delegate lookup feature*.
8
+ Containers are not required to implement this feature to respect the `ContainerInterface`.
9
+ However, containers implementing this feature will offer a greater lever of interoperability
10
+ with other containers, allowing multiple containers to share entries in the same application.
11
+ Implementation of this feature is therefore recommanded.
12
+
13
+ 2. Why Bother?
14
+ --------------
15
+
16
+ The [`ContainerInterface`](../src/Interop/Container/ContainerInterface.php) ([meta doc](ContainerInterface.md))
17
+ standardizes how frameworks and libraries make use of a container to obtain objects and parameters.
18
+
19
+ By standardizing such a behavior, frameworks and libraries relying on the `ContainerInterface`
20
+ could work with any compatible container.
21
+ That would allow end users to choose their own container based on their own preferences.
22
+
23
+ The `ContainerInterface` is also enough if we want to have several containers side-by-side in the same
24
+ application. For instance, this is what the [CompositeContainer](https://github.com/jeremeamia/acclimate-container/blob/master/src/CompositeContainer.php)
25
+ class of [Acclimate](https://github.com/jeremeamia/acclimate-container) is designed for:
26
+
27
+ ![Side by side containers](images/side_by_side_containers.png)
28
+
29
+ However, an instance in container 1 cannot reference an instance in container 2.
30
+
31
+ It would be better if an instance of container 1 could reference an instance in container 2,
32
+ and the opposite should be true.
33
+
34
+ ![Interoperating containers](images/interoperating_containers.png)
35
+
36
+ In the sample above, entry 1 in container 1 is referencing entry 3 in container 2.
37
+
38
+ 3. Scope
39
+ --------
40
+
41
+ ### 3.1 Goals
42
+
43
+ The goal of the *delegate lookup* feature is to allow several containers to share entries.
44
+
45
+ 4. Approaches
46
+ -------------
47
+
48
+ ### 4.1 Chosen Approach
49
+
50
+ Containers implementing this feature can perform dependency lookups in other containers.
51
+
52
+ A container implementing this feature:
53
+
54
+ - must implement the `ContainerInterface`
55
+ - must provide a way to register a *delegate container* (using a constructor parameter, or a setter, or any
56
+ possible way). The *delegate container* must implement the `ContainerInterface`.
57
+
58
+ When a *delegate container* is configured on a container:
59
+
60
+ - Calls to the `get` method should only return an entry if the entry is part of the container.
61
+ If the entry is not part of the container, an exception should be thrown (as required in the `ContainerInterface`).
62
+ - Calls to the `has` method should only return *true* if the entry is part of the container.
63
+ If the entry is not part of the container, *false* should be returned.
64
+ - Finally, the important part: if the entry we are fetching has dependencies,
65
+ **instead** of perfoming the dependency lookup in the container, the lookup is performed on the *delegate container*.
66
+
67
+ Important! By default, the lookup should be performed on the delegate container **only**, not on the container itself.
68
+
69
+ It is however allowed for containers to provide exception cases for special entries, and a way to lookup into
70
+ the same container (or another container) instead of the delegate container.
71
+
72
+ ### 4.2 Typical usage
73
+
74
+ The *delegate container* will usually be a composite container. A composite container is a container that
75
+ contains several other containers. When performing a lookup on a composite container, the inner containers are
76
+ queried until one container returns an entry.
77
+ An inner container implementing the *delegate lookup feature* will return entries it contains, but if these
78
+ entries have dependencies, the dependencies lookup calls will be performed on the composite container, giving
79
+ a chance to all containers to answer.
80
+
81
+ Interestingly enough, the order in which containers are added in the composite container matters. Indeed,
82
+ the first containers to be added in the composite container can "override" the entries of containers with
83
+ lower priority.
84
+
85
+ ![Containers priority](images/priority.png)
86
+
87
+ In the example above, "container 2" contains a controller "myController" and the controller is referencing an
88
+ "entityManager" entry. "Container 1" contains also an entry named "entityManager".
89
+ Without the *delegate lookup* feature, when requesting the "myController" instance to container 2, it would take
90
+ in charge the instanciation of both entries.
91
+
92
+ However, using the *delegate lookup* feature, here is what happens when we ask the composite container for the
93
+ "myController" instance:
94
+
95
+ - The composite container asks container 1 if if contains the "myController" instance. The answer is no.
96
+ - The composite container asks container 2 if if contains the "myController" instance. The answer is yes.
97
+ - The composite container performs a `get` call on container 2 for the "myController" instance.
98
+ - Container 2 sees that "myController" has a dependency on "entityManager".
99
+ - Container 2 delegates the lookup of "entityManager" to the composite container.
100
+ - The composite container asks container 1 if if contains the "entityManager" instance. The answer is yes.
101
+ - The composite container performs a `get` call on container 1 for the "entityManager" instance.
102
+
103
+ In the end, we get a controller instanciated by container 2 that references an entityManager instanciated
104
+ by container 1.
105
+
106
+ ### 4.3 Alternative: the fallback strategy
107
+
108
+ The first proposed approach we tried was to perform all the lookups in the "local" container,
109
+ and if a lookup fails in the container, to use the delegate container. In this scenario, the
110
+ delegate container is used in "fallback" mode.
111
+
112
+ This strategy has been described in @moufmouf blog post: http://mouf-php.com/container-interop-whats-next (solution 1).
113
+ It was also discussed [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-33570697) and
114
+ [here](https://github.com/container-interop/container-interop/pull/20#issuecomment-56599631).
115
+
116
+ Problems with this strategy:
117
+
118
+ - Heavy problem regarding infinite loops
119
+ - Unable to overload a container entry with the delegate container entry
120
+
121
+ ### 4.4 Alternative: force implementing an interface
122
+
123
+ The first proposed approach was to develop a `ParentAwareContainerInterface` interface.
124
+ It was proposed here: https://github.com/container-interop/container-interop/pull/8
125
+
126
+ The interface would have had the behaviour of the delegate lookup feature but would have forced the addition of
127
+ a `setParentContainter` method:
128
+
129
+ ```php
130
+ interface ParentAwareContainerInterface extends ReadableContainerInterface {
131
+ /**
132
+ * Sets the parent container associated to that container. This container will call
133
+ * the parent container to fetch dependencies.
134
+ *
135
+ * @param ContainerInterface $container
136
+ */
137
+ public function setParentContainer(ContainerInterface $container);
138
+ }
139
+ ```
140
+
141
+ The interface idea was first questioned by @Ocramius [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-51721777).
142
+ @Ocramius expressed the idea that an interface should not contain setters, otherwise, it is forcing implementation
143
+ details on the class implementing the interface.
144
+ Then @mnapoli made a proposal for a "convention" [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-51841079),
145
+ this idea was further discussed until all participants in the discussion agreed to remove the interface idea
146
+ and replace it with a "standard" feature.
147
+
148
+ **Pros:**
149
+
150
+ If we had had an interface, we could have delegated the registration of the delegate/composite container to the
151
+ the delegate/composite container itself.
152
+ For instance:
153
+
154
+ ```php
155
+ $containerA = new ContainerA();
156
+ $containerB = new ContainerB();
157
+
158
+ $compositeContainer = new CompositeContainer([$containerA, $containerB]);
159
+
160
+ // The call to 'setParentContainer' is delegated to the CompositeContainer
161
+ // It is not the responsibility of the user anymore.
162
+ class CompositeContainer {
163
+ ...
164
+
165
+ public function __construct($containers) {
166
+ foreach ($containers as $container) {
167
+ if ($container instanceof ParentAwareContainerInterface) {
168
+ $container->setParentContainer($this);
169
+ }
170
+ }
171
+ ...
172
+ }
173
+ }
174
+
175
+ ```
176
+
177
+ **Cons:**
178
+
179
+ Cons have been extensively discussed [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-51721777).
180
+ Basically, forcing a setter into an interface is a bad idea. Setters are similar to constructor arguments,
181
+ and it's a bad idea to standardize a constructor: how the delegate container is configured into a container is an implementation detail. This outweights the benefits of the interface.
182
+
183
+ ### 4.4 Alternative: no exception case for delegate lookups
184
+
185
+ Originally, the proposed wording for delegate lookup calls was:
186
+
187
+ > Important! The lookup MUST be performed on the delegate container **only**, not on the container itself.
188
+
189
+ This was later replaced by:
190
+
191
+ > Important! By default, the lookup SHOULD be performed on the delegate container **only**, not on the container itself.
192
+ >
193
+ > It is however allowed for containers to provide exception cases for special entries, and a way to lookup
194
+ > into the same container (or another container) instead of the delegate container.
195
+
196
+ Exception cases have been allowed to avoid breaking dependencies with some services that must be provided
197
+ by the container (on @njasm proposal). This was proposed here: https://github.com/container-interop/container-interop/pull/20#issuecomment-56597235
198
+
199
+ ### 4.5 Alternative: having one of the containers act as the composite container
200
+
201
+ In real-life scenarios, we usually have a big framework (Symfony 2, Zend Framework 2, etc...) and we want to
202
+ add another DI container to this container. Most of the time, the "big" framework will be responsible for
203
+ creating the controller's instances, using it's own DI container. Until *container-interop* is fully adopted,
204
+ the "big" framework will not be aware of the existence of a composite container that it should use instead
205
+ of its own container.
206
+
207
+ For this real-life use cases, @mnapoli and @moufmouf proposed to extend the "big" framework's DI container
208
+ to make it act as a composite container.
209
+
210
+ This has been discussed [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-40367194)
211
+ and [here](http://mouf-php.com/container-interop-whats-next#solution4).
212
+
213
+ This was implemented in Symfony 2 using:
214
+
215
+ - [interop.symfony.di](https://github.com/thecodingmachine/interop.symfony.di/tree/v0.1.0)
216
+ - [framework interop](https://github.com/mnapoli/framework-interop/)
217
+
218
+ This was implemented in Silex using:
219
+
220
+ - [interop.silex.di](https://github.com/thecodingmachine/interop.silex.di)
221
+
222
+ Having a container act as the composite container is not part of the delegate lookup standard because it is
223
+ simply a temporary design pattern used to make existing frameworks that do not support yet ContainerInterop
224
+ play nice with other DI containers.
225
+
226
+
227
+ 5. Implementations
228
+ ------------------
229
+
230
+ The following projects already implement the delegate lookup feature:
231
+
232
+ - [Mouf](http://mouf-php.com), through the [`setDelegateLookupContainer` method](https://github.com/thecodingmachine/mouf/blob/2.0/src/Mouf/MoufManager.php#L2120)
233
+ - [PHP-DI](http://php-di.org/), through the [`$wrapperContainer` parameter of the constructor](https://github.com/mnapoli/PHP-DI/blob/master/src/DI/Container.php#L72)
234
+ - [pimple-interop](https://github.com/moufmouf/pimple-interop), through the [`$container` parameter of the constructor](https://github.com/moufmouf/pimple-interop/blob/master/src/Interop/Container/Pimple/PimpleInterop.php#L62)
235
+
236
+ 6. People
237
+ ---------
238
+
239
+ Are listed here all people that contributed in the discussions, by alphabetical order:
240
+
241
+ - [Alexandru Pătrănescu](https://github.com/drealecs)
242
+ - [Ben Peachey](https://github.com/potherca)
243
+ - [David Négrier](https://github.com/moufmouf)
244
+ - [Jeremy Lindblom](https://github.com/jeremeamia)
245
+ - [Marco Pivetta](https://github.com/Ocramius)
246
+ - [Matthieu Napoli](https://github.com/mnapoli)
247
+ - [Nelson J Morais](https://github.com/njasm)
248
+ - [Phil Sturgeon](https://github.com/philsturgeon)
249
+ - [Stephan Hochdörfer](https://github.com/shochdoerfer)
250
+
251
+ 7. Relevant Links
252
+ -----------------
253
+
254
+ _**Note:** Order descending chronologically._
255
+
256
+ - [Pull request on the delegate lookup feature](https://github.com/container-interop/container-interop/pull/20)
257
+ - [Pull request on the interface idea](https://github.com/container-interop/container-interop/pull/8)
258
+ - [Original article exposing the delegate lookup idea along many others](http://mouf-php.com/container-interop-whats-next)
259
+
addons/lib/ioc/container-interop/container-interop/docs/Delegate-lookup.md ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Delegate lookup feature
2
+ =======================
3
+
4
+ This document describes a standard for dependency injection containers.
5
+
6
+ The goal set by the *delegate lookup* feature is to allow several containers to share entries.
7
+ Containers implementing this feature can perform dependency lookups in other containers.
8
+
9
+ Containers implementing this feature will offer a greater lever of interoperability
10
+ with other containers. Implementation of this feature is therefore RECOMMENDED.
11
+
12
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
13
+ "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
14
+ interpreted as described in [RFC 2119][].
15
+
16
+ The word `implementor` in this document is to be interpreted as someone
17
+ implementing the delegate lookup feature in a dependency injection-related library or framework.
18
+ Users of dependency injections containers (DIC) are referred to as `user`.
19
+
20
+ [RFC 2119]: http://tools.ietf.org/html/rfc2119
21
+
22
+ 1. Vocabulary
23
+ -------------
24
+
25
+ In a dependency injection container, the container is used to fetch entries.
26
+ Entries can have dependencies on other entries. Usually, these other entries are fetched by the container.
27
+
28
+ The *delegate lookup* feature is the ability for a container to fetch dependencies in
29
+ another container. In the rest of the document, the word "container" will reference the container
30
+ implemented by the implementor. The word "delegate container" will reference the container we are
31
+ fetching the dependencies from.
32
+
33
+ 2. Specification
34
+ ----------------
35
+
36
+ A container implementing the *delegate lookup* feature:
37
+
38
+ - MUST implement the [`ContainerInterface`](ContainerInterface.md)
39
+ - MUST provide a way to register a delegate container (using a constructor parameter, or a setter,
40
+ or any possible way). The delegate container MUST implement the [`ContainerInterface`](ContainerInterface.md).
41
+
42
+ When a container is configured to use a delegate container for dependencies:
43
+
44
+ - Calls to the `get` method should only return an entry if the entry is part of the container.
45
+ If the entry is not part of the container, an exception should be thrown
46
+ (as requested by the [`ContainerInterface`](ContainerInterface.md)).
47
+ - Calls to the `has` method should only return `true` if the entry is part of the container.
48
+ If the entry is not part of the container, `false` should be returned.
49
+ - If the fetched entry has dependencies, **instead** of performing
50
+ the dependency lookup in the container, the lookup is performed on the *delegate container*.
51
+
52
+ Important: By default, the dependency lookups SHOULD be performed on the delegate container **only**, not on the container itself.
53
+
54
+ It is however allowed for containers to provide exception cases for special entries, and a way to lookup
55
+ into the same container (or another container) instead of the delegate container.
56
+
57
+ 3. Package / Interface
58
+ ----------------------
59
+
60
+ This feature is not tied to any code, interface or package.
addons/lib/ioc/container-interop/container-interop/docs/images/interoperating_containers.png ADDED
Binary file
addons/lib/ioc/container-interop/container-interop/docs/images/priority.png ADDED
Binary file
addons/lib/ioc/container-interop/container-interop/docs/images/side_by_side_containers.png ADDED
Binary file
addons/lib/ioc/container-interop/container-interop/src/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 Interop\Container;
7
+
8
+ use 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/lib/ioc/container-interop/container-interop/src/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 Interop\Container\Exception;
7
+
8
+ use 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/lib/ioc/container-interop/container-interop/src/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 Interop\Container\Exception;
7
+
8
+ use 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/lib/ioc/php-di/invoker/CONTRIBUTING.md ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Contributing
2
+
3
+ First of all, **thank you** for contributing!
4
+
5
+ Here are a few rules to follow in order to ease code reviews and merging:
6
+
7
+ - follow [PSR-1](http://www.php-fig.org/psr/1/) and [PSR-2](http://www.php-fig.org/psr/2/)
8
+ - run the test suite
9
+ - write (or update) unit tests when applicable
10
+ - write documentation for new features
11
+ - use [commit messages that make sense](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)
12
+
13
+ One may ask you to [squash your commits](http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html) too. This is used to "clean" your pull request before merging it (we don't want commits such as `fix tests`, `fix 2`, `fix 3`, etc.).
14
+
15
+ When creating your pull request on GitHub, please write a description which gives the context and/or explains why you are creating it.
addons/lib/ioc/php-di/invoker/LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) Matthieu Napoli
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
addons/lib/ioc/php-di/invoker/README.md ADDED
@@ -0,0 +1,234 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Invoker
2
+
3
+ Generic and extensible callable invoker.
4
+
5
+ [![Build Status](https://img.shields.io/travis/PHP-DI/Invoker.svg?style=flat-square)](https://travis-ci.org/PHP-DI/Invoker)
6
+ [![Coverage Status](https://img.shields.io/coveralls/PHP-DI/Invoker/master.svg?style=flat-square)](https://coveralls.io/r/PHP-DI/Invoker?branch=master)
7
+ [![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/PHP-DI/Invoker.svg?style=flat-square)](https://scrutinizer-ci.com/g/PHP-DI/Invoker/?branch=master)
8
+ [![Latest Version](https://img.shields.io/github/release/PHP-DI/invoker.svg?style=flat-square)](https://packagist.org/packages/PHP-DI/invoker)
9
+
10
+ ## Why?
11
+
12
+ Who doesn't need an over-engineered `call_user_func()`?
13
+
14
+ ### Named parameters
15
+
16
+ Does this [Silex](http://silex.sensiolabs.org) example look familiar:
17
+
18
+ ```php
19
+ $app->get('/project/{project}/issue/{issue}', function ($project, $issue) {
20
+ // ...
21
+ });
22
+ ```
23
+
24
+ Or this command defined with [Silly](https://github.com/mnapoli/silly#usage):
25
+
26
+ ```php
27
+ $app->command('greet [name] [--yell]', function ($name, $yell) {
28
+ // ...
29
+ });
30
+ ```
31
+
32
+ Same pattern in [Slim](http://www.slimframework.com):
33
+
34
+ ```php
35
+ $app->get('/hello/:name', function ($name) {
36
+ // ...
37
+ });
38
+ ```
39
+
40
+ You get the point. These frameworks invoke the controller/command/handler using something akin to named parameters: whatever the order of the parameters, they are matched by their name.
41
+
42
+ **This library allows to invoke callables with named parameters in a generic and extensible way.**
43
+
44
+ ### Dependency injection
45
+
46
+ Anyone familiar with AngularJS is familiar with how dependency injection is performed:
47
+
48
+ ```js
49
+ angular.controller('MyController', ['dep1', 'dep2', function(dep1, dep2) {
50
+ // ...
51
+ }]);
52
+ ```
53
+
54
+ In PHP we find this pattern again in some frameworks and DI containers with partial to full support. For example in Silex you can type-hint the application to get it injected, but it only works with `Silex\Application`:
55
+
56
+ ```php
57
+ $app->get('/hello/{name}', function (Silex\Application $app, $name) {
58
+ // ...
59
+ });
60
+ ```
61
+
62
+ In Silly, it only works with `OutputInterface` to inject the application output:
63
+
64
+ ```php
65
+ $app->command('greet [name]', function ($name, OutputInterface $output) {
66
+ // ...
67
+ });
68
+ ```
69
+
70
+ [PHP-DI](http://php-di.org/doc/container.html) provides a way to invoke a callable and resolve all dependencies from the container using type-hints:
71
+
72
+ ```php
73
+ $container->call(function (Logger $logger, EntityManager $em) {
74
+ // ...
75
+ });
76
+ ```
77
+
78
+ **This library provides clear extension points to let frameworks implement any kind of dependency injection support they want.**
79
+
80
+ ### TL/DR
81
+
82
+ In short, this library is meant to be a base building block for calling a function with named parameters and/or dependency injection.
83
+
84
+ ## Installation
85
+
86
+ ```sh
87
+ $ composer require PHP-DI/invoker
88
+ ```
89
+
90
+ ## Usage
91
+
92
+ ### Default behavior
93
+
94
+ By default the `Invoker` can call using named parameters:
95
+
96
+ ```php
97
+ $invoker = new Invoker\Invoker;
98
+
99
+ $invoker->call(function () {
100
+ echo 'Hello world!';
101
+ });
102
+
103
+ // Simple parameter array
104
+ $invoker->call(function ($name) {
105
+ echo 'Hello ' . $name;
106
+ }, ['John']);
107
+
108
+ // Named parameters
109
+ $invoker->call(function ($name) {
110
+ echo 'Hello ' . $name;
111
+ }, [
112
+ 'name' => 'John'
113
+ ]);
114
+
115
+ // Use the default value
116
+ $invoker->call(function ($name = 'world') {
117
+ echo 'Hello ' . $name;
118
+ });
119
+
120
+ // Invoke any PHP callable
121
+ $invoker->call(['MyClass', 'myStaticMethod']);
122
+
123
+ // Using Class::method syntax
124
+ $invoker->call('MyClass::myStaticMethod');
125
+ ```
126
+
127
+ Dependency injection in parameters is supported but needs to be configured with your container. Read on or jump to [*Built-in support for dependency injection*](#built-in-support-for-dependency-injection) if you are impatient.
128
+
129
+ Additionally, callables can also be resolved from your container. Read on or jump to [*Resolving callables from a container*](#resolving-callables-from-a-container) if you are impatient.
130
+
131
+ ### Parameter resolvers
132
+
133
+ Extending the behavior of the `Invoker` is easy and is done by implementing a [`ParameterResolver`](https://github.com/PHP-DI/Invoker/blob/master/src/ParameterResolver/ParameterResolver.php).
134
+
135
+ This is explained in details the [Parameter resolvers documentation](doc/parameter-resolvers.md).
136
+
137
+ #### Built-in support for dependency injection
138
+
139
+ Rather than have you re-implement support for dependency injection with different containers every time, this package ships with 2 optional resolvers:
140
+
141
+ - [`TypeHintContainerResolver`](https://github.com/PHP-DI/Invoker/blob/master/src/ParameterResolver/Container/TypeHintContainerResolver.php)
142
+
143
+ This resolver will inject container entries by searching for the class name using the type-hint:
144
+
145
+ ```php
146
+ $invoker->call(function (Psr\Logger\LoggerInterface $logger) {
147
+ // ...
148
+ });
149
+ ```
150
+
151
+ In this example it will `->get('Psr\Logger\LoggerInterface')` from the container and inject it.
152
+
153
+ This resolver is only useful if you store objects in your container using the class (or interface) name. Silex or Symfony for example store services under a custom name (e.g. `twig`, `db`, etc.) instead of the class name: in that case use the resolver shown below.
154
+
155
+ - [`ParameterNameContainerResolver`](https://github.com/PHP-DI/Invoker/blob/master/src/ParameterResolver/Container/ParameterNameContainerResolver.php)
156
+
157
+ This resolver will inject container entries by searching for the name of the parameter:
158
+
159
+ ```php
160
+ $invoker->call(function ($twig) {
161
+ // ...
162
+ });
163
+ ```
164
+
165
+ In this example it will `->get('twig')` from the container and inject it.
166
+
167
+ These resolvers can work with any dependency injection container compliant with [container-interop](https://github.com/container-interop/container-interop). If you container is not compliant you can use the [Acclimate](https://github.com/jeremeamia/acclimate-container) package.
168
+
169
+ Setting up those resolvers is simple:
170
+
171
+ ```php
172
+ // $container must be an instance of Interop\Container\ContainerInterface
173
+ $container = ...
174
+
175
+ $containerResolver = new TypeHintContainerResolver($container);
176
+ // or
177
+ $containerResolver = new ParameterNameContainerResolver($container);
178
+
179
+ $invoker = new Invoker\Invoker;
180
+ // Register it before all the other parameter resolvers
181
+ $invoker->getParameterResolver()->prependResolver($containerResolver);
182
+ ```
183
+
184
+ You can also register both resolvers at the same time if you wish by prepending both. Implementing support for more tricky things is easy and up to you!
185
+
186
+ ### Resolving callables from a container
187
+
188
+ The `Invoker` can be wired to your DI container to resolve the callables.
189
+
190
+ For example with an invokable class:
191
+
192
+ ```php
193
+ class MyHandler
194
+ {
195
+ public function __invoke()
196
+ {
197
+ // ...
198
+ }
199
+ }
200
+
201
+ // By default this doesn't work: an instance of the class should be provided
202
+ $invoker->call('MyHandler');
203
+
204
+ // If we set up the container to use
205
+ $invoker = new Invoker\Invoker(null, $container);
206
+ // Now 'MyHandler' is resolved using the container!
207
+ $invoker->call('MyHandler');
208
+ ```
209
+
210
+ The same works for a class method:
211
+
212
+ ```php
213
+ class WelcomeController
214
+ {
215
+ public function home()
216
+ {
217
+ // ...
218
+ }
219
+ }
220
+
221
+ // By default this doesn't work: home() is not a static method
222
+ $invoker->call(['WelcomeController', 'home']);
223
+
224
+ // If we set up the container to use
225
+ $invoker = new Invoker\Invoker(null, $container);
226
+ // Now 'WelcomeController' is resolved using the container!
227
+ $invoker->call(['WelcomeController', 'home']);
228
+ // Alternatively we can use the Class::method syntax
229
+ $invoker->call('WelcomeController::home');
230
+ ```
231
+
232
+ That feature can be used as the base building block for a framework's dispatcher.
233
+
234
+ Again, any [container-interop](https://github.com/container-interop/container-interop) compliant container can be provided, and [Acclimate](https://github.com/jeremeamia/acclimate-container) can be used for incompatible containers.
addons/lib/ioc/php-di/invoker/composer.json ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "php-di/invoker",
3
+ "description": "Generic and extensible callable invoker",
4
+ "keywords": ["invoker", "dependency-injection", "dependency", "injection", "callable", "invoke"],
5
+ "homepage": "https://github.com/PHP-DI/Invoker",
6
+ "license": "MIT",
7
+ "type": "library",
8
+ "autoload": {
9
+ "psr-4": {
10
+ "Invoker\\": "src/"
11
+ }
12
+ },
13
+ "autoload-dev": {
14
+ "psr-4": {
15
+ "Invoker\\Test\\": "tests/"
16
+ }
17
+ },
18
+ "require": {
19
+ "container-interop/container-interop": "~1.1"
20
+ },
21
+ "require-dev": {
22
+ "phpunit/phpunit": "~4.5",
23
+ "athletic/athletic": "~0.1.8"
24
+ }
25
+ }
addons/lib/ioc/php-di/invoker/doc/parameter-resolvers.md ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Parameter resolvers
2
+
3
+ Extending the behavior of the `Invoker` is easy and is done by implementing a [`ParameterResolver`](https://github.com/PHP-DI/Invoker/blob/master/src/ParameterResolver/ParameterResolver.php):
4
+
5
+ ```php
6
+ interface ParameterResolver
7
+ {
8
+ public function getParameters(
9
+ ReflectionFunctionAbstract $reflection,
10
+ array $providedParameters,
11
+ array $resolvedParameters
12
+ );
13
+ }
14
+ ```
15
+
16
+ - `$providedParameters` contains the parameters provided by the user when calling `$invoker->call($callable, $parameters)`
17
+ - `$resolvedParameters` contains parameters that have already been resolved by other parameter resolvers
18
+
19
+ An `Invoker` can chain multiple parameter resolvers to mix behaviors, e.g. you can mix "named parameters" support with "dependency injection" support. This is why a `ParameterResolver` should skip parameters that are already resolved in `$resolvedParameters`.
20
+
21
+ Here is an implementation example for dumb dependency injection that creates a new instance of the classes type-hinted:
22
+
23
+ ```php
24
+ class MyParameterResolver implements ParameterResolver
25
+ {
26
+ public function getParameters(
27
+ ReflectionFunctionAbstract $reflection,
28
+ array $providedParameters,
29
+ array $resolvedParameters
30
+ ) {
31
+ foreach ($reflection->getParameters() as $index => $parameter) {
32
+ if (array_key_exists($index, $resolvedParameters)) {
33
+ // Skip already resolved parameters
34
+ continue;
35
+ }
36
+
37
+ $class = $parameter->getClass();
38
+
39
+ if ($class) {
40
+ $resolvedParameters[$index] = $class->newInstance();
41
+ }
42
+ }
43
+
44
+ return $resolvedParameters;
45
+ }
46
+ }
47
+ ```
48
+
49
+ To use it:
50
+
51
+ ```php
52
+ $invoker = new Invoker\Invoker(new MyParameterResolver);
53
+
54
+ $invoker->call(function (ArticleManager $articleManager) {
55
+ $articleManager->publishArticle('Hello world', 'This is the article content.');
56
+ });
57
+ ```
58
+
59
+ A new instance of `ArticleManager` will be created by our parameter resolver.
60
+
61
+ ## Chaining parameter resolvers
62
+
63
+ The fun starts to happen when we want to add support for many things:
64
+
65
+ - named parameters
66
+ - dependency injection for type-hinted parameters
67
+ - ...
68
+
69
+ This is where we should use the [`ResolverChain`](https://github.com/PHP-DI/Invoker/blob/master/src/ParameterResolver/ResolverChain.php). This resolver implements the [Chain of responsibility](http://en.wikipedia.org/wiki/Chain-of-responsibility_pattern) design pattern.
70
+
71
+ For example the default chain is:
72
+
73
+ ```php
74
+ $parameterResolver = new ResolverChain([
75
+ new NumericArrayResolver,
76
+ new AssociativeArrayResolver,
77
+ new DefaultValueResolver,
78
+ ]);
79
+ ```
80
+
81
+ It allows to support even the weirdest use cases like:
82
+
83
+ ```php
84
+ $parameters = [];
85
+
86
+ // First parameter will receive "Welcome"
87
+ $parameters[] = 'Welcome';
88
+
89
+ // Parameter named "content" will receive "Hello world!"
90
+ $parameters['content'] = 'Hello world!';
91
+
92
+ // $published is not defined so it will use its default value
93
+ $invoker->call(function ($title, $content, $published = true) {
94
+ // ...
95
+ }, $parameters);
96
+ ```
97
+
98
+ We can put our custom parameter resolver in the list and created a super-duper invoker that also supports basic dependency injection:
99
+
100
+ ```php
101
+ $parameterResolver = new ResolverChain([
102
+ new MyParameterResolver, // Our resolver is at the top for highest priority
103
+ new NumericArrayResolver,
104
+ new AssociativeArrayResolver,
105
+ new DefaultValueResolver,
106
+ ]);
107
+
108
+ $invoker = new Invoker\Invoker($parameterResolver);
109
+ ```
addons/lib/ioc/php-di/invoker/src/CallableResolver.php ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Invoker;
4
+
5
+ use Interop\Container\ContainerInterface;
6
+ use Interop\Container\Exception\NotFoundException;
7
+ use 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/lib/ioc/php-di/invoker/src/Exception/InvocationException.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace 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/lib/ioc/php-di/invoker/src/Exception/NotCallableException.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace 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/lib/ioc/php-di/invoker/src/Exception/NotEnoughParametersException.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace 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/lib/ioc/php-di/invoker/src/Invoker.php ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Invoker;
4
+
5
+ use Interop\Container\ContainerInterface;
6
+ use Invoker\Exception\NotCallableException;
7
+ use Invoker\Exception\NotEnoughParametersException;
8
+ use Invoker\ParameterResolver\AssociativeArrayResolver;
9
+ use Invoker\ParameterResolver\DefaultValueResolver;
10
+ use Invoker\ParameterResolver\NumericArrayResolver;
11
+ use Invoker\ParameterResolver\ParameterResolver;
12
+ use Invoker\ParameterResolver\ResolverChain;
13
+ use 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/lib/ioc/php-di/invoker/src/InvokerInterface.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Invoker;
4
+
5
+ use Invoker\Exception\InvocationException;
6
+ use Invoker\Exception\NotCallableException;
7
+ use 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/lib/ioc/php-di/invoker/src/ParameterResolver/AssociativeArrayResolver.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace 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/lib/ioc/php-di/invoker/src/ParameterResolver/Container/ParameterNameContainerResolver.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Invoker\ParameterResolver\Container;
4
+
5
+ use Interop\Container\ContainerInterface;
6
+ use 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/lib/ioc/php-di/invoker/src/ParameterResolver/Container/TypeHintContainerResolver.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Invoker\ParameterResolver\Container;
4
+
5
+ use Interop\Container\ContainerInterface;
6
+ use 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/lib/ioc/php-di/invoker/src/ParameterResolver/DefaultValueResolver.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace 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/lib/ioc/php-di/invoker/src/ParameterResolver/NumericArrayResolver.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace 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/lib/ioc/php-di/invoker/src/ParameterResolver/ParameterResolver.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace 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/lib/ioc/php-di/invoker/src/ParameterResolver/ResolverChain.php ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace 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/lib/ioc/php-di/invoker/src/ParameterResolver/TypeHintResolver.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Invoker\ParameterResolver;
4
+
5
+ use 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/lib/ioc/php-di/invoker/src/Reflection/CallableReflection.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Invoker\Reflection;
4
+
5
+ use 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/lib/ioc/php-di/php-di/.coveralls.yml ADDED
@@ -0,0 +1,2 @@
 
 
1
+ coverage_clover: clover.xml
2
+ json_path: coveralls-upload.json
addons/lib/ioc/php-di/php-di/.gitattributes ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ # .gitattributes
2
+ tests/ export-ignore
3
+ website/ export-ignore
4
+ doc/ export-ignore
5
+ news/ export-ignore
6
+
7
+ # Auto detect text files and perform LF normalization
8
+ * text=auto
addons/lib/ioc/php-di/php-di/.gitignore ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ /.idea/
2
+ /vendor/
3
+ /composer.phar
4
+ /composer.lock
5
+ /theme/
6
+ /.couscous/
7
+ /website/bower_components/
8
+ /website/css/all.min.css
9
+ /logo/
addons/lib/ioc/php-di/php-di/.travis.yml ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ language: php
2
+
3
+ php:
4
+ - 5.4
5
+ - 5.5
6
+ - 5.6
7
+ - 7.0
8
+ - hhvm
9
+
10
+ matrix:
11
+ include:
12
+ - php: 5.4
13
+ env: dependencies=lowest
14
+
15
+ before_script:
16
+ - composer self-update
17
+ - if [[ $(phpenv version-name) == '5.6' ]]; then composer require satooshi/php-coveralls:dev-master -n ; fi
18
+ - if [[ $(phpenv version-name) != '5.6' ]]; then composer install -n ; fi
19
+ - if [ "$dependencies" = "lowest" ]; then composer update --prefer-lowest --prefer-stable -n; fi;
20
+
21
+ script:
22
+ - if [[ $(phpenv version-name) == '5.6' ]]; then phpunit --coverage-clover clover.xml ; fi
23
+ - if [[ $(phpenv version-name) != '5.6' ]]; then phpunit ; fi
24
+
25
+ after_script:
26
+ - if [[ $(phpenv version-name) == '5.6' ]]; then php vendor/bin/coveralls -v ; fi
addons/lib/ioc/php-di/php-di/404.md ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ ---
2
+ layout: 404
3
+ ---
addons/lib/ioc/php-di/php-di/CONTRIBUTING.md ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Contributing
2
+
3
+ [![Build Status](https://travis-ci.org/PHP-DI/PHP-DI.png?branch=master)](https://travis-ci.org/PHP-DI/PHP-DI) [![Coverage Status](https://coveralls.io/repos/PHP-DI/PHP-DI/badge.png?branch=master)](https://coveralls.io/r/PHP-DI/PHP-DI?branch=master)
4
+
5
+ PHP-DI is license under the MIT License.
6
+
7
+
8
+ ## Set up
9
+
10
+ * Check out the sources using git or download them
11
+
12
+ ```bash
13
+ $ git clone https://github.com/PHP-DI/PHP-DI.git
14
+ ```
15
+
16
+ * Install the libraries using composer:
17
+
18
+ ```bash
19
+ $ curl -s http://getcomposer.org/installer | php
20
+ $ php composer.phar install
21
+ ```
22
+
23
+ If you are running Windows or are having trouble, read [the official documentation](http://getcomposer.org/doc/00-intro.md#installation).
24
+
25
+
26
+ ## Run the tests
27
+
28
+ The tests are run with [PHPUnit](http://www.phpunit.de/manual/current/en/installation.html):
29
+
30
+ ```bash
31
+ $ phpunit
32
+ ```
33
+
34
+
35
+ ## Learning the internals
36
+
37
+ Read the [How it works](doc/how-it-works.md) documentation.
38
+
39
+
40
+ ## What to do?
41
+
42
+ - Add tests: pick up uncovered situations in the [code coverage report](https://coveralls.io/r/PHP-DI/PHP-DI)
43
+ - Resolve issues: [issue list](https://github.com/PHP-DI/PHP-DI/issues)
44
+ - Improve the documentation
45
+ - …
46
+
47
+
48
+ ## Coding style
49
+
50
+ The code follows PSR0, PSR1 and [PSR2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md).
51
+
52
+ Also, do not hesitate to add your name to the author list of a class in the docblock if you improve it.
addons/lib/ioc/php-di/php-di/LICENSE ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ PHP-DI - PHP Dependency Injection
2
+
3
+ Copyright (C) Matthieu Napoli
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
6
+ associated documentation files (the "Software"), to deal in the Software without restriction,
7
+ including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
+ and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
9
+ subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all copies or substantial
12
+ portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
15
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
16
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
17
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
18
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
addons/lib/ioc/php-di/php-di/README.md ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ layout: home
3
+ ---
4
+
5
+ PHP-DI is a Dependency Injection Container made for humans.
6
+
7
+ [![Build Status](https://img.shields.io/travis/PHP-DI/PHP-DI.svg?style=flat-square)](https://travis-ci.org/PHP-DI/PHP-DI)
8
+ [![HHVM Status](https://img.shields.io/hhvm/php-di/php-di.svg?style=flat-square)](http://hhvm.h4cc.de/package/php-di/php-di)
9
+ [![Coverage Status](https://img.shields.io/coveralls/PHP-DI/PHP-DI/master.svg?style=flat-square)](https://coveralls.io/r/PHP-DI/PHP-DI?branch=master)
10
+ [![Scrutinizer Code Quality](https://img.shields.io/scrutinizer/g/PHP-DI/PHP-DI.svg?style=flat-square)](https://scrutinizer-ci.com/g/PHP-DI/PHP-DI/?branch=master)
11
+ [![Latest Version](https://img.shields.io/github/release/PHP-DI/PHP-DI.svg?style=flat-square)](https://packagist.org/packages/php-di/php-di)
12
+ [![Total Downloads](https://img.shields.io/packagist/dt/mnapoli/PHP-DI.svg?style=flat-square)](https://packagist.org/packages/mnapoli/php-di)
13
+
14
+ [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/PHP-DI/PHP-DI.svg)](http://isitmaintained.com/project/PHP-DI/PHP-DI "Average time to resolve an issue")
15
+ [![Percentage of issues still open](http://isitmaintained.com/badge/open/PHP-DI/PHP-DI.svg)](http://isitmaintained.com/project/PHP-DI/PHP-DI "Percentage of issues still open")
16
+
17
+ It is meant to be practical, powerful, and framework-agnostic.
18
+
19
+ Read more on the website: **[php-di.org](http://php-di.org)**
20
+
21
+ Join us in the Gitter chat room: [![Gitter chat](https://badges.gitter.im/PHP-DI/PHP-DI.png)](https://gitter.im/PHP-DI/PHP-DI)
22
+
23
+ Support is always appreciated: [![Gratipay](https://img.shields.io/gratipay/mnapoli.svg)](https://gratipay.com/mnapoli/)
addons/lib/ioc/php-di/php-di/change-log.md ADDED
@@ -0,0 +1,280 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Change log
2
+
3
+ ## 5.0
4
+
5
+ This is the complete change log. You can also read the [migration guide](doc/migration/5.0.md) for upgrading, or [the news article](news/15-php-di-5-0-released.md) for a nicer introduction to this new version.
6
+
7
+ Improvements:
8
+
9
+ - Moved to an organization on GitHub: [github.com/PHP-DI/PHP-DI](https://github.com/PHP-DI/PHP-DI)
10
+ - The package has been renamed to: from `mnapoli/php-di` to [`php-di/php-di`](https://packagist.org/packages/php-di/php-di)
11
+ - New [Silex integration](doc/frameworks/silex.md)
12
+ - Lighter package: from 10 to 3 Composer dependencies!
13
+ - [#235](https://github.com/PHP-DI/PHP-DI/issues/235): `DI\link()` is now deprecated in favor of `DI\get()`. There is no BC break as `DI\link()` still works.
14
+ - [#207](https://github.com/PHP-DI/PHP-DI/issues/207): Support for `DI\link()` in arrays
15
+ - [#203](https://github.com/PHP-DI/PHP-DI/issues/203): New `DI\string()` helper ([documentation](doc/php-definitions.md))
16
+ - [#208](https://github.com/PHP-DI/PHP-DI/issues/208): Support for nested definitions
17
+ - [#226](https://github.com/PHP-DI/PHP-DI/pull/226): `DI\factory()` can now be omitted with closures:
18
+
19
+ ```php
20
+ // before
21
+ 'My\Class' => DI\factory(function () { ... })
22
+ // now (optional shortcut)
23
+ 'My\Class' => function () { ... }
24
+ ```
25
+ - [#193](https://github.com/PHP-DI/PHP-DI/issues/193): `DI\object()->method()` now supports calling the same method twice (or more).
26
+ - [#248](https://github.com/PHP-DI/PHP-DI/issues/248): New `DI\decorate()` helper to decorate a previously defined entry ([documentation](doc/definition-overriding.md))
27
+ - [#215](https://github.com/PHP-DI/PHP-DI/pull/215): New `DI\add()` helper to add entries to an existing array ([documentation](doc/definition-overriding.md))
28
+ - [#218](https://github.com/PHP-DI/PHP-DI/issues/218): `ContainerBuilder::addDefinitions()` can now take an array of definitions
29
+ - [#211](https://github.com/PHP-DI/PHP-DI/pull/211): `ContainerBuilder::addDefinitions()` is now fluent (return `$this`)
30
+ - [#250](https://github.com/PHP-DI/PHP-DI/issues/250): `Container::call()` now also accepts parameters not indexed by name as well as embedded definitions ([documentation](doc/container.md))
31
+ - Various performance improvements, e.g. lower the number of files loaded, simpler architecture, …
32
+
33
+ BC breaks:
34
+
35
+ - PHP-DI now requires a version of PHP >= 5.4.0
36
+ - The package is lighter by default:
37
+ - [#251](https://github.com/PHP-DI/PHP-DI/issues/251): Annotations are disabled by default, if you use annotations enable them with `$containerBuilder->useAnnotations(true)`. Additionally the `doctrine/annotations` package isn't required by default anymore, so you also need to run `composer require doctrine/annotations`.
38
+ - `doctrine/cache` is not installed by default anymore, you need to require it in `composer.json` (`~1.0`) if you want to configure a cache for PHP-DI
39
+ - [#198](https://github.com/PHP-DI/PHP-DI/issues/198): `ocramius/proxy-manager` is not installed by default anymore, you need to require it in `composer.json` (`~1.0`) if you want to use **lazy injection**
40
+ - Closures are now converted into factory definitions automatically. If you ever defined a closure as a value (e.g. to have the closure injected in a class), you need to wrap the closure with the new `DI\value()` helper.
41
+ - [#223](https://github.com/PHP-DI/PHP-DI/issues/223): `DI\ContainerInterface` was deprecated since v4.1 and has been removed
42
+
43
+ Internal changes in case you were replacing/extending some parts:
44
+
45
+ - the definition sources architecture has been refactored, if you defined custom definition sources you will need to update your code (it should be much easier now)
46
+ - [#252](https://github.com/PHP-DI/PHP-DI/pull/252): `DI\Scope` internal implementation has changed. You are encouraged to use the constants (`DI\Scope::SINGLETON` and `DI\Scope::PROTOTYPE`) instead of the static methods, but backward compatibility is kept (static methods still work).
47
+ - [#241](https://github.com/PHP-DI/PHP-DI/issues/241): `Container::call()` now uses the *Invoker* external library
48
+
49
+ ## 4.4
50
+
51
+ Read the [news entry](news/13-php-di-4-4-released.md).
52
+
53
+ - [#185](https://github.com/PHP-DI/PHP-DI/issues/185) Support for invokable objects in `Container::call()`
54
+ - [#192](https://github.com/PHP-DI/PHP-DI/pull/192) Support for invokable classes in `Container::call()` (will instantiate the class)
55
+ - [#184](https://github.com/PHP-DI/PHP-DI/pull/184) Option to ignore phpdoc errors
56
+
57
+ ## 4.3
58
+
59
+ Read the [news entry](news/11-php-di-4-3-released.md).
60
+
61
+ - [#176](https://github.com/PHP-DI/PHP-DI/pull/176) New definition type for reading environment variables: `DI\env()`
62
+ - [#181](https://github.com/PHP-DI/PHP-DI/pull/181) `DI\FactoryInterface` and `DI\InvokerInterface` are now auto-registered inside the container so that you can inject them without any configuration needed
63
+ - [#173](https://github.com/PHP-DI/PHP-DI/pull/173) `$container->call(['MyClass', 'method]);` will get `MyClass` from the container if `method()` is not a static method
64
+
65
+ ## 4.2.2
66
+
67
+ - Fixed [#180](https://github.com/PHP-DI/PHP-DI/pull/180): `Container::call()` with object methods (`[$object, 'method']`) is now supported
68
+
69
+ ## 4.2.1
70
+
71
+ - Support for PHP 5.3.3, which was previously incomplete because of a bug in the reflection (there is now a workaround for this bug)
72
+
73
+ But if you can, seriously avoid this (really old) PHP version and upgrade.
74
+
75
+ ## 4.2
76
+
77
+ Read the [news entry](news/10-php-di-4-2-released.md).
78
+
79
+ **Minor BC-break**: Optional parameters (that were not configured) were injected, they are now ignored, which is what naturally makes sense since they are optional.
80
+ Example:
81
+
82
+ ```php
83
+ public function __construct(Bar $bar = null)
84
+ {
85
+ $this->bar = $bar ?: $this->createDefaultBar();
86
+ }
87
+ ```
88
+
89
+ Before 4.2, PHP-DI would try to inject a `Bar` instance. From 4.2 and onwards, it will inject `null`.
90
+
91
+ Of course, you can still explicitly define an injection for the optional parameters and that will work.
92
+
93
+ All changes:
94
+
95
+ * [#162](https://github.com/PHP-DI/PHP-DI/pull/162) Added `Container::call()` to call functions with dependency injection
96
+ * [#156](https://github.com/PHP-DI/PHP-DI/issues/156) Wildcards (`*`) in definitions
97
+ * [#164](https://github.com/PHP-DI/PHP-DI/issues/164) Prototype scope is now available for `factory()` definitions too
98
+ * FIXED [#168](https://github.com/PHP-DI/PHP-DI/pull/168) `Container::has()` now returns false for interfaces and abstract classes that are not mapped in the definitions
99
+ * FIXED [#171](https://github.com/PHP-DI/PHP-DI/issues/171) Optional parameters are now ignored (not injected) if not set in the definitions (see the BC-break warning above)
100
+
101
+ ## 4.1
102
+
103
+ Read the [news entry](news/09-php-di-4-1-released.md).
104
+
105
+ BC-breaks: None.
106
+
107
+ * [#138](https://github.com/PHP-DI/PHP-DI/issues/138) [Container-interop](https://github.com/container-interop/container-interop) compliance
108
+ * [#143](https://github.com/PHP-DI/PHP-DI/issues/143) Much more explicit exception messages
109
+ * [#157](https://github.com/PHP-DI/PHP-DI/issues/157) HHVM support
110
+ * [#158](https://github.com/PHP-DI/PHP-DI/issues/158) Improved the documentation for [Symfony 2 integration](http://php-di.org/doc/frameworks/symfony2.html)
111
+
112
+ ## 4.0
113
+
114
+ Major changes:
115
+
116
+ * The configuration format has changed ([read more here to understand why](news/06-php-di-4-0-new-definitions.md))
117
+
118
+ Read the migration guide if you are using 3.x: [Migration guide from 3.x to 4.0](doc/migration/4.0.md).
119
+
120
+ BC-breaks:
121
+
122
+ * YAML, XML and JSON definitions have been removed, and the PHP definition format has changed (see above)
123
+ * `ContainerSingleton` has been removed
124
+ * You cannot configure an injection as lazy anymore, you can only configure a container entry as lazy
125
+ * The Container constructor now takes mandatory parameters. Use the ContainerBuilder to create a Container.
126
+ * Removed `ContainerBuilder::setDefinitionsValidation()` (no definition validation anymore)
127
+ * `ContainerBuilder::useReflection()` is now named: `ContainerBuilder::useAutowiring()`
128
+ * `ContainerBuilder::addDefinitionsFromFile()` is now named: `ContainerBuilder::addDefinitions()`
129
+ * The `$proxy` parameter in `Container::get($name, $proxy = true)` hase been removed. To get a proxy, you now need to define an entry as "lazy".
130
+
131
+ Other changes:
132
+
133
+ * Added `ContainerInterface` and `FactoryInterface`, both implemented by the container.
134
+ * [#115](https://github.com/PHP-DI/PHP-DI/issues/115) Added `Container::has()`
135
+ * [#142](https://github.com/PHP-DI/PHP-DI/issues/142) Added `Container::make()` to resolve an entry
136
+ * [#127](https://github.com/PHP-DI/PHP-DI/issues/127) Added support for cases where PHP-DI is wrapped by another container (like Acclimate): PHP-DI can now use the wrapping container to perform injections
137
+ * [#128](https://github.com/PHP-DI/PHP-DI/issues/128) Configure entry aliases
138
+ * [#110](https://github.com/PHP-DI/PHP-DI/issues/110) XML definitions are not supported anymore
139
+ * [#122](https://github.com/PHP-DI/PHP-DI/issues/122) JSON definitions are not supported anymore
140
+ * `ContainerSingleton` has finally been removed
141
+ * Added `ContainerBuilder::buildDevContainer()` to get started with a default container very easily.
142
+ * [#99](https://github.com/PHP-DI/PHP-DI/issues/99) Fixed "`@param` with PHP internal type throws exception"
143
+
144
+ ## 3.5.1
145
+
146
+ * FIXED [#126](https://github.com/PHP-DI/PHP-DI/issues/126): `Container::set` without effect if a value has already been set and retrieved
147
+
148
+ ## 3.5
149
+
150
+ Read the [news entry](news/05-php-di-3-5.md).
151
+
152
+ * Importing `@Inject` and `@Injectable` annotations is now optional! It means that you don't have to write `use DI\Annotation\Inject` anymore
153
+ * FIXED [#124](https://github.com/PHP-DI/PHP-DI/issues/124): `@Injects` annotation conflicts with other annotations
154
+
155
+ ## 3.4
156
+
157
+ Read the [news entry](news/04-php-di-3-4.md).
158
+
159
+ * [#106](https://github.com/PHP-DI/PHP-DI/pull/106) You can now define arrays of values (in YAML, PHP, …) thanks to [@unkind](https://github.com/unkind)
160
+ * [#98](https://github.com/PHP-DI/PHP-DI/issues/98) `ContainerBuilder` is now fluent thanks to [@drdamour](https://github.com/drdamour)
161
+ * [#101](https://github.com/PHP-DI/PHP-DI/pull/101) Optional parameters are now supported: if you don't define a value to inject, their default value will be used
162
+ * XML definitions have been deprecated, there weren't even documented and were not maintained. They will be removed in 4.0.
163
+ * FIXED [#100](https://github.com/PHP-DI/PHP-DI/issues/100): bug for lazy injection in constructors
164
+
165
+ ## 3.3
166
+
167
+ Read the [news entry](news/03-php-di-3-3.md).
168
+
169
+ * Inject dependencies on an existing instance with `Container::injectOn` (work from [Jeff Flitton](https://github.com/jflitton): [#89](https://github.com/PHP-DI/PHP-DI/pull/89)).
170
+ * [#86](https://github.com/PHP-DI/PHP-DI/issues/86): Optimized definition lookup (faster)
171
+ * FIXED [#87](https://github.com/PHP-DI/PHP-DI/issues/87): Rare bug in the `PhpDocParser`, fixed by [drdamour](https://github.com/drdamour)
172
+
173
+ ## 3.2
174
+
175
+ Read the [news entry](news/02-php-di-3-2.md).
176
+
177
+ Small BC-break: PHP-DI 3.0 and 3.1 injected properties before calling the constructor. This was confusing and [not supported for internal classes](https://github.com/PHP-DI/PHP-DI/issues/74).
178
+ From 3.2 and on, properties are injected after calling the constructor.
179
+
180
+ * **[Lazy injection](doc/lazy-injection.md)**: it is now possible to use lazy injection on properties and methods (setters and constructors).
181
+ * Lazy dependencies are now proxies that extend the class they proxy, so type-hinting works.
182
+ * Addition of the **`ContainerBuilder`** object, that helps to [create and configure a `Container`](doc/container-configuration.md).
183
+ * Some methods for configuring the Container have gone **deprecated** in favor of the `ContainerBuilder`. Fear not, these deprecated methods will remain until next major version (4.0).
184
+ * `Container::useReflection`, use ContainerBuilder::useReflection instead
185
+ * `Container::useAnnotations`, use ContainerBuilder::useAnnotations instead
186
+ * `Container::setDefinitionCache`, use ContainerBuilder::setDefinitionCache instead
187
+ * `Container::setDefinitionsValidation`, use ContainerBuilder::setDefinitionsValidation instead
188
+ * The container is now auto-registered (as 'DI\Container'). You can now inject the container without registering it.
189
+
190
+ ## 3.1.1
191
+
192
+ * Value definitions (`$container->set('foo', 80)`) are not cached anymore
193
+ * FIXED [#82](https://github.com/PHP-DI/PHP-DI/issues/82): Serialization error when using a cache
194
+
195
+ ## 3.1
196
+
197
+ Read the [news entry](news/01-php-di-3-1.md).
198
+
199
+ * Zend Framework 1 integration through the [PHP-DI-ZF1 project](https://github.com/PHP-DI/PHP-DI-ZF1)
200
+ * Fixed the order of priorities when you mix different definition sources (reflection, annotations, files, …). See [Definition overriding](doc/definition-overriding.md)
201
+ * Now possible to define null values with `$container->set('foo', null)` (see [#79](https://github.com/PHP-DI/PHP-DI/issues/79)).
202
+ * Deprecated usage of `ContainerSingleton`, will be removed in next major version (4.0)
203
+
204
+ ## 3.0.6
205
+
206
+ * FIXED [#76](https://github.com/PHP-DI/PHP-DI/issues/76): Definition conflict when setting a closure for a class name
207
+
208
+ ## 3.0.5
209
+
210
+ * FIXED [#70](https://github.com/PHP-DI/PHP-DI/issues/70): Definition conflict when setting a value for a class name
211
+
212
+ ## 3.0.4
213
+
214
+ * FIXED [#69](https://github.com/PHP-DI/PHP-DI/issues/69): YamlDefinitionFileLoader crashes if YAML file is empty
215
+
216
+ ## 3.0.3
217
+
218
+ * Fixed over-restrictive dependencies in composer.json
219
+
220
+ ## 3.0.2
221
+
222
+ * [#64](https://github.com/PHP-DI/PHP-DI/issues/64): Non PHP-DI exceptions are not captured-rethrown anymore when injecting dependencies (cleaner stack trace)
223
+
224
+ ## 3.0.1
225
+
226
+ * [#62](https://github.com/PHP-DI/PHP-DI/issues/62): When using aliases, definitions are now merged
227
+
228
+ ## 3.0
229
+
230
+ Major compatibility breaks with 2.x.
231
+
232
+ * The container is no longer a Singleton (but `ContainerSingleton::getInstance()` is available for fools who like it)
233
+ * Setter injection
234
+ * Constructor injection
235
+ * Scopes: singleton (share the same instance of the class) or prototype (create a new instance each time it is fetched). Defined at class level.
236
+ * Configuration is reworked from scratch. Now every configuration backend can do 100% of the job.
237
+ * Provided configuration backends:
238
+ * Reflection
239
+ * Annotations: @Inject, @Injectable
240
+ * PHP code (`Container::set()`)
241
+ * PHP array
242
+ * YAML file
243
+ * As a consequence, annotations are not mandatory anymore, all functionalities can be used with or without annotations.
244
+ * Renamed `DI\Annotations\` to `DI\Annotation\`
245
+ * `Container` no longer implements ArrayAccess, use only `$container->get($key)` now
246
+ * ZF1 integration broken and removed (work in progress for next releases)
247
+ * Code now follows PSR1 and PSR2 coding styles
248
+ * FIXED: [#58](https://github.com/PHP-DI/PHP-DI/issues/58) Getting a proxy of an alias didn't work
249
+
250
+ ## 2.1
251
+
252
+ * `use` statements to import classes from other namespaces are now taken into account with the `@var` annotation
253
+ * Updated and lightened the dependencies : `doctrine/common` has been replaced with more specific `doctrine/annotations` and `doctrine/cache`
254
+
255
+ ## 2.0
256
+
257
+ Major compatibility breaks with 1.x.
258
+
259
+ * `Container::resolveDependencies()` has been renamed to `Container::injectAll()`
260
+ * Dependencies are now injected **before** the constructor is called, and thus are available in the constructor
261
+ * Merged `@Value` annotation with `@Inject`: no difference between value and bean injection anymore
262
+ * Container implements ArrayAccess for get() and set() (`$container['db.host'] = 'localhost';`)
263
+ * Ini configuration files removed: configuration is done in PHP
264
+ * Allow to define beans within closures for lazy-loading
265
+ * Switched to MIT License
266
+
267
+ Warning:
268
+
269
+ * If you use PHP 5.3 and __wakeup() methods, they will be called when PHP-DI creates new instances of those classes.
270
+
271
+ ## 1.1
272
+
273
+ * Caching of annotations based on Doctrine caches
274
+
275
+ ## 1.0
276
+
277
+ * DependencyManager renamed to Container
278
+ * Refactored basic Container usage with `get` and `set`
279
+ * Allow named injection `@Inject(name="")`
280
+ * Zend Framework integration
addons/lib/ioc/php-di/php-di/composer.json ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "php-di/php-di",
3
+ "type": "library",
4
+ "description": "The dependency injection container for humans",
5
+ "keywords": ["di", "dependency injection", "container"],
6
+ "homepage": "http://php-di.org/",
7
+ "license": "MIT",
8
+ "autoload": {
9
+ "psr-4": {
10
+ "DI\\": "src/DI/"
11
+ },
12
+ "files": [
13
+ "src/DI/functions.php"
14
+ ]
15
+ },
16
+ "autoload-dev": {
17
+ "psr-4": {
18
+ "DI\\Test\\IntegrationTest\\": "tests/IntegrationTest/",
19
+ "DI\\Test\\UnitTest\\": "tests/UnitTest/"
20
+ }
21
+ },
22
+ "require": {
23
+ "php": ">=5.4.0",
24
+ "container-interop/container-interop": "~1.0",
25
+ "php-di/invoker": "~1.0",
26
+ "php-di/phpdoc-reader": "~2.0"
27
+ },
28
+ "require-dev": {
29
+ "phpunit/phpunit": "~4.5",
30
+ "mnapoli/phpunit-easymock": "~0.1.4",
31
+ "doctrine/cache": "~1.0",
32
+ "doctrine/annotations": "~1.2",
33
+ "ocramius/proxy-manager": "~1.0"
34
+ },
35
+ "suggest": {
36
+ "doctrine/cache": "Install it if you want to use the cache (version ~1.0)",
37
+ "doctrine/annotations": "Install it if you want to use annotations (version ~1.2)",
38
+ "ocramius/proxy-manager": "Install it if you want to use lazy injection (version ~1.0)"
39
+ }
40
+ }
addons/lib/ioc/php-di/php-di/couscous.yml ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ baseUrl: http://php-di.org
2
+
3
+ scripts:
4
+ before:
5
+ - lessc --clean-css website/less/main.less website/css/all.min.css
6
+
7
+ menu:
8
+ items:
9
+ introduction:
10
+ section: Introduction
11
+ items:
12
+ getting-started:
13
+ text: Getting started
14
+ url: doc/getting-started.html
15
+ understanding-di:
16
+ text: Understanding dependency injection
17
+ url: doc/understanding-di.html
18
+ best-practices:
19
+ text: "\"Best practices\" guide"
20
+ url: doc/best-practices.html
21
+ usage:
22
+ section: Usage
23
+ items:
24
+ container-configuration:
25
+ text: Configuring the container
26
+ url: doc/container-configuration.html
27
+ container:
28
+ text: Using the container
29
+ url: doc/container.html
30
+ definition:
31
+ section: Definitions
32
+ items:
33
+ introduction:
34
+ text: Introduction
35
+ url: doc/definition.html
36
+ autowiring:
37
+ text: Autowiring
38
+ url: doc/autowiring.html
39
+ php:
40
+ text: PHP definitions
41
+ url: doc/php-definitions.html
42
+ annotations:
43
+ text: Annotations
44
+ url: doc/annotations.html
45
+ definition-overriding:
46
+ text: Definition extensions and overriding
47
+ url: doc/definition-overriding.html
48
+ frameworks:
49
+ section: Frameworks
50
+ items:
51
+ symfony2:
52
+ text: Symfony 2
53
+ url: doc/frameworks/symfony2.html
54
+ silex:
55
+ text: Silex
56
+ url: doc/frameworks/silex.html
57
+ zf1:
58
+ text: Zend Framework 1
59
+ url: doc/frameworks/zf1.html
60
+ silly:
61
+ text: Silly
62
+ url: doc/frameworks/silly.html
63
+ advanced:
64
+ section: Advanced topics
65
+ items:
66
+ performances:
67
+ text: Performances
68
+ url: doc/performances.html
69
+ scopes:
70
+ text: Scopes
71
+ url: doc/scopes.html
72
+ lazy-injection:
73
+ text: Lazy injection
74
+ url: doc/lazy-injection.html
75
+ inject-on-instance:
76
+ text: Inject on an existing instance
77
+ url: doc/inject-on-instance.html
78
+ environments:
79
+ text: Injections depending on the environment
80
+ url: doc/environments.html
81
+ migration:
82
+ section: Migration guides
83
+ items:
84
+ 4:
85
+ text: From PHP-DI 3.x to 4.0
86
+ url: doc/migration/4.0.html
87
+ 5:
88
+ text: From PHP-DI 4.x to 5.0
89
+ url: doc/migration/5.0.html
90
+ internals:
91
+ section: Internals
92
+ items:
93
+ contributing:
94
+ text: Contributing
95
+ url: contributing.html
96
+ how-it-works:
97
+ text: How PHP-DI works
98
+ url: doc/how-it-works.html
99
+ versions:
100
+ section: Old documentation
101
+ items:
102
+ v3:
103
+ text: PHP-DI 3.x
104
+ absoluteUrl: https://github.com/PHP-DI/PHP-DI/tree/3.x/doc
105
+ v4:
106
+ text: PHP-DI 4.x
107
+ absoluteUrl: https://github.com/PHP-DI/PHP-DI/tree/4.x/doc
addons/lib/ioc/php-di/php-di/phpunit.xml.dist ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!--
3
+ phpunit -c phpunit.xml
4
+ -->
5
+ <phpunit backupGlobals="false"
6
+ backupStaticAttributes="false"
7
+ colors="true"
8
+ convertErrorsToExceptions="true"
9
+ convertNoticesToExceptions="true"
10
+ convertWarningsToExceptions="true"
11
+ syntaxCheck="true"
12
+ forceCoversAnnotation="true"
13
+ bootstrap="./vendor/autoload.php">
14
+
15
+ <testsuites>
16
+ <testsuite name="unit">
17
+ <directory>./tests/UnitTest/</directory>
18
+ </testsuite>
19
+ <testsuite name="integration">
20
+ <directory>./tests/IntegrationTest/</directory>
21
+ </testsuite>
22
+ </testsuites>
23
+
24
+ <filter>
25
+ <whitelist processUncoveredFilesFromWhitelist="true">
26
+ <directory suffix=".php">src</directory>
27
+ </whitelist>
28
+ </filter>
29
+
30
+ </phpunit>
addons/lib/ioc/php-di/php-di/src/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 DI\Annotation;
11
+
12
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Annotation;
11
+
12
+ use 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/lib/ioc/php-di/php-di/src/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 DI;
11
+
12
+ use DI\Definition\ObjectDefinition;
13
+ use DI\Definition\Definition;
14
+ use DI\Definition\FactoryDefinition;
15
+ use DI\Definition\InstanceDefinition;
16
+ use DI\Definition\Resolver\ResolverDispatcher;
17
+ use DI\Definition\Source\CachedDefinitionSource;
18
+ use DI\Definition\Source\DefinitionSource;
19
+ use DI\Definition\Source\MutableDefinitionSource;
20
+ use DI\Definition\Helper\DefinitionHelper;
21
+ use DI\Definition\Resolver\DefinitionResolver;
22
+ use DI\Invoker\DefinitionParameterResolver;
23
+ use DI\Proxy\ProxyFactory;
24
+ use Exception;
25
+ use Interop\Container\ContainerInterface;
26
+ use InvalidArgumentException;
27
+ use Invoker\Invoker;
28
+ use Invoker\ParameterResolver\AssociativeArrayResolver;
29
+ use Invoker\ParameterResolver\Container\TypeHintContainerResolver;
30
+ use Invoker\ParameterResolver\NumericArrayResolver;
31
+ use Invoker\ParameterResolver\ResolverChain;
32
+
33
+ /**
34
+ * Dependency Injection Container.
35
+ *
36
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
37
+ */
38
+ class Container implements ContainerInterface, FactoryInterface, \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 \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['DI\Container'] = $this;
95
+ $this->singletonEntries['DI\ContainerInterface'] = $this;
96
+ $this->singletonEntries['DI\FactoryInterface'] = $this;
97
+ $this->singletonEntries['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. 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 \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/lib/ioc/php-di/php-di/src/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 DI;
11
+
12
+ use DI\Definition\Source\AnnotationReader;
13
+ use DI\Definition\Source\DefinitionArray;
14
+ use DI\Definition\Source\CachedDefinitionSource;
15
+ use DI\Definition\Source\DefinitionSource;
16
+ use DI\Definition\Source\DefinitionFile;
17
+ use DI\Definition\Source\Autowiring;
18
+ use DI\Definition\Source\SourceChain;
19
+ use DI\Proxy\ProxyFactory;
20
+ use Doctrine\Common\Cache\Cache;
21
+ use 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 = '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/lib/ioc/php-di/php-di/src/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 DI;
11
+
12
+ use DI\Definition\Definition;
13
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition;
11
+
12
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition;
11
+
12
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition;
11
+
12
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition;
11
+
12
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition;
11
+
12
+ /**
13
+ * Cacheable definition
14
+ *
15
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
16
+ */
17
+ interface CacheableDefinition extends Definition
18
+ {
19
+ }
addons/lib/ioc/php-di/php-di/src/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 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/lib/ioc/php-di/php-di/src/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 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/lib/ioc/php-di/php-di/src/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 DI\Definition\Dumper;
11
+
12
+ use DI\Definition\AliasDefinition;
13
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition\Dumper;
11
+
12
+ use DI\Debug;
13
+ use DI\Definition\ArrayDefinition;
14
+ use DI\Definition\Definition;
15
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition\Dumper;
11
+
12
+ use DI\Definition\DecoratorDefinition;
13
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition\Dumper;
11
+
12
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition\Dumper;
11
+
12
+ use 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
+ 'DI\Definition\ValueDefinition' => new ValueDefinitionDumper(),
60
+ 'DI\Definition\FactoryDefinition' => new FactoryDefinitionDumper(),
61
+ 'DI\Definition\DecoratorDefinition' => new DecoratorDefinitionDumper(),
62
+ 'DI\Definition\AliasDefinition' => new AliasDefinitionDumper(),
63
+ 'DI\Definition\ObjectDefinition' => new ObjectDefinitionDumper(),
64
+ 'DI\Definition\EnvironmentVariableDefinition' => new EnvironmentVariableDefinitionDumper(),
65
+ ];
66
+ }
67
+ }
68
+ }
addons/lib/ioc/php-di/php-di/src/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 DI\Definition\Dumper;
11
+
12
+ use DI\Debug;
13
+ use DI\Definition\Definition;
14
+ use DI\Definition\EntryReference;
15
+ use DI\Definition\EnvironmentVariableDefinition;
16
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition\Dumper;
11
+
12
+ use DI\Definition\Definition;
13
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition\Dumper;
11
+
12
+ use DI\Definition\ObjectDefinition;
13
+ use DI\Definition\ObjectDefinition\MethodInjection;
14
+ use DI\Definition\Definition;
15
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition\Dumper;
11
+
12
+ use DI\Definition\Definition;
13
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition\Dumper;
11
+
12
+ use DI\Definition\Definition;
13
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition;
11
+
12
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition;
11
+
12
+ use 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/lib/ioc/php-di/php-di/src/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 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/lib/ioc/php-di/php-di/src/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 DI\Definition\Exception;
11
+
12
+ use DI\Debug;
13
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition;
11
+
12
+ use 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/lib/ioc/php-di/php-di/src/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 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/lib/ioc/php-di/php-di/src/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 DI\Definition\Helper;
11
+
12
+ use 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/lib/ioc/php-di/php-di/src/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 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 \DI\Definition\Definition
22
+ */
23
+ public function getDefinition($entryName);
24
+ }
addons/lib/ioc/php-di/php-di/src/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 DI\Definition\Helper;
11
+
12
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition\Helper;
11
+
12
+ use DI\Definition\DecoratorDefinition;
13
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition\Helper;
11
+
12
+ use DI\Definition\ObjectDefinition;
13
+ use DI\Definition\ObjectDefinition\MethodInjection;
14
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition\Helper;
11
+
12
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition\Helper;
11
+
12
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition;
11
+
12
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition;
11
+
12
+ use DI\Definition\ObjectDefinition\MethodInjection;
13
+ use DI\Definition\ObjectDefinition\PropertyInjection;
14
+ use DI\Definition\Exception\DefinitionException;
15
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition\ObjectDefinition;
11
+
12
+ use 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/lib/ioc/php-di/php-di/src/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 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/lib/ioc/php-di/php-di/src/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 DI\Definition\Resolver;
11
+
12
+ use DI\Definition\AliasDefinition;
13
+ use DI\Definition\Definition;
14
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition\Resolver;
11
+
12
+ use DI\Definition\ArrayDefinition;
13
+ use DI\Definition\Definition;
14
+ use DI\Definition\Helper\DefinitionHelper;
15
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition\Resolver;
11
+
12
+ use DI\Definition\DecoratorDefinition;
13
+ use DI\Definition\Exception\DefinitionException;
14
+ use DI\Definition\Definition;
15
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition\Resolver;
11
+
12
+ use DI\Definition\Definition;
13
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition\Resolver;
11
+
12
+ use DI\Definition\Definition;
13
+ use DI\Definition\EnvironmentVariableDefinition;
14
+ use DI\Definition\Exception\DefinitionException;
15
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition\Resolver;
11
+
12
+ use DI\Definition\Exception\DefinitionException;
13
+ use DI\Definition\FactoryDefinition;
14
+ use DI\Definition\Definition;
15
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition\Resolver;
11
+
12
+ use DI\Definition\Definition;
13
+ use DI\Definition\InstanceDefinition;
14
+ use DI\DependencyException;
15
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition\Resolver;
11
+
12
+ use DI\Definition\ObjectDefinition;
13
+ use DI\Definition\Definition;
14
+ use DI\Definition\Exception\DefinitionException;
15
+ use DI\Definition\ObjectDefinition\PropertyInjection;
16
+ use DI\Definition\Helper\DefinitionHelper;
17
+ use DI\DependencyException;
18
+ use DI\Proxy\ProxyFactory;
19
+ use Exception;
20
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition\Resolver;
11
+
12
+ use DI\Definition\AbstractFunctionCallDefinition;
13
+ use DI\Definition\ObjectDefinition;
14
+ use DI\Definition\Exception\DefinitionException;
15
+ use 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/lib/ioc/php-di/php-di/src/DI/Definition/Resolver/ResolverDispatcher.php ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DI\Definition\Resolver;
4
+
5
+ use DI\Definition\Definition;
6
+ use DI\Definition\Exception\DefinitionException;
7
+ use DI\Proxy\ProxyFactory;
8
+ use 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 'DI\Definition\ValueDefinition':
92
+ if (! $this->valueResolver) {
93
+ $this->valueResolver = new ValueResolver();
94
+ }
95
+ return $this->valueResolver;
96
+ case 'DI\Definition\ArrayDefinition':
97
+ case 'DI\Definition\ArrayDefinitionExtension':
98
+ if (! $this->arrayResolver) {
99
+ $this->arrayResolver = new ArrayResolver($this);
100
+ }
101
+ return $this->arrayResolver;
102
+ case 'DI\Definition\FactoryDefinition':
103
+ if (! $this->factoryResolver) {
104
+ $this->factoryResolver = new FactoryResolver($this->container);
105
+ }
106
+ return $this->factoryResolver;
107
+ case 'DI\Definition\DecoratorDefinition':
108
+ if (! $this->decoratorResolver) {
109
+ $this->decoratorResolver = new DecoratorResolver($this->container, $this);
110
+ }
111
+ return $this->decoratorResolver;
112
+ case 'DI\Definition\AliasDefinition':
113
+ if (! $this->aliasResolver) {
114
+ $this->aliasResolver = new AliasResolver($this->container);
115
+ }
116
+ return $this->aliasResolver;
117
+ case 'DI\Definition\ObjectDefinition':
118
+ if (! $this->objectResolver) {
119
+ $this->objectResolver = new ObjectCreator($this, $this->proxyFactory);
120
+ }
121
+ return $this->objectResolver;
122
+ case 'DI\Definition\InstanceDefinition':
123
+ if (! $this->instanceResolver) {
124
+ $this->instanceResolver = new InstanceInjector($this, $this->proxyFactory);
125
+ }
126
+ return $this->instanceResolver;
127
+ case 'DI\Definition\EnvironmentVariableDefinition':
128
+ if (! $this->envVariableResolver) {
129
+ $this->envVariableResolver = new EnvironmentVariableResolver($this);
130
+ }
131
+ return $this->envVariableResolver;
132
+ case '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/lib/ioc/php-di/php-di/src/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 DI\Definition\Resolver;
11
+
12
+ use DI\Definition\Definition;
13
+ use DI\Definition\StringDefinition;
14
+ use DI\DependencyException;
15
+ use DI\NotFoundException;
16
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition\Resolver;
11
+
12
+ use DI\Definition\Definition;
13
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition\Source;
11
+
12
+ use DI\Annotation\Inject;
13
+ use DI\Annotation\Injectable;
14
+ use DI\Definition\ObjectDefinition;
15
+ use DI\Definition\EntryReference;
16
+ use DI\Definition\Exception\AnnotationException;
17
+ use DI\Definition\Exception\DefinitionException;
18
+ use DI\Definition\ObjectDefinition\MethodInjection;
19
+ use 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 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, '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, '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('DI\Annotation', __DIR__ . '/../../../');
246
+ $this->annotationReader = new SimpleAnnotationReader();
247
+ $this->annotationReader->addNamespace('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, '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/lib/ioc/php-di/php-di/src/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 DI\Definition\Source;
11
+
12
+ use DI\Definition\ObjectDefinition;
13
+ use DI\Definition\EntryReference;
14
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition\Source;
11
+
12
+ use DI\Definition\CacheableDefinition;
13
+ use 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 = '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/lib/ioc/php-di/php-di/src/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 DI\Definition\Source;
11
+
12
+ use DI\Definition\ArrayDefinition;
13
+ use DI\Definition\ObjectDefinition;
14
+ use DI\Definition\Definition;
15
+ use DI\Definition\FactoryDefinition;
16
+ use DI\Definition\ValueDefinition;
17
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition\Source;
11
+
12
+ use DI\Definition\Definition;
13
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition\Source;
11
+
12
+ use DI\Definition\Definition;
13
+ use 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/lib/ioc/php-di/php-di/src/DI/Definition/Source/MutableDefinitionSource.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DI\Definition\Source;
4
+
5
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition\Source;
11
+
12
+ use DI\Definition\Definition;
13
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition;
11
+
12
+ use 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/lib/ioc/php-di/php-di/src/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 DI\Definition;
11
+
12
+ use 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/lib/ioc/php-di/php-di/src/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 DI;
11
+
12
+ use Interop\Container\Exception\ContainerException;
13
+
14
+ /**
15
+ * Exception for the Container
16
+ */
17
+ class DependencyException extends \Exception implements ContainerException
18
+ {
19
+ }
addons/lib/ioc/php-di/php-di/src/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 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/lib/ioc/php-di/php-di/src/DI/Invoker/DefinitionParameterResolver.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace DI\Invoker;
4
+
5
+ use DI\Definition\Helper\DefinitionHelper;
6
+ use DI\Definition\Resolver\DefinitionResolver;
7
+ use 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/lib/ioc/php-di/php-di/src/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 DI;
11
+
12
+ /**
13
+ * Invoke a callable.
14
+ *
15
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
16
+ */
17
+ interface InvokerInterface extends \Invoker\InvokerInterface
18
+ {
19
+ }
addons/lib/ioc/php-di/php-di/src/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 DI;
11
+
12
+ use 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/lib/ioc/php-di/php-di/src/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 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/lib/ioc/php-di/php-di/src/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 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/lib/ioc/php-di/php-di/src/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 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/lib/ioc/php-di/php-di/src/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 DI;
11
+
12
+ use DI\Definition\EntryReference;
13
+ use DI\Definition\Helper\ArrayDefinitionExtensionHelper;
14
+ use DI\Definition\Helper\FactoryDefinitionHelper;
15
+ use DI\Definition\Helper\ObjectDefinitionHelper;
16
+ use DI\Definition\Helper\EnvironmentVariableDefinitionHelper;
17
+ use DI\Definition\Helper\ValueDefinitionHelper;
18
+ use DI\Definition\Helper\StringDefinitionHelper;
19
+
20
+ if (! function_exists('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('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('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('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('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('DI\link')) {
100
+ /**
101
+ * Helper for referencing another container entry in an object definition.
102
+ *
103
+ * @deprecated \DI\link() has been replaced by \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('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('DI\add')) {
134
+ /**
135
+ * Helper for extending another definition.
136
+ *
137
+ * Example:
138
+ *
139
+ * 'log.backends' => DI\add(DI\get('My\Custom\LogBackend'))
140
+ *
141
+ * or:
142
+ *
143
+ * 'log.backends' => DI\add([
144
+ * 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('DI\string')) {
164
+ /**
165
+ * Helper for concatenating strings.
166
+ *
167
+ * Example:
168
+ *
169
+ * 'log.filename' => 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/lib/ioc/php-di/phpdoc-reader/.gitattributes ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ # .gitattributes
2
+ tests/ export-ignore
3
+ phpunit.xml.dist export-ignore
4
+ .travis.yml export-ignore
5
+
6
+ # Auto detect text files and perform LF normalization
7
+ * text=auto
addons/lib/ioc/php-di/phpdoc-reader/.gitignore ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ .DS_Store
2
+ .idea/*
3
+ vendor/*
4
+ composer.phar
5
+ composer.lock
addons/lib/ioc/php-di/phpdoc-reader/LICENSE ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (C) 2015 Matthieu Napoli
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
4
+ associated documentation files (the "Software"), to deal in the Software without restriction,
5
+ including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
6
+ and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
7
+ subject to the following conditions:
8
+
9
+ The above copyright notice and this permission notice shall be included in all copies or substantial
10
+ portions of the Software.
11
+
12
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
13
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
14
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
15
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
16
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
addons/lib/ioc/php-di/phpdoc-reader/README.md ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # PhpDocReader
2
+
3
+ [![Build Status](https://img.shields.io/travis/PHP-DI/PhpDocReader.svg)](https://travis-ci.org/mnapoli/PhpDocReader)
4
+ ![](https://img.shields.io/packagist/dt/PHP-DI/phpdoc-reader.svg)
5
+
6
+ This project is used by:
7
+
8
+ - [PHP-DI](http://php-di.org/)
9
+ - [phockito-unit-php-di](https://github.com/balihoo/phockito-unit-php-di)
10
+
11
+ Fork the README to add your project here.
12
+
13
+ ## Features
14
+
15
+ PhpDocReader parses `@var` and `@param` values in PHP docblocks:
16
+
17
+ ```php
18
+
19
+ use My\Cache\Backend;
20
+
21
+ class Cache
22
+ {
23
+ /**
24
+ * @var Backend
25
+ */
26
+ protected $backend;
27
+
28
+ /**
29
+ * @param Backend $backend
30
+ */
31
+ public function __construct($backend)
32
+ {
33
+ }
34
+ }
35
+ ```
36
+
37
+ It supports namespaced class names with the same resolution rules as PHP:
38
+
39
+ - fully qualified name (starting with `\`)
40
+ - imported class name (eg. `use My\Cache\Backend;`)
41
+ - relative class name (from the current namespace, like `SubNamespace\MyClass`)
42
+ - aliased class name (eg. `use My\Cache\Backend as FooBar;`)
43
+
44
+ Primitive types (`@var string`) are ignored (returns null), only valid class names are returned.
45
+
46
+ ## Usage
47
+
48
+ ```php
49
+ $reader = new PhpDocReader();
50
+
51
+ // Read a property type (@var phpdoc)
52
+ $property = new ReflectionProperty($className, $propertyName);
53
+ $propertyClass = $reader->getPropertyClass($property);
54
+
55
+ // Read a parameter type (@param phpdoc)
56
+ $parameter = new ReflectionParameter(array($className, $methodName), $parameterName);
57
+ $parameterClass = $reader->getParameterClass($parameter);
58
+ ```
addons/lib/ioc/php-di/phpdoc-reader/composer.json ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "php-di/phpdoc-reader",
3
+ "type": "library",
4
+ "description": "PhpDocReader parses @var and @param values in PHP docblocks (supports namespaced class names with the same resolution rules as PHP)",
5
+ "keywords": ["phpdoc", "reflection"],
6
+ "license": "MIT",
7
+ "autoload": {
8
+ "psr-4": {
9
+ "PhpDocReader\\": "src/PhpDocReader"
10
+ }
11
+ },
12
+ "autoload-dev": {
13
+ "psr-4": {
14
+ "UnitTest\\PhpDocReader\\": "tests/"
15
+ }
16
+ },
17
+ "require": {
18
+ "php": ">=5.4.0"
19
+ },
20
+ "require-dev": {
21
+ "phpunit/phpunit": "~4.6"
22
+ }
23
+ }
addons/lib/ioc/php-di/phpdoc-reader/src/PhpDocReader/AnnotationException.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace PhpDocReader;
4
+
5
+ /**
6
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
7
+ */
8
+ class AnnotationException extends \Exception
9
+ {
10
+ }
addons/lib/ioc/php-di/phpdoc-reader/src/PhpDocReader/PhpDocReader.php ADDED
@@ -0,0 +1,311 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace PhpDocReader;
4
+
5
+ use 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
+ * @author Matthieu Napoli <matthieu@mnapoli.fr>
16
+ */
17
+ class PhpDocReader
18
+ {
19
+ /**
20
+ * @var UseStatementParser
21
+ */
22
+ private $parser;
23
+
24
+ private $ignoredTypes = array(
25
+ 'bool',
26
+ 'boolean',
27
+ 'string',
28
+ 'int',
29
+ 'integer',
30
+ 'float',
31
+ 'double',
32
+ 'array',
33
+ 'object',
34
+ 'callable',
35
+ 'resource',
36
+ 'mixed',
37
+ );
38
+
39
+ /**
40
+ * Enable or disable throwing errors when PhpDoc Errors occur (when parsing annotations)
41
+ *
42
+ * @var bool
43
+ */
44
+ private $ignorePhpDocErrors;
45
+
46
+ /**
47
+ *
48
+ * @param bool $ignorePhpDocErrors
49
+ */
50
+ public function __construct($ignorePhpDocErrors = false)
51
+ {
52
+ $this->parser = new UseStatementParser();
53
+ $this->ignorePhpDocErrors = $ignorePhpDocErrors;
54
+ }
55
+
56
+ /**
57
+ * Parse the docblock of the property to get the class of the var annotation.
58
+ *
59
+ * @param ReflectionProperty $property
60
+ *
61
+ * @throws AnnotationException
62
+ * @return string|null Type of the property (content of var annotation)
63
+ *
64
+ * @deprecated Use getPropertyClass instead.
65
+ */
66
+ public function getPropertyType(ReflectionProperty $property)
67
+ {
68
+ return $this->getPropertyClass($property);
69
+ }
70
+
71
+ /**
72
+ * Parse the docblock of the property to get the class of the var annotation.
73
+ *
74
+ * @param ReflectionProperty $property
75
+ *
76
+ * @throws AnnotationException
77
+ * @return string|null Type of the property (content of var annotation)
78
+ */
79
+ public function getPropertyClass(ReflectionProperty $property)
80
+ {
81
+ // Get the content of the @var annotation
82
+ if (preg_match('/@var\s+([^\s]+)/', $property->getDocComment(), $matches)) {
83
+ list(, $type) = $matches;
84
+ } else {
85
+ return null;
86
+ }
87
+
88
+ // Ignore primitive types
89
+ if (in_array($type, $this->ignoredTypes)) {
90
+ return null;
91
+ }
92
+
93
+ // Ignore types containing special characters ([], <> ...)
94
+ if (! preg_match('/^[a-zA-Z0-9\\\\_]+$/', $type)) {
95
+ return null;
96
+ }
97
+
98
+ $class = $property->getDeclaringClass();
99
+
100
+ // If the class name is not fully qualified (i.e. doesn't start with a \)
101
+ if ($type[0] !== '\\') {
102
+ // Try to resolve the FQN using the class context
103
+ $resolvedType = $this->tryResolveFqn($type, $class, $property);
104
+
105
+ if (!$resolvedType && !$this->ignorePhpDocErrors) {
106
+ throw new AnnotationException(sprintf(
107
+ 'The @var annotation on %s::%s contains a non existent class "%s". '
108
+ . 'Did you maybe forget to add a "use" statement for this annotation?',
109
+ $class->name,
110
+ $property->getName(),
111
+ $type
112
+ ));
113
+ }
114
+
115
+ $type = $resolvedType;
116
+ }
117
+
118
+ if (!$this->classExists($type) && !$this->ignorePhpDocErrors) {
119
+ throw new AnnotationException(sprintf(
120
+ 'The @var annotation on %s::%s contains a non existent class "%s"',
121
+ $class->name,
122
+ $property->getName(),
123
+ $type
124
+ ));
125
+ }
126
+
127
+ // Remove the leading \ (FQN shouldn't contain it)
128
+ $type = ltrim($type, '\\');
129
+
130
+ return $type;
131
+ }
132
+
133
+ /**
134
+ * Parse the docblock of the property to get the class of the param annotation.
135
+ *
136
+ * @param ReflectionParameter $parameter
137
+ *
138
+ * @throws AnnotationException
139
+ * @return string|null Type of the property (content of var annotation)
140
+ *
141
+ * @deprecated Use getParameterClass instead.
142
+ */
143
+ public function getParameterType(ReflectionParameter $parameter)
144
+ {
145
+ return $this->getParameterClass($parameter);
146
+ }
147
+
148
+ /**
149
+ * Parse the docblock of the property to get the class of the param annotation.
150
+ *
151
+ * @param ReflectionParameter $parameter
152
+ *
153
+ * @throws AnnotationException
154
+ * @return string|null Type of the property (content of var annotation)
155
+ */
156
+ public function getParameterClass(ReflectionParameter $parameter)
157
+ {
158
+ // Use reflection
159
+ $parameterClass = $parameter->getClass();
160
+ if ($parameterClass !== null) {
161
+ return $parameterClass->name;
162
+ }
163
+
164
+ $parameterName = $parameter->name;
165
+ // Get the content of the @param annotation
166
+ $method = $parameter->getDeclaringFunction();
167
+ if (preg_match('/@param\s+([^\s]+)\s+\$' . $parameterName . '/', $method->getDocComment(), $matches)) {
168
+ list(, $type) = $matches;
169
+ } else {
170
+ return null;
171
+ }
172
+
173
+ // Ignore primitive types
174
+ if (in_array($type, $this->ignoredTypes)) {
175
+ return null;
176
+ }
177
+
178
+ // Ignore types containing special characters ([], <> ...)
179
+ if (! preg_match('/^[a-zA-Z0-9\\\\_]+$/', $type)) {
180
+ return null;
181
+ }
182
+
183
+ $class = $parameter->getDeclaringClass();
184
+
185
+ // If the class name is not fully qualified (i.e. doesn't start with a \)
186
+ if ($type[0] !== '\\') {
187
+ // Try to resolve the FQN using the class context
188
+ $resolvedType = $this->tryResolveFqn($type, $class, $parameter);
189
+
190
+ if (!$resolvedType && !$this->ignorePhpDocErrors) {
191
+ throw new AnnotationException(sprintf(
192
+ 'The @param annotation for parameter "%s" of %s::%s contains a non existent class "%s". '
193
+ . 'Did you maybe forget to add a "use" statement for this annotation?',
194
+ $parameterName,
195
+ $class->name,
196
+ $method->name,
197
+ $type
198
+ ));
199
+ }
200
+
201
+ $type = $resolvedType;
202
+ }
203
+
204
+ if (!$this->classExists($type) && !$this->ignorePhpDocErrors) {
205
+ throw new AnnotationException(sprintf(
206
+ 'The @param annotation for parameter "%s" of %s::%s contains a non existent class "%s"',
207
+ $parameterName,
208
+ $class->name,
209
+ $method->name,
210
+ $type
211
+ ));
212
+ }
213
+
214
+ // Remove the leading \ (FQN shouldn't contain it)
215
+ $type = ltrim($type, '\\');
216
+
217
+ return $type;
218
+ }
219
+
220
+ /**
221
+ * Attempts to resolve the FQN of the provided $type based on the $class and $member context.
222
+ *
223
+ * @param string $type
224
+ * @param ReflectionClass $class
225
+ * @param Reflector $member
226
+ *
227
+ * @return string|null Fully qualified name of the type, or null if it could not be resolved
228
+ */
229
+ private function tryResolveFqn($type, ReflectionClass $class, Reflector $member)
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
+ } else {
242
+ return $uses[$loweredAlias];
243
+ }
244
+ } elseif ($this->classExists($class->getNamespaceName() . '\\' . $type)) {
245
+ return $class->getNamespaceName() . '\\' . $type;
246
+ } elseif (isset($uses['__NAMESPACE__']) && $this->classExists($uses['__NAMESPACE__'] . '\\' . $type)) {
247
+ // Class namespace
248
+ return $uses['__NAMESPACE__'] . '\\' . $type;
249
+ } elseif ($this->classExists($type)) {
250
+ // No namespace
251
+ return $type;
252
+ }
253
+
254
+ if (version_compare(phpversion(), '5.4.0', '<')) {
255
+ return null;
256
+ } else {
257
+ // If all fail, try resolving through related traits
258
+ return $this->tryResolveFqnInTraits($type, $class, $member);
259
+ }
260
+ }
261
+
262
+ /**
263
+ * Attempts to resolve the FQN of the provided $type based on the $class and $member context, specifically searching
264
+ * through the traits that are used by the provided $class.
265
+ *
266
+ * @param string $type
267
+ * @param ReflectionClass $class
268
+ * @param Reflector $member
269
+ *
270
+ * @return string|null Fully qualified name of the type, or null if it could not be resolved
271
+ */
272
+ private function tryResolveFqnInTraits($type, ReflectionClass $class, Reflector $member)
273
+ {
274
+ /** @var ReflectionClass[] $traits */
275
+ $traits = array();
276
+
277
+ // Get traits for the class and its parents
278
+ while ($class) {
279
+ $traits = array_merge($traits, $class->getTraits());
280
+ $class = $class->getParentClass();
281
+ }
282
+
283
+ foreach ($traits as $trait) {
284
+ // Eliminate traits that don't have the property/method/parameter
285
+ if ($member instanceof ReflectionProperty && !$trait->hasProperty($member->name)) {
286
+ continue;
287
+ } elseif ($member instanceof ReflectionMethod && !$trait->hasMethod($member->name)) {
288
+ continue;
289
+ } elseif ($member instanceof ReflectionParameter && !$trait->hasMethod($member->getDeclaringFunction()->name)) {
290
+ continue;
291
+ }
292
+
293
+ // Run the resolver again with the ReflectionClass instance for the trait
294
+ $resolvedType = $this->tryResolveFqn($type, $trait, $member);
295
+
296
+ if ($resolvedType) {
297
+ return $resolvedType;
298
+ }
299
+ }
300
+ return null;
301
+ }
302
+
303
+ /**
304
+ * @param string $class
305
+ * @return bool
306
+ */
307
+ private function classExists($class)
308
+ {
309
+ return class_exists($class) || interface_exists($class);
310
+ }
311
+ }
addons/lib/ioc/php-di/phpdoc-reader/src/PhpDocReader/PhpParser/TokenParser.php ADDED
@@ -0,0 +1,159 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace 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 array
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 A list with all found use statements.
61
+ */
62
+ public function parseUseStatements($namespaceName)
63
+ {
64
+ $statements = array();
65
+ while (($token = $this->next())) {
66
+ if ($token[0] === T_USE) {
67
+ $statements = array_merge($statements, $this->parseUseStatement());
68
+ continue;
69
+ }
70
+ if ($token[0] !== T_NAMESPACE || $this->parseNamespace() != $namespaceName) {
71
+ continue;
72
+ }
73
+
74
+ // Get fresh array for new namespace. This is to prevent the parser to collect the use statements
75
+ // for a previous namespace with the same name. This is the case if a namespace is defined twice
76
+ // or if a namespace with the same name is commented out.
77
+ $statements = array();
78
+ }
79
+
80
+ return $statements;
81
+ }
82
+
83
+ /**
84
+ * Gets the next non whitespace and non comment token.
85
+ *
86
+ * @param boolean $docCommentIsComment If TRUE then a doc comment is considered a comment and skipped.
87
+ * If FALSE then only whitespace and normal comments are skipped.
88
+ *
89
+ * @return array|null The token if exists, null otherwise.
90
+ */
91
+ private function next($docCommentIsComment = true)
92
+ {
93
+ for ($i = $this->pointer; $i < $this->numTokens; $i++) {
94
+ $this->pointer++;
95
+ if ($this->tokens[$i][0] === T_WHITESPACE ||
96
+ $this->tokens[$i][0] === T_COMMENT ||
97
+ ($docCommentIsComment && $this->tokens[$i][0] === T_DOC_COMMENT)) {
98
+
99
+ continue;
100
+ }
101
+
102
+ return $this->tokens[$i];
103
+ }
104
+
105
+ return null;
106
+ }
107
+
108
+ /**
109
+ * Parses a single use statement.
110
+ *
111
+ * @return array A list with all found class names for a use statement.
112
+ */
113
+ private function parseUseStatement()
114
+ {
115
+ $class = '';
116
+ $alias = '';
117
+ $statements = array();
118
+ $explicitAlias = false;
119
+ while (($token = $this->next())) {
120
+ $isNameToken = $token[0] === T_STRING || $token[0] === T_NS_SEPARATOR;
121
+ if (!$explicitAlias && $isNameToken) {
122
+ $class .= $token[1];
123
+ $alias = $token[1];
124
+ } elseif ($explicitAlias && $isNameToken) {
125
+ $alias .= $token[1];
126
+ } elseif ($token[0] === T_AS) {
127
+ $explicitAlias = true;
128
+ $alias = '';
129
+ } elseif ($token === ',') {
130
+ $statements[strtolower($alias)] = $class;
131
+ $class = '';
132
+ $alias = '';
133
+ $explicitAlias = false;
134
+ } elseif ($token === ';') {
135
+ $statements[strtolower($alias)] = $class;
136
+ break;
137
+ } else {
138
+ break;
139
+ }
140
+ }
141
+
142
+ return $statements;
143
+ }
144
+
145
+ /**
146
+ * Gets the namespace.
147
+ *
148
+ * @return string The found namespace.
149
+ */
150
+ private function parseNamespace()
151
+ {
152
+ $name = '';
153
+ while (($token = $this->next()) && ($token[0] === T_STRING || $token[0] === T_NS_SEPARATOR)) {
154
+ $name .= $token[1];
155
+ }
156
+
157
+ return $name;
158
+ }
159
+ }
addons/lib/ioc/php-di/phpdoc-reader/src/PhpDocReader/PhpParser/UseStatementParser.php ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace 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
+ * @author Fabien Potencier <fabien@symfony.com>
13
+ * @author Christian Kaps <christian.kaps@mohiva.com>
14
+ */
15
+ class UseStatementParser
16
+ {
17
+ /**
18
+ * @return array A list with use statements in the form (Alias => FQN).
19
+ */
20
+ public function parseUseStatements(\ReflectionClass $class)
21
+ {
22
+ if (false === $filename = $class->getFilename()) {
23
+ return array();
24
+ }
25
+
26
+ $content = $this->getFileContent($filename, $class->getStartLine());
27
+
28
+ if (null === $content) {
29
+ return array();
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
+ $statements = $tokenizer->parseUseStatements($class->getNamespaceName());
37
+
38
+ return $statements;
39
+ }
40
+
41
+ /**
42
+ * Gets the content of the file right up to the given line number.
43
+ *
44
+ * @param string $filename The name of the file to load.
45
+ * @param integer $lineNumber The number of lines to read from file.
46
+ *
47
+ * @return string The content of the file.
48
+ */
49
+ private function getFileContent($filename, $lineNumber)
50
+ {
51
+ if ( ! is_file($filename)) {
52
+ return null;
53
+ }
54
+
55
+ $content = '';
56
+ $lineCnt = 0;
57
+ $file = new SplFileObject($filename);
58
+ while (!$file->eof()) {
59
+ if ($lineCnt++ == $lineNumber) {
60
+ break;
61
+ }
62
+
63
+ $content .= $file->fgets();
64
+ }
65
+
66
+ return $content;
67
+ }
68
+ }
addons/lib/ioc/psr/container/.gitignore ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ composer.lock
2
+ composer.phar
3
+ /vendor/
addons/lib/ioc/psr/container/LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013-2016 container-interop
4
+ Copyright (c) 2016 PHP Framework Interoperability Group
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
7
+ this software and associated documentation files (the "Software"), to deal in
8
+ the Software without restriction, including without limitation the rights to
9
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10
+ the Software, and to permit persons to whom the Software is furnished to do so,
11
+ subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
addons/lib/ioc/psr/container/README.md ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ # PSR Container
2
+
3
+ This repository holds all interfaces/classes/traits related to [PSR-11](https://github.com/container-interop/fig-standards/blob/master/proposed/container.md).
4
+
5
+ Note that this is not a container implementation of its own. See the specification for more details.
addons/lib/ioc/psr/container/composer.json ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "psr/container",
3
+ "type": "library",
4
+ "description": "Common Container Interface (PHP FIG PSR-11)",
5
+ "keywords": ["psr", "psr-11", "container", "container-interop", "container-interface"],
6
+ "homepage": "https://github.com/php-fig/container",
7
+ "license": "MIT",
8
+ "authors": [
9
+ {
10
+ "name": "PHP-FIG",
11
+ "homepage": "http://www.php-fig.org/"
12
+ }
13
+ ],
14
+ "require": {
15
+ "php": ">=5.3.0"
16
+ },
17
+ "autoload": {
18
+ "psr-4": {
19
+ "Psr\\Container\\": "src/"
20
+ }
21
+ },
22
+ "extra": {
23
+ "branch-alias": {
24
+ "dev-master": "1.0.x-dev"
25
+ }
26
+ }
27
+ }
addons/lib/ioc/psr/container/src/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 Psr\Container;
7
+
8
+ /**
9
+ * Base interface representing a generic exception in a container.
10
+ */
11
+ interface ContainerExceptionInterface
12
+ {
13
+ }
addons/lib/ioc/psr/container/src/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 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/lib/ioc/psr/container/src/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 Psr\Container;
7
+
8
+ /**
9
+ * No entry was found in the container.
10
+ */
11
+ interface NotFoundExceptionInterface extends ContainerExceptionInterface
12
+ {
13
+ }
addons/lib/script-loader-tag/script-loader-tag-interface.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\lib\script_loader_tag;
4
+
5
+ Interface Script_Loader_Tag_Interface {
6
+
7
+ /**
8
+ * @param $tag
9
+ * @param $type
10
+ *
11
+ * @return mixed
12
+ */
13
+ public function add_tag($tag, $type );
14
+
15
+ /**
16
+ * @param $tag
17
+ * @param $handle
18
+ * @param $src
19
+ *
20
+ * @return mixed
21
+ */
22
+ public function cookiebot_add_consent_attribute_to_tag( $tag, $handle, $src );
23
+ }
addons/lib/script-loader-tag/script-loader-tag.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\lib\script_loader_tag;
4
+
5
+ class Script_Loader_Tag implements Script_Loader_Tag_Interface {
6
+
7
+ /**
8
+ * List of tags to load in cookiebot attributes
9
+ *
10
+ * @var array
11
+ *
12
+ * @since 1.1.0
13
+ */
14
+ private $tags = array();
15
+
16
+ /**
17
+ * Cookiebot_Script_Loader_Tag constructor.
18
+ * Adds filter to enhance script attribute
19
+ *
20
+ * @since 1.1.0
21
+ */
22
+ public function __construct() {
23
+ add_filter( 'script_loader_tag', array( $this, 'cookiebot_add_consent_attribute_to_tag' ), 10, 3 );
24
+ }
25
+
26
+ /**
27
+ * Adds enqueue script handle tag to the array of tags.
28
+ * So that the script can be updated with cookieconsent attribute.
29
+ *
30
+ * @param $tag string Enqueue script handle name
31
+ * @param $type array
32
+ *
33
+ * @since 1.2.0
34
+ */
35
+ public function add_tag( $tag, $type ) {
36
+ $this->tags[ $tag ] = $type;
37
+ }
38
+
39
+ /**
40
+ * Modifies external links to google analytics
41
+ *
42
+ * @param $tag
43
+ * @param $handle
44
+ * @param $src
45
+ *
46
+ * @return string
47
+ *
48
+ * @since 1.2.0
49
+ */
50
+ public function cookiebot_add_consent_attribute_to_tag( $tag, $handle, $src ) {
51
+ if ( array_key_exists( $handle, $this->tags ) ) {
52
+ return '<script src="' . $src . '" type="text/plain" data-cookieconsent="' . implode( ',', $this->tags[ $handle ] ) . '"></script>';
53
+ }
54
+
55
+ return $tag;
56
+ }
57
+ }
addons/lib/settings-service-interface.php ADDED
@@ -0,0 +1,163 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
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
+ */
16
+ public function __construct( $container );
17
+
18
+ /**
19
+ * Returns true if the addon is enabled in the backend
20
+ *
21
+ * @param $addon string option name
22
+ *
23
+ * @return mixed
24
+ *
25
+ * @since 1.3.0
26
+ */
27
+ public function is_addon_enabled( $addon );
28
+
29
+ /**
30
+ * Returns true if the addon is installed
31
+ *
32
+ * @param $addon string plugin file, for example: test/test.php
33
+ *
34
+ * @return int|\WP_Error
35
+ *
36
+ * @since 1.3.0
37
+ */
38
+ public function is_addon_installed( $addon );
39
+
40
+ /**
41
+ * Returns true if the addon plugin is activated
42
+ *
43
+ * @param $addon string plugin file, for example: test/test.php
44
+ *
45
+ * @return bool
46
+ *
47
+ * @since 1.3.0
48
+ */
49
+ public function is_addon_activated( $addon );
50
+
51
+ /**
52
+ * Returns the addon version
53
+ *
54
+ * @param $addon
55
+ *
56
+ * @return bool
57
+ *
58
+ * @since 2.2.1
59
+ */
60
+ public function get_addon_version( $addon );
61
+
62
+ /**
63
+ * Returns all cookie type for given addon
64
+ *
65
+ * @param $addon string option name
66
+ * @param $default array default cookie types
67
+ *
68
+ * @return array
69
+ *
70
+ * @since 1.3.0
71
+ */
72
+ public function get_cookie_types( $addon, $default = array() );
73
+
74
+ /**
75
+ * Returns addons one by one through a generator
76
+ *
77
+ * @return \Generator
78
+ * @throws \DI\DependencyException
79
+ * @throws \DI\NotFoundException
80
+ *
81
+ * @since 1.3.0
82
+ */
83
+ public function get_addons();
84
+
85
+ /**
86
+ * Returns active addons
87
+ *
88
+ * @return array
89
+ * @throws \DI\DependencyException
90
+ * @throws \DI\NotFoundException
91
+ *
92
+ * @since 1.3.0
93
+ */
94
+ public function get_active_addons();
95
+
96
+ /**
97
+ * returns the placeholder if it does exist
98
+ *
99
+ * @param $option_key
100
+ * @param $default_placeholder
101
+ * @param $cookies
102
+ *
103
+ * @return bool|mixed
104
+ *
105
+ * @since 1.8.0
106
+ */
107
+ public function get_placeholder( $option_key, $default_placeholder, $cookies );
108
+
109
+ /**
110
+ * returns true if the "remove tag" option is enabled
111
+ *
112
+ * @param $option_key
113
+ *
114
+ * @return bool
115
+ *
116
+ * @since 2.1.0
117
+ */
118
+ public function is_remove_tag_enabled( $option_key );
119
+
120
+ /**
121
+ * returns true if the "remove tag" option is enabled
122
+ *
123
+ * @param $option_key
124
+ * @param $widget_key
125
+ *
126
+ * @return bool
127
+ *
128
+ * @since 2.1.0
129
+ */
130
+ public function is_widget_remove_tag_enabled( $option_key, $widget_key );
131
+
132
+ /**
133
+ * Check if the previous version is active
134
+ *
135
+ * @param $addons array List of addons
136
+ * @param $addon_class string The name of the class
137
+ *
138
+ * @return bool
139
+ *
140
+ * @since 2.1.3
141
+ */
142
+ public function is_previous_version_active( $addons, $addon_class );
143
+
144
+ /**
145
+ * Checks if the addon is the latest plugin version.
146
+ * Latest plugin version doesn't have extended class.
147
+ *
148
+ * @param $addon
149
+ *
150
+ * @return bool
151
+ *
152
+ * @since 2.1.3
153
+ */
154
+ public function is_latest_plugin_version( $addon );
155
+
156
+ /**
157
+ * The cookiebot plugin is deactivated
158
+ * so run this function to cleanup the addons.
159
+ *
160
+ * @since 2.2.0
161
+ */
162
+ public function cookiebot_deactivated();
163
+ }
addons/lib/settings-service.php ADDED
@@ -0,0 +1,542 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
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
+
12
+ CONST OPTION_NAME = 'cookiebot_available_addons';
13
+
14
+ /**
15
+ * Settings_Service constructor.
16
+ *
17
+ * @param $container
18
+ *
19
+ * @since 1.3.0
20
+ */
21
+ public function __construct( $container ) {
22
+ $this->container = $container;
23
+ }
24
+
25
+ /**
26
+ * Returns true if the addon is enabled in the backend
27
+ *
28
+ * @param $addon
29
+ *
30
+ * @return mixed
31
+ *
32
+ * @since 1.3.0
33
+ */
34
+ public function is_addon_enabled( $addon ) {
35
+ $option = get_option( static::OPTION_NAME );
36
+
37
+ if ( isset( $option[ $addon ]['enabled'] ) ) {
38
+ return true;
39
+ }
40
+
41
+ return false;
42
+ }
43
+
44
+ /**
45
+ * Returns true if the addon is installed
46
+ *
47
+ * @param $addon
48
+ *
49
+ * @return int|\WP_Error
50
+ *
51
+ * @since 1.3.0
52
+ */
53
+ public function is_addon_installed( $addon ) {
54
+ return ( $addon !== false && is_wp_error( validate_plugin( $addon ) ) ) ? false : true;
55
+ }
56
+
57
+ /**
58
+ * Returns the addon version
59
+ *
60
+ * @param $addon
61
+ *
62
+ * @return bool
63
+ *
64
+ * @since 2.2.1
65
+ */
66
+ public function get_addon_version( $addon ) {
67
+ $plugin_data = get_file_data( WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . $addon, array( 'Version' => 'version' ), false );
68
+
69
+ return ( isset( $plugin_data['Version'] ) ) ? $plugin_data['Version'] : false;
70
+ }
71
+
72
+ /**
73
+ * Returns true if the addon plugin is activated
74
+ *
75
+ * @param $addon
76
+ *
77
+ * @return bool
78
+ *
79
+ * @since 1.3.0
80
+ */
81
+ public function is_addon_activated( $addon ) {
82
+ return ( $addon === false || is_plugin_active( $addon ) ) ? true : false;
83
+ }
84
+
85
+ /**
86
+ * Returns all cookie type for given addon
87
+ *
88
+ * @param $addon string option name
89
+ * @param $default array default cookie types
90
+ *
91
+ * @return array
92
+ *
93
+ * @since 1.3.0
94
+ */
95
+ public function get_cookie_types( $addon, $default = array() ) {
96
+ $option = get_option( static::OPTION_NAME );
97
+
98
+ if ( isset( $option[ $addon ]['cookie_type'] ) && is_array( $option[ $addon ]['cookie_type'] ) ) {
99
+ return $option[ $addon ]['cookie_type'];
100
+ }
101
+
102
+ return $default;
103
+ }
104
+
105
+ /**
106
+ * Returns addons one by one through a generator
107
+ *
108
+ * @return array
109
+ * @throws \DI\DependencyException
110
+ * @throws \DI\NotFoundException
111
+ *
112
+ * @since 1.3.0
113
+ */
114
+ public function get_addons() {
115
+ $addons = array();
116
+
117
+ foreach ( $this->container->get( 'plugins' ) as $addon ) {
118
+ $addons[] = $this->container->get( $addon->class );
119
+ }
120
+
121
+ return $addons;
122
+ }
123
+
124
+ /**
125
+ * Returns active addons
126
+ *
127
+ * @return array
128
+ * @throws \DI\DependencyException
129
+ * @throws \DI\NotFoundException
130
+ *
131
+ * @since 1.3.0
132
+ */
133
+ public function get_active_addons() {
134
+ $active_addons = array();
135
+
136
+ foreach ( $this->get_addons() as $addon ) {
137
+ /**
138
+ * Load addon code if the plugin is active and addon is activated
139
+ */
140
+ if ( $addon->is_addon_enabled() && $addon->is_addon_installed() && $addon->is_addon_activated() ) {
141
+ $active_addons[] = $addon;
142
+ }
143
+ }
144
+
145
+ return $active_addons;
146
+ }
147
+
148
+ /**
149
+ * Returns widget cookie types
150
+ *
151
+ * @param $option_key
152
+ * @param $widget
153
+ * @param array $default
154
+ *
155
+ * @return array
156
+ *
157
+ * @since 1.3.0
158
+ */
159
+ public function get_widget_cookie_types( $option_key, $widget, $default = array() ) {
160
+ $option = get_option( $option_key );
161
+
162
+ if ( isset( $option[ $widget ]['cookie_type'] ) && is_array( $option[ $widget ]['cookie_type'] ) ) {
163
+ return $option[ $widget ]['cookie_type'];
164
+ }
165
+
166
+ return $default;
167
+ }
168
+
169
+ /**
170
+ * Is widget enabled
171
+ *
172
+ * @param $option_key
173
+ * @param $widget
174
+ *
175
+ * @return bool
176
+ */
177
+ public function is_widget_enabled( $option_key, $widget ) {
178
+ $option = get_option( $option_key );
179
+
180
+ if ( isset( $option[ $widget ] ) && ! isset( $option[ $widget ]['enabled'] ) ) {
181
+ return false;
182
+ }
183
+
184
+ return true;
185
+ }
186
+
187
+ /**
188
+ * Is placeholder enabled for a widget
189
+ *
190
+ * @param $option_key
191
+ * @param $widget
192
+ *
193
+ * @return bool
194
+ */
195
+ public function is_widget_placeholder_enabled( $option_key, $widget ) {
196
+ $option = get_option( $option_key );
197
+
198
+ if ( isset( $option[ $widget ] ) && ! isset( $option[ $widget ]['placeholder']['enabled'] ) ) {
199
+ return false;
200
+ }
201
+
202
+ return true;
203
+ }
204
+
205
+ /**
206
+ * Checks if addon has placeholders
207
+ *
208
+ * @param $option_key
209
+ *
210
+ * @return bool
211
+ *
212
+ * @since 1.8.0
213
+ */
214
+ public function widget_has_placeholder( $option_key, $widget_key ) {
215
+ $option = get_option( $option_key );
216
+
217
+ if ( isset( $option[ $widget_key ]['placeholder']['languages'] ) ) {
218
+ return true;
219
+ }
220
+
221
+ return false;
222
+ }
223
+
224
+ /**
225
+ * Returns widget placeholders
226
+ *
227
+ * @param $option_key
228
+ * @param $widget_key
229
+ *
230
+ * @return bool
231
+ *
232
+ * @since 1.8.0
233
+ */
234
+ public function get_widget_placeholders( $option_key, $widget_key ) {
235
+ $option = get_option( $option_key );
236
+
237
+ if ( isset( $option[ $widget_key ]['placeholder']['languages'] ) ) {
238
+ return $option[ $widget_key ]['placeholder']['languages'];
239
+ }
240
+
241
+ return false;
242
+ }
243
+
244
+ /**
245
+ * Returns all placeholders
246
+ *
247
+ * @param $option_key
248
+ *
249
+ * @return bool
250
+ *
251
+ * @since 1.8.0
252
+ */
253
+ public function get_placeholders( $option_key ) {
254
+ $option = get_option( static::OPTION_NAME );
255
+
256
+ if ( isset( $option[ $option_key ]['placeholder']['languages'] ) ) {
257
+ return $option[ $option_key ]['placeholder']['languages'];
258
+ }
259
+
260
+ return false;
261
+ }
262
+
263
+ /**
264
+ * Checks if addon has placeholders
265
+ *
266
+ * @param $option_key
267
+ *
268
+ * @return bool
269
+ *
270
+ * @since 1.8.0
271
+ */
272
+ public function has_placeholder( $option_key ) {
273
+ $option = get_option( static::OPTION_NAME );
274
+
275
+ if ( isset( $option[ $option_key ]['placeholder']['languages'] ) ) {
276
+ return true;
277
+ }
278
+
279
+ return false;
280
+ }
281
+
282
+ /**
283
+ * returns true if the addon placeholder is enabled
284
+ *
285
+ * @param $option_key
286
+ *
287
+ * @return bool
288
+ *
289
+ * @since 1.8.0
290
+ */
291
+ public function is_placeholder_enabled( $option_key ) {
292
+ $option = get_option( static::OPTION_NAME );
293
+
294
+ if ( isset( $option[ $option_key ]['placeholder']['enabled'] ) ) {
295
+ return true;
296
+ }
297
+
298
+ return false;
299
+ }
300
+
301
+ /**
302
+ * returns the placeholder if it does exist
303
+ *
304
+ * @param $option_key
305
+ * @param $default_placeholder
306
+ * @param $cookies
307
+ *
308
+ * @return bool|mixed
309
+ *
310
+ * @since 1.8.0
311
+ */
312
+ public function get_placeholder( $option_key, $default_placeholder, $cookies, $src = '' ) {
313
+ $option = get_option( static::OPTION_NAME );
314
+
315
+ if ( isset( $option[ $option_key ]['placeholder']['enabled'] ) ) {
316
+ return $this->get_translated_placeholder( $option, $option_key, $default_placeholder, $cookies, $src );
317
+ }
318
+
319
+ return false;
320
+ }
321
+
322
+ /**
323
+ * returns the placeholder if it does exist
324
+ *
325
+ * @param $option_key
326
+ * @param $default_placeholder
327
+ * @param $cookies
328
+ *
329
+ * @return bool|mixed
330
+ *
331
+ * @since 1.8.0
332
+ */
333
+ public function get_widget_placeholder( $option_key, $widget_key, $default_placeholder, $cookies = '' ) {
334
+ $option = get_option( $option_key );
335
+
336
+ if ( isset( $option[ $widget_key ]['placeholder']['enabled'] ) ) {
337
+ return $this->get_translated_placeholder( $option, $widget_key, $default_placeholder, $cookies );
338
+ }
339
+
340
+ return false;
341
+ }
342
+
343
+ /**
344
+ * Translates the placeholder text in the current page language
345
+ *
346
+ * @param $option
347
+ * @param $option_key
348
+ * @param $default_placeholder
349
+ * @param $cookies
350
+ * @param string $src
351
+ *
352
+ * @return mixed
353
+ *
354
+ * @since 1.9.0
355
+ */
356
+ private function get_translated_placeholder( $option, $option_key, $default_placeholder, $cookies, $src = '' ) {
357
+ $current_lang = cookiebot_addons_get_language();
358
+
359
+ if ( $current_lang == false || $current_lang == '' ) {
360
+ $current_lang = 'site-default';
361
+ }
362
+
363
+ /**
364
+ * Loop every language and match current language
365
+ */
366
+ if ( isset( $option[ $option_key ]['placeholder']['languages'] ) && is_array( $option[ $option_key ]['placeholder']['languages'] ) ) {
367
+ foreach ( $option[ $option_key ]['placeholder']['languages'] as $key => $value ) {
368
+
369
+ /**
370
+ * if current lang match with the prefix language in the database then get the text
371
+ */
372
+ if ( $key == $current_lang ) {
373
+ return $this->placeholder_merge_tag( $option[ $option_key ]['placeholder']['languages'][ $key ], $cookies, $src );
374
+ }
375
+ }
376
+ }
377
+
378
+ /**
379
+ * Returns site-default text if no match found.
380
+ */
381
+ if ( isset( $option[ $option_key ]['placeholder']['languages']['site-default'] ) ) {
382
+ return $this->placeholder_merge_tag( $option[ $option_key ]['placeholder']['languages']['site-default'], $cookies, $src );
383
+ }
384
+
385
+ /**
386
+ * Returns addon default placeholder (code)
387
+ */
388
+ return $this->placeholder_merge_tag( $default_placeholder, $cookies, $src );
389
+ }
390
+
391
+ /**
392
+ * Merges placeholder tags with values
393
+ *
394
+ * @param $placeholder
395
+ * @param $cookies
396
+ *
397
+ * @return mixed
398
+ *
399
+ * @since 1.8.0
400
+ */
401
+ private function placeholder_merge_tag( $placeholder, $cookies, $src ) {
402
+ if ( strpos( $placeholder, '%cookie_types' ) !== false ) {
403
+ $placeholder = str_replace( '%cookie_types', $cookies, $placeholder );
404
+ }
405
+
406
+ if ( strpos( $placeholder, '%src' ) !== false ) {
407
+ $placeholder = str_replace( '%src', $src, $placeholder );
408
+ }
409
+
410
+ if ( strpos( $placeholder, '[renew_consent]' ) !== false ) {
411
+ $placeholder = str_replace( '[renew_consent]', '<a href="javascript:Cookiebot.renew()">', $placeholder );
412
+ }
413
+
414
+ if ( strpos( $placeholder, '[/renew_consent]' ) !== false ) {
415
+ $placeholder = str_replace( '[/renew_consent]', '</a>', $placeholder );
416
+ }
417
+
418
+ return $placeholder;
419
+ }
420
+
421
+ /**
422
+ * returns true if the "remove tag" option is enabled
423
+ *
424
+ * @param $option_key
425
+ *
426
+ * @return bool
427
+ *
428
+ * @since 2.1.0
429
+ */
430
+ public function is_remove_tag_enabled( $option_key ) {
431
+ //Always return false if COOKIEBOT_OPTION_REMOVE_TAG
432
+ if ( ! defined( 'COOKIEBOT_OPTION_REMOVE_TAG' ) || ! COOKIEBOT_OPTION_REMOVE_TAG ) {
433
+ return false;
434
+ }
435
+
436
+ $option = get_option( static::OPTION_NAME );
437
+
438
+ if ( isset( $option[ $option_key ]['remove_tag'] ) ) {
439
+ return true;
440
+ }
441
+
442
+ return false;
443
+ }
444
+
445
+ /**
446
+ * returns true if the "remove tag" option is enabled
447
+ *
448
+ * @param $option_key
449
+ * @param $widget_key
450
+ *
451
+ * @return bool
452
+ *
453
+ * @since 2.1.0
454
+ */
455
+ public function is_widget_remove_tag_enabled( $option_key, $widget_key ) {
456
+ //Always return false if COOKIEBOT_OPTION_REMOVE_TAG
457
+ if ( ! defined( 'COOKIEBOT_OPTION_REMOVE_TAG' ) || ! COOKIEBOT_OPTION_REMOVE_TAG ) {
458
+ return false;
459
+ }
460
+
461
+ $option = get_option( $option_key );
462
+
463
+ if ( isset( $option[ $widget_key ]['remove_tag'] ) ) {
464
+ return true;
465
+ }
466
+
467
+ return false;
468
+ }
469
+
470
+ /**
471
+ * Check if the previous version is active
472
+ *
473
+ * @param $addons array List of addons
474
+ * @param $addon_class string The name of the class
475
+ *
476
+ * @return bool
477
+ *
478
+ * @since 2.1.3
479
+ */
480
+ public function is_previous_version_active( $addons, $addon_class ) {
481
+ foreach ( $addons as $addon ) {
482
+ $parent_class = $addon->get_parent_class();
483
+
484
+ if ( $parent_class !== false ) {
485
+ if ( $parent_class == $addon_class ) {
486
+ if ( $addon->is_addon_activated() ) {
487
+ return true;
488
+ }
489
+ }
490
+ }
491
+ }
492
+
493
+ return false;
494
+ }
495
+
496
+ /**
497
+ * Checks if the addon is the latest plugin version.
498
+ * Latest plugin version doesn't have extended class.
499
+ *
500
+ * @param $addon
501
+ *
502
+ * @return bool
503
+ *
504
+ * @since 2.1.3
505
+ */
506
+ public function is_latest_plugin_version( $addon ) {
507
+ return ( get_parent_class( $addon ) === false ) ? true : false;
508
+ }
509
+
510
+ /**
511
+ * Check if the addon option name matchs with the parameter
512
+ * then run the post_hook_after_enabling function in the addon class.
513
+ *
514
+ * @param $addon_option_name string Addon option name
515
+ *
516
+ * @throws \DI\DependencyException
517
+ * @throws \DI\NotFoundException
518
+ *
519
+ * @since 2.2.0
520
+ */
521
+ public function post_hook_after_enabling_addon_on_settings_page( $addon_option_name ) {
522
+ $addons = $this->get_addons();
523
+
524
+ foreach( $addons as $addon ) {
525
+ if( $addon->get_option_name() == $addon_option_name ) {
526
+ $addon->post_hook_after_enabling();
527
+ }
528
+ }
529
+ }
530
+
531
+ /**
532
+ * The cookiebot plugin is deactivated
533
+ * so run this function to cleanup the addons.
534
+ *
535
+ * @since 2.2.0
536
+ */
537
+ public function cookiebot_deactivated() {
538
+ foreach( $this->get_active_addons() as $addon ) {
539
+ $addon->plugin_deactivated();
540
+ }
541
+ }
542
+ }
addons/style/css/admin_styles.css ADDED
@@ -0,0 +1,144 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .cookiebot-addon.postbox {
2
+ padding: 12px 0 12px 15px;
3
+ }
4
+
5
+ .cookiebot-addon.postbox h2 {
6
+ padding-top: 0;
7
+ padding-bottom: 10px;
8
+ margin: 0;
9
+ font-size: 16px;
10
+ }
11
+
12
+ form.not_installed_plugins p.submit {
13
+ display: none;
14
+ }
15
+
16
+ ul.cookietypes li {
17
+ display: inline;
18
+ }
19
+
20
+ .placeholder {
21
+ margin: 0 15px 15px 0;
22
+ background: #EEE;
23
+ padding: 15px;
24
+ }
25
+
26
+ .placeholder_enable,
27
+ .placeholder_select_div {
28
+ width: 100%;
29
+ display: block;
30
+ }
31
+
32
+ div.extra_information {
33
+ font-weight: 400;
34
+ }
35
+
36
+ .placeholder_content .textarea {
37
+ display: flex;
38
+ }
39
+
40
+ /**
41
+ * Help Tip
42
+ */
43
+ .help-tip {
44
+ color: #666;
45
+ display: inline-block;
46
+ font-size: 1.5em;
47
+ font-style: normal;
48
+ height: 16px;
49
+ line-height: 16px;
50
+ position: relative;
51
+ vertical-align: middle;
52
+ width: 16px
53
+ }
54
+
55
+ .help-tip::after {
56
+ font-family: Dashicons;
57
+ speak: none;
58
+ font-weight: 400;
59
+ font-variant: normal;
60
+ text-transform: none;
61
+ line-height: 1;
62
+ -webkit-font-smoothing: antialiased;
63
+ margin: 0;
64
+ text-indent: 0;
65
+ position: absolute;
66
+ top: 0;
67
+ left: 0;
68
+ width: 100%;
69
+ height: 100%;
70
+ text-align: center;
71
+ content: "";
72
+ cursor: help
73
+ }
74
+
75
+ #tiptip_holder{
76
+ position: absolute;
77
+ top: 0;
78
+ }
79
+
80
+ #tiptip_holder.tip_top {
81
+ padding-bottom: 5px
82
+ }
83
+
84
+ #tiptip_holder.tip_top #tiptip_arrow_inner {
85
+ margin-top: -7px;
86
+ margin-left: -6px;
87
+ border-top-color: #333
88
+ }
89
+
90
+ #tiptip_holder.tip_bottom {
91
+ padding-top: 5px
92
+ }
93
+
94
+ #tiptip_holder.tip_bottom #tiptip_arrow_inner {
95
+ margin-top: -5px;
96
+ margin-left: -6px;
97
+ border-bottom-color: #333
98
+ }
99
+
100
+ #tiptip_holder.tip_right {
101
+ padding-left: 5px
102
+ }
103
+
104
+ #tiptip_holder.tip_right #tiptip_arrow_inner {
105
+ margin-top: -6px;
106
+ margin-left: -5px;
107
+ border-right-color: #333
108
+ }
109
+
110
+ #tiptip_holder.tip_left {
111
+ padding-right: 5px
112
+ }
113
+
114
+ #tiptip_holder.tip_left #tiptip_arrow_inner {
115
+ margin-top: -6px;
116
+ margin-left: -7px;
117
+ border-left-color: #333
118
+ }
119
+
120
+ #tiptip_content, .chart-tooltip, .wc_error_tip {
121
+ color: #fff;
122
+ font-size: .8em;
123
+ max-width: 300px;
124
+ background: #333;
125
+ text-align: center;
126
+ border-radius: 3px;
127
+ padding: .618em 1em;
128
+ -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, .2);
129
+ box-shadow: 0 1px 3px rgba(0, 0, 0, .2)
130
+ }
131
+
132
+ #tiptip_content code, .chart-tooltip code, .wc_error_tip code {
133
+ padding: 1px;
134
+ background: #888
135
+ }
136
+
137
+ #tiptip_arrow, #tiptip_arrow_inner {
138
+ position: absolute;
139
+ border-color: transparent;
140
+ border-style: solid;
141
+ border-width: 6px;
142
+ height: 0;
143
+ width: 0
144
+ }
addons/tests/bootstrap.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHPUnit bootstrap file
4
+ *
5
+ * @package Klasse_Plugin_Boilerplate
6
+ */
7
+ //
8
+ $_tests_dir = getenv( 'WP_TESTS_DIR' );
9
+
10
+ if ( ! $_tests_dir ) {
11
+ $_tests_dir = '/tmp/wordpress-tests-lib';
12
+ }
13
+
14
+ define( 'PLUGIN_NAME', 'cookiebot-addons.php' );
15
+ define( 'PLUGIN_FOLDER', basename( dirname( __DIR__ ) ) );
16
+ define( 'PLUGIN_PATH', PLUGIN_FOLDER . '/' . PLUGIN_NAME );
17
+
18
+ // Activates this plugin in WordPress so it can be tested.
19
+ $GLOBALS['wp_tests_options'] = array(
20
+ 'active_plugins' => array( PLUGIN_PATH ),
21
+ );
22
+
23
+ // Give access to tests_add_filter() function.
24
+ require_once $_tests_dir . '/includes/functions.php';
25
+
26
+ /**
27
+ * Manually load the plugin being tested.
28
+ */
29
+ function _manually_load_plugin() {
30
+ // plugin
31
+ require dirname( dirname( __FILE__ ) ) . '/cookiebot-addons-init.php';
32
+ }
33
+
34
+ tests_add_filter( 'muplugins_loaded', '_manually_load_plugin' );
35
+
36
+ // Start up the WP testing environment.
37
+ require $_tests_dir . '/includes/bootstrap.php';
addons/tests/integration/addons/test-add-to-any.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\tests\integration\addons;
4
+
5
+ class Test_Add_To_Any extends \WP_UnitTestCase {
6
+
7
+ /**
8
+ * This will cover the existince of the wp_enqueue_script addtoany
9
+ *
10
+ * @covers \cookiebot_addons\controller\addons\add_to_any\Add_To_Any
11
+ *
12
+ * @since 2.1.0
13
+ */
14
+ public function test_script_loader_tag_addtoany() {
15
+ $content = file_get_contents( 'http://plugins.svn.wordpress.org/add-to-any/trunk/add-to-any.php' );
16
+
17
+ $this->assertNotFalse( strpos( $content, "wp_enqueue_script( 'addtoany'" ) );
18
+ }
19
+ }
addons/tests/integration/addons/test-caos-host-analyticsjs-local-save-ga-local.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\tests\integration\addons;
4
+
5
+ class Test_Caos_Host_Analyticsjs_Local_Save_Ga_Local extends \WP_UnitTestCase {
6
+
7
+ /**
8
+ * This will validate if the hook "caos_analytics_render_tracking_code" still exists
9
+ *
10
+ * @covers \cookiebot_addons\controller\addons\add_to_any\Add_To_Any
11
+ *
12
+ * @since 2.1.0
13
+ */
14
+ public function test_host_analyticsjs_local() {
15
+ $content = file_get_contents( 'http://plugins.svn.wordpress.org/host-analyticsjs-local/tags/2.0.0/save-ga-local.php' );
16
+
17
+ $this->assertNotFalse( strpos( $content,
18
+ 'add_action(\'wp_footer\', \'caos_analytics_render_tracking_code\', $sgal_enqueue_order);' ) );
19
+ $this->assertNotFalse( strpos( $content,
20
+ 'add_action(\'wp_head\', \'caos_analytics_render_tracking_code\', $sgal_enqueue_order);' ) );
21
+ }
22
+ }
addons/tests/integration/addons/test-caos-host-analyticsjs-local.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\tests\integration\addons;
4
+
5
+ class Test_Caos_Host_Analyticsjs_Local extends \WP_UnitTestCase {
6
+
7
+ /**
8
+ * This will validate if the hook "caos_analytics_render_tracking_code" still exists
9
+ *
10
+ * @covers \cookiebot_addons\controller\addons\add_to_any\Add_To_Any
11
+ *
12
+ * @since 2.1.0
13
+ */
14
+ public function test_host_analyticsjs_local() {
15
+ $content = file_get_contents( 'http://plugins.svn.wordpress.org/host-analyticsjs-local/trunk/host-analyticsjs-local.php' );
16
+
17
+ $this->assertNotFalse( strpos( $content,
18
+ 'add_action(\'wp_footer\', \'caos_analytics_render_tracking_code\', $sgal_enqueue_order);' ) );
19
+ $this->assertNotFalse( strpos( $content,
20
+ 'add_action(\'wp_head\', \'caos_analytics_render_tracking_code\', $sgal_enqueue_order);' ) );
21
+ }
22
+ }
addons/tests/integration/addons/test-custom-facebook-feed.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\tests\integration\addons;
4
+
5
+ class Test_Custom_Facebook_Feed extends \WP_UnitTestCase {
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 = file_get_contents( '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
+ }
addons/tests/integration/addons/test-facebook-for-woocommerce.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\tests\integration\addons;
4
+
5
+ class Test_Facebook_For_Woocommerce extends \WP_UnitTestCase {
6
+
7
+ public function setUp() {
8
+
9
+ }
10
+
11
+ /**
12
+ * @covers \cookiebot_addons\controller\addons\facebook_for_woocommerce\Facebook_For_Woocommerce
13
+ */
14
+ public function test_facebook_for_woocommerce_main_file() {
15
+ $content = file_get_contents( 'https://raw.githubusercontent.com/facebookincubator/facebook-for-woocommerce/master/facebook-commerce.php' );
16
+
17
+ $this->assertNotFalse( strpos( $content, 'WC_Facebookcommerce' ) );
18
+ }
19
+
20
+ /**
21
+ * @covers \cookiebot_addons\controller\addons\facebook_for_woocommerce\Facebook_For_Woocommerce
22
+ */
23
+ public function test_facebook_for_woocommerce_hooks() {
24
+ $content = file_get_contents( 'https://raw.githubusercontent.com/facebookincubator/facebook-for-woocommerce/master/facebook-commerce-events-tracker.php' );
25
+
26
+ $this->assertNotFalse( strpos( $content, 'add_action(\'wp_head\', array($this, \'apply_filters\'));' ) );
27
+ $this->assertNotFalse( strpos( $content, 'add_action(\'woocommerce_after_single_product' ) );
28
+ $this->assertNotFalse( strpos( $content, 'add_action(\'woocommerce_after_shop_loop' ) );
29
+ $this->assertNotFalse( strpos( $content, 'add_action(\'pre_get_posts' ) );
30
+ $this->assertNotFalse( strpos( $content, 'add_action(\'woocommerce_after_cart' ) );
31
+ $this->assertNotFalse( strpos( $content, 'add_action(\'woocommerce_add_to_cart' ) );
32
+ $this->assertNotFalse( strpos( $content, 'add_action(\'wc_ajax_fb_inject_add_to_cart_event' ) );
33
+ $this->assertNotFalse( strpos( $content, 'add_action(\'woocommerce_after_checkout_form' ) );
34
+ $this->assertNotFalse( strpos( $content, 'add_action(\'woocommerce_thankyou' ) );
35
+ $this->assertNotFalse( strpos( $content, 'add_action(\'woocommerce_payment_complete' ) );
36
+ }
37
+ }
addons/tests/integration/addons/test-ga-google-analytics.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\tests\integration\addons;
4
+
5
+ class Test_Ga_Google_Analytics extends \WP_UnitTestCase {
6
+
7
+ public function setUp() {
8
+
9
+ }
10
+
11
+ /**
12
+ * This will validate if the hook "ga_google_analytics_tracking_code" still exists
13
+ *
14
+ * @since 2.1.0
15
+ */
16
+ public function test_host_analyticsjs_local() {
17
+ $content = file_get_contents( 'http://plugins.svn.wordpress.org/ga-google-analytics/trunk/inc/plugin-core.php' );
18
+
19
+ $this->assertNotFalse( strpos( $content, 'ga_google_analytics_tracking_code') );
20
+ }
21
+ }
addons/tests/integration/addons/test-gadwp.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\tests\integration\addons;
4
+
5
+ class Test_Gadwp extends \WP_UnitTestCase {
6
+
7
+ public function setUp() {
8
+
9
+ }
10
+
11
+ /**
12
+ * This will validate if the hooks for "google_analytics" still exists
13
+ *
14
+ * @since 2.1.0
15
+ */
16
+ public function test_hooks() {
17
+ $content = file_get_contents( 'http://plugins.svn.wordpress.org/google-analytics-dashboard-for-wp/trunk/front/views/tagmanager-code.php' );
18
+
19
+ $this->assertNotFalse( strpos( $content, 'https://www.googletagmanager.com') );
20
+
21
+ $content = file_get_contents( 'http://plugins.svn.wordpress.org/google-analytics-dashboard-for-wp/trunk/front/views/analytics-optout-code.php' );
22
+
23
+ $this->assertNotFalse( strpos( $content, 'ga-disable-') );
24
+
25
+ $content = file_get_contents( 'http://plugins.svn.wordpress.org/google-analytics-dashboard-for-wp/trunk/front/views/analytics-code.php' );
26
+
27
+ $this->assertNotFalse( strpos( $content, 'tracking_script_path') );
28
+ }
29
+ }
addons/tests/integration/addons/test-google-analyticator.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\tests\integration\addons;
4
+
5
+ class Test_Google_Analyticator extends \WP_UnitTestCase {
6
+
7
+ public function setUp() {
8
+
9
+ }
10
+
11
+ /**
12
+ * This will validate if the hooks for "google_analyticator" still exists
13
+ *
14
+ * @since 2.1.1
15
+ */
16
+ public function test_hooks() {
17
+ $content = file_get_contents( 'http://plugins.svn.wordpress.org/google-analyticator/trunk/google-analyticator.php' );
18
+
19
+ $this->assertNotFalse( strpos( $content, 'add_action(\'wp_print_scripts\', \'ga_external_tracking_js\',99999);') );
20
+ $this->assertNotFalse( strpos( $content, 'add_action(\'login_head\', \'add_google_analytics\', 99);') );
21
+ $this->assertNotFalse( strpos( $content, 'add_action(\'wp_head\', \'add_google_analytics\',99);') );
22
+ $this->assertNotFalse( strpos( $content, 'wp_enqueue_script(\'ga-external-tracking\', plugins_url') );
23
+ }
24
+ }
addons/tests/integration/addons/test-google-analytics-plus.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\tests\integration\addons;
4
+
5
+ class Test_Google_Analytics_Async extends \WP_UnitTestCase {
6
+
7
+ public function setUp() {
8
+
9
+ }
10
+
11
+ /**
12
+ * This will validate if the hook for "google_analytics_async" still exists
13
+ *
14
+ * @since 2.1.0
15
+ */
16
+ public function test_hooks() {
17
+ $file = WP_PLUGIN_DIR . '/google-analytics-async/google-analytics-async.php';
18
+
19
+ if( file_exists( $file ) ) {
20
+ $content = file_get_contents( $file );
21
+
22
+ $this->assertNotFalse( strpos( $content, 'add_action( \'wp_head\', array( &$this, \'tracking_code_output\' ) );') );
23
+ }
24
+ }
25
+ }
addons/tests/integration/addons/test-google-analytics.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\tests\integration\addons;
4
+
5
+ class Test_Google_Analytics extends \WP_UnitTestCase {
6
+
7
+ public function setUp() {
8
+
9
+ }
10
+
11
+ /**
12
+ * This will validate if the hooks for "google_analytics" still exists
13
+ *
14
+ * @since 2.1.0
15
+ */
16
+ public function test_hooks() {
17
+ $content = file_get_contents( 'http://plugins.svn.wordpress.org/googleanalytics/trunk/class/Ga_Frontend.php' );
18
+
19
+ $this->assertNotFalse( strpos( $content, 'add_action( \'wp_footer\', \'Ga_Frontend::insert_ga_script\' );') );
20
+ $this->assertNotFalse( strpos( $content, 'add_action( \'wp_enqueue_scripts\', \'Ga_Frontend::platform_sharethis\' );') );
21
+ }
22
+ }
addons/tests/integration/addons/test-hubspot-leadin.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\tests\integration\addons;
4
+
5
+ class Test_Hubspot_Leadin extends \WP_UnitTestCase {
6
+
7
+ public function setUp() {
8
+
9
+ }
10
+
11
+ /**
12
+ * This will validate if the hook for "hubspot_leadin" still exists
13
+ *
14
+ * @since 2.1.0
15
+ */
16
+ public function test_hook() {
17
+ $content = file_get_contents( 'http://plugins.svn.wordpress.org/leadin/trunk/inc/class-leadin.php' );
18
+
19
+ $this->assertNotFalse( strpos( $content, '$embedId = \'leadin-scriptloader-js\';') );
20
+ }
21
+ }
addons/tests/integration/addons/test-hubspot-tracking-code.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\tests\integration\addons;
4
+
5
+ class Test_Hubspot_Tracking_Code extends \WP_UnitTestCase {
6
+
7
+ public function setUp() {
8
+
9
+ }
10
+
11
+ /**
12
+ * This will validate if the hook for "hubspot_tracking_code" still exists
13
+ *
14
+ * @since 2.1.0
15
+ */
16
+ public function test_hubspot_tracking_code() {
17
+ $content = file_get_contents( 'http://plugins.svn.wordpress.org/hubspot-tracking-code/trunk/inc/class-hubspot-tracking-code-analytics.php' );
18
+
19
+ $this->assertNotFalse( strpos( $content, '<script type="text/javascript" id="hs-script-loader"') );
20
+ }
21
+ }
addons/tests/integration/addons/test-instagram-feed.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\tests\integration\addons;
4
+
5
+ class Test_Instagram_Feed extends \WP_UnitTestCase {
6
+
7
+ public function setUp() {
8
+
9
+ }
10
+
11
+ /**
12
+ * This will validate if the hook "instagram_feed" still exists
13
+ *
14
+ * @since 2.1.0
15
+ */
16
+ public function test_instagram_feed() {
17
+ $content = file_get_contents( 'http://plugins.svn.wordpress.org/instagram-feed/trunk/instagram-feed.php' );
18
+
19
+ $this->assertNotFalse( strpos( $content, 'add_action( \'wp_enqueue_scripts\', \'sb_instagram_scripts_enqueue\' );') );
20
+ }
21
+ }
addons/tests/integration/addons/test-jetpack-facebook-widget.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\tests\integration\addons;
4
+
5
+ class Test_Jetpack_Facebook_Widget extends \WP_UnitTestCase {
6
+
7
+ public function setUp() {
8
+
9
+ }
10
+
11
+ /**
12
+ * This will validate if the hook "jetpack facebook widget" still exists
13
+ *
14
+ * @since 2.1.0
15
+ */
16
+ public function test_facebook_widget() {
17
+ $content = file_get_contents( 'http://plugins.svn.wordpress.org/jetpack/trunk/class.jetpack.php' );
18
+
19
+ $this->assertNotFalse( strpos( $content, 'wp_register_script(
20
+ \'jetpack-facebook-embed\'') );
21
+ }
22
+ }
addons/tests/integration/addons/test-jetpack-goodreads-widget.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\tests\integration\addons;
4
+
5
+ class Test_Jetpack_Goodreads_Widget extends \WP_UnitTestCase {
6
+
7
+ public function setUp() {
8
+
9
+ }
10
+
11
+ /**
12
+ * This will validate if the hook "jetpack goodreads widget" still exists
13
+ *
14
+ * @since 2.1.0
15
+ */
16
+ public function test_goodreads_widget() {
17
+ $content = file_get_contents( 'http://plugins.svn.wordpress.org/jetpack/trunk/modules/widgets/goodreads.php' );
18
+
19
+ $this->assertNotFalse( strpos( $content, 'parent::__construct(
20
+ \'wpcom-goodreads\'') );
21
+ }
22
+ }
addons/tests/integration/addons/test-jetpack-google-maps-widget.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\tests\integration\addons;
4
+
5
+ class Test_Jetpack_Google_Maps_Widget extends \WP_UnitTestCase {
6
+
7
+ public function setUp() {
8
+
9
+ }
10
+
11
+ /**
12
+ * This will validate if the hook "jetpack google maps widget" still exists
13
+ *
14
+ * @since 2.1.0
15
+ */
16
+ public function test_google_maps_widget() {
17
+ $content = file_get_contents('http://plugins.svn.wordpress.org/jetpack/trunk/modules/widgets/contact-info.php');
18
+
19
+ $this->assertNotFalse( strpos( $content, 'do_action( \'jetpack_contact_info_widget_start\' );' ) );
20
+ $this->assertNotFalse( strpos( $content, 'do_action( \'jetpack_contact_info_widget_end\' );' ) );
21
+ $this->assertNotFalse( strpos( $content, 'do_action( \'jetpack_stats_extra\', \'widget_view\', \'contact_info\' );' ) );
22
+ }
23
+ }
addons/tests/integration/addons/test-jetpack-googleplus-badge-widget.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\tests\integration\addons;
4
+
5
+ class Test_Jetpack_Googleplus_Badge_Widget extends \WP_UnitTestCase {
6
+
7
+ public function setUp() {
8
+
9
+ }
10
+
11
+ /**
12
+ * This will validate if the hook "jetpack googleplus badge widget" still exists
13
+ *
14
+ * @since 2.1.0
15
+ */
16
+ public function test_googleplus_badge_widget() {
17
+ $content = file_get_contents('http://plugins.svn.wordpress.org/jetpack/tags/6.9/modules/widgets/googleplus-badge.php');
18
+
19
+ $this->assertNotFalse( strpos( $content, 'wp_enqueue_script( \'googleplus-widget\',' ) );
20
+ }
21
+ }
addons/tests/integration/addons/test-jetpack-internet-defense-league-widget.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\tests\integration\addons;
4
+
5
+ class Test_Jetpack_Internet_Defense_League_Widget extends \WP_UnitTestCase {
6
+
7
+ public function setUp() {
8
+
9
+ }
10
+
11
+ /**
12
+ * This will validate if the hook "jetpack internet defense league widget" still exists
13
+ *
14
+ * @since 2.1.0
15
+ */
16
+ public function test_internet_defense_league_widget() {
17
+ $content = file_get_contents('http://plugins.svn.wordpress.org/jetpack/trunk/modules/widgets/internet-defense-league.php');
18
+
19
+ $this->assertNotFalse( strpos( $content, 'add_action( \'wp_footer\', array( $this, \'footer_script\' ) );' ) );
20
+ }
21
+ }
addons/tests/integration/addons/test-jetpack-twitter-timeline-widget.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\tests\integration\addons;
4
+
5
+ class Test_Jetpack_Twitter_Timeline_Widget extends \WP_UnitTestCase {
6
+
7
+ public function setUp() {
8
+
9
+ }
10
+
11
+ /**
12
+ * This will validate if the hook "jetpack twitter timeline widget" still exists
13
+ *
14
+ * @since 2.1.0
15
+ */
16
+ public function test_twitter_timeline_widget() {
17
+ $content = file_get_contents('http://plugins.svn.wordpress.org/jetpack/trunk/modules/widgets/twitter-timeline.php');
18
+
19
+ $this->assertNotFalse( strpos( $content, 'wp_enqueue_script( \'jetpack-twitter-timeline\' );' ) );
20
+ }
21
+ }
addons/tests/integration/addons/test-ninja-forms.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\tests\integration\addons;
4
+
5
+ class Test_Ninja_Forms extends \WP_UnitTestCase {
6
+
7
+ public function setUp() {
8
+
9
+ }
10
+
11
+ /**
12
+ * This will validate if the hook "ninja_forms" still exists
13
+ *
14
+ * @since 2.1.0
15
+ */
16
+ public function test_host_analyticsjs_local() {
17
+ $content = file_get_contents( 'http://plugins.svn.wordpress.org/ninja-forms/trunk/includes/Display/Render.php' );
18
+
19
+ $this->assertNotFalse( strpos( $content, 'wp_enqueue_script(\'nf-google-recaptcha\'') );
20
+ }
21
+ }
addons/tests/integration/addons/test-optinmonster.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\tests\integration\addons;
4
+
5
+ class Test_Optinmonster extends \WP_UnitTestCase {
6
+
7
+ public function setUp() {
8
+
9
+ }
10
+
11
+ /**
12
+ * This will validate if the hook "api-scripts" still exists
13
+ *
14
+ * @since 2.1.0
15
+ */
16
+ public function test_optinmonster() {
17
+ $content = file_get_contents( 'http://plugins.svn.wordpress.org/optinmonster/trunk/OMAPI/Output.php' );
18
+
19
+ $this->assertNotFalse( strpos( $content, 'add_action( \'wp_enqueue_scripts\', array( $this, \'api_script\' ) );') );
20
+ }
21
+ }
addons/tests/integration/addons/test-pixel-caffeine.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\tests\integration\addons;
4
+
5
+ class Test_Pixel_Caffeine extends \WP_UnitTestCase {
6
+
7
+ public function setUp() {
8
+
9
+ }
10
+
11
+ /**
12
+ * This will validate if the hooks "pixel_caffeine" still exists
13
+ *
14
+ * @since 2.1.0
15
+ */
16
+ public function test_pixel_caffeine() {
17
+ $content = file_get_contents( 'http://plugins.svn.wordpress.org/pixel-caffeine/trunk/includes/class-aepc-pixel-scripts.php' );
18
+
19
+ $this->assertNotFalse( strpos( $content, 'add_action( \'wp_head\', array( __CLASS__, \'pixel_init\' ), 99 );') );
20
+ $this->assertNotFalse( strpos( $content, 'add_action( \'wp_footer\', array( __CLASS__, \'pixel_init\' ), 1 );') );
21
+ $this->assertNotFalse( strpos( $content, 'wp_register_script( \'aepc-pixel-events\',') );
22
+ }
23
+ }
addons/tests/integration/addons/test-wd-google-analytics.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\tests\integration\addons;
4
+
5
+ class Test_Wd_Google_Analytics extends \WP_UnitTestCase {
6
+
7
+ public function setUp() {
8
+
9
+ }
10
+
11
+ /**
12
+ * This will validate if the hooks for "wd_google_analytics" still exists
13
+ *
14
+ * @since 2.1.0
15
+ */
16
+ public function test_wd_google_analytics() {
17
+ $content = file_get_contents( 'http://plugins.svn.wordpress.org/wd-google-analytics/trunk/gawd_class.php' );
18
+
19
+ $this->assertNotFalse( strpos( $content, 'add_action(\'wp_head\', array($this, \'gawd_tracking_code\'), 99);') );
20
+ }
21
+ }
addons/tests/integration/addons/test-wp-analytify.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\tests\integration\addons;
4
+
5
+ class Test_Wp_Analytify extends \WP_UnitTestCase {
6
+
7
+ public function setUp() {
8
+
9
+ }
10
+
11
+ /**
12
+ * This will validate if the hooks for "wp_analytify" still exists
13
+ *
14
+ * @since 2.1.0
15
+ */
16
+ public function test_wp_analytify() {
17
+ $content = file_get_contents( 'http://plugins.svn.wordpress.org/wp-analytify/trunk/wp-analytify.php' );
18
+
19
+ $this->assertNotFalse( strpos( $content, 'add_action( \'wp_head\', array( $this, \'analytify_add_analytics_code\' ) );') );
20
+ }
21
+ }
addons/tests/integration/addons/test-wp-piwik.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\tests\integration\addons;
4
+
5
+ class Test_Wp_Piwik extends \WP_UnitTestCase {
6
+
7
+ public function setUp() {
8
+
9
+ }
10
+
11
+ /**
12
+ * This will validate if the hook "wp_piwik" still exists
13
+ *
14
+ * @since 2.1.0
15
+ */
16
+ public function test_host_analyticsjs_local() {
17
+ $content = file_get_contents( 'http://plugins.svn.wordpress.org/wp-piwik/trunk/classes/WP_Piwik.php' );
18
+
19
+ $this->assertNotFalse( strpos( $content, '\'disableCookies\' => self::$settings->getGlobalOption ( \'disable_cookies\' ) ? 1 : 0') );
20
+ }
21
+ }
addons/tests/integration/test-buffer-priorities.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\tests\integration;
4
+
5
+ class Test_Buffer_Priorities extends \WP_UnitTestCase {
6
+
7
+ public function setUp() {
8
+
9
+ }
10
+
11
+ /**
12
+ * @covers \cookiebot_addons\controller\addons\custom_facebook_feed\Custom_Facebook_Feed
13
+ */
14
+ public function test_custom_facebook_feed() {
15
+ $content = file_get_contents( 'http://plugins.svn.wordpress.org/custom-facebook-feed/trunk/custom-facebook-feed.php' );
16
+
17
+ $this->assertNotFalse( strpos( $content, "add_action( 'wp_footer', 'cff_js' );" ) );
18
+ }
19
+
20
+ /**
21
+ * @covers \cookiebot_addons\controller\addons\caos_host_analyticsjs_local\CAOS_Host_Analyticsjs_Local
22
+ */
23
+ public function test_host_analyticsjs_local() {
24
+ $content = file_get_contents( 'http://plugins.svn.wordpress.org/host-analyticsjs-local/trunk/save-ga-local.php' );
25
+
26
+ $this->assertNotFalse( strpos( $content, 'add_action(\'wp_footer\', \'add_ga_header_script\', $sgal_enqueue_order);' ) );
27
+ $this->assertNotFalse( strpos( $content, 'add_action(\'wp_head\', \'add_ga_header_script\', $sgal_enqueue_order);' ) );
28
+ }
29
+
30
+ /**
31
+ * @covers \cookiebot_addons\controller\addons\ga_google_analytics\Ga_Google_Analytics
32
+ */
33
+ public function test_ga_google_analytics() {
34
+ $content = file_get_contents( 'http://plugins.svn.wordpress.org/ga-google-analytics/trunk/inc/plugin-core.php' );
35
+
36
+ $this->assertNotFalse( strpos( $content, 'add_action(\'wp_head\', $function);' ) );
37
+ $this->assertNotFalse( strpos( $content, 'add_action(\'wp_footer\', $function);' ) );
38
+ }
39
+
40
+ /**
41
+ * @covers \cookiebot_addons|controller\addons\google_analyticator\Google_Analyticator
42
+ */
43
+ // public function test_google_analyticator() {
44
+ // $content = file_get_contents( 'http://plugins.svn.wordpress.org/ga-google-analytics/trunk/inc/plugin-core.php' );
45
+ //
46
+ // $this->assertNotFalse( strpos( $content, 'add_action(\'wp_head\', \'add_google_analytics\',99);' ) );
47
+ // $this->assertNotFalse( strpos( $content, 'add_action(\'login_head\', \'add_google_analytics\', 99);' ) );
48
+ // }
49
+ }
addons/tests/unit/test-addon-file-name.php ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\tests\unit;
4
+
5
+ use DI\ContainerBuilder;
6
+ use DI;
7
+
8
+ class Test_Addon_File_Name extends \WP_UnitTestCase {
9
+ /**
10
+ * The file path of addons json
11
+ *
12
+ * @var string
13
+ */
14
+ protected $file_path;
15
+ /**
16
+ * The list of all addons, json encoded
17
+ *
18
+ * @var string
19
+ */
20
+ protected $file;
21
+
22
+ public function setUp() {
23
+ $this->get_plugins();
24
+ }
25
+
26
+ /**
27
+ * Load the addons through json file.
28
+ */
29
+ private function get_plugins() {
30
+ $this->file_path = dirname( dirname( __DIR__ ) ) . '/addons.json';
31
+ $this->file = file_get_contents( $this->file_path );
32
+ $this->plugins = json_decode( $this->file );
33
+ }
34
+
35
+ /**
36
+ * Validate if the plugins in addons.json do exist as a class in addons controller directory.
37
+ */
38
+ public function test_plugins_are_valid() {
39
+ foreach ( $this->plugins as $plugin ) {
40
+ $check = is_object( $plugin ) && class_exists( $plugin->class );
41
+ $this->assertTrue( $check );
42
+ }
43
+ }
44
+
45
+ public function test_get_svn_url() {
46
+ $settingsMock = $this->getMockBuilder( 'cookiebot_addons\lib\Settings_Service_Interface' )->getMock();
47
+ $scriptLoaderTagMock = $this->getMockBuilder( 'cookiebot_addons\lib\script_loader_tag\Script_Loader_Tag_Interface' )->getMock();
48
+ $cookieConsentMock = $this->getMockBuilder( 'cookiebot_addons\lib\Cookie_Consent_Interface' )->getMock();
49
+ $bufferOutputMock = $this->getMockBuilder( 'cookiebot_addons\lib\buffer\Buffer_Output_Interface' )->getMock();
50
+ $result = array();
51
+
52
+ foreach ( $this->plugins as $plugin ) {
53
+ $p = new $plugin->class( $settingsMock, $scriptLoaderTagMock, $cookieConsentMock, $bufferOutputMock );
54
+ if ( method_exists( $p, 'get_svn_url' ) && ! $p->get_svn_url() ) {
55
+ $svn_address = $p->get_svn_url();
56
+ if ( ! empty( $svn_address ) ) {
57
+ $content = file_get_contents($svn_address);
58
+ $this->assertNotFalse( $content, $plugin->class );
59
+ }
60
+ }
61
+ }
62
+ }
63
+ }
addons/tests/unit/test-get-option-name.php ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\tests\unit;
4
+
5
+ class Test_Get_Option_Name extends \WP_UnitTestCase {
6
+
7
+ /**
8
+ * The file path of addons json
9
+ *
10
+ * @var string
11
+ */
12
+ protected $file_path;
13
+
14
+ /**
15
+ * The list of all addons, json encoded
16
+ *
17
+ * @var string
18
+ */
19
+ protected $file;
20
+
21
+ /**
22
+ * Get the plugins
23
+ *
24
+ * @since 1.8.0
25
+ */
26
+ public function setUp() {
27
+ $this->get_plugins();
28
+ }
29
+
30
+ /**
31
+ * Load the addons through json file.
32
+ *
33
+ * @since 1.8.0
34
+ */
35
+ private function get_plugins() {
36
+ $this->file_path = dirname( dirname( __DIR__ ) ) . '/addons.json';
37
+ $this->file = file_get_contents( $this->file_path );
38
+ $this->plugins = json_decode( $this->file );
39
+ }
40
+
41
+ /**
42
+ * Validate if the plugins in addons.json do exist as a class in addons controller directory.
43
+ *
44
+ * @since 1.8.0
45
+ */
46
+ public function test_plugins_are_valid() {
47
+ foreach ( $this->plugins as $plugin ) {
48
+ $check = is_object( $plugin ) && class_exists( $plugin->class );
49
+ $this->assertTrue( $check );
50
+ }
51
+ }
52
+
53
+ /**
54
+ * Check if get_option_name is unique in every addon.
55
+ * @covers \cookiebot_addons\lib\Settings_Service_Interface
56
+ * @covers \cookiebot_addons\lib\script_loader_tag\Script_Loader_Tag_Interface
57
+ * @covers \cookiebot_addons\lib\script_loader_tag\Script_Loader_Tag_Interface
58
+ * @covers \cookiebot_addons\lib\buffer\Buffer_Output_Interface
59
+ *
60
+ * @version 2.1.3
61
+ * @since 1.8.0
62
+ */
63
+ public function test_get_option_name_unique() {
64
+ $options = array();
65
+
66
+ $settingsMock = $this->getMockBuilder( 'cookiebot_addons\lib\Settings_Service_Interface' )->getMock();
67
+ $scriptLoaderTagMock = $this->getMockBuilder( 'cookiebot_addons\lib\script_loader_tag\Script_Loader_Tag_Interface' )->getMock();
68
+ $cookieConsentMock = $this->getMockBuilder( 'cookiebot_addons\lib\Cookie_Consent_Interface' )->getMock();
69
+ $bufferOutputMock = $this->getMockBuilder( 'cookiebot_addons\lib\buffer\Buffer_Output_Interface' )->getMock();
70
+
71
+ foreach ( $this->plugins as $plugin ) {
72
+ $p = new $plugin->class( $settingsMock, $scriptLoaderTagMock, $cookieConsentMock, $bufferOutputMock );
73
+
74
+ // if it doesn't have parent class
75
+ if ( get_parent_class( $p ) === false ) {
76
+ // test if the option_name exists in the options array
77
+ $this->assertNotContains( $p->get_option_name(), $options );
78
+
79
+ // add name to options array
80
+ $options[] = $p->get_option_name();
81
+ }
82
+
83
+ }
84
+ }
85
+
86
+ }
addons/tests/unit/test-latest-plugin-version.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\tests\unit;
4
+
5
+ use cookiebot_addons\controller\addons\caos_host_analyticsjs_local_save_ga_local\CAOS_Host_Analyticsjs_Local_Save_Ga_Local;
6
+ use cookiebot_addons\controller\addons\caos_host_analyticsjs_local\CAOS_Host_Analyticsjs_Local;
7
+ use cookiebot_addons\lib\Settings_Service;
8
+
9
+ class Test_Latest_Plugin_Version extends \WP_UnitTestCase {
10
+
11
+ /**
12
+ * Test if older version has the latest plugin version
13
+ *
14
+ * @since 2.1.3
15
+ */
16
+ public function test_if_older_version_has_latest_plugin_version() {
17
+ $settings = new Settings_Service( new \stdClass() );
18
+
19
+ $scriptLoaderTagMock = $this->getMockBuilder( 'cookiebot_addons\lib\script_loader_tag\Script_Loader_Tag_Interface' )->getMock();
20
+ $cookieConsentMock = $this->getMockBuilder( 'cookiebot_addons\lib\Cookie_Consent_Interface' )->getMock();
21
+ $bufferOutputMock = $this->getMockBuilder( 'cookiebot_addons\lib\buffer\Buffer_Output_Interface' )->getMock();
22
+
23
+ $addonMock = new CAOS_Host_Analyticsjs_Local_Save_Ga_Local(
24
+ $settings,
25
+ $scriptLoaderTagMock,
26
+ $cookieConsentMock,
27
+ $bufferOutputMock
28
+ );
29
+
30
+ $this->assertFalse( $settings->is_latest_plugin_version( $addonMock ) );
31
+ }
32
+
33
+ /**
34
+ * Test if newer version has the latest plugin version
35
+ *
36
+ * @since 2.1.3
37
+ */
38
+ public function test_if_newer_version_has_latest_plugin_version() {
39
+ $settings = new Settings_Service( new \stdClass() );
40
+
41
+ $scriptLoaderTagMock = $this->getMockBuilder( 'cookiebot_addons\lib\script_loader_tag\Script_Loader_Tag_Interface' )->getMock();
42
+ $cookieConsentMock = $this->getMockBuilder( 'cookiebot_addons\lib\Cookie_Consent_Interface' )->getMock();
43
+ $bufferOutputMock = $this->getMockBuilder( 'cookiebot_addons\lib\buffer\Buffer_Output_Interface' )->getMock();
44
+
45
+ $addonMock = new CAOS_Host_Analyticsjs_Local(
46
+ $settings,
47
+ $scriptLoaderTagMock,
48
+ $cookieConsentMock,
49
+ $bufferOutputMock
50
+ );
51
+
52
+ $this->assertTrue( $settings->is_latest_plugin_version( $addonMock ) );
53
+ }
54
+ }
addons/tests/unit/test-manipulate-script.php ADDED
@@ -0,0 +1,299 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\tests\unit;
4
+
5
+ class Test_Manipulate_Script extends \WP_UnitTestCase {
6
+
7
+ /**
8
+ * Validate if the plugins in addons.json do exist as a class in addons controller directory.
9
+ */
10
+ public function test_manipulate_script() {
11
+ $buffer = "<head>
12
+ <meta charset='utf-8'>
13
+ <meta http-equiv='X-UA-Compatible' content='IE=edge'>
14
+ <meta name='viewport' content='width=device-width, initial-scale=1'>
15
+ <link rel='alternate' type='application/rss+xml' title='Ursula Sandner - Use your strength Feed' href='https://www.ursula-sandner.com/feed/'>
16
+ <link rel='apple-touch-icon' sizes='57x57' href='https://www.ursula-sandner.com/wp-content/themes/ursula-sandner-2015/dist/images/favicon/apple-touch-icon-57x57.png'>
17
+ <link rel='apple-touch-icon' sizes='60x60' href='https://www.ursula-sandner.com/wp-content/themes/ursula-sandner-2015/dist/images/favicon/apple-touch-icon-60x60.png'>
18
+ <link rel='apple-touch-icon' sizes='72x72' href='https://www.ursula-sandner.com/wp-content/themes/ursula-sandner-2015/dist/images/favicon/apple-touch-icon-72x72.png'>
19
+ <link rel='apple-touch-icon' sizes='76x76' href='https://www.ursula-sandner.com/wp-content/themes/ursula-sandner-2015/dist/images/favicon/apple-touch-icon-76x76.png'>
20
+ <link rel='apple-touch-icon' sizes='114x114' href='https://www.ursula-sandner.com/wp-content/themes/ursula-sandner-2015/dist/images/favicon/apple-touch-icon-114x114.png'>
21
+ <link rel='apple-touch-icon' sizes='120x120' href='https://www.ursula-sandner.com/wp-content/themes/ursula-sandner-2015/dist/images/favicon/apple-touch-icon-120x120.png'>
22
+ <link rel='apple-touch-icon' sizes='144x144' href='https://www.ursula-sandner.com/wp-content/themes/ursula-sandner-2015/dist/images/favicon/apple-touch-icon-144x144.png'>
23
+ <link rel='apple-touch-icon' sizes='152x152' href='https://www.ursula-sandner.com/wp-content/themes/ursula-sandner-2015/dist/images/favicon/apple-touch-icon-152x152.png'>
24
+ <link rel='apple-touch-icon' sizes='180x180' href='https://www.ursula-sandner.com/wp-content/themes/ursula-sandner-2015/dist/images/favicon/apple-touch-icon-180x180.png'>
25
+ <link rel='icon' type='image/png' href='https://www.ursula-sandner.com/wp-content/themes/ursula-sandner-2015/dist/images/favicon/favicon-32x32.png' sizes='32x32'>
26
+ <link rel='icon' type='image/png' href='https://www.ursula-sandner.com/wp-content/themes/ursula-sandner-2015/dist/images/favicon/favicon-194x194.png' sizes='194x194'>
27
+ <link rel='icon' type='image/png' href='https://www.ursula-sandner.com/wp-content/themes/ursula-sandner-2015/dist/images/favicon/favicon-96x96.png' sizes='96x96'>
28
+ <link rel='icon' type='image/png' href='https://www.ursula-sandner.com/wp-content/themes/ursula-sandner-2015/dist/images/favicon/android-chrome-192x192.png' sizes='192x192'>
29
+ <link rel='icon' type='image/png' href='https://www.ursula-sandner.com/wp-content/themes/ursula-sandner-2015/dist/images/favicon/favicon-16x16.png' sizes='16x16'>
30
+ <link rel='manifest' href='https://www.ursula-sandner.com/wp-content/themes/ursula-sandner-2015/dist/images/favicon/manifest.json'>
31
+ <link rel='shortcut icon' href='https://www.ursula-sandner.com/wp-content/themes/ursula-sandner-2015/dist/images/favicon/favicon.ico'>
32
+ <meta name='msapplication-TileColor' content='#da532c'>
33
+ <meta name='msapplication-TileImage' content='https://www.ursula-sandner.com/wp-content/themes/ursula-sandner-2015/dist/images/favicon/mstile-144x144.png'>
34
+ <meta name='msapplication-config' content='https://www.ursula-sandner.com/wp-content/themes/ursula-sandner-2015/dist/images/favicon/browserconfig.xml'>
35
+ <meta name='theme-color' content='#ffffff'>
36
+
37
+
38
+ <!--[if lt IE 9]>
39
+ <script src='https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js'></script>
40
+ <script src='https://oss.maxcdn.com/respond/1.4.2/respond.min.js'></script>
41
+ <![endif]-->
42
+ <title>Ursula Sandner - Use your strength</title>
43
+ <link rel='alternate' hreflang='ro-ro' href='https://www.ursula-sandner.com'>
44
+ <link rel='alternate' hreflang='en-us' href='https://www.ursula-sandner.com/en/'>
45
+
46
+ <meta name='description' content='Sunt life-coach, psihoterapeut și trainer de programare neurolingvistică. Iubesc ceea ce fac și în fiecare zi îmi practic meseria cu entuziasm și bucurie. Dar nu a fost dintotdeauna așa... Până să ajung aici viața m-a purtat pe cărări întortocheate sau, mai bine zis, eu am ales să explorez toate aceste cărări până când mi-am dat seama că ceea ce fac acum este parte din misiunea vieții mele și că nu doresc să mă mulțumesc cu mai puțin de atât.'>
47
+ <link rel='canonical' href='https://www.ursula-sandner.com/'>
48
+ <meta property='og:locale' content='ro_RO'>
49
+ <meta property='og:type' content='website'>
50
+ <meta property='og:title' content='Ursula Sandner - Use your strength'>
51
+ <meta property='og:description' content='Sunt life-coach, psihoterapeut și trainer de programare neurolingvistică. Iubesc ceea ce fac și în fiecare zi îmi practic meseria cu entuziasm și bucurie. Dar nu a fost dintotdeauna așa... Până să ajung aici viața m-a purtat pe cărări întortocheate sau, mai bine zis, eu am ales să explorez toate aceste cărări până când mi-am dat seama că ceea ce fac acum este parte din misiunea vieții mele și că nu doresc să mă mulțumesc cu mai puțin de atât.'>
52
+ <meta property='og:url' content='https://www.ursula-sandner.com/'>
53
+ <meta property='og:site_name' content='Ursula Sandner - Use your strength'>
54
+ <meta property='og:image' content='https://www.ursula-sandner.com/wp-content/uploads/2015/05/facebook-default-uys.png'>
55
+ <meta property='og:image:secure_url' content='https://www.ursula-sandner.com/wp-content/uploads/2015/05/facebook-default-uys.png'>
56
+ <meta property='og:image:width' content='470'>
57
+ <meta property='og:image:height' content='246'>
58
+ <script src='https://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js' type='text/javascript' async=''></script><script async='' src='//w.likebtn.com/js/w/widget.js'></script><script type='text/javascript' charset='UTF-8' async='' src='https://consent.cookiebot.com/7eebc73a-cd27-4eff-acdc-08662a546220/cc.js?renew=false&amp;referer=https%3A%2F%2Fwww.ursula-sandner.com&amp;culture=RO&amp;dnt=false&amp;forceshow=false&amp;cbid=7eebc73a-cd27-4eff-acdc-08662a546220&amp;whitelabel=false&amp;brandid=Cookiebot'></script><script async='' src='//w.likebtn.com/js/w/widget.js'></script><script type='application/ld+json'>{'@context':'https:\/\/schema.org','@type':'WebSite','@id':'#website','url':'https:\/\/www.ursula-sandner.com\/','name':'Ursula Sandner - Use your strength','potentialAction':{'@type':'SearchAction','target':'https:\/\/www.ursula-sandner.com\/?s={search_term_string}','query-input':'required name=search_term_string'}}</script>
59
+ <script type='application/ld+json'>{'@context':'https:\/\/schema.org','@type':'Person','url':'https:\/\/www.ursula-sandner.com\/','sameAs':['https:\/\/www.facebook.com\/SandnerMindConsulting','https:\/\/instagram.com\/ursula.sandner','https:\/\/twitter.com\/psihotimisoara'],'@id':'#person','name':'Ursula Yvonne Sandner'}</script>
60
+
61
+ <link rel='dns-prefetch' href='//s.w.org'>
62
+ <link rel='alternate' type='application/rss+xml' title='Flux comentarii Ursula Sandner - Use your strength » Prima pagină' href='https://www.ursula-sandner.com/prima-pagina/feed/'>
63
+ <style>.monsterinsights-async-hide { opacity: 0 !important} </style>
64
+ <script>(function(a,s,y,n,c,h,i,d,e){s.className+=' '+y;h.start=1*new Date;
65
+ h.end=i=function(){s.className=s.className.replace(RegExp(' ?'+y),'')};
66
+ (a[n]=a[n]||[]).hide=h;setTimeout(function(){i();h.end=null},c);h.timeout=c;
67
+ })(window,document.documentElement,'monsterinsights-async-hide','dataLayer',4000,
68
+ {'GTM-5RSGFLM':true});</script>
69
+
70
+ <script type='text/plain' data-cfasync='false' data-cookieconsent='statistics'>
71
+ var mi_version = '7.1.1';
72
+ var mi_track_user = true;
73
+ var mi_no_track_reason = '';
74
+
75
+ var disableStr = 'ga-disable-UA-22754433-1';
76
+
77
+ /* Function to detect opted out users */
78
+ function __gaTrackerIsOptedOut() {
79
+ return document.cookie.indexOf(disableStr + '=true') > -1;
80
+ }
81
+
82
+ /* Disable tracking if the opt-out cookie exists. */
83
+ if ( __gaTrackerIsOptedOut() ) {
84
+ window[disableStr] = true;
85
+ }
86
+
87
+ /* Opt-out function */
88
+ function __gaTrackerOptout() {
89
+ document.cookie = disableStr + '=true; expires=Thu, 31 Dec 2099 23:59:59 UTC; path=/';
90
+ window[disableStr] = true;
91
+ }
92
+
93
+ if ( mi_track_user ) {
94
+ (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
95
+ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
96
+ m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
97
+ })(window,document,'script','//www.google-analytics.com/analytics.js','__gaTracker');
98
+
99
+ window.ga = __gaTracker; __gaTracker('create', 'UA-22754433-1', 'auto', {'useAmpClientId':true});
100
+ __gaTracker('set', 'forceSSL', true);
101
+ __gaTracker('set', 'anonymizeIp', true);
102
+ __gaTracker('require', 'ec');
103
+ __gaTracker('require', 'linkid', 'linkid.js');
104
+ __gaTracker('set', 'displayFeaturesTask', null);
105
+ __gaTracker('require', 'GTM-5RSGFLM');
106
+ __gaTracker('send','pageview');
107
+ } else {
108
+ console.log( '' );
109
+ (function() {
110
+ /* https://developers.google.com/analytics/devguides/collection/analyticsjs/ */
111
+ var noopfn = function() {
112
+ return null;
113
+ };
114
+ var noopnullfn = function() {
115
+ return null;
116
+ };
117
+ var Tracker = function() {
118
+ return null;
119
+ };
120
+ var p = Tracker.prototype;
121
+ p.get = noopfn;
122
+ p.set = noopfn;
123
+ p.send = noopfn;
124
+ var __gaTracker = function() {
125
+ var len = arguments.length;
126
+ if ( len === 0 ) {
127
+ return;
128
+ }
129
+ var f = arguments[len-1];
130
+ if ( typeof f !== 'object' || f === null || typeof f.hitCallback !== 'function' ) {
131
+ console.log( 'Not running function __gaTracker(' + arguments[0] + ' ....) because you are not being tracked. ' + mi_no_track_reason );
132
+ return;
133
+ }
134
+ try {
135
+ f.hitCallback();
136
+ } catch (ex) {
137
+
138
+ }
139
+ };
140
+ __gaTracker.create = function() {
141
+ return new Tracker();
142
+ };
143
+ __gaTracker.getByName = noopnullfn;
144
+ __gaTracker.getAll = function() {
145
+ return [];
146
+ };
147
+ __gaTracker.remove = noopfn;
148
+ window['__gaTracker'] = __gaTracker;
149
+ window.ga = __gaTracker; })();
150
+ }
151
+ </script>
152
+
153
+ <script type='text/javascript'>
154
+ window._wpemojiSettings = {'baseUrl':'https:\/\/s.w.org\/images\/core\/emoji\/11\/72x72\/','ext':'.png','svgUrl':'https:\/\/s.w.org\/images\/core\/emoji\/11\/svg\/','svgExt':'.svg','source':{'concatemoji':'https:\/\/www.ursula-sandner.com\/wp-includes\/js\/wp-emoji-release.min.js'}};
155
+ !function(a,b,c){function d(a,b){var c=String.fromCharCode;l.clearRect(0,0,k.width,k.height),l.fillText(c.apply(this,a),0,0);var d=k.toDataURL();l.clearRect(0,0,k.width,k.height),l.fillText(c.apply(this,b),0,0);var e=k.toDataURL();return d===e}function e(a){var b;if(!l||!l.fillText)return!1;switch(l.textBaseline='top',l.font='600 32px Arial',a){case'flag':return!(b=d([55356,56826,55356,56819],[55356,56826,8203,55356,56819]))&&(b=d([55356,57332,56128,56423,56128,56418,56128,56421,56128,56430,56128,56423,56128,56447],[55356,57332,8203,56128,56423,8203,56128,56418,8203,56128,56421,8203,56128,56430,8203,56128,56423,8203,56128,56447]),!b);case'emoji':return b=d([55358,56760,9792,65039],[55358,56760,8203,9792,65039]),!b}return!1}function f(a){var c=b.createElement('script');c.src=a,c.defer=c.type='text/javascript',b.getElementsByTagName('head')[0].appendChild(c)}var g,h,i,j,k=b.createElement('canvas'),l=k.getContext&&k.getContext('2d');for(j=Array('flag','emoji'),c.supports={everything:!0,everythingExceptFlag:!0},i=0;i<j.length;i++)c.supports[j[i]]=e(j[i]),c.supports.everything=c.supports.everything&&c.supports[j[i]],'flag'!==j[i]&&(c.supports.everythingExceptFlag=c.supports.everythingExceptFlag&&c.supports[j[i]]);c.supports.everythingExceptFlag=c.supports.everythingExceptFlag&&!c.supports.flag,c.DOMReady=!1,c.readyCallback=function(){c.DOMReady=!0},c.supports.everything||(h=function(){c.readyCallback()},b.addEventListener?(b.addEventListener('DOMContentLoaded',h,!1),a.addEventListener('load',h,!1)):(a.attachEvent('onload',h),b.attachEvent('onreadystatechange',function(){'complete'===b.readyState&&c.readyCallback()})),g=c.source||{},g.concatemoji?f(g.concatemoji):g.wpemoji&&g.twemoji&&(f(g.twemoji),f(g.wpemoji)))}(window,document,window._wpemojiSettings);
156
+ </script><script src='https://www.ursula-sandner.com/wp-includes/js/wp-emoji-release.min.js' type='text/javascript' defer=''></script>
157
+ <style type='text/css'>
158
+ img.wp-smiley,
159
+ img.emoji {
160
+ display: inline !important;
161
+ border: none !important;
162
+ box-shadow: none !important;
163
+ height: 1em !important;
164
+ width: 1em !important;
165
+ margin: 0 .07em !important;
166
+ vertical-align: -0.1em !important;
167
+ background: none !important;
168
+ padding: 0 !important;
169
+ }
170
+ </style>
171
+ <link rel='stylesheet' id='contact-form-7-css' href='https://www.ursula-sandner.com/wp-content/plugins/contact-form-7/includes/css/styles.css' type='text/css' media='all'>
172
+ <link rel='stylesheet' id='dedo-css-css' href='https://www.ursula-sandner.com/wp-content/plugins/delightful-downloads/assets/css/delightful-downloads.min.css' type='text/css' media='all'>
173
+ <link rel='stylesheet' id='likebtn_style-css' href='https://www.ursula-sandner.com/wp-content/plugins/likebtn-like-button/public/css/style.css' type='text/css' media='all'>
174
+ <link rel='stylesheet' id='follow-up-emails-css' href='https://www.ursula-sandner.com/wp-content/plugins/woocommerce-follow-up-emails/templates/followups.css' type='text/css' media='all'>
175
+ <link rel='stylesheet' id='wpml-legacy-horizontal-list-0-css' href='//www.ursula-sandner.com/wp-content/plugins/sitepress-multilingual-cms/templates/language-switchers/legacy-list-horizontal/style.css' type='text/css' media='all'>
176
+ <link rel='stylesheet' id='ywot_style-css' href='https://www.ursula-sandner.com/wp-content/plugins/yith-woocommerce-order-tracking/assets/css/ywot_style.css' type='text/css' media='all'>
177
+ <link rel='stylesheet' id='wc-bundle-style-css' href='https://www.ursula-sandner.com/wp-content/plugins/woocommerce-product-bundles/assets/css/wc-pb-frontend.css' type='text/css' media='all'>
178
+ <link rel='stylesheet' id='sage_css-css' href='https://www.ursula-sandner.com/wp-content/themes/ursula-sandner-2015/dist/styles/main-dc01f269.css' type='text/css' media='all'>
179
+ <script type='text/javascript'>
180
+ /* <![CDATA[ */
181
+ var wp_sentry = {'dsn':'https:\/\/935f99b8fbe14f3b95c53ff8b820c3b3@sentry.io\/293758','options':{'release':'1.0','environment':'unspecified','tags':{'wordpress':'4.9.8','language':'ro-RO'},'user':{'id':0,'name':'anonymous'}}};
182
+ /* ]]> */
183
+ </script>
184
+ <script type='text/javascript' src='https://www.ursula-sandner.com/wp-content/plugins/wp-sentry-integration/public/raven-3.26.3.min.js'></script>
185
+ <script type='text/javascript'>
186
+ /* <![CDATA[ */
187
+ var monsterinsights_frontend = {'js_events_tracking':'true','is_debug_mode':'false','download_extensions':'doc,exe,js,pdf,ppt,tgz,zip,xls','inbound_paths':'','home_url':'https:\/\/www.ursula-sandner.com','track_download_as':'event','internal_label':'int','hash_tracking':'false'};
188
+ /* ]]> */
189
+ </script>
190
+ <script type='text/javascript' src='https://www.ursula-sandner.com/wp-content/plugins/google-analytics-premium/assets/js/frontend.min.js'></script>
191
+ <script type='text/javascript' src='https://www.ursula-sandner.com/wp-includes/js/jquery/jquery.js'></script>
192
+ <script type='text/javascript' src='https://www.ursula-sandner.com/wp-includes/js/jquery/jquery-migrate.min.js'></script>
193
+ <script type='text/javascript'>
194
+ /* <![CDATA[ */
195
+ var likebtn_eh_data = {'ajaxurl':'https:\/\/www.ursula-sandner.com\/wp-admin\/admin-ajax.php','security':'5b3b461d95'};
196
+ /* ]]> */
197
+ </script>
198
+ <script type='text/javascript' src='https://www.ursula-sandner.com/wp-content/plugins/likebtn-like-button/public/js/frontend.js'></script>
199
+ <script type='text/javascript'>
200
+ /* <![CDATA[ */
201
+ var FUE = {'ajaxurl':'https:\/\/www.ursula-sandner.com\/wp-admin\/admin-ajax.php','ajax_loader':'https:\/\/www.ursula-sandner.com\/wp-content\/plugins\/woocommerce-follow-up-emails\/templates\/images\/ajax-loader.gif'};
202
+ /* ]]> */
203
+ </script>
204
+ <script type='text/javascript' src='https://www.ursula-sandner.com/wp-content/plugins/woocommerce-follow-up-emails/templates/js/fue-account-subscriptions.js'></script>
205
+ <script type='text/javascript' src='https://www.ursula-sandner.com/wp-content/plugins/yith-woocommerce-order-tracking/assets/js/jquery.tooltipster.min.js'></script>
206
+ <script type='text/javascript'>
207
+ /* <![CDATA[ */
208
+ var ywot = {'p':''};
209
+ /* ]]> */
210
+ </script>
211
+ <script type='text/javascript' src='https://www.ursula-sandner.com/wp-content/plugins/yith-woocommerce-order-tracking/assets/js/ywot.js'></script>
212
+ <link rel='https://api.w.org/' href='https://www.ursula-sandner.com/wp-json/'>
213
+ <link rel='shortlink' href='https://www.ursula-sandner.com/'>
214
+ <link rel='alternate' type='application/json+oembed' href='https://www.ursula-sandner.com/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fwww.ursula-sandner.com%2F'>
215
+ <link rel='alternate' type='text/xml+oembed' href='https://www.ursula-sandner.com/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fwww.ursula-sandner.com%2F&amp;format=xml'>
216
+ <meta name='generator' content='WPML ver:4.0.7 stt:1,46;'>
217
+ <script id='Cookiebot' src='https://consent.cookiebot.com/uc.js' data-cbid='7eebc73a-cd27-4eff-acdc-08662a546220' data-culture='RO' type='text/javascript' async=''></script>
218
+ <script type='text/javascript'>
219
+ var USY = {'theme_dir_uri':'https:\/\/www.ursula-sandner.com\/wp-content\/themes\/ursula-sandner-2015','promotions_active':1,'promotions_minimize_time':'7'};
220
+ </script>
221
+ <noscript><style>.woocommerce-product-gallery{ opacity: 1 !important; }</style></noscript>
222
+ <meta name='onesignal' content='wordpress-plugin'>
223
+ <link rel='manifest' href='https://www.ursula-sandner.com/wp-content/plugins/onesignal-free-web-push-notifications/sdk_files/manifest.json.php?gcm_sender_id='>
224
+ <script src='https://cdn.onesignal.com/sdks/OneSignalSDK.js' async=''></script> <script>
225
+
226
+ window.OneSignal = window.OneSignal || [];
227
+
228
+ OneSignal.push( function() {
229
+ OneSignal.SERVICE_WORKER_UPDATER_PATH = 'OneSignalSDKUpdaterWorker.js.php';
230
+ OneSignal.SERVICE_WORKER_PATH = 'OneSignalSDKWorker.js.php';
231
+ OneSignal.SERVICE_WORKER_PARAM = { scope: '/' };
232
+
233
+ OneSignal.setDefaultNotificationUrl('https://www.ursula-sandner.com');
234
+ var oneSignal_options = {};
235
+ window._oneSignalInitOptions = oneSignal_options;
236
+
237
+ oneSignal_options['wordpress'] = true;
238
+ oneSignal_options['appId'] = 'eedf1600-3f95-47ee-a5f3-df67051e1bcf';
239
+ oneSignal_options['autoRegister'] = true;
240
+ oneSignal_options['welcomeNotification'] = { };
241
+ oneSignal_options['welcomeNotification']['title'] = 'Dr. Ursula Sandner';
242
+ oneSignal_options['welcomeNotification']['message'] = 'Îți urez success în călătoria propriei tale dezvoltări';
243
+ oneSignal_options['path'] = 'https://www.ursula-sandner.com/wp-content/plugins/onesignal-free-web-push-notifications/sdk_files/';
244
+ oneSignal_options['safari_web_id'] = 'web.onesignal.auto.145f18a4-510a-4781-b676-50fa3f7fa700';
245
+ oneSignal_options['persistNotification'] = true;
246
+ oneSignal_options['promptOptions'] = { };
247
+ oneSignal_options['notifyButton'] = { };
248
+ oneSignal_options['notifyButton']['enable'] = true;
249
+ oneSignal_options['notifyButton']['position'] = 'bottom-right';
250
+ oneSignal_options['notifyButton']['theme'] = 'default';
251
+ oneSignal_options['notifyButton']['size'] = 'large';
252
+ oneSignal_options['notifyButton']['prenotify'] = true;
253
+ oneSignal_options['notifyButton']['showCredit'] = false;
254
+ oneSignal_options['notifyButton']['text'] = {};
255
+ oneSignal_options['notifyButton']['text']['message.prenotify'] = 'Click aici pentru a te abona la notificări';
256
+ oneSignal_options['notifyButton']['text']['tip.state.unsubscribed'] = 'Abonează-te la notificări';
257
+ oneSignal_options['notifyButton']['text']['tip.state.subscribed'] = 'Te-ai abonat la notificări';
258
+ oneSignal_options['notifyButton']['text']['tip.state.blocked'] = 'Ai blocat notificările';
259
+ oneSignal_options['notifyButton']['text']['message.action.subscribed'] = 'Bun venit în comunitate!';
260
+ oneSignal_options['notifyButton']['text']['message.action.resubscribed'] = 'Te-ai re-abonat la notificări';
261
+ oneSignal_options['notifyButton']['text']['message.action.unsubscribed'] = 'Nu vei mai primi notificări de acum înainte';
262
+ oneSignal_options['notifyButton']['text']['dialog.main.title'] = 'Gestionează notificările';
263
+ oneSignal_options['notifyButton']['text']['dialog.main.button.subscribe'] = 'Abonează-te';
264
+ oneSignal_options['notifyButton']['text']['dialog.main.button.unsubscribe'] = 'Dezbonează-te';
265
+ oneSignal_options['notifyButton']['text']['dialog.blocked.title'] = 'Deblochează notificările';
266
+ oneSignal_options['notifyButton']['text']['dialog.blocked.message'] = 'Urmează aceste instrucțiuni pentru a te abona la notificări';
267
+ OneSignal.init(window._oneSignalInitOptions);
268
+ });
269
+
270
+ function documentInitOneSignal() {
271
+ var oneSignal_elements = document.getElementsByClassName('OneSignal-prompt');
272
+
273
+ var oneSignalLinkClickHandler = function(event) { OneSignal.push(['registerForPushNotifications']); event.preventDefault(); }; for(var i = 0; i < oneSignal_elements.length; i++)
274
+ oneSignal_elements[i].addEventListener('click', oneSignalLinkClickHandler, false);
275
+ }
276
+
277
+ if (document.readyState === 'complete') {
278
+ documentInitOneSignal();
279
+ }
280
+ else {
281
+ window.addEventListener('load', function(event){
282
+ documentInitOneSignal();
283
+ });
284
+ }
285
+ </script>
286
+
287
+
288
+ <link rel='stylesheet' href='https://fonts.googleapis.com/css?family=PT+Sans:400,700,400italic%7CCardo:400,700,400italic%7CMerriweather:400,300,700&amp;subset=latin,latin-ext,latin,latin-ext,latin,latin-ext' media='all'><style type='text/css' id='CookieConsentStateDisplayStyles'>.cookieconsent-optin-preferences,.cookieconsent-optin-statistics,.cookieconsent-optin-marketing,.cookieconsent-optin{display:none;}.cookieconsent-optout-preferences,.cookieconsent-optout-statistics,.cookieconsent-optout-marketing,.cookieconsent-optout{display:block;}</style><link type='text/css' rel='stylesheet' href='//w.likebtn.com/css/w/widget.css?v=36'><style type='text/css' id='CookiebotDialogStyle'>#CybotCookiebotDialog,#CybotCookiebotDialogBodyUnderlay{animation:none;animation-fill-mode:none;animation-name:none;border-collapse:separate;border-image:none;bottom:auto;caption-side:top;clear:none;clip:auto;columns:auto;column-count:auto;column-fill:balance;column-gap:normal;column-rule:medium none currentColor;column-rule-color:currentColor;column-rule-style:none;column-rule-width:none;column-span:1;column-width:auto;content:normal;counter-increment:none;counter-reset:none;cursor:auto;display:inline;empty-cells:show;hyphens:none;max-height:none;min-height:0;min-width:0;orphans:0;overflow-x:visible;overflow-y:visible;page-break-after:auto;page-break-before:auto;page-break-inside:auto;perspective:none;right:auto;tab-size:8;table-layout:auto;text-align-last:auto;text-decoration:none;text-decoration-color:inherit;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-shadow:none;text-transform:none;transform:none;transition:none;transition-property:none;vertical-align:baseline;white-space:normal;widows:0;width:auto;word-spacing:normal;opacity:1;font-weight:400;box-sizing:content-box;outline:0;top:0;left:0;height:auto;border-spacing:0}#CybotCookiebotDialog a,#CybotCookiebotDialog a:hover{text-decoration:underline;color:#2a2a2a}#CybotCookiebotDialog,#CybotCookiebotDialogBodyContentTitle,#CybotCookiebotDialogBodyUnderlay{margin:0;visibility:visible;letter-spacing:normal;float:none}#CybotCookiebotDialog,#CybotCookiebotDialog::after,#CybotCookiebotDialog::before,.CybotCookiebotDialogBodyButton,.CybotCookiebotDialogBodyButton::after,.CybotCookiebotDialogBodyButton::before{box-sizing:content-box}#CybotCookiebotDialogBodyUnderlay{animation-delay:0;animation-direction:normal;animation-duration:0;animation-iteration-count:1;animation-play-state:running;animation-timing-function:ease;backface-visibility:visible;background:#121212;background-clip:border-box;background-origin:padding-box;background-position-x:0;background-position-y:0;background-size:auto auto;border:0;border-width:medium;border-color:inherit;border-bottom:0;border-bottom-color:inherit;border-left:0;border-left-color:inherit;border-radius:0;border-right:0;border-right-color:inherit;border-top:0;border-top-color:inherit;box-shadow:none;color:inherit;font:400;font-family:inherit;font-size:medium;font-style:normal;font-variant:normal;line-height:normal;list-style:disc;max-width:none;outline-width:medium;perspective-origin:50% 50%;text-align:inherit;transform-style:flat;transition-delay:0s;transition-duration:0s;transition-timing-function:ease;position:absolute;padding:0;z-index:2147483630;overflow:hidden}#CybotCookiebotDialog{animation-delay:0;animation-direction:normal;animation-duration:0;animation-iteration-count:1;animation-play-state:running;animation-timing-function:ease;backface-visibility:visible;background:#ffffff;background-clip:border-box;background-origin:padding-box;background-position-x:0;background-position-y:0;background-size:auto auto;font:400;font-style:normal;font-variant:normal;list-style:disc;outline-width:medium;padding:0 0 8px;perspective-origin:50% 50%;transform-style:flat;transition-delay:0s;transition-duration:0s;transition-timing-function:ease;max-width:574px;position:fixed;overflow:hidden;filter:Alpha(opacity=100);z-index:2147483640;color:#2a2a2a;font-family:'Segoe UI',Arial,Helvetica,Verdana,sans-serif;font-size:8pt;border:18px solid #2a2a2a;box-shadow:#121212 2px 2px 14px 2px;-webkit-border-radius:12px;-moz-border-radius:12px;border-radius:12px;line-height:1.231;text-align:left;text-rendering:geometricPrecision}#CybotCookiebotDialog br,#CybotCookiebotDialog div,#CybotCookiebotDialog td{line-height:1.231}#CybotCookiebotDialog a,#CybotCookiebotDialog div,#CybotCookiebotDialogBodyContentTitle{font-family:'Segoe UI',Arial,Helvetica,Verdana,sans-serif}#CybotCookiebotDialog[dir=rtl],div[dir=rtl] #CybotCookiebotDialogBodyContentText,div[dir=rtl] #CybotCookiebotDialogBodyContentTitle{text-align:right}#CybotCookiebotDialog a{line-height:1.231}#CybotCookiebotDialogDetailBodyContentCookieContainerAdvertising,#CybotCookiebotDialogDetailBodyContentCookieContainerNecessary,#CybotCookiebotDialogDetailBodyContentCookieContainerPreference,#CybotCookiebotDialogDetailBodyContentCookieContainerStatistics,#CybotCookiebotDialogDetailBodyContentCookieContainerUnclassified{margin:0}#CybotCookiebotDialogPoweredbyLink{position:absolute;z-index:2147483646;width:48px;height:36px;margin-left:16px;margin-right:0;margin-top:20px}div[dir=rtl] #CybotCookiebotDialogPoweredbyLink{margin-left:0;margin-right:16px}#CybotCookiebotDialogPoweredbyImage{border:none;padding:0;margin:1px 0 0 1px;width:46px}#CybotCookiebotDialogBody{width:100%;z-index:2147483647;vertical-align:top;overflow:hidden}#CybotCookiebotDialogBodyContent{min-height:32px;font-size:12pt;font-weight:400;line-height:130%;margin:0;padding:16px 12px 4px 80px}div[dir=rtl] #CybotCookiebotDialogBodyContent{padding-left:12px;padding-right:80px}#CybotCookiebotDialogBodyContentTitle{font-size:18pt;font-weight:700;line-height:110%;padding:0;color:#2a2a2a;display:block;position:static;text-align:left}#CybotCookiebotDialogBodyContentText{margin-top:14px;margin-bottom:12px;text-align:left}#CybotCookiebotDialogBodyButtons{display:block;margin:0 12px 18px 6px;z-index:10;padding-left:62px;padding-right:0}div[dir=rtl] #CybotCookiebotDialogBodyButtons{margin:0 6px 18px 12px;padding-left:0;padding-right:62px}#CybotCookiebotDialogBodyButtons a,#CybotCookiebotDialogBodyButtons a:hover{text-decoration:none;color:#ffffff}.CybotCookiebotDialogBodyButton{display:inline-block;padding:1px 4px 3px;z-index:10;font-size:9.5pt;font-weight:400;margin-left:12px;margin-right:0;margin-top:8px;text-align:center;white-space:nowrap;min-width:80px}div[dir=rtl] .CybotCookiebotDialogBodyButton{margin-left:0;margin-right:12px}#CybotCookiebotDialogBodyButtonAccept{background-color:#18a300;border:1px solid #18a300}#CybotCookiebotDialogBodyButtonDecline{background-color:#333333;border:1px solid #333333}#CybotCookiebotDialogBodyButtons .CybotCookiebotDialogBodyLink,#CybotCookiebotDialogBodyLevelDetailsButton{display:inline-block;color:#2a2a2a;text-decoration:none;font-size:9pt;margin-top:8px;text-align:right;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAGCAMAAAAmGUT3AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkI3NDEyNDEwNzk0MjExRTQ5RUE5RkRFMUQ3MEU1NTZDIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkI3NDEyNDExNzk0MjExRTQ5RUE5RkRFMUQ3MEU1NTZDIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6Qjc0MTI0MEU3OTQyMTFFNDlFQTlGREUxRDcwRTU1NkMiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6Qjc0MTI0MEY3OTQyMTFFNDlFQTlGREUxRDcwRTU1NkMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz70ohqeAAAABlBMVEVgYGAAAAAPhzbbAAAAAnRSTlP/AOW3MEoAAAAjSURBVHjaYmBkYAQBBkYGIAAxQBQcQ/ggCiLFCGFBCIAAAwADkwAg7Yr51AAAAABJRU5ErkJggg==);background-repeat:no-repeat;background-position-x:right;background-position-y:12px;background-position:right 12px;border-left:0;border-right:5px solid transparent;padding:7px 19px 0 0}div[dir=rtl] #CybotCookiebotDialogBodyButtons .CybotCookiebotDialogBodyLink,div[dir=rtl] #CybotCookiebotDialogBodyLevelDetailsButton{padding-left:19px;padding-right:0;background-position-x:left;background-position-y:12px;background-position:left 12px;border-left:5px solid transparent;border-right:0}div[dir=rtl] #CybotCookiebotDialogBodyLevelDetailsButton,div[dir=rtl] .CybotCookiebotDialogBodyLevelDetailsButtonExpanded{background-position-x:left!important;background-position-y:5px!important;background-position:left 5px!important}#CybotCookiebotDialogBodyButtons .CybotCookiebotDialogBodyLink:hover,#CybotCookiebotDialogBodyLevelDetailsButton:hover{color:#2a2a2a;text-decoration:underline}.CybotCookiebotDialogBodyLevelDetailsButtonExpanded,.CybotCookiebotDialogBodyLinkExpanded{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAGCAYAAAARx7TFAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjU0QzAwODExNzk0MjExRTQ4QzBERTBGMTkxMUY2M0M0IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjU0QzAwODEyNzk0MjExRTQ4QzBERTBGMTkxMUY2M0M0Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NTRDMDA4MEY3OTQyMTFFNDhDMERFMEYxOTExRjYzQzQiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NTRDMDA4MTA3OTQyMTFFNDhDMERFMEYxOTExRjYzQzQiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz576KdnAAAATklEQVR42kyO2xEAMQgCJZ3afxFcyGRz+uMD3EHdXbYrJSltrz4Dt4UBNfsWPG614oRwO2Q/Eg+IwvnDj8kjk+48MzmZeNYI/4jRPwEGAFy/MS7NcXxJAAAAAElFTkSuQmCC)!important}a#CybotCookiebotDialogBodyLevelDetailsButton{text-decoration:none;padding-top:0;padding-left:4px;margin:1px 0 0;background-position-x:right;background-position-y:5px;background-position:right 5px;text-align:left;color:#2a2a2a;line-height:16px}div[dir=rtl] a#CybotCookiebotDialogBodyLevelDetailsButton{text-align:right}a#CybotCookiebotDialogBodyLevelDetailsButton:hover{text-decoration:none;color:#2a2a2a}#CybotCookiebotDialogBodyButtonDetails{display:inline-block;float:right;outline:0}div[dir=rtl] #CybotCookiebotDialogBodyButtonDetails{float:left}#CybotCookiebotDialogBodyLevelWrapper{display:none;text-align:right;padding-left:4px;padding-right:12px;pointer-events:none}div[dir=rtl] #CybotCookiebotDialogBodyLevelWrapper{text-align:left;padding-left:12px;padding-right:4px}#CybotCookiebotDialogBodyLevelButtons{font-size:9pt;float:left;margin-left:8px;margin-right:0;pointer-events:auto}div[dir=rtl] #CybotCookiebotDialogBodyLevelButtons{float:right;margin-left:0;margin-right:8px}#CybotCookiebotDialogBodyLevelButtonsTable{display:inline-table;margin:5px 0 4px}div[dir=rtl] #CybotCookiebotDialogBodyLevelButtonsTable{margin-left:0;margin-right:0}#CybotCookiebotDialogBodyLevelButtonsRow{display:table-row}#CybotCookiebotDialogBodyLevelButtonsSelectPane{display:table-cell;border:1px solid #cccccc;padding:4px 3px 3px 9px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px;text-align:left;vertical-align:top}#CybotCookiebotDialogBodyLevelButtonAcceptWrapper{display:inline-block;float:right;margin-left:0;margin-right:0;pointer-events:auto}div[dir=rtl] #CybotCookiebotDialogBodyLevelButtonAcceptWrapper{display:inline-block;float:left;margin-left:0;margin-right:0}a#CybotCookiebotDialogBodyLevelButtonAccept{display:inline-block;background-color:#18a300;border:1px solid #18a300;padding:3px 2px;min-width:80px;color:#ffffff;text-decoration:none;margin-left:0;margin-top:6px;z-index:10;font-size:9.5pt;font-weight:400;margin-right:0;text-align:center;white-space:nowrap}a#CybotCookiebotDialogBodyLevelButtonAccept:hover{color:#ffffff;text-decoration:none}div[dir=rtl] #CybotCookiebotDialogBodyLevelButtonsSelectPane{text-align:right;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.CybotCookiebotDialogBodyLevelButtonWrapper{display:inline-block;position:relative;margin-right:14px;margin-left:0;line-height:16px}div[dir=rtl] .CybotCookiebotDialogBodyLevelButtonWrapper{margin-right:0;margin-left:14px}.CybotCookiebotDialogBodyLevelButtonWrapper:last-of-type{margin-right:7px;margin-left:0}div[dir=rtl] .CybotCookiebotDialogBodyLevelButtonWrapper:last-of-type{margin-right:0;margin-left:7px}.CybotCookiebotDialogBodyLevelButtonWrapper label{white-space:nowrap}input[type=checkbox].CybotCookiebotDialogBodyLevelButton{opacity:0;position:absolute;top:0;left:0;z-index:2;cursor:pointer}input[type=checkbox].CybotCookiebotDialogBodyLevelButton.CybotCookiebotDialogBodyLevelButtonDisabled{cursor:default}input[type=checkbox].CybotCookiebotDialogBodyLevelButton+label{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjYxNkU3NEJGQkJDMjExRTNCMzA3ODU5MUUzMDlDM0FDIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjYxNkU3NEMwQkJDMjExRTNCMzA3ODU5MUUzMDlDM0FDIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NjE2RTc0QkRCQkMyMTFFM0IzMDc4NTkxRTMwOUMzQUMiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NjE2RTc0QkVCQkMyMTFFM0IzMDc4NTkxRTMwOUMzQUMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz71Yc/eAAAAOklEQVR42mL8//8/AzmAkf4aL1y4QLROfX19RjgHpBFkKyGMro6JgUwwqnFQaWQBERcvXiQ53QEEGADSSDs5lXMYKAAAAABJRU5ErkJggg==);background-repeat:no-repeat;height:auto;min-height:14px;width:auto;display:inline-block;padding:1px 0 0 17px;position:relative;top:0;left:0;z-index:1;cursor:pointer;margin-top:0;background-position:left 1px;vertical-align:top;line-height:16px}div[dir=rtl] input[type=checkbox].CybotCookiebotDialogBodyLevelButton+label{background-position:right 1px;padding:2px 17px 0 0}input[type=checkbox].CybotCookiebotDialogBodyLevelButton:checked+label{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjNGMUE0MkE1QkJDMjExRTM5QUIxQzQwRjkwREYzMUIyIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjNGMUE0MkE2QkJDMjExRTM5QUIxQzQwRjkwREYzMUIyIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6M0YxQTQyQTNCQkMyMTFFMzlBQjFDNDBGOTBERjMxQjIiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6M0YxQTQyQTRCQkMyMTFFMzlBQjFDNDBGOTBERjMxQjIiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4IZcVrAAAA5UlEQVR42mL8//8/AyMjIwMxQHwRgwOQAuEJjMRqBGoSAFL3gRhEf2BiIB7Mh2oCgQ+MFy5c+E9Ix/o3SxlmPOtGFnJkAZEGBgaMeJyoAKTOI9k24WUcwwEmNEUGBJx4AaipEMRgQtIEUnAeSCcgiRVAQxEGEmEMsB/dLxk4Atn70RRcgDoRDGLEMxh63WfAvQSz8QIUIztvPRL/QixQIzIAawS6+wMopNA0K8CCHogD0T0O9yMOzSDQCJR7gFMjmuYFUKEDQLEJ2KKJBV0AqjkRGKILsdiOqhFv6kHSCkrXMAAQYACIkU0SIPgtxAAAAABJRU5ErkJggg==);background-repeat:no-repeat;height:auto;width:auto;min-height:14px;display:inline-block;padding:1px 0 0 17px;background-position:left 1px;vertical-align:top;line-height:16px}div[dir=rtl] input[type=checkbox].CybotCookiebotDialogBodyLevelButton:checked+label{background-position:right 1px;padding:2px 17px 0 0}input[type=checkbox].CybotCookiebotDialogBodyLevelButton.CybotCookiebotDialogBodyLevelButtonDisabled+label{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjgzMjc3NEM2QkJDMjExRTNBN0ExOUJFMzFCMzdBRjdEIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjgzMjc3NEM3QkJDMjExRTNBN0ExOUJFMzFCMzdBRjdEIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ODMyNzc0QzRCQkMyMTFFM0E3QTE5QkUzMUIzN0FGN0QiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6ODMyNzc0QzVCQkMyMTFFM0E3QTE5QkUzMUIzN0FGN0QiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz54CbH2AAABFElEQVR42oxSLQ/CQAy9I6hZMrVgQW4aCdnvGIoER8Lm+AcbWBIcFo0cFuw0dkxMMAlyvC69y/hek6VN19e+16ssy1JIKUUTC8Owh9o+wkNbNDSADICmCA18w1ZTIEAeg8juMkmS8h+oKAqR57nIsmzD0pYVVcdx5A+KHRQuLMuaEYj0+b5/br0UdT9QHANgcJwGQbCjWAOjKPKoM/yglhvB9dTW0WCrG5LGOI77SM5rz0IFKXILniRs2564rqsL2tzpQjQQKqoectdao9Q0zScJFVXwvsGteIr612F/Q279ql1rxKYqME8WNV17NL5+BSowCmnykUFngA6fnunt5Jj2Fhs9wV++XlKTy1GGzeptPQQYAF1/e0nsKZ1HAAAAAElFTkSuQmCC);background-repeat:no-repeat;height:auto;width:auto;min-height:14px;display:inline-block;padding:1px 0 0 17px;position:relative;top:0;left:0;z-index:1;cursor:default;background-position:left 1px;vertical-align:top;line-height:16px}div[dir=rtl] input[type=checkbox].CybotCookiebotDialogBodyLevelButton.CybotCookiebotDialogBodyLevelButtonDisabled+label{background-position:right 1px;padding:2px 17px 0 0}input[type=checkbox].CybotCookiebotDialogBodyLevelButton:focus+label{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkUwQkVDMzlCQkQ4NTExRTM5RTEwRUIwNUNENTg2N0Q4IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkUwQkVDMzlDQkQ4NTExRTM5RTEwRUIwNUNENTg2N0Q4Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6RTBCRUMzOTlCRDg1MTFFMzlFMTBFQjA1Q0Q1ODY3RDgiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6RTBCRUMzOUFCRDg1MTFFMzlFMTBFQjA1Q0Q1ODY3RDgiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7Y0XwIAAAAOElEQVR42mL8//8/AzmAiYFMQLZGxtLSUqLd2tXVxQhjs8AMIELf/4H146hGWmhkwRa5xACAAAMAL2gJGKxaSssAAAAASUVORK5CYII=);background-repeat:no-repeat;height:auto;width:auto;min-height:14px;display:inline-block;padding:1px 0 0 17px;background-position:left 1px;vertical-align:top;line-height:16px}div[dir=rtl] input[type=checkbox].CybotCookiebotDialogBodyLevelButton:focus+label{background-position:right 1px;padding:2px 17px 0 0}input[type=checkbox].CybotCookiebotDialogBodyLevelButton:checked:focus+label{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjk3MjVBRTM5QkQ4MDExRTM4RDBEOTEzMTQxN0RDRjc0IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjk3MjVBRTNBQkQ4MDExRTM4RDBEOTEzMTQxN0RDRjc0Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6OTcyNUFFMzdCRDgwMTFFMzhEMEQ5MTMxNDE3RENGNzQiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6OTcyNUFFMzhCRDgwMTFFMzhEMEQ5MTMxNDE3RENGNzQiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7V1txIAAAA6UlEQVR42mL8//8/AyMjIwMxQHwRgwOQAuEJjMRqBGoSAFL3gRhEf2BiIB7Mh2oCgQ+MpaWl/wnpuC5yluG05D5kIUcWENnd3c2Ix4kKQOo8km0TXsYxHGBCU2RAwIkXgJoKQQwmJE0gBeeBdAKSWAE0FGEgEcZgQQpmmIb5QD7YdCDuhynUf2XFsKvk2AUYH2bjBShGdt56JP4F/ZfWKO4HawS6+wMopNA0K8CCHogD0T0O9yMOzSDQCJR7gFMjmuYFUKEDQLEJ2KKJBV0AqjkRGEALsdiOqhFr6rkMpUsRQqB0DQMAAQYAX31KK0vr8I0AAAAASUVORK5CYII=);background-repeat:no-repeat;height:auto;width:auto;min-height:14px;display:inline-block;padding:1px 0 0 17px;background-position:left 1px;vertical-align:top;line-height:16px}div[dir=rtl] input[type=checkbox].CybotCookiebotDialogBodyLevelButton:checked:focus+label{background-position:right 1px;padding:2px 17px 0 0}#CybotCookiebotDialogBodyLevelDetailsWrapper{display:table-cell;background-color:#f6f6f9;border:1px solid #cccccc;border-left:none;height:14px;padding:4px 0 4px 4px;text-align:left;vertical-align:top;cursor:pointer}div[dir=rtl] #CybotCookiebotDialogBodyLevelDetailsWrapper{border:1px solid #cccccc;border-right:none;text-align:right;padding:4px 4px 4px 0}#CybotCookiebotDialogDetail{display:none;background-color:#ffffff;padding-top:0;padding-bottom:1px;overflow:auto}#CybotCookiebotDialogDetailBody{max-width:632px;padding:0 12px;vertical-align:top}div[dir=rtl] #CybotCookiebotDialogDetailBody{text-align:right}#CybotCookiebotDialogDetailBodyContent{background-color:#ffffff;color:#2a2a2a;border:1px solid #cccccc;border-bottom:4px solid #cccccc;height:170px}#CybotCookiebotDialogDetailBodyContent a{font-size:9pt}#CybotCookiebotDialogDetailBodyContentTabs a{font-size:10.5pt}#CybotCookiebotDialogDetailBodyContentText{padding:8px;font-size:10pt}#CybotCookiebotDialogDetailBodyContentTabs{position:relative;height:auto;display:inline-block;white-space:nowrap}.CybotCookiebotDialogDetailBodyContentTabsItem,.CybotCookiebotDialogDetailBodyContentTabsItemSelected{font-size:10.5pt;border-right:1px solid #cccccc;position:relative;top:1px;z-index:10;white-space:normal;line-height:100%;display:inline-block;border-top:1px solid #cccccc;font-weight:400}a.CybotCookiebotDialogDetailBodyContentTabsItem{margin:0;text-decoration:none!important}a.CybotCookiebotDialogDetailBodyContentTabsItem:hover{text-decoration:none!important;background-color:#ffffff!important;color:#2a2a2a!important;opacity:.9}a.CybotCookiebotDialogDetailBodyContentTabsItemSelected{margin:0;text-decoration:none!important;color:#2a2a2a!important;opacity:1}a.CybotCookiebotDialogDetailBodyContentTabsItemSelected:hover{text-decoration:none!important;color:#2a2a2a!important;cursor:default}.CybotCookiebotDialogDetailBodyContentTabsItem{background:#f6f6f9;color:#2a2a2a!important;opacity:.85;margin-top:1px;cursor:pointer;padding:7px 18px 5px}.CybotCookiebotDialogDetailBodyContentTabsItem:first-of-type{border-left:1px solid #cccccc}.CybotCookiebotDialogDetailBodyContentTabsItemSelected{background:#ffffff;color:#2a2a2a;padding:8px 18px 6px}.CybotCookiebotDialogDetailBodyContentTab:first-child{border-left:1px solid #cccccc;-webkit-border-radius:4px 0 0 0;-moz-border-radius:4px 0 0;border-radius:4px 0 0}div[dir=rtl] .CybotCookiebotDialogDetailBodyContentTab:first-child{border-left:none;-webkit-border-radius:0 4px 0 0;-moz-border-radius:0 4px 0 0;border-radius:0 4px 0 0}.CybotCookiebotDialogDetailBodyContentTab{border-left:none}div[dir=rtl] .CybotCookiebotDialogDetailBodyContentTab{border-left:1px solid #cccccc}#CybotCookiebotDialogDetailFooter{padding-top:4px;padding-right:2px;color:#2a2a2a;text-align:right;opacity:.85;background-color:#ffffff}div[dir=rtl] #CybotCookiebotDialogDetailFooter{text-align:left}#CybotCookiebotDialogDetailFooter a{color:#2a2a2a}#CybotCookiebotDialogDetailBodyContentTextAbout{padding:18px 12px 12px;font-size:9pt;height:140px;overflow:auto;display:none}#CybotCookiebotDialogDetailBodyContentTextOverview{display:inline-block}#CybotCookiebotDialogDetailBodyContentCookieContainerTypes{float:left;white-space:nowrap;padding:0;background-color:#f6f6f9;font-size:9pt}div[dir=rtl] #CybotCookiebotDialogDetailBodyContentCookieContainerTypes{float:right}#CybotCookiebotDialogDetailBodyContentCookieContainerTypeDetails{padding:12px;font-size:9pt;overflow:auto;height:146px;max-height:146px}.CybotCookiebotDialogDetailBodyContentCookieContainerTypesSelected{padding:8px;background-color:#ffffff;border-bottom:1px solid #cccccc;border-right:1px solid #ffffff;border-left:none;display:block;text-decoration:none!important;color:#2a2a2a!important}div[dir=rtl] .CybotCookiebotDialogDetailBodyContentCookieContainerTypesSelected{border-left:1px solid #ffffff;border-right:none}.CybotCookiebotDialogDetailBodyContentCookieContainerTypes{padding:8px;cursor:pointer;background-color:#f6f6f9;border-bottom:1px solid #cccccc;border-right:1px solid #cccccc;border-left:none;display:block;text-decoration:none!important;color:#2a2a2a!important;opacity:1}.CybotCookiebotDialogDetailBodyContentCookieContainerTypes:first-child{border-top:1px solid #cccccc}.CybotCookiebotDialogDetailBodyContentCookieContainerTypesSelected:first-child{border-top:1px solid #ffffff}.CybotCookiebotDialogDetailBodyContentCookieContainerTypes label,.CybotCookiebotDialogDetailBodyContentCookieContainerTypesSelected label{cursor:pointer;display:none}div[dir=rtl] .CybotCookiebotDialogDetailBodyContentCookieContainerTypes{border-left:1px solid #cccccc;border-right:none}a.CybotCookiebotDialogDetailBodyContentCookieContainerTypes:hover{text-decoration:none!important;background:#ffffff!important;color:#2a2a2a!important;opacity:1}a.CybotCookiebotDialogDetailBodyContentCookieContainerTypesSelected:hover{text-decoration:none!important;color:#2a2a2a!important;cursor:default}#CybotCookiebotDialogDetailBodyContentCookieTabsAdvertising,#CybotCookiebotDialogDetailBodyContentCookieTabsPreference,#CybotCookiebotDialogDetailBodyContentCookieTabsStatistics,#CybotCookiebotDialogDetailBodyContentCookieTabsUnclassified{display:none}.CybotCookiebotDialogDetailBodyContentCookieTypeTable{padding:0;margin:8px 0 0;font-size:9pt;border-spacing:0;border-collapse:collapse;width:100%}.CybotCookiebotDialogDetailBodyContentCookieTypeTable thead td,.CybotCookiebotDialogDetailBodyContentCookieTypeTable thead th{background-color:#f6f6f9!important;color:#2a2a2a!important;text-align:left;vertical-align:top;padding:2px;border-bottom:1px solid #cccccc;font-weight:400}div[dir=rtl] .CybotCookiebotDialogDetailBodyContentCookieTypeTable thead td,div[dir=rtl] .CybotCookiebotDialogDetailBodyContentCookieTypeTable thead th{text-align:right}.CybotCookiebotDialogDetailBodyContentCookieTypeTable tbody td{border-bottom:1px solid #cccccc;border-right:1px solid #cccccc;text-align:left;vertical-align:top;padding:4px;max-width:72px;overflow:hidden;font-size:9pt;color:#2a2a2a!important}.CybotCookiebotDialogDetailBodyContentCookieTypeTable tbody td:last-child{border-right:0}div[dir=rtl] .CybotCookiebotDialogDetailBodyContentCookieTypeTable tbody td{text-align:right}.CybotCookiebotDialogDetailBodyContentCookieTypeTable tbody td.CybotCookiebotDialogDetailBodyContentCookieTypeTableEmpty{border:none;border-top:1px solid #cccccc;padding:4px 0 0}</style></head>";
289
+
290
+ $keywords = array(
291
+ 'onesignal' => 'statistics',
292
+ 'facebook' => 'marketing'
293
+ );
294
+
295
+ $changed_header = cookiebot_addons_manipulate_script( $buffer, $keywords );
296
+
297
+ $this->assertNotFalse( strpos( $changed_header, 'data-cookieconsent="statistics" src=\'https://cdn.onesignal.com/sdks/OneSignalSDK.js\'' ) );
298
+ }
299
+ }
addons/tests/unit/test-previous-version-active.php ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace cookiebot_addons\tests\unit;
4
+
5
+ use cookiebot_addons\controller\addons\caos_host_analyticsjs_local_save_ga_local\CAOS_Host_Analyticsjs_Local_Save_Ga_Local;
6
+ use cookiebot_addons\controller\addons\caos_host_analyticsjs_local\CAOS_Host_Analyticsjs_Local;
7
+ use cookiebot_addons\lib\Settings_Service;
8
+
9
+ class Test_Previous_Version_Active extends \WP_UnitTestCase {
10
+
11
+ /**
12
+ * Test if older version has the latest plugin version
13
+ *
14
+ * @since 2.1.3
15
+ */
16
+ public function test_if_older_version_has_latest_plugin_version() {
17
+ $settings = new Settings_Service( new \stdClass() );
18
+
19
+ $scriptLoaderTagMock = $this->getMockBuilder( 'cookiebot_addons\lib\script_loader_tag\Script_Loader_Tag_Interface' )->getMock();
20
+ $cookieConsentMock = $this->getMockBuilder( 'cookiebot_addons\lib\Cookie_Consent_Interface' )->getMock();
21
+ $bufferOutputMock = $this->getMockBuilder( 'cookiebot_addons\lib\buffer\Buffer_Output_Interface' )->getMock();
22
+
23
+ $addon = $this->getMockBuilder( 'cookiebot_addons\controller\addons\caos_host_analyticsjs_local_save_ga_local\CAOS_Host_Analyticsjs_Local_Save_Ga_Local' )
24
+ ->setConstructorArgs(
25
+ array(
26
+ $settings,
27
+ $scriptLoaderTagMock,
28
+ $cookieConsentMock,
29
+ $bufferOutputMock
30
+ )
31
+ )
32
+ ->getMock();
33
+
34
+ $addon->expects( $this->any() )
35
+ ->method( 'is_addon_activated' )
36
+ ->will( $this->returnValue( true ) );
37
+
38
+ $addon->expects( $this->any() )
39
+ ->method( 'get_parent_class' )
40
+ ->will( $this->returnValue( 'CAOS_Host_Analyticsjs_Local' ) );
41
+
42
+ $this->assertTrue( $settings->is_previous_version_active( array( $addon ), 'CAOS_Host_Analyticsjs_Local' ) );
43
+ }
44
+
45
+ /**
46
+ * Test if newer version has the latest plugin version
47
+ *
48
+ * @since 2.1.3
49
+ */
50
+ public function test_if_newer_version_has_latest_plugin_version() {
51
+ $settings = new Settings_Service( new \stdClass() );
52
+
53
+ $scriptLoaderTagMock = $this->getMockBuilder( 'cookiebot_addons\lib\script_loader_tag\Script_Loader_Tag_Interface' )->getMock();
54
+ $cookieConsentMock = $this->getMockBuilder( 'cookiebot_addons\lib\Cookie_Consent_Interface' )->getMock();
55
+ $bufferOutputMock = $this->getMockBuilder( 'cookiebot_addons\lib\buffer\Buffer_Output_Interface' )->getMock();
56
+
57
+ $addon = $this->getMockBuilder( 'cookiebot_addons\controller\addons\caos_host_analyticsjs_local\CAOS_Host_Analyticsjs_Local' )
58
+ ->setConstructorArgs(
59
+ array(
60
+ $settings,
61
+ $scriptLoaderTagMock,
62
+ $cookieConsentMock,
63
+ $bufferOutputMock
64
+ )
65
+ )
66
+ ->getMock();
67
+
68
+ $addon->expects( $this->any() )
69
+ ->method( 'is_addon_activated' )
70
+ ->will( $this->returnValue( true ) );
71
+
72
+ $this->assertFalse( $settings->is_previous_version_active( array( $addon ), 'CAOS_Host_Analyticsjs_Local' ) );
73
+ }
74
+ }
addons/view/admin/settings/available-addon-callback.php ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $addon = $args['addon'];
3
+
4
+ require_once( ABSPATH . '/wp-includes/l10n.php' );
5
+ require_once( ABSPATH . '/wp-admin/includes/translation-install.php' );
6
+ ?>
7
+ <div class="postbox cookiebot-addon">
8
+ <p>
9
+ <label for="<?php echo 'enabled_' . $addon->get_option_name(); ?>"><?php _e( 'Enable', 'cookie' ); ?></label>
10
+ <input type="checkbox" id="<?php echo 'enabled_' . $addon->get_option_name(); ?>"
11
+ name="cookiebot_available_addons[<?php echo $addon->get_option_name() ?>][enabled]"
12
+ value="1" <?php checked( 1, $addon->is_addon_enabled(), true ); ?> />
13
+ </p>
14
+ <p><?php _e( 'Check one or multiple cookie types:', 'cookiebot' ); ?></p>
15
+ <ul class="cookietypes">
16
+ <li><input type="checkbox" id="cookie_type_preferences_<?php echo $addon->get_option_name(); ?>"
17
+ value="preferences"
18
+ <?php cookiebot_addons_checked_selected_helper( $addon->get_cookie_types(), 'preferences' ); ?>
19
+ name="cookiebot_available_addons[<?php echo $addon->get_option_name(); ?>][cookie_type][]"><label>Preferences</label>
20
+ </li>
21
+ <li><input type="checkbox" id="cookie_type_statistics_<?php echo $addon->get_option_name(); ?>"
22
+ value="statistics"
23
+ <?php cookiebot_addons_checked_selected_helper( $addon->get_cookie_types(), 'statistics' ); ?>
24
+ name="cookiebot_available_addons[<?php echo $addon->get_option_name(); ?>][cookie_type][]"><label>Statistics</label>
25
+ </li>
26
+ <li><input type="checkbox" id="cookie_type_marketing_<?php echo $addon->get_option_name(); ?>"
27
+ value="marketing"
28
+ <?php cookiebot_addons_checked_selected_helper( $addon->get_cookie_types(), 'marketing' ); ?>
29
+ name="cookiebot_available_addons[<?php echo $addon->get_option_name(); ?>][cookie_type][]"><label>Marketing</label>
30
+ </li>
31
+ </ul>
32
+
33
+ <p>
34
+ <label><?php _e( 'Display a placeholder', 'cookiebot-addons' ); ?></label>
35
+ <input type="checkbox"
36
+ class="placeholder_enable"
37
+ data-addon="<?php echo $addon->get_option_name(); ?>"
38
+ name="cookiebot_available_addons[<?php echo $addon->get_option_name(); ?>][placeholder][enabled]"
39
+ <?php checked( 1, $addon->is_placeholder_enabled() ); ?>
40
+ value="1">
41
+ </p>
42
+
43
+ <div class="placeholder"
44
+ data-addon="<?php echo $addon->get_option_name(); ?>" <?php echo ( ! $addon->is_placeholder_enabled() ) ? 'style="display:none"' : ''; ?>>
45
+ <?php if ( $addon->has_placeholder() ): ?>
46
+ <?php $count = 0; ?>
47
+ <?php foreach ( $addon->get_placeholders() as $placeholder_lang => $placeholder_value ): ?>
48
+ <div class="placeholder_content submitbox">
49
+ <p>
50
+ <label><?php _e( 'Language', 'cookiebot-addons' ); ?></label>
51
+ <?php
52
+ $name = 'cookiebot_available_addons[' . $addon->get_option_name() . '][placeholder][languages][' . $placeholder_lang . ']';
53
+ echo cookiebot_addons_get_dropdown_languages( 'placeholder_select_language', $name, $placeholder_lang );
54
+ ?>
55
+ <?php if ( $count != 0 ): ?>
56
+ <a href=""
57
+ class="submitdelete deletion"><?php _e( 'Remove language', 'cookiebot-addons' ); ?></a>
58
+ <?php endif; ?>
59
+ </p>
60
+ <p>
61
+ <textarea cols="60" rows="5"
62
+ name="cookiebot_available_addons[<?php echo $addon->get_option_name(); ?>][placeholder][languages][<?php echo $placeholder_lang; ?>]"><?php echo $placeholder_value; ?></textarea>
63
+ <span class="help-tip" title="<?php echo $addon->get_placeholder_helper(); ?>"></span>
64
+ </p>
65
+ </div>
66
+ <?php $count ++; ?>
67
+ <?php endforeach; ?>
68
+ <?php else: ?>
69
+ <div class="placeholder_content">
70
+ <p>
71
+ <label><?php _e( 'Language', 'cookiebot-addons' ); ?></label>
72
+ <select class="placeholder_select_language"
73
+ name="cookiebot_available_addons[<?php echo $addon->get_option_name(); ?>][placeholder][languages][site-default]">
74
+ <?php
75
+ if ( function_exists( 'cookiebot' ) ) {
76
+ ?>
77
+ <option value=""><?php _e( 'Default (Autodetect)', 'cookiebot' ); ?></option>
78
+ <?php
79
+ foreach ( wp_get_available_translations() as $key => $value ) {
80
+ echo '<option value="' . $key . '">' . $value . '</option>';
81
+ }
82
+ }
83
+ ?>
84
+ </select>
85
+ <?php
86
+ $name = 'cookiebot_available_addons[' . $addon->get_option_name() . '][placeholder][languages][site-default]';
87
+ echo cookiebot_addons_get_dropdown_languages( 'placeholder_select_language', $name, '' );
88
+ ?>
89
+ </p>
90
+ <p>
91
+ <textarea cols="80" rows="5"
92
+ name="cookiebot_available_addons[<?php echo $addon->get_option_name(); ?>][placeholder][languages][site-default]"><?php echo $addon->get_default_placeholder(); ?></textarea>
93
+ <span class="help-tip" title="<?php echo $addon->get_placeholder_helper(); ?>"></span>
94
+ </p>
95
+ </div>
96
+ <?php endif; ?>
97
+
98
+ <p class="add_placeholder_language">
99
+ <button class="btn_add_language button button-secondary"
100
+ data-addon="<?php echo $addon->get_option_name(); ?>"><?php _e( '+ Add language', 'cookiebot-addons' ); ?></button>
101
+ </p>
102
+ </div>
103
+ <?php if ( method_exists($addon,'has_remove_tag_option') && $addon->has_remove_tag_option() &&
104
+ defined( 'COOKIEBOT_OPTION_REMOVE_TAG' ) && COOKIEBOT_OPTION_REMOVE_TAG ): ?>
105
+ <p>
106
+ <input type="checkbox" id="<?php echo 'remove_tag_' . $addon->get_option_name(); ?>"
107
+ name="cookiebot_available_addons[<?php echo $addon->get_option_name() ?>][remove_tag]"
108
+ value="1" <?php checked( 1, $addon->is_remove_tag_enabled(), true ); ?> />
109
+ <label for="<?php echo 'remove_tag_' . $addon->get_option_name(); ?>"><?php _e( 'Remove script untill consent is given.', 'cookiebot-addons' ); ?></label>
110
+ <span class="help-tip" title="<?php _e("The script will be excluded from the DOM when the consent is not given. It will be included in the next page load after the consent is given. This option is included for better performance as the cookiebot will not scan the buffer to manipulate the attribute.", 'cookiebot-addons'); ?>"></span>
111
+
112
+ </p>
113
+ <?php endif; ?>
114
+ </div>
addons/view/admin/settings/jetpack-addon-callback.php ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $widget = $args['widget'];
3
+ $addon = $args['addon'];
4
+
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"
18
+ <?php cookiebot_addons_checked_selected_helper( $widget->get_widget_cookie_types( $widget->get_widget_option_name() ), 'preferences' ); ?>
19
+ name="cookiebot_jetpack_addon[<?php echo $widget->get_widget_option_name(); ?>][cookie_type][]"><label>Preferences</label>
20
+ </li>
21
+ <li><input type="checkbox" id="cookie_type_statistics_<?php echo $widget->get_widget_option_name(); ?>"
22
+ value="statistics"
23
+ <?php cookiebot_addons_checked_selected_helper( $widget->get_widget_cookie_types( $widget->get_widget_option_name() ), 'statistics' ); ?>
24
+ name="cookiebot_jetpack_addon[<?php echo $widget->get_widget_option_name(); ?>][cookie_type][]"><label>Statistics</label>
25
+ </li>
26
+ <li><input type="checkbox" id="cookie_type_marketing_<?php echo $widget->get_widget_option_name(); ?>"
27
+ value="marketing"
28
+ <?php cookiebot_addons_checked_selected_helper( $widget->get_widget_cookie_types( $widget->get_widget_option_name() ), 'marketing' ); ?>
29
+ name="cookiebot_jetpack_addon[<?php echo $widget->get_widget_option_name(); ?>][cookie_type][]"><label>Marketing</label>
30
+ </li>
31
+ </ul>
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(); ?>"
39
+ name="cookiebot_jetpack_addon[<?php echo $widget->get_widget_option_name(); ?>][placeholder][enabled]"
40
+ <?php checked( 1, $widget->is_widget_placeholder_enabled() ); ?>
41
+ value="1">
42
+ </p>
43
+
44
+ <div class="placeholder"
45
+ data-addon="<?php echo $widget->get_widget_option_name(); ?>" <?php echo ( ! $widget->is_widget_placeholder_enabled() ) ? 'style="display:none"' : ''; ?>>
46
+ <?php if ( $widget->widget_has_placeholder() ): ?>
47
+ <?php $count = 0; ?>
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>
62
+ <textarea cols="60" rows="5"
63
+ name="cookiebot_jetpack_addon[<?php echo $widget->get_widget_option_name(); ?>][placeholder][languages][<?php echo $placeholder_lang; ?>]"><?php echo $placeholder_value; ?></textarea>
64
+ <span class="help-tip" title="<?php echo $addon->get_placeholder_helper(); ?>"></span>
65
+ </p>
66
+ </div>
67
+ <?php $count ++; ?>
68
+ <?php endforeach; ?>
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, '' );
76
+ ?>
77
+ </p>
78
+ <p>
79
+ <textarea cols="80" rows="5"
80
+ name="cookiebot_jetpack_addon[<?php echo $widget->get_widget_option_name(); ?>][placeholder][languages][site-default]"><?php echo $widget->get_default_placeholder(); ?></textarea>
81
+ <span class="help-tip" title="<?php echo $addon->get_placeholder_helper(); ?>"></span>
82
+ </p>
83
+ </div>
84
+ <?php endif; ?>
85
+
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
+ <?php if ( method_exists($widget,'has_remove_tag_option') && $widget->has_remove_tag_option() &&
93
+ defined( 'COOKIEBOT_OPTION_REMOVE_TAG' ) && COOKIEBOT_OPTION_REMOVE_TAG ): ?>
94
+ <p>
95
+ <input type="checkbox" id="<?php echo 'remove_tag_' . $widget->get_widget_option_name(); ?>"
96
+ name="cookiebot_jetpack_addon[<?php echo $widget->get_widget_option_name() ?>][remove_tag]"
97
+ value="1" <?php checked( 1, $widget->is_widget_remove_tag_enabled(), true ); ?> />
98
+ <label for="<?php echo 'remove_tag_' . $widget->get_widget_option_name(); ?>"><?php _e( 'Remove script untill consent is given.', 'cookiebot-addons' ); ?></label>
99
+ <span class="help-tip" title="<?php _e("The script will be excluded from the DOM when the consent is not given. It will be included in the next page load after the consent is given. This option is included for better performance as the cookiebot will not scan the buffer to manipulate the attribute.", 'cookiebot-addons'); ?>"></span>
100
+
101
+ </p>
102
+ <?php endif; ?>
103
+ </div>
addons/view/admin/settings/setting-page.php ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!-- Create a header in the default WordPress 'wrap' container -->
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
+
22
+ </div>
23
+ <?php
24
+ if ( defined( 'COOKIEBOT_ADDONS_UNSUPPORTED_PHPVERSION' ) ) {
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
32
+ }
33
+ else {
34
+ ?>
35
+ <?php if ( isset( $_GET['tab'] ) ) {
36
+ $active_tab = $_GET['tab'];
37
+ } else if ( $active_tab == 'unavailable_addons' ) {
38
+ $active_tab = 'unavailable_addons';
39
+ } else {
40
+ $active_tab = 'available_addons';
41
+ } ?>
42
+
43
+ <h2 class="nav-tab-wrapper">
44
+ <a href="?page=cookiebot-addons&tab=available_addons"
45
+ class="nav-tab <?php echo $active_tab == 'available_addons' ? 'nav-tab-active' : ''; ?>">Available
46
+ Plugins</a>
47
+ <a href="?page=cookiebot-addons&tab=unavailable_addons"
48
+ class="nav-tab <?php echo $active_tab == 'unavailable_addons' ? 'nav-tab-active' : ''; ?>">Unavailable
49
+ Plugins</a>
50
+ <?php
51
+ if ( is_plugin_active( 'jetpack/jetpack.php' ) ) {
52
+ ?>
53
+ <a href="?page=cookiebot-addons&tab=jetpack"
54
+ class="nav-tab <?php echo $active_tab == 'jetpack' ? 'nav-tab-active' : ''; ?>">Jetpack</a>
55
+ <?php
56
+ }
57
+ ?>
58
+
59
+ </h2>
60
+
61
+ <form method="post" action="options.php" class="<?php echo $active_tab; ?>">
62
+ <?php
63
+
64
+ if ( $active_tab == 'available_addons' ) {
65
+ settings_fields( 'cookiebot_available_addons' );
66
+ do_settings_sections( 'cookiebot-addons' );
67
+ } elseif ( $active_tab == 'jetpack' ) {
68
+ settings_fields( 'cookiebot_jetpack_addon' );
69
+ do_settings_sections( 'cookiebot-addons' );
70
+ } else {
71
+ settings_fields( 'cookiebot_not_installed_options' );
72
+ do_settings_sections( 'cookiebot-addons' );
73
+ } // end if/else
74
+
75
+ submit_button();
76
+
77
+ ?>
78
+ </form>
79
+ <?php
80
+ }
81
+ ?>
82
+ </div><!-- /.wrap -->
assets/guide_add_language.gif ADDED
Binary file
assets/icon.svg ADDED
@@ -0,0 +1 @@
 
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 75.590554 75.590549"><g fill="#39a8ef" fill-rule="evenodd"><path d="M48.79525367 19.69869148C43.86310823 14.30427459 36.75671475 10.91895 28.8569608 10.91895c-14.89357147 0-26.967197 12.03291698-26.967197 26.87627322 0 14.84335525 12.07362553 26.87627323 26.967197 26.87627323 7.89975395 0 15.00614743-3.3853245 19.93829287-8.77974218-2.89172428-1.3698268-5.40310078-3.40782928-7.33322758-5.91378297-3.12362093 3.21166268-7.49825333 5.20778178-12.34068085 5.20778178-9.49100206 0-17.18497868-7.66803642-17.18497868-17.12703704 0-9.45900162 7.69397662-17.12703703 17.18497868-17.12703703 4.72679741 0 9.0078732 1.90192802 12.1147894 4.97980187 1.95829657-2.64298481 4.55321967-4.78887696 7.55911903-6.2127894z"/><path d="M57.30896325 53.59908517c-9.05295481 0-16.39182535-7.31412618-16.39182535-16.33655758 0-9.0224324 7.33887054-16.33655859 16.39182535-16.33655859 9.05295581 0 16.39182535 7.31412618 16.39182535 16.33655859 0 9.0224314-7.33886954 16.33655758-16.39182535 16.33655758zm.02132496-7.76107767c4.74035292 0 8.5831683-3.8298583 8.5831683-8.554228 0-4.72436972-3.84281538-8.554228-8.5831683-8.554228-4.74035192 0-8.5831673 3.82985828-8.5831673 8.554228 0 4.7243697 3.84281538 8.554228 8.5831673 8.554228z"/></g></svg>
cookiebot-logo.png ADDED
Binary file
cookiebot.php ADDED
@@ -0,0 +1,1128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Plugin Name: Cookiebot | GDPR Compliant Cookie Consent and Notice
4
+ Plugin URI: https://cookiebot.com/
5
+ Description: Cookiebot is a fully GDPR & ePrivacy compliant cookie consent solution supporting prior consent, cookie declaration, and documentation of consents. Easy to install, implement and configure.
6
+ Author: Cybot A/S
7
+ Version: 2.3.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 = '2.3.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('plugins_loaded', array($this, 'cookiebot_init'), 5);
58
+ register_activation_hook( __FILE__ , array($this, 'activation'));
59
+ register_deactivation_hook( __FILE__, 'cookiebot_addons_plugin_deactivated' );
60
+ }
61
+
62
+ /**
63
+ * Cookiebot_WP Installation actions
64
+ *
65
+ * @version 2.1.4
66
+ * @since 2.1.4
67
+ * @accces public
68
+ */
69
+ function activation() {
70
+ //Delay display of recommendation notice in 3 days if not activated ealier
71
+ if(get_option('cookiebot_notice_recommend',false) === false) {
72
+ //Not set yet - this must be first activation - delay in 3 days
73
+ update_option('cookiebot_notice_recommend', strtotime('+3 days'));
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Cookiebot_WP Init Cookiebot.
79
+ *
80
+ * @version 2.2.0
81
+ * @since 1.6.2
82
+ * @access public
83
+ */
84
+ function cookiebot_init() {
85
+ /* Load Cookiebot Addons Framework */
86
+ $dismissAddons = false;
87
+ if(defined('CAF_DIR')) {
88
+ $dismissAddons = true;
89
+ /*add_action('admin_notices', function() {
90
+ ?>
91
+ <div class="notice notice-warning">
92
+ <p>
93
+ <?php _e( 'You have Cookiebot Addons installed.', 'cookiebot' ); ?><br />
94
+ <?php _e( 'In this and future releases of Cookiebot all available Addons are bundled directly with the Cookiebot plugin.', 'cookiebot' ); ?><br />
95
+ <?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' ); ?>
96
+ </p>
97
+ </div>
98
+ <?php
99
+ });*/
100
+ }
101
+ else {
102
+ if( (!defined('COOKIEBOT_ADDONS_STANDALONE') || COOKIEBOT_ADDONS_STANDALONE != true || !defined('COOKIE_ADDONS_LOADED')) && $dismissAddons !== true ) {
103
+ //Make sure we got a PHP version that works
104
+ if(version_compare(PHP_VERSION, '5.4.0', '>=')) {
105
+ include_once('addons/cookiebot-addons-init.php');
106
+ }
107
+ else {
108
+ define('COOKIEBOT_ADDONS_UNSUPPORTED_PHPVERSION',true);
109
+ }
110
+ }
111
+ else {
112
+ add_action('admin_notices', function() {
113
+ ?>
114
+ <div class="notice notice-warning">
115
+ <p>
116
+ <?php _e( 'You are using Cookiebot Addons Standalone.', 'cookiebot' ); ?>
117
+ </p>
118
+ </div>
119
+ <?php
120
+ });
121
+ }
122
+ }
123
+ if(is_admin()) {
124
+
125
+ //Adding menu to WP admin
126
+ add_action('admin_menu', array($this,'add_menu'),1);
127
+
128
+ if(is_multisite()) {
129
+ add_action('network_admin_menu', array($this,'add_network_menu'),1);
130
+ add_action('network_admin_edit_cookiebot_network_settings', array($this,'network_settings_save'));
131
+ }
132
+
133
+ //Register settings
134
+ add_action('admin_init', array($this,'register_cookiebot_settings'));
135
+
136
+ //Adding dashboard widgets
137
+ add_action('wp_dashboard_setup', array($this,'add_dashboard_widgets'));
138
+
139
+ add_action('admin_notices', array( $this, 'cookiebot_admin_notices' ) );
140
+ add_action('admin_init', array($this,'save_notice_link'));
141
+
142
+ //Check if we should show cookie consent banner on admin pages
143
+ $addJSAdmin = true;
144
+ if(is_multisite() && get_site_option('cookiebot-nooutput-admin',false)) {
145
+ $addJSAdmin = false;
146
+ }
147
+ elseif(get_option('cookiebot-nooutput-admin',false)) {
148
+ $addJSAdmin = false;
149
+ }
150
+ if($addJSAdmin) {
151
+ //adding cookie banner in admin area too
152
+ add_action('admin_head', array($this,'add_js'));
153
+ }
154
+ }
155
+
156
+
157
+ // Set up localisation
158
+ load_plugin_textdomain('cookiebot', false, dirname( plugin_basename( __FILE__ ) ) . '/langs/' );
159
+
160
+ //add JS
161
+ add_action('wp_head', array($this,'add_js'));
162
+ add_shortcode('cookie_declaration', array($this,'show_declaration'));
163
+
164
+ //Add filter if WP rocket is enabled
165
+ if(defined('WP_ROCKET_VERSION')) {
166
+ add_filter('rocket_minify_excluded_external_js', array($this,'wp_rocket_exclude_external_js'));
167
+ }
168
+
169
+ //Automatic update plugin
170
+ if(is_admin() || (defined('DOING_CRON') && DOING_CRON)) {
171
+ add_filter('auto_update_plugin', array($this,'automatic_updates'), 10, 2);
172
+ }
173
+ }
174
+
175
+ /**
176
+ * Cookiebot_WP Load text domain
177
+ *
178
+ * @version 2.0.0
179
+ * @since 2.0.0
180
+ */
181
+ function load_textdomain() {
182
+ load_plugin_textdomain( 'cookiebot', false, basename( dirname( __FILE__ ) ) . '/langs' );
183
+ }
184
+
185
+ /**
186
+ * Cookiebot_WP Add dashboard widgets to admin
187
+ *
188
+ * @version 1.0.0
189
+ * @since 1.0.0
190
+ */
191
+
192
+ function add_dashboard_widgets() {
193
+ wp_add_dashboard_widget('cookiebot_status', __('Cookiebot Status','cookiebot'), array($this,'dashboard_widget_status'));
194
+ }
195
+
196
+ /**
197
+ * Cookiebot_WP Output Dashboard Status Widget
198
+ *
199
+ * @version 1.0.0
200
+ * @since 1.0.0
201
+ */
202
+ function dashboard_widget_status() {
203
+ $cbid = $this->get_cbid();
204
+ if(empty($cbid)) {
205
+ echo '<p>'.__('You need to enter your Cookiebot ID.','cookiebot').'</p>';
206
+ echo '<p><a href="options-general.php?page=cookiebot">';
207
+ echo __('Update your Cookiebot ID','cookiebot');
208
+ echo '</a></p>';
209
+ }
210
+ else {
211
+ echo '<p>'._e('Your Cookiebot is working!','cookiebot').'</p>';
212
+ }
213
+ }
214
+
215
+ /**
216
+ * Cookiebot_WP Add option menu page for Cookiebot
217
+ *
218
+ * @version 2.2.0
219
+ * @since 1.0.0
220
+ */
221
+ function add_menu() {
222
+ //Cookiebot Icon SVG base64 encoded
223
+ $icon = 'data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNTQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGcgZmlsbD0iI0ZGRkZGRiIgZmlsbC1ydWxlPSJldmVub2RkIj48cGF0aCBkPSJNNDYuODcyNTkwMyA4Ljc3MzU4MzM0QzQxLjk0MzkwMzkgMy4zODI5NTAxMSAzNC44NDI0OTQ2IDAgMjYuOTQ4MjgxOSAwIDEyLjA2NTE1NjggMCAwIDEyLjAyNDQ3NzQgMCAyNi44NTc0MjE5YzAgMTQuODMyOTQ0NSAxMi4wNjUxNTY4IDI2Ljg1NzQyMTkgMjYuOTQ4MjgxOSAyNi44NTc0MjE5IDcuODk0MjEyNyAwIDE0Ljk5NTYyMi0zLjM4Mjk1MDIgMTkuOTI0MzA4NC04Ljc3MzU4MzQtMi44ODk2OTY3LTEuMzY4ODY2My01LjM5OTMxMS0zLjQwNTQzOS03LjMyODA4MzgtNS45MDk2MzU4LTMuMTIxNDMwNiAzLjIwOTQxMDQtNy40OTI5OTQ0IDUuMjA0MTI5MS0xMi4zMzIwMjU4IDUuMjA0MTI5MS05LjQ4NDM0NDQgMC0xNy4xNzI5MjQ3LTcuNjYyNjU3Mi0xNy4xNzI5MjQ3LTE3LjExNTAyMzhzNy42ODg1ODAzLTE3LjExNTAyMzcgMTcuMTcyOTI0Ny0xNy4xMTUwMjM3YzQuNzIzNDgyMiAwIDkuMDAxNTU1MiAxLjkwMDU5MzkgMTIuMTA2MjkyIDQuOTc2MzA5IDEuOTU2OTIzNy0yLjY0MTEzMSA0LjU1MDAyNjMtNC43ODU1MTgzIDcuNTUzODE3Ni02LjIwODQzMTg2eiIvPjxwYXRoIGQ9Ik01NS4zODAzMjgyIDQyLjY1MDE5OTFDNDYuMzMzNzIyNyA0Mi42NTAxOTkxIDM5IDM1LjM0MTIwMzEgMzkgMjYuMzI1MDk5NiAzOSAxNy4zMDg5OTYgNDYuMzMzNzIyNyAxMCA1NS4zODAzMjgyIDEwYzkuMDQ2NjA1NSAwIDE2LjM4MDMyODIgNy4zMDg5OTYgMTYuMzgwMzI4MiAxNi4zMjUwOTk2IDAgOS4wMTYxMDM1LTcuMzMzNzIyNyAxNi4zMjUwOTk1LTE2LjM4MDMyODIgMTYuMzI1MDk5NXptLjAyMTMwOTItNy43NTU2MzQyYzQuNzM3MDI3NiAwIDguNTc3MTQ3MS0zLjgyNzE3MiA4LjU3NzE0NzEtOC41NDgyMjc5IDAtNC43MjEwNTYtMy44NDAxMTk1LTguNTQ4MjI4LTguNTc3MTQ3MS04LjU0ODIyOC00LjczNzAyNzUgMC04LjU3NzE0NyAzLjgyNzE3Mi04LjU3NzE0NyA4LjU0ODIyOCAwIDQuNzIxMDU1OSAzLjg0MDExOTUgOC41NDgyMjc5IDguNTc3MTQ3IDguNTQ4MjI3OXoiLz48L2c+PC9zdmc+';
224
+ add_menu_page( 'Cookiebot', __('Cookiebot','cookiebot'), 'manage_options', 'cookiebot', array($this,'settings_page'),$icon);
225
+
226
+ add_submenu_page('cookiebot',__('Cookiebot Settings','cookiebot'),__('Settings','cookiebot'), 'manage_options', 'cookiebot',array($this,'settings_page'));
227
+ add_submenu_page('cookiebot',__('Cookiebot Support','cookiebot'),__('Support','cookiebot'), 'manage_options', 'cookiebot_support',array($this,'support_page'));
228
+ add_submenu_page('cookiebot',__('IAB','cookiebot'),__('IAB','cookiebot'), 'manage_options', 'cookiebot_iab',array($this,'iab_page'));
229
+
230
+ if(defined('COOKIEBOT_ADDONS_UNSUPPORTED_PHPVERSION')) {
231
+ //Load prior consent page anyway - but from Cookiebot WP Core plugin.
232
+ add_submenu_page( 'cookiebot', __( 'Prior Consent', 'cookiebot' ), __( 'Prior Consent', 'cookiebot' ), 'manage_options', 'cookiebot-addons', array($this,'setting_page_placeholder' ) );
233
+ }
234
+ }
235
+
236
+ /**
237
+ * Cookiebot_WP Add menu for network sites
238
+ *
239
+ * @version 2.2.0
240
+ * @since 2.2.0
241
+ */
242
+ function add_network_menu() {
243
+ $icon = 'data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNTQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGcgZmlsbD0iI0ZGRkZGRiIgZmlsbC1ydWxlPSJldmVub2RkIj48cGF0aCBkPSJNNDYuODcyNTkwMyA4Ljc3MzU4MzM0QzQxLjk0MzkwMzkgMy4zODI5NTAxMSAzNC44NDI0OTQ2IDAgMjYuOTQ4MjgxOSAwIDEyLjA2NTE1NjggMCAwIDEyLjAyNDQ3NzQgMCAyNi44NTc0MjE5YzAgMTQuODMyOTQ0NSAxMi4wNjUxNTY4IDI2Ljg1NzQyMTkgMjYuOTQ4MjgxOSAyNi44NTc0MjE5IDcuODk0MjEyNyAwIDE0Ljk5NTYyMi0zLjM4Mjk1MDIgMTkuOTI0MzA4NC04Ljc3MzU4MzQtMi44ODk2OTY3LTEuMzY4ODY2My01LjM5OTMxMS0zLjQwNTQzOS03LjMyODA4MzgtNS45MDk2MzU4LTMuMTIxNDMwNiAzLjIwOTQxMDQtNy40OTI5OTQ0IDUuMjA0MTI5MS0xMi4zMzIwMjU4IDUuMjA0MTI5MS05LjQ4NDM0NDQgMC0xNy4xNzI5MjQ3LTcuNjYyNjU3Mi0xNy4xNzI5MjQ3LTE3LjExNTAyMzhzNy42ODg1ODAzLTE3LjExNTAyMzcgMTcuMTcyOTI0Ny0xNy4xMTUwMjM3YzQuNzIzNDgyMiAwIDkuMDAxNTU1MiAxLjkwMDU5MzkgMTIuMTA2MjkyIDQuOTc2MzA5IDEuOTU2OTIzNy0yLjY0MTEzMSA0LjU1MDAyNjMtNC43ODU1MTgzIDcuNTUzODE3Ni02LjIwODQzMTg2eiIvPjxwYXRoIGQ9Ik01NS4zODAzMjgyIDQyLjY1MDE5OTFDNDYuMzMzNzIyNyA0Mi42NTAxOTkxIDM5IDM1LjM0MTIwMzEgMzkgMjYuMzI1MDk5NiAzOSAxNy4zMDg5OTYgNDYuMzMzNzIyNyAxMCA1NS4zODAzMjgyIDEwYzkuMDQ2NjA1NSAwIDE2LjM4MDMyODIgNy4zMDg5OTYgMTYuMzgwMzI4MiAxNi4zMjUwOTk2IDAgOS4wMTYxMDM1LTcuMzMzNzIyNyAxNi4zMjUwOTk1LTE2LjM4MDMyODIgMTYuMzI1MDk5NXptLjAyMTMwOTItNy43NTU2MzQyYzQuNzM3MDI3NiAwIDguNTc3MTQ3MS0zLjgyNzE3MiA4LjU3NzE0NzEtOC41NDgyMjc5IDAtNC43MjEwNTYtMy44NDAxMTk1LTguNTQ4MjI4LTguNTc3MTQ3MS04LjU0ODIyOC00LjczNzAyNzUgMC04LjU3NzE0NyAzLjgyNzE3Mi04LjU3NzE0NyA4LjU0ODIyOCAwIDQuNzIxMDU1OSAzLjg0MDExOTUgOC41NDgyMjc5IDguNTc3MTQ3IDguNTQ4MjI3OXoiLz48L2c+PC9zdmc+';
244
+ add_menu_page( 'Cookiebot', __('Cookiebot','cookiebot'), 'manage_network_options', 'cookiebot_network', array($this,'network_settings_page'),$icon);
245
+
246
+ add_submenu_page('cookiebot_network',__('Cookiebot Settings','cookiebot'),__('Settings','cookiebot'), 'network_settings_page', 'cookiebot_network',array($this,'network_settings_page'));
247
+ add_submenu_page('cookiebot_network',__('Cookiebot Support','cookiebot'),__('Support','cookiebot'), 'network_settings_page', 'cookiebot_support',array($this,'support_page'));
248
+
249
+ }
250
+
251
+ /**
252
+ * Cookiebot_WP Cookiebot prior consent placeholder page
253
+ *
254
+ * @version 1.4.0
255
+ * @since 1.0.0
256
+ */
257
+ function setting_page_placeholder() {
258
+ include __DIR__ . DIRECTORY_SEPARATOR . 'addons' . DIRECTORY_SEPARATOR . 'view/admin/settings/setting-page.php';
259
+ }
260
+
261
+ /**
262
+ * Cookiebot_WP Register Cookiebot settings
263
+ *
264
+ * @version 2.1.5
265
+ * @since 1.0.0
266
+ */
267
+ function register_cookiebot_settings() {
268
+ register_setting('cookiebot', 'cookiebot-cbid');
269
+ register_setting('cookiebot', 'cookiebot-language');
270
+ register_setting('cookiebot', 'cookiebot-nooutput');
271
+ register_setting('cookiebot', 'cookiebot-nooutput-admin');
272
+ register_setting('cookiebot', 'cookiebot-autoupdate');
273
+ register_setting('cookiebot', 'cookiebot-script-tag-uc-attribute');
274
+ register_setting('cookiebot', 'cookiebot-script-tag-cd-attribute');
275
+ register_setting('cookiebot-iab', 'cookiebot-iab');
276
+ }
277
+
278
+ /**
279
+ * Cookiebot_WP Automatic update plugin if activated
280
+ *
281
+ * @version 2.2.0
282
+ * @since 1.5.0
283
+ */
284
+ function automatic_updates($update, $item) {
285
+ //Do not update from subsite on a multisite installation
286
+ if(is_multisite() && ! is_main_site()) {
287
+ return $update;
288
+ }
289
+
290
+ //Check if we have everything we need
291
+ $item = (array)$item;
292
+ if(!isset($item['new_version']) || !isset($item['slug'])) {
293
+ return $update;
294
+ }
295
+
296
+ //It is not Cookiebot
297
+ if($item['slug'] !== 'cookiebot') {
298
+ return $update;
299
+ }
300
+
301
+ // Check if cookiebot autoupdate is disabled
302
+ if(!get_option('cookiebot-autoupdate',true)) {
303
+ return $update;
304
+ }
305
+
306
+ // Check if multisite autoupdate is disabled
307
+ if(is_multisite() && !get_site_option('cookiebot-autoupdate',true)) {
308
+ return $update;
309
+ }
310
+
311
+ return true;
312
+ }
313
+
314
+
315
+ /**
316
+ * Cookiebot_WP Get list of supported languages
317
+ *
318
+ * @version 1.4.0
319
+ * @since 1.4.0
320
+ */
321
+ function get_supported_languages() {
322
+ $supportedLanguages = array();
323
+ $supportedLanguages['nb'] = __('Norwegian Bokmål','cookiebot');
324
+ $supportedLanguages['tr'] = __('Turkish','cookiebot');
325
+ $supportedLanguages['de'] = __('German','cookiebot');
326
+ $supportedLanguages['cs'] = __('Czech','cookiebot');
327
+ $supportedLanguages['da'] = __('Danish','cookiebot');
328
+ $supportedLanguages['sq'] = __('Albanian','cookiebot');
329
+ $supportedLanguages['he'] = __('Hebrew','cookiebot');
330
+ $supportedLanguages['ko'] = __('Korean','cookiebot');
331
+ $supportedLanguages['it'] = __('Italian','cookiebot');
332
+ $supportedLanguages['nl'] = __('Dutch','cookiebot');
333
+ $supportedLanguages['vi'] = __('Vietnamese','cookiebot');
334
+ $supportedLanguages['ta'] = __('Tamil','cookiebot');
335
+ $supportedLanguages['is'] = __('Icelandic','cookiebot');
336
+ $supportedLanguages['ro'] = __('Romanian','cookiebot');
337
+ $supportedLanguages['si'] = __('Sinhala','cookiebot');
338
+ $supportedLanguages['ca'] = __('Catalan','cookiebot');
339
+ $supportedLanguages['bg'] = __('Bulgarian','cookiebot');
340
+ $supportedLanguages['uk'] = __('Ukrainian','cookiebot');
341
+ $supportedLanguages['zh'] = __('Chinese','cookiebot');
342
+ $supportedLanguages['en'] = __('English','cookiebot');
343
+ $supportedLanguages['ar'] = __('Arabic','cookiebot');
344
+ $supportedLanguages['hr'] = __('Croatian','cookiebot');
345
+ $supportedLanguages['th'] = __('Thai','cookiebot');
346
+ $supportedLanguages['el'] = __('Greek','cookiebot');
347
+ $supportedLanguages['lt'] = __('Lithuanian','cookiebot');
348
+ $supportedLanguages['pl'] = __('Polish','cookiebot');
349
+ $supportedLanguages['lv'] = __('Latvian','cookiebot');
350
+ $supportedLanguages['fr'] = __('French','cookiebot');
351
+ $supportedLanguages['id'] = __('Indonesian','cookiebot');
352
+ $supportedLanguages['mk'] = __('Macedonian','cookiebot');
353
+ $supportedLanguages['et'] = __('Estonian','cookiebot');
354
+ $supportedLanguages['pt'] = __('Portuguese','cookiebot');
355
+ $supportedLanguages['ga'] = __('Irish','cookiebot');
356
+ $supportedLanguages['ms'] = __('Malay','cookiebot');
357
+ $supportedLanguages['sl'] = __('Slovenian','cookiebot');
358
+ $supportedLanguages['ru'] = __('Russian','cookiebot');
359
+ $supportedLanguages['ja'] = __('Japanese','cookiebot');
360
+ $supportedLanguages['hi'] = __('Hindi','cookiebot');
361
+ $supportedLanguages['sk'] = __('Slovak','cookiebot');
362
+ $supportedLanguages['es'] = __('Spanish','cookiebot');
363
+ $supportedLanguages['sv'] = __('Swedish','cookiebot');
364
+ $supportedLanguages['sr'] = __('Serbian','cookiebot');
365
+ $supportedLanguages['fi'] = __('Finnish','cookiebot');
366
+ $supportedLanguages['eu'] = __('Basque','cookiebot');
367
+ asort($supportedLanguages,SORT_LOCALE_STRING);
368
+ return $supportedLanguages;
369
+ }
370
+
371
+ /**
372
+ * Cookiebot_WP Output settings page
373
+ *
374
+ * @version 2.2.0
375
+ * @since 1.0.0
376
+ */
377
+ function settings_page() {
378
+ /* Check if multisite */
379
+ if($is_ms = is_multisite()) {
380
+ //Receive settings from multisite - this might change the way we render the form
381
+ $network_cbid = get_site_option('cookiebot-cbid','');
382
+ $network_scrip_tag_uc_attr = get_site_option('cookiebot-script-tag-uc-attribute','custom');
383
+ $network_scrip_tag_cd_attr = get_site_option('cookiebot-script-tag-cd-attribute','custom');
384
+ }
385
+ ?>
386
+ <div class="wrap">
387
+ <h1><?php _e('Cookiebot Settings','cookiebot'); ?></h1>
388
+ <a href="https://www.cookiebot.com">
389
+ <img src="<?php echo plugins_url( 'cookiebot-logo.png', __FILE__ ); ?>" style="float:right;margin-left:1em;">
390
+ </a>
391
+ <p>
392
+ <?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/en/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'); ?>
393
+ </p>
394
+ <form method="post" action="options.php">
395
+ <?php settings_fields( 'cookiebot' ); ?>
396
+ <?php do_settings_sections( 'cookiebot' ); ?>
397
+ <table class="form-table">
398
+ <tr valign="top">
399
+ <th scope="row"><?php _e('Cookiebot ID','cookiebot'); ?></th>
400
+ <td>
401
+ <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" />
402
+ <p class="description">
403
+ <?php _e('Need an ID?','cookiebot'); ?>
404
+ <a href="https://www.cookiebot.com/en/signup" target="_blank"><?php _e('Sign up for free on cookiebot.com','cookiebot'); ?></a>
405
+ </p>
406
+ </td>
407
+ </tr>
408
+ <tr valign="top">
409
+ <th scope="row"><?php _e('Cookiebot Language','cookiebot'); ?></th>
410
+ <td>
411
+ <div>
412
+ <select name="cookiebot-language" id="cookiebot-language">
413
+ <?php
414
+ $currentLang = $this->get_language(true);
415
+ ?>
416
+ <option value=""><?php _e('Default (Autodetect)','cookiebot'); ?></option>
417
+ <option value="_wp"<?php echo ($currentLang == '_wp') ? ' selected' : ''; ?>><?php _e('Use Wordpress Language','cookiebot'); ?></option>
418
+ <?php
419
+ $supportedLanguages = $this->get_supported_languages();
420
+ foreach($supportedLanguages as $langCode=>$langName) {
421
+ echo '<option value="'.$langCode.'"'.(($currentLang==$langCode) ? ' selected' : '').'>'.$langName.'</option>';
422
+ }
423
+ ?>
424
+ </select>
425
+ </div>
426
+ <div class="notice inline notice-warning notice-alt cookiebot-notice" style="padding:12px;font-size:13px;display:inline-block;">
427
+ <div style="<?php echo ($currentLang=='') ? 'display:none;' : '' ?>" id="info_lang_specified">
428
+ <?php _e('You need to add the language in the Cookiebot administration tool.'); ?>
429
+ </div>
430
+ <div style="<?php echo ($currentLang=='') ? '' : 'display:none;' ?>" id="info_lang_autodetect">
431
+ <?php _e('You need to add all languages that you want auto-detected in the Cookiebot administration tool.'); ?> <br/>
432
+ <?php _e('The auto-detect checkbox needs to be enabled in the Cookiebot administration tool.'); ?><br/>
433
+ <?php _e('If the auto-detected language is not supported, Cookiebot will use the default language.'); ?>
434
+ </div>
435
+ <br />
436
+
437
+ <a href="#" id="show_add_language_guide"><?php _e('Show guide to add languages'); ?></a>
438
+ &nbsp;
439
+ <a href="https://support.cookiebot.com/hc/en-us/articles/360003793394-How-do-I-set-the-language-of-the-consent-banner-dialog-" target="_blank">
440
+ <?php _e('Read more here'); ?>
441
+ </a>
442
+
443
+ <div id="add_language_guide" style="display:none;">
444
+ <img src="<?php echo plugin_dir_url( __FILE__ ); ?>/assets/guide_add_language.gif" alt="Add language in Cookiebot administration tool" />
445
+ <br />
446
+ <a href="#" id="hide_add_language_guide"><?php _e('Hide guide'); ?></a>
447
+ </div>
448
+ </div>
449
+ <script>
450
+ jQuery(document).ready(function($) {
451
+ $('#show_add_language_guide').on('click',function(e) {
452
+ e.preventDefault();
453
+ $('#add_language_guide').slideDown();
454
+ $(this).hide();
455
+ });
456
+ $('#hide_add_language_guide').on('click',function(e) {
457
+ e.preventDefault();
458
+ $('#add_language_guide').slideUp();
459
+ $('#show_add_language_guide').show();
460
+ });
461
+
462
+ $('#cookiebot-language').on('change', function() {
463
+ if(this.value == '') {
464
+ $('#info_lang_autodetect').show();
465
+ $('#info_lang_specified').hide();
466
+ }
467
+ else {
468
+ $('#info_lang_autodetect').hide();
469
+ $('#info_lang_specified').show();
470
+ }
471
+ });
472
+ });
473
+ </script>
474
+
475
+ </td>
476
+ </tr>
477
+ <tr valign="top">
478
+ <th scope="row">
479
+ <?php _e('Add async or defer attribute','cookiebot'); ?>
480
+ <br /><?php _e('Consent banner script tag'); ?>
481
+ </th>
482
+ <td>
483
+ <?php
484
+ $cv = get_option('cookiebot-script-tag-uc-attribute','async');
485
+ $disabled = false;
486
+ if($is_ms && $network_scrip_tag_uc_attr != 'custom') {
487
+ $disabled = true;
488
+ $cv = $network_scrip_tag_uc_attr;
489
+ }
490
+ ?>
491
+ <label>
492
+ <input type="radio" name="cookiebot-script-tag-uc-attribute"<?php echo ($disabled) ? ' disabled' : ''; ?> value="" <?php checked('', $cv, true); ?> />
493
+ <i>None</i>
494
+ </label>
495
+ &nbsp; &nbsp;
496
+ <label>
497
+ <input type="radio" name="cookiebot-script-tag-uc-attribute"<?php echo ($disabled) ? ' disabled' : ''; ?> value="async" <?php checked('async',$cv, true); ?> />
498
+ async
499
+ </label>
500
+ &nbsp; &nbsp;
501
+ <label>
502
+ <input type="radio" name="cookiebot-script-tag-uc-attribute"<?php echo ($disabled) ? ' disabled' : ''; ?> value="defer" <?php checked('defer',$cv, true); ?> />
503
+ defer
504
+ </label>
505
+ <p class="description">
506
+ <?php if($disabled) { echo '<b>'._('Network setting applied. Please contact website administrator to change this setting.').'</b><br />'; } ?>
507
+ <?php _e('Add async or defer attribute to Cookiebot script tag. Default: async','cookiebot') ?>
508
+ </p>
509
+ </td>
510
+ </tr>
511
+ <tr valign="top">
512
+ <th scope="row">
513
+ <?php _e('Add async or defer attribute','cookiebot'); ?>
514
+ <br /><?php _e('Cookie declaration script tag'); ?>
515
+ </th>
516
+ <td>
517
+ <?php
518
+ $cv = get_option('cookiebot-script-tag-cd-attribute','async');
519
+ $disabled = false;
520
+ if($is_ms && $network_scrip_tag_cd_attr != 'custom') {
521
+ $disabled = true;
522
+ $cv = $network_scrip_tag_cd_attr;
523
+ }
524
+ ?>
525
+ <label>
526
+ <input type="radio" name="cookiebot-script-tag-cd-attribute"<?php echo ($disabled) ? ' disabled' : ''; ?> value="" <?php checked('', $cv, true); ?> />
527
+ <i>None</i>
528
+ </label>
529
+ &nbsp; &nbsp;
530
+ <label>
531
+ <input type="radio" name="cookiebot-script-tag-cd-attribute"<?php echo ($disabled) ? ' disabled' : ''; ?> value="async" <?php checked('async',$cv, true); ?> />
532
+ async
533
+ </label>
534
+ &nbsp; &nbsp;
535
+ <label>
536
+ <input type="radio" name="cookiebot-script-tag-cd-attribute"<?php echo ($disabled) ? ' disabled' : ''; ?> value="defer" <?php checked('defer',$cv, true); ?> />
537
+ defer
538
+ </label>
539
+ <p class="description">
540
+ <?php if($disabled) { echo '<b>'._('Network setting applied. Please contact website administrator to change this setting.').'</b><br />'; } ?>
541
+ <?php _e('Add async or defer attribute to Cookiebot script tag. Default: async','cookiebot') ?>
542
+ </p>
543
+ </td>
544
+ </tr>
545
+ <?php
546
+ if(!is_multisite()) {
547
+ ?>
548
+ <tr valign="top">
549
+ <th scope="row"><?php _e('Auto-update Cookiebot','cookiebot'); ?></th>
550
+ <td>
551
+ <input type="checkbox" name="cookiebot-autoupdate" value="1" <?php checked(1,get_option('cookiebot-autoupdate',true), true); ?> />
552
+ <p class="description">
553
+ <?php _e('Automatic update your Cookiebot plugin when new releases becomes available.','cookiebot') ?>
554
+ </p>
555
+ </td>
556
+ </tr>
557
+ <?php
558
+ }
559
+ ?>
560
+ <tr valign="top">
561
+ <th scope="row"><?php _e('Hide Cookie Popup','cookiebot'); ?></th>
562
+ <td>
563
+ <?php
564
+ $disabled = false;
565
+ if($is_ms && get_site_option('cookiebot-nooutput',false)) {
566
+ $disabled = true;
567
+ echo '<input type="checkbox" checked disabled />';
568
+ }
569
+ else {
570
+ ?>
571
+ <input type="checkbox" name="cookiebot-nooutput" value="1" <?php checked(1,get_option('cookiebot-nooutput',false), true); ?> />
572
+ <?php
573
+ }
574
+ ?>
575
+ <p class="description">
576
+ <?php if($disabled) { echo '<b>'._('Network setting applied. Please contact website administrator to change this setting.').'</b><br />'; } ?>
577
+ <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 />
578
+ <?php _e('If you are using Google Tag Manager (or equal), you need to add the Cookiebot script in your Tag Manager.','cookiebot') ?><br />
579
+ <?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') ?>
580
+ </p>
581
+ </td>
582
+ </tr>
583
+ <tr valign="top">
584
+ <th scope="row"><?php _e('Hide Cookie Popup in WP Admin','cookiebot'); ?></th>
585
+ <td>
586
+ <?php
587
+ $disabled = false;
588
+ if($is_ms && get_site_option('cookiebot-nooutput-admin',false)) {
589
+ echo '<input type="checkbox" checked disabled />';
590
+ $disabled = true;
591
+ }
592
+ else {
593
+ ?>
594
+ <input type="checkbox" name="cookiebot-nooutput-admin" value="1" <?php checked(1,get_option('cookiebot-nooutput-admin',false), true); ?> />
595
+ <?php
596
+ }
597
+ ?>
598
+ <p class="description">
599
+ <?php if($disabled) { echo '<b>'._('Network setting applied. Please contact website administrator to change this setting.').'</b><br />'; } ?>
600
+ <b><?php _e('This checkbox will remove the cookie consent banner the Wordpress Admin area.','cookiebot') ?></b>
601
+ </p>
602
+ </td>
603
+ </tr>
604
+ </table>
605
+ <?php submit_button(); ?>
606
+ </form>
607
+ </div>
608
+ <?php
609
+ }
610
+
611
+ /**
612
+ * Cookiebot_WP Cookiebot network setting page
613
+ *
614
+ * @version 2.2.0
615
+ * @since 2.2.0
616
+ */
617
+ function network_settings_page() {
618
+ ?>
619
+ <div class="wrap">
620
+ <h1><?php _e('Cookiebot Network Settings','cookiebot'); ?></h1>
621
+ <a href="https://www.cookiebot.com">
622
+ <img src="<?php echo plugins_url( 'cookiebot-logo.png', __FILE__ ); ?>" style="float:right;margin-left:1em;">
623
+ </a>
624
+ <p>
625
+ <?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/en/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'); ?>
626
+ </p>
627
+ <p>
628
+ <b><big style="color:red;"><?php _e('The settings below is network wide settings. See notes below each field.'); ?></big></b>
629
+ </p>
630
+ <form method="post" action="edit.php?action=cookiebot_network_settings">
631
+ <?php wp_nonce_field( 'cookiebot-network-settings' ); ?>
632
+ <table class="form-table">
633
+ <tr valign="top">
634
+ <th scope="row"><?php _e('Network Cookiebot ID','cookiebot'); ?></th>
635
+ <td>
636
+ <input type="text" name="cookiebot-cbid" value="<?php echo esc_attr( get_site_option('cookiebot-cbid','') ); ?>" style="width:300px" />
637
+ <p class="description">
638
+ <b><?php _e('If added this will be the default Cookiebot ID for all subsites. Subsites are able to override the Cookiebot ID.'); ?></b>
639
+ <br />
640
+ <?php _e('Need an ID?','cookiebot'); ?>
641
+ <a href="https://www.cookiebot.com/en/signup" target="_blank"><?php _e('Sign up for free on cookiebot.com','cookiebot'); ?></a>
642
+ </p>
643
+ </td>
644
+ </tr>
645
+ <tr valign="top">
646
+ <th scope="row">
647
+ <?php _e('Add async or defer attribute','cookiebot'); ?>
648
+ <br /><?php _e('Consent banner script tag'); ?>
649
+ </th>
650
+ <td>
651
+ <?php
652
+ $cv = get_site_option('cookiebot-script-tag-uc-attribute','custom');
653
+ ?>
654
+ <label>
655
+ <input type="radio" name="cookiebot-script-tag-uc-attribute" value="" <?php checked('', $cv, true); ?> />
656
+ <i>None</i>
657
+ </label>
658
+ &nbsp; &nbsp;
659
+ <label>
660
+ <input type="radio" name="cookiebot-script-tag-uc-attribute" value="async" <?php checked('async',$cv, true); ?> />
661
+ async
662
+ </label>
663
+ &nbsp; &nbsp;
664
+ <label>
665
+ <input type="radio" name="cookiebot-script-tag-uc-attribute" value="defer" <?php checked('defer',$cv, true); ?> />
666
+ defer
667
+ </label>
668
+ &nbsp; &nbsp;
669
+ <label>
670
+ <input type="radio" name="cookiebot-script-tag-uc-attribute" value="custom" <?php checked('custom',$cv, true); ?> />
671
+ <i>Choose per subsite</i>
672
+ </label>
673
+ <p class="description">
674
+ <b><?php _e('Setting will apply for all subsites. Subsites will not be able to override.'); ?></b><br />
675
+ <?php _e('Add async or defer attribute to Cookiebot script tag. Default: Choose per subsite','cookiebot') ?>
676
+ </p>
677
+ </td>
678
+ </tr>
679
+ <tr valign="top">
680
+ <th scope="row">
681
+ <?php _e('Add async or defer attribute','cookiebot'); ?>
682
+ <br /><?php _e('Cookie declaration script tag'); ?>
683
+ </th>
684
+ <td>
685
+ <?php
686
+ $cv = get_site_option('cookiebot-script-tag-cd-attribute','custom');
687
+ ?>
688
+ <label>
689
+ <input type="radio" name="cookiebot-script-tag-cd-attribute" value="" <?php checked('', $cv, true); ?> />
690
+ <i>None</i>
691
+ </label>
692
+ &nbsp; &nbsp;
693
+ <label>
694
+ <input type="radio" name="cookiebot-script-tag-cd-attribute" value="async" <?php checked('async',$cv, true); ?> />
695
+ async
696
+ </label>
697
+ &nbsp; &nbsp;
698
+ <label>
699
+ <input type="radio" name="cookiebot-script-tag-cd-attribute" value="defer" <?php checked('defer',$cv, true); ?> />
700
+ defer
701
+ </label>
702
+ &nbsp; &nbsp;
703
+ <label>
704
+ <input type="radio" name="cookiebot-script-tag-cd-attribute" value="custom" <?php checked('custom',$cv, true); ?> />
705
+ <i>Choose per subsite</i>
706
+ </label>
707
+ <p class="description">
708
+ <b><?php _e('Setting will apply for all subsites. Subsites will not be able to override.'); ?></b><br />
709
+ <?php _e('Add async or defer attribute to Cookiebot script tag. Default: Choose per subsite','cookiebot') ?>
710
+ </p>
711
+ </td>
712
+ </tr>
713
+ <tr valign="top">
714
+ <th scope="row"><?php _e('Auto-update Cookiebot','cookiebot'); ?></th>
715
+ <td>
716
+ <input type="checkbox" name="cookiebot-autoupdate" value="1" <?php checked(1,get_site_option('cookiebot-autoupdate',true), true); ?> />
717
+ <p class="description">
718
+ <?php _e('Automatic update your Cookiebot plugin when new releases becomes available.','cookiebot') ?>
719
+ </p>
720
+ </td>
721
+ </tr>
722
+ <tr valign="top">
723
+ <th scope="row"><?php _e('Hide Cookie Popup','cookiebot'); ?></th>
724
+ <td>
725
+ <input type="checkbox" name="cookiebot-nooutput" value="1" <?php checked(1,get_site_option('cookiebot-nooutput',false), true); ?> />
726
+ <p class="description">
727
+ <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 />
728
+ <?php _e('If you are using Google Tag Manager (or equal), you need to add the Cookiebot script in your Tag Manager.','cookiebot') ?><br />
729
+ <?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') ?>
730
+ </p>
731
+ </td>
732
+ </tr>
733
+ <tr valign="top">
734
+ <th scope="row"><?php _e('Hide Cookie Popup in WP Admin','cookiebot'); ?></th>
735
+ <td>
736
+ <input type="checkbox" name="cookiebot-nooutput-admin" value="1" <?php checked(1,get_site_option('cookiebot-nooutput-admin',false), true); ?> />
737
+ <p class="description">
738
+ <b><?php _e('Remove the cookie consent banner the Wordpress Admin area for all subsites. This cannot be changed by subsites.','cookiebot') ?></b>
739
+ </p>
740
+ </td>
741
+ </tr>
742
+ </table>
743
+ <?php submit_button(); ?>
744
+ </form>
745
+ </div>
746
+ <?php
747
+ }
748
+
749
+
750
+ /**
751
+ * Cookiebot_WP Cookiebot save network settings
752
+ *
753
+ * @version 2.2.0
754
+ * @since 2.2.0
755
+ */
756
+ function network_settings_save() {
757
+ check_admin_referer( 'cookiebot-network-settings' );
758
+
759
+ update_site_option('cookiebot-cbid', $_POST['cookiebot-cbid'] );
760
+ update_site_option('cookiebot-script-tag-uc-attribute', $_POST['cookiebot-script-tag-uc-attribute'] );
761
+ update_site_option('cookiebot-script-tag-cd-attribute', $_POST['cookiebot-script-tag-cd-attribute'] );
762
+ update_site_option('cookiebot-autoupdate', $_POST['cookiebot-autoupdate'] );
763
+ update_site_option('cookiebot-nooutput', $_POST['cookiebot-nooutput'] );
764
+ update_site_option('cookiebot-nooutput-admin', $_POST['cookiebot-nooutput-admin'] );
765
+
766
+ wp_redirect( add_query_arg( array(
767
+ 'page' => 'cookiebot_network',
768
+ 'updated' => true ), network_admin_url('admin.php')
769
+ ));
770
+ exit;
771
+ }
772
+
773
+ /**
774
+ * Cookiebot_WP Cookiebot support page
775
+ *
776
+ * @version 2.2.0
777
+ * @since 2.0.0
778
+ */
779
+ function support_page() {
780
+ ?>
781
+ <div class="wrap">
782
+ <h1><?php _e('Support','cookiebot'); ?></h1>
783
+ <h2><?php _e('How to find my Cookiebot ID','cookiebot'); ?></h2>
784
+ <p>
785
+ <ol>
786
+ <li><?php _e('Log in to your <a href="https://www.cookiebot.com/en/account" target="_blank">Cookiebot account</a>.','cookiebot'); ?></li>
787
+ <li><?php _e('Go to <b>Manage</b> > <b>Settings</b> and add setup your Cookiebot','cookiebot'); ?></li>
788
+ <li><?php _e('Go to the <b>"Your scripts"</b> tab','cookiebot'); ?></li>
789
+ <li><?php _e('Copy the value inside the data-cid parameter - eg.: abcdef12-3456-7890-abcd-ef1234567890','cookiebot'); ?></li>
790
+ <li><?php _e('Add <b>[cookie_declaration]</b> shortcode to a page to show the declation','cookiebot'); ?></li>
791
+ <li><?php _e('Remember to change your scripts as descripted below','cookiebot'); ?></li>
792
+ </ol>
793
+ </p>
794
+ <h2><?php _e('Add the Cookie Declaration to your website'); ?></h2>
795
+ <p>
796
+ <?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'); ?>
797
+ <br />
798
+ <?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'); ?>
799
+ </p>
800
+ <p>
801
+ <a href="https://www.youtube.com/watch?v=OCXz2bt4H_w" target="_blank" class="button"><?php _e('Watch video demonstration','cookiebot'); ?></a>
802
+ </p>
803
+ <h2><?php _e('Update your script tags','cookiebot'); ?></h2>
804
+ <p>
805
+ <?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'); ?>
806
+ </p>
807
+ <code>
808
+ <?php
809
+ echo htmlentities("<script type=\"text/plain\" data-cookieconsent=\"statistics\">").'<br />';
810
+ 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 />';
811
+ echo htmlentities("ga('create', 'UA-00000000-0', 'auto');").'<br />';
812
+ echo htmlentities("ga('send', 'pageview');").'<br />';
813
+ echo htmlentities("</script>").'<br />';
814
+ ?>
815
+ </code>
816
+ <p>
817
+ <a href="https://www.youtube.com/watch?v=MeHycvV2QCQ" target="_blank" class="button"><?php _e('Watch video demonstration','cookiebot'); ?></a>
818
+ </p>
819
+
820
+ <h2><?php _e('Helper function to update your scripts','cookiebot'); ?></h2>
821
+ <p>
822
+ <?php _e('You are able to update your scripts yourself. However, Cookiebot also offers a small helper function that makes the work easier.','cookiebot'); ?>
823
+ <br />
824
+ <?php _e('Update your script tags this way:','cookiebot'); ?>
825
+ </p>
826
+ <?php
827
+ printf(
828
+ __('%s to %s'),
829
+ '<code>'.htmlentities('<script type="text/javascript">').'</code>',
830
+ '<code>'.htmlentities('<script<?php echo cookiebot_assist(\'marketing\') ?>>').'</code>'
831
+ );
832
+ ?>
833
+ </div>
834
+ <?php
835
+ }
836
+
837
+ /**
838
+ * Cookiebot_WP Cookiebot IAB page
839
+ *
840
+ * @version 2.0.0
841
+ * @since 2.0.0
842
+ */
843
+ function iab_page() {
844
+ ?>
845
+ <div class="wrap">
846
+ <h1><?php _e('IAB','cookiebot'); ?></h1>
847
+
848
+ <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>
849
+
850
+ <form method="post" action="options.php">
851
+ <?php settings_fields( 'cookiebot-iab' ); ?>
852
+ <?php do_settings_sections( 'cookiebot-iab' ); ?>
853
+
854
+ <label>Enable IAB integration</label>
855
+ <input type="checkbox" name="cookiebot-iab" value="1" <?php checked(1,get_option('cookiebot-iab'), true); ?>>
856
+
857
+ <?php submit_button(); ?>
858
+ </form>
859
+ </div>
860
+ <?php
861
+ }
862
+
863
+ /**
864
+ * Cookiebot_WP Add Cookiebot JS to <head>
865
+ *
866
+ * @version 2.2.0
867
+ * @since 1.0.0
868
+ */
869
+ function add_js() {
870
+ $cbid = $this->get_cbid();
871
+ if(!empty($cbid)) {
872
+ if(is_multisite() && get_site_option('cookiebot-nooutput',false)) {
873
+ return; //Is multisite - and disabled output is checked as network setting
874
+ }
875
+ if(get_option('cookiebot-nooutput',false)) {
876
+ return; //Do not show JS - output disabled
877
+ }
878
+
879
+
880
+ $lang = $this->get_language();
881
+ if(!empty($lang)) {
882
+ $lang = ' data-culture="'.strtoupper($lang).'"'; //Use data-culture to define language
883
+ }
884
+
885
+ if(!is_multisite() || get_site_option('cookiebot-script-tag-uc-attribute','custom') == 'custom') {
886
+ $tagAttr = get_option('cookiebot-script-tag-uc-attribute','async');
887
+ }
888
+ else {
889
+ $tagAttr = get_site_option('cookiebot-script-tag-uc-attribute');
890
+ }
891
+
892
+ $iab = ( get_option('cookiebot-iab') != false ) ? 'data-framework="IAB"' : '';
893
+ ?>
894
+ <script id="Cookiebot" src="https://consent.cookiebot.com/uc.js" <?php echo $iab; ?> data-cbid="<?php echo $cbid; ?>"<?php echo $lang; ?> type="text/javascript" <?php echo $tagAttr; ?>></script>
895
+ <?php
896
+ }
897
+ }
898
+
899
+ /**
900
+ * Cookiebot_WP Output declation shortcode [cookie_declaration]
901
+ * Support attribute lang="LANGUAGE_CODE". Eg. lang="en".
902
+ *
903
+ * @version 2.2.0
904
+ * @since 1.0.0
905
+ */
906
+ function show_declaration($atts) {
907
+ $cbid = $this->get_cbid();
908
+ $lang = '';
909
+ if(!empty($cbid)) {
910
+
911
+ $atts = shortcode_atts(array(
912
+ 'lang' => $this->get_language(),
913
+ ), $atts, 'cookie_declaration'
914
+ );
915
+
916
+ if(!empty($atts['lang'])) {
917
+ $lang = ' data-culture="'.strtoupper($atts['lang']).'"'; //Use data-culture to define language
918
+ }
919
+
920
+ if(!is_multisite() || get_site_option('cookiebot-script-tag-cd-attribute','custom') == 'custom') {
921
+ $tagAttr = get_option('cookiebot-script-tag-cd-attribute','async');
922
+ }
923
+ else {
924
+ $tagAttr = get_site_option('cookiebot-script-tag-cd-attribute');
925
+ }
926
+
927
+ return '<script id="CookieDeclaration" src="https://consent.cookiebot.com/'.$cbid.'/cd.js"'.$lang.' type="text/javascript" '.$tagAttr.'></script>';
928
+ }
929
+ else {
930
+ return __('Please add your Cookiebot ID to show Cookie Declarations','cookiebot');
931
+ }
932
+ }
933
+
934
+ /**
935
+ * Cookiebot_WP Get cookiebot cbid
936
+ *
937
+ * @version 2.2.0
938
+ * @since 1.0.0
939
+ */
940
+ public static function get_cbid() {
941
+ $cbid = get_option('cookiebot-cbid');
942
+ if(is_multisite() && ($network_cbid = get_site_option('cookiebot-cbid'))) {
943
+ if(empty($cbid)) {
944
+ return $network_cbid;
945
+ }
946
+ }
947
+ return $cbid;
948
+ }
949
+
950
+ /**
951
+ * Cookiebot_WP Get the language code for Cookiebot
952
+ *
953
+ * @version 1.4.0
954
+ * @since 1.4.0
955
+ */
956
+ function get_language($onlyFromSetting=false) {
957
+ // Get language set in setting page - if empty use WP language info
958
+ $lang = get_option('cookiebot-language');
959
+ if(!empty($lang)) {
960
+ if($lang != '_wp') {
961
+ return $lang;
962
+ }
963
+ }
964
+
965
+ if($onlyFromSetting) {
966
+ return $lang; //We want only to get if already set
967
+ }
968
+
969
+ //Language not set - use WP language
970
+ if($lang == '_wp') {
971
+ $lang = get_bloginfo('language'); //Gets language in en-US format
972
+ if(!empty($lang)) {
973
+ list($lang) = explode('-',$lang); //Changes format from eg. en-US to en.
974
+ }
975
+ }
976
+ return $lang;
977
+ }
978
+
979
+ /**
980
+ * Cookiebot_WP Adding Cookiebot domain(s) to exclude list for WP Rocket minification.
981
+ *
982
+ * @version 1.6.1
983
+ * @since 1.6.1
984
+ */
985
+ function wp_rocket_exclude_external_js($external_js_hosts) {
986
+ $external_js_hosts[] = 'consent.cookiebot.com'; // Add cookiebot domains
987
+ $external_js_hosts[] = 'consentcdn.cookiebot.com';
988
+ return $external_js_hosts;
989
+ }
990
+
991
+ /**
992
+ * Display admin notice for recommending cookiebot
993
+ *
994
+ * @version 2.0.5
995
+ * @since 2.0.5
996
+ */
997
+ function cookiebot_admin_notices() {
998
+ if( ! $this->cookiebot_valid_admin_recommendation() ) {
999
+ return false;
1000
+ }
1001
+ $two_week_review_ignore = add_query_arg( array( 'cookiebot_admin_notice' => 'hide' ) );
1002
+ $two_week_review_temp = add_query_arg( array( 'cookiebot_admin_notice' => 'two_week' ) );
1003
+
1004
+ $notices = array(
1005
+ 'title' => __('Leave A Review?', 'cookiebot'),
1006
+ 'msg' => __('We hope you enjoy using WordPress Cookiebot! Would you consider leaving us a review on WordPress.org?', 'cookiebot'),
1007
+ '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>
1008
+ <li><span class="dashicons dashicons-smiley"></span><a href="' . $two_week_review_ignore . '"> ' . __('I\'ve already left a review', 'cookiebot') . '</a></li>
1009
+ <li><span class="dashicons dashicons-calendar-alt"></span><a href="' . $two_week_review_temp . '">' . __('Maybe Later', 'cookiebot') . '</a></li>
1010
+ <li><span class="dashicons dashicons-dismiss"></span><a href="' . $two_week_review_ignore . '">' . __('Never show again', 'cookiebot') . '</a></li>',
1011
+ 'later_link' => $two_week_review_temp,
1012
+ 'int' => 14
1013
+ );
1014
+
1015
+ echo '<div class="update-nag cookiebot-admin-notice">
1016
+ <div class="cookiebot-notice-logo"></div>
1017
+ <p class="cookiebot-notice-title">' . $notices['title'] . '</p>
1018
+ <p class="cookiebot-notice-body">' . $notices['msg'] . '</p>
1019
+ <ul class="cookiebot-notice-body wd-blue">' . $notices['link'] . '</ul>
1020
+ <a href="' . $notices['later_link'] . '" class="dashicons dashicons-dismiss"></a>
1021
+ </div>';
1022
+
1023
+ wp_enqueue_style( 'cookiebot-admin-notices', plugins_url( 'css/notice.css', __FILE__ ), array(), '2.0.4' );
1024
+ }
1025
+
1026
+
1027
+ /**
1028
+ * Validate if the last user action is valid for plugin recommendation
1029
+ *
1030
+ * @return bool
1031
+ *
1032
+ * @version 2.0.5
1033
+ * @since 2.0.5
1034
+ */
1035
+ function cookiebot_valid_admin_recommendation() {
1036
+ //Default - the recommendation is allowed to be visible
1037
+ $return = true;
1038
+
1039
+ $option = get_option('cookiebot_notice_recommend');
1040
+
1041
+ if( $option != false ) {
1042
+ //Never show again is clicked
1043
+ if( $option == 'hide' ) {
1044
+ $return = false;
1045
+ }
1046
+ elseif( is_numeric($option) && strtotime('now') < $option ) {
1047
+ //Show me after 2 weeks is clicked and the time is not valid yet
1048
+ $return = false;
1049
+ }
1050
+ }
1051
+ return $return;
1052
+ }
1053
+
1054
+ /**
1055
+ * Save the user action on cookiebot recommendation link
1056
+ *
1057
+ * @version 2.0.5
1058
+ * @since 2.0.5
1059
+ */
1060
+ function save_notice_link() {
1061
+ if( isset( $_GET['cookiebot_admin_notice'] ) ) {
1062
+ if( $_GET['cookiebot_admin_notice'] == 'hide' ) {
1063
+ update_option('cookiebot_notice_recommend', 'hide' );
1064
+ }
1065
+ else {
1066
+ update_option('cookiebot_notice_recommend', strtotime('+2 weeks') );
1067
+ }
1068
+ }
1069
+ }
1070
+
1071
+ }
1072
+ endif;
1073
+
1074
+
1075
+ /**
1076
+ * Helper function to manipulate script tags
1077
+ *
1078
+ * @version 1.6
1079
+ * @since 1.0
1080
+ * @return string
1081
+ */
1082
+ function cookiebot_assist($type='statistics') {
1083
+ //change to array
1084
+ if(!is_array($type)) { $type = array($type); }
1085
+
1086
+ foreach($type as $tk=>$tv) {
1087
+ if(!in_array($tv,array('marketing','statistics','preferences'))) {
1088
+ unset($type[$tk]);
1089
+ }
1090
+ }
1091
+ if(sizeof($type) > 0) {
1092
+ return ' type="text/plain" data-cookieconsent="'.implode(',',$type).'"';
1093
+ }
1094
+ return '';
1095
+ }
1096
+
1097
+
1098
+ /**
1099
+ * Helper function to check if cookiebot is active.
1100
+ * Useful for other plugins adding support for Cookiebot.
1101
+ *
1102
+ * @version 2.2.2
1103
+ * @since 1.2
1104
+ * @return string
1105
+ */
1106
+ function cookiebot_active() {
1107
+ $cbid = Cookiebot_WP::get_cbid();
1108
+ if(!empty($cbid)) {
1109
+ return true;
1110
+ }
1111
+ return false;
1112
+ }
1113
+
1114
+
1115
+ if(!function_exists('cookiebot')) {
1116
+ /**
1117
+ * Returns the main instance of Cookiebot_WO to prevent the need to use globals.
1118
+ *
1119
+ * @version 1.0.0
1120
+ * @since 1.0.0
1121
+ * @return Cookiebot_WP
1122
+ */
1123
+ function cookiebot() {
1124
+ return Cookiebot_WP::instance();
1125
+ }
1126
+ }
1127
+
1128
+ cookiebot();
css/notice.css ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .cookiebot-admin-notice {
2
+ background: #fff;
3
+ border: 4px;
4
+ display: block;
5
+ min-height: 68px;
6
+ padding: 10px 40px 10px 125px;
7
+ position: relative;
8
+ margin-top: 35px;
9
+ }
10
+ .cookiebot-admin-notice a {
11
+ color: #10738B;
12
+ }
13
+ .cookiebot-notice-logo {
14
+ clear: both;
15
+ content: "";
16
+ display: block;
17
+ background-image: url("../assets/icon.svg");
18
+ background-size: 108px auto;
19
+ background-repeat: no-repeat;
20
+ background-position: 0 45%;
21
+ width: 125px;
22
+ position: absolute;
23
+ top: 0;
24
+ bottom: 0;
25
+ left: 5px;
26
+ }
27
+ .cookiebot-admin-notice > .dashicons {
28
+ color: #424242;
29
+ position: absolute;
30
+ right: 20px;
31
+ top: 40%;
32
+ }
33
+ .cookiebot-notice-title {
34
+ font-size: 24px;
35
+ margin: 0;
36
+ }
37
+ .cookiebot-notice-body {
38
+ font-weight: normal;
39
+ margin: 5px 0;
40
+ }
41
+ .cookiebot-notice-body:after {
42
+ clear: both;
43
+ content: "";
44
+ display: block;
45
+ }
46
+ .cookiebot-notice-body li {
47
+ float: left;
48
+ margin-right: 20px;
49
+ }
50
+ .cookiebot-notice-body .dashicons {
51
+ font-size: 17px;
52
+ }
53
+ .cookiebot-blue {
54
+ color: #10738B;
55
+ }
56
+
57
+ .admin-notice-promo {
58
+ background: #fff;
59
+ border-top: 4px;
60
+ display: block;
61
+ min-height: 68px;
62
+ padding: 10px 40px 0px 10px;
63
+ margin: 10px 0;
64
+ position: relative;
65
+ }
66
+
67
+ .admin-notice-promo:after {
68
+ content: '';
69
+ display: table;
70
+ clear: both;
71
+ }
72
+
73
+ .close-promo {
74
+ position: absolute;
75
+ top: 5px;
76
+ right: 5px;
77
+ }
78
+
79
+ .promo {
80
+ background-position: center;
81
+ background-repeat: no-repeat;
82
+ background-size: 972px 200px;
83
+ height: 200px;
84
+ max-width: 100%;
85
+ }
86
+
87
+ .promo a {
88
+ display: block;
89
+ height: 100%;
90
+ }
documentation/admin-ui.md ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # How to manage the addon in admin ui
2
+
3
+ Every addon can be configured in the admin ui.
4
+
5
+ This document contains explainations of the configurable options.
6
+
7
+ # Tabs
8
+
9
+ Cookiebot Addons settings page has 3 tabs:
10
+ - [Available plugins](#available-plugins)
11
+ - [Unavailable plugins](#unavailable-plugins)
12
+ - [Jetpack](#jetpack)
13
+
14
+ # Available plugins
15
+
16
+ In this screenshot you see the plugins that are installed and activated.
17
+
18
+ ![available plugins][available-plugin]
19
+
20
+ In this section you manage the available plugins for cookiebot.
21
+
22
+ Example settings:
23
+ - disable addon
24
+ - Select required cookie types
25
+ - Add placeholder text in multi languages
26
+
27
+ In order to create unique placeholder experience, we have added few merge tags you can use in the placeholder text:
28
+ - ```%cookie_types```
29
+ Displays required cookie types to enable the addon.
30
+
31
+ - ```%src```
32
+ src url for youtube, facebook, vimeo and twitter videos. Currently it only works for Embed addon.
33
+
34
+ - ```[renew_consent]``` and ```[/renew_consent]```
35
+ Both tag will be replaced by a link element with a href to the cookiebot settings box, so the visitor can enable or disable the cookie types.
36
+
37
+
38
+ On top of that, there are also few filters to manipulate the placeholders:
39
+
40
+ #### Twitter
41
+
42
+ - ```add_filter('cookiebot_addons_embed_twitter_source', $source)```
43
+
44
+ This filter is used to manipulate the source attribute for twitter videos
45
+
46
+ - ```add_filter('cookiebot_addons_embed_twitter_placeholder', $content, $source, $cookie_types)```
47
+
48
+ This filter is used to manipulate the placeholder output
49
+
50
+ #### Youtube, Vimeo and Facebook
51
+
52
+ - ```add_filter('cookiebot_addons_embed_source', $source)```
53
+
54
+ This filter is used to manipulate the source attribute for embedded video
55
+
56
+ - ```add_filter('cookiebot_addons_embed_placeholder', $content, $source, $cookie_types)```
57
+
58
+ This filter is used to manipulate the placeholder output
59
+
60
+
61
+ # Unavailable plugins
62
+
63
+ In this screenshot you see the plugins which are not activated or installed.
64
+
65
+ ![unavailable plugins][unavailable-plugin]
66
+
67
+ # Jetpack
68
+
69
+ Jetpack has one more tab to configure the widgets.
70
+
71
+ ![jetpack][jetpack]
72
+
73
+ [available-plugin]: assets/available-plugins.png
74
+ [unavailable-plugin]: assets/unavailable-plugins.png
75
+ [jetpack]: assets/jetpack.png
documentation/assets/available-plugins.png ADDED
Binary file
documentation/assets/jetpack.png ADDED
Binary file
documentation/assets/unavailable-plugins.png ADDED
Binary file
documentation/how-to-add-new-addon.md ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # How to add new addon
2
+
3
+ Steps
4
+ ---
5
+
6
+ 1. Add new addon to addons.json
7
+ 2. Create a directory in addons/controller/addons
8
+ 3. Create a class in that new directory (copy class from another addon and adjust the namespace, classname and methods.)
9
+ 4. Edit 'load_configuration' method. That is the only method that needs to be worked on to block the cookies. You can create your own method from there.
10
+ 5. Test
11
+ 6. Create integration test if you did use dependencies from the addon plugin. (We run daily tests to see if the dependencies from the addons plugin are still valid.)
12
+ 7. Send a pull-request in github
13
+
14
+ Example
15
+ ---
16
+ 1. New addon to addons.json
17
+
18
+ ```json
19
+ "Add_To_Any": {
20
+ "class": "cookiebot_addons\\controller\\addons\\add_to_any\\Add_To_Any"
21
+ },
22
+ ```
23
+
24
+ 2. Create directory 'add_to_any' in controller/addons
25
+
26
+ 3. Create a class 'Add_To_Any' in 'add_to_any' directory (copy class from another addon and rename everything accordingly)
27
+
28
+ 5. Go to 'load_configuration' method and rename the callback function to make it give more sense. Write your cookie-blocking logic in that function. You can find more information about how to block cookies in [how-to-block-cookies](how-to-block-cookies.md).
29
+
30
+ 6. Test if the cookies are blocked.
31
+
32
+ 7. Create integration test for the addon dependencies: https://github.com/CybotAS/CookiebotAddons/blob/develop/tests/integration/addons/test-add-to-any.php
33
+
34
+ 8. Send a pull-request to our github repository.
documentation/how-to-block-cookies.md ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # How to block cookies
2
+
3
+ Cookiebot Addons uses different techniques to block cookies from 3rd party plugins.
4
+
5
+ This document contains explainations of the classes and functions that are available.
6
+
7
+ List of included interfaces in every addon
8
+ --
9
+ - [Settings_Service_Interface](#settings-service-interface)
10
+ - [Script_Loader_Tag_Interface](#script-loader-tag-interface)
11
+ - [Cookie_Consent_Interface](#cookie-consent-interface)
12
+ - [Buffer_Output_Interface](#buffer-output-interface)
13
+
14
+ List of helpers to block cookies
15
+ ---
16
+ - [remove_action](#remove-action)
17
+ - [cookiebot_remove_class_action](#cookiebot-remove-class-action)
18
+
19
+ # Settings Service Interface
20
+
21
+ The Settings Service is used to store and retrieve settings.
22
+
23
+ Example settings:
24
+
25
+ - Check if the addon is active or not.
26
+ - Get the placeholder text that should be displayed to renew a end-users consent
27
+ - Get the tracking types that the addon needs consent for
28
+
29
+ This will return the configured cookie types for an addon:
30
+ ```
31
+ $this->settings->get_cookie_types( $this->get_option_name() );
32
+ ```
33
+
34
+ # Script Loader Tag Interface
35
+
36
+ Script Loader Tag is used to manipulate the enqeueud scripts. It will add cookiebot script attributes to the script tag so the cookiebot can block the script while consent is not given.
37
+
38
+ Example:
39
+
40
+ Below function will manipulate scripts added with the handle 'addtoany'. The second parameter will send the cookie types that were selected in the administration UI for the addon at hand. Those types will be implemented into the data-cookieconsent attribute.
41
+ ```
42
+ $this->script_loader_tag->add_tag( 'addtoany', $this->get_cookie_types() );
43
+
44
+ // will change the script tag into this
45
+ <script text='text/plain' data-cookieconsent='statistics,marketing'>
46
+ ```
47
+
48
+ # Cookie Consent Interface
49
+
50
+ Cookie Consent will return the tracking types which the user has consented to (statistics,marketing etc.). If the necessary cookie types are selected, you can then skip the code to block the cookies because the consent is already given.
51
+
52
+ Example:
53
+ This will check if required consents are given.
54
+ ```
55
+ if( $this->cookie_consent->are_cookie_states_accepted( $this->get_cookie_types() ) ){
56
+ ```
57
+
58
+ # Buffer Output Interface
59
+
60
+ The Buffer Output is used to manipulate the scripts which are hardcoded, and can't be hooked into with default functionality. There is no other way to block those cookies then to use buffer output manipulation.
61
+
62
+ Example:
63
+
64
+ This will manipulate the output from wp_footer action hook starting from priority 9 till 11. And it will search for keys given in 3rd parameter(gtag, _gaq, ...). If it does find it then it will apply the cookie types that were selected in the administration UI for the addon at hand. If you don't want to use those types, you can change the parameter into a custom array like this: array('statistics', 'marketing').
65
+
66
+ ```
67
+ $this->buffer_output->add_tag( 'wp_footer', 10, array(
68
+ 'gtag' => $this->get_cookie_types(),
69
+ 'google-analytics' => $this->get_cookie_types(),
70
+ '_gaq' => $this->get_cookie_types(),
71
+ 'www.googletagmanager.com/gtag/js?id=' => $this->get_cookie_types()
72
+ ), false );
73
+ ```
74
+
75
+ # Remove Action
76
+
77
+ Sometimes you have the option to block the action hook before the hardcoded script. Then you can use remove action to block the cookies.
78
+
79
+ Example:
80
+ ```
81
+ remove_action(actionname, functionname);
82
+ ```
83
+
84
+ ```
85
+ if ( has_action( 'wp_head', 'A2A_SHARE_SAVE_head_script' ) ) {
86
+ remove_action( 'wp_head', 'A2A_SHARE_SAVE_head_script' );
87
+ }
88
+ ```
89
+
90
+
91
+ # Cookiebot Remove Class Action
92
+
93
+ Some action hooks are used in a class. By default WordPress doesn't have a feature to remove those action hooks. So we added our own helper function to do that.
94
+
95
+ Example:
96
+
97
+ This will remove the method pixel_init in the class of AEPC_Pixel_Scripts.
98
+
99
+ - wp_head = action hook
100
+ - AEPC_Pixel_Scripts = class name
101
+ - pixel_init = method name
102
+ - 99 = priority
103
+ ```
104
+ cookiebot_remove_class_action( 'wp_head', 'AEPC_Pixel_Scripts', 'pixel_init', 99 );
105
+ ```
langs/cookiebot-da_DK.mo ADDED
Binary file
langs/cookiebot-da_DK.po ADDED
@@ -0,0 +1,159 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # WordPress Blank Pot
2
+ # Copyright (C) 2014 ...
3
+ # This file is distributed under the GNU General Public License v2 or later.
4
+ msgid ""
5
+ msgstr ""
6
+ "Project-Id-Version: Cookiebot\n"
7
+ "Report-Msgid-Bugs-To: Translator Name <translations@example.com>\n"
8
+ "POT-Creation-Date: 2017-12-21 10:51+0100\n"
9
+ "PO-Revision-Date: \n"
10
+ "Last-Translator: \n"
11
+ "Language-Team: Cookiebot <qa@cookiebot.com>\n"
12
+ "Language: da\n"
13
+ "MIME-Version: 1.0\n"
14
+ "Content-Type: text/plain; charset=UTF-8\n"
15
+ "Content-Transfer-Encoding: 8bit\n"
16
+ "Plural-Forms: nplurals=2; plural=(n != 1);\n"
17
+ "X-Textdomain-Support: yesX-Generator: Poedit 1.6.4\n"
18
+ "X-Poedit-SourceCharset: UTF-8\n"
19
+ "X-Poedit-KeywordsList: __;_e;esc_html_e;esc_html_x:1,2c;esc_html__;"
20
+ "esc_attr_e;esc_attr_x:1,2c;esc_attr__;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2;"
21
+ "_x:1,2c;_n:1,2;_n_noop:1,2;__ngettext:1,2;__ngettext_noop:1,2;_c,_nc:4c,1,2\n"
22
+ "X-Poedit-Basepath: ..\n"
23
+ "X-Generator: Poedit 2.0.4\n"
24
+ "X-Poedit-SearchPath-0: .\n"
25
+
26
+ #: cookiebot.php:79
27
+ msgid "Cookiebot Status"
28
+ msgstr "Cookiebot Status"
29
+
30
+ #: cookiebot.php:91
31
+ msgid "You need to enter your Cookiebot ID."
32
+ msgstr "Du skal indtaste et Cookiebot ID."
33
+
34
+ #: cookiebot.php:93
35
+ msgid "Update your Cookiebot ID"
36
+ msgstr "Opdater dit Cookiebot ID"
37
+
38
+ #: cookiebot.php:97
39
+ msgid "Your Cookiebot is working!"
40
+ msgstr "Din Cookiebot virker!"
41
+
42
+ #: cookiebot.php:108
43
+ msgid "Cookiebot"
44
+ msgstr "Cookiebot"
45
+
46
+ #: cookiebot.php:130
47
+ msgid "Cookiebot Settings"
48
+ msgstr "Cookiebot indstillinger"
49
+
50
+ #: cookiebot.php:135
51
+ msgid ""
52
+ "Cookiebot enables your website to comply with current legislation in the EU "
53
+ "on the use of cookies for user tracking and profiling. The EU ePrivacy "
54
+ "Directive requires prior, informed consent of your site users, while the <a "
55
+ "href=\"https://www.cookiebot.com/en/gdpr\" target=\"_blank\">General Data "
56
+ "Protection Regulation (GDPR)</a> requires you to document each consent. At "
57
+ "the same time you must be able to account for what user data you share with "
58
+ "embedded third-party services on your website and where in the world the "
59
+ "user data is sent."
60
+ msgstr ""
61
+ "Med Cookiebot kan din hjemmeside overholde gældende lovgivning i EU ift. "
62
+ "brugen af cookies til sporing og profilering af dine brugere. EU's ePrivacy-"
63
+ "direktiv kræver forudgående, informeret samtykke fra dine hjemmeside-"
64
+ "brugere, mens persondata-forordingen (GDPR) kræver, at du kan dokumentere "
65
+ "hvert enkelt samtykke. Samtidig skal du kunne redegøre for hvilke bruger-"
66
+ "data, du deler med de indlejrede tredjeparts-tjenester på din hjemmeside, og "
67
+ "hvor i Verden brugernes data sendes hen."
68
+
69
+ #: cookiebot.php:142
70
+ msgid "Cookiebot ID"
71
+ msgstr "Cookiebot ID"
72
+
73
+ #: cookiebot.php:146
74
+ msgid "Need an ID?"
75
+ msgstr "Brug for et ID?"
76
+
77
+ #: cookiebot.php:147
78
+ msgid "Sign up for free on cookiebot.com"
79
+ msgstr "Opret dig gratis på cookiebot.com"
80
+
81
+ #: cookiebot.php:154
82
+ msgid "How to find my Cookiebot ID"
83
+ msgstr "Hvordan finder jeg mit Cookiebot ID"
84
+
85
+ #: cookiebot.php:157
86
+ msgid ""
87
+ "Log in to your <a href=\"https://www.cookiebot.com/en/account\" target="
88
+ "\"_blank\">Cookiebot account</a>."
89
+ msgstr ""
90
+ "Log ind på din <a href=\"https://www.cookiebit.com/da/account\" target="
91
+ "\"blank\">Cookiebot konto</a>."
92
+
93
+ #: cookiebot.php:158
94
+ msgid "Go to <b>Manage</b> > <b>Settings</b> and add setup your Cookiebot"
95
+ msgstr ""
96
+ "GÃ¥ til <b>Administration</b> > <b>Indstillinger</b> og opret din Cookiebot"
97
+
98
+ #: cookiebot.php:159
99
+ msgid "Go to the <b>\"Your scripts\"</b> tab"
100
+ msgstr "GÃ¥ til <b>\"Dine scripts\"</b> fanen"
101
+
102
+ #: cookiebot.php:160
103
+ msgid ""
104
+ "Copy the value inside the data-cid parameter - eg.: abcdef12-3456-7890-abcd-"
105
+ "ef1234567890"
106
+ msgstr ""
107
+ "Kopier værdien i data-cid parameteren - f.eks.: abcdef12-3456-7890-abcd-"
108
+ "ef1234567890"
109
+
110
+ #: cookiebot.php:161
111
+ msgid ""
112
+ "Add <b>[cookie_declaration]</b> shortcode to a page to show the declation"
113
+ msgstr ""
114
+ "Tilføj <b>[cookie_declaration]</b> shortcoden til siden hvor du ønsker at "
115
+ "vise deklarationen"
116
+
117
+ #: cookiebot.php:162
118
+ msgid "Remember to change your scripts as descripted below"
119
+ msgstr "Husk at opdatere dine scripts som beskrevet nedenfor"
120
+
121
+ #: cookiebot.php:165
122
+ msgid "Update your script tags"
123
+ msgstr "Opdater dine script tags"
124
+
125
+ #: cookiebot.php:167
126
+ msgid ""
127
+ "To enable prior consent, apply the attribute \"data-cookieconsent\" to "
128
+ "cookie-setting script tags on your website. Set the comma-separated value to "
129
+ "one or more of the cookie categories \"preferences\", \"statistics\" and "
130
+ "\"marketing\" in accordance with the types of cookies being set by each "
131
+ "script. Finally change the attribute \"type\" from \"text/javascript\" to "
132
+ "\"text/plain\". Example on modifying an existing Google Analytics Universal "
133
+ "script tag."
134
+ msgstr ""
135
+
136
+ #: cookiebot.php:178
137
+ msgid "Helper function to update your scripts"
138
+ msgstr "Hjælperfunktion til at opdatere dine scripts"
139
+
140
+ #: cookiebot.php:180
141
+ msgid ""
142
+ "You are able to update your scripts yourself. However, Cookiebot also offers "
143
+ "a small helper function that makes the work easier."
144
+ msgstr ""
145
+ "Du kan selv opdatere dine scripts, men Cookiebot tilbyder også en lille "
146
+ "hjælperfunktion, der gør arbejdet lidt nemmere."
147
+
148
+ #: cookiebot.php:182
149
+ msgid "Update your script tags this way:"
150
+ msgstr "Opdater dine script tags på denne måde:"
151
+
152
+ #: cookiebot.php:186
153
+ #, php-format
154
+ msgid "%s to %s"
155
+ msgstr "%s til %s"
156
+
157
+ #: cookiebot.php:224
158
+ msgid "Please add your Cookiebot ID to show Cookie Declarations"
159
+ msgstr "Tilføj dit Cookiebot ID for at vise Cookie deklarationen"
langs/cookiebot.pot ADDED
@@ -0,0 +1,426 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (C) 2018 Cookiebot | GDPR Compliant Cookie Consent and Notice
2
+ # This file is distributed under the same license as the Cookiebot | GDPR Compliant Cookie Consent and Notice package.
3
+ msgid ""
4
+ msgstr ""
5
+ "Project-Id-Version: Cookiebot | GDPR Compliant Cookie Consent and Notice "
6
+ "1.6.0\n"
7
+ "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/cookiebot\n"
8
+ "POT-Creation-Date: 2018-05-30 16:47:20+00:00\n"
9
+ "MIME-Version: 1.0\n"
10
+ "Content-Type: text/plain; charset=UTF-8\n"
11
+ "Content-Transfer-Encoding: 8bit\n"
12
+ "PO-Revision-Date: 2018-MO-DA HO:MI+ZONE\n"
13
+ "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14
+ "Language-Team: LANGUAGE <LL@li.org>\n"
15
+
16
+ #: cookiebot.php:85
17
+ msgid "Cookiebot Status"
18
+ msgstr ""
19
+
20
+ #: cookiebot.php:97
21
+ msgid "You need to enter your Cookiebot ID."
22
+ msgstr ""
23
+
24
+ #: cookiebot.php:99
25
+ msgid "Update your Cookiebot ID"
26
+ msgstr ""
27
+
28
+ #: cookiebot.php:103
29
+ msgid "Your Cookiebot is working!"
30
+ msgstr ""
31
+
32
+ #: cookiebot.php:114
33
+ msgid "Cookiebot"
34
+ msgstr ""
35
+
36
+ #: cookiebot.php:170
37
+ msgid "Norwegian Bokmål"
38
+ msgstr ""
39
+
40
+ #: cookiebot.php:171
41
+ msgid "Turkish"
42
+ msgstr ""
43
+
44
+ #: cookiebot.php:172
45
+ msgid "German"
46
+ msgstr ""
47
+
48
+ #: cookiebot.php:173
49
+ msgid "Czech"
50
+ msgstr ""
51
+
52
+ #: cookiebot.php:174
53
+ msgid "Danish"
54
+ msgstr ""
55
+
56
+ #: cookiebot.php:175
57
+ msgid "Albanian"
58
+ msgstr ""
59
+
60
+ #: cookiebot.php:176
61
+ msgid "Hebrew"
62
+ msgstr ""
63
+
64
+ #: cookiebot.php:177
65
+ msgid "Korean"
66
+ msgstr ""
67
+
68
+ #: cookiebot.php:178
69
+ msgid "Italian"
70
+ msgstr ""
71
+
72
+ #: cookiebot.php:179
73
+ msgid "Dutch"
74
+ msgstr ""
75
+
76
+ #: cookiebot.php:180
77
+ msgid "Vietnamese"
78
+ msgstr ""
79
+
80
+ #: cookiebot.php:181
81
+ msgid "Tamil"
82
+ msgstr ""
83
+
84
+ #: cookiebot.php:182
85
+ msgid "Icelandic"
86
+ msgstr ""
87
+
88
+ #: cookiebot.php:183
89
+ msgid "Romanian"
90
+ msgstr ""
91
+
92
+ #: cookiebot.php:184
93
+ msgid "Sinhala"
94
+ msgstr ""
95
+
96
+ #: cookiebot.php:185
97
+ msgid "Catalan"
98
+ msgstr ""
99
+
100
+ #: cookiebot.php:186
101
+ msgid "Bulgarian"
102
+ msgstr ""
103
+
104
+ #: cookiebot.php:187
105
+ msgid "Ukrainian"
106
+ msgstr ""
107
+
108
+ #: cookiebot.php:188
109
+ msgid "Chinese"
110
+ msgstr ""
111
+
112
+ #: cookiebot.php:189
113
+ msgid "English"
114
+ msgstr ""
115
+
116
+ #: cookiebot.php:190
117
+ msgid "Arabic"
118
+ msgstr ""
119
+
120
+ #: cookiebot.php:191
121
+ msgid "Croatian"
122
+ msgstr ""
123
+
124
+ #: cookiebot.php:192
125
+ msgid "Thai"
126
+ msgstr ""
127
+
128
+ #: cookiebot.php:193
129
+ msgid "Greek"
130
+ msgstr ""
131
+
132
+ #: cookiebot.php:194
133
+ msgid "Lithuanian"
134
+ msgstr ""
135
+
136
+ #: cookiebot.php:195
137
+ msgid "Polish"
138
+ msgstr ""
139
+
140
+ #: cookiebot.php:196
141
+ msgid "Latvian"
142
+ msgstr ""
143
+
144
+ #: cookiebot.php:197
145
+ msgid "French"
146
+ msgstr ""
147
+
148
+ #: cookiebot.php:198
149
+ msgid "Indonesian"
150
+ msgstr ""
151
+
152
+ #: cookiebot.php:199
153
+ msgid "Macedonian"
154
+ msgstr ""
155
+
156
+ #: cookiebot.php:200
157
+ msgid "Estonian"
158
+ msgstr ""
159
+
160
+ #: cookiebot.php:201
161
+ msgid "Portuguese"
162
+ msgstr ""
163
+
164
+ #: cookiebot.php:202
165
+ msgid "Irish"
166
+ msgstr ""
167
+
168
+ #: cookiebot.php:203
169
+ msgid "Malay"
170
+ msgstr ""
171
+
172
+ #: cookiebot.php:204
173
+ msgid "Slovenian"
174
+ msgstr ""
175
+
176
+ #: cookiebot.php:205
177
+ msgid "Russian"
178
+ msgstr ""
179
+
180
+ #: cookiebot.php:206
181
+ msgid "Japanese"
182
+ msgstr ""
183
+
184
+ #: cookiebot.php:207
185
+ msgid "Hindi"
186
+ msgstr ""
187
+
188
+ #: cookiebot.php:208
189
+ msgid "Slovak"
190
+ msgstr ""
191
+
192
+ #: cookiebot.php:209
193
+ msgid "Spanish"
194
+ msgstr ""
195
+
196
+ #: cookiebot.php:210
197
+ msgid "Swedish"
198
+ msgstr ""
199
+
200
+ #: cookiebot.php:211
201
+ msgid "Serbian"
202
+ msgstr ""
203
+
204
+ #: cookiebot.php:212
205
+ msgid "Finnish"
206
+ msgstr ""
207
+
208
+ #: cookiebot.php:226
209
+ msgid "Cookiebot Settings"
210
+ msgstr ""
211
+
212
+ #: cookiebot.php:231
213
+ msgid ""
214
+ "Cookiebot enables your website to comply with current legislation in the EU "
215
+ "on the use of cookies for user tracking and profiling. The EU ePrivacy "
216
+ "Directive requires prior, informed consent of your site users, while the <a "
217
+ "href=\"https://www.cookiebot.com/en/gdpr\" target=\"_blank\">General Data "
218
+ "Protection Regulation (GDPR)</a> requires you to document each consent. At "
219
+ "the same time you must be able to account for what user data you share with "
220
+ "embedded third-party services on your website and where in the world the "
221
+ "user data is sent."
222
+ msgstr ""
223
+
224
+ #: cookiebot.php:238
225
+ msgid "Cookiebot ID"
226
+ msgstr ""
227
+
228
+ #: cookiebot.php:242
229
+ msgid "Need an ID?"
230
+ msgstr ""
231
+
232
+ #: cookiebot.php:243
233
+ msgid "Sign up for free on cookiebot.com"
234
+ msgstr ""
235
+
236
+ #: cookiebot.php:248
237
+ msgid "Cookiebot Language"
238
+ msgstr ""
239
+
240
+ #: cookiebot.php:254
241
+ msgid "Default (Autodetect)"
242
+ msgstr ""
243
+
244
+ #: cookiebot.php:255
245
+ msgid "Use Wordpress Language"
246
+ msgstr ""
247
+
248
+ #: cookiebot.php:265
249
+ msgid "You need to add the language in the Cookiebot administration tool."
250
+ msgstr ""
251
+
252
+ #: cookiebot.php:268
253
+ msgid ""
254
+ "You need to add all languages that you want auto-detected in the Cookiebot "
255
+ "administration tool."
256
+ msgstr ""
257
+
258
+ #: cookiebot.php:269
259
+ msgid ""
260
+ "The auto-detect checkbox needs to be enabled in the Cookiebot administration "
261
+ "tool."
262
+ msgstr ""
263
+
264
+ #: cookiebot.php:270
265
+ msgid ""
266
+ "If the auto-detected language is not supported, Cookiebot will use the "
267
+ "default language."
268
+ msgstr ""
269
+
270
+ #: cookiebot.php:274
271
+ msgid "Read more here"
272
+ msgstr ""
273
+
274
+ #: cookiebot.php:277
275
+ msgid "Show guide to add languages"
276
+ msgstr ""
277
+
278
+ #: cookiebot.php:282
279
+ msgid "Hide guide"
280
+ msgstr ""
281
+
282
+ #: cookiebot.php:313
283
+ msgid "Auto-update Cookiebot"
284
+ msgstr ""
285
+
286
+ #: cookiebot.php:317
287
+ msgid ""
288
+ "Automatic update your Cookiebot plugin when new releases becomes available."
289
+ msgstr ""
290
+
291
+ #: cookiebot.php:322
292
+ msgid "Hide Cookie Popup"
293
+ msgstr ""
294
+
295
+ #: cookiebot.php:326
296
+ msgid ""
297
+ "This checkbox will remove the cookie consent banner from your website. The "
298
+ "<i>[cookie_declaration]</i> shortcode will still be available."
299
+ msgstr ""
300
+
301
+ #: cookiebot.php:327
302
+ msgid ""
303
+ "If you are using Google Tag Manager (or equal), you need to add the "
304
+ "Cookiebot script in your Tag Manager."
305
+ msgstr ""
306
+
307
+ #: cookiebot.php:328
308
+ msgid ""
309
+ "<a href=\"https://support.cookiebot.com/hc/en-us/articles/360003793854-"
310
+ "Google-Tag-Manager-deployment\" target=\"_blank\">See a detailed guide here</"
311
+ "a>"
312
+ msgstr ""
313
+
314
+ #: cookiebot.php:335
315
+ msgid "How to find my Cookiebot ID"
316
+ msgstr ""
317
+
318
+ #: cookiebot.php:338
319
+ msgid ""
320
+ "Log in to your <a href=\"https://www.cookiebot.com/en/account\" target="
321
+ "\"_blank\">Cookiebot account</a>."
322
+ msgstr ""
323
+
324
+ #: cookiebot.php:339
325
+ msgid "Go to <b>Manage</b> > <b>Settings</b> and add setup your Cookiebot"
326
+ msgstr ""
327
+
328
+ #: cookiebot.php:340
329
+ msgid "Go to the <b>\"Your scripts\"</b> tab"
330
+ msgstr ""
331
+
332
+ #: cookiebot.php:341
333
+ msgid ""
334
+ "Copy the value inside the data-cid parameter - eg.: abcdef12-3456-7890-abcd-"
335
+ "ef1234567890"
336
+ msgstr ""
337
+
338
+ #: cookiebot.php:342
339
+ msgid ""
340
+ "Add <b>[cookie_declaration]</b> shortcode to a page to show the declation"
341
+ msgstr ""
342
+
343
+ #: cookiebot.php:343
344
+ msgid "Remember to change your scripts as descripted below"
345
+ msgstr ""
346
+
347
+ #: cookiebot.php:346
348
+ msgid "Add the Cookie Declaration to your website"
349
+ msgstr ""
350
+
351
+ #: cookiebot.php:348
352
+ msgid ""
353
+ "Use the shortcode <b>[cookie_declaration]</b> to add the cookie declaration "
354
+ "a page or post. The cookie declaration will always show the latest version "
355
+ "from Cookiebot."
356
+ msgstr ""
357
+
358
+ #: cookiebot.php:350
359
+ msgid ""
360
+ "If you need to force language of the cookie declaration, you can add the "
361
+ "<i>lang</i> attribute. Eg. <b>[cookie_declaration lang=\"de\"]</b>."
362
+ msgstr ""
363
+
364
+ #: cookiebot.php:353 cookiebot.php:369
365
+ msgid "Watch video demonstration"
366
+ msgstr ""
367
+
368
+ #: cookiebot.php:355
369
+ msgid "Update your script tags"
370
+ msgstr ""
371
+
372
+ #: cookiebot.php:357
373
+ msgid ""
374
+ "To enable prior consent, apply the attribute \"data-cookieconsent\" to "
375
+ "cookie-setting script tags on your website. Set the comma-separated value to "
376
+ "one or more of the cookie categories \"preferences\", \"statistics\" and "
377
+ "\"marketing\" in accordance with the types of cookies being set by each "
378
+ "script. Finally change the attribute \"type\" from \"text/javascript\" to "
379
+ "\"text/plain\". Example on modifying an existing Google Analytics Universal "
380
+ "script tag."
381
+ msgstr ""
382
+
383
+ #: cookiebot.php:372
384
+ msgid "Helper function to update your scripts"
385
+ msgstr ""
386
+
387
+ #: cookiebot.php:374
388
+ msgid ""
389
+ "You are able to update your scripts yourself. However, Cookiebot also offers "
390
+ "a small helper function that makes the work easier."
391
+ msgstr ""
392
+
393
+ #: cookiebot.php:376
394
+ msgid "Update your script tags this way:"
395
+ msgstr ""
396
+
397
+ #: cookiebot.php:380
398
+ msgid "%s to %s"
399
+ msgstr ""
400
+
401
+ #: cookiebot.php:431
402
+ msgid "Please add your Cookiebot ID to show Cookie Declarations"
403
+ msgstr ""
404
+
405
+ #. Plugin Name of the plugin/theme
406
+ msgid "Cookiebot | GDPR Compliant Cookie Consent and Notice"
407
+ msgstr ""
408
+
409
+ #. Plugin URI of the plugin/theme
410
+ msgid "https://cookiebot.com/"
411
+ msgstr ""
412
+
413
+ #. Description of the plugin/theme
414
+ msgid ""
415
+ "Cookiebot is a fully GDPR & ePrivacy compliant cookie consent solution "
416
+ "supporting prior consent, cookie declaration, and documentation of consents. "
417
+ "Easy to install, implement and configure."
418
+ msgstr ""
419
+
420
+ #. Author of the plugin/theme
421
+ msgid "Cybot A/S"
422
+ msgstr ""
423
+
424
+ #. Author URI of the plugin/theme
425
+ msgid "http://cookiebot.com"
426
+ msgstr ""
phpunit.xml ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <phpunit
2
+ bootstrap="addons/tests/bootstrap.php"
3
+ backupGlobals="false"
4
+ colors="true"
5
+ convertErrorsToExceptions="true"
6
+ convertNoticesToExceptions="true"
7
+ convertWarningsToExceptions="true"
8
+ >
9
+ <testsuites>
10
+ <testsuite>
11
+ <directory prefix="test" suffix=".php">./addons/tests/</directory>
12
+ </testsuite>
13
+ </testsuites>
14
+ <filter>
15
+ <whitelist processUncoveredFilesFromWhitelist="true">
16
+ <directory suffix=".php">./model</directory>
17
+ <file>example-model</file>
18
+ </whitelist>
19
+ </filter>
20
+ <logging>
21
+ <log type="coverage-text" target="php://stdout" showUncoveredFiles="false"/>
22
+ </logging>
23
+ <php>
24
+ <var name="DB_DSN" value="mysql:dbname=wordpress_test;host=localhost" />
25
+ <var name="DB_USER" value="root" />
26
+ <var name="DB_PASSWD" value="root" />
27
+ <var name="DB_DBNAME" value="wordpress_test" />
28
+ </php>
29
+ </phpunit>
readme.txt ADDED
@@ -0,0 +1,262 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Cookiebot | GDPR Compliant Cookie Consent and Notice #
2
+ * Contributors: cookiebot,phpgeekdk,aytac
3
+ * Tags: cookie, compliance, eu, gdpr, europe, cookie consent, consent
4
+ * Requires at least: 4.4
5
+ * Tested up to: 5.1
6
+ * Stable tag: 2.3.0
7
+ * Requires PHP: 5.4
8
+ * License: GPLv2 or later
9
+
10
+ Cookiebot is a fully GDPR & ePrivacy compliant cookie consent solution supporting prior consent, cookie declaration, and documentation of consents. Easy to install, implement and configure.
11
+
12
+ ## Description ##
13
+
14
+ ### What Cookiebot Offers ###
15
+
16
+ Cookiebot is a cloud-driven solution that offers:
17
+
18
+ * A highly customizable consent banner to handle user consents and give the users the required possibility to opt-in and -out of cookie categories.
19
+ * A cookie policy and declaration, with purpose descriptions and automatic categorization of your cookies (strictly necessary, preference, statistics, marketing).
20
+ * Full monthly scans to detect all tracking in place on the website as well as detection of where data is being sent to and where in the source code the cookie can be found.
21
+ * A scanner that detects various online trackers such as Cookies, HTML5 Local Storage, Flash Local Shared Object, Silverlight Isolated Storage, IndexedDB, ultrasound beacons, pixel tags etc.
22
+ * An easy way to allow the users to change or withdraw their consent.
23
+ * Translations for 44 languages and the ability to change the text on the banner and declaration for any language.
24
+ * Storage of user-consents in our cloud-driven environment, which are downloadable and can be used as proof.
25
+ * Execution of cookie-setting scripts without a page reload, if the user gives consent.
26
+
27
+ Please read our FAQ at the bottom of the page for more information.
28
+
29
+ https://youtube.com/watch?v=t1LJ6i1i9gA
30
+
31
+ ### Will my website become compliant once I install Cookiebot? ###
32
+ The short answer is; no.
33
+
34
+ Although Cookiebot enables your website to become fully compliant, [especially obeying the prior consent rule](https://support.cookiebot.com/hc/en-us/articles/360004104033-What-does-prior-consent-mean-and-how-do-I-implement-it-), some manual work is required to achieve compliance.
35
+
36
+ * If you are using plugins that set cookies which require consent (which most do), you have to:
37
+ * Ask the plugin developers if they are planning on becoming GDPR compliant, or if they would like to integrate with Cookiebot.
38
+ * Check if there already exists an addon for your plugin in the "Prior consent" submenu.
39
+ * [Check out our Github repository](https://github.com/CybotAS/CookiebotAddons), where we are developing integrations for Cookiebot, until the plugin developers choose to do this themselves, [or WP Core enables such functionality](https://core.trac.wordpress.org/ticket/44043)
40
+
41
+ Once Cookiebot is installed, and we've scanned your site, you can check the [cookie report](https://manage.cookiebot.com/goto/reports), to identify all cookies being set on your website. If the cookies are coming from content that you have inserted manually, then you can mark up that content [as described in our help section step 3](https://www.cookiebot.com/goto/help/).
42
+
43
+ Embedded videos and iframes, which set cookies, can be marked up as explain in our [Iframe cookie consent with YouTube example](https://support.cookiebot.com/hc/en-us/articles/360003790854-Iframe-cookie-consent-with-YouTube-example).
44
+
45
+
46
+ ### Cookiebot Addons ####
47
+ 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.
48
+
49
+ 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.
50
+
51
+ 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.
52
+
53
+ If your favourite plugin isn't supported you're welcome to contribute or request on our [Github development page](https://github.com/CybotAS/CookiebotAddons).
54
+
55
+
56
+ ## Installation ##
57
+ First, install the plugin on your WordPress site.
58
+
59
+ Then, go to Settings -> Cookiebot and add your Cookiebot ID.
60
+
61
+ If you haven't created one yet - or if you're not sure how to find it - follow the instructions on the page.
62
+
63
+ Once your Cookiebot ID is added, the consent dialog will be displayed to the visitors of your site.
64
+
65
+ [For more help, visit our support section, that contains various articles on how to set up Cookiebot properly](https://support.cookiebot.com/).
66
+
67
+ **Installation video:**
68
+
69
+ https://www.youtube.com/watch?v=t1LJ6i1i9gA
70
+
71
+ **Implementing the cookie declaration:**
72
+
73
+ https://youtu.be/OCXz2bt4H_w
74
+
75
+ **Implementing prior consent:**
76
+
77
+ https://youtu.be/MeHycvV2QCQ
78
+
79
+ ## Frequently Asked Questions ##
80
+
81
+ ### Is Cookiebot free? ###
82
+ Cookiebot is a freemium plugin, much like [Jetpack](https://wordpress.org/plugins/jetpack/) and [Monsterinsights](https://wordpress.org/plugins/google-analytics-for-wordpress/).
83
+
84
+ Whether the free plan can suffice or you need a premium plan, depends on two things:
85
+
86
+ **1. The size of your website, i.e. the number of subpages on your website.**
87
+ In other words, you cannot choose whether you want a free plan or a premium plan, as this is determined by the amount of subpages on your website. You can [get a quote](https://www.cookiebot.com/en/quote-input/) to see what plan you need for your website.
88
+
89
+ **2. Your necessities, as the free plan does not include all features available in the premium plans.** The free plan does not include customization of banner and cookies declaration, multiple languages, e-mail reports, data-export, geo location, bulk consent, consent statistics, internal domain alias for development, test and staging.
90
+
91
+ No matter the size of your website, you do have the right to a one month trial of Cookiebot for free.
92
+
93
+ See all details of [Cookiebot plans and pricing](https://www.cookiebot.com/en/pricing/).
94
+
95
+ ### What does Cookiebot count as pages?
96
+ Your pricing plan is dependent on the number of subpages we have detected on your website.
97
+
98
+ Some users mistakenly think that Cookiebot counts their **image files** as subpages, thus setting the users on a higher subscription plan.
99
+
100
+ Cookiebot does **not count image files as subpages**. Depending on your theme, Wordpress may automatically create real pages for content placed in your media library, called Attachment pages. Because these pages can contain online trackers, Cookiebot includes them in your page count.
101
+
102
+ To disable the Attachment page feature in Wordpress, please see the following guides:
103
+
104
+ https://themeskills.com/disable-media-attachment-pages-wordpress/
105
+ https://www.wpexplorer.com/disable-image-page/
106
+
107
+ ### Cookie declaration ###
108
+ The Cookiebot solution also includes an automatically updated cookie declaration about the cookies in use on your site.
109
+
110
+ By implementing it, you ensure that your cookie declaration is specific and accurate at all times, as required by the GDPR. Also, the declaration automatically provides the mandatory options for the user to change or withdraw consent.
111
+
112
+ To display your cookie declaration, create a new page on your website - and add the shortcode that the plugin provides to the page: [cookie_declaration]. Alternatively, you can incorporate it into e.g. your existing Privacy Policy.
113
+
114
+ By default the cookie declaration is displayed in the chosen Cookiebot language. You are able to override this setting with a "lang" attribute in the shortcode. Eg.: [cookie_declaration lang="de"] for a German version. Remember to add all used languages in the Cookiebot administration tool.
115
+
116
+ https://youtu.be/OCXz2bt4H_w
117
+
118
+ ### Cookie-checker: What cookies are in use on my site? ###
119
+ If you are in doubt about what cookies are in use on our site, you can start by trying our free compliance test:
120
+
121
+ **[Test my site](https://www.cookiebot.com/en/)**
122
+
123
+ The test scans five pages of your website and sends you a complete report of the cookies and online tracking on these pages, including information on their provenance, purpose and whether or not they are compliant with the EU-regulations.
124
+
125
+ If you want a complete overview of the cookies and online tracking going on on all of your website, sign up to the Cookiebot solution.
126
+
127
+ ### What is GDPR? ###
128
+ The GDPR is the General Data Protection Regulation, a EU-law that is enforced on the 25. May 2018, and affects all organizations and websites that handle data of EU-citizens.
129
+
130
+ See the [EU homepage of the GDPR](https://www.eugdpr.org/) for more information, and their infographic for businesses: [Data Protection: Better rules for small businesses](http://ec.europa.eu/justice/smedataprotect/index_en.htm)
131
+
132
+ ### How do I make other plugins support Cookiebot? ###
133
+ If you favourite plugins doesn't support Cookiebot you always welcome to ask the author to add support for Cookiebot.
134
+
135
+ Send an e-mail to the author of the plugin you want to support Cookiebot. Ask for adding support for Cookiebot. Cookiebot provides a helper function to check if there is an active, working version of Cookiebot on the website.
136
+
137
+ The easiest way for at developer to implement Cookiebot support is following to add a check for Cookiebot where <script> tags are outputted to the visitor. This can be done following way
138
+
139
+ $scriptTag = '<script>';
140
+ if(function_exists('cookiebot_active') && cookiebot_active()) {
141
+ $scriptTag = '<script'.cookiebot_assist('statistics').'>';
142
+ }
143
+
144
+ The developer of the plugin can see more details on [our Github repository](https://github.com/CybotAS/CookiebotAddons)
145
+
146
+ ### Can I use Cookiebot with GTM? ###
147
+ Cookiebot works with GTM, however you need to enable the "Hide Cookie Popup" option on the Cookiebot plugin settings page.
148
+
149
+ [Please see our article on how to depoloy Cookiebot with GTM](https://support.cookiebot.com/hc/en-us/articles/360003793854-Google-Tag-Manager-deployment).
150
+
151
+
152
+ ## Changelog ##
153
+
154
+ ### 2.3.0 - 2019-03-13 ###
155
+ * Added GADWP addon
156
+ * Changes in file structure of plugin
157
+
158
+ ### 2.2.2 - 2019-02-12 ###
159
+ * Fix warning non-static call to get_cbid
160
+
161
+ ### 2.2.1 - 2019-02-12 ###
162
+ * Adding support for WPForms
163
+ * Add plugin deactivation hook for addons
164
+
165
+ ### 2.2.0 - 2019-02-11 ###
166
+ * Adding support for network wide settings on Multisite Wordpress setups.
167
+
168
+ ### 2.1.5 - 2019-01-17 ###
169
+ * New addon: Custom Facebook Feed Pro
170
+ * Adding support for setting none, defer or async to Cookiebot script tags
171
+
172
+ ### 2.1.3 - 2018-11-18 ###
173
+ * New addon: Popups by OptinMonster
174
+ * Added support for grouping addons for different versions of same plugin
175
+
176
+ ### 2.1.2 - 2018-11-06 ###
177
+ * Auto correct addon added support for single quotes in iframe embeds
178
+
179
+ ### 2.1.1 - 2018-11-02 ###
180
+ * Updated addons with new tests and better plugin integration
181
+
182
+ ### 2.1.0 - 2018-10-05 ###
183
+ * Updated addons improved handling of tags
184
+ * Adding Basque as language option
185
+ * Remove .git files in addons
186
+
187
+ ### 2.0.6 - 2018-09-26 ###
188
+ * Updated addons to support newest version of CAOS
189
+ * Minor bugfixes and text adjustments
190
+
191
+ ### 2.0.5 - 2018-09-21 ###
192
+ * Added "Leave a review" admin notice
193
+
194
+ ### 2.0.4 - 2018-09-18 ###
195
+ * Added [IAB Consent Framework](https://support.cookiebot.com/hc/en-us/articles/360007652694-Cookiebot-and-the-IAB-Consent-Framework) option
196
+ * Update Cookiebot Addons
197
+ * Minor bugfixes
198
+
199
+ ### 2.0.3 - 2018-08-10 ###
200
+ * Removing informative message in admin_notice. Causing parse error for some users.
201
+
202
+ ### 2.0.2 - 2018-08-01 ###
203
+ * Quickfix - disable Script Config. Made trouble for some users.
204
+
205
+ ### 2.0.1 - 2018-08-01 ###
206
+ * Disable load of Addons if server runs PHP < 5.4.
207
+ * Fix placeholder in addons
208
+
209
+ ### 2.0.0 - 2018-07-30 ###
210
+ * Merge Cookiebot and Cookiebot Addons plugins. Cookiebot plugin now bundled with addons making other plugins GDPR compliant.
211
+
212
+ ### 1.6.2 - 2018-06-21 ###
213
+ * Fix check for WP Rocket.
214
+
215
+ ### 1.6.1 - 2018-06-11 ###
216
+ * Fixing shortcode when using WP Rocket
217
+
218
+ ### 1.6.0 - 2018-05-30 ###
219
+ * Support for removing cookie consent banner for tag manager users
220
+ * Support for multiple consent types in cookie_assist - eg. cookie_assist(['marketing','statistics']);
221
+ * Loading Cookiebot JS on admin pages too
222
+ * Adjusting help texts and adding links to demonstration videos.
223
+
224
+ ### 1.5.1 - 2018-05-25 ###
225
+ * Adjusting readme.txt including new video
226
+
227
+ ### 1.5.0 - 2018-05-22 ###
228
+ * Adding autoupdate for Cookiebot
229
+
230
+ ### 1.4.2 - 2018-05-17 ###
231
+ * Fix undefined $lang bug in shortcode output
232
+
233
+ ### 1.4.1 - 2018-05-11 ###
234
+ * Adjusting readme file
235
+
236
+ ### 1.4.0 - 2018-05-10 ###
237
+ * Adding support for specifying language of cookie banner
238
+ * Adding optional "lang" attribute to [cookie_declaration] shortcode
239
+
240
+ ### 1.3.0 - 2018-04-29 ###
241
+ * Bug fixed: Headers already sent when editing pages using shortcode
242
+
243
+ ### 1.2.0 - 2018-03-28 ###
244
+ * Updating readme file with more details
245
+ * Adding cookiebot_active helper function
246
+
247
+ ### 1.1.2 - 2018-02-27 ###
248
+ * Removing short array syntax to improve compatibility
249
+
250
+ ### 1.1.1 - 2018-02-02 ###
251
+ * Adjusting readme.txt
252
+
253
+ ### 1.1.0 - 2018-02-02 ###
254
+ * Adding data-culture to cookiebot script tags.
255
+
256
+ ### 1.0.0 ###
257
+ * Initial release of the plugin.
258
+
259
+
260
+ ## Copyright and Trademarks ##
261
+
262
+ Cookiebot is a registered trademark of Cybot A/S